containerd 是一个简单的守护进程,可以在任何系统上运行。 它提供了一个最小配置,来配置这个守护进程和必要的时候使用什么插件

  1. containerd --help
  2. NAME:
  3. containerd -
  4. __ _ __
  5. _________ ____ / /_____ _(_)___ ___ _________/ /
  6. / ___/ __ \/ __ \/ __/ __ `/ / __ \/ _ \/ ___/ __ /
  7. / /__/ /_/ / / / / /_/ /_/ / / / / / __/ / / /_/ /
  8. \___/\____/_/ /_/\__/\__,_/_/_/ /_/\___/_/ \__,_/
  9. high performance container runtime
  10. USAGE:
  11. containerd [global options] command [command options] [arguments...]
  12. VERSION:
  13. 1.4.6
  14. DESCRIPTION:
  15. containerd is a high performance container runtime whose daemon can be started
  16. by using this command. If none of the *config*, *publish*, or *help* commands
  17. are specified, the default action of the **containerd** command is to start the
  18. containerd daemon in the foreground.
  19. A default configuration is used if no TOML configuration is specified or located
  20. at the default file location. The *containerd config* command can be used to
  21. generate the default configuration for containerd. The output of that command
  22. can be used and modified as necessary as a custom configuration.
  23. COMMANDS:
  24. config information on the containerd config
  25. publish binary to publish events to containerd
  26. oci-hook provides a base for OCI runtime hooks to allow arguments to be injected.
  27. help, h Shows a list of commands or help for one command
  28. GLOBAL OPTIONS:
  29. --config value, -c value path to the configuration file (default: "/etc/containerd/config.toml")
  30. --log-level value, -l value set the logging level [trace, debug, info, warn, error, fatal, panic]
  31. --address value, -a value address for containerd's GRPC server
  32. --root value containerd root directory
  33. --state value containerd state directory
  34. --help, -h show help
  35. --version, -v print the version

一些守护进程级别的选项可以通过 flags 进行配置,主要的 containerd 配置被保存在配置文件中,默认的配置文件路径在 /etc/containerd/config.tom,可以通过 --config, -c flags 在启动 daemon 的时候配置这个路径。

Systemd

如果你使用 systemd 作为你的初始化系统(在大多数现代的 linux 系统上是),service 文件需要一些修改

  1. [Unit]
  2. Description=containerd container runtime
  3. Documentation=https://containerd.io
  4. After=network.target
  5. [Service]
  6. ExecStartPre=-/sbin/modprobe overlay
  7. ExecStart=/usr/local/bin/containerd
  8. Delegate=yes
  9. KillMode=process
  10. [Install]
  11. WantedBy=multi-user.target

Delegate=yesKillMode=yes 是两项需要在 Service 选项中配置的最重要的改变

Delegate 允许 containerd 和它的 runtimes 控制它创建的容器的 cgroups。如果没有设置这个参数,systemd 会尝试将进程移动到它自己的 cgroups 中,这会导致 containerd 和它的 runtimes 无法正确的说明容器的资源用量。

在 containerd 被关闭的时候,默认情况下,systemd 将查看其 named cgroup 并杀死它知道的每个服务进程。这不是我们想要的。我们像能够升级 containerd 并且在中断的时候允许现存的容器保持运行。设置 KillMode 来保证 systemd 只杀死 containerd 的守护进程而不包括子进程 shims 和容器。

下面的 system-run 命令会以同样的方式打开 containerd

  1. sudo systemd-run -p Delegate=yes -p KillMode=process /usr/local/bin/containerd

Base Configuration

在 containerd 的配置文件中,分为持久化和运行时存储,像 grpc,debug 和 metrics 的地址,有多种 API

只有一小部分设置是比较重要的,首先是 oom_score,因为 containerd 会管理很多容器,我们需要确保在 containerd daemon 进入内存不足的状态之前杀掉容器。我们也不想让 containerd 被杀掉,但是我们想要降低它的相对于其他系统守护进程的评分。

containerd 通过 Promethues metric 的形式(/v1/metrics)暴露自己的 metrics, 等级与容器的等级一致。现在, Promethues 只支持 TCP 端口的形式,所以 metrics 地址应该是一个 TCP 地址,让你的 Promethues 基础设置能够抓取到 metrics。

containerd 在一个主机上有两种不同的存储位置。一种是持久化存储,另一种是运行时存储。

root会被用来存储任何类型的持久化数据,快照,content,容器和镜像的 metadata,还有插件数据。 root 对于容器加载的插件也是 namespaced。每一个插件会有自己存储数据的文件夹,containerd 自己不持有任何他自己需要的持久化数据,它的功能来自于加载的插件。

  1. /var/lib/containerd/
  2. ├── io.containerd.content.v1.content
  3. ├── blobs
  4. └── ingest
  5. ├── io.containerd.metadata.v1.bolt
  6. └── meta.db
  7. ├── io.containerd.runtime.v1.linux
  8. ├── default
  9. └── example
  10. ├── io.containerd.snapshotter.v1.btrfs
  11. └── io.containerd.snapshotter.v1.overlayfs
  12. ├── metadata.db
  13. └── snapshots

state 将会被用于存储任何类型的暂时数据,sockets,pid,运行时状态,挂载点,还有其他不需要持久化的插件数据。

  1. /run/containerd
  2. ├── containerd.sock
  3. ├── debug.sock
  4. ├── io.containerd.runtime.v1.linux
  5. └── default
  6. └── redis
  7. ├── config.json
  8. ├── init.pid
  9. ├── log.json
  10. └── rootfs
  11. ├── bin
  12. ├── data
  13. ├── dev
  14. ├── etc
  15. ├── home
  16. ├── lib
  17. ├── media
  18. ├── mnt
  19. ├── proc
  20. ├── root
  21. ├── run
  22. ├── sbin
  23. ├── srv
  24. ├── sys
  25. ├── tmp
  26. ├── usr
  27. └── var
  28. └── runc
  29. └── default
  30. └── redis
  31. └── state.json

rootstate 文件夹对于插件都是 namespaced。这两个目录都是 containerd 和其插件的实现细节,它们不应该被篡改,否则会发生错误和 bug。当 containerd 或者插件清理资源时,外部的 APP 读取或者监听这些文件夹的变化会导致 EBUSY 和陈旧的文件句柄(EBUSY and stale file handles)。

  1. # persistent data location
  2. root = "/var/lib/containerd"
  3. # runtime state information
  4. state = "/run/containerd"
  5. # set containerd's OOM score
  6. oom_score = -999
  7. # grpc configuration
  8. [grpc]
  9. address = "/run/containerd/containerd.sock"
  10. # socket uid
  11. uid = 0
  12. # socket gid
  13. gid = 0
  14. # debug configuration
  15. [debug]
  16. address = "/run/containerd/debug.sock"
  17. # socket uid
  18. uid = 0
  19. # socket gid
  20. gid = 0
  21. # debug level
  22. level = "info"
  23. # metrics configuration
  24. [metrics]
  25. # tcp address!
  26. address = "127.0.0.1:1234"

Plugin Configuration

归根结底,containerd 的核心是非常小的,真正的功能来自于插件。快照,运行时和 content 的所有都是在运行时注册的插件。因为这些各种各样的插件之间的不同,我们需要给插件提供类型安全的配置,我们可以做的唯一方式就是通过配置文件而不是 flags。

在配置文件中,你可以指定插件的等级选项,通过 plugin.<name>,你将会不得不读取插件的特殊文档,来找到你插件需要的选项。

Linux Runtime Plugin

linux 运行时允许设置一些选项来配置你所使用的 shim 和 runtime

  1. [plugins.linux]
  2. # shim binary name/path
  3. shim = ""
  4. # runtime binary name/path
  5. runtime = "runc"
  6. # do not use a shim when starting containers, saves on memory but
  7. # live restore is not supported
  8. no_shim = false
  9. # display shim logs in the containerd daemon's log output
  10. shim_debug = true

Blot Metadata Plugin

Bolt 元数据插件允许配置命名空间之间的内容共享策略。


默认模式“共享”将使 blob 在被拉入任何命名空间后在所有命名空间中可用。 如果使用后端中已经存在的“预期”摘要打开编写器,则 blob 将被拉入命名空间。

替代模式“隔离”要求客户端通过在将 blob 添加到命名空间之前将所有内容提供给摄取来证明他们有权访问内容。

两种模式共享备份数据,而“共享”将减少跨命名空间的总带宽,代价是仅通过了解其摘要就允许访问任何 blob。

默认为“共享”。 虽然这在很大程度上是最需要的策略,但可以使用以下配置更改为“隔离”模式:

  1. [plugins.bolt]
  2. content_sharing_policy = "isolated"