前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Dragonfly 和 Nydus Mirror 模式集成实践

Dragonfly 和 Nydus Mirror 模式集成实践

作者头像
CNCF
发布2022-11-28 17:33:00
8860
发布2022-11-28 17:33:00
举报
文章被收录于专栏:CNCFCNCF

作者:Gaius,Dragonfly Maintainer

简介

自 17 年开源以来,Dragonfly[1] 被许多大规模互联网公司选用并投入生产使用, 并在 18 年 10 月正式进入 CNCF,成为中国第三个进入 CNCF 沙箱级别的项目。 2020 年 4 月,CNCF 技术监督委员会(TOC)投票决定接受 Dragonfly 作为孵化级别的托管项目。 Dragonfly 多年生产实践经验打磨的下一代产品,它汲取了上一代 Dragonfly1.x 的优点并针对已知问题做了大量的优化。

Nydus[2] 作为 Dragonfly 的子项目优化了 OCIv1 镜像格式,并以此设计了一个镜像文件系统, 使容器可以按需下载镜像,不再需要下载完整镜像即可启动容器。 在最新版本中 Dragonfly 完成了和子项目 Nydus 的集成,让容器启动即可以按需下载镜像,减少下载量。 也可以在传输过程中利用 Dragonfly P2P 的传输方式,降低回源流量并且提升下载速度。

实践

依赖

所需软件

版本要求

文档

Kubernetes cluster

1.20+

kubernetes.io[3]

Helm

3.8.0+

helm.sh[4]

Containerd

v1.4.3+

containerd.io[5]

Nerdctl

0.22+

containerd/nerdctl[6]

注意: 如果没有可用的 Kubernetes 集群进行测试,推荐使用 Kind[7]

安装 Dragonfly

基于 Kubernetes cluster 详细安装文档可以参考 quick-start-kubernetes[8]

使用 Kind 安装 Kubernetes 集群

创建 Kind 多节点集群配置文件 kind-config.yaml, 配置如下:

代码语言:javascript
复制
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
  - role: control-plane
  - role: worker
    extraPortMappings:
      - containerPort: 30950
        hostPort: 65001
      - containerPort: 30951
        hostPort: 40901
  - role: worker

使用配置文件创建 Kind 集群:

代码语言:javascript
复制
kind create cluster --config kind-config.yaml

切换 Kubectl 的 context 到 Kind 集群:

代码语言:javascript
复制
kubectl config use-context kind-kind
Kind 加载 Dragonfly 镜像

下载 Dragonfly latest 镜像:

代码语言:javascript
复制
docker pull dragonflyoss/scheduler:latest
docker pull dragonflyoss/manager:latest
docker pull dragonflyoss/dfdaemon:latest

Kind 集群加载 Dragonfly latest 镜像:

代码语言:javascript
复制
kind load docker-image dragonflyoss/scheduler:latest
kind load docker-image dragonflyoss/manager:latest
kind load docker-image dragonflyoss/dfdaemon:latest
基于 Helm Charts 创建 Dragonfly P2P 集群

创建 Helm Charts 配置文件 charts-config.yaml 并且开启 Peer 的预取功能, 配置如下:

代码语言:javascript
复制
scheduler:
  replicas: 1
  metrics:
    enable: true
  config:
    verbose: true
    pprofPort: 18066

seedPeer:
  replicas: 1
  metrics:
    enable: true
  config:
    verbose: true
    pprofPort: 18066
    download:
      prefetch: true

dfdaemon:
  hostNetwork: true
  config:
    verbose: true
    pprofPort: 18066
    metrics: :8000
    download:
      prefetch: true
    proxy:
      defaultFilter: 'Expires&Signature&ns'
      security:
        insecure: true
      tcpListen:
        listen: 0.0.0.0
        port: 65001
      registryMirror:
        dynamic: true
        url: https://index.docker.io
      proxies:
        - regx: blobs/sha256.*

manager:
  replicas: 1
  metrics:
    enable: true
  config:
    verbose: true
    pprofPort: 18066

使用配置文件部署 Dragonfly Helm Charts:

代码语言:javascript
复制
$ helm repo add dragonfly https://dragonflyoss.github.io/helm-charts/
$ helm install --wait --create-namespace --namespace dragonfly-system dragonfly dragonfly/dragonfly -f charts-config.yaml
NAME: dragonfly
LAST DEPLOYED: Wed Oct 19 04:23:22 2022
NAMESPACE: dragonfly-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
1. Get the scheduler address by running these commands:
  export SCHEDULER_POD_NAME=$(kubectl get pods --namespace dragonfly-system -l "app=dragonfly,release=dragonfly,component=scheduler" -o jsonpath={.items[0].metadata.name})
  export SCHEDULER_CONTAINER_PORT=$(kubectl get pod --namespace dragonfly-system $SCHEDULER_POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
  kubectl --namespace dragonfly-system port-forward $SCHEDULER_POD_NAME 8002:$SCHEDULER_CONTAINER_PORT
  echo "Visit http://127.0.0.1:8002 to use your scheduler"

2. Get the dfdaemon port by running these commands:
  export DFDAEMON_POD_NAME=$(kubectl get pods --namespace dragonfly-system -l "app=dragonfly,release=dragonfly,component=dfdaemon" -o jsonpath={.items[0].metadata.name})
  export DFDAEMON_CONTAINER_PORT=$(kubectl get pod --namespace dragonfly-system $DFDAEMON_POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
  You can use $DFDAEMON_CONTAINER_PORT as a proxy port in Node.

3. Configure runtime to use dragonfly:
  https://d7y.io/docs/getting-started/quick-start/kubernetes/

检查 Dragonfly 是否部署成功:

代码语言:javascript
复制
$ kubectl get po -n dragonfly-system
NAME                                 READY   STATUS    RESTARTS       AGE
dragonfly-dfdaemon-rhnr6             1/1     Running   4 (101s ago)   3m27s
dragonfly-dfdaemon-s6sv5             1/1     Running   5 (111s ago)   3m27s
dragonfly-manager-67f97d7986-8dgn8   1/1     Running   0              3m27s
dragonfly-mysql-0                    1/1     Running   0              3m27s
dragonfly-redis-master-0             1/1     Running   0              3m27s
dragonfly-redis-replicas-0           1/1     Running   1 (115s ago)   3m27s
dragonfly-redis-replicas-1           1/1     Running   0              95s
dragonfly-redis-replicas-2           1/1     Running   0              70s
dragonfly-scheduler-0                1/1     Running   0              3m27s
dragonfly-seed-peer-0                1/1     Running   2 (95s ago)    3m27s

创建 Peer Service 配置文件 peer-service-config.yaml 配置如下:

代码语言:javascript
复制
apiVersion: v1
kind: Service
metadata:
  name: peer
  namespace: dragonfly-system
spec:
  type: NodePort
  ports:
    - name: http-65001
      nodePort: 30950
      port: 65001
    - name: http-40901
      nodePort: 30951
      port: 40901
  selector:
    app: dragonfly
    component: dfdaemon
    release: dragonfly

使用配置文件部署 Peer Service:

代码语言:javascript
复制
kubectl apply -f peer-service-config.yaml

Containerd 集成 Nydus

生产环境 Containerd 集成 Nydus 详细文档可以参考nydus-setup-for-containerd-environment[9]。 下面例子使用 Systemd 管理 nydus-snapshotter 服务。

下载安装 Nydus 工具

下载 containerd-nydus-grpc 二进制文件, 下载地址为 nydus-snapshotter/releases[10]:

代码语言:javascript
复制
NYDUS_SNAPSHOTTER_VERSION=0.3.2
wget https://github.com/containerd/nydus-snapshotter/releases/download/v$NYDUS_SNAPSHOTTER_VERSION/nydus-snapshotter-v$NYDUS_SNAPSHOTTER_VERSION-x86_64.tgz
tar zxvf nydus-snapshotter-v$NYDUS_SNAPSHOTTER_VERSION-x86_64.tgz

安装 containerd-nydus-grpc 工具:

代码语言:javascript
复制
sudo cp nydus-snapshotter/containerd-nydus-grpc /usr/local/bin/

下载 nydus-imagenydusd 以及 nydusify 二进制文件, 下载地址为 dragonflyoss/image-service[11]:

代码语言:javascript
复制
NYDUS_VERSION=2.1.1
wget https://github.com/dragonflyoss/image-service/releases/download/v$NYDUS_VERSION/nydus-static-v$NYDUS_VERSION-linux-amd64.tgz
tar zxvf nydus-static-v$NYDUS_VERSION-linux-amd64.tgz

安装 nydus-imagenydusd 以及 nydusify 工具:

代码语言:javascript
复制
sudo cp nydus-static/nydus-image nydus-static/nydusd nydus-static/nydusify /usr/local/bin/
Containerd 集成 Nydus Snapshotter 插件

配置 Containerd 使用 nydus-snapshotter 插件, 详细文档参考configure-and-start-containerd[12]

首先修改 Containerd 配置在 /etc/containerd/config.toml 添加下面内容:

代码语言:javascript
复制
[proxy_plugins]
  [proxy_plugins.nydus]
    type = "snapshot"
    address = "/run/containerd-nydus/containerd-nydus-grpc.sock"

[plugins.cri]
  [plugins.cri.containerd]
    snapshotter = "nydus"
    disable_snapshot_annotations = false

重启 Containerd 服务:

代码语言:javascript
复制
sudo systemctl restart containerd

验证 containerd 是否使用 nydus-snapshotter 插件:

代码语言:javascript
复制
$ ctr -a /run/containerd/containerd.sock plugin ls | grep nydus
io.containerd.snapshotter.v1          nydus                    -              ok
Systemd 启动 Nydus Snapshotter 服务

Nydusd 的 Mirror 模式配置详细文档可以参考enable-mirrors-for-storage-backend[13]

创建 Nydusd 配置文件 nydusd-config.json, 配置如下:

代码语言:javascript
复制
{
  "device": {
    "backend": {
      "type": "registry",
      "config": {
        "mirrors": [
          {
            "host": "http://127.0.0.1:65001",
            "auth_through": false,
            "headers": {
              "X-Dragonfly-Registry": "https://index.docker.io"
            },
            "ping_url": "http://127.0.0.1:40901/server/ping"
          }
        ],
        "scheme": "https",
        "skip_verify": false,
        "timeout": 10,
        "connect_timeout": 10,
        "retry_limit": 2
      }
    },
    "cache": {
      "type": "blobcache",
      "config": {
        "work_dir": "/var/lib/nydus/cache/"
      }
    }
  },
  "mode": "direct",
  "digest_validate": false,
  "iostats_files": false,
  "enable_xattr": true,
  "fs_prefetch": {
    "enable": true,
    "threads_count": 10,
    "merging_size": 131072,
    "bandwidth_rate": 1048576
  }
}

复制配置文件至 /etc/nydus/config.json 文件:

代码语言:javascript
复制
sudo mkdir /etc/nydus && cp nydusd-config.json /etc/nydus/config.json

创建 Nydus Snapshotter Systemd 配置文件 nydus-snapshotter.service, 配置如下:

代码语言:javascript
复制
[Unit]
Description=nydus snapshotter
After=network.target
Before=containerd.service

[Service]
Type=simple
Environment=HOME=/root
ExecStart=/usr/local/bin/containerd-nydus-grpc --config-path /etc/nydus/config.json
Restart=always
RestartSec=1
KillMode=process
OOMScoreAdjust=-999
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target

复制配置文件至 /etc/systemd/system/ 目录:

代码语言:javascript
复制
sudo cp nydus-snapshotter.service /etc/systemd/system/

Systemd 启动 Nydus Snapshotter 服务:

代码语言:javascript
复制
$ sudo systemctl enable nydus-snapshotter
$ sudo systemctl start nydus-snapshotter
$ sudo systemctl status nydus-snapshotter
● nydus-snapshotter.service - nydus snapshotter
     Loaded: loaded (/etc/systemd/system/nydus-snapshotter.service; enabled; vendor preset: enabled)
     Active: active (running) since Wed 2022-10-19 08:01:00 UTC; 2s ago
   Main PID: 2853636 (containerd-nydu)
      Tasks: 9 (limit: 37574)
     Memory: 4.6M
        CPU: 20ms
     CGroup: /system.slice/nydus-snapshotter.service
             └─2853636 /usr/local/bin/containerd-nydus-grpc --config-path /etc/nydus/config.json

Oct 19 08:01:00 kvm-gaius-0 systemd[1]: Started nydus snapshotter.
Oct 19 08:01:00 kvm-gaius-0 containerd-nydus-grpc[2853636]: time="2022-10-19T08:01:00.493700269Z" level=info msg="gc goroutine start..."
Oct 19 08:01:00 kvm-gaius-0 containerd-nydus-grpc[2853636]: time="2022-10-19T08:01:00.493947264Z" level=info msg="found 0 daemons running"
转换 Nydus 格式镜像

转换 python:latest 镜像为 Nydus 格式镜像, 可以直接使用已经转换好的 dragonflyoss/python-nydus:latest 镜像, 跳过该步骤。 转换工具可以使用 nydusify[14] 也可以使用 acceld[15]

登陆 Dockerhub:

代码语言:javascript
复制
docker login

转换 Nydus 镜像, DOCKERHUB_REPO_NAME 环境变量设置为用户个人的镜像仓库:

代码语言:javascript
复制
DOCKERHUB_REPO_NAME=dragonflyoss
sudo nydusify convert --nydus-image /usr/local/bin/nydus-image --source python:latest --target $DOCKERHUB_REPO_NAME/python-nydus:latest
Nerdctl 运行 Nydus 镜像

使用 Nerdctl 运行 python-nydus:latest, 过程中即通过 Nydus 和 Dragonfly 下载镜像:

代码语言:javascript
复制
sudo nerdctl --snapshotter nydus run --rm -it $DOCKERHUB_REPO_NAME/python-nydus:latest

搜索日志验证 Nydus 基于 Mirror 模式通过 Dragonfly 分发流量:

代码语言:javascript
复制
$ grep mirrors /var/lib/containerd-nydus/logs/**/*log
[2022-10-19 10:16:13.276548 +00:00] INFO [storage/src/backend/connection.rs:271] backend config: ConnectionConfig { proxy: ProxyConfig { url: "", ping_url: "", fallback: false, check_interval: 5, use_http: false }, mirrors: [MirrorConfig { host: "http://127.0.0.1:65001", headers: {"X-Dragonfly-Registry": "https://index.docker.io"}, auth_through: false }], skip_verify: false, timeout: 10, connect_timeout: 10, retry_limit: 2 }

性能测试

测试 Nydus Mirror 模式与 Dragonfly P2P 集成后的单机镜像下载的性能。测试是在同一台机器上面做不同场景的测试。由于机器本身网络环境、配置等影响,实际下载时间不具有参考价值,但是不同场景下载时间所提升的比率是有重要意义的。

  • OCIv1: 使用 Containerd 直接拉取镜像并且启动成功的数据。
  • Nydus Cold Boot: 使用 Containerd 通过 Nydus 拉取镜像,没有命中任何缓存并且启动成功的数据。
  • Nydus & Dragonfly Cold Boot: 使用 Containerd 通过 Nydus 拉取镜像,并且基于 Nydus Mirror 模式流量转发至 Dragonfly P2P,在没有命中任何缓存并且启动成功的数据。
  • Hit Dragonfly Remote Peer Cache: 使用 Containerd 通过 Nydus 拉取镜像, 并且基于 Nydus Mirror 模式流量转发至 Dragonfly P2P,在命中 Dragonfly 的远端 Peer 缓存的情况下并且成功启动的数据。
  • Hit Dragonfly Local Peer Cache: 使用 Containerd 通过 Nydus 拉取镜像, 并且基于 Nydus Mirror 模式流量转发至 Dragonfly P2P,在命中 Dragonfly 的本地 Peer 缓存的情况下并且成功启动的数据。
  • Hit Nydus Cache: 使用 Containerd 通过 Nydus 拉取镜像, 并且基于 Nydus Mirror 模式流量转发至 Dragonfly P2P,在命中 Nydus 的本地缓存的情况下并且成功启动的数据。

测试结果表明 Nydus Mirror 模式和 Dragonfly P2P 集成。使用 Nydus 下载镜像对比 OCIv1 的模式, 能够有效减少镜像下载时间。Nydus 冷启动和 Nydus & Dragonfly 冷启动数据基本接近。 其他命中 Dragonfly Cache 的结果均好于只使用 Nydus 的情况。最重要的是如果很大规模集群使用 Nydus 拉取镜像, 会将每个镜像层的下载分解按需产生很多 Range 请求。增加镜像仓库源站 QPS。 而 Dragonfly 可以基于 P2P 技术有效减少回源镜像仓库的请求数量和下载流量。 最优的情况,Dragonfly 可以保证大规模集群中每个下载任务只回源一次。

链接

Dragonfly 社区

  • 官方网站: https://d7y.io/[16]
  • Github 仓库: https://github.com/dragonflyoss/Dragonfly2[17]
  • Slack Channel: #dragonfly[18] on CNCF Slack[19]
  • Discussion Group: dragonfly-discuss@googlegroups.com
  • Twitter: @dragonfly_oss[20]

Nydus 社区

  • 官方网站: https://nydus.dev/[21]
  • Github 仓库: https://github.com/dragonflyoss/image-service[22]
  • Slack Channel: #nydus[23]

参考资料

[1]

Dragonfly: https://d7y.io/

[2]

Nydus: https://nydus.dev/

[3]

kubernetes.io: https://kubernetes.io/

[4]

helm.sh: https://helm.sh/

[5]

containerd.io: https://containerd.io/

[6]

containerd/nerdctl: https://github.com/containerd/nerdctl

[7]

Kind: https://kind.sigs.k8s.io/

[8]

quick-start-kubernetes: https://d7y.io/zh/docs/getting-started/quick-start/kubernetes/

[9]

nydus-setup-for-containerd-environment: https://github.com/dragonflyoss/image-service/blob/master/docs/containerd-env-setup.md#nydus-setup-for-containerd-environment

[10]

nydus-snapshotter/releases: https://github.com/containerd/nydus-snapshotter/releases/latest

[11]

dragonflyoss/image-service: https://github.com/dragonflyoss/image-service/releases/latest

[12]

configure-and-start-containerd: https://github.com/dragonflyoss/image-service/blob/master/docs/containerd-env-setup.md#configure-and-start-containerd

[13]

enable-mirrors-for-storage-backend: https://github.com/dragonflyoss/image-service/blob/master/docs/nydusd.md#enable-mirrors-for-storage-backend

[14]

nydusify: https://github.com/dragonflyoss/image-service/blob/master/docs/nydusify.md

[15]

acceld: https://github.com/goharbor/acceleration-service

[16]

https://d7y.io/: https://d7y.io/

[17]

https://github.com/dragonflyoss/Dragonfly2: https://github.com/dragonflyoss/Dragonfly2

[18]

#dragonfly: https://cloud-native.slack.com/messages/dragonfly/

[19]

CNCF Slack: https://slack.cncf.io/

[20]

@dragonfly_oss: https://twitter.com/dragonfly_oss

[21]

https://nydus.dev/: https://nydus.dev/

[22]

https://github.com/dragonflyoss/image-service: https://github.com/dragonflyoss/image-service

[23]

#nydus: https://join.slack.com/t/nydusimageservice/shared_invite/zt-pz4qvl4y-WIh4itPNILGhPS8JqdFm_w

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2022-11-07,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CNCF 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 简介
  • 实践
    • 依赖
      • 安装 Dragonfly
        • 使用 Kind 安装 Kubernetes 集群
        • Kind 加载 Dragonfly 镜像
        • 基于 Helm Charts 创建 Dragonfly P2P 集群
      • Containerd 集成 Nydus
        • 下载安装 Nydus 工具
        • Containerd 集成 Nydus Snapshotter 插件
        • Systemd 启动 Nydus Snapshotter 服务
        • 转换 Nydus 格式镜像
        • Nerdctl 运行 Nydus 镜像
    • 性能测试
    • 链接
      • Dragonfly 社区
        • Nydus 社区
          • 参考资料
          相关产品与服务
          容器服务
          腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档