containerd:使用 ctr 和 runc 管理容器

大家好!在今天的文章中,我们将深入探讨 containerd 生态系统的核心组件,特别是它的命令行工具 ctr 以及底层的 OCI 运行时 runc。对于希望理解容器技术底层原理或直接与 containerd 交互(例如在 Kubernetes 环境中进行调试)的朋友来说,掌握 ctr 是非常有价值的。

containerd 是一个行业标准的容器运行时,负责管理完整的容器生命周期——从镜像传输和存储到容器执行、监控以及网络。而 runc 是一个轻量级的工具,用于根据 OCI (Open Container Initiative) 规范来运行容器。ctr 则是 containerd 提供的一个简单、面向开发的 CLI 工具,允许我们直接与 containerd守护进程交互。

让我们一步步来探索如何安装 runc 并使用 ctr 进行各种容器和镜像管理操作。

一、安装 runC

runc 是执行容器的核心。虽然 containerd 通常会自带或依赖特定版本的 runc,但了解如何手动安装或更新它也很有用。

  1. 下载 runc 二进制文件
    我们可以从 runc 的 GitHub Releases 页面下载预编译的二进制文件。请确保选择适合您系统架构(如此处的 amd64)的版本。

    # 访问官方 Releases 页面获取最新版本或所需版本链接
    # https://github.com/opencontainers/runc/releases
    # 例如,下载 v1.1.12 版本
    wget https://github.com/opencontainers/runc/releases/download/v1.1.12/runc.amd64
    
    # (备用)如果您有内部软件源,也可以从内部地址下载
    # wget http://192.168.16.253/Linux92/Docker/day14-/softwares/runc.amd64
    
  2. runc 安装到系统 PATH
    为了能在任何地方调用 runc 命令,需要将其移动到环境变量 PATH 包含的目录中(如 /usr/bin/usr/local/bin),并重命名为 runc

    # 查看下载的文件信息
    [root@docker102 ~]# ll -h runc.amd64
    -rw-r--r--. 1 root root 11M Feb 17 19:16 runc.amd64
    
    # 移动并重命名到 /usr/bin/
    [root@docker102 ~]# mv runc.amd64 /usr/bin/runc
    

    注意:生产环境中, /usr/local/bin 通常是更推荐的自定义二进制文件安装位置。

  3. 添加执行权限
    确保 runc 文件具有可执行权限。

    [root@docker102 ~]# chmod +x /usr/bin/runc
    
  4. 验证安装
    检查 runc 版本信息以确认安装成功。

    [root@docker102 ~]# runc --version
    runc version 1.1.12
    commit: v1.1.12-0-g51d5e946
    spec: 1.0.2-dev
    go: go1.20.13
    libseccomp: 2.5.4
    

二、使用 ctr 进行镜像管理

