跳到主要内容

3 篇博文 含有标签「docker」

查看所有标签

· 8 分钟阅读
anjia0532

简单介绍下

  • google jib :支持 gradle 和 maven,用于构建 java 应用镜像时,将基础镜像(jdk),
  • 依赖(jar lib),资源文件(resources),class 文件等进行分层(layer),这样依赖,在拉取和推送镜像时,起到加速和节省带宽的目的。
  • Dragonfly2:是阿里开源的一款基于 P2P 协议的,镜像和文件分发加速工具,
  • 与 dragonfly1 相比,dragonfly2 用 golang 重构了,运行时占用资源更少。理论上可以基于 dragonfly 做一个局域网 CDN,及局域网镜像加速器,
  • 文件通过 dragonfly 下载后,缓存到局域网内,再次请求时,如果局域网节点内有,且未过期,则通过 p2p 协议从局域网内拉取,防止占用公网带宽及某个节点过 载被打死的情况。

简单总结下,jib 解决的是 java 应用动不动 100M+甚至 1G+的情况(变成了 80M JDK(基本不变)+200M jar(基本不变)+300M resource(基本不变)+ 1M class(每次发版会变)), 而 dragonfly2 解决的是节省公网带宽,减少内部 registry 节点过热的情况,加起来就是,容器 push&pull 的过程更快了

其实三年前写过阿里 Dragonfly+google jib 的文章,但是时间比较久远,有些内容已经过时,所以准备重新整理下。 之前文章如下:

Google Jib

jib 支持 maven: jib-maven-plugingradle: jib-gradle-plugin , 以及常见的 多模块场景

翻了翻新版的 jib-maven-plugin 文档, 主要部分跟我之前的 加速和简化构建 Docker(基于 Google jib) 差不多,不再CV

但是加了不少新特性,比如

特别的说一下,jib 的很多配置,除了改 pom.xml 外,还支持无侵入的通过命令行指定,并且,命令行传入优先级更高, 比如 mvn compile com.google.cloud.tools:jib-maven-plugin:3.2.0:build -Dimage=<MY IMAGE>中的-Dimage= 对应的是 pom.xml 里的<configuration><to><image></image></to></configuration>

K8S(kubernetes)以 rke2 为例

安装 k8s 集群,如果只是简单测试一下,可以用 k3s 或者 本地分布式开发环境搭建使用 Vagrant 和 Virtualbox 或者 rke2 (如果会用 ansible 也可以用 ansible playbook rke2 )

如果想可视化看下 k8s 集群,可以用kube-explorer, k9s 也可以用rancher2.6(注意如果用 rancher 的话 ,注意 rke2 安装的版本,以最新稳定版本 2.6.3为例,默认支持的是 k8s v1.21.7,也就是得用rke2 v1.21.7+rke2r2)

Dragonfly2

详细内容可参考官网 d8y.io

helm 安装

官方文档 https://github.com/dragonflyoss/helm-charts/blob/main/charts/dragonfly/README.md

考虑到国内特殊国情,可能会访问 github 失败,可以用 https://gitee.com/projects/import/url 中转(也可以用我的 https://gitee.com/anjia/dragonflyoss-helm-charts)

git clone https://gitee.com/anjia/dragonflyoss-helm-charts.git

cd ./dragonflyoss-helm-charts/charts/dragonfly

helm dependency update

helm install --create-namespace --namespace dragonfly-system dragonfly . -f values.yml

如果要自定义参数,通过 -f values.yml 来指定,如果默认则移除 -f values.yml, 支持的配置有 https://github.com/dragonflyoss/helm-charts/tree/main/charts/dragonfly#values

