一文学会Containerd配置和镜像加速

一文学会Containerd配置和镜像加速

❤️ 摘要: 本文介绍了 Containerd 的基本概念及其在 Kubernetes 中的作用,并详细说明了如何通过配置代理、使用国内镜像源或手动下载等方式加速镜像拉取。此外,还提供了针对不同场景的具体配置方法,包括通过环境变量、config.toml 文件和 hosts.toml 文件实现镜像加速的具体步骤。这些方法有助于提高容器镜像的拉取效率。通过这些详细的步骤和示例,读者可以更好地理解和掌握Containerd的使用方法。

目录

1 概念

在这里插入图片描述

1.1 什么是Containerd

前文《一文掌握Containerd配置Harbor私有仓库》已经简单介绍过Containerd以及其配置说明。

Kubernetes 1.20 版本开始,Containerd 被设置为默认的容器运行时接口(CRI)。Kubernetes 官方在此版本中逐步淘汰了 Docker 作为默认 CRI,转而推荐使用 Containerd 来处理容器管理任务。所以如果您正在使用Kubernetes,那么了解并掌握Containerd是必要的。

1.1.1 Containerd如何为Kubernetes服务?

Containerd 通常与Kubelet运行在同一节点上,而Containerd内置了一个cri插件,通过cri插件处理来自 Kubelet 的所有 CRI 服务请求,并使用 containerd 来管理完整的容器生命周期和容器镜像。

下图是Kubelet与Containerd的关系图:

在这里插入图片描述

1.1.2 创建单容器 pod 的工作原理

❔ 说明: 以创建单容器pod的例子解释kublet、Containerd的工作原理

  1. Kubelet 通过 CRI 运行时服务 API 调用cri插件来创建 pod;
  2. cri使用 CNI 创建并配置 pod 的网络命名空间;
  3. cri使用containerd内部创建并启动一个特殊的暂停容器(Pause)(沙箱容器),并将该容器放入pod的cgroup和命名空间中(为简洁起见,省略了步骤);
  4. 随后Kubelet 通过 CRI 镜像服务 API 调用cri插件来拉取应用程序容器镜像;
  5. 如果节点上不存在镜像, cri会进一步使用 containerd 来拉取镜像;
  6. 然后,Kubelet 通过 CRI 运行时服务 API 调用cri ,使用拉取的容器镜像在 pod 内创建并启动应用程序容器;
  7. 最终cri插件使用containerd内部创建应用程序容器,将其放入pod的cgroup和命名空间中,然后启动pod的应用程序容器。经过这些步骤,一个 pod 及其对应的应用程序容器就被创建并运行了。
Kubelet CRI Plugin Containerd Pod CNI ①调用 CRI 运行时服务 API 创建 Pod ②使用 CNI 创建并配置网络命名空间 ③创建并启动 Pause 容器 ④将 Pause 容器放入 Pod 的 cgroup 和命名空间 ⑤调用 CRI 镜像服务 API 拉取应用程序镜像 ⑥检查镜像是否存在 ⑦镜像不存在,拉取镜像 ⑧镜像拉取完成 ⑨调用 CRI 运行时服务 API 创建并启动应用程序容器 ⑩使用镜像创建应用程序容器 ⑪将应用程序容器放入 Pod 的 cgroup 和命名空间 ⑫启动应用程序容器 Pod 及应用程序容器运行 Kubelet CRI Plugin Containerd Pod CNI

1.2 Containerd的镜像加速方式

❔ 说明:国内用户在拉取镜像时,往往会遇到过镜像拉取超时或者速度极慢的问题,那是因为 dockerContainerd 默认都是指向国外的镜像源(没有科学上网无法直接访问), 如docker.io, gcr.io,ghcr.io,k8s.gcr.io,quay.io。

目前实现镜像加速的方式有三种。

  1. 镜像代理或镜像同步
  2. 使用国内的镜像源
  3. 手动下载并上传到私有镜像仓库

在这里插入图片描述


1.2.1 镜像代理或镜像同步

  • 镜像代理:通过代理服务器加速镜像拉取,代理会将请求转发到目标镜像仓库,并在本地缓存镜像。常见的方案有 Docker 官方提供的镜像加速器或配置私有代理。
  • 镜像同步:使用代理服务器下载外部公共镜像再同步到本地镜像仓库,减少跨国下载的延迟,并确保镜像的稳定性和安全性。

