↓Skip to main content
  1. Docs/

Dragonfly(二):从文件下载到 containerd 镜像加速

·7 mins· ·
Owl Dawn
Author
Owl Dawn
Table of Contents

这篇要验证什么
#

建议按两个阶段操作:先用一个自己控制的 HTTP 文件验证 P2P,再配置 containerd 镜像加速。这样遇到问题时,可以区分是 Dragonfly 本身没有工作,还是 Registry、证书或运行时接入有问题。

架构和术语见 入门、组件与工作原理。本文命令面向 Linux / Bash,集群使用 Kubernetes;配置固定为 Chart 1.7.0、控制面 v2.5.0、客户端 v1.4.0。

一、准备测试环境
#

需要一个隔离测试集群、Helm 3 和 kubectl。为观察跨节点下载,至少准备两台能够运行 Client Pod 的工作节点,并检查:

  • 节点能够拉取示例镜像、访问测试源站和组件服务。
  • 节点之间允许 Peer 服务的通信,没有被防火墙或 NetworkPolicy 阻断。
  • 没有其他程序占用示例使用的主机端口。
  • 集群策略允许 Chart 中相应的 hostNetwork、hostPID 和主机访问配置。

示例使用每节点 Client、一个 Manager、一个 Scheduler、一个 Seed,以及测试用 MySQL、Redis。为降低实验环境的存储要求,数据库、Redis 和 Seed 不使用持久卷;数据可随 Pod 重建而丢失。 这些设置不适合直接复制到生产环境。

本文不需要先修改 containerd,也不需要先开启 dfinit。安装 Dragonfly 自身镜像的下载路径应当在没有 Dragonfly 的情况下可用,避免形成启动依赖循环。

二、检查并安装固定版本 Chart
#

下载本页附带的 lab-values.yaml 和 origin.yaml,放在工作目录。前者是实验配置,后者创建一个提供 64 MiB 测试文件的 HTTP 服务。

helm repo add dragonfly https://dragonflyoss.github.io/helm-charts/
helm repo update

# 查看版本和默认配置,不把其他版本的参数混进来。
helm show chart dragonfly/dragonfly --version 1.7.0
helm show values dragonfly/dragonfly --version 1.7.0 > defaults-1.7.0.yaml

# 先生成清单,检查将要部署的资源、镜像、权限和挂载。
helm template dragonfly dragonfly/dragonfly \
  --version 1.7.0 --namespace dragonfly-system \
  -f lab-values.yaml > rendered.yaml

helm upgrade --install dragonfly dragonfly/dragonfly \
  --version 1.7.0 --namespace dragonfly-system --create-namespace \
  -f lab-values.yaml --wait --timeout 10m

实验配置明确启用 Manager、MySQL 和 Redis,关闭 dfinit,避免安装阶段自动改动所有节点的运行时配置。当前其他版本 Chart 的默认部署形态可能不同,不应省略版本号后假定行为相同。

Chart 还依赖数据库等辅助镜像;固定 Chart 不表示这些镜像在任何网络中都能拉取。离线或受限网络需要预先同步依赖镜像,并核对架构和仓库可达性。

kubectl -n dragonfly-system get pods -o wide
kubectl -n dragonfly-system rollout status deployment/dragonfly-manager
kubectl -n dragonfly-system rollout status statefulset/dragonfly-scheduler
kubectl -n dragonfly-system rollout status statefulset/dragonfly-seed-client
kubectl -n dragonfly-system rollout status daemonset/dragonfly-client

这些名称对应本文固定的 release 和 Chart。修改 release 名或命名配置后,应先通过 kubectl get deployment,statefulset,daemonset 查找实际名称。

Pod Ready 只是第一步,还要验证实际请求路径。若部署失败,先看 kubectl describe pod <pod-name> 的事件,以及相关容器日志;不要先反复删除全部组件。

三、创建一个可控的文件源站
#

kubectl apply -f origin.yaml
kubectl -n dragonfly-system rollout status deployment/dragonfly-lab-origin