ctr 提供了丰富的子命令来管理容器镜像。

  1. 查看本地镜像列表 (images ls)
    列出 containerd 已知的所有镜像。

    [root@docker102 ~]# ctr images ls
    REF TYPE DIGEST SIZE PLATFORMS LABELS
    # 初始状态下,列表为空
    
  2. 拉取镜像 (images pull)
    从指定的容器镜像仓库拉取镜像。

    [root@docker102 ~]# ctr images pull registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1
    # 输出显示了拉取过程,包括解析、下载各层(layer)和配置(config)
    # ... (省略了详细下载进度)
    unpacking linux/amd64 sha256:3bee216f250cfd2dbda1744d6849e27118845b8f4d55dda3ca3c6c1227cc2e5c...
    done: 797.550909ms
    
    # 再次查看镜像列表
    [root@docker102 ~]# ctr images ls
    REF                                                       TYPE                                                 DIGEST                                                                  SIZE    PLATFORMS   LABELS
    registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1 application/vnd.docker.distribution.manifest.v2+json sha256:3bee216f250cfd2dbda1744d6849e27118845b8f4d55dda3ca3c6c1227cc2e5c 9.6 MiB linux/amd64 -
    

    注意:ctr 默认不会像 Docker 那样自动搜索 docker.io,需要提供完整的镜像引用。

  3. 挂载镜像查看内容 (images mount)
    这是一个非常有用的调试功能,可以将镜像的根文件系统挂载到宿主机的某个目录,方便查看其内部结构,而无需启动容器。

    # 创建或指定一个挂载点,例如 /mnt
    [root@docker102 ~]# mkdir -p /mnt/image_rootfs
    
    # 挂载镜像
    [root@docker102 ~]# ctr images mount registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1 /mnt/image_rootfs
    sha256:1d14ebb5d571f4ae7b23885c1936c7ccf7ccea25d9abe47adef4bbb08b02b0c1
    /mnt/image_rootfs
    
    # 查看挂载后的目录内容
    [root@docker102 ~]# ls -l /mnt/image_rootfs
    total 84
    drwxr-xr-x  2 root root 4096 Nov 12  2021 bin
    drwxr-xr-x  2 root root 4096 Nov 12  2021 dev
    # ... (其他文件和目录)
    
    # 查看完毕后,务必卸载
    [root@docker102 ~]# umount /mnt/image_rootfs
    
  4. 导出镜像 (images export)
    将本地镜像导出为一个 tar 包,通常用于离线传输或备份。可以指定平台。

    [root@docker102 ~]# ctr images export --platform linux/amd64 oldboyedu-xiuxian-v1.tar.gz registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1
    [root@docker102 ~]# ll -h oldboyedu-xiuxian-v1.tar.gz
    -rw-r--r-- 1 root root 9.7M Jul 27 15:36 oldboyedu-xiuxian-v1.tar.gz
    
  5. 删除本地镜像 (images rm)
    移除不再需要的本地镜像。

    [root@docker102 ~]# ctr images rm registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1
    registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1
    [root@docker102 ~]# ctr images ls
    REF TYPE DIGEST SIZE PLATFORMS LABELS
    # 列表再次变空
    
  6. 导入镜像 (images import)
    从导出的 tar 包中加载镜像到本地。

    [root@docker102 ~]# ctr images import --platform linux/amd64 oldboyedu-xiuxian-v1.tar.gz
    unpacking registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1 (sha256:3bee216f250cfd2dbda1744d6849e27118845b8f4d55dda3ca3c6c1227cc2e5c)...done
    [root@docker102 ~]# ctr images ls
    REF                                                       TYPE                                                 DIGEST                                                                  SIZE    PLATFORMS   LABELS
    registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1 application/vnd.docker.distribution.manifest.v2+json sha256:3bee216f250cfd2dbda1744d6849e27118845b8f4d55dda3ca3c6c1227cc2e5c 9.6 MiB linux/amd64 -
    
  7. 给镜像打标签 (images tag)
    为一个已存在的镜像(通过其引用或摘要)创建一个新的引用(标签)。这常用于版本管理或推送到不同仓库。

    # 将现有镜像打上新的标签
    [root@docker102 ~]# ctr images tag registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1 10.0.0.101/oldboyedu-games/xiuxian:v1
    10.0.0.101/oldboyedu-games/xiuxian:v1
    
    # 查看列表,会发现多了一个引用,但 DIGEST 相同,表示指向同一个镜像内容
    [root@docker102 ~]# ctr images ls
    REF                                                       TYPE                                                 DIGEST                                                                  SIZE    PLATFORMS   LABELS
    10.0.0.101/oldboyedu-games/xiuxian:v1                     application/vnd.docker.distribution.manifest.v2+json sha256:3bee216f250cfd2dbda1744d6849e27118845b8f4d55dda3ca3c6c1227cc2e5c 9.6 MiB linux/amd64 -
    registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1 application/vnd.docker.distribution.manifest.v2+json sha256:3bee216f250cfd2dbda1744d6849e27118845b8f4d55dda3ca3c6c1227cc2e5c 9.6 MiB linux/amd64 -
    
  8. 检查镜像完整性 (images check)
    验证本地镜像的所有层数据是否都存在且可用。

    [root@docker102 ~]# ctr images check
    REF                                                       TYPE                                                 DIGEST                                                                  STATUS         SIZE            UNPACKED
    10.0.0.101/oldboyedu-games/xiuxian:v1                     application/vnd.docker.distribution.manifest.v2+json sha256:3bee216f250cfd2dbda1744d6849e27118845b8f4d55dda3ca3c6c1227cc2e5c complete (8/8) 9.6 MiB/9.6 MiB true
    registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1 application/vnd.docker.distribution.manifest.v2+json sha256:3bee216f250cfd2dbda1744d6849e27118845b8f4d55dda3ca3c6c1227cc2e5c complete (8/8) 9.6 MiB/9.6 MiB true
    