1.2.2 使用国内的镜像源

使用国内的镜像源,如阿里云、网易云、华为云等提供的公共镜像加速服务,这些服务在国内多个地区都部署镜像官方仓库,大大减少网络传输延迟。

1.2.3 手动下载并上传到私有镜像仓库

手动从公共镜像仓库打包下载镜像,然后上传到本地或私有镜像仓库,确保本地有需要的镜像。

1.2.4 三种方式对比

方式优点缺点适用场景
镜像代理或镜像同步速度提升:通过代理或同步,镜像从本地网络获取,避免跨国网络带来的延迟问题。
高可用性:同步镜像可以确保即使外部仓库不可用,本地镜像仍可使用,增强容错性。
自动化:镜像同步可通过自动任务(如 Harbor 的同步功能)定期更新,无需人工干预。
复杂度:设置代理或镜像同步可能需要额外的网络配置或额外的基础设施(如网络代理,私有镜像仓库)。
开销成本:部署代理服务需要额外的带宽费用,本地存储的镜像占用较多的磁盘空间。
○ 大规模集群或企业内部环境,希望加速镜像拉取并提高可用性。
○ 需要对镜像进行统一管理、保证安全性。
使用国内的镜像源简单快捷:直接通过配置国内镜像源即可加速,无需复杂的网络设置。
成本低:大多数国内镜像源是免费的。
镜像同步及时:国内镜像源通常会快速同步官方仓库的镜像,更新速度较快。
依赖第三方服务:依赖国内的镜像源,无法保证服务的稳定性和长期可用性。
受限于公共镜像源的内容:如果某些镜像源未同步特定镜像,可能需要额外的处理步骤。
○ 小规模或个人用户,需要快速加速镜像拉取且不愿意搭建自有基础设施。
○ 对镜像源的稳定性和可用性要求较低的场景。
手动下载并上传到私有镜像仓库完全自主:不依赖外部服务,镜像管理自主可控。
安全性:镜像经过本地或私有仓库管理,确保镜像来源安全可控,适合企业的安全策略要求。
手动维护:需要手动下载和上传镜像,耗时耗力,尤其在更新频繁时难以管理。
复杂性高:需要私有镜像仓库和相关基础设施的支持,增加运维复杂度。
存储成本:所有镜像都需要存储在私有仓库中,带来较大的存储和管理负担。
○ 需要严格管理镜像安全和来源的企业环境。
○ 需要确保离线环境中使用的镜像始终可用的场景。
○ 容器需求较小的场景,如学习或测试。

2 Containerd配置镜像加速

❔ 说明:本环境是Containerd版本: v1.6.4(systemd部署); Kubernetes版本:V1.29.7(二进制部署)

2.1 未设置镜像加速

[root@k8s-master1 containerd.service.d]# time crictl pull gcr.io/google-containers/busybox:latest
E0911 19:34:59.050185   19189 remote_image.go:238] "PullImage from image service failed" err="rpc error: code = Unknown desc = failed to pull and unpack image \"gcr.io/google-containers/busybox:latest\": failed to resolve reference \"gcr.io/google-containers/busybox:latest\": failed to do request: Head \"https://gcr.io/v2/google-containers/busybox/manifests/latest\": dial tcp 108.177.97.82:443: i/o timeout" image="gcr.io/google-containers/busybox:latest"
FATA[0030] pulling image: rpc error: code = Unknown desc = failed to pull and unpack image "gcr.io/google-containers/busybox:latest": failed to resolve reference "gcr.io/google-containers/busybox:latest": failed to do request: Head "https://gcr.io/v2/google-containers/busybox/manifests/latest": dial tcp 108.177.97.82:443: i/o timeout

  • 这里拉取gcr.io的镜像肯定会超时。

2.2 Containerd代理实现镜像加速

关于Linux系统代理,可以通过两种方法实现。

方法一: 如果你希望系统中所有应用都使用代理,可以直接在系统的环境变量中配置实现全局代理。(自行百度,这里不展开说明。)

方法二: 针对Containerd服务配置代理,进而实现镜像加速。

