容器管理工具Containerd(上篇):介绍、安装与ctr命令实践
一、Containerd介绍
1.前言
- 早在2016年3月,Docker 1.11的Docker Engine里就包含了containerd,而现在则是把containerd
从Docker Engine里彻底剥离出来,作为一个独立的开源项目独立发展,目标是提供一个更加开
放、稳定的容器运行基础设施。和原先包含在Docker Engine里containerd相比,独立的 containerd将具有更多的功能,可以涵盖整个容器运行时管理的所有需求。 - containerd并不是直接面向最终用户的,而是主要用于集成到更上层的系统里,比如Swarm,
Kubernetes, Mesos等容器编排系统。 - containerd以Daemon的形式运行在系统上,通过暴露底层的gRPC API,上层系统可以通过这些
API管理机器上的容器。 - 每个containerd只负责一台机器,Pull镜像,对容器的操作(启动、停止等),网络,存储都是由
containerd完成。具体运行容器由runC负责,实际上只要是符合OCI规范的容器都可以支持。 - 对于容器编排服务来说,运行时只需要使用containerd+runC,更加轻量,容易管理。
- 独立之后containerd的特性演进可以和Docker Engine分开,专注容器运行时管理,可以更稳定。

2.Containerd前世今生
2013年docker公司在推出docker产品后,由于其对全球技术产生了一定的影响力,Google公司明显感觉
到自己公司内部所使用的Brog系统江湖地位受到的威胁,希望Docker公司能够与自己联合打造一款开源
的容器运行时作为Docker核心依赖,但Docker公司拒绝了;接着Google公司联合RedHat、IBM等公司
说服Docker公司把其容器核心技术libcontainer捐给中立社区(OCI,Open Container Intiative),并更名为
runC。 为了进一步遏制Docker在未来技术市场影响力,避免在容器市场上Docker一家独大,Google公
司带领导RedHat、IBM等成立了CNCF(Cloud Native Computing Fundation)基金会,即云原生计算基金
会。CNCF的目标很明确,既然在容器应用领域无法与Docker相抗衡,那就做Google更有经验的技术市
场------大规模容器编排应用场景,Google公司把自己内部使用的Brog系统开源------Kubernetes,也就是
我们今天所说的云原生技术生态。
2016年Docker公司推出了Docker Swarm,意在一统Docker生态,让Docker既可以实现容器应用管
理,也可以实现大规模容器编排,经过近1年左右时间的市场验证后,发现在容器编排方面无法独立抗衡
kubernetes,所以Docker公司于2017年正式宣布原生支持Kubernetes,至此,Docker在大规模容器编排
应用市场败下阵来,但是Docker依然不甘心失败,把Docker核心依赖Containerd捐给了CNCF,依此说
明Docker依旧是一个PaaS平台。
2020年CNCF基金会宣布Kubernetes 1.20版本将不再仅支持Docker容器管理工具,此事的起因主要也与
Docker捐给CNCF基金会的Containerd有关,早期为了实现Kubernetes能够使用Docker实现容器管理,
专门在Kubernetes组件中集成一个shim(垫片)技术,用来将Kubernetes容器运行时接口(CRI,
Container Runntime Interface)调用翻译成Docker的API,这样就可以很好地使用Docker了,但是随着
Kubernetes在全球技术市场的广泛应用,有更多的容器管理工具的出现,它们都想能够借助于
Kubernetes被用户所使用,所以就提出标准化容器运行时接口,只要适配了这个接口就可以集成到
Kubernetes生态当中,所以Kubernetes取消了对shim的维护,并且由于Containerd技术的成功,可以
实现无缝对接Kubernetes,所以接下来Kubernetes容器运行时的主角是Containerd。
3.Containerd架构
3.1 架构图
Containerd设计的目的是为了嵌入到Kubernetes中使用,它是一个工业级的容器运行时,不提供给开发
人员和终端用户直接使用,这样就避免了与Docker产生竞争,但事实上,Containerd已经实现大多数容
器管理功能,例如:容器生命周期管理、容器镜像传输和管理、容器存储与网络管理等。