源站启动时生成 test.bin,内容为 64 MiB 零字节,再由 nginx 提供 HTTP 下载。它用于验证分发路径,不代表真实模型或镜像的压缩与存储特性。

取出源站的 ClusterIP,并组成相同的文件 URL:

origin_ip=$(kubectl -n dragonfly-system get svc dragonfly-lab-origin \
  -o jsonpath='{.spec.clusterIP}')
url="http://${origin_ip}/test.bin"
printf '%s\n' "$url"

这里用集群内地址避免公开实验服务;访问者必须位于能够到达该 ClusterIP 的网络中。

四、在两个节点上请求同一文件
#

先查看 Client Pod 与节点的对应关系:

kubectl -n dragonfly-system get pods \
  -l 'app=dragonfly,release=dragonfly,component=client' -o wide

选择两台不同节点上的 Client Pod,将实际名称写入下面变量。本文使用固定 Chart 中的 client 容器:

p1='替换为第一台节点上的-client-Pod-名称'
p2='替换为第二台节点上的-client-Pod-名称'

kubectl -n dragonfly-system exec "$p1" -c client -- \
  dfget "$url" -O /tmp/test-a.bin

kubectl -n dragonfly-system exec "$p2" -c client -- \
  dfget "$url" -O /tmp/test-b.bin

这两次下载使用相同 URL,分别进入两个节点的 dfdaemon。命令从 Client 容器内发起,目的是先验证下载链路,不要求另外安装 dfget 或向业务 Pod 挂载 socket。

再次运行前换一个输出文件名,或按 dfget --help 选择覆盖方式;不要把“输出文件已存在”误认为缓存故障。

检查结果是否正确
#

kubectl -n dragonfly-system exec "$p1" -c client -- sha256sum /tmp/test-a.bin
kubectl -n dragonfly-system exec "$p2" -c client -- sha256sum /tmp/test-b.bin
kubectl -n dragonfly-system exec deployment/dragonfly-lab-origin -- \
  sha256sum /usr/share/nginx/html/test.bin

三个结果应相同。如果所用镜像没有 sha256sum,应把结果导出后在本地校验,不能跳过完整性检查。

怎样证明第二次用了 P2P
#

“第二次更快”还不够,可能只是磁盘或操作系统缓存起作用。需要结合证据判断:

# 对照时间查看两个 Client 的下载日志。
kubectl -n dragonfly-system logs "$p1" -c client --since=10m
kubectl -n dragonfly-system logs "$p2" -c client --since=10m

# 观察源站请求;Range 下载可能对应多条访问记录。
kubectl -n dragonfly-system logs deployment/dragonfly-lab-origin --since=10m

在日志或指标中确认数据来自父节点,比较源站实际发送字节数,以及 Peer 上传/下载字节数。第二次可能由 Seed 或第一个 Peer 提供,不保证一定由指定的 p1 提供。

如果已经命中旧缓存、修改了 URL、两次请求进入不同 P2P 集群,或者源站被其他任务访问,结果就不能直接比较。也不要只按源站请求条数推算流量:分片、Range 和元数据检查都可能产生请求。

五、再接入 containerd
#

先确认要接的是哪一条路径
#

目标路径是:

containerd 从本机 dfdaemon 获取镜像数据,随后完成校验解压和容器启动

本文先演示手工接入一台测试节点、一个仓库,方便看清改动,再考虑用 dfinit 自动推广。以下片段针对 containerd 1.7 的 v2 配置;containerd 2.x 的插件表等可能不同,应查看实际配置,不能直接复制旧表名。

本机代理地址的前提是节点网络中的 127.0.0.1:4001 能访问 dfdaemon。本文 Chart 的 Client 使用 hostNetwork;普通业务 Pod 的 localhost 并不自动指向主机。

配置 CRI 的 Registry 目录
#

在测试节点上备份原配置,然后在现有配置中设置对应字段,不要用这几行覆盖整个 config.toml:

# /etc/containerd/config.toml 中的相关片段
version = 2

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

新增或改变 config_path 等主配置通常需要按运行时要求重启 containerd,应放在测试节点或维护窗口执行。若该目录已经生效,只修改 hosts.toml 通常不需要重启守护进程。不要把所有变更一概处理为“无需重启”或“一定重启”。

只让 Docker Hub 经过本机代理
#

创建或合并 /etc/containerd/certs.d/docker.io/hosts.toml:

server = "https://index.docker.io"

[host."http://127.0.0.1:4001"]
  capabilities = ["pull", "resolve"]

  [host."http://127.0.0.1:4001".header]
    X-Dragonfly-Registry = ["https://index.docker.io"]

X-Dragonfly-Registry 告诉 Dragonfly 应使用哪个上游仓库。否则即使请求进入代理,也可能发往错误的源站。这里不需要关闭上游 HTTPS 证书校验。

多个 Registry 应分别配置各自的 namespace 与上游;私有仓库还需要核对认证、CA、重定向和代理规则。先验证一个仓库,再逐步扩大范围,不要一开始把所有未知仓库都强制接入。

使用正确的工具验证
#

在这台节点上使用指向其实际 CRI socket 的 crictl 测试,例如:

crictl pull docker.io/library/nginx:1.28-alpine

ctr images pull 不一定使用 CRI 的 Registry 配置。如果用 ctr 排查,应明确指定相应的 hosts 目录,例如 ctr images pull --hosts-dir /etc/containerd/certs.d ...,并注意它与 CRI 的凭据来源仍可能不同。

镜像层已经存在于 containerd 内容存储时,可能根本不会下载,所以成功和耗时都不能单独证明 Dragonfly 生效。应在另一台未缓存该镜像的测试节点验证,或使用独立实验环境;不要为了测试而清空生产节点的镜像存储。

最终还应在已配置节点上运行真实 Pod,检查拉镜像事件、Dragonfly 日志和流量。运行时的代理配置、Dragonfly 的 P2P 规则、镜像本地缓存是三个不同环节。

六、什么时候使用 dfinit
#

手工验证完成后,可以按固定 Chart 的 client.dfinit 配置自动接入。它可能修改主机运行时配置,并按版本策略重启运行时,因此先在少量测试节点上验证和备份。

本文实验默认关闭 dfinit。自动接入时,要明确设置仓库范围、上游地址、CA 和实际 containerd 路径,不要只把 enable 改为 true 就直接推广。

七、预热怎样使用
#

有 Manager 的部署可以通过 Console 或 Open API 提交文件或镜像预热任务。基本过程是:选择目标集群、指定内容和所需凭据、提交任务、等待任务完成,再从业务节点验证实际下载。

预热成功只说明本次准备任务完成,不表示缓存永久保留,也不表示预热入口和业务入口一定生成相同的任务标识。应核对 URL/digest、参数、目标集群和后续回收情况。

Open API 的请求结构与认证方式应以对应版本为准,不能把管理 API 的 Token 与 Registry 拉取凭据混用。

八、结束实验与回退
#

如果只做了文件实验,没有改运行时:

kubectl delete -f origin.yaml
helm uninstall dragonfly -n dragonfly-system

如果改过 containerd,先恢复原运行时配置并验证直接拉取,再卸载 Dragonfly,否则节点可能继续访问一个已经不存在的本地代理。Helm 卸载也不保证恢复 dfinit 对主机做过的所有修改,或删除所有 PVC、hostPath 数据。

上线前继续阅读 注意事项与排障。

参考与验证范围
#

本文附件已进行 Helm 模板渲染与静态检查,未在真实 Kubernetes 集群中执行安装和下载。镜像可达性、节点权限、网络规则和实际性能需要在目标环境验证。

Related

Dragonfly(一):入门、组件与工作原理
·8 mins
Dragonfly(三):注意事项、性能验证与故障排查
·7 mins