注意点

  1. dragonfly 的 helm 支持 docker 和 containerd 两种引擎,官方推荐使用 containerd(因为支持 fallback,docker 不支持),如果是加速多镜像库官方推荐使 用 containerd1.5.x+, 因为 /etc/containerd/config.toml 是 version2 版本,支持多个注册中心的加速,否则只支持一个,当然也有办法解决,后边再说。
  2. rke2 是通过 /etc/rancher/rke2/registries.yaml 来生成 /var/lib/rancher/rke2/agent/etc/containerd/config.toml的, 而目前版本的 helm 不支持自定义/etc/containerd/config.toml就会导致 daemon 启动失败, 提了个 pr 还没过 https://github.com/dragonflyoss/helm-charts/pull/51,可以先手动修改
  3. 通过 d7y 的 helm 修改的 config.toml 一重启 rke2-server/agent 就会被覆盖,所以,最终要修改 /etc/rancher/rke2/registries.yaml , 而这个改动需要重启 rke2-server/agent 才生效,所以注意测试是否对业务有影响,尽量一次改完
  4. 注意污点(taints)对于 d7y daemon 的影响,如果确定要不走 d7y 的,注意别改 /etc/rancher/rke2/registries.yaml, 虽然 containerd 有 fallback,但是多少影响点时间不是么,如果有污点也有用 d7y 记得在 values 里加上对应的容忍(tolerations)
  5. 注意 d7y 的磁盘规划,以及缓存时间的设置
  6. 可以通过 多次运行 time sudo /var/lib/rancher/rke2/bin/crictl --config=/var/lib/rancher/rke2/agent/etc/crictl.yaml pull xxx:latest 镜像来评估 d7y 对于镜像的加速作用(如果是在一台执行,记得执行 sudo /var/lib/rancher/rke2/bin/crictl --config=/var/lib/rancher/rke2/agent/etc/crictl.yaml rmi --prune来清理无用镜像)
  7. containerd1.4.x 支持多注册中心的办法:1. 等 d7y 官方支持,参见 PRchore: enable range feature gate in e2e, 2,等 rancher 官方支持 containerd1.5.9 且你的集群升得动,3,改 hosts 劫持(但是不支持 fallback),4,只加速最常用的一个注册中心, 5,将其他不常用的注册中心的镜像 pull&push 到加速的注册中心里(注意别有镜像冲突)6,起两套 daemon 分别监听 65001 65002
  8. d7y 支持预热功能,但是 consoleui 版本的,暂时没测通,api 版本可以,
  9. 参见文档 Preheat API
  10. Harbor p2p 预热支持 d7y
  11. containerd 如果要配置私有镜像库加速,需要配置127.0.0.1:65001的 auth,详见 issues dragonflyoss/Dragonfly2/#1065

附赠:docker hub 转移镜像到阿里私服 bash 脚本

注意将 xxxx 替换成实际值 用法 /path/to/pull_push.sh nginx:alpine

#!/usr/bin/env bash

sudo service docker start

sudo docker login -uxxxx -pxxxxx registry.cn-zhangjiakou.aliyuncs.com

sudo docker pull $1