-
Containerd 采用标准的 C/S 架构
- 服务端通过 GRPC 协议提供稳定的 API
- 客户端通过调用服务端的 API 进行高级的操作
-
为了实现解耦,Containerd 将不同的职责划分给不同的组件,每个组件就相当于一个子系统
(subsystem)。连接不同子系统的组件被称为模块。 -
Containerd 两大子系统为:
- Bundle : 在 Containerd 中,Bundle 包含了配置、元数据和根文件系统数据,你可以理解为
容器的文件系统。而 Bundle 子系统允许用户从镜像中提取和打包 Bundles。 - Runtime : Runtime 子系统用来执行 Bundles,比如创建容器。
- Bundle : 在 Containerd 中,Bundle 包含了配置、元数据和根文件系统数据,你可以理解为
-
其中,每一个子系统的行为都由一个或多个模块协作完成(架构图中的 Core 部分)。每一种类型
的模块都以插件的形式集成到 Containerd 中,而且插件之间是相互依赖的。
例如,上图中的每一个长虚线的方框都表示一种类型的插件,包括 Service Plugin、Metadata
Plugin、GC Plugin、Runtime Plugin 等,其中 Service Plugin 又会依赖 Metadata Plugin、GC
Plugin 和 Runtime Plugin。每一个小方框都表示一个细分的插件,例如 Metadata Plugin 依赖
Containers Plugin、Content Plugin 等。
3.2 常用插件
- Content Plugin : 提供对镜像中可寻址内容的访问,所有不可变的内容都被存储在这里。
- Snapshot Plugin : 用来管理容器镜像的文件系统快照。镜像中的每一个 layer 都会被解压成文件
系统快照,类似于 Docker 中的 graphdriver 。 - Metrics : 暴露各个组件的监控指标。

3.3 架构缩略图
Containerd 被分为三个大块:Storage 、Metadata 和 Runtime

3.4 与其它容器运行时工具性能对比
这是使用 bucketbench 对 Docker、crio 和 Containerd 的性能测试结果,包括启动、停止和删除容器,
以比较它们所耗的时间:

结论: Containerd 在各个方面都表现良好,总体性能优于 Docker 和 crio 。
二、Containerd安装
操作系统: CentOS Stream 8
1.YUM方式安装
基于CentOS-Stream-8模板制作.md 制作的模板克隆一台虚拟机命名为Containerd
安装必要工具
[root@localhost ~]# yum install -y yum-utils device-mapper-persistent-data lvm2
vim
安装Containerd
# 1.获取阿里云YUM源
[root@localhost ~]# yum-config-manager --add-repo
https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
[root@localhost ~]# yum makecache
# 2.查看YUM源中Containerd软件
[root@localhost ~]# yum list | grep containerd
containerd.io.x86_64 1.6.32-3.1.el8
docker-ce-stable
# 3.安装Containerd.io软件,即可安装Containerd
[root@localhost ~]# yum -y install containerd.io
# 4.使用rpm -qa命令查看是否安装
[root@localhost ~]# rpm -qa | grep containerd
containerd.io-1.6.32-3.1.el8.x86_64
# 5.设置containerd服务启动及开机自启动
[root@localhost ~]# systemctl enable containerd --now
[root@localhost ~]# systemctl status containerd
# 6.验证
# 安装Containerd时ctr命令亦可使用,ctr命令主要用于管理容器及容器镜像等。
# 使用ctr命令查看Containerd客户端及服务端相关信息
[root@localhost ~]# ctr version
Client:
Version: 1.6.32
Revision: 8b3b7ca2e5ce38e8f31a34f35b2b68ceb8470d89
Go version: go1.21.10
Server:
Version: 1.6.32
Revision: 8b3b7ca2e5ce38e8f31a34f35b2b68ceb8470d89
UUID: 979940af-68e0-4681-a560-189eeaefbdfc
2.二进制方式安装
Containerd有两种安装包:
- 第一种是containerd-xxx,这种包用于单机测试没问题,不包含runC,需要提前安装。
- 第二种是cri-containerd-cni-xxxx,包含runc和k8s里的所需要的相关文件。k8s集群里需要用到此
包。虽然包含runC,但是依赖系统中的seccomp(安全计算模式,是一种限制容器调用系统资源的
模式。)
2.1 安装Containerd
打开github官网,搜索containerd项目


找到1.6.32

往下翻,找到软件包下载,然后上传到centos
也可以右击,复制链接,wget下载
https://github.com/containerd/containerd/releases/download/v1.6.32/cri-containerd-cni-1.6.32-linux-amd64.tar.gz

