一,Containerd
很早就知道Docker Engine中就有containerd,现在只不过是将containerd从docker engine 中分离出来,作为一个独立的开源项目,目标是提供一个更加开放,稳定的容器运行基础设施,分离出来的containerd将具有更多的功能,涵盖整个容器运行时管理的所有需求,提供更强大的支持。
containerd是一个工业级标准的容器运行时,他强调简单性,健壮性,可移植性,containerd可以负责干以下事情,
管理容器的生命周期(从创建容器到销毁容器)
拉取、推送容器镜像
存储管理(管理镜像及容器数据的存储)
调用runc运行容器(与runc等容器运行时交互)
管理容器网络接口及网络
二,架构
containerd可作用linux和windows的守护程序,他管理其主机系统的完整的容器器生命周期从镜像传输和存储到容器执行和检测,再到底层存储到网络附件等等。
上图是containerd官方提供的架构图,可以看出containerd也是采用的C/S架构,服务端也是通过unix domain socket 暴露底层的gRPC API接口出去,客户端通过这些API接口管理节点上的容器,每个containerd只负责一台机器,pull镜像,对容器操作(启动、停止等),网络,存储都是由containerd来完成的,具体运行容器是由runc来负责的,实际上只要符合OCI规范的容器都可以支持。
为了解耦,containerd将系统划分了不同组件,每个组件都由一个或者做个模块来完成(core部分),每一种类型的模块都可以插件的形式集成到containerd中,而插。件之间是相互依赖的,例如上图中的每个长虚线的方框都表示一种类型的插件,包括Service Plugin,Metadata Plugin,GC Plugin,Runtime Plugin 等,其中 Service Plugin 又会依赖 Metadata Plugin、GC Plugin 和 Runtime Plugin。每一个小方框都表示一个细分的插件,例如 Metadata Plugin 依赖 Containers Plugin、Content Plugin 等。比如:
Content Plugin:
提供镜像中可寻址内容的访问,所有不可变得内容都被存储到这里Snapshot Plugin:
用来管理容器镜像的文件系统快照,镜像中的每一层都会被解压成文件系统快照,类似于docker中的graphdriver。总体来看containerd可分为三大部分:Storage,Matedata和Runtime。
三,安装
1,安装依赖
yum install -y libseccomp
2,安装containerd
由于 containerd 需要调用 runc,所以我们也需要先安装 runc,不过 containerd 提供了一个包含相关依赖的压缩包 cri-containerd-cni-${VERSION}.${OS}-${ARCH}.tar.gz
,可以直接使用这个包来进行安装。首先从 release 页面下载最新版本的压缩包,当前为 1.5.5 版本:
wget https://github.com/containerd/containerd/releases/download/v1.5.5/cri-containerd-cni-1.5.5-linux-amd64.tar.gz
# 如果有限制,也可以替换成下面的 URL 加速下载
wget https://download.fastgit.org/containerd/containerd/releases/download/v1.5.5/cri-containerd-cni-1.5.5-linux-amd64.tar.gz
查看压缩包里有哪些文件
[root@one test]# tar tf cri-containerd-cni-1.5.5-linux-amd64.tar.gz
etc/
etc/crictl.yaml
etc/cni/
etc/cni/net.d/
etc/cni/net.d/10-containerd-net.conflist
etc/systemd/
etc/systemd/system/
etc/systemd/system/containerd.service
usr/
usr/local/
usr/local/sbin/
usr/local/sbin/runc
usr/local/bin/
usr/local/bin/containerd-shim-runc-v1
usr/local/bin/critest
usr/local/bin/ctr
usr/local/bin/containerd-shim
usr/local/bin/crictl
usr/local/bin/containerd
usr/local/bin/ctd-decoder
usr/local/bin/containerd-stress
usr/local/bin/containerd-shim-runc-v2
opt/
opt/cni/
opt/cni/bin/
opt/cni/bin/firewall
opt/cni/bin/macvlan
opt/cni/bin/vrf
opt/cni/bin/ipvlan
opt/cni/bin/dhcp
opt/cni/bin/flannel
opt/cni/bin/bandwidth
opt/cni/bin/portmap
opt/cni/bin/ptp
opt/cni/bin/host-local
opt/cni/bin/sbr
opt/cni/bin/loopback
opt/cni/bin/static
opt/cni/bin/host-device
opt/cni/bin/tuning
opt/cni/bin/bridge
opt/cni/bin/vlan
opt/containerd/
opt/containerd/cluster/
opt/containerd/cluster/gce/
opt/containerd/cluster/gce/env
opt/containerd/cluster/gce/configure.sh
opt/containerd/cluster/gce/cloud-init/
opt/containerd/cluster/gce/cloud-init/master.yaml
opt/containerd/cluster/gce/cloud-init/node.yaml
opt/containerd/cluster/gce/cni.template
opt/containerd/cluster/version
直接解压到系统个目录中
tar -C / -xzf cri-containerd-cni-1.5.5-linux-amd64.tar.gz
/usr/local/bin 和 /usr/local/sbin 追加到 ~/.bashrc 文件的 PATH 环境变量中:
echo 'export PATH=$PATH:/usr/local/bin:/usr/local/sbin' >>~/.bashrc
containerd的默认的配置文件为/etc/containerd/config.toml,我们可以通过一下命令生成一个默认的配置文件
mkdir -p /etc/containerd
containerd config default >/etc/containerd/config.toml
由于我们下载的containerd压缩包中包含一个/etc/systemd/system/containerd.service的文件我们就可以通过systemd来配置containerd作为守护进程运行了,
[root@one containerd]# cat /etc/systemd/system/containerd.service
# Copyright The containerd Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target local-fs.target
[Service]
ExecStartPre=-/sbin/modprobe overlay
ExecStart=/usr/local/bin/containerd
Type=notify
Delegate=yes
KillMode=process
Restart=always
RestartSec=5
# Having non-zero Limit*s causes performance problems due to accounting overhead
# in the kernel. We recommend using cgroups to do container-local accounting.
LimitNPROC=infinity
LimitCORE=infinity
LimitNOFILE=infinity
# Comment TasksMax if your systemd version does not supports it.
# Only systemd 226 and above support this version.
TasksMax=infinity
OOMScoreAdjust=-999
[Install]
WantedBy=multi-user.target
这里有两个重要的参数:
Delegate:
这个选项允许containerd以及运行时自己管理自己创建容器的cgroups,如果不设置这个选项,systemd就会将进程移到自己的cgroups中,从而导致containerd无法正确的获取容器的资源使用情况。
KillMode:
这个选项用来处理containerd进程被杀死的方式,默认情况下,systemd会在进程的cgroup中查找并杀死containerd的所有子进程,killmode字段可以设置一下值:
control-group(默认值):
当前控制组里面的所有子进程都会被杀死
process:
自杀死主进程
mixed:
主进程将受到SIGTERM信号,子进程会收到SIGKILL信号
none:
没有进程会被杀掉,只是执行服务的stop命令
我们只需要将killmode的值设置成process,这样可以确保升级或者重启containerd时不杀死现有的容器
启动containerd
systemctl enable containerd --now
启动完成后可以使用containerd的本地CLI工具ctr了,比如查看版本:
[root@one containerd]# ctr version
Client:
Version: v1.5.5
Revision: 72cec4be58a9eb6b2910f5d10f1c01ca47d231c0
Go version: go1.16.6
Server:
Version: v1.5.5
Revision: 72cec4be58a9eb6b2910f5d10f1c01ca47d231c0
UUID: c26ef0fc-56cb-4ce8-b05b-be36c06a0947
containerd的配置
[root@one containerd]# cat /etc/containerd/config.toml
disabled_plugins = []
imports = []
oom_score = 0
plugin_dir = ""
required_plugins = []
root = "/var/lib/containerd"
state = "/run/containerd"
version = 2
[cgroup]
path = ""
[debug]
address = ""
format = ""
gid = 0
level = ""
uid = 0
[grpc]
address = "/run/containerd/containerd.sock"
gid = 0
max_recv_message_size = 16777216
max_send_message_size = 16777216
tcp_address = ""
tcp_tls_cert = ""
tcp_tls_key = ""
uid = 0
[metrics]
address = ""
grpc_histogram = false
[plugins]
[plugins."io.containerd.gc.v1.scheduler"]
deletion_threshold = 0
mutation_threshold = 100
pause_threshold = 0.02
schedule_delay = "0s"
startup_delay = "100ms"
[plugins."io.containerd.grpc.v1.cri"]
disable_apparmor = false
disable_cgroup = false
disable_hugetlb_controller = true
disable_proc_mount = false
disable_tcp_service = true
enable_selinux = false
enable_tls_streaming = false
ignore_image_defined_volumes = false
max_concurrent_downloads = 3
max_container_log_line_size = 16384
netns_mounts_under_state_dir = false
restrict_oom_score_adj = false
sandbox_image = "k8s.gcr.io/pause:3.5"
selinux_category_range = 1024
stats_collect_period = 10
stream_idle_timeout = "4h0m0s"
stream_server_address = "127.0.0.1"
stream_server_port = "0"
systemd_cgroup = false
tolerate_missing_hugetlb_controller = true
unset_seccomp_profile = ""
[plugins."io.containerd.grpc.v1.cri".cni]
bin_dir = "/opt/cni/bin"
conf_dir = "/etc/cni/net.d"
conf_template = ""
max_conf_num = 1
[plugins."io.containerd.grpc.v1.cri".containerd]
default_runtime_name = "runc"
disable_snapshot_annotations = true
discard_unpacked_layers = false
no_pivot = false
snapshotter = "overlayfs"
[plugins."io.containerd.grpc.v1.cri".containerd.default_runtime]
base_runtime_spec = ""
container_annotations = []
pod_annotations = []
privileged_without_host_devices = false
runtime_engine = ""
runtime_root = ""
runtime_type = ""
[plugins."io.containerd.grpc.v1.cri".containerd.default_runtime.options]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
base_runtime_spec = ""
container_annotations = []
pod_annotations = []
privileged_without_host_devices = false
runtime_engine = ""
runtime_root = ""
runtime_type = "io.containerd.runc.v2"
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
BinaryName = ""
CriuImagePath = ""
CriuPath = ""
CriuWorkPath = ""
IoGid = 0
IoUid = 0
NoNewKeyring = false
NoPivotRoot = false
Root = ""
ShimCgroup = ""
SystemdCgroup = false
[plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime]
base_runtime_spec = ""
container_annotations = []
pod_annotations = []
privileged_without_host_devices = false
runtime_engine = ""
runtime_root = ""
runtime_type = ""
[plugins."io.containerd.grpc.v1.cri".containerd.untrusted_workload_runtime.options]
[plugins."io.containerd.grpc.v1.cri".image_decryption]
key_model = "node"
[plugins."io.containerd.grpc.v1.cri".registry]
config_path = ""
[plugins."io.containerd.grpc.v1.cri".registry.auths]
[plugins."io.containerd.grpc.v1.cri".registry.configs]
[plugins."io.containerd.grpc.v1.cri".registry.headers]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".x509_key_pair_streaming]
tls_cert_file = ""
tls_key_file = ""
[plugins."io.containerd.internal.v1.opt"]
path = "/opt/containerd"
[plugins."io.containerd.internal.v1.restart"]
interval = "10s"
[plugins."io.containerd.metadata.v1.bolt"]
content_sharing_policy = "shared"
[plugins."io.containerd.monitor.v1.cgroups"]
no_prometheus = false
[plugins."io.containerd.runtime.v1.linux"]
no_shim = false
runtime = "runc"
runtime_root = ""
shim = "containerd-shim"
shim_debug = false
[plugins."io.containerd.runtime.v2.task"]
platforms = ["linux/amd64"]
[plugins."io.containerd.service.v1.diff-service"]
default = ["walking"]
[plugins."io.containerd.snapshotter.v1.aufs"]
root_path = ""
[plugins."io.containerd.snapshotter.v1.btrfs"]
root_path = ""
[plugins."io.containerd.snapshotter.v1.devmapper"]
async_remove = false
base_image_size = ""
pool_name = ""
root_path = ""
[plugins."io.containerd.snapshotter.v1.native"]
root_path = ""
[plugins."io.containerd.snapshotter.v1.overlayfs"]
root_path = ""
[plugins."io.containerd.snapshotter.v1.zfs"]
root_path = ""
[proxy_plugins]
[stream_processors]
[stream_processors."io.containerd.ocicrypt.decoder.v1.tar"]
accepts = ["application/vnd.oci.image.layer.v1.tar+encrypted"]
args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]
env = ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]
path = "ctd-decoder"
returns = "application/vnd.oci.image.layer.v1.tar"
[stream_processors."io.containerd.ocicrypt.decoder.v1.tar.gzip"]
accepts = ["application/vnd.oci.image.layer.v1.tar+gzip+encrypted"]
args = ["--decryption-keys-path", "/etc/containerd/ocicrypt/keys"]
env = ["OCICRYPT_KEYPROVIDER_CONFIG=/etc/containerd/ocicrypt/ocicrypt_keyprovider.conf"]
path = "ctd-decoder"
returns = "application/vnd.oci.image.layer.v1.tar+gzip"
[timeouts]
"io.containerd.timeout.shim.cleanup" = "5s"
"io.containerd.timeout.shim.load" = "5s"
"io.containerd.timeout.shim.shutdown" = "3s"
"io.containerd.timeout.task.state" = "2s"
[ttrpc]
address = ""
gid = 0
uid = 0
配置文件比较复杂,可以将重点放在其中的plugins配置上面,仔细观察可以发现每一个顶级配置快的命名都是plugins."containerd.xx.vx.xxx"这种形式,每一个顶级快配置都表示一个插件,其中io.containerd.xx.vx表示插件的类型vx后面的xxx表示插件的id可以通过ctr查看插件列表
[root@one containerd]# ctr plugin ls
TYPE ID PLATFORMS STATUS
io.containerd.content.v1 content - ok
io.containerd.snapshotter.v1 aufs linux/amd64 skip
io.containerd.snapshotter.v1 btrfs linux/amd64 skip
io.containerd.snapshotter.v1 devmapper linux/amd64 error
io.containerd.snapshotter.v1 native linux/amd64 ok
io.containerd.snapshotter.v1 overlayfs linux/amd64 ok
io.containerd.snapshotter.v1 zfs linux/amd64 skip
io.containerd.metadata.v1 bolt - ok
io.containerd.differ.v1 walking linux/amd64 ok
io.containerd.gc.v1 scheduler - ok
io.containerd.service.v1 introspection-service - ok
io.containerd.service.v1 containers-service - ok
io.containerd.service.v1 content-service - ok
io.containerd.service.v1 diff-service - ok
io.containerd.service.v1 images-service - ok
io.containerd.service.v1 leases-service - ok
io.containerd.service.v1 namespaces-service - ok
io.containerd.service.v1 snapshots-service - ok
io.containerd.runtime.v1 linux linux/amd64 ok
io.containerd.runtime.v2 task linux/amd64 ok
io.containerd.monitor.v1 cgroups linux/amd64 ok
io.containerd.service.v1 tasks-service - ok
io.containerd.internal.v1 restart - ok
io.containerd.grpc.v1 containers - ok
io.containerd.grpc.v1 content - ok
io.containerd.grpc.v1 diff - ok
io.containerd.grpc.v1 events - ok
io.containerd.grpc.v1 healthcheck - ok
io.containerd.grpc.v1 images - ok
io.containerd.grpc.v1 leases - ok
io.containerd.grpc.v1 namespaces - ok
io.containerd.internal.v1 opt - ok
io.containerd.grpc.v1 snapshots - ok
io.containerd.grpc.v1 tasks - ok
io.containerd.grpc.v1 version - ok
io.containerd.grpc.v1 cri linux/amd64 ok
顶级配置块下面的子配置块表示该插件的各种配置,比如cri插件下面就分为containerd,cin,registry的配置,而containerd下面又可以配置各种runtime,还可以配置默认的runtime,比如现在配置一个镜像加速器,就需要在cri配置块下面的registry配置块下面配置registry.mirrors:
136 [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
138 [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
139 endpoint = ["https://bqr1dr1n.mirror.aliyuncs.com"]
140 [plugins."io.containerd.grpc.v1.cri".registry.mirrors."k8s.gcr.io"]
141 endpoint = ["https://registry.aliyuncs.com/k8sxio"]
注意:缩进,和mirrors的位置,不能随便配置,
registry.mirrors."xxx":
表示需要配置mirror的镜像仓库,例如:registry.mirrors."docker.io"
表示docker.io的mirror
endpoint:
表示提供镜像加速服务,比如注册一个阿里云的镜像服务来作为docker.io的mirror
另外在配置还有两个关于存储的路径配置
root = "/var/lib/containerd"
state = "/run/containerd"
其中root是用来保存持久化数据的,包括 Snapshots, Content, Metadata 以及各种插件的数据,每个插件都有自己单独的目录,Containerd本身不存储任何数据,它的所有功能都来自于已加载的插件
而另外的state是用来保存运行时的临时数据的,包括sockets,pid,挂载点,运行时的状态以及不需要持久化的插件数据。
四,使用Containerd
输入ctr获取使用的相关方式
[root@one containerd]# ctr
NAME:
ctr -
__
_____/ /______
/ ___/ __/ ___/
/ /__/ /_/ /
\___/\__/_/
containerd CLI
USAGE:
ctr [global options] command [command options] [arguments...]
VERSION:
v1.5.5
DESCRIPTION:
ctr is an unsupported debug and administrative client for interacting
with the containerd daemon. Because it is unsupported, the commands,
options, and operations are not guaranteed to be backward compatible or
stable from release to release of the containerd project.
COMMANDS:
plugins, plugin provides information about containerd plugins
version print the client and server versions
containers, c, container manage containers
content manage content
events, event display containerd events
images, image, i manage images
leases manage leases
namespaces, namespace, ns manage namespaces
pprof provide golang pprof outputs for containerd
run run a container
snapshots, snapshot manage snapshots
tasks, t, task manage tasks
install install a new package
oci OCI tools
shim interact with a shim directly
help, h Shows a list of commands or help for one command
GLOBAL OPTIONS:
--debug enable debug output in logs
--address value, -a value address for containerd's GRPC server (default: "/run/containerd/containerd.sock") [$CONTAINERD_ADDRESS]
--timeout value total timeout for ctr commands (default: 0s)
--connect-timeout value timeout for connecting to containerd (default: 0s)
--namespace value, -n value namespace to use with commands (default: "default") [$CONTAINERD_NAMESPACE]
--help, -h show help
--version, -v print the version
1,镜像操作
拉去镜像可以使用ctr image pull
来完成比如拉取docker hub官方镜像nginx:alpine需要注意的是镜像地址需要加上docker.io host来完成
拉去镜像
[root@one containerd]# ctr image pull --all-platform docker.io/library/nginx:alpine
docker.io/library/nginx:alpine: resolved |++++++++++++++++++++++++++++++++++++++|
index-sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31: done |++++++++++++++++++++++++++++++++++++++|
manifest-sha256:efc09388b15fb423c402f0b8b28ca70c7fd20fe31f8d7531ae1896bbb4944999: done |++++++++++++++++++++++++++++++++++++++|
layer-sha256:4071be97c256d6f5ab0e05ebdebcfec3d0779a5e199ad0d71a5fccba4b3e2ce4: done |++++++++++++++++++++++++++++++++++++++|
config-sha256:51696c87e77e4ff7a53af9be837f35d4eacdb47b4ca83ba5fd5e4b5101d98502: done |++++++++++++++++++++++++++++++++++++++|
layer-sha256:df9b9388f04ad6279a7410b85cedfdcb2208c0a003da7ab5613af71079148139: done |++++++++++++++++++++++++++++++++++++++|
layer-sha256:5867cba5fcbd3ae827c5801e76d20e7dc91cbb626ac5c871ec6c4d04eb818b16: done |++++++++++++++++++++++++++++++++++++++|
layer-sha256:4b639e65cb3ba47e77db93f93c6625a62ba1b9eec99160b254db380115ae009d: done |++++++++++++++++++++++++++++++++++++++|
layer-sha256:061ed9e2b9762825b9869a899a696ce8b56e7e0ec1e1892b980969bf7bcda56a: done |++++++++++++++++++++++++++++++++++++++|
layer-sha256:bc19f3e8eeb1bb75268787f8689edec9a42deda5cdecdf2f95b3c6df8eb57a48: done |++++++++++++++++++++++++++++++++++++++|
elapsed: 21.1s total: 9.7 Mi (470.7 KiB/s)
unpacking linux/amd64 sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31...
done: 658.992696ms
也可以使用 --platform
选项指定对应平台的镜像。当然对应的也有推送镜像的命令 ctr image push,如果是私有镜像则在推送的时候可以通过 --user 来自定义仓库的用户名和密码。
查看镜像
[root@one containerd]# ctr image ls
REF TYPE DIGEST SIZE PLATFORMS LABELS
docker.io/library/nginx:alpine application/vnd.docker.distribution.manifest.list.v2+json sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31 9.7 MiB linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8,linux/ppc64le,linux/s390x -
也可以使用-q(--quiet)选项只打印镜像名称
[root@one containerd]# ctr image ls -q
docker.io/library/nginx:alpine
检测本地镜像
[root@one containerd]# ctr image check
REF TYPE DIGEST STATUS SIZE UNPACKED
docker.io/library/nginx:alpine application/vnd.docker.distribution.manifest.list.v2+json sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31 complete (7/7) 9.7 MiB/9.7 MiB true
其中主要查看STATUS complete
表示完整状态可用的状态。
重新打标签
我们也可以给指定的镜像打tag:
[root@one containerd]# ctr image tag docker.io/library/nginx:alpine nginx:alpine
nginx:alpine
删除镜像
[root@one containerd]# ctr image rm nginx:alpine
nginx:alpine
[root@one containerd]# ctr image ls -q
docker.io/library/nginx:alpine
加上--sync
选项可以同步删除镜像和所有相关资源。
将镜像挂在到主机目录
[root@one ~]# ctr image mount docker.io/library/nginx:alpine /mnt
sha256:1380ce106a10fac3c312f83ddf8406d187d5c0dd567d9a2454abe6ba563114cd
/mnt
[root@one ~]# ll /mnt/
total 76
drwxr-xr-x 2 root root 4096 Apr 5 00:06 bin
drwxr-xr-x 2 root root 4096 Apr 5 00:06 dev
drwxr-xr-x 1 root root 4096 Apr 5 15:22 docker-entrypoint.d
-rwxrwxr-x 1 root root 1202 Apr 5 15:21 docker-entrypoint.sh
drwxr-xr-x 1 root root 4096 Apr 5 15:22 etc
drwxr-xr-x 2 root root 4096 Apr 5 00:06 home
drwxr-xr-x 1 root root 4096 Apr 5 00:06 lib
drwxr-xr-x 5 root root 4096 Apr 5 00:06 media
drwxr-xr-x 2 root root 4096 Apr 5 00:06 mnt
drwxr-xr-x 2 root root 4096 Apr 5 00:06 opt
dr-xr-xr-x 2 root root 4096 Apr 5 00:06 proc
drwx------ 2 root root 4096 Apr 5 00:06 root
drwxr-xr-x 2 root root 4096 Apr 5 00:06 run
drwxr-xr-x 2 root root 4096 Apr 5 00:06 sbin
drwxr-xr-x 2 root root 4096 Apr 5 00:06 srv
drwxr-xr-x 2 root root 4096 Apr 5 00:06 sys
drwxrwxrwt 1 root root 4096 Apr 5 15:22 tmp
drwxr-xr-x 1 root root 4096 Apr 5 00:06 usr
drwxr-xr-x 1 root root 4096 Apr 5 00:06 var
将镜像从主机目录卸载
[root@one ~]# ctr image unmount /mnt
/mnt
将镜像导出为压缩包
ctr image export --platform linux/amd64 nginx.tar.gz docker.io/library/nginx:alpine
从压缩包导入镜像
[root@one ~]# ctr image import nginx.tar.gz
unpacking docker.io/library/nginx:alpine (sha256:5a0df7fb7c8c03e4158ae9974bfbd6a15da2bdfdeded4fb694367ec812325d31)...done
2,容器操作
创建容器
[root@one ~]# ctr container create docker.io/library/nginx:alpine nginx
列出容器
[root@one ~]# ctr container ls
CONTAINER IMAGE RUNTIME
nginx docker.io/library/nginx:alpine io.containerd.runc.v2
#注:同样可以精简列出容器
[root@one ~]# ctr container ls -q
nginx
查看容器相关配置
类似于docker inspect
的功能
[root@one ~]# ctr container info nginx
{
"ID": "nginx",
"Labels": {
"io.containerd.image.config.stop-signal": "SIGQUIT"
},
"Image": "docker.io/library/nginx:alpine",
"Runtime": {
"Name": "io.containerd.runc.v2",
"Options": {
"type_url": "containerd.runc.v1.Options"
}
},
"SnapshotKey": "nginx",
"Snapshotter": "overlayfs",
"CreatedAt": "2022-04-30T07:21:37.96898519Z",
"UpdatedAt": "2022-04-30T07:21:37.96898519Z",
"Extensions": null,
"Spec": {
"ociVersion": "1.0.2-dev",
"process": {
"user": {
"uid": 0,
"gid": 0,
"additionalGids": [
........
删除容器
[root@one ~]# ctr container rm nginx
[root@one ~]# ctr container ls
CONTAINER IMAGE RUNTIME
#注:除了使用rm子命令删除容器也可以使用delete,del来删除容器
3,任务
上面我们是用container create命令创建容器,并没有处于运行状态,只是一个静态的容器,一个container对象只是包含了运行一个容器所需的资源及相关配置数据,百世namespaces,rootfs和容器的配置都已经初始化成功了,只是用户进程还没有启动
一个容器真正运行起来是有Task任务实现的,Task可以为容器设置网卡,还可以配置工具来对容器进行监控等。
Task相关操作可以通过ctr task
获取,下面就通过task来启动容器
[root@one ~]# ctr container create docker.io/library/nginx:alpine nginx
[root@one ~]# ctr task start -d nginx
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
启动的容器可以用task ls
查看
[root@one ~]# ctr task ls
TASK PID STATUS
nginx 4943 RUNNING
同样可以使用exec
进入容器
[root@one ~]# ctr task exec --exec-id 0 -t nginx sh
#注:这里必须要指定`--exec-id` 参数,这个id随便写,只要唯一就行
暂停容器和docker pause
类似功能
[root@one ~]# ctr task pause nginx
[root@one ~]# ctr task ls
TASK PID STATUS
nginx 4943 PAUSED
同样也一刻使用resume
命令来恢复容器
[root@one ~]# ctr task resume nginx
[root@one ~]# ctr task ls
TASK PID STATUS
nginx 4943 RUNNING
注:不过需要注意的ctr没有stop停止容器的功能,只能暂停容器或者杀死容器,杀死容器使用 task kill
命令
[root@one ~]# ctr task kill nginx
[root@one ~]# ctr task ls
TASK PID STATUS
nginx 4943 STOPPED
杀死容器后可以看见容器的状态变成STOPPED
,可以使用task rm
来删除容器
除此之外还可以获取容器的cgroup相关信息,可以使用 task metrics
命令来获取容器的内存,cpu ,和pid的限额和使用量
[root@one ~]# ctr task metrics nginx
ID TIMESTAMP
nginx 2022-04-30 07:51:58.922189846 +0000 UTC
METRIC VALUE
memory.usage_in_bytes 6262784
memory.limit_in_bytes 9223372036854771712
memory.stat.cache 6262784
cpuacct.usage 41570198
cpuacct.usage_percpu [41570198]
pids.current 0
pids.limit 0
还可以是用task ps
查看容器中所有进程的在宿主机的pid
[root@one ~]# ctr task ps nginx
PID INFO
8188 -
8219 -
[root@one ~]# ctr task ls
TASK PID STATUS
nginx 8188 RUNNING
4,命名空间
此外containerd中也支持命名空间的概念,比如查看命名空间
[root@one ~]# ctr ns ls
NAME LABELS
default
如果不指定ctr默认使用的是default
空间,可以使用ns create
创建命名空间
[root@one ~]# ctr ns create test
[root@one ~]# ctr ns ls
NAME LABELS
default
test
使用remove
或者rm
可以删除namespace
[root@one ~]# ctr ns rm test
test
[root@one ~]# ctr ns ls
NAME LABELS
default
有了命名空间后就可以在操作资源的时候指定namespace,比如查看test命名空间的镜像,在命令后面加上-n test
[root@one ~]# ctr -n test image ls
REF TYPE DIGEST SIZE PLATFORMS LABELS
我们知道Docker其实默认也是调用的containerd,事实上docker使用的是conrainerd下面命令空间是默认的moby
,而不是default
加入我们有docker启动的容器也可以通过ctr -n moby
来定位下面的容器
ctr -n moby container ls
同样k8s下使用的containerd默认命名空间是k8s.io,所以我们可以是用ctr -n k8s.io
来查看kubernetes下面创建的容器。