sudo docker tag $1 registry.cn-zhangjiakou.aliyuncs.com/xxxx/${1##*/}

sudo docker push registry.cn-zhangjiakou.aliyuncs.com/xxxx/${1##*/}

招聘小广告

山东济南的小伙伴欢迎投简历啊 加入我们 , 一起搞事情。 长期招聘,Java 程序员,大数据工程师,运维工程师,前端工程师。

参考资料

· 7 分钟阅读
anjia0532

阿里Dragonfly体验之私有registry下载(基于0.3.0)

书接上篇012-P2P加速Docker镜像分发(阿里Dragonfly) ,讲解了如何快速搭建 Dragonfly,但是访问的是公开镜像,本文主要讲解如何下载私有镜像。

实验环境

主机

类型主机名系统ipdocker version
supernoded7y-1Ubuntu Server 16.04.6 LTS X64192.168.0.7517.06.2ubuntu
clinet1d7y-2Ubuntu Server 16.04.6 LTS X64192.168.0.7617.06.2ubuntu
clinet2d7y-3Ubuntu Server 16.04.6 LTS X64192.168.0.7717.06.2ubuntu

私有registry

本次以阿里云私有镜像库为例,可以自行开通。

文档之坑

官方文档比较简单,甚至带有误导性,下意识的以为应该在dfdaemon节点上配置auth信息,并且配的是真实的私有registry,如果真这么搞了,肯定被坑。 (但是也能解释通,比较绕,dfdaemon本身就是一个伪装成registry,用来加速私有registry,那么登陆信息就应该换成dfdaemon ip,只是示例不太恰当而 已,对初学者相当不友好倒是真的)

image.png

supernode步骤

安装supernode

root@d7y-1:~# docker run --name dragonfly-supernode --restart=always \
-d -p 8001:8001 -p 8002:8002 -v /data/dragonfly/supernode:/home/admin/supernode \
registry.cn-hangzhou.aliyuncs.com/dragonflyoss/supernode:0.3.0 \
-Dsupernode.advertiseIp=192.168.0.75

root@d7y-1:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
be7fb931db0b registry.cn-hangzhou.aliyuncs.com/dragonflyoss/supernode:0.3.0 "/bin/sh -c '/root..." About a minute ago Up About a minute 0.0.0.0:8001-8002->8001-8002/tcp dragonfly-supernode

root@d7y-1:/data/dragonfly/supernode/logs# cat app.log
2019-03-30 01:04:40.065 INFO [ main] c.d.d.s.SuperNodeStarter - Starting SuperNodeStarter on be7fb931db0b with PID 9 (/supernode.jar started by root in /)
2019-03-30 01:04:40.069 INFO [ main] c.d.d.s.SuperNodeStarter - No active profile set, falling back to default profiles: default
2019-03-30 01:04:42.151 INFO [ main] c.d.d.s.c.SupernodeProperties - init local ip of supernode, use ip:192.168.0.75
2019-03-30 01:04:42.253 INFO [ main] c.d.d.s.c.SupernodeProperties - cluster members: [{"downloadPort":8001,"ip":"localhost","registerPort":8002}]
2019-03-30 01:04:42.263 INFO [ main] c.d.d.s.c.util.MonitorService - available processors count is 4
2019-03-30 01:04:42.272 ERROR [ Thread-2] c.d.d.s.c.util.MonitorService - process fields:null error
java.io.IOException: Cannot run program "tsar": error=2, No such file or directory
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
at java.lang.Runtime.exec(Runtime.java:620)
at java.lang.Runtime.exec(Runtime.java:450)
at java.lang.Runtime.exec(Runtime.java:347)
at com.dragonflyoss.dragonfly.supernode.common.util.MonitorService$1.run(MonitorService.java:56)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.io.IOException: error=2, No such file or directory
at java.lang.UNIXProcess.forkAndExec(Native Method)
at java.lang.UNIXProcess.<init>(UNIXProcess.java:247)
at java.lang.ProcessImpl.start(ProcessImpl.java:134)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1029)
... 5 common frames omitted
2019-03-30 01:04:43.507 INFO [ main] c.d.d.s.SuperNodeStarter - Started SuperNodeStarter in 3.906 seconds (JVM running for 4.59)
2019-03-30 01:04:49.472 INFO [ spring-1] c.d.d.s.s.p.PreheatServiceImpl - deleteExpiresPreheatTask, count:0

2019-03-30 01:04:42.151 INFO [ main] c.d.d.s.c.SupernodeProperties - init local ip of supernode, use ip:192.168.0.75 看,启动ip设置成功.

注意,官方的镜像没改时区,默认是UTC时间,比北京东八区早8小时。

登陆私有registry并推送镜像

root@d7y-1:~# docker login https://registry.cn-qingdao.aliyuncs.com
Username: //你阿里云账号
Password: //你阿里云密码
Login Succeeded
root@d7y-1:~# docker pull nginx:alpine
root@d7y-1:~# docker tag nginx:alpine registry.cn-qingdao.aliyuncs.com/d7y-test/nginx:alpine
root@d7y-1:~# docker push registry.cn-qingdao.aliyuncs.com/d7y-test/nginx:alpine
alpine: digest: sha256:857e6f195df0e9b497be0c7fad0f013126407aaeb71edcef66a24e8b990d94b3 size: 1153

dfdaemon 步骤

安装dfdaemon

在两台client节点分别执行如下命令

root@d7y-2:~# cat <<EOD >/etc/dragonfly.conf
[node]
address=192.168.0.75
EOD
root@d7y-2:~# docker run --name dragonfly-dfclient --restart=always \
-d -p 65001:65001 -v /root/.small-dragonfly:/root/.small-dragonfly \
-v /etc/dragonfly.conf:/etc/dragonfly.conf dragonflyoss/dfclient:v0.3.0 \
--registry=https://registry.cn-qingdao.aliyuncs.com --ratelimit 100M
Unable to find image 'dragonflyoss/dfclient:v0.3.0' locally
v0.3.0: Pulling from dragonflyoss/dfclient
169185f82c45: Pull complete
f58f64214283: Pull complete
bd8f062dc2d2: Pull complete
Digest: sha256:5bcabd5b34f4da0c2d489c8f99a23a401fb9ec57e54d4fa90457a93c5a85371f
Status: Downloaded newer image for dragonflyoss/dfclient:v0.3.0
b491e90489a584119b82ca934cf2ae087abc136f7f9de3542e14fb12bc1c7512

root@d7y-2:~# cat <<EOD >/etc/docker/daemon.json
{
"registry-mirrors": ["http://127.0.0.1:65001"]
}
EOD
root@d7y-2:~# systemctl restart docker

root@d7y-2:~# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b491e90489a5 dragonflyoss/dfclient:v0.3.0 "/dfclient/dfdaemo..." 28 seconds ago Up 4 seconds 0.0.0.0:65001->65001/tcp dragonfly-dfclient

root@d7y-2:~/.small-dragonfly/logs# cat dfdaemon.log
2019-03-30 01:18:21.331 INFO sign:1 : init...
2019-03-30 01:18:21.331 INFO sign:1 : rotate log routine start...
2019-03-30 01:18:21.338 INFO sign:1 : dfget version:
2019-03-30 01:18:21.338 ERRO sign:1 : init properties failed:open /etc/dragonfly/dfdaemon.yml: no such file or directory
2019-03-30 01:18:21.338 INFO sign:1 : init properties:{"Registries":[{"Schema":"https","Host":"registry.cn-qingdao.aliyuncs.com","Certs":null,"Regx":"(^localhost$)|(^127.0.0.1$)|(^127.0.0.1$)"}]}
2019-03-30 01:18:21.338 INFO sign:1 : init finish
2019-03-30 01:18:21.338 INFO sign:1 : start dfdaemon param: &{DfPath:/dfclient/dfget DFRepo:/root/.small-dragonfly/dfdaemon/data/ RateLimit:100M CallSystem:com_ops_dragonfly URLFilter:Signature&Expires&OSSAccessKeyId Notbs:true MaxProcs:4 Version:false Verbose:false HostIP:127.0.0.1 Port:65001 Registry:https://registry.cn-qingdao.aliyuncs.com DownRule: CertFile: KeyFile: TrustHosts:[] ConfigPath:/etc/dragonfly/dfdaemon.yml}
2019-03-30 01:18:21.338 INFO sign:1 : launch dfdaemon http server on 127.0.0.1:65001

登陆dfdaemon

root@d7y-2:~# docker login http://127.0.0.1:65001
Username: //你阿里云账号
Password: //你阿里云密码
Login Succeeded
root@d7y-2:~# cat ~/.docker/config.json
{
"auths": {
"127.0.0.1:65001": {
"auth": "zzxxxxxx="
}
}
}

pull 私有镜像

root@d7y-2:~# docker pull 127.0.0.1:65001/d7y-test/nginx:alpine
alpine: Pulling from d7y-test/nginx
8e402f1a9c57: Pull complete
56b0d9b69cc9: Pull complete
b66c8bb200cc: Pull complete
4ec77fc9c55f: Pull complete
Digest: sha256:857e6f195df0e9b497be0c7fad0f013126407aaeb71edcef66a24e8b990d94b3
Status: Downloaded newer image for 127.0.0.1:65001/d7y-test/nginx:alpine

可以通过iftop 等命令,观察流量。

其他

排错

如果有遇到其他问题,可以通过查看日志来获取更多信息。

dfdaemon log : /root/.small-dragonfly/logs/{dfclient.log,dfdaemon.log,dfserver.log}
supernode log: /home/admin/supernode/{app.log,data-gc.log,downloader.log,piece-hit.log,space-gc.log}

公开和私有registry混用

如果大量都是私有registry的话,可以在/etc/docker/daemon.json 中配置dfdaemon和加速器,如果是一半一半的话,那就干脆起两个dfdaemon就行了, 一个--registry写私有的,一个--registry写公有的,然后也是配置 /etc/docker/daemon.json

cat /etc/docker/daemon.json
{
"registry-mirrors": ["http://127.0.0.1:65001","https://xxx.mirror.aliyuncs.com"],
"dns": ["223.5.5.5"]
}

吐槽

再次吐槽一下d7y的产品很好,解决了很大问题。但是这文档,真心不是给新手看的。从未见过如此坑多且深的文档。没见过哪家quick start 写的这么复杂。

鸣谢

非常感谢钉钉群内的 d7y 的 contributor 太云-lowzj 耐心解答,从开始研究d7y开始, 遇到的很多坑都是在 太云-lowzj 帮助下蹚过去的。但是还是觉得,如果文档足够友好,肯定会减少群内被打扰的次数, 进而节省自己时间的。

image.png

招聘小广告

山东济南的小伙伴欢迎投简历啊 加入我们 , 一起搞事情。

长期招聘,Java程序员,大数据工程师,运维工程师,前端工程师。

· 7 分钟阅读
anjia0532

使用 Dragonfly 加速 Docker 镜像分发(基于 0.3.0)

介绍

如果说,微服务和容器是最佳拍档,那么模块多实例是肯定少不了。 假如没有使用类似 Google jib 等手段进行镜像分层(利用镜像缓存),势必会造成:

  • 带宽浪费:尤其是公网带宽,如果是自建 harbor,那么会容易导致单节点网卡被打满,如果用了 harbor 联邦,又会导致数据同步等运维问题。
  • 集群拉起慢:镜像下载慢,必然会导致服务拉起慢。

关于 Google jib 可以参见我另外一篇 加速和简化构建 Docker(基于 Google jib), 本文只介绍 Dragonfly + dfdaemon

Dragonfly 是阿里巴巴自研并开源的一款基于 P2P 协议的文件分发系统。除了使用 dfget 进行文件下载外,还支持 dfdaemon 进行 docker 镜像下载。

关于 Dragonfly 的镜像分发的原理性说明,可参见直击阿里双 11 神秘技术:PB 级大规模文件分发系统“蜻蜓” ,文中介绍很详细,此处不多说明。

实验环境

类型系统ipdocker version
supernodeUbuntu Server 16.04.6 LTS X64192.168.0.4417.06.2~ce-0~ubuntu
clinet1Ubuntu Server 16.04.6 LTS X64192.168.0.4017.06.2~ce-0~ubuntu
clinet2Ubuntu Server 16.04.6 LTS X64192.168.0.4517.06.2~ce-0~ubuntu
注意

如果是实验目的,建议用 Vmware,并且在关键操作时备份快照(比如,刚装完环境,升级完 PS 和.Net 后),这样能够及时,干净的还原现场, 节省每次重装系统导致的时间浪费安装吐槽一下 Dragonfly 的文档,简直让人不知所以。结合 issues + 钉钉群内请教,遂整理出最简使用文档。

supernode

可选:给 supernode 增加 docker 加速器,可以参考 https://cr.console.aliyun.com/cn-hangzhou/instances/mirrors ,如果不需要,可以去掉。

$ cat << EOD >/etc/docker/daemon.json
{
"registry-mirrors": ["https://xxxx.mirror.aliyuncs.com"]
}
EOD
$ systemctl restart docker
$ docker run --name dragonfly-supernode --restart=always -d -p 8001:8001 -p 8002:8002 \
-v /data/dragonfly/supernode:/home/admin/supernode registry.cn-hangzhou.aliyuncs.com/dragonflyoss/supernode:0.3.0 \
-Dsupernode.advertiseIp=172.60.20.44
说明
  • --restart=always 在容器退出时,自动重启容器,防止异常 kill 或者 oom 导致的异常退出
  • registry.cn-hangzhou.aliyuncs.com/dragonflyoss/supernode:0.3.0 dragonfly 的 supernode 目前没有 docker hub 镜像,只能用阿里云的 -v /data/dragonfly/supernode:/home/admin/supernode 将 supernode 的 data dir 挂载到宿主机上
  • -Dsupernode.advertiseIp=172.60.20.44 设置 clinet 可以访问的 supernode ip,这是一个大坑。如果不设置,有可能会导致 client 无法连接 supernode,届时,docker pull 会走 clinet 的网络,从真实的 registry 直接下载镜像

image.png

dfdaemon

$ cat <<EOD >/etc/dragonfly.conf
[node]
address=192.168.0.44
EOD
$ docker run --name dragonfly-dfclient --restart=always -d -p 65001:65001 \
-v /root/.small-dragonfly:/root/.small-dragonfly \
-v /etc/dragonfly.conf:/etc/dragonfly.conf dragonflyoss/dfclient:v0.3.0 \
--registry=https://xxx.mirror.aliyuncs.com --ratelimit 100M

$ cat <<EOD >/etc/docker/daemon.json
{
"registry-mirrors": ["http://127.0.0.1:65001"]
}
EOD

$ systemctl restart docker
解释
  • 在 /etc/dragonfly.conf 中配置 client 可以访问的 supernode 的 ip 地址,但是,目前官方没有做 HA,supernode 没法组集群,撑死算是联邦, 不能共享文件信息,而且最坑的是,快速开始里,中英文均未提供需要配置此文件, 等有所提及(我都是被坑完后,用关键词在 d7y 的 org 里搜索,类似知道答案后,找出处 手动[捂脸]
  • -v /root/.small-dragonfly:/root/.small-dragonfly ,将容器中的关键目录挂载到宿主机上,防止重启或者镜像升级时,数据丢失
  • --registry=https://xxx.mirror.aliyuncs.com 从何处下载镜像,可以写 harbor 地址,也可以写加速器地址。默认是 https://index.docker.io ,但是,因为国内网络原因,会导致大概率性失败。很灵异。 而官方文档是写的 --registry https://xxx.xx.x 不能算是坑,但是,对于 docker 不熟悉的,往往会不知能不能用加速器。
  • --ratelimit 100M 是限速,默认是 20M ,这肯定不算坑哈,这是正常特性,但是,文档是有误的 -ratelimit 而实际是 --ratelimit ,如果不改此参数,会发现,下载很慢。
  • 修改/etc/docker/daemon.json 是为了让 docker engine 走 dfdaemon
  • systemctl restart docker 是为了让 daemon 生效

测试

大文件测试

docker pull anjia0532/kubeflow-images-public.tensorflow-1.6.0-notebook-gpu:v20180604-b3733835

可以通过 iftop 等软件,查看带宽使用情况判断是否生效,也可以通过查看日志来判断。 image.png

但是会经常性的出现 error pulling image configuration: received unexpected HTTP status: 502 Bad Gateway

最后

需要结合实际情况,配置相关参数,比如,文件失效时间,用来平衡文件有效期及磁盘使用量。

参考资料

招聘小广告

山东济南的小伙伴欢迎投简历啊 加入我们 , 一起搞事情。

长期招聘,Java 程序员,大数据工程师,运维工程师,前端工程师。