Talk about containerd

背景

最近看一些社区 issue 中正好接触到 containerd 源码, 早年大家基本都使用 docker/podman 这类容器上层包装, 包括我也是, 故对真正容器运行时的结构部分了解得不够深入, 最近 k8s 社区在 1.21 规划上计划从 kubelet 中移除 docker-shim 交互的逻辑, 大势上组件走上 containerd-shim, 故需要着手对容器运行时更深入了解.

带着问题作为引入,

容器底层还是对 Linux LXC 的交互, 那究竟 docker daemon 中是哪个组件来完成这一步的呢?

1、背景知识

首先我们需要了解 Docker Daemon 生产出容器的过程.

当前整个 Docker 调用链架构可以用下图来简单概括

[站外图片上传中...(image-1c45f5-1618194667876)]

从 Docker 1.11 之后,Docker Daemon 被分成了多个模块以适应 OCI 标准。拆分之后,结构分成了以下几个部分:

16年12月 Docker公司宣布将 containerd 从Docker Engine中分离,并捐赠到开源社区独立发展和运营。

一个工业标准的容器运行时,注重简单、 健壮性、可移植性

Docker本身其实已经被剥离干净了,只剩下 Docker 自身作为 cli 的一些特色功能了,真正容器的管控都在 containerd 里实现。

在 17 年 docker重命名为moby, 从命名上逐渐脱离和 container 的关系, 而 Moby 更像是一个“乐高积木”,它包含了容器化的组件库 底层的构建、日志处理、卷管理、网络、镜像管理、containerd、SwarmKit等模块, 是个大杂烩.

19年2月containerd 正式从cncf社区毕业,成为继 Kubernetes, Prometheus, Envoy, and CoreDNS 之后第五个毕业项目。

2、生态架构

docker生态

单看 docker 生态圈是非常庞大的, 故今天我们聚焦在运行时 containerd 生态架构上, 周边生态如下:

  • OCI
  • CRI
  • kubelet
  • dockerd
    • docker.sock (/var/run/docker.sock)
  • dockershim
    • dockershim.sock (/var/run/dockershim.sock)
  • containerd-cri
    • containerd.sock (/var/run/docker/containerd/containerd.sock|/run/containerd/containerd.sock)
  • containerd-shim
  • Runc
  • RunV
  • Kata
  • gVisor

containerd 在容器生态中的角色, 作为容器运行时的扛把子

p

3、containerd 架构

img

简单来说分为:

  • containerd-shim
  • runC
  • LXC 调用封装

更细化为

containerd-arch

grpc 模块向上层提供服务接口,metrics 则提供监控数据(cgroup 相关数据),两者均向上层提供服务。containerd 包含一个守护进程,该进程通过本地 UNIX 套接字暴露 grpc 接口。

storage 部分负责镜像的存储、管理、拉取等metadata 管理容器及镜像的元数据,通过bootio存储在磁盘上task -- 管理容器的逻辑结构,与 low-level 交互event -- 对容器操作的事件,上层通过订阅可以知道发生了什么事情Runtimes -- low-level runtime(对接 runC)

containerd-shim

containerd-shim 是 containerd 的一个组件,主要是用于剥离 containerd 守护进程与容器进程。containerd 通过 shim 调用 runc 的包函数来启动容器.

各个组件以插件的形式注册

plugin registry

cri /run/containerd/containerd.sock

  • containers/tasks/event/snapshots/namespace/tasks/image /run/containerd/containerd.sock
  • 低内存环境 /run/containerd/containerd.sock.ttrpc
  • debug /run/containerd/debug.sock /debug/pprof
  • metrics metrics.sock /v1/metrics
  • bolt 元数据存储 和etcd底层使用相同结构

直接启动containerd和moby启动方式

  • 检测 /run/containerd/containerd.sock是否存在,判断是否启动containerd
  • 用supervisor启动containerd,直接二进制调用

容器的 namespace

容器 namespace

容器 ns 主要目的用于在 Linux 层面做 namespace 划分, 故拆分为一下3种主流 namespace.

目前最常见的 namespace type 主要分下面两种:

  • io.kubernetes.cri.container-type

  • io.kubernetes.docker.type

containerd-shim 容器生命周期管理

containerd-shim 类似 docker-shim 也是一层 gRPC 交互层, 提供对下层运行时的标准化 api 接口.
其特性有

  • 允许 runC 在创建&运行容器之后退出
  • 用 shim 作为容器的父进程,而不是直接用 containerd 作为容器的父进程,是为了防止这种情况:当 containerd 挂掉的时候,shim 还在,因此可以保证容器打开的文件描述符不会被关掉
  • 依靠 shim 来收集&报告容器的退出状态,这样就不需要 containerd 来wait 子进程

使用 shim 的主要作用,就是将 containerd 和真实的容器(里的进程)解耦。

回过来看特性第一点,为什么要允许 runc 退出呢? 因为,Go 编译出来的二进制文件,默认是静态链接,因此,如果一个机器上起N个容器,那么就会占用M*N的内存,其中M是一个 runc 所消耗的内存。 但是出于上面描述的原因又不想直接让 containerd 来做容器的父进程,因此,就需要一个比 runc 占内存更小的东西来作父进程,也就是 shim。

与 OCI 组件的交互

runC 是标准化的产物,为了防止一家商业公司主导容器化标准,因此又成立了 opencontainers 组织.

有了 runC 后, OCI 对容器 runtime 的标准所定义的指定容器的运行状态和 runtime 需要提供的命令得以打通.

runC 有以下特性:

  • 构建出的二进制直接调用
  • 用于更新 dockerd 配置文件 config.v2.json, hostconfig.json 文件
  • 提供了 k8s runtime class
  • 与 OCI 交互标准化

docker-init

UNIX系统中,1号进程是init进程,也是所有孤儿进程的父进程。而使用 docker 时,如果不加 --init 参数,容器中的1号进程 就是所给的ENTRYPOINT,例如下面例子中的 sh。而加上 --init 之后,1号进程就会是 tini

故在 docker 中启动容器时默认会走 docker-init 进程,其作用为

  • 避免僵尸进程
  • 默认信号处理
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,847评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,208评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,587评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,942评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,332评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,587评论 1 218
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,853评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,568评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,273评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,542评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,033评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,373评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,031评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,073评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,830评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,628评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,537评论 2 269

推荐阅读更多精彩内容

  • 虽然Kubernetes 在 v1.20 版本之后将不支持 Docker作为容器运行时Container Runt...
    向前进一点阅读 382评论 0 1
  • docker概念 镜像与容器 docker镜像是一个统一文件系统,由一系列只读层堆叠而成。容器则是在只读层堆顶加上...
    羽色云烟阅读 649评论 0 0
  • 深入浅出Docker学习笔记 Docker引擎 Docker引擎:用来运行和管理容器的核心文件模块化(基于开放容器...
    yuq329阅读 769评论 0 4
  • chroot chroot就是可以改变某进程的根目录,使这个程序不能访问目录之外的其他目录。Docker是利用Li...
    一生逍遥一生阅读 567评论 0 1
  • CRI - Container Runtime Interface(容器运行时接口) CRI中定义了容器和镜像的服...
    ywhu阅读 20,870评论 3 10