Docker 被 K8s 分手后,我扒了扒接盘的 containerd

容器管理工具 Containerd

一、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 公司明显感觉到自己公司内部所使用的 Borg 系统江湖地位受到的威胁, 希望 Docker 公司能够与自己联合打造一款开源的容器运行时作为 Docker 核心依赖, 但 Docker 公司拒绝了; 接着 Google 公司联合 RedHat、IBM 等公司说服 Docker 公司把其容器核心技术 libcontainer 捐给中立社区(OCI, Open Container Initiative), 并更名为 runC。为了进一步遏制 Docker 在未来技术市场影响力, 避免在容器市场上 Docker 一家独大, Google 公司带领 RedHat、IBM 等成立了 CNCF(Cloud Native Computing Foundation)基金会, 即云原生计算基金会。CNCF 的目标很明确, 既然在容器应用领域无法与 Docker 相抗衡, 那就做 Google 更有经验的技术市场------大规模容器编排应用场景, Google 公司把自己内部使用的 Borg 系统开源------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 Runtime 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, 比如创建容器。

其中, 每一个子系统的行为都由一个或多个模块协作完成(架构图中的 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 模板克隆一台虚拟机命名为 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

三.容器镜像管理

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 查看镜像

[root@docker ~]# ctr images list
REF    TYPE    DIGEST    SIZE    PLATFORMS    LABELS
[root@docker ~]# ctr images ls
REF    TYPE    DIGEST    SIZE    PLATFORMS    LABELS
[root@docker ~]# ctr image list
REF    TYPE    DIGEST    SIZE    PLATFORMS    LABELS
[root@docker ~]# ctr image ls
REF    TYPE    DIGEST    SIZE    PLATFORMS    LABELS
[root@docker ~]# ctr i list
REF    TYPE    DIGEST    SIZE    PLATFORMS    LABELS
[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 pull <镜像加速地址>.mirror.swr.myhuaweicloud.com/library/nginx:latest

# 验证现象
[root@localhost ~]# ctr image ls
REF                                                                       TYPE                                    DIGEST       SIZE      PLATFORMS                                                                                                                       LABELS
<镜像加速地址>.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 镜像挂载

方便查看镜像中包含的内容。

# 挂载
[root@localhost ~]# ctr images mount <镜像加速地址>.mirror.swr.myhuaweicloud.com/library/nginx:latest /mnt
sha256:3c1159cd77f83ede793fc21502ae30b39b04378b6b1b625451d701d555cc1cb9
/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

# 卸载
[root@localhost ~]# umount /mnt

3.5 镜像导出

#--platform linux/amd64,导出指定平台镜像
[root@localhost ~]# ctr i export --platform linux/amd64 nginx.tar <镜像加速地址>.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

# 删除指定镜像
[root@localhost ~]# ctr image rm <镜像加速地址>.mirror.swr.myhuaweicloud.com/library/nginx:latest
<镜像加速地址>.mirror.swr.myhuaweicloud.com/library/nginx:latest

# 验证现象
[root@localhost ~]# ctr image ls
REF    TYPE    DIGEST    SIZE    PLATFORMS    LABELS

3.7 镜像导入

# 导入镜像
[root@localhost ~]# ctr images import --platform linux/amd64 nginx.tar
unpacking <镜像加速地址>.mirror.swr.myhuaweicloud.com/library/nginx:latest (sha256:84ec966e61a8c7846f509da7eb081c55c1d56817448728924a87ab32f12a72fb)...done

# 验证现象
[root@localhost ~]# ctr image ls
REF                                                                       TYPE                                    DIGEST       SIZE      PLATFORMS                                                                                                                       LABELS
<镜像加速地址>.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

# 把 <镜像加速地址>.mirror.swr.myhuaweicloud.com/library/nginx:latest 修改为 nginx:latest
[root@localhost ~]# ctr images tag <镜像加速地址>.mirror.swr.myhuaweicloud.com/library/nginx:latest nginx:latest
nginx:latest

# 验证现象
[root@localhost ~]# ctr image ls
REF                                                                       TYPE                                    DIGEST       SIZE      PLATFORMS                                                                                                                       LABELS
<镜像加速地址>.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 --help 输出同上文"三、3.1 帮助命令", 此处不再重复。

[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
[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。

[root@localhost ~]# ctr container ls    # 可以简写为 ctr c ls
CONTAINER    IMAGE    RUNTIME

3. 查看任务

task 表示容器里跑的进程, 可用 t 缩写代表 task。

[root@localhost ~]# ctr task ls    # 可以简写为 ctr t ls
TASK    PID    STATUS

4. 创建静态容器

[root@localhost ~]# ctr container create nginx:latest nginx1
[root@localhost ~]# ctr container ls
CONTAINER    IMAGE         RUNTIME
nginx1       nginx:latest  io.containerd.runc.v2
[root@localhost ~]# ctr container info nginx1

5. 静态容器启动为动态容器

[root@localhost ~]# ctr task ls
TASK    PID    STATUS
[root@localhost ~]# ctr task start -d nginx1    #启动task, 即表示在容器中运行了进程, 即为动态容器 -d 后台
[root@localhost ~]# ctr task ls    #容器是以宿主机进程的方式存在的
TASK      PID      STATUS
nginx1    22614    RUNNING
[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. 进入容器操作

[root@localhost ~]# ctr task exec --exec-id $RANDOM -t nginx1 /bin/sh
#为exec进程设定一个id, 可以随意输入, 只要保证唯一即可, 也可使用$RANDOM变量

7. 直接运行一个动态容器

[root@localhost ~]# ctr run -d --net-host nginx:latest nginx2
# --net-host 代表容器的IP就是宿主机的IP(相当于docker里的host类型网络)

8. 暂停容器

[root@localhost ~]# ctr tasks pause nginx2
[root@localhost ~]# ctr task ls
TASK      PID      STATUS
nginx1    22614    RUNNING
nginx2    25569    PAUSED    #状态为PAUSED, 表示暂停

9. 恢复容器

[root@localhost ~]# ctr tasks resume nginx2
[root@localhost ~]# ctr task ls
TASK      PID      STATUS
nginx1    22614    RUNNING
nginx2    25569    RUNNING    #恢复RUNNING

10. 停止容器

[root@localhost ~]# ctr tasks kill nginx2
[root@localhost ~]# ctr tasks ls
TASK      PID      STATUS
nginx1    22614    RUNNING
nginx2    25569    STOPPED    #容器停止后STATUS为STOPPED

11. 删除容器

[root@localhost ~]# ctr tasks delete nginx2    #必须先停止tasks或先删除task, 再删除容器
[root@localhost ~]# ctr tasks ls
TASK      PID      STATUS
nginx1    22614    RUNNING
[root@localhost ~]# ctr container ls    # 查看静态容器, 确认其还存在于系统中
CONTAINER    IMAGE         RUNTIME
nginx1       nginx:latest  io.containerd.runc.v2
nginx2       nginx:latest  io.containerd.runc.v2
[root@localhost ~]# ctr container delete nginx2
[root@localhost ~]# ctr container ls
CONTAINER    IMAGE         RUNTIME
nginx1       nginx:latest  io.containerd.runc.v2

五、Containerd 使用私有容器镜像仓库 Harbor

# 手动在containerd宿主机上添加此配置信息,如果域名解析已存在忽略
# 下方为实验环境内网地址, 发博客时请替换为自己的 Harbor 地址
[root@localhost ~]# vim /etc/hosts
<Harbor主机IP> my.harbor.com

# harbor仓库需要提前在Harbor主机上部署(参考docker教案), 镜像需要提前传到harbor上, 如果没有使用https可以使用--plain-http 指定http协议
[root@localhost ~]# ctr image pull --plain-http <Harbor主机IP>/cloud/nginx:latest

# 上传镜像到Harbor
[root@localhost ~]# ctr images tag nginx:latest my.harbor.com/cloud/nginx:latest
[root@localhost ~]# ctr image push --platform linux/amd64 --plain-http --user "<Harbor用户名>:<Harbor密码>" my.harbor.com/cloud/nginx:latest
manifest-sha256:6533ddd664582430971e93e69cf343e3bfffceadeaaa97d4379c4d7a29f21d47: done       |++++++++++++++++++++++++++++++++++++++|
config-sha256:2cd1d97f893f70cee86a38b7160c30e5750f3ed6ad86c598884ca9c6a563a501: done       |++++++++++++++++++++++++++++++++++++++|
elapsed: 0.1 s
total:  3.3 KiB/3.3 KiB

注意: 原文示例中 Harbor 推送使用了明文账号密码(images_admin:Cloud12#$), 整理时已替换为占位符。若你在公开博客中贴出真实凭据, 请立即到 Harbor 控制台修改密码。

六、Containerd NameSpace 管理

containerd 中 namespace 的作用为隔离运行的容器, 可以实现运行多个容器。

1. 列出已有 namespace

[root@localhost ~]# ctr namespace ls
NAME      LABELS
default          #containerd默认工作在default命名空间

[root@docker ~]# ctr namespace ls    #在docker环境中打
NAME    LABELS
moby           #docker默认工作在moby空间

2. 创建 namespace

[root@localhost ~]# ctr namespace create myns
[root@localhost ~]# ctr namespace create testns
[root@localhost ~]# ctr namespace ls
NAME      LABELS
default
myns
testns

3. 删除 namespace

[root@localhost ~]# ctr namespace rm testns
testns
[root@localhost ~]# ctr namespace ls
NAME      LABELS
default
myns

4. 查看指定 namespace 中镜像

[root@localhost ~]# ctr -n myns images ls
REF    TYPE    DIGEST    SIZE    PLATFORMS    LABELS

5. 查看指定 namespace 中是否有用户进程在运行

[root@localhost ~]# ctr -n myns tasks ls
TASK    PID    STATUS

6. 在指定 namespace 中下载容器镜像

[root@localhost ~]# ctr -n myns images pull <镜像加速地址>.mirror.swr.myhuaweicloud.com/library/nginx:latest
[root@localhost ~]# ctr -n myns images ls
REF                                                                       TYPE                                    DIGEST       SIZE      PLATFORMS                                                                                                                       LABELS
<镜像加速地址>.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 中创建静态容器

[root@localhost ~]# ctr -n myns container create <镜像加速地址>.mirror.swr.myhuaweicloud.com/library/nginx:latest mynginx

8. 查看在指定 namespace 中创建的容器

[root@localhost ~]# ctr -n myns container ls
CONTAINER    IMAGE                                                                       RUNTIME
mynginx      <镜像加速地址>.mirror.swr.myhuaweicloud.com/library/nginx:latest    io.containerd.runc.v2
[root@localhost ~]# ctr -n myns task start -d mynginx
[root@localhost ~]# ctr -n myns tasks ls
TASK       PID     STATUS
mynginx    5873    RUNNING

七、nerdctl 实践

nerdctl 安装

我们推荐使用 nerdctl 管理 containerd, 命令语法与 docker 一致。

截止 2023-05-24 最新版本是 v1.4.0。

github 项目地址: https://github.com/containerd/nerdctl/releases

cni 插件项目地址: https://github.com/containernetworking/plugins/releases

# 下载并安装
[root@localhost ~]# wget https://github.com/containerd/nerdctl/releases/download/v1.4.0/nerdctl-1.4.0-linux-amd64.tar.gz
[root@localhost ~]# tar -xf nerdctl-1.4.0-linux-amd64.tar.gz -C /usr/bin/

# 配置nerdctl命令自动补全
[root@localhost ~]# nerdctl completion bash > /etc/bash_completion.d/nerdctl
[root@localhost ~]# source /etc/bash_completion.d/nerdctl

# 下载nerdctl所需要的cni插件
[root@localhost ~]# wget https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz
[root@localhost ~]# mkdir -p /opt/cni/bin
[root@localhost ~]# tar -xf cni-plugins-linux-amd64-v1.3.0.tgz -C /opt/cni/bin

如果 nerdctl 补全时报错信息如下:

_get_comp_words_by_ref: command not found

解决方法: 安装 bash-completion:

[root@localhost ~]# yum install -y bash-completion

配置镜像加速

#编辑containerd的配置文件config.toml, 如果不存在, 需要手动生成, 方法 containerd config default > /etc/containerd/config.toml, 在配置文件中搜索关键字"config_path", 在其下面添加镜像加速参数
[root@docker ~]# containerd config default > /etc/containerd/config.toml
[root@control ~]# vim /etc/containerd/config.toml
146    [plugins."io.containerd.grpc.v1.cri".registry]
147      config_path = "/etc/containerd/certs.d"              #配置这里

[root@control ~]# mkdir -p /etc/containerd/certs.d/docker.io
[root@localhost ~]# vim /etc/containerd/certs.d/docker.io/hosts.toml
server = "https://<镜像加速地址>.mirror.swr.myhuaweicloud.com"

[host."https://<镜像加速地址>.mirror.swr.myhuaweicloud.com"]
  capabilities = ["pull", "resolve"]

#重启containerd服务生效
[root@control ~]# systemctl restart containerd

nerdctl 管理镜像

[root@localhost ~]# nerdctl image <按tab键><按tab键>
build    (Build an image from a Dockerfile. Needs buildkitd to be running.)
convert  (convert an image)
decrypt  (decrypt an image)
encrypt  (encrypt image layers)
history  (Show the history of an image)
inspect  (Display detailed information on one or more images.)
load     (Load an image from a tar archive or STDIN)
ls       (List images)
prune    (Remove unused images)
pull     (Pull an image from a registry. Optionally specify "ipfs://" or "ipns://" scheme to pull image from IPFS.)
push     (Push an image or a repository to a registry. Optionally specify "ipfs://" or "ipns://" scheme to push image to IPFS.)
rm       (Remove one or more images)
save     (Save one or more images to a tar archive (streamed to STDOUT by default))
tag      (Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE)
ls

作用: 查看本地镜像清单。

示例:

[root@localhost ~]# nerdctl image ls
REPOSITORY    TAG    IMAGE ID    CREATED    PLATFORM    SIZE    BLOB SIZE
# 可简写如下
[root@localhost ~]# nerdctl images
pull

作用: 从网络上下载镜像。

示例:

#下载镜像busybox
[root@localhost ~]# nerdctl image pull busybox
# 可简写如下下载httpd
[root@localhost ~]# nerdctl pull httpd
[root@localhost ~]# nerdctl image ls
REPOSITORY    TAG       IMAGE ID        CREATED            PLATFORM        SIZE        BLOB SIZE
busybox       latest    f9a104fddb33    19 minutes ago     linux/amd64     4.1 MiB     2.1 MiB
httpd         latest    fbc12199ccad    44 seconds ago     linux/amd64     152.4 MiB   55.8 MiB
rm

作用: 删除本地不用的镜像。

示例:

[root@localhost ~]# nerdctl image rm httpd
[root@localhost ~]# nerdctl rmi busybox
[root@localhost ~]# nerdctl images
REPOSITORY    TAG       IMAGE ID        CREATED            PLATFORM        SIZE        BLOB SIZE
busybox       latest    f9a104fddb33    19 minutes ago     linux/amd64     4.1 MiB     2.1 MiB
tag

作用: 给镜像打标签。

示例:

[root@localhost ~]# nerdctl tag busybox busybox_containerd
[root@localhost ~]# nerdctl images
REPOSITORY            TAG       IMAGE ID        CREATED            PLATFORM        SIZE        BLOB SIZE
busybox               latest    f9a104fddb33    34 minutes ago     linux/amd64     4.1 MiB     2.1 MiB
busybox_containerd    latest    f9a104fddb33    3 seconds ago      linux/amd64     4.1 MiB     2.1 MiB
save

作用: 将本地镜像导出为文件。

示例:

[root@localhost ~]# nerdctl image save busybox -o busybox.tar
# 可简写为
[root@localhost ~]# nerdctl save busybox -o busybox.tar

# 删除镜像
[root@localhost ~]# nerdctl image rm busybox
[root@localhost ~]# nerdctl images
REPOSITORY            TAG       IMAGE ID        CREATED            PLATFORM        SIZE        BLOB SIZE
busybox_containerd    latest    f9a104fddb33    57 seconds ago     linux/amd64     4.1 MiB     2.1 MiB
load

作用: 导入 tar 文件中镜像。

示例:

[root@localhost ~]# nerdctl image load -i busybox.tar
# 可简写为
[root@localhost ~]# nerdctl load -i busybox.tar
[root@localhost ~]# nerdctl images
REPOSITORY            TAG       IMAGE ID        CREATED             PLATFORM        SIZE        BLOB SIZE
busybox               latest    f9a104fddb33    7 seconds ago       linux/amd64     4.1 MiB     2.1 MiB
busybox_containerd    latest    f9a104fddb33    About a minute ago  linux/amd64     4.1 MiB     2.1 MiB
history

作用: 查看镜像构建时的历史命令层次结构。

示例:

[root@localhost ~]# nerdctl image history busybox
SNAPSHOT                                                                  CREATED         CREATED BY                          SIZE       COMMENT
sha256:65014c70e84b6817fac42bb201ec5c1ea460a8da246cac0e481f5c9a9491eac0    10 months ago   BusyBox 1.37.0 (glibc), Debian 12    4.1 MiB
inspect

作用: 查看镜像详细信息。

示例:

[root@localhost ~]# nerdctl image inspect busybox
[
    {
        "Id": "sha256:6d3e4188a38af91b0c1577b9e88c53368926b2fe0e1fb985d6e8a70040520c4d",
        "RepoTags": [
            "busybox:latest"
        ],
        "RepoDigests": [
            "busybox@sha256:f9a104fddb33220ec80fc45a4e606c74aadf1ef7a3832eb0b05be9e90cd61f5f"
        ],
        "Comment": "",
        "Created": "2024-09-26T21:31:42Z",
        "Author": "",
        "Config": {
            "AttachStdin": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "sh"
            ]
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 4337664,
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:65014c70e84b6817fac42bb201ec5c1ea460a8da246cac0e481f5c9a9491eac0"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]
prune

作用: 删除所有未使用的镜像。

示例:

[root@localhost ~]# nerdctl image prune --all --force
[root@localhost ~]# nerdctl image ls
REPOSITORY    TAG    IMAGE ID    CREATED    PLATFORM    SIZE    BLOB SIZE

nerdctl 管理容器

帮助信息
[root@localhost ~]# nerdctl container --help
Manage containers

Usage: nerdctl container [flags]

Commands:
  commit    Create a new image from a container's changes
  cp        Copy files/folders between a running container and the local filesystem.
  create    Create a new container. Optionally specify "ipfs://" or "ipns://" scheme to pull image from IPFS.
  exec      Run a command in a running container
  inspect   Display detailed information on one or more containers.
  kill      Kill one or more running containers
  logs      Fetch the logs of a container. Expected to be used with 'nerdctl run -d'.
  ls        List containers
  pause     Pause all processes within one or more containers
  port      List port mappings or a specific mapping for the container
  prune     Remove all stopped containers
  rename    rename a container
  restart   Restart one or more running containers
  rm        Remove one or more containers
  run       Run a command in a new container. Optionally specify "ipfs://" or "ipns://" scheme to pull image from IPFS.
  start     Start one or more running containers
  stop      Stop one or more running containers
  unpause   Unpause all processes within one or more containers
  update    Update one or more running containers
  wait      Block until one or more containers stop, then print their exit codes.

Flags:
  -h, --help   help for container

See also 'nerdctl --help' for the global flags such as '--namespace', '--snapshotter', and '--cgroup-manager'.
ls

作用: 查看容器清单。

示例:

[root@localhost ~]# nerdctl container ls
CONTAINER ID    IMAGE    COMMAND    CREATED    STATUS    PORTS    NAMES
# 可简写为
[root@localhost ~]# nerdctl ps
CONTAINER ID    IMAGE    COMMAND    CREATED    STATUS    PORTS    NAMES
# 使用-a选项查看所有容器, 包括未运行的
[root@localhost ~]# nerdctl container ls -a
CONTAINER ID    IMAGE    COMMAND    CREATED    STATUS    PORTS    NAMES

常用选项:

-a, --all             Show all containers (default shows just running)
-f, --filter strings  Filter matches containers based on given conditions
--format string       Format the output using the given Go template, e.g, '{{json .}}', 'wide'
run

作用: 创建并运行容器。

示例:

# 语法:
[root@localhost ~]# nerdctl run --help
Run a command in a new container. Optionally specify "ipfs://" or "ipns://" scheme to pull image from IPFS.

Usage: nerdctl run [flags] IMAGE [COMMAND] [ARG...]

[root@localhost ~]# nerdctl container run -it ubuntu
root@0da9aad32119:/# exit
exit
# 可简写为
[root@localhost ~]# nerdctl run -it ubuntu

# 容器状态为Exited
[root@localhost ~]# nerdctl container ls
CONTAINER ID    IMAGE    COMMAND    CREATED    STATUS    PORTS    NAMES
[root@localhost ~]# nerdctl container ls -a
CONTAINER ID    IMAGE                            COMMAND       CREATED          STATUS                        PORTS    NAMES
0da9aad32119    docker.io/library/ubuntu:latest  "/bin/bash"   3 minutes ago    Exited (130) 2 minutes ago             ubuntu-0da9a

常用选项:

--cpu-shares uint     CPU shares (relative weight)
--cpus float          Number of CPUs
-d, --detach          Run container in background and print container ID
--dns strings         Set custom DNS servers
-e, --env stringArray Set environment variables
-h, --hostname string Container host name
-i, --interactive     Keep STDIN open even if not attached
--ip string           IPv4 address to assign to the container
--mac-address string  MAC address to assign to the container
-m, --memory string   Memory limit
--name string         Assign a name to the container
--net strings         Connect a container to a network ("bridge"|"host"|"none"|) (default [bridge])
--network strings     Connect a container to a network ("bridge"|"host"|"none"|"container:"|) (default [bridge])
--privileged          Give extended privileges to this container
--pull string         Pull image before running ("always"|"missing"|"never") (default "missing")
--restart string      Restart policy to apply when a container exits (implemented values: "no"|"always|on-failure:n|unless-stopped") (default "no")
--rm                  Automatically remove the container when it exits
--runtime string      Runtime to use for this container, e.g.
--stop-signal string  Signal to stop a container (default "SIGTERM")
--stop-timeout        Timeout (in seconds) to stop a container
-t, --tty             Allocate a pseudo-TTY
-v, --volume          Bind mount a volume
rm

作用: 删除容器。

示例:

[root@localhost ~]# nerdctl container rm 0da9aad32119
0da9aad32119
[root@localhost ~]# nerdctl container ls -a
CONTAINER ID    IMAGE    COMMAND    CREATED    STATUS    PORTS    NAMES
prune

作用: 删除所有未运行的容器。

示例:

[root@localhost ~]# nerdctl container run ubuntu
[root@localhost ~]# nerdctl container run ubuntu
[root@localhost ~]# nerdctl container ls -a
CONTAINER ID    IMAGE                            COMMAND       CREATED           STATUS                    PORTS    NAMES
3778651cfacb    docker.io/library/ubuntu:latest  "/bin/bash"   5 seconds ago     Exited (0) 5 seconds ago           ubuntu-37786
3e8221845ab4    docker.io/library/ubuntu:latest  "/bin/bash"   11 seconds ago    Exited (0) 11 seconds ago          ubuntu-3e822
[root@localhost ~]# nerdctl container prune --force
Deleted Containers:
3778651cfacba1cd489b065ff7017b272b9edddc71211e2a6e567d9d0ec8ac54
3e8221845ab479f18a091c04443d26632946c9ced264c21a490f6b3052bde0b2
rename

作用: 重命名容器。

示例:

[root@localhost ~]# nerdctl container run --name ubuntu-1 ubuntu
[root@localhost ~]# nerdctl container ls -a
CONTAINER ID    IMAGE                            COMMAND       CREATED           STATUS                     PORTS    NAMES
61384145427a    docker.io/library/ubuntu:latest  "/bin/bash"   13 seconds ago    Exited (0) 13 seconds ago           ubuntu-1
[root@localhost ~]# nerdctl container rename ubuntu-1 ubuntu
[root@localhost ~]# nerdctl container ls -a
CONTAINER ID    IMAGE                            COMMAND       CREATED           STATUS                     PORTS    NAMES
61384145427a    docker.io/library/ubuntu:latest  "/bin/bash"   26 seconds ago    Exited (0) 26 seconds ago           ubuntu
[root@localhost ~]# nerdctl container rm ubuntu
ubuntu
stop 和 start

作用: 停止和启动容器。

示例:

[root@localhost ~]# nerdctl container run -d --name nginx1 nginx
[root@localhost ~]# nerdctl container ls --format "{{.Names}} {{.Status}}"
nginx1 Up
[root@localhost ~]# nerdctl container stop nginx1
nginx1
[root@localhost ~]# nerdctl container ls --format "{{.Names}} {{.Status}}" -a
nginx1 Exited (0) 13 seconds ago
[root@localhost ~]# nerdctl container start nginx1
nginx1
[root@localhost ~]# nerdctl container ls --format "{{.Names}} {{.Status}}"
nginx1 Up
restart

作用: 重启容器。

示例:

[root@localhost ~]# nerdctl container restart nginx1
nginx1
pause 和 unpause

作用: 暂停和取消挂起容器。

示例:

[root@localhost ~]# nerdctl container pause nginx1
nginx1
[root@localhost ~]# nerdctl container ls --format "{{.Names}} {{.Status}}" -a
nginx1 Paused
[root@localhost ~]# nerdctl container unpause nginx1
nginx1
[root@localhost ~]# nerdctl container ls --format "{{.Names}} {{.Status}}" -a
nginx1 Up
kill

作用: 给容器发信号, 默认发 KILL 信号。

示例:

[root@localhost ~]# nerdctl container kill nginx1
945c89b61aafc3475317e8801ad8526fdf337b038bfa315472e4c723bf5406f1
[root@localhost ~]# nerdctl container ls -a --format "{{.Names}} {{.Status}}"
nginx1 Exited (137) 8 seconds ago
exec

作用: 在运行的容器内部执行命令。

示例:

[root@localhost ~]# nerdctl container start nginx1
nginx1
[root@localhost ~]# nerdctl container exec -it nginx1 bash
root@945c89b61aaf:/# exit
exit
cp

作用: 将宿主机文件复制给容器。

示例:

[root@localhost ~]# nerdctl container cp /etc/hostname nginx1:
[root@localhost ~]# nerdctl container exec nginx1 ls hostname
hostname

思考: 如果容器中的文件拷贝给宿主机该如何操作?

inspect

作用: 查看容器详细信息。

示例:

[root@localhost ~]# nerdctl container inspect nginx1
[
    {
        "Id": "945c89b61aafc3475317e8801ad8526fdf337b038bfa315472e4c723bf5406f1",
        "Created": "2025-08-02T14:07:36.213384887Z",
        "Path": "/docker-entrypoint.sh",
        "Args": [
            "nginx",
            "-g",
            "daemon off;"
        ],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "Pid": 49359,
            "ExitCode": 0,
            "Error": "",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "docker.io/library/nginx:latest",
        "ResolvConfPath": "/var/lib/nerdctl/1935db59/containers/default/945c89b61aafc3475317e8801ad8526fdf337b038bfa315472e4c723bf5406f1/resolv.conf",
        "HostnamePath": "/var/lib/nerdctl/1935db59/containers/default/945c89b61aafc3475317e8801ad8526fdf337b038bfa315472e4c723bf5406f1/hostname",
        "LogPath": "/var/lib/nerdctl/1935db59/containers/default/945c89b61aafc3475317e8801ad8526fdf337b038bfa315472e4c723bf5406f1/945c89b61aafc3475317e8801ad8526fdf337b038bfa315472e4c723bf5406f1-json.log",
        "Name": "nginx1",
        "RestartCount": 0,
        "Driver": "overlayfs",
        "Platform": "linux",
        "AppArmorProfile": "",
        "Mounts": null,
        "Config": {
            "Hostname": "945c89b61aaf",
            "AttachStdin": false,
            "Labels": {
                "containerd.io/restart.explicitly-stopped": "false",
                "io.containerd.image.config.stop-signal": "SIGQUIT",
                "nerdctl/extraHosts": "null",
                "nerdctl/hostname": "945c89b61aaf",
                "nerdctl/log-uri": "binary:///usr/bin/nerdctl?_NERDCTL_INTERNAL_LOGGING=%2Fvar%2Flib%2Fnerdctl%2F1935db59",
                "nerdctl/name": "nginx1",
                "nerdctl/namespace": "default",
                "nerdctl/networks": "[\"bridge\"]",
                "nerdctl/platform": "linux/amd64",
                "nerdctl/state-dir": "/var/lib/nerdctl/1935db59/containers/default/945c89b61aafc3475317e8801ad8526fdf337b038bfa315472e4c723bf5406f1"
            }
        },
        "NetworkSettings": {
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "10.4.0.15",
            "IPPrefixLen": 24,
            "MacAddress": "32:81:21:fb:b4:72",
            "Networks": {
                "unknown-eth0": {
                    "IPAddress": "10.4.0.15",
                    "IPPrefixLen": 24,
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "32:81:21:fb:b4:72"
                }
            }
        }
    }
]
logs

作用: 显示容器 console 终端内容。

示例:

[root@localhost ~]# nerdctl container logs nginx1
/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
10-listen-on-ipv6-by-default.sh: info: IPv6 listen already enabled
/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2025/08/02 14:10:40 [notice] 1#1: using the "epoll" event method
2025/08/02 14:10:40 [notice] 1#1: nginx/1.29.0
2025/08/02 14:10:40 [notice] 1#1: built by gcc 12.2.0 (Debian 12.2.0-14+deb12u1)
2025/08/02 14:10:40 [notice] 1#1: OS: Linux 4.18.0-553.6.1.el8.x86_64
2025/08/02 14:10:40 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1024:1024
2025/08/02 14:10:40 [notice] 1#1: start worker processes
2025/08/02 14:10:40 [notice] 1#1: start worker process 22
2025/08/02 14:10:40 [notice] 1#1: start worker process 23
2025/08/02 14:10:40 [notice] 1#1: start worker process 24
2025/08/02 14:10:40 [notice] 1#1: start worker process 25
port

作用: 显示宿主机和容器之间端口映射关系。

示例:

[root@localhost ~]# nerdctl container run --name nginx -d -p 8080:80 nginx
2d0923e9f7c816d9fc8f5fa30b1be332c90fff0e354c981b919fc67bd1f97101
[root@localhost ~]# nerdctl container port nginx
80/tcp -> 0.0.0.0:8080
commit

作用: 将容器提交为镜像。

示例:

[root@localhost ~]# nerdctl commit nginx nginx_containerd
sha256:6e60d18c9e7f7968f49edfacae16e39df2a995d3119b0b23356fd501cd8348a6
[root@localhost ~]# nerdctl images
REPOSITORY          TAG       IMAGE ID        CREATED            PLATFORM        SIZE         BLOB SIZE
nginx               latest    84ec966e61a8    17 minutes ago     linux/amd64     194.4 MiB    68.9 MiB
nginx_containerd    latest    d59a30a56f7f    3 seconds ago      linux/amd64     194.4 MiB    68.9 MiB
ubuntu              latest    a08e551cb338    26 minutes ago     linux/amd64     81.1 MiB     28.4 MiB

nerdctl 管理网络

Containerd 中的网络与 Docker 类似, 所有网络接口默认都是虚拟接口。

当使用 nerdctl 创建容器时, nerdctl 命令会创建一个名称为 bridge 的 Linux 网桥(其上有一个 nerdctl0 内部接口), 利用了 Linux 虚拟网络技术, 在本地主机和容器内分别创建一个虚拟接口, 并让它们彼此连通(这样的一对接口叫做 veth pair)。Containerd 默认指定了 nerdctl0 接口的 IP 地址和子网掩码, 让主机和容器之间可以通过网桥相互通信。

示例(以下 IP 为实验环境取值, 你自己的环境会不同):

[root@localhost ~]# nerdctl run -d busybox -- sleep infinity
b721795e02103578656152662f414e88f32191e64976ccafe60c4af10a8fa8c8
[root@localhost ~]# nerdctl container ls
CONTAINER ID    IMAGE                             COMMAND             CREATED         STATUS    PORTS    NAMES
b721795e0210    docker.io/library/busybox:latest  "sleep infinity"    12 seconds ago  Up                 busybox-b7217
[root@localhost ~]# nerdctl exec busybox-b7217 -- ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0@if5: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether f6:fc:0b:35:5e:2c brd ff:ff:ff:ff:ff:ff
    inet 10.4.0.18/24 brd 10.4.0.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::f4fc:bff:fe35:5e2c/64 scope link
       valid_lft forever preferred_lft forever

容器内看到的网卡名: 2: eth0@if5, @if5 代表对端是 5 号网卡。

[root@localhost ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:0c:29:a7:b8:a7 brd ff:ff:ff:ff:ff:ff
    altname enp3s0
    inet 192.168.108.30/24 brd 192.168.108.255 scope global noprefixroute ens160
       valid_lft forever preferred_lft forever
    inet6 fe80::20c:29ff:fea7:b8a7/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
3: nerdctl0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 3a:1a:93:b7:ea:d7 brd ff:ff:ff:ff:ff:ff
    inet 10.4.0.1/24 brd 10.4.0.255 scope global nerdctl0
       valid_lft forever preferred_lft forever
    inet6 fe80::381a:93ff:feb7:ead7/64 scope link
       valid_lft forever preferred_lft forever
5: veth790d9140@if2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master nerdctl0 state UP group default
    link/ether 3a:fa:0e:fd:27:5b brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::38fa:eff:fefd:275b/64 scope link
       valid_lft forever preferred_lft forever

对应容器主机的网卡: 5: veth790d9140@if2, @if2 代表对端容器内对应 2 号网卡。

示例:

[root@localhost ~]# nerdctl network ls
NETWORK ID      NAME      FILE
17f29b073143    bridge    /etc/cni/net.d/nerdctl-bridge.conflist
host
none
[root@localhost ~]# nerdctl network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "17f29b073143d8cd97b5bbe492bdeffec1c5fee55cc1fe2112c8b9335f8b6121",
        "IPAM": {
            "Config": [
                {
                    "Subnet": "10.4.0.0/24",
                    "Gateway": "10.4.0.1"
                }
            ]
        },
        "Labels": {
            "nerdctl/default-network": "true"
        }
    }
]

# 主机中nerdctl0就是容器的网关
[root@localhost ~]# ip addr show nerdctl0
3: nerdctl0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 3a:1a:93:b7:ea:d7 brd ff:ff:ff:ff:ff:ff
    inet 10.4.0.1/24 brd 10.4.0.255 scope global nerdctl0
       valid_lft forever preferred_lft forever
    inet6 fe80::381a:93ff:feb7:ead7/64 scope link
       valid_lft forever preferred_lft forever

目前 Containerd 网桥是 Linux 网桥, 用户可以使用 brctl show 命令查看网桥和端口连接信息。

[root@localhost ~]# brctl show
bridge name     bridge id               STP enabled     interfaces
nerdctl0        8000.3a1a93b7ead7       no              veth790d9140

nerdctl network 命令使用帮助:

[root@localhost ~]# nerdctl network --help
Manage networks

Usage: nerdctl network [flags]

Commands:
  create    Create a network
  inspect   Display detailed information on one or more networks
  ls        List networks
  prune     Remove all unused networks
  rm        Remove one or more networks

Flags:
  -h, --help   help for network

See also 'nerdctl --help' for the global flags such as '--namespace', '--snapshotter', and '--cgroup-manager'.

nerdctl 管理存储

nerdctl volume 命令使用帮助:

[root@localhost ~]# nerdctl volume --help
Manage volumes

Usage: nerdctl volume [flags]

Commands:
  create    Create a volume
  inspect   Display detailed information on one or more volumes
  ls        List volumes
  prune     Remove all unused local volumes
  rm        Remove one or more volumes

Flags:
  -h, --help   help for volume

See also 'nerdctl --help' for the global flags such as '--namespace', '--snapshotter', and '--cgroup-manager'.

nerdctl 命令创建容器的时候, 可以使用 -v 选项将本地目录挂载给容器实现数据持久化。

示例:

[root@localhost ~]# mkdir /data
[root@localhost ~]# nerdctl run -d -v /data:/data busybox -- sleep infinity
d00a1646169a199e3038851f86b82bff03ac2db6ffd8ea3e875789d2a6d1a000
[root@localhost ~]# touch /data/f1
[root@localhost ~]# nerdctl exec busybox-d00a1 -- ls /data
f1

nerdctl 命令创建容器的时候, 也可以使用 -v 选项指定 volume。

# 直接写容器目录, 会自动生成目录
[root@localhost ~]# nerdctl run -d -v /data busybox -- sleep infinity
29c94622886a219c93b5f6cd1c1ab190f998c66e3b4cbce75437507803b82eea
[root@localhost ~]# nerdctl exec busybox-29c94 -- touch /data/f2
#在/var/lib/nerdctl/xx/volumes/default/xx/_data/f2

#指定宿主机生成的目录名为data
[root@localhost ~]# nerdctl run -d -v data:/data busybox -- sleep infinity
1b1fc00e88471a5abd8787bae438ab8d5ab08f4ec4fa073805407f9fffe2fe73
[root@localhost ~]# nerdctl exec busybox-1b1fc -- touch /data/f3

# 生成data名字的卷
[root@localhost ~]# nerdctl volume ls
VOLUME NAME                                                              DIRECTORY
0c70033c26bcf456d9a0dc3f7dfe723f232e48dee2c8898bf987f8aeebacc1c7         /var/lib/nerdctl/1935db59/volumes/default/0c70033c26bcf456d9a0dc3f7dfe723f232e48dee2c8898bf987f8aeebacc1c7/_data
data                                                                     /var/lib/nerdctl/1935db59/volumes/default/data/_data
[root@localhost ~]# ls /var/lib/nerdctl/1935db59/volumes/default/0c70033c26bcf456d9a0dc3f7dfe723f232e48dee2c8898bf987f8aeebacc1c7/_data
f2
[root@localhost ~]# ls /var/lib/nerdctl/1935db59/volumes/default/data/_data
f3

nerdctl 管理命名空间

[root@localhost ~]# nerdctl namespace
Unrelated to Linux namespaces and Kubernetes namespaces

Usage: nerdctl namespace [flags]

Aliases: namespace, ns

Commands:
  create    Create a new namespace
  inspect   Display detailed information on one or more namespaces.
  ls        List containerd namespaces
  remove    Remove one or more namespaces
  update    Update labels for a namespace

Flags:
  -h, --help   help for namespace

See also 'nerdctl --help' for the global flags such as '--namespace', '--snapshotter', and '--cgroup-manager'.

示例:

[root@localhost ~]# nerdctl namespace ls
NAME       CONTAINERS    IMAGES    VOLUMES    LABELS
default    10            4         2

八、crictl 实践

crictl 命令介绍

crictl 命令是遵循 CRI 接口规范的一个命令行工具, 通常用它来检查和管理 kubelet 节点上的容器运行时和镜像。

在 kubernetes 集群环境中, 当我们执行 kubectl 命令时, kubelet 代理会自动调用 crictl 命令管理镜像和容器。

手动执行 crictl 命令时, 一般用于查看镜像和容器。

crictl 命令安装

配置 kubernetes 源:

[root@localhost ~]# vim /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.30/rpm/
enabled=1
gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes-new/core/stable/v1.30/rpm/repodata/repomd.xml.key

安装 CRI 命令:

[root@localhost ~]# yum install -y cri-tools

crictl 命令配置

使用 crictl 命令之前, 需要先配置 /etc/crictl.yaml。

示例: 配置 crictl 后端运行时使用 containerd。

[root@localhost ~]# vim /etc/crictl.yaml
runtime-endpoint: unix:///run/containerd/containerd.sock
image-endpoint: unix:///run/containerd/containerd.sock
timeout: 5
debug: false

也可以通过命令进行设置:

[root@localhost ~]# crictl config runtime-endpoint unix:///run/containerd/containerd.sock
[root@localhost ~]# crictl config image-endpoint unix:///run/containerd/containerd.sock

更多命令操作, 可以直接在命令行输入命令查看帮助。

[root@localhost ~]# crictl config --help
NAME:
   crictl config - Get and set crictl client configuration options

USAGE:
   crictl config [command options] [<crictl options>]

EXAMPLE:
   crictl config --set debug=true

CRICTL OPTIONS:
   runtime-endpoint:      Container runtime endpoint
   image-endpoint:        Image endpoint
   timeout:               Timeout of connecting to server (default: 2s)
   debug:                 Enable debug output (default: false)
   pull-image-on-create:  Enable pulling image on create requests (default: false)
   disable-pull-on-run:   Disable pulling image on run requests (default: false)

OPTIONS:
   --get value                  show the option value
   --list                       show all option value (default: false)
   --set value [ --set value ]  set option (can specify multiple or separate values with commas: opt1=val1,opt2=val2)
   --help, -h                   show help

crictl 命令实践

帮助信息:

[root@localhost ~]# crictl
NAME:
   crictl - client for CRI

USAGE:
   crictl [global options] command [command options]

VERSION:
   v1.30.1

COMMANDS:
   attach              Attach to a running container
   create              Create a new container
   exec                Run a command in a running container
   version             Display runtime version information
   images, image, img  List images
   inspect             Display the status of one or more containers
   inspecti            Return the status of one or more images
   imagefsinfo         Return image filesystem info
   inspectp            Display the status of one or more pods
   logs                Fetch the logs of a container
   port-forward        Forward local port to a pod
   ps                  List containers
   pull                Pull an image from a registry
   run                 Run a new container inside a sandbox
   runp                Run a new pod
   rm                  Remove one or more containers
   rmi                 Remove one or more images
   rmp                 Remove one or more pods
   pods                List pods
   start               Start one or more created containers
   info                Display information of the container runtime
   stop                Stop one or more running containers
   stopp               Stop one or more running pods
   update              Update one or more running containers
   config              Get and set crictl client configuration options
   stats               List container(s) resource usage statistics
   statsp              List pod statistics. Stats represent a structured API that will fulfill the Kubelet's /stats/summary endpoint.
   metricsp            List pod metrics. Metrics are unstructured key/value pairs gathered by CRI meant to replace cAdvisor's /metrics/cadvisor endpoint.
   completion          Output shell completion code
   checkpoint          Checkpoint one or more running containers
   runtime-config      Retrieve the container runtime configuration
   events, event       Stream the events of containers
   help, h             Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --config value, -c value    Location of the client config file. If not specified and the default does not exist, the program's directory is searched as well (default: "/etc/crictl.yaml") [$CRI_CONFIG_FILE]
   --debug, -D                 Enable debug mode (default: false)
   --enable-tracing            Enable OpenTelemetry tracing. (default: false)
   --image-endpoint value, -i value      Endpoint of CRI image manager service (default: uses 'runtime-endpoint' setting) [$IMAGE_SERVICE_ENDPOINT]
   --runtime-endpoint value, -r value    Endpoint of CRI container runtime service (default: uses in order the first successful one of [unix:///run/containerd/containerd.sock unix:///run/crio/crio.sock unix:///var/run/cri-dockerd.sock]). Default is now deprecated and the endpoint should be set instead. [$CONTAINER_RUNTIME_ENDPOINT]
   --timeout value, -t value   Timeout of connecting to the server in seconds (e.g. 2s, 20s.). 0 or less is set to default (default: 2s)
   --tracing-endpoint value    Address to which the gRPC tracing collector will send spans to. (default: "127.0.0.1:4317")
   --tracing-sampling-rate-per-million value    Number of samples to collect per million OpenTelemetry spans. Set to 1000000 to always sample. (default: -1)
   --help, -h                  show help
   --version, -v               print the version

案例:

[root@localhost ~]# crictl pull <镜像加速地址>.mirror.swr.myhuaweicloud.com/library/nginx:latest
Image is up to date for sha256:9f33606b36859ee2db3b761a893fb7c2fc8a13c0fe5f24e304b129f3caf499ad
[root@localhost ~]# crictl images
IMAGE                      TAG        IMAGE ID           SIZE
docker.io/library/httpd    latest     65005131d37e9      45.2MB

镜像命令:

images, image, img  List images
pull                Pull an image from a registry
inspecti            Return the status of one or more images
imagefsinfo         Return image filesystem info
rmi                 Remove one or more images

容器命令:

ps                  List containers
create              Create a new container
run                 Run a new container inside a sandbox
inspect             Display the status of one or more containers
info                Display information of the container runtime
attach              Attach to a running container
exec                Run a command in a running container
logs                Fetch the logs of a container
update              Update one or more running containers
stats               List container(s) resource usage statistics
checkpoint          Checkpoint one or more running containers
start               Start one or more created containers
stop                Stop one or more running containers
rm                  Remove one or more containers

pod 命令:

pods                List pods
runp                Run a new pod
inspectp            Display the status of one or more pods
statsp              List pod resource usage statistics
port-forward        Forward local port to a pod
stopp               Stop one or more running pods
rmp                 Remove one or more pods

其他命令:

version             Display runtime version information
config              Get and set crictl client configuration options
completion          Output shell completion code
help, h             Shows a list of commands or help for one command

命令行对照表

命令功能dockerpodmannerdctlctrcrictl
查看容器状态docker pspodman psnerdctl psctr task ls / ctr container lscrictl ps
查看镜像docker imagespodman imagesnerdctl imagesctr image lscrictl images
查看容器日志docker logspodman logsnerdctl logscrictl logs
查看容器信息docker inspectpodman inspectnerdctl inspectctr container infocrictl inspect
查看容器资源docker statspodman statsnerdctl statscrictl stats
运行新容器docker runpodman runnerdctl runctr run
修改镜像标签docker tagpodman tagnerdctl tagctr image tag
创建新容器docker createpodman createnerdctl createctr container createcrictl create
导入镜像docker loadpodman loadnerdctl loadctr image import
导出镜像docker savepodman savenerdctl savectr image export
删除容器docker rmpodman rmnerdctl rmctr container rmcrictl rm
删除镜像docker rmipodman rminerdctl rmictr image rmcrictl rmi
拉取镜像docker pullpodman pullnerdctl pullctr image pullcrictl pull
推送镜像docker pushpodman pushnerdctl pushctr image push
在容器内部执行命令docker execpodman execnerdctl execcrictl exec

如果您还对 Docker 比较怀旧的话, 执行 alias docker=nerdctl 这样的命令后, 您依然可以体验到与 Docker 相似的感觉。

nerdctl 和 crictl 都是用于管理和操作容器的命令行工具, 但是它们在开发者、设计目的和功能上有所不同。

  1. nerdctl:

    • 开发者: 由 Docker 的创始人之一, 也是 containerd 项目的主要贡献者 Akihiro Suda 开发。
    • 设计目的: nerdctl 是一个兼容 Docker CLI 的 containerd CLI, 意味着大部分 Docker 命令可以在 nerdctl 中运行。
    • 功能: 它可以管理容器的生命周期, 如创建、运行、停止和删除容器。此外, 它还支持镜像管理、网络管理、卷管理等。
  2. crictl:

    • 开发者: 由 Kubernetes 项目社区开发。
    • 设计目的: crictl 是一个命令行接口, 用于与任何实现了 Kubernetes 容器运行时接口(CRI)的容器运行时进行交互, 例如 containerd、CRI-O 等。
    • 功能: 它主要用于调试, 可以从 Kubernetes API Server 的角度检查和理解容器运行时的行为。它允许用户直接与容器运行时进行交互, 实现容器生命周期管理、镜像管理等。

总的来说, 二者主要区别在于他们的使用场景和目标用户并不完全相同。nerdctl 更适合需要 Docker CLI 兼容性的用户, 而 crictl 则更适合需要调试和理解 Kubernetes CRI 容器运行时行为的用户。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值