三、使用 ctr 进行容器生命周期管理

ctr 不仅管理镜像,还管理容器的创建、运行和销毁。需要理解 container(容器元数据)和 task(运行中的容器进程)的区别。

  1. 创建容器 (containers create)
    基于一个镜像创建一个容器的定义(元数据),但此时容器并未运行。

    [root@docker102 ~]# ctr containers create registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1 xiuxian
    # "xiuxian" 是我们为这个容器指定的名字 (Container ID)
    
  2. 查看容器列表 (containers ls)
    列出所有已创建的容器(无论是否在运行)。

    [root@docker102 ~]# ctr containers ls
    CONTAINER    IMAGE                                                        RUNTIME
    xiuxian      registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1    io.containerd.runc.v2
    
  3. 查看容器详细信息 (containers info)
    获取指定容器的详细配置和状态信息。

    [root@docker102 ~]# ctr containers info xiuxian
    # 输出为 JSON 格式,包含 ID, Labels, Image, Snapshotter, Runtime, Spec 等信息
    # {
    #     "ID": "xiuxian",
    #     "Labels": { ... },
    #     "Image": "registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1",
    #     ...
    # }
    
  4. 启动容器任务 (task start)
    为一个已创建的容器启动一个任务(即运行容器内的进程)。-d 选项表示在后台运行(detach)。

    [root@docker102 ~]# ctr task start -d xiuxian
    # 容器启动时可能会打印其入口点脚本的日志
    # /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
    # ...
    
  5. 查看运行中的任务 (task ls)
    列出当前正在运行的任务及其状态和宿主机 PID。

    [root@docker102 ~]# ctr task ls
    TASK       PID       STATUS
    xiuxian    629615    RUNNING
    
  6. 查看任务在宿主机的进程
    可以使用 ps 结合 ctr task ls 输出的 PID 来查看容器进程在宿主机上的情况。

    [root@docker102 ~]# ps -ef | grep 629615
    root      629615  629592  0 16:09 ?        00:00:00 nginx: master process nginx -g daemon off;
    systemd+  629660  629615  0 16:09 ?        00:00:00 nginx: worker process
    # ... (其他相关进程)
    
  7. 在运行的任务中执行命令 (task exec)
    类似于 docker exec,允许在运行的容器(任务)内部执行命令。

    • --exec-id:为每次执行指定一个唯一的 ID。
    • -t:分配一个 TTY,用于交互式会话。
    # 执行单个命令并获取输出
    [root@docker102 ~]# ctr task exec --exec-id 1 xiuxian ifconfig -a
    # lo        Link encap:Local Loopback ...
    
    # 启动一个交互式 shell
    [root@docker102 ~]# ctr task exec --exec-id 2 -t xiuxian sh
    / # ps -ef
    PID   USER     TIME  COMMAND
        1 root      0:00 nginx: master process nginx -g daemon off;
       23 nginx     0:00 nginx: worker process
       # ...
    / # exit
    
  8. 直接运行容器 (run)
    ctr runcontainers createtask start 的组合,一步到位地创建并启动容器。

    • --net-host:使容器共享宿主机的网络命名空间。
    • -d:后台运行。
    • 重要提示: ctr run 如果发现本地没有指定的镜像,它不会像 Docker 那样自动去远程仓库拉取,你需要先手动 ctr images pull
    # 确保镜像存在
    [root@docker102 ~]# ctr i ls | grep apps:v1
    # ... (确认镜像存在)
    
    # 运行一个新容器 xiuxian2,使用宿主机网络
    [root@docker102 ~]# ctr run -d --net-host registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1 xiuxian2
    # ... (启动日志)
    
    [root@docker102 ~]# ctr task ls
    TASK        PID       STATUS
    xiuxian     629615    RUNNING
    xiuxian2    630188    RUNNING
    
  9. 暂停任务 (tasks pause)
    暂停指定任务的所有进程。

    [root@docker102 ~]# ctr tasks pause xiuxian
    [root@docker102 ~]# ctr task ls
    TASK        PID       STATUS
    xiuxian     629615    PAUSED
    xiuxian2    630188    RUNNING
    # 暂停状态下无法执行 exec
    [root@docker102 ~]# ctr task exec --exec-id 3 -t xiuxian sh
    ctr: cannot exec in a paused state: unknown
    
  10. 恢复任务 (tasks resume)
    恢复被暂停的任务。

    [root@docker102 ~]# ctr tasks resume xiuxian
    [root@docker102 ~]# ctr task ls
    TASK        PID       STATUS
    xiuxian     629615    RUNNING
    xiuxian2    630188    RUNNING
    # 恢复后可以正常 exec
    [root@docker102 ~]# ctr task exec --exec-id 4 -t xiuxian sh
    / # hostname
    docker102 # (因为之前是 --net-host, 这里可能显示宿主机名, 否则是容器ID)
    / # exit
    
  11. 停止/杀死任务 (task kill)
    向任务的主进程发送信号以停止它。默认发送 SIGTERM,可以使用 --signal 指定其他信号 (如 SIGKILL)。

    [root@docker102 ~]# ctr task kill xiuxian
    [root@docker102 ~]# ctr task ls
    TASK        PID       STATUS
    xiuxian     629615    STOPPED
    xiuxian2    630188    RUNNING
    
  12. 删除任务 (task rm)
    移除已停止的任务。运行中的任务默认不能删除。

    # 删除已停止的 xiuxian 任务
    [root@docker102 ~]# ctr task rm xiuxian
    [root@docker102 ~]# ctr task ls
    TASK        PID       STATUS
    xiuxian2    630188    RUNNING
    
    # 尝试删除运行中的 xiuxian2 (会失败)
    [root@docker102 ~]# ctr task rm xiuxian2
    ERRO[0000] unable to delete xiuxian2 error="task must be stopped before deletion: running: failed precondition"
    ctr: task must be stopped before deletion: running: failed precondition
    
    # 使用 -f 强制删除运行中的任务 (先发送 SIGKILL 再删除)
    [root@docker102 ~]# ctr task rm -f xiuxian2
    WARN[0000] task xiuxian2 exit with non-zero exit code 137
    [root@docker102 ~]# ctr task ls
    TASK    PID    STATUS
    # 任务列表变空
    

    注意:删除任务后,容器的定义 (ctr containers ls) 可能仍然存在,需要单独删除。

  13. 删除容器 (containers rm)
    删除容器的定义。通常在关联的任务被删除后进行。

    # 先确保任务已删除 (task ls 为空)
    # 再删除容器定义
    [root@docker102 ~]# ctr containers ls
    CONTAINER    IMAGE                                                        RUNTIME
    xiuxian      registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1    io.containerd.runc.v2
    xiuxian2     registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1    io.containerd.runc.v2
    [root@docker102 ~]# ctr containers rm xiuxian
    [root@docker102 ~]# ctr containers rm xiuxian2
    [root@docker102 ~]# ctr containers ls
    CONTAINER    IMAGE    RUNTIME
    # 容器列表也变空
    

