作者简介
戚文博(百蓦)
Dragonfly Maintainer,蚂蚁团体软件工程师
次要负责「基于 P2P 的文件散发以及镜像减速零碎」。
本文 2036 字 浏览 8 分钟
Dragonfly 提供高效、稳固、平安的基于 P2P 技术的文件散发和镜像减速零碎,并且是云原生架构中镜像减速畛域的规范解决方案以及最佳实际。当初为云原生计算机基金会(CNCF)托管作为孵化级(Incubating)我的项目。
文章次要论述如何在多集群环境下部署 Dragonfly。一个 Dragonfly 集群治理一个独自网络环境的集群,如果有两个集群是互相隔离的网络环境,就须要有两个 Dragonfly 集群治理各自的集群。
举荐用户在多 Kubernetes 集群场景下,应用一个 Dragonfly 集群治理一个 Kubernetes 集群,二者 1:1 关系。并且应用一个中心化的 Manager 服务去治理多个 Dragonfly 集群。因为对于 Dragonfly,一个 Dragonfly 集群中的所有 Peers 只能在以后 Dragonfly 集群内 P2P 传输数据,所以肯定要保障一个 Dragonfly 集群中的所有 Peers 网络是互通的。那么如果一个 Dragonfly 集群治理一个 Kubernetes 集群,那么代表集群内的 Peers 只在 Kubernetes 集群维度进行 P2P 传输数据。
筹备 Kubernetes 集群
如果没有可用的 Kubernetes 集群进行测试,举荐应用 Kind[1]。
创立 Kind 多节点集群配置文件 kind-config.yaml,配置如下:
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
extraPortMappings:
- containerPort: 30950
hostPort: 8080
labels:
cluster: a
- role: worker
labels:
cluster: a
- role: worker
labels:
cluster: b
- role: worker
labels:
cluster: b
应用配置文件创立 Kind 集群:
kind create cluster --config kind-config.yaml
切换 Kubectl 的 context 到 Kind 集群:
kubectl config use-context kind-kind
Kind 加载 Dragonfly 镜像
下载 Dragonfly latest 镜像:
docker pull dragonflyoss/scheduler:latest
docker pull dragonflyoss/manager:latest
docker pull dragonflyoss/dfdaemon:latest
Kind 集群加载 Dragonfly latest 镜像:
kind load docker-image dragonflyoss/scheduler:latest
kind load docker-image dragonflyoss/manager:latest
kind load docker-image dragonflyoss/dfdaemon:latest
创立 Dragonfly 集群 A
创立 Dragonfly 集群 A,应该应用 Helm 在以后集群内装置中心化的 Manager、Scheduler、Seed Peer、Peer。
基于 Helm Charts 创立 Dragonfly 集群 A
创立 Helm Charts 的 Dragonfly 集群 A 的配置文件 charts-config-cluster-a.yaml,配置如下:
containerRuntime:
containerd:
enable: true
injectConfigPath: true
registries:
- 'https://ghcr.io'
scheduler:
image: dragonflyoss/scheduler
tag: latest
nodeSelector:
cluster: a
replicas: 1
metrics:
enable: true
config:
verbose: true
pprofPort: 18066
seedPeer:
image: dragonflyoss/dfdaemon
tag: latest
nodeSelector:
cluster: a
replicas: 1
metrics:
enable: true
config:
verbose: true
pprofPort: 18066
dfdaemon:
image: dragonflyoss/dfdaemon
tag: latest
nodeSelector:
cluster: a
metrics:
enable: true
config:
verbose: true
pprofPort: 18066
manager:
image: dragonflyoss/manager
tag: latest
nodeSelector:
cluster: a
replicas: 1
metrics:
enable: true
config:
verbose: true
pprofPort: 18066
jaeger:
enable: true
应用配置文件部署 Helm Charts 的 Dragonfly 集群 A:
$ helm repo add dragonfly https://dragonflyoss.github.io/helm-charts/
$ helm install --wait --create-namespace --namespace cluster-a dragonfly dragonfly/dragonfly -f charts-config-cluster-a.yaml
NAME: dragonfly
LAST DEPLOYED: Mon Aug 7 22:07:02 2023
NAMESPACE: cluster-a
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 cluster-a -l "app=dragonfly,release=dragonfly,component=scheduler" -o jsonpath={.items[0].metadata.name})
export SCHEDULER_CONTAINER_PORT=$(kubectl get pod --namespace cluster-a $SCHEDULER_POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
kubectl --namespace cluster-a 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 cluster-a -l "app=dragonfly,release=dragonfly,component=dfdaemon" -o jsonpath={.items[0].metadata.name})
export DFDAEMON_CONTAINER_PORT=$(kubectl get pod --namespace cluster-a $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/
4. Get Jaeger query URL by running these commands:
export JAEGER_QUERY_PORT=$(kubectl --namespace cluster-a get services dragonfly-jaeger-query -o jsonpath="{.spec.ports[0].port}")
kubectl --namespace cluster-a port-forward service/dragonfly-jaeger-query 16686:$JAEGER_QUERY_PORT
echo "Visit http://127.0.0.1:16686/search?limit=20&lookback=1h&maxDuration&minDuration&service=dragonfly to query download events"
查看 Dragonfly 集群 A 是否部署胜利:
$ kubectl get po -n cluster-a
NAME READY STATUS RESTARTS AGE
dragonfly-dfdaemon-7t6wc 1/1 Running 0 3m18s
dragonfly-dfdaemon-r45bk 1/1 Running 0 3m18s
dragonfly-jaeger-84dbfd5b56-fmhh6 1/1 Running 0 3m18s
dragonfly-manager-75f4c54d6d-tr88v 1/1 Running 0 3m18s
dragonfly-mysql-0 1/1 Running 0 3m18s
dragonfly-redis-master-0 1/1 Running 0 3m18s
dragonfly-redis-replicas-0 1/1 Running 1 (2m ago) 3m18s
dragonfly-redis-replicas-1 1/1 Running 0 96s
dragonfly-redis-replicas-2 1/1 Running 0 45s
dragonfly-scheduler-0 1/1 Running 0 3m18s
dragonfly-seed-peer-0 1/1 Running 1 (37s ago) 3m18s
创立 Manager REST 服务的 NodePort Service 资源
创立 Manager REST 服务的配置文件 manager-rest-svc.yaml,配置如下:
apiVersion: v1
kind: Service
metadata:
name: manager-rest
namespace: cluster-a
spec:
type: NodePort
ports:
- name: http
nodePort: 30950
port: 8080
selector:
app: dragonfly
component: manager
release: dragonfly
应用配置文件创立 Manager REST 服务的 Service 资源:
kubectl apply -f manager-rest-svc.yaml -n cluster-a
拜访 Manager 控制台
应用默认用户名 root,明码 dragonfly 拜访 localhost:8080 的 Manager 控制台地址,并且进入控制台。
在 Dragonfly Manager 部署胜利后,默认状况下 Dragonfly Manager 在第一次启动的时候,如果没有任何集群,那么会主动创立集群 A 的记录。用户能够点击 Manager 控制台看到集群 A 的详细信息。
创立 Dragonfly 集群 B
创立 Dragonfly 集群 B,须要在 Manager 控制台首先创立 Dragonfly 集群记录,而后再应用 Helm 装置 Scheduler、Seed Peer 和 Peer。
Manager 控制台创立 Dragonfly 集群 B 的记录
点击 ADD CLUSTER
按钮创立集群 B 的记录,留神 IDC 设置为 cluster-2 使其可能跟前面 Peer 配置文件中 IDC 值为 cluster-2 的 Peer 相匹配。
创立 Dragonfly 集群 B 记录胜利。
应用 Scopes 配置辨别 不同 Dragonfly 集群
Cluster 管辖的 Scopes 信息。Peer 会依据 Dfdaemon 启动的配置文件 host.idc、host.location 以及 host.advertiseIP 的内容上报给 Manager。而后 Manager 抉择跟 Cluster Scopes 中 IDC、Location 以及 CIDRs 匹配的 Cluster。被选中的 Cluster 会提供本身的 Scheduler Cluster 和 Seed Peer Cluster 对以后 Peer 进行服务。这样能够通过 Scopes 来辨别不同 Cluster 服务的 Peer 群,在多集群场景中十分重要。Peer 的配置文件能够参考文档 dfdaemon config[2]。
如果 Peer 的 Scopes 信息和 Dragonfly 集群匹配,那么会优先应用以后 Dragonfly 集群的 Scheduler 和 Seed Peer 提供服务。也就是说以后 Dragonfly 集群内的 Peer 只能在集群外部进行 P2P 传输数据。如果没有匹配的 Dragonfly 集群,那么应用默认的 Dragonfly 集群提供服务。
Location: Cluster 须要为该 Location 的所有 Peer 提供服务。当对 Peer 配置中的 Location 与 Cluster 中的 Location 配时,Peer 将优先应用 Cluster 的 Scheduler 和 Seed Peer。用“|”分隔,例如“地区 | 国家 | 省 | 城市”。
IDC: Cluster 须要服务 IDC 内的所有 Peer。当 Peer 配置中的 IDC 与 Cluster 中的 IDC 匹配时,Peer 将优先应用 Cluster 的 Scheduler 和 Seed Peer。IDC 在 Scopes 内的优先级高于 Location。
CIDRs: Cluster 须要为 CIDR 中的所有 Peer 提供服务。当 Peer 启动时,将在 Peer 配置中应用 Advertise IP,如果 Peer 配置中的 Advertise IP 为空,则 Peer 将主动获取 Expose IP 作为 Advertise IP。当 Peer 上报的 IP 与 Cluster 中的 CIDR 匹配时,Peer 将优先应用 Cluster 的 Scheduler 和 Seed Peer。CIDR 在 Scopes 内的优先级高于 IDC。
基于 Helm Charts 创立 Dragonfly 集群 B
创立 Helm Charts 文件的内容能够在 Manager 控制台对应的 Dragonfly 集群信息详情中查看。
Scheduler.config.manager.schedulerClusterID
是 Manager 控制台的 cluster-2 集群信息中的Scheduler cluster ID
值。Scheduler.config.manager.addr
是 Manager 的 GRPC 服务地址。seedPeer.config.scheduler.manager.seedPeer.clusterID
是 Manager 控制台的 cluster-2 集群信息中的Seed peer cluster ID
值。seedPeer.config.scheduler.manager.netAddrs[0].addr
是 Manager 的 GRPC 服务地址。dfdaemon.config.host.idc
是 Manager 控制台的 cluster-2 集群信息中的 IDC 值。dfdaemon.config.scheduler.manager.netAddrs[0].addr
是 Manager 的 GRPC 服务地址。externalManager.host
是 Manager 的 GRPC 服务的 Host。externalRedis.addrs[0]
是 Redis 的服务地址。
创立 Helm Charts 的 Dragonfly 集群 B 的配置文件 charts-config-cluster-b.yaml,配置如下:
containerRuntime:
containerd:
enable: true
injectConfigPath: true
registries:
- 'https://ghcr.io'
scheduler:
image: dragonflyoss/scheduler
tag: latest
nodeSelector:
cluster: b
replicas: 1
config:
manager:
addr: dragonfly-manager.cluster-a.svc.cluster.local:65003
schedulerClusterID: 2
seedPeer:
image: dragonflyoss/dfdaemon
tag: latest
nodeSelector:
cluster: b
replicas: 1
config:
scheduler:
manager:
netAddrs:
- type: tcp
addr: dragonfly-manager.cluster-a.svc.cluster.local:65003
seedPeer:
enable: true
clusterID: 2
dfdaemon:
image: dragonflyoss/dfdaemon
tag: latest
nodeSelector:
cluster: b
config:
host:
idc: cluster-2
scheduler:
manager:
netAddrs:
- type: tcp
addr: dragonfly-manager.cluster-a.svc.cluster.local:65003
manager:
enable: false
externalManager:
enable: true
host: dragonfly-manager.cluster-a.svc.cluster.local
restPort: 8080
grpcPort: 65003
redis:
enable: false
externalRedis:
addrs:
- dragonfly-redis-master.cluster-a.svc.cluster.local:6379
password: dragonfly
mysql:
enable: false
jaeger:
enable: true
应用配置文件部署 Helm Charts 的 Dragonfly 集群 B:
$ helm install --wait --create-namespace --namespace cluster-b dragonfly dragonfly/dragonfly -f charts-config-cluster-b.yaml
NAME: dragonfly
LAST DEPLOYED: Mon Aug 7 22:13:51 2023
NAMESPACE: cluster-b
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 cluster-b -l "app=dragonfly,release=dragonfly,component=scheduler" -o jsonpath={.items[0].metadata.name})
export SCHEDULER_CONTAINER_PORT=$(kubectl get pod --namespace cluster-b $SCHEDULER_POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
kubectl --namespace cluster-b 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 cluster-b -l "app=dragonfly,release=dragonfly,component=dfdaemon" -o jsonpath={.items[0].metadata.name})
export DFDAEMON_CONTAINER_PORT=$(kubectl get pod --namespace cluster-b $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/
4. Get Jaeger query URL by running these commands:
export JAEGER_QUERY_PORT=$(kubectl --namespace cluster-b get services dragonfly-jaeger-query -o jsonpath="{.spec.ports[0].port}")
kubectl --namespace cluster-b port-forward service/dragonfly-jaeger-query 16686:$JAEGER_QUERY_PORT
echo "Visit http://127.0.0.1:16686/search?limit=20&lookback=1h&maxDuration&minDuration&service=dragonfly to query download events"
查看 Dragonfly 集群 B 是否部署胜利:
$ kubectl get po -n dragonfly-system
NAME READY STATUS RESTARTS AGE
dragonfly-dfdaemon-q8bsg 1/1 Running 0 67s
dragonfly-dfdaemon-tsqls 1/1 Running 0 67s
dragonfly-jaeger-84dbfd5b56-rg5dv 1/1 Running 0 67s
dragonfly-scheduler-0 1/1 Running 0 67s
dragonfly-seed-peer-0 1/1 Running 0 67s
创立 Dragonfly 集群 B 胜利。
应用 Dragonfly 在多集群环境下散发镜像
集群 A 中 Containerd 通过 Dragonfly 首次回源拉镜像
在 kind-worker Node 下载 ghcr.io/dragonflyoss/dragonfly2/scheduler:v2.0.5
镜像:
docker exec -i kind-worker /usr/local/bin/crictl pull ghcr.io/dragonflyoss/dragonfly2/scheduler:v2.0.5
裸露 Jaeger 16686 端口:
kubectl --namespace cluster-a port-forward service/dragonfly-jaeger-query 16686:16686
进入 Jaeger 页面 \<http://127.0.0.1:16686/search >,搜寻 Tags 值为 http.url="/v2/dragonflyoss/dragonfly2/scheduler/blobs/sha256:82cbeb56bf8065dfb9ff5a0c6ea212ab3a32f413a137675df59d496e68eaf399?ns=ghcr.io"
Tracing:
Tracing 具体内容:
集群 A 内首次回源时,下载 82cbeb56bf8065dfb9ff5a0c6ea212ab3a32f413a137675df59d496e68eaf399
层须要耗费工夫为 1.47s
。
集群 A 中 Containerd 下载镜像命中 Dragonfly 近程 Peer 的缓存
在 kind-worker2 Node 下载 ghcr.io/dragonflyoss/dragonfly2/scheduler:v2.0.5
镜像:
docker exec -i kind-worker2 /usr/local/bin/crictl pull ghcr.io/dragonflyoss/dragonfly2/scheduler:v2.0.5
裸露 Jaeger 16686 端口:
kubectl --namespace cluster-a port-forward service/dragonfly-jaeger-query 16686:16686
进入 Jaeger 页面 \<http://127.0.0.1:16686/search >,搜寻 Tags 值为 http.url="/v2/dragonflyoss/dragonfly2/scheduler/blobs/sha256:82cbeb56bf8065dfb9ff5a0c6ea212ab3a32f413a137675df59d496e68eaf399?ns=ghcr.io"
Tracing:
Tracing 具体内容:
集群 A 中命中近程 Peer 缓存时,下载 82cbeb56bf8065dfb9ff5a0c6ea212ab3a32f413a137675df59d496e68eaf399
层须要耗费工夫为 37.48ms
。
集群 B 中 Containerd 通过 Dragonfly 首次回源拉镜像
在 kind-worker3 Node 下载 ghcr.io/dragonflyoss/dragonfly2/scheduler:v2.0.5
镜像:
docker exec -i kind-worker3 /usr/local/bin/crictl pull ghcr.io/dragonflyoss/dragonfly2/scheduler:v2.0.5
裸露 Jaeger 16686 端口:
kubectl --namespace cluster-b port-forward service/dragonfly-jaeger-query 16686:16686
进入 Jaeger 页面 \<http://127.0.0.1:16686/search >,搜寻 Tags 值为 http.url="/v2/dragonflyoss/dragonfly2/scheduler/blobs/sha256:82cbeb56bf8065dfb9ff5a0c6ea212ab3a32f413a137675df59d496e68eaf399?ns=ghcr.io"
Tracing:
Tracing 具体内容:
集群 B 中命中近程 Peer 缓存时,下载 82cbeb56bf8065dfb9ff5a0c6ea212ab3a32f413a137675df59d496e68eaf399
层须要耗费工夫为 4.97s
。
集群 B 中 Containerd 下载镜像命中 Dragonfly 近程 Peer 的缓存
在 kind-worker4 Node 下载 ghcr.io/dragonflyoss/dragonfly2/scheduler:v2.0.5
镜像:
docker exec -i kind-worker4 /usr/local/bin/crictl pull ghcr.io/dragonflyoss/dragonfly2/scheduler:v2.0.5
裸露 Jaeger 16686 端口:
kubectl --namespace cluster-b port-forward service/dragonfly-jaeger-query 16686:16686
进入 Jaeger 页面 \<http://127.0.0.1:16686/search >,搜寻 Tags 值为 http.url="/v2/dragonflyoss/dragonfly2/scheduler/blobs/sha256:82cbeb56bf8065dfb9ff5a0c6ea212ab3a32f413a137675df59d496e68eaf399?ns=ghcr.io"
Tracing:
Tracing 具体内容:
集群 B 中命中近程 Peer 缓存时,下载 82cbeb56bf8065dfb9ff5a0c6ea212ab3a32f413a137675df59d496e68eaf399
层须要耗费工夫为 14.53ms
。
Dragonfly Star 一下✨:
https://github.com/dragonflyoss/Dragonfly2
相干链接
[1]Kind:https://kind.sigs.k8s.io/
[2]dfdaemon config:https://d7y.io/zh/docs/next/reference/configuration/dfdaemon/
[3]Dragonfly 官网:https://d7y.io/
[4]Dragonfly Github 仓库:https://github.com/dragonflyoss/Dragonfly2
[5]Dragonfly Slack Channel(#dragonfly on CNCF Slack):https://cloud-native.slack.com/?redir=%2Fmessages%2Fdragonfly%2F
[6]Dragonfly Discussion Group: dragonfly-discuss@googlegroups.com
[7]Dragonfly Twitter(@dragonfly\_oss):https://twitter.com/dragonfly_oss
[8]Nydus Github 仓库: https://github.com/dragonflyoss/image-service
[9]Nydus 官网: https://nydus.dev/
举荐浏览
Dragonfly 公布 v2.1.0 版本!
Dragonfly 中 P2P 传输协定优化
蚂蚁 SOFAServerless 微服务新架构的摸索与实际
超过边界:FaaS 的利用实际和将来瞻望