2.2.1 配置 Containerd 的环境变量

❔说明: 你需要提前部署代理服务器,并在Containerd服务器配置代理服务。(代理部署方法自行百度,这里不展开说明。)

查看Containerd的服务文件位置

[root@k8s-master1 ~]# systemctl cat containerd
# /usr/local/lib/systemd/system/containerd.service

编辑 /etc/systemd/system/containerd.service.d/http-proxy.conf 文件(如果文件不存在,则创建它):

# 添加containerd.service链接
cd /etc/systemd/system/
ln -s /usr/local/lib/systemd/system/containerd.service  containerd.service 
# 创建containerd.service的代理配置
mkdir -p /etc/systemd/system/containerd.service.d
vim /etc/systemd/system/containerd.service.d/http-proxy.conf

添加以下内容(根据你的代理信息进行修改):

[Service]
Environment="HTTP_PROXY=http://your-proxy-server:port"
Environment="HTTPS_PROXY=http://your-proxy-server:port"
Environment="NO_PROXY=localhost,127.0.0.1,::1,192.168.0.0/16,10.0.0.0/8,172.16.0.0/12,,.svc,.cluster.local"

❔ 参数说明:

  • HTTP_PROXY:设置 HTTP 请求的代理。
  • HTTPS_PROXY:设置 HTTPS 请求的代理。
  • NO_PROXY:设置不走代理的网段

⚠️ 在生产环境谨慎配置系统代理,否则可能会导致网络不通影响正常业务,建议 NO_PROXY 配置包括但不限以下网段:

  1. 本地地址和网段:localhost127.0.0.1127.0.0.0/8
  2. Kubernetes 的默认域名后缀:.svc.cluster.local
  3. Kubernetes Node 的网段甚至所有应该不用 proxy 访问的 node 网段:<nodeCIDR>
  4. APIServer 的内部 URL: <APIServerInternalURL>
  5. Service Network: <serviceNetworkCIDRs>
  6. (如有)etcd 的 Discovery Domain: <etcdDiscoveryDomain>
  7. Cluster Network: <clusterNetworkCIDRs>
  8. 其他特定平台相关网段(如 DevOps, Git/制品仓库): <platformSpecific>
  9. 常用内网网段:
    1. 10.0.0.0/8
    2. 172.16.0.0/12
    3. 192.168.0.0/16

将代理配置为 Containerd 的服务环境变量后,重新加载并重启 Containerd 服务:

systemctl daemon-reload
systemctl restart containerd

2.2.2 测试拉取镜像

尝试拉取镜像

[root@k8s-master1 system]# time crictl pull gcr.io/google-containers/busybox:latest
Image is up to date for sha256:36a4dca0fe6fb2a5133dc11a6c8907a97aea122613fa3e98be033959a0821a1f

real    0m2.694s
user    0m0.011s
sys     0m0.007s


  • 发现拉取成功, 而且速度还不错。

2.3 Containerd的config.toml实现镜像加速

如果没有/etc/containerd/config.toml,执行以下命令生成默认配置

sudo containerd config default | sudo tee /etc/containerd/config.toml

编辑Containerd的配置文件,添加以下镜像配置

   # 找到mirrors配置处
      [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
            endpoint = ["https://docker.io","https://6qxc6b6n.mirror.aliyuncs.com","https://docker.m.daocloud.io","https://dockerproxy.com/"]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"]
            endpoint = ["https://gcr.m.daocloud.io","https://gcr.nju.edu.cn","https://gcr.dockerproxy.com"]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."k8s.gcr.io"]
            endpoint = ["https://k8s-gcr.m.daocloud.io","https://gcr.nju.edu.cn/google-containers/","https://k8s.dockerproxy.com/"]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"]
            endpoint = ["https://quay.m.daocloud.io","https://quay.nju.edu.cn"]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]
            endpoint = ["https://k8s.m.daocloud.io","https://k8s.nju.edu.cn"]
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.elastic.co"]
            endpoint = ["https://elastic.m.daocloud.io"]  
        [plugins."io.containerd.grpc.v1.cri".registry.mirrors."ghcr.io"]
            endpoint = ["https://ghcr.m.daocloud.io","https://ghcr.nju.edu.cn"] 

重启Containerd服务