四、使用 ctr 管理命名空间 (Namespaces)

containerd 支持命名空间,用于隔离资源(如镜像、容器、快照)。这对于多租户场景或区分不同应用的环境非常有用。Kubernetes 就利用了命名空间(通常是 k8s.io)。默认命名空间是 default

  1. 查看现有命名空间 (namespaces lsns ls)

    [root@docker102 ~]# ctr ns ls
    NAME    LABELS
    default
    
  2. 创建命名空间 (ns create)

    [root@docker102 ~]# ctr ns create oldboyedu-linux92
    [root@docker102 ~]# ctr ns ls
    NAME              LABELS
    default
    oldboyedu-linux92
    
  3. 在指定命名空间中操作
    使用 -n <namespace>--namespace <namespace> 标志在特定命名空间下执行 ctr 命令。

    # 在 'oldboyedu-linux92' 命名空间下拉取镜像
    [root@docker102 ~]# ctr -n oldboyedu-linux92 image pull registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v2
    # ... (拉取过程)
    
    # 查看默认命名空间的镜像 (看不到 apps:v2)
    [root@docker102 ~]# ctr image ls
    REF                                                       TYPE                                                 DIGEST                                                                  SIZE    PLATFORMS   LABELS
    10.0.0.101/oldboyedu-games/xiuxian:v1                     application/vnd.docker.distribution.manifest.v2+json sha256:3bee216f250cfd2dbda1744d6849e27118845b8f4d55dda3ca3c6c1227cc2e5c 9.6 MiB linux/amd64 -
    registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1 application/vnd.docker.distribution.manifest.v2+json sha256:3bee216f250cfd2dbda1744d6849e27118845b8f4d55dda3ca3c6c1227cc2e5c 9.6 MiB linux/amd64 -
    
    # 查看 'oldboyedu-linux92' 命名空间的镜像
    [root@docker102 ~]# ctr -n oldboyedu-linux92 image ls
    REF                                                       TYPE                                                 DIGEST                                                                  SIZE    PLATFORMS   LABELS
    registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v2 application/vnd.docker.distribution.manifest.v2+json sha256:3ac38ee6161e11f2341eda32be95dcc6746f587880f923d2d24a54c3a525227e 9.6 MiB linux/amd64 -
    
  4. 删除命名空间 (ns rm)
    重要: 只能删除空的命名空间。删除前必须先移除该命名空间下的所有容器、任务、镜像等资源。

    # 尝试直接删除 (会失败,因为里面有镜像)
    [root@docker102 ~]# ctr ns rm oldboyedu-linux92
    ERRO[0000] unable to delete oldboyedu-linux92 error="namespace \"oldboyedu-linux92\" must be empty..."
    ctr: unable to delete oldboyedu-linux92: namespace "oldboyedu-linux92" must be empty...
    
    # 先删除命名空间内的镜像
    [root@docker102 ~]# ctr -n oldboyedu-linux92 image rm registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v2
    registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v2
    
    # 确认命名空间已空
    [root@docker102 ~]# ctr -n oldboyedu-linux92 image ls
    REF TYPE DIGEST SIZE PLATFORMS LABELS
    
    # 再次尝试删除命名空间 (成功)
    [root@docker102 ~]# ctr ns rm oldboyedu-linux92
    oldboyedu-linux92
    [root@docker102 ~]# ctr ns ls
    NAME    LABELS
    default
    