# 1.下载Containerd安装包
# 此处是下载的第二种
[root@localhost ~]# wget https://github.com/containerd/containerd/releases/download/v1.6.32/cri-
containerd-cni-1.6.32-linux-amd64.tar.gz
# 2.安装containerd
[root@localhost ~]# mkdir containerd
[root@localhost ~]# tar xf cri-containerd-cni-1.6.32-linux-amd64.tar.gz -C containerd/
[root@localhost ~]# cd containerd/
[root@localhost containerd]# ls
cri-containerd.DEPRECATED.txt etc opt usr
[root@localhost containerd]# tree
.
├── cri-containerd.DEPRECATED.txt
├── etc #etc目录主要为containerd服务管理配置文件及cni虚拟网卡配置文件
│ ├── cni
│ │ └── net.d
│ │ └── 10-containerd-net.conflist #网络插件配置文件
│ ├── crictl.yaml
│ └── systemd
│ └── system
│ └── containerd.service #服务配置文件
├── opt #opt目录主要为gce环境中使用containerd配置文件
#及cni插件
│ ├── cni #网络插件
│ │ └── bin
│ │ ├── bandwidth
│ │ ├── bridge
│ │ ├── dhcp
│ │ ├── firewall
│ │ ├── host-device
│ │ ├── host-local
│ │ ├── ipvlan
│ │ ├── loopback
│ │ ├── macvlan
│ │ ├── portmap
│ │ ├── ptp
│ │ ├── sbr
│ │ ├── static
│ │ ├── tuning
│ │ ├── vlan
│ │ └── vrf
│ └── containerd
│ └── cluster
│ ├── gce
│ │ ├── cloud-init
│ │ │ ├── master.yaml
│ │ │ └── node.yaml
│ │ ├── cni.template
│ │ ├── configure.sh
│ │ └── env
│ └── version
└── usr #usr目录主要为containerd运行时文件,包含runc
└── local # bin,sbin命令
├── bin
│ ├── containerd
│ ├── containerd-shim
│ ├── containerd-shim-runc-v1
│ ├── containerd-shim-runc-v2
│ ├── containerd-stress
│ ├── crictl
│ ├── critest
│ ├── ctd-decoder
│ └── ctr
└── sbin
└── runc
16 directories, 36 files
#查看containerd.service文件,了解containerd文件安装位置
[root@localhost 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 #查看此位置,把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
#复制containerd运行时文件至系统
[root@localhost containerd]# cp usr/local/bin/* /usr/local/bin
#添加containerd.service文件至系统
[root@localhost containerd]# cp etc/systemd/system/containerd.service/usr/lib/systemd/system/containerd.service
[root@localhost containerd]# mkdir /etc/containerd
# 生成containerd默认配置文件,重定向输出到/etc/containerd/config.toml
[root@localhost containerd]# containerd config default > /etc/containerd/config.toml
# 查看生成的containerd配置文件内容
[root@localhost containerd]# cat /etc/containerd/config.toml
disabled_plugins = []
imports = []
oom_score = 0
plugin_dir = ""
required_plugins = []
root = "/var/lib/containerd"
state = "/run/containerd"
temp = ""
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_ca = ""
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"]
device_ownership_from_security_context = false
disable_apparmor = false
disable_cgroup = false
disable_hugetlb_controller = true
disable_proc_mount = false
disable_tcp_service = true
drain_exec_sync_io_timeout = "0s"
enable_selinux = false
enable_tls_streaming = false
enable_unprivileged_icmp = false
enable_unprivileged_ports = false
ignore_deprecation_warnings = []
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 = "registry.k8s.io/pause:3.6"
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 = ""
ip_pref = ""
max_conf_num = 1
[plugins."io.containerd.grpc.v1.cri".containerd]
default_runtime_name = "runc"
disable_snapshot_annotations = true
discard_unpacked_layers = false
ignore_rdt_not_enabled_errors = false
no_pivot = false
snapshotter = "overlayfs"
[plugins."io.containerd.grpc.v1.cri".containerd.default_runtime]
base_runtime_spec = ""
cni_conf_dir = ""
cni_max_conf_num = 0
container_annotations = []
pod_annotations = []
privileged_without_host_devices = false
runtime_engine = ""
runtime_path = ""
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 = ""
cni_conf_dir = ""
cni_max_conf_num = 0
container_annotations = []
pod_annotations = []
privileged_without_host_devices = false
runtime_engine = ""
runtime_path = ""
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 = ""
cni_conf_dir = ""
cni_max_conf_num = 0
container_annotations = []
pod_annotations = []
privileged_without_host_devices = false
runtime_engine = ""
runtime_path = ""
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.internal.v1.tracing"]
[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"]
sched_core = false
[plugins."io.containerd.service.v1.diff-service"]
default = ["walking"]
[plugins."io.containerd.service.v1.tasks-service"]
rdt_config_file = ""
[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 = ""
discard_blocks = false
fs_options = ""
fs_type = ""
pool_name = ""
root_path = ""
[plugins."io.containerd.snapshotter.v1.native"]
root_path = ""
[plugins."io.containerd.snapshotter.v1.overlayfs"]
mount_options = []
root_path = ""
sync_remove = false
upperdir_label = false
[plugins."io.containerd.snapshotter.v1.zfs"]
root_path = ""
[plugins."io.containerd.tracing.processor.v1.otlp"]
[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.bolt.open" = "0s"
"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
#启动containerd并验证
# 设置containerd开机自启并立即启动,--now表示同时立即启动服务
[root@localhost ~]# systemctl enable containerd --now
# 查看containerd服务的运行状态
[root@localhost ~]# systemctl status containerd
# 查看containerd客户端(Client)与服务端(Server)的版本信息
[root@localhost ~]# ctr version
Client:
Version: v1.6.32
Revision: 8b3b7ca2e5ce38e8f31a34f35b2b68ceb8470d89
Go version: go1.21.10
Server:
Version: v1.6.32
Revision: 8b3b7ca2e5ce38e8f31a34f35b2b68ceb8470d89
UUID: 3ece67b1-4d8e-4059-afae-b837672ede83
2.2 安装runC
由于二进制包中提供的runC默认需要系统中安装seccomp支持,需要单独安装,且不同版本runC对
seccomp版本要求一致,所以建议单独下载runC 二进制包进行安装,里面包含了seccomp模块支持
下载地址:https://github.com/opencontainers/runc/releases
# 使用wget下载runc
[root@localhost ~]# wgethttps://github.com/opencontainers/runc/releases/download/v1.3.0/runc.amd64
# 安装runc
[root@localhost ~]# mv runc.amd64 /usr/sbin/runc
# 为runc添加可执行权限
[root@localhost ~]# chmod +x /usr/sbin/runc
# 使用runc命令验证是否安装成功
[root@localhost ~]# runc -v
runc version 1.3.0
commit: v1.3.0-0-g4ca628d1
spec: 1.2.1
go: go1.23.8
libseccomp: 2.5.6
三、Containerd容器镜像管理
3.1.帮助命令
- docker使用docker images命令管理镜像
- 单机containerd使用ctr images命令管理镜像,containerd本身的CLI
- k8s中containerd使用crictl images命令管理镜像,Kubernetes社区的专用CLI工具
#命令帮助
[root@localhost ~]# ctr --help
NAME:
ctr -
__
_____/ /______
/ ___/ __/ ___/
/ /__/ /_/ /
\___/\__/_/
containerd CLI
USAGE:
ctr [global options] command [command options] [arguments...]
VERSION:
v1.6.32
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
deprecations
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
# 子命令帮助
[root@localhost ~]# ctr images --help
NAME:
ctr images - manage images
USAGE:
ctr images command [command options] [arguments...]
COMMANDS:
check check existing images to ensure all content is
available locally
export export images
import import images
list, ls list images known to containerd
mount mount an image to a target path
unmount unmount the image from the target
pull pull an image from a remote
push push an image to a remote
delete, del, remove, rm remove one or more images by reference
tag tag an image
label set and clear labels for an image
convert convert an image
OPTIONS:
--help, -h show help
3.2.查看镜像
# 使用images子命令查看镜像列表(list)
[root@docker ~]# ctr images list
REF TYPE DIGEST SIZE PLATFORMS LABELS
# 使用images子命令查看镜像列表(ls为list的简写)
[root@docker ~]# ctr images ls
REF TYPE DIGEST SIZE PLATFORMS LABELS
# 使用image子命令查看镜像列表(list)
[root@docker ~]# ctr image list
REF TYPE DIGEST SIZE PLATFORMS LABELS
# 使用image子命令查看镜像列表(ls为list的简写)
[root@docker ~]# ctr image ls
REF TYPE DIGEST SIZE PLATFORMS LABELS
# 使用i子命令查看镜像列表(i为images的简写)
[root@docker ~]# ctr i list
REF TYPE DIGEST SIZE PLATFORMS LABELS
# 使用i子命令查看镜像列表(i和ls均为简写)
[root@docker ~]# ctr i ls
REF TYPE DIGEST SIZE PLATFORMS LABELS
3.3.下载镜像
containerd支持oci标准的镜像,所以可以直接使用docker官方或dockerfile构建的镜像
# 这里ctr命令pull镜像时,不能直接把镜像名字写成nginx:alpine
[root@localhost ~]# ctr images pull054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:lates
t
# 验证现象
# 使用image子命令查看镜像列表(ls为list的简写)
[root@localhost ~]# ctr image ls
REF
TYPE DIGEST
SIZE PLATFORMS
LABELS
054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest application/vnd.oci.image.index.v1+json
sha256:84ec966e61a8c7846f509da7eb081c55c1d56817448728924a87ab32f12a72fb 68.9 MiB
linux/386,linux/amd64,linux/arm/v5,linux/arm/v7,linux/arm64/v8,linux/mips64le,linux/ppc64le,linux/s390x,unknown/unknown -
3.4.镜像挂载
方便查看镜像中包含的内容
# 将nginx镜像挂载到/mnt目录,方便查看镜像中包含的内容
[root@localhost ~]# ctr images mount 054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest /mnt
sha256:3c1159cd77f83ede793fc21502ae30b39b04378b6b1b625451d701d555cc1cb9
/mnt
# 查看挂载目录/mnt中的内容
[root@localhost ~]# ls /mnt
bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64
media mnt opt proc root run sbin srv sys tmp usr var
# 卸载已挂载的/mnt目录
[root@localhost ~]# umount /mnt
3.5.镜像导出
# 导出nginx镜像为nginx.tar文件,--platform指定导出linux/amd64平台镜像
[root@localhost ~]# ctr i export --platform linux/amd64 nginx.tar
054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest
# 查看当前目录下的文件
[root@localhost ~]# ls
nginx.tar
3.6.镜像删除
# 查看ctr image rm删除镜像命令的帮助
[root@localhost ~]# ctr image rm --help
NAME:
ctr images delete - remove one or more images by reference
USAGE:
ctr images delete [command options] [flags] <ref> [<ref>, ...]
DESCRIPTION:
remove one or more images by reference
OPTIONS:
--sync Synchronously remove image and all associated resources
# 删除指定的nginx镜像
[root@localhost ~]# ctr image rm 054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest
054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest
# 验证现象
# 使用image子命令查看镜像列表(ls为list的简写)
[root@localhost ~]# ctr image ls
REF TYPE DIGEST SIZE PLATFORMS LABELS
3.7.镜像导入
# 导入nginx.tar镜像文件,--platform指定导入linux/amd64平台镜像
[root@localhost ~]# ctr images import --platform linux/amd64 nginx.tar
unpacking
054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest
(sha256:84ec966e61a8c7846f509da7eb081c55c1d56817448728924a87ab32f12a72fb)...done
# 验证现象
# 使用image子命令查看镜像列表(ls为list的简写)
[root@localhost ~]# ctr image ls
REF
TYPE DIGEST
SIZE PLATFORMS
LABELS
054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest application/vnd.oci.image.index.v1+json
sha256:84ec966e61a8c7846f509da7eb081c55c1d56817448728924a87ab32f12a72fb 68.9 MiB
linux/386,linux/amd64,linux/arm/v5,linux/arm/v7,linux/arm64/v8,linux/mips64le,linux/ppc64le,linux/s390x,unknown/unknown -
3.8.修改镜像tag
把054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:lates
t 修改为 nginx:latest
# 为镜像修改标签,将长镜像名打上nginx:latest标签
[root@localhost ~]# ctr images tag 054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest nginx:latest
nginx:latest
# 验证现象
# 使用image子命令查看镜像列表(ls为list的简写)
[root@localhost ~]# ctr image ls
REF
TYPE DIGEST
SIZE PLATFORMS
LABELS
054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest application/vnd.oci.image.index.v1+json
sha256:84ec966e61a8c7846f509da7eb081c55c1d56817448728924a87ab32f12a72fb 68.9 MiB
linux/386,linux/amd64,linux/arm/v5,linux/arm/v7,linux/arm64/v8,linux/mips64le,linux/ppc64le,linux/s390x,unknown/unknown -
nginx:latest
application/vnd.oci.image.index.v1+json
sha256:84ec966e61a8c7846f509da7eb081c55c1d56817448728924a87ab32f12a72fb 68.9 MiB
linux/386,linux/amd64,linux/arm/v5,linux/arm/v7,linux/arm64/v8,linux/mips64le,linux/ppc64le,linux/s390x,unknown/unknown -
四、Containerd容器管理
1.获取命令帮助
# 查看ctr命令帮助信息,了解可用的子命令和全局选项
[root@localhost ~]# ctr --help #ctr命令帮助
NAME:
ctr -
__
_____/ /______
/ ___/ __/ ___/
/ /__/ /_/ /
\___/\__/_/
containerd CLI
USAGE:
ctr [global options] command [command options] [arguments...]
VERSION:
v1.6.32
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
deprecations
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
# 查看ctr container容器管理子命令的帮助,了解创建静态容器的命令
[root@localhost ~]# ctr container --help #获取创建静态容器命令帮助 使用`ctr
container create `命令创建容器后,容器并没有处于运行状态,其只是一个静态的容器。这个container 对象只是包含了运行一个容器所需的资源及配置的数据结构,例如: namespaces、rootfs 和容器的配置都已经初始化成功了,只是用户进程(本案例为nginx)还没有启动。需要使用`ctr tasks`命令才能获取一个动态容器。
NAME:
ctr containers - manage containers
USAGE:
ctr containers command [command options] [arguments...]
COMMANDS:
create create container
delete, del, remove, rm delete one or more existing containers
info get info about a container
list, ls list containers
label set and clear labels for a container
checkpoint checkpoint a container
restore restore a container from checkpoint
OPTIONS:
--help, -h show help
# 查看ctr run命令帮助,该命令可一步创建并运行容器
[root@localhost ~]# ctr run --help # 使用ctr run命令可以创建一个静态容器并使其运行。一步到位运行容器。
NAME:
ctr run - run a container
USAGE:
ctr run [command options] [flags] Image|RootFS ID [COMMAND] [ARG...]
OPTIONS:
--rm remove the container after running,
cannot be used with --detach
--null-io send all IO to /dev/null
--log-uri value log uri
--detach, -d detach from the task after it has
started execution, cannot be used with --rm
--fifo-dir value directory used for storing IO FIFOs
--cgroup value cgroup path (To disable use of cgroup,
set to "" explicitly)
--platform value run image for specific platform
--cni enable cni networking for the
container
--runc-binary value specify runc-compatible binary
--runc-root value specify runc-compatible root
--runc-systemd-cgroup start runc with systemd cgroup manager
--uidmap container-uid:host-uid:length run inside a user namespace with the
specified UID mapping range; specified with the format container-uid:host-
uid:length
--gidmap container-gid:host-gid:length run inside a user namespace with the
specified GID mapping range; specified with the format container-gid:host-
gid:length
--remap-labels provide the user namespace ID
remapping to the snapshotter via label options; requires snapshotter support
--cpus value set the CFS cpu quota (default: 0)
--cpu-shares value set the cpu shares (default: 1024)
--snapshotter value snapshotter name. Empty value stands
for the default value. [$CONTAINERD_SNAPSHOTTER]
--snapshotter-label value labels added to the new snapshot for
this container.
--config value, -c value path to the runtime-specific spec
config file
--cwd value specify the working directory of the
process
--env value specify additional container
environment variables (e.g. FOO=bar)
--env-file value specify additional container
environment variables in a file(e.g. FOO=bar, one per line)
--label value specify additional labels (e.g.
foo=bar)
--annotation value specify additional OCI annotations
(e.g. foo=bar)
--mount value specify additional container mount
(e.g. type=bind,src=/tmp,dst=/host,options=rbind:ro)
--net-host enable host networking for the
container
--privileged run privileged container
--read-only set the containers filesystem as
readonly
--runtime value runtime name (default:
"io.containerd.runc.v2")
--runtime-config-path value optional runtime config path
--tty, -t allocate a TTY for the container
--with-ns value specify existing Linux namespaces to
join at container runtime (format '<nstype>:<path>')
--pid-file value file path to write the task's pid
--gpus value add gpus to the container
--allow-new-privs turn off OCI spec's NoNewPrivileges
feature flag
--memory-limit value memory limit (in bytes) for the
container (default: 0)
--device value file path to a device to add to the
container; or a path to a directory tree of devices to add to the container
--cap-add value add Linux capabilities (Set
capabilities with 'CAP_' prefix)
--cap-drop value drop Linux capabilities (Set
capabilities with 'CAP_' prefix)
--seccomp enable the default seccomp profile
--seccomp-profile value file path to custom seccomp profile.
seccomp must be set to true, before using seccomp-profile
--apparmor-default-profile value enable AppArmor with the default
profile with the specified name, e.g. "cri-containerd.apparmor.d"
--apparmor-profile value enable AppArmor with an existing
custom profile
--rdt-class value name of the RDT class to associate the
container with. Specifies a Class of Service (CLOS) for cache and memory
bandwidth management.
--rootfs use custom rootfs that is not managed
by containerd snapshotter
--no-pivot disable use of pivot-root (linux only)
--cpu-quota value Limit CPU CFS quota (default: -1)
--cpu-period value Limit CPU CFS period (default: 0)
--rootfs-propagation value set the propagation of the container
rootfs
2.查看容器(container表示静态容器,可用c缩写代表container)
# 查看静态容器列表(container可简写为c)
[root@localhost ~]# ctr container ls # 可以简写为 ctr c ls
CONTAINER IMAGE RUNTIME
3.查看任务(task表示容器里跑的进程, 可用t缩写代表task)
# 查看任务列表,task表示容器中运行的进程(可简写为t)
[root@localhost ~]# ctr task ls # 可以简写为 ctr t ls
TASK PID STATUS
4.创建静态容器
# 使用nginx:latest镜像创建名为nginx1的静态容器(此时容器未运行)
[root@localhost ~]# ctr container create nginx:latest nginx1
# 查看静态容器列表(container可简写为c)
[root@localhost ~]# ctr container ls
CONTAINER IMAGE RUNTIME
nginx1 nginx:latest io.containerd.runc.v2
# 查看nginx1容器的详细信息
[root@localhost ~]# ctr container info nginx1
5.静态容器启动为动态容器
# 查看任务列表,task表示容器中运行的进程(可简写为t)
[root@localhost ~]# ctr task ls
TASK PID STATUS
# 启动nginx1容器的task,-d后台运行,使静态容器变为动态容器
[root@localhost ~]# ctr task start -d nginx1 #启动task,即表示在容器中运行了进程,即为动态容器 -d 后台
# 查看任务列表,task表示容器中运行的进程(可简写为t)
[root@localhost ~]# ctr task ls #容器是以宿主机进程的方式存在的
TASK PID STATUS
nginx1 22614 RUNNING
# 查看系统中所有进程,grep过滤PID 22614,确认容器以宿主机进程方式运行
[root@localhost ~]# ps aux | grep 22614
root 22614 0.0 0.0 11468 7196 ? Ss 15:40 0:00 nginx: master
process nginx -g daemon off;
root 22969 0.0 0.0 12216 1104 pts/0 S+ 15:41 0:00 grep --
color=auto 22614
6.进入容器操作
# 进入nginx1容器执行shell,--exec-id为exec进程指定唯一ID(可用$RANDOM),-t分配终端
[root@localhost ~]# ctr task exec --exec-id $RANDOM -t nginx1 /bin/sh #为exec进程设定一个id,可以随意输入,只要保证唯一即可,也可使用$RANDOM变量
7.直接运行一个动态容器
# 直接运行nginx2动态容器,-d后台运行,--net-host容器IP即宿主机IP(host网络类型)
[root@localhost ~]# ctr run -d --net-host nginx:latest nginx2 # --net-host 代表容器的IP就是宿主机的IP(相当于docker里的host类型网络)
8.暂停容器
# 暂停nginx2容器的task
[root@localhost ~]# ctr tasks pause nginx2
# 查看任务列表,task表示容器中运行的进程(可简写为t)
[root@localhost ~]# ctr task ls
TASK PID STATUS
nginx1 22614 RUNNING
nginx2 25569 PAUSED #状态为PAUSED,表示暂停
9.恢复容器
# 恢复nginx2容器task运行
[root@localhost ~]# ctr tasks resume nginx2
# 查看任务列表,task表示容器中运行的进程(可简写为t)
[root@localhost ~]# ctr task ls
TASK PID STATUS
nginx1 22614 RUNNING
nginx2 25569 RUNNING #恢复RUNNING
10.停止容器
# 停止(杀死)nginx2容器的task
[root@localhost ~]# ctr tasks kill nginx2
# 查看任务列表(tasks可简写为t)
[root@localhost ~]# ctr tasks ls
TASK PID STATUS
nginx1 22614 RUNNING
nginx2 25569 STOPPED #容器停止后STATUS为STOPPED
11.删除容器
# 删除nginx2容器的task(必须先停止task再删除)
[root@localhost ~]# ctr tasks delete nginx2 #必须先停止tasks或先删除task,再删除容器
# 查看任务列表(tasks可简写为t)
[root@localhost ~]# ctr tasks ls
TASK PID STATUS
nginx1 22614 RUNNING
# 查看静态容器列表(container可简写为c)
[root@localhost ~]# ctr container ls # 查看静态容器,确认其还存在于系统中
CONTAINER IMAGE RUNTIME
nginx1 nginx:latest io.containerd.runc.v2
nginx2 nginx:latest io.containerd.runc.v2
# 删除nginx2静态容器
[root@localhost ~]# ctr container delete nginx2
# 查看静态容器列表(container可简写为c)
[root@localhost ~]# ctr container ls
CONTAINER IMAGE RUNTIME
nginx1 nginx:latest io.containerd.runc.v2
五、Containerd使用私有容器镜像仓库Harbor
# 编辑/etc/hosts主机映射文件,添加Harbor仓库域名解析(已存在可忽略)
[root@localhost ~]# vim /etc/hosts
192.168.108.30 my.harbor.com
# harbor仓库需要提前在192.168.108.30上部署(参考docker教案),镜像需要提前传到harbor上,如果没有使用https可以使用--plain-http 指定http协议
# 从Harbor私有仓库拉取nginx镜像,--plain-http指定使用http协议
[root@localhost ~]# ctr image pull --plain-http 192.168.108.30/cloud/nginx:latest
# 为nginx镜像打上Harbor仓库标签,准备上传
[root@localhost ~]# ctr images tag nginx:latest my.harbor.com/cloud/nginx:latest
# 上传镜像到Harbor仓库,--platform指定平台,--plain-http使用http协议,--user指定仓库用户名和密码
[root@localhost ~]# ctr image push --platform linux/amd64 --plain-http --user "images_admin:Cloud12#$" my.harbor.com/cloud/nginx:latest
manifest-sha256:6533ddd664582430971e93e69cf343e3bfffceadeaaa97d4379c4d7a29f21d47: done |++++++++++++++++++++++++++++++++++++++|
config-sha256:2cd1d97f893f70cee86a38b7160c30e5750f3ed6ad86c598884ca9c6a563a501: done |++++++++++++++++++++++++++++++++++++++|
elapsed: 0.1 s
六、Containerd NameSpace管理
containerd中namespace的作用为隔离运行的容器,可以实现运行多个容器
1.列出已有namespace
# 查看已有namespace(命名空间)列表
[root@localhost ~]# ctr namespace ls
NAME LABELS
default #containerd默认工作在default命名空间
# 查看已有namespace(命名空间)列表
[root@docker ~]# ctr namespace ls #在docker环境中打
NAME LABELS
moby #docker默认工作在moby空间
2.创建namespace
# 创建名为myns的namespace
[root@localhost ~]# ctr namespace create myns
# 创建名为testns的namespace
[root@localhost ~]# ctr namespace create testns
# 查看已有namespace(命名空间)列表
[root@localhost ~]# ctr namespace ls
NAME LABELS
default
myns
testns
3.删除namespace
# 删除名为testns的namespace
[root@localhost ~]# ctr namespace rm testns
testns
# 查看已有namespace(命名空间)列表
[root@localhost ~]# ctr namespace ls
NAME LABELS
default
myns
4.查看指定namespace中镜像
# 查看myns命名空间中的镜像列表,-n指定namespace
[root@localhost ~]# ctr -n myns images ls
REF TYPE DIGEST SIZE PLATFORMS LABELS
5.查看指定namespace中是否有用户进程在运行
# 查看myns命名空间中是否有用户进程在运行
[root@localhost ~]# ctr -n myns tasks ls
TASK PID STATUS
6.在指定namespace中下载容器镜像
# 在myns命名空间中拉取nginx镜像
[root@localhost ~]# ctr -n myns images pull 054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest
# 查看myns命名空间中的镜像列表,-n指定namespace
[root@localhost ~]# ctr -n myns images ls
REF
TYPE DIGEST
SIZE PLATFORMS
LABELS
054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest application/vnd.oci.image.index.v1+json
sha256:84ec966e61a8c7846f509da7eb081c55c1d56817448728924a87ab32f12a72fb 68.9 MiB
linux/386,linux/amd64,linux/arm/v5,linux/arm/v7,linux/arm64/v8,linux/mips64le,linux/ppc64le,linux/s390x,unknown/unknown -
7.在指定namespace中创建静态容器
# 在myns命名空间中基于nginx镜像创建名为mynginx的静态容器
[root@localhost ~]# ctr -n myns container create 054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest mynginx
8.查看在指定namespace中创建的容器
# 查看myns命名空间中的容器列表,确认mynginx已创建
[root@localhost ~]# ctr -n myns container ls
CONTAINER IMAGE
RUNTIME
mynginx
054b8ac70e8010d90f2ac00ef29e6580.mirror.swr.myhuaweicloud.com/library/nginx:latest io.containerd.runc.v2
# 启动mynginx容器的task,-d后台运行
[root@localhost ~]# ctr -n myns task start -d mynginx
# 查看myns命名空间中是否有用户进程在运行
[root@localhost ~]# ctr -n myns tasks ls
TASK PID STATUS
mynginx 5873 RUNNING
转载自 CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/qq_52580914/article/details/166490736