systemctl restart containerd

尝试在节点上通过Containerd直接拉取镜像,验证是否成功:

[root@k8s-master1 containerd.service.d]# time crictl pull gcr.io/google-containers/busybox:latest
Image is up to date for sha256:36a4dca0fe6fb2a5133dc11a6c8907a97aea122613fa3e98be033959a0821a1f

real    0m5.123s
user    0m0.013s
sys     0m0.058s

  • 成功拉取镜像,速度也可以。

2.4 Containerd的hosts.toml实现镜像加速

❔ 说明:Containerd v1.5 版本以后新增了新的镜像仓库配置方式—主机配置(hosts.toml),同时支持ctr(containerd 工具)、containerd 镜像服务客户端和 CRI 客户端(例如kubectlcrictl )等客户端。

2.4.1 主机配置方式对比config.toml配置方式的区别

  • config.tomlContainerd 的核心配置文件,定义了 Containerd 的全局行为和设置。
  • hosts.toml是从config.toml全局配置中分离出来,专用于配置 Containerd 的镜像仓库相关信息。这个文件可以定义多个镜像仓库以及如何访问这些仓库,可以实现更细粒度管理。
  • hosts.toml最大于config.toml的优势是配置不需要重启即可生效,避免了修改配置出错导致Containerd无法起来和减小修改全局配置的风险。

2.4.2 通过主机配置方式配置

为Containerd配置注册表将通过在配置目录中为每个所需的注册表主机指定(可选) hosts.toml文件来完成。注意:此目录下的更新不需要重新启动containerd守护进程。

配置全局配置文件/etc/containerd/config.toml,指定主机配置主目录,配置如下:

version = 2

[plugins."io.containerd.grpc.v1.cri".registry]
   config_path = "/etc/containerd/certs.d"