五、ctr 实现容器数据持久化 (Bind Mounts)

容器默认是无状态的,其文件系统在删除后会丢失。要持久化数据,需要使用卷挂载。ctr 支持多种挂载类型,这里演示最常用的 bind 类型(将宿主机目录挂载到容器内)。

  1. 准备宿主机目录和拉取镜像

    # 如果命名空间不存在,ctr 会在拉取时自动创建
    [root@docker102 ~]# ctr -n oldboyedu-linux92 image pull registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v2
    # ... (拉取镜像)
    
    # 创建用于挂载的宿主机目录
    [root@docker102 ~]# mkdir -pv /oldboyedu/games
    mkdir: created directory '/oldboyedu/games'
    
  2. 创建容器时指定挂载点 (--mount)
    使用 --mount 标志在 container createrun 时指定挂载。

    • type=bind:指定挂载类型为绑定挂载。
    • src=/path/on/host:宿主机上的源路径。
    • dst=/path/in/container:容器内的目标路径。
    • options=rbind:rw:挂载选项。rbind 允许递归挂载子目录,rw 表示读写权限。
    [root@docker102 ~]# ctr -n oldboyedu-linux92 container create --mount type=bind,src=/oldboyedu/games,dst=/usr/local/nginx/html,options=rbind:rw registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v2 xiuxian
    
  3. 启动容器

    [root@docker102 ~]# ctr -n oldboyedu-linux92 task start -d xiuxian
    # ... (启动日志)
    
  4. 验证挂载和数据写入

    # 在宿主机上放入一个文件到挂载目录
    [root@docker102 ~]# cp /etc/os-release /oldboyedu/games/
    
    # 进入容器查看挂载点,并写入新文件
    [root@docker102 ~]# ctr -n oldboyedu-linux92 task exec --exec-id $RANDOM -t xiuxian sh
    / # ls -l /usr/local/nginx/html  # 应该能看到 os-release 文件
    total 4
    -rw-r--r--    1 root     root           382 Jul 27 08:42 os-release
    / # echo haha > /usr/local/nginx/html/haha.log
    / # ls -l /usr/local/nginx/html  # 新文件 haha.log 也出现了
    total 8
    -rw-r--r--    1 root     root             5 Jul 27 08:45 haha.log
    -rw-r--r--    1 root     root           382 Jul 27 08:42 os-release
    / # exit
    
  5. 在宿主机上验证数据持久化
    容器内写入的文件 haha.log 现在也出现在宿主机的 /oldboyedu/games 目录下。

    [root@docker102 ~]# ll /oldboyedu/games/
    total 16
    drwxr-xr-x 2 root root 4096 Jul 27 16:45 ./
    drwxr-xr-x 5 root root 4096 Jul 27 16:40 ../
    -rw-r--r-- 1 root root    5 Jul 27 16:45 haha.log
    -rw-r--r-- 1 root root  382 Jul 27 16:42 os-release
    
  6. 删除容器,验证数据依然存在
    即使删除了容器和任务,宿主机目录 /oldboyedu/games 及其内容会保持不变。

    # 强制删除任务
    [root@docker102 ~]# ctr -n oldboyedu-linux92 tasks rm -f xiuxian
    WARN[0000] task xiuxian exit with non-zero exit code 137
    
    # 删除容器定义
    [root@docker102 ~]# ctr -n oldboyedu-linux92 container rm xiuxian
    
    # 检查宿主机目录,数据仍然存在
    [root@docker102 ~]# ll /oldboyedu/games/
    total 16
    # ... (文件列表不变)
    

