说明
如果说微服务和容器是最佳拍档,那么模块多实例是肯定少不了。假如没有使用类似 Google jib 等手段进行镜像分层(利用镜像缓存),势必会造成:
- 带宽浪费: 尤其是公网带宽,如果是自建 harbor,那么会容易导致单节点网卡被打满,如果用了 harbor 联邦,又会导致数据同步等运维问题。
- 集群拉起慢:镜像下载慢,必然会导致服务拉起慢。
Dragonfly 是阿里巴巴自研并开源的一款基于 P2P 协议的文件分发系统。除了使用 dfget 进行文件下载外,还支持通过 dfdaemon 调用 dfget 进行 docker 镜像下载。
对于 dfdaemon 放置方案
方案 优点 缺点
通过 daemonset 部署到所有节点 简单 新节点启动,其 dfdaemon 自身还无法启动,无法提供代理功能,出现鸡和蛋的问题
通过 daemonset 部署到已有部分节点 资源复用 拉取镜像需要消耗这些节点大量的流量和资源,对这些节点上的应用产生影响
通过 docker 在新节点初始化时部署 解决鸡和蛋的问题 会造成管理复杂性,这部分容器不受 kubernetes 管理
通过二进制在新节点初始化时部署 资源复用 增加了节点初始化时间,随着节点增加,复杂度线性增长
通过额外节点 docker 部署 隔离效果好,复杂度固定 增加了成本
吐槽
Dragonfly 的一些资料除了网上早几年的宣传文档,几乎没找到近期的一些实战资料(不禁怀疑真的有生产用户在用?)。另外官方文档简陋的几页,都年久失修,简直就是 TMD 的垃圾中的战斗机(致敬满满铜臭的阿里)。
安装
步骤 1:部署 Dragonfly 集群管理器(Cluster Manager)服务端 Supernode
打印默认配置:
参考:https://github.com/dragonflyoss/Dragonfly/blob/master/docs/config/supernode_config_template.yml
# docker run --rm -it dragonflyoss/supernode:1.0.6 config default
启动 supernode 容器:
备注:我这里时间设置都尽量调大了,为了尽可能多的使用 cache
--advertise-ip 是 supernode 所在宿主机的 IP,必须是客户端能够连通的,如果不设置,有可能会导致 client 无法连接 supernode,届时 docker pull 会走 clinet 的网络,从真实的 registry 直接下载镜像
--pool-size 是核心池大小。当请求启动下载任务时,超级节点将构造一个线程并发池,以下载源文件片段并写入指定的存储。通过 HTTP 标头中设置的 range 属性将源文件下载分成多个部分。
--max-bandwidth 是超级节点可以使用的网络带宽
--system-bandwidth 是为系统软件保留的网络带宽
--fail-access-interval 是访问 URL 失败后的时间间隔。如果无法从源下载任务,则自上次失败以来的时间内将不会重试该任务。
--gc-initial-delay 从启动到第一次执行 GC 的延迟时间
--gc-meta-interval 执行 GC 元数据的间隔时间
--task-expire-time 当未在 task-expire-time 内访问任务时,该任务将被视为过期
--peer-gc-delay 对等方报告脱机之后执行 GC 的延迟时间
# mkdir -p /opt/dragonfly
# cat > /opt/dragonfly/supernode.yml <<EOF
base:
cdnPattern: local
listenPort: 8002
downloadPort: 8001
homeDir: /home/admin/supernode
schedulerCorePoolSize: 100
downloadpath: /home/admin/supernode/repo/download
peerUpLimit: 5
peerDownLimit: 5
# 当 dfget 节点开始扮演对等方的角色时,它将为其他对等方提供服务。如果在为对等方提供服务时遇到问题,其自故障将增加 1。当故障限制达到 eliminationLimit 时,对等方会将自己隔离为不健康状态。然后,此 dfget 将不再被其他对等方调用
eliminationLimit: 5
# 是在 dfget 客户端在超级节点中设置的故障计数限制。当 dfget 客户端加入由超级节点构建的对等网络时,超级节点将命令对等方开始分发任务。当 dfget 客户端未能完成分发任务时,客户端的失败计数将增加 1。当客户端的失败计数达到 failureCountLimit 时,dfget 客户端将被移至超级节点的黑名单以停止作为对等方角色。
failureCountLimit: 5
linkLimit: 20MB
systemReservedBandwidth: 20MB
maxBandwidth: 200MB
enableProfiler: false
debug: true
# supernode 地址
advertiseIP: "10.64.57.72"
failAccessInterval: 1m
gcInitialDelay: 5m
gcMetaInterval: 24h
taskExpireTime: 30m
peerGCDelay: 24h
# 执行磁盘 GC 的间隔时间
gcDiskInterval: 5m
# 如果可用磁盘空间大于 YoungGCThreshold 不需要 GC 磁盘
youngGCThreshold: 10GB
# 如果可用磁盘空间小于 FullGCThreshold,超级节点应 gc 所有未使用的任务文件
fullGCThreshold: 5GB
# 访问任务文件的时间间隔的阈值
IntervalThreshold: 2h0m0s
cleanratio: 1
logConfig:
maxSize: 0
maxBackups: 0
path: ""
plugins: {}
storages: {}
EOF
# docker run --name supernode \
-d \
--restart=always \
-p 8001:8001 \
-p 8002:8002 \
-v /opt/dragonfly/supernode:/home/admin/supernode \
-v /opt/dragonfly/supernode.yml:/etc/dragonfly/supernode.yml:ro \
dragonflyoss/supernode:1.0.6 \
--config /etc/dragonfly/supernode.yml
# docker exec -it supernode netstat -tnlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:8001 0.0.0.0:* LISTEN 7/nginx: master pro
tcp 0 0 :::8002 :::* LISTEN 8/supernode
查看目录:
注意:repo 目录是用来做临时源缓存的
# docker exec -it supernode ls -l /home/admin/supernode/
total 0
drwxr--r-- 2 root root 20 Dec 2 07:05 logs
drwxr-xr-x 2 root root 6 Dec 2 07:05 repo
查看日志:
# docker logs -f supernode
time="2020-12-02T07:05:11Z" level=debug msg="use log file /home/admin/supernode/logs/app.log"
# docker exec -it supernode tail -f /home/admin/supernode/logs/app.log
cleanratio: 1
logConfig:
maxSize: 0
maxBackups: 0
path: ""
plugins: {}
storages: {}
2020-12-02 07:05:11.455 INFO sign:8 : start to run supernode
2020-12-02 07:05:11.465 DEBU sign:8 : start the gc job
步骤 2:部署 Dragonfly 客户端 dfclient
打印默认配置:
参考:https://github.com/dragonflyoss/Dragonfly/blob/master/docs/config/dfdaemon_config_template.yml
# docker run --rm -it dragonflyoss/dfclient:1.0.6 config default
注意:该镜像中包含 dfdaemon 和 dfget
注意:dfdaemon 仅用于拉取镜像。dfdaemon 扮演代理角色,拦截容器引擎的镜像下载请求并重定向到 dfget 中。
注意:--node 指定 supernodes 地址,支持多个地址如:nodeIp1,nodeIp2
注意:--registry 指定镜像仓库地址,https://index.docker.io 为官方镜像仓库,您也可以设置为其他仓库地址,也可以写加速器地址。
注意:--workHome 测试无法改变 /root/.small-dragonfly 目录
# mkdir -p /opt/dragonfly
# cat > /opt/dragonfly/dfdaemon.yml <<EOF
# 配置注册表的镜像,从自己的私有仓库下拉,拉不到就去 docker hub 拉,再拉不到报错
registry_mirror:
remote: https://harbor.sit.hupu.io
certs: null
insecure: false
direct: false
# 透明代理的规则列表。如果未提供任何规则,则将直接代理所有请求。请求将使用第一个匹配规则进行代理
proxies: []
## proxy all http image layer download requests with dfget
#- regx: blobs/sha256.*
## change http requests to some-registry to https and proxy them with dfget
#- regx: some-registry/
# use_https: true
## proxy requests directly, without dfget
#- regx: no-proxy-reg
# direct: true
# dfdaemon 应当劫持其 https 请求的主机列表。如果网址与代理规则匹配,则 DFdaemon 将能够使用 dfget 代理来自它们的请求。将使用第一个匹配的规则。
hijack_https: null
## key pair used to hijack https requests
#cert: df.crt
#key: df.key
#hosts:
# - regx: mirror.aliyuncs.com:443 # regexp to match request hosts
# # whether to ignore https certificate errors
# insecure: false
# # optional certificates if the host uses self-signed certificates
# certs: []
port: 65001
hostIp: 127.0.0.1
certpem: ""
keypem: ""
verbose: false
maxprocs: 4
# --node 指定 supernodes
# --expiretime:缓存的文件不被任何进程访问持续时间(默认 3 分钟)
# --alivetime:上载器在任何期间都无法访问任何上载请求的有效持续时间,在此期间上载器将自动退出(默认值为 5m0s)
#dfget_flags: ["--node", "192.168.33.21", "--verbose", "--ip", "192.168.33.23", "--port", "15001", "--expiretime", "3m0s", "--alivetime", "5m0s", "-f", "filterParam1&filterParam2"]
dfget_flags: ["--expiretime", "24h", "--alivetime", "1h"]
# 这里指定多个 supernode 节点
supernodes:
- 10.64.56.175:8002
- 10.64.56.176:8002
ratelimit: 200MB
workHome: /root/.small-dragonfly
localrepo: /root/.small-dragonfly/dfdaemon/data
dfpath: /opt/dragonfly/df-client/dfget
logConfig:
maxSize: 0
maxBackups: 0
path: ""
localIP: ""
peerPort: 0
streamMode: false
EOF
# docker run --name dfclient \
-d \
--restart=always \
-p 65001:65001 \
-v /opt/dragonfly/.small-dragonfly:/root/.small-dragonfly \
-v /opt/dragonfly/dfdaemon.yml:/etc/dragonfly/dfdaemon.yml:ro \
dragonflyoss/dfclient:1.0.6 \
--config /etc/dragonfly/dfdaemon.yml
# docker logs -f dfclient
# docker exec -it dfclient tail -f /root/.small-dragonfly/logs/dfdaemon.log
备注:如果要使用二进制部署:
# wget https://github.com/dragonflyoss/Dragonfly/releases/download/v1.0.6/Dragonfly_1.0.6_linux_amd64.tar.gz
# tar -zxf Dragonfly_1.0.6_linux_amd64.tar.gz
# mv Dragonfly_1.0.6_linux_amd64/{supernode,dfget,dfdaemon} /usr/local/bin/
# rm -rf Dragonfly_1.0.6_linux_amd64/
# vi /etc/dragonfly/dfdaemon.yml
# 注意修改 dfget 路径
dfpath: /usr/local/bin/dfget
# cat > /usr/lib/systemd/system/dfdaemon.service <<EOF
[Unit]
Description=dfdaemon server
Documentation=https://github.com/dragonflyoss/Dragonfly
After=network.target
[Service]
ExecStart=/usr/local/bin/dfdaemon --config /etc/dragonfly/dfdaemon.yml
Type=simple
Restart=always
RestartSec=5
LimitNPROC=infinity
LimitCORE=infinity
LimitNOFILE=1048576
TasksMax=infinity
OOMScoreAdjust=-999
[Install]
WantedBy=multi-user.target
EOF
# systemctl enable dfdaemon.service --now
步骤 3:修改 Docker Daemon 配置
我们需要修改 Docker Daemon 配置,通过 mirror 方式来使用 Dragonfly 进行镜像的拉取。即让 docker engine 走 dfdaemon
注意:如果是本机代理用 127.0.0.1 即可,如果额外部署 dfdaemon 节点的话,需要用 LB 去负载均衡,这里就要换成 LB 地址
# vi /etc/docker/daemon.json
{
"registry-mirrors": ["http://127.0.0.1:65001"]
}
重启 Docker Daemon:
# systemctl restart docker
步骤 4:拉取镜像
通过以上步骤我们即完成了 Dragonfly 服务端与客户端的部署,并且设置了 Docker Daemon 通过 Dragonfly 来拉取 harbor 镜像。
注意:不要在 imageName 中包含映像库 URL,因为在启动 dfdaemon 时已使用注册表参数指定了库 URL
直接走公网下载:
# docker pull grafana/grafana:7.3.4
直接走 harbor 下载:
# docker pull harbor.sit.hupu.io/k8s/grafana:7.3.2
走 dragonfly 下载:
注意:当 dfdaemon 都挂掉了,那么这里就无法拉取了,会报错的
注意:首先去 harbor 拉取,如果 harbor 没有就去 docker hub 拉取,如果再没有就报错
# docker pull k8s/grafana:7.3.1
查看镜像:
# docker images |grep grafana
grafana/grafana 7.3.4 651ff2dc930f 2 weeks ago 187MB
harbor.sit.hupu.io/k8s/grafana 7.3.2 68f75fcab5a9 3 weeks ago 186MB
k8s/grafana 7.3.1 900b03b57e41 5 weeks ago 186MB
步骤 5:验证
您可以通过执行以下命令,检验 alpine 镜像是否通过 Dragonfly 来传输完成。
# docker exec dfclient grep 'downloading piece' /root/.small-dragonfly/logs/dfclient.log
...
2020-12-02 06:46:45.790 INFO sign:126-1606891605.701 : downloading piece:{"taskID":"3dad6a545f6d13baf8708306d6ae7dda0d4b45e14b2172cd9e0b4f4d0a249b8e","superNode":"10.64.57.72:8002","dstCid":"","range":"","result":502,"status":700,"pieceSize":0,"pieceNum":0}
另外还可以查看其他日志:
# docker exec -it dfclient ls -la /root/.small-dragonfly/logs
total 532
drwxr--r-- 2 root root 63 Dec 2 07:11 .
drwxr-xr-x 6 root root 54 Dec 2 07:11 ..
-rw-r--r-- 1 root root 277869 Dec 2 07:12 dfclient.log
-rw-r--r-- 1 root root 14482 Dec 2 07:13 dfdaemon.log
-rw-r--r-- 1 root root 2259 Dec 2 07:12 dfserver.log
# docker exec dfclient cat /root/.small-dragonfly/logs/dfdaemon.log
2020-12-02 06:46:44.904 INFO sign:1 : start download url:https://harbor.sit.hupu.io/v2/base/openjdk/blobs/sha256:53301c1d4ea328b37c7cf0577a15b083d175a88e1375632a8ac6532e820a9332 to 98907c7d-6f41-46f9-b111-7a4a8cf1af9d in repo
2020-12-02 06:46:44.904 DEBU sign:1 : round trip with dfget: https://harbor.sit.hupu.io/v2/base/openjdk/blobs/sha256:b205ed23b4294eb568169e43e158008ab7c43c32ad78b8c7a492448a7bbd371b
查看目录:
# docker exec -it dfclient ls -la /root/.small-dragonfly/
total 4
drwxr-xr-x 6 root root 54 Dec 2 07:11 .
drwx------ 1 root root 30 Dec 2 07:09 ..
drwxr-xr-x 2 root root 4096 Dec 2 07:12 data
drwxr-xr-x 3 root root 17 Dec 2 07:09 dfdaemon
drwxr--r-- 2 root root 63 Dec 2 07:11 logs
drwxr-xr-x 2 root root 22 Dec 2 07:11 meta
发现拉取的数据:
# docker exec -it dfclient ls -la /root/.small-dragonfly/meta
total 4
drwxr-xr-x 2 root root 22 Dec 2 07:11 .
drwxr-xr-x 6 root root 54 Dec 2 07:11 ..
-rwxr-xr-x 1 root root 21 Dec 2 07:11 host.meta
# docker exec -it dfclient ls -la /root/.small-dragonfly/data
total 256108
drwxr-xr-x 2 root root 4096 Dec 2 07:12 .
drwxr-xr-x 6 root root 54 Dec 2 07:11 ..
-rwxr-xr-x 1 root root 30210 Dec 2 07:11 1f1b8628-743f-4d86-b6e6-daa039563005-86-1606893114.657.service
-rwxr-xr-x 1 root root 916 Dec 2 07:12 21102506-36cd-431c-89ca-5b192bd38e92-226-1606893129.060.service
-rwxr-xr-x 1 root root 11669 Dec 2 07:11 2e0ac47e-5a01-481e-be61-45e3bff18bfd-40-1606893114.210.service
-rwxr-xr-x 1 root root 5779438 Dec 2 07:11 364e003e-0431-4123-8fcd-95d1f3d8adc5-113-1606893118.230.service
-rwxr-xr-x 1 root root 12401014 Dec 2 07:12 39f690e5-3e86-44f2-bc5f-5b6e9cebcac5-171-1606893122.577.service
-rwxr-xr-x 1 root root 541 Dec 2 07:12 3bfc69a4-1312-4590-9b9a-eed9243bf477-180-1606893122.861.service
-rwxr-xr-x 1 root root 960596 Dec 2 07:11 40bb4cdd-74b6-4664-ac96-01fcd9cf5386-95-1606893114.949.service
-rwxr-xr-x 1 root root 540 Dec 2 07:12 4f650c4d-1dae-4320-a4fb-be5bdde8cde5-163-1606893122.237.service
-rwxr-xr-x 1 root root 200 Dec 2 07:12 6ec2527a-1962-4f9e-8eed-9d9e49599e78-153-1606893121.884.service
-rwxr-xr-x 1 root root 18013716 Dec 2 07:12 73dbede6-d852-48be-ab0d-2e1c3fd485e5-103-1606893115.691.service
-rwxr-xr-x 1 root root 57784 Dec 2 07:12 78ea94a9-c56b-4222-b078-41d8205d94a2-122-1606893120.421.service
-rwxr-xr-x 1 root root 73361858 Dec 2 07:11 85f2cebd-030e-4ed1-8cdd-af91536b9dd5-47-1606893114.232.service
-rwxr-xr-x 1 root root 43395889 Dec 2 07:11 89aa7794-2e25-47e8-ae5a-175d59b42a19-45-1606893114.223.service
-rwxr-xr-x 1 root root 104078240 Dec 2 07:12 9f374057-72ef-4c23-b637-5cd23546a68a-143-1606893121.682.service
-rwxr-xr-x 1 root root 56984 Dec 2 07:12 bfd1e2fc-60e6-4f44-8ca9-7160b0388152-130-1606893120.808.service
-rwxr-xr-x 1 root root 4047182 Dec 2 07:12 c1d46b63-9c6b-4f63-a224-f963aa950c9f-139-1606893121.689.service
-rwxr-xr-x 1 root root 590 Dec 2 07:12 cfdc0a72-f543-4060-b337-e1570b6646e3-199-1606893124.507.service
-rwxr-xr-x 1 root root 412 Dec 2 07:11 da69371b-810e-41e9-84b8-a2b9c8ca3299-55-1606893114.207.service
-rwxr-xr-x 1 root root 512 Dec 2 07:12 df8b81da-e052-41ef-bbc2-451d6ce13964-189-1606893123.371.service
-rwxr-xr-x 1 root root 590 Dec 2 07:12 e0ee3ef4-7e0c-41a6-8e39-99c74b8df5aa-209-1606893127.091.service
-rwxr-xr-x 1 root root 436 Dec 2 07:12 e22b5706-3ba4-470b-87bb-ecb158f8be62-214-1606893127.138.service
步骤 6:k8s 上验证
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: flog
name: flog
namespace: default
spec:
progressDeadlineSeconds: 600
replicas: 4
revisionHistoryLimit: 10
selector:
matchLabels:
app: flog
strategy:
type: Recreate
template:
metadata:
creationTimestamp: null
labels:
app: flog
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- flog
topologyKey: kubernetes.io/hostname
weight: 100
containers:
- args:
- -t
- stdout
- -n
- "100000000000"
- -l
# 注意:image 无需带上 registry 地址和端口
image: k8s/flog:latest
imagePullPolicy: IfNotPresent
name: flog
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
# kubectl apply -f flog.yaml
排错
错误 1:
# docker pull base/openjdk:v1.8
Error response from daemon: pull access denied for base/openjdk, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
解决:
需要指定 mirror 的仓库
registry_mirror:
remote: https://harbor.sit.hupu.io
certs: null
insecure: false
direct: false
或:
--registry https://harbor.sit.hupu.io
错误2:
通过一个 daemonset 启动 2 GB 镜像(节点 200 台),然后蜻蜓 dfdaemon 就全挂了
# docker exec -it dfclient tail -f /root/.small-dragonfly/logs/dfdaemon.log
2020-12-24 03:48:42.019 ERRO sign:1 : download fail: dfget fail(exit status 2):exit status 2
2020-12-24 03:48:42.019 ERRO sign:1 : download fail: dfget fail(signal: killed):signal: killed
2020-12-24 03:48:42.019 ERRO sign:1 : download fail: dfget fail(exit status 80):exit status 80
解决:
架构:
nodes -> SLB -> dfdaemons -> supernodes -> harbor
阿里群里 2个大佬说目前 dfdaemon 目前只支持本地代理,2.0 架构会支持上面的部署模式。
但是不对,因为早上我刚开始用 ds 启动 grafana(200 个 grafana) 是正常的,grafana 镜像应该比较小。然后换成我自己特地弄的 2 个大镜像(单个 1.6G)就不行了。真心不靠谱啊。
又有大佬说:理论上 1.0 的就算这样使用,也是可以下载文件的,看上去应该是 dfget 有问题,下载不了文件导致的。这个还比较中肯。
查看发现 load 太高了,iowait 也很高,内存 8G 也用光了
# top
top - 12:12:23 up 1 day, 18:11, 1 user, load average: 829.77, 905.13, 868.60
Tasks: 296 total, 1 running, 270 sleeping, 0 stopped, 25 zombie
%Cpu(s): 1.8 us, 4.6 sy, 0.0 ni, 0.0 id, 93.4 wa, 0.0 hi, 0.2 si, 0.0 st
KiB Mem : 7733220 total, 101964 free, 7292648 used, 338608 buff/cache
KiB Swap: 0 total, 0 free, 0 used. 63700 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
16499 root 20 0 134868 25764 0 S 5.4 0.3 1:18.02 dfget
27092 root 20 0 185408 42756 1500 S 5.1 0.6 0:02.09 dfget
28461 root 20 0 238580 96816 0 S 4.9 1.3 3:09.05 dfdaemon
3331 root 20 0 130176 17396 0 S 3.4 0.2 0:47.88 dfget
25958 root 20 0 117940 47708 1124 S 3.3 0.6 0:02.20 dfget
3692 root 20 0 116684 40892 0 S 3.0 0.5 7:07.46 node_exporter
21333 root 20 0 123460 18336 0 D 2.5 0.2 0:12.52 dfget
26251 root 20 0 117848 8412 764 S 2.5 0.1 0:04.54 dfget
25564 root 20 0 125208 16356 0 D 2.3 0.2 0:04.60 dfget
9414 root 20 0 134316 20448 0 S 2.1 0.3 0:55.74 dfget
55887 root 20 0 212824 30608 0 S 1.5 0.4 1:55.30 dfget
465 root 0 -20 0 0 0 S 1.3 0.0 0:10.58 kworker/3:1H
26240 root 20 0 185592 52772 1772 S 1.0 0.7 0:04.50 dfget
3379 root 20 0 1226372 12980 1104 S 0.7 0.2 5:24.39 /usr/local/clou
26252 root 20 0 253520 101456 1668 D 0.7 1.3 0:03.31 dfget
27865 root 20 0 117756 67168 880 S 0.7 0.9 0:02.94 dfget
27888 root 20 0 185500 88564 1672 S 0.7 1.1 0:00.88 dfget
28938 root 20 0 118032 35352 2488 S 0.7 0.5 0:00.65 dfget
27656 root 20 0 117848 62964 576 S 0.5 0.8 0:01.02 dfget
46168 root 10 -10 137704 10388 0 S 0.5 0.1 3:13.82 AliYunDun
2 root 20 0 0 0 0 D 0.3 0.0 0:03.46 kthreadd
3 root 20 0 0 0 0 S 0.3 0.0 0:12.40 ksoftirqd/0
26227 root 20 0 185776 102396 1352 S 0.3 1.3 0:07.07 dfget
26286 root 20 0 117848 58804 768 S 0.3 0.8 0:01.76 dfget
27074 root 20 0 117848 21228 868 S 0.3 0.3 0:04.37 dfget
27461 root 20 0 117848 21168 1152 S 0.3 0.3 0:01.76 dfget
27577 root 20 0 117940 25304 1084 S 0.3 0.3 0:00.72 dfget
27777 root 20 0 185868 81376 1184 S 0.3 1.1 0:02.01 dfget
27823 root 20 0 185500 79720 700 S 0.3 1.0 0:00.90 dfget
27881 root 20 0 118032 24388 1600 S 0.3 0.3 0:02.43 dfget
# iostat -x 1
avg-cpu: %user %nice %system %iowait %steal %idle
5.70 0.00 5.44 88.86 0.00 0.00
Device: rrqm/s wrqm/s r/s w/s rkB/s wkB/s avgrq-sz avgqu-sz await r_await w_await svctm %util
vda 0.00 0.00 0.00 2.00 0.00 8.00 8.00 0.00 0.00 0.00 0.00 0.00 0.00
vdb 207.00 0.00 114.00 520.00 21776.00 95992.00 371.51 119.03 414.62 242.16 452.43 1.47 93.00
dfget 进程很多:
# ps -elf|grep dfget|wc -l
339
查看发现 OOM:
[Thu Dec 24 12:23:09 2020] kthreadd invoked oom-killer: gfp_mask=0x3000d0, order=2, oom_score_adj=0
[Thu Dec 24 12:23:09 2020] kthreadd cpuset=/ mems_allowed=0
[Thu Dec 24 12:23:09 2020] CPU: 0 PID: 2 Comm: kthreadd Tainted: G OE ------------ T 3.10.0-957.21.3.el7.x86_64 #1
[Thu Dec 24 12:23:09 2020] Hardware name: Alibaba Cloud Alibaba Cloud ECS, BIOS 8c24b4c 04/01/2014
[Thu Dec 24 12:23:09 2020] Call Trace:
[Thu Dec 24 12:23:09 2020] [<ffffffffa4963107>] dump_stack+0x19/0x1b
[Thu Dec 24 12:23:09 2020] [<ffffffffa495db2a>] dump_header+0x90/0x229
[Thu Dec 24 12:23:09 2020] [<ffffffffa4301292>] ? ktime_get_ts64+0x52/0xf0
[Thu Dec 24 12:23:09 2020] [<ffffffffa43584df>] ? delayacct_end+0x8f/0xb0
[Thu Dec 24 12:23:09 2020] [<ffffffffa43ba834>] oom_kill_process+0x254/0x3d0
[Thu Dec 24 12:23:09 2020] [<ffffffffa43ba2dd>] ? oom_unkillable_task+0xcd/0x120
[Thu Dec 24 12:23:09 2020] [<ffffffffa43ba386>] ? find_lock_task_mm+0x56/0xc0
[Thu Dec 24 12:23:09 2020] [<ffffffffa43bb076>] out_of_memory+0x4b6/0x4f0
[Thu Dec 24 12:23:09 2020] [<ffffffffa495e62e>] __alloc_pages_slowpath+0x5d6/0x724
[Thu Dec 24 12:23:09 2020] [<ffffffffa43c1454>] __alloc_pages_nodemask+0x404/0x420
[Thu Dec 24 12:23:09 2020] [<ffffffffa42c1cd0>] ? insert_kthread_work+0x40/0x40
[Thu Dec 24 12:23:09 2020] [<ffffffffa4294dfd>] copy_process+0x1dd/0x1a40
[Thu Dec 24 12:23:09 2020] [<ffffffffa4296811>] do_fork+0x91/0x320
[Thu Dec 24 12:23:09 2020] [<ffffffffa4296ac6>] kernel_thread+0x26/0x30
[Thu Dec 24 12:23:09 2020] [<ffffffffa42c2761>] kthreadd+0x2c1/0x300
[Thu Dec 24 12:23:09 2020] [<ffffffffa42c24a0>] ? kthread_create_on_cpu+0x60/0x60
[Thu Dec 24 12:23:09 2020] [<ffffffffa4975c37>] ret_from_fork_nospec_begin+0x21/0x21
[Thu Dec 24 12:23:09 2020] [<ffffffffa42c24a0>] ? kthread_create_on_cpu+0x60/0x60
[Thu Dec 24 12:23:09 2020] Mem-Info:
[Thu Dec 24 12:23:09 2020] active_anon:1689377 inactive_anon:174 isolated_anon:0
active_file:1285 inactive_file:2791 isolated_file:245
unevictable:0 dirty:0 writeback:147 unstable:0
slab_reclaimable:11342 slab_unreclaimable:35879
mapped:334 shmem:254 pagetables:8860 bounce:0
free:25505 free_pcp:0 free_cma:0
[Thu Dec 24 12:23:09 2020] Node 0 DMA free:15908kB min:136kB low:168kB high:204kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolated(file):0kB present:15992kB managed:15908kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:0kB slab_unreclaimable:0kB kernel_stack:0kB pagetables:0kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? yes
[Thu Dec 24 12:23:09 2020] lowmem_reserve[]: 0 2795 7533 7533
[Thu Dec 24 12:23:09 2020] Node 0 DMA32 free:43740kB min:25024kB low:31280kB high:37536kB active_anon:2495316kB inactive_anon:184kB active_file:2308kB inactive_file:7212kB unevictable:0kB isolated(anon):0kB isolated(file):1184kB present:3111608kB managed:2865384kB mlocked:0kB dirty:164kB writeback:376kB mapped:784kB shmem:284kB slab_reclaimable:19756kB slab_unreclaimable:47628kB kernel_stack:44064kB pagetables:10072kB unstable:0kB bounce:0kB free_pcp:408kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:3153 all_unreclaimable? no
[Thu Dec 24 12:23:09 2020] lowmem_reserve[]: 0 0 4738 4738
[Thu Dec 24 12:23:09 2020] Node 0 Normal free:42300kB min:42416kB low:53020kB high:63624kB active_anon:4262192kB inactive_anon:512kB active_file:3348kB inactive_file:5520kB unevictable:0kB isolated(anon):0kB isolated(file):496kB present:4980736kB managed:4851916kB mlocked:0kB dirty:40kB writeback:212kB mapped:1028kB shmem:732kB slab_reclaimable:25612kB slab_unreclaimable:95888kB kernel_stack:35232kB pagetables:25368kB unstable:0kB bounce:0kB free_pcp:0kB local_pcp:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:1787 all_unreclaimable? no
[Thu Dec 24 12:23:09 2020] lowmem_reserve[]: 0 0 0 0
[Thu Dec 24 12:23:09 2020] Node 0 DMA: 1*4kB (U) 0*8kB 0*16kB 1*32kB (U) 2*64kB (U) 1*128kB (U) 1*256kB (U) 0*512kB 1*1024kB (U) 1*2048kB (M) 3*4096kB (M) = 15908kB
[Thu Dec 24 12:23:09 2020] Node 0 DMA32: 11064*4kB (UM) 0*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 44256kB
[Thu Dec 24 12:23:09 2020] Node 0 Normal: 1723*4kB (UEM) 4480*8kB (UEM) 4*16kB (UM) 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 42796kB
[Thu Dec 24 12:23:09 2020] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=1048576kB
[Thu Dec 24 12:23:09 2020] Node 0 hugepages_total=0 hugepages_free=0 hugepages_surp=0 hugepages_size=2048kB
[Thu Dec 24 12:23:09 2020] 3797 total pagecache pages
[Thu Dec 24 12:23:09 2020] 0 pages in swap cache
[Thu Dec 24 12:23:09 2020] Swap cache stats: add 0, delete 0, find 0/0
[Thu Dec 24 12:23:09 2020] Free swap = 0kB
[Thu Dec 24 12:23:09 2020] Total swap = 0kB
[Thu Dec 24 12:23:09 2020] 2027084 pages RAM
[Thu Dec 24 12:23:09 2020] 0 pages HighMem/MovableOnly
[Thu Dec 24 12:23:09 2020] 93782 pages reserved
[Thu Dec 24 12:23:09 2020] [ pid ] uid tgid total_vm rss nr_ptes swapents oom_score_adj name
[Thu Dec 24 12:23:09 2020] [ 505] 0 505 11115 139 23 0 -1000 systemd-udevd
[Thu Dec 24 12:23:09 2020] [ 757] 0 757 6653 140 19 0 0 systemd-logind
[Thu Dec 24 12:23:09 2020] [ 762] 999 762 153083 2192 62 0 0 polkitd
[Thu Dec 24 12:23:09 2020] [ 763] 81 763 14883 441 33 0 -900 dbus-daemon
[Thu Dec 24 12:23:09 2020] [ 771] 998 771 29446 130 28 0 0 chronyd
[Thu Dec 24 12:23:09 2020] [ 816] 0 816 31579 166 19 0 0 crond
[Thu Dec 24 12:23:09 2020] [ 819] 0 819 6476 51 19 0 0 atd
[Thu Dec 24 12:23:09 2020] [ 828] 0 828 27526 32 11 0 0 agetty
[Thu Dec 24 12:23:09 2020] [ 829] 0 829 27526 33 9 0 0 agetty
[Thu Dec 24 12:23:09 2020] [ 1025] 0 1025 25710 514 49 0 0 dhclient
[Thu Dec 24 12:23:09 2020] [ 1086] 0 1086 143480 2768 98 0 0 tuned
[Thu Dec 24 12:23:09 2020] [ 1339] 0 1339 4451 120 13 0 0 assist_daemon
[Thu Dec 24 12:23:09 2020] [ 1372] 0 1372 10534 190 13 0 0 aliyun-service
[Thu Dec 24 12:23:09 2020] [ 3621] 0 3621 5632 91 15 0 0 argusagent
[Thu Dec 24 12:23:09 2020] [ 3623] 0 3623 288161 3274 57 0 0 /usr/local/clou
[Thu Dec 24 12:23:09 2020] [ 3731] 997 3731 19740 202 37 0 0 zabbix_agentd
[Thu Dec 24 12:23:09 2020] [ 3732] 997 3732 19765 318 37 0 0 zabbix_agentd
[Thu Dec 24 12:23:09 2020] [ 3733] 997 3733 19740 228 38 0 0 zabbix_agentd
[Thu Dec 24 12:23:09 2020] [ 3734] 997 3734 19740 228 38 0 0 zabbix_agentd
[Thu Dec 24 12:23:09 2020] [ 3735] 997 3735 19740 228 38 0 0 zabbix_agentd
[Thu Dec 24 12:23:09 2020] [ 3736] 997 3736 20848 309 42 0 0 zabbix_agentd
[Thu Dec 24 12:23:09 2020] [ 3973] 0 3973 29123 11172 33 0 0 node_exporter
[Thu Dec 24 12:23:09 2020] [ 4012] 0 4012 109224 148 27 0 0 AliSecGuard
[Thu Dec 24 12:23:09 2020] [ 4762] 0 4762 28216 258 57 0 -1000 sshd
[Thu Dec 24 12:23:09 2020] [ 6035] 0 6035 13881 114 27 0 -1000 auditd
[Thu Dec 24 12:23:09 2020] [ 7333] 0 7333 185371 8005 67 0 -999 containerd
[Thu Dec 24 12:23:09 2020] [ 8114] 0 8114 191483 14776 116 0 -1000 dockerd
[Thu Dec 24 12:23:09 2020] [21528] 0 21528 96053 1291 62 0 0 rsyslogd
[Thu Dec 24 12:23:09 2020] [31410] 0 31410 54259 1829 18 0 -1000 docker-proxy
[Thu Dec 24 12:23:09 2020] [31425] 0 31425 28343 2055 13 0 -998 containerd-shim
[Thu Dec 24 12:23:09 2020] [31445] 0 31445 60469 23040 96 0 0 dfdaemon
[Thu Dec 24 12:23:09 2020] [49106] 0 49106 8133 360 21 0 0 AliYunDunUpdate
[Thu Dec 24 12:23:09 2020] [49133] 0 49133 34587 2763 67 0 0 AliYunDun
[Thu Dec 24 12:23:09 2020] [58651] 0 58651 39180 331 79 0 0 sshd
[Thu Dec 24 12:23:09 2020] [58653] 1002 58653 39180 341 76 0 0 sshd
[Thu Dec 24 12:23:09 2020] [58654] 1002 58654 28991 235 13 0 0 bash
[Thu Dec 24 12:23:09 2020] [58685] 0 58685 60294 293 73 0 0 sudo
[Thu Dec 24 12:23:09 2020] [58686] 0 58686 47944 146 49 0 0 su
[Thu Dec 24 12:23:09 2020] [58687] 0 58687 29023 258 13 0 0 bash
[Thu Dec 24 12:23:09 2020] [ 9952] 0 9952 30543 2953 26 0 0 dfget
[Thu Dec 24 12:23:09 2020] [11576] 0 11576 30060 1638 22 0 0 dfget
[Thu Dec 24 12:23:09 2020] [13986] 0 13986 33625 6044 44 0 0 dfget
[Thu Dec 24 12:23:09 2020] [14617] 0 14617 29462 1883 18 0 0 dfget
[Thu Dec 24 12:23:09 2020] [16105] 0 16105 35097 6758 52 0 0 dfget
...
[Thu Dec 24 12:23:09 2020] [42344] 0 42344 29393 1261 19 0 0 dfget
[Thu Dec 24 12:23:09 2020] [42345] 0 42345 29324 1516 18 0 0 dfget
[Thu Dec 24 12:23:09 2020] [42346] 0 42346 29347 1457 19 0 0 dfget
[Thu Dec 24 12:23:09 2020] [42560] 0 42560 57650 1292 26 0 -998 runc
[Thu Dec 24 12:23:09 2020] [42779] 0 42779 29324 1279 17 0 0 dfget
[Thu Dec 24 12:23:09 2020] [42961] 997 42961 20848 266 44 0 0 zabbix_agentd
[Thu Dec 24 12:23:09 2020] [42977] 0 42977 41388 209 37 0 0 crond
[Thu Dec 24 12:23:09 2020] [43068] 0 43068 29324 1472 18 0 0 dfget
[Thu Dec 24 12:23:09 2020] Out of memory: Kill process 35174 (dfget) score 14 or sacrifice child
[Thu Dec 24 12:23:09 2020] Killed process 35174 (dfget) total-vm:185500kB, anon-rss:109556kB, file-rss:0kB, shmem-rss:0kB
查看日志发现一些节点回源通信错误,换成 --net=host 试试,可惜问题也无法解决。
大佬说明:
一般 dfclient 都是节点粒度的,镜像的下载都是一对一的,只会启动一个 dfget 去下载,然后你现在的这个模式,变成了多对多,启动了几百个 dfget 去下载,小文件还好,大文件就爆了,我看你设置的 down limit 是 50,这样每个 dfget 占用的内存就可能会达到 15 * 50M 的,几百个 dfget 一起下载,多半就跪了。就算改小了,这里还是可能有问题的,dfclient 没有针对大量的请求做优化,还是会有崩掉的可能。
后面会上线一个 seed 的功能,应该可以满足你这个需求的,不会有那么多的 dfget 了,是单进程的
后续
换方案,每个节点使用二进制部署,然后本地代理,使用 10 个 daemonset(15 个节点),最终部分镜像下载成功,部分就一直无法下载了,惨不忍睹,真不知道阿里内部说严重依靠dragonfly做镜像分发是否是真的,或者说开源出来的版本完全就是个摆设?只能用于少量的镜像分发,对应大量的镜像直接挂,那要它何用?
kubectl delete -f grafana-dragonfly.yaml -f grafana-dragonfly0.yaml -f grafana-dragonfly1.yaml -f grafana-dragonfly2.yaml -f grafana-dragonfly3.yaml -f grafana-dragonfly4.yaml -f grafana-dragonfly5.yaml -f grafana-dragonfly6.yaml -f grafana-dragonfly7.yaml -f grafana-dragonfly8.yaml -f grafana-dragonfly9.yaml
snap_screen_20201225175017.png
结论
测试了几天,目前发现 dragonfly 无法应对量数据分发场景,且有一些性能问题,换了两组方案都无法成功 pull。
看看就好,生产慎重。
网友评论