⚠️ 注意:同时将之前config.toml关于容器仓库的配置都要注释掉, 否则会冲突。

    [plugins."io.containerd.grpc.v1.cri".registry]
      config_path = "/etc/containerd/certs.d"
      
      [plugins."io.containerd.grpc.v1.cri".registry.auths]

      [plugins."io.containerd.grpc.v1.cri".registry.configs]
      #  [plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.zx".auth]
      #    username = "admin"
      #    password = "admin12345"
      #
      #  [plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.zx".tls]
      #    insecure_skip_verify = false
      #    ca_file = "/etc/containerd/certs.d/harbor.zx/ca.crt"
      #    cert_file = "/etc/containerd/certs.d/harbor.zx/client.cert"
      #    key_file = "/etc/containerd/certs.d/harbor.zx/client.key"

      [plugins."io.containerd.grpc.v1.cri".registry.headers]

      [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
        #[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
        #    endpoint = ["https://6qxc6b6n.mirror.aliyuncs.com","https://docker.m.daocloud.io","https://dockerproxy.com/"]
        #[plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"]
        #    endpoint = ["https://gcr.m.daocloud.io","https://gcr.nju.edu.cn","https://gcr.dockerproxy.com"]
        #[plugins."io.containerd.grpc.v1.cri".registry.mirrors."k8s.gcr.io"]
        #    endpoint = ["https://k8s-gcr.m.daocloud.io","https://gcr.nju.edu.cn/google-containers/","https://k8s.dockerproxy.com/"]
        #[plugins."io.containerd.grpc.v1.cri".registry.mirrors."quay.io"]
        #    endpoint = ["https://quay.m.daocloud.io","https://quay.nju.edu.cn"]
        #[plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]
        #    endpoint = ["https://k8s.m.daocloud.io","https://k8s.nju.edu.cn"]
        #[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.elastic.co"]
        #    endpoint = ["https://elastic.m.daocloud.io"]
        #[plugins."io.containerd.grpc.v1.cri".registry.mirrors."ghcr.io"]
        #    endpoint = ["https://ghcr.m.daocloud.io","https://ghcr.nju.edu.cn"]
        #[plugins."io.containerd.grpc.v1.cri".registry.mirrors."harbor.zx"]
        #    endpoint = ["https://harbor.zx"]

重启Containerd服务

systemctl restart containerd

docker.io 的示例,其主机目录结构以下:

# 创建命名空间
mkdir -p /etc/containerd/certs.d/docker.io

# 创建主机配置
touch /etc/containerd/certs.d/docker.io/hosts.toml

# 目录结构
$ tree /etc/containerd/certs.d
/etc/containerd/certs.d
└── docker.io                 #  命名空间名称与镜像仓库域名一致
    └── hosts.toml         #  该镜像仓库的配置文件
 

❔ 目录结构说明:

  • 主机配置主目录为/etc/containerd/certs.d
  • 官方文档提出了三个概念: 注册表主机(registry host)、注册表镜像(registry mirror)、注册表主机命名空间(registry host namespace )
    • 注册表主机, 例如,docker.io、quay.io和 ghcr.io, 即容器镜像的仓库,一般以http/https协议提供对对服务;
    • 注册表镜像是registry host 的缓存或加速代理,类似于CDN加速;
    • 注册表主机命名空间即是主机配置主目录下的子目录,如docker.io, 格式可以是[registry_host_name|IP address][:port]

2.4.3 为所有注册表设置默认镜像

如果没有其他命名空间匹配,则可以选择将_default注册表主机命名空间用作后备。

$ tree /etc/containerd/certs.d
/etc/containerd/certs.d
└── _default
    └── hosts.toml

$ cat /etc/containerd/certs.d/_default/hosts.toml
[host."https://registry.example.com"]
  capabilities = ["pull", "resolve"]

2.4.4 hosts.toml 内容详细说明

对于容器仓库config_path中的每个容器仓库命名空间目录,您可以包含一个hosts.toml配置文件。以下根级别 toml 字段适用于容器仓库命名空间:

⚠️ 注意hosts.toml文件中指定的所有路径可以是绝对路径,也可以是相对于hosts.toml文件的相对路径。

2.4.4.1 公共仓库案例

下面以docker.io作为配置案例:

编写hosts.toml

server = "https://docker.io"

[host."https://docker.m.daocloud.io"]
  capabilities = ["pull", "resolve"]
[host."https://dockerproxy.com/"]
  capabilities = ["pull", "resolve"]

❔ 参数说明:

字段说明可能值
server指定此注册表主机命名空间的默认服务器1) 如果仅配置server,没有配置host,则访问server地址;
2)如果配置一个或多个主机,则按顺序尝试访问所有host ,则server将用作后备;
3)如果没有server和host,则以命名空间来访问
host指定此注册表主机终端节点,可以有一个或多个主机。可以是域名或者是IP地址,类似于CNAME;
capabilities是一个可选设置,用于指定主机能够执行哪些操作。1)push是指向镜像仓库推送镜像;
2)pull是向镜像仓库拉取镜像;
3)resolve是将镜像(image:tag)翻译成唯一标识的 digest(哈希值)

测试拉取镜像

[root@k8s-master1 certs.d]# crictl pull docker.io/library/busybox
Image is up to date for sha256:87ff76f62d367950186bde563642e39208c0e2b4afc833b4b3b01b8fef60ae9e

2.4.4.2 私有仓库案例

以harbor私有仓库为例:

创建主机配置目录

mkdir -p /etc/containerd/certs.d/harbor.zx/

编辑hosts.toml文件

server = "https://harbor.zx"

[host."https://harbor.zx"]
  capabilities = ["pull", "resolve", "push"]
  skip_verify = true
  #
  ca = "/etc/containerd/certs.d/harbor.zx/ca.crt"
  #双向认证配置客户端证书
  #client = ["/etc/certs/client.cert", "/etc/certs/client.key"]

❔参数说明:

  • skip_verify:是否跳过对注册表的证书链和主机名的验证。这只能用于测试或与其他验证连接的方法结合使用。 (默认为false
  • ca:ca (证书颁发机构认证)可以设置为一个路径或一组路径,每个路径都指向一个 ca 文件,用于通过注册表命名空间进行身份验证。
  • client: client证书配置, 如果是双向认证需要配置客户端证书。

3 参考资料

[1] Containerd 如何配置 Proxy

[2]主流可用Docker镜像加速站列表汇总

[3]docker proxy官方文档

[4]Registry Configuration - Introduction

[5] Configure Image Registry

  • 16
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

StevenZeng学堂

🎉 每笔打赏都是我分享的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值