六、ctr 与私有仓库 (Harbor) 交互

在生产环境中,我们通常使用私有镜像仓库,如 Harbor。ctr 也可以配置与这些仓库交互。

  1. 配置 containerd 以信任不安全的 Registry (HTTP)
    如果您的 Harbor 仓库使用 HTTP 而非 HTTPS,或者使用了自签名证书,需要配置 containerd。编辑 containerd 的配置文件(通常是 /etc/containerd/config.toml)。

    # vim /etc/containerd/config.toml
    
    # 在 [plugins."io.containerd.grpc.v1.cri".registry.mirrors] 下添加或修改
    # 注意:这里的层级是针对 CRI 插件的配置,如果只想为 ctr 配置,
    # 可以放在 [plugins."io.containerd.internal.v1.cri".registry.configs."<registry-host>".tls] 或类似位置,
    # 或者更通用的 [plugins."io.containerd.internal.v1.remote".registry]
    # 最简单的方式通常是在 mirrors 下配置 endpoint 为 http://...
    
    # [plugins."io.containerd.grpc.v1.cri".registry] # 这层可能已存在
      [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
        # 添加你的 Harbor 地址
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."10.0.0.101"]
          endpoint = ["http://10.0.0.101"] # 使用 http://
    

    重要:修改配置后,必须重启 containerd 服务才能生效。

    [root@docker102 ~]# systemctl restart containerd
    

    对于需要证书验证的 HTTPS 仓库,配置方式会有所不同,通常涉及在 [plugins."io.containerd.grpc.v1.cri".registry.configs] 下配置 TLS 信息。

  2. 推送镜像到 Harbor

    • 首先,确保你的镜像有一个指向 Harbor 仓库地址的标签。
    • 使用 ctr images push 命令推送。
    • --plain-http:如果仓库是 HTTP 协议,需要此标志。
    • -u <username>:<password>:提供登录凭据。
    # 确认已有指向 Harbor 的标签 (之前已打好)
    [root@docker102 ~]# ctr i ls | grep 10.0.0.101/oldboyedu-games/xiuxian:v1
    # 10.0.0.101/oldboyedu-games/xiuxian:v1 ...
    
    # 推送镜像
    [root@docker102 ~]# ctr images push --platform linux/amd64 --plain-http -u admin:Harbor12345 10.0.0.101/oldboyedu-games/xiuxian:v1
    # ... (推送进度)
    

    注意:在命令行直接提供密码 -u admin:Harbor12345 存在安全风险,会被记录在 history 中。生产环境中,建议使用 ctr login 或其他更安全的认证方式。但 ctr 本身的 login 功能相对基础。

  3. 从 Harbor 拉取镜像

    # 拉取另一个在 Harbor 上的镜像
    [root@docker102 ~]# ctr images pull --plain-http -u admin:Harbor12345 10.0.0.101/oldboyedu-games/doudizhu:v0.1
    # ... (拉取进度)
    
    # 查看本地镜像列表,确认已拉取成功
    [root@docker102 ~]# ctr i ls
    REF                                                       TYPE                                                 DIGEST                                                                  SIZE    PLATFORMS   LABELS
    10.0.0.101/oldboyedu-games/doudizhu:v0.1                  application/vnd.docker.distribution.manifest.v2+json sha256:adabbc8e7ea0bc5858223c414832e3fdd21bffb4a78ece88c6b67895b0eec9a0 9.7 MiB linux/amd64 -
    10.0.0.101/oldboyedu-games/xiuxian:v1                     application/vnd.docker.distribution.manifest.v2+json sha256:3bee216f250cfd2dbda1744d6849e27118845b8f4d55dda3ca3c6c1227cc2e5c 9.6 MiB linux/amd64 -
    registry.cn-hangzhou.aliyuncs.com/yinzhengjie-k8s/apps:v1 application/vnd.docker.distribution.manifest.v2+json sha256:3bee216f250cfd2dbda1744d6849e27118845b8f4d55dda3ca3c6c1227cc2e5c 9.6 MiB linux/amd64 -
    

总结

通过这篇文章,我们实践了 runc 的安装和验证,并详细探索了 ctr 命令行工具在镜像管理(拉取、推送、导入/导出、挂载、打标签)、容器生命周期管理(创建、启动、停止、暂停/恢复、删除、执行命令)、命名空间隔离以及数据持久化(绑定挂载)方面的使用方法。同时,我们也了解了如何配置 containerd 并使用 ctr 与私有 HTTP 仓库(如 Harbor)进行交互。

虽然 ctr 被定位为面向开发和调试的工具,不如 Docker CLI 或 Podman 那样用户友好,但它提供了一种直接、底层的方式来与 containerd 交互,这对于理解容器运行时的工作原理、排查 Kubernetes 集群问题或进行特定的底层操作非常有帮助。

希望这篇详细的实践指南能帮助大家更好地理解和使用 containerd 及其生态工具!如果你有任何问题或补充,欢迎在评论区交流。


posted on 2025-04-14 10:13  Leo-Yide  阅读(374)  评论(1)    收藏  举报