你将在本文学到什么?
-
多k8s集群镜像分发方案 -
dragonfly2的理解 -
harbor的预热机制 -
dragonfly2的使用以及排障
K8S多集群镜像分发问题
在边缘云架构的生产环境下,演进过程中,一开始的镜像分发方案如下:每个边缘集群都存在节点的harbor仓库,进行缓存操作,当边缘集群集体崩溃重启过程中,不会引发所有worker上中心仓拉取镜像。 带来的问题是:
-
每套环境一个harbor,引起的部署,维护的困难。 -
harbor的复制策略比较简单,无法单例执行。并且重试非常占用中心仓带宽。
那么面对这种场景存在以下两种方案:
-
harbor仓库分级复制策略 -
P2P镜像分发策略
harbor仓库分级复制策略,存在以下问题:
-
如何进行分级划分。 -
升级过程,如果节点所处的是第三级,如何触发复制策略加速缓存。 -
每个节点增加了安全暴露面。 -
节点的不断增加,后续是否需要3级,4级,5级,维护管理成本指数增加。
所以在项目中,我的选择是 dragonfly2的P2P镜像分发策略。
dragonfly2是什么
在理解过程中,首先需要搞懂以下几个问题:
-
p2p是什么? -
镜像的分层拉取策略。
什么是P2P
此p2p不是金融圈里面经常暴雷的,而是peer to peer网络技术。有几个比较突出的使用:
-
迅雷 -
某夭折的播放器(快B) -
以及国内一些视频网站白嫖用户网络的P2P CDN。
为什么需要P2P网络?P2P网络对应的就是传统网络传输C/S模式,传统模式下,所有的客户端请求数据下载都需要访问服务器,那么服务器的压力会非常大,当客户端多的情况下,网络带宽也存在问题。
★
来自wiki百科:对等式网络(英语:peer-to-peer, 简称P2P),又称点对点技术,是去中心化、依靠用户群(peers)交换信息的互联网体系,它的作用在于,减低以往网路传输中的节点,以降低资料遗失的风险。与有中心服务器的中央网络系统不同,对等网络的每个用户端既是一个节点,也有服务器的功能,任何一个节点无法直接找到其他节点,必须依靠其户群进行信息交流。
”
镜像分层拉取
docker镜像通过分层进行资源共享,通过copy-on-write完成文件隔离。在执行pull的时候,可以看到
c1c792ed5250: Already exists
fcac137f6aa5: Already exists
c31aa26549dd: Already exists
04699d7e44fb: Pull complete
已经存在以及拉取动作,可以分析得出,在docker pull时,先会判断本地是否存在当前层,如果没有则从远端服务器拉取层。
dragonfly2架构
组件包括: Manager: 多dragonfly2调度节点进行管理,提供了UI管理界面,镜像预热机制。 Scheduler:
-
基于机器学习的多场景自适应智能 P2P 节点调度, 为当前下载节点选择最优父节点。 -
构建 P2P 下载网络的有向无环图。 -
根据不同特征值评估节点下载能力, 剔除异常节点。 -
当下载失败情况,主动通知 Dfdaemon 进行回源下载。
DfDaemon:(分为peer, seed peer)
-
基于 GRPC 提供下载功能, 并提供多源适配能力。 -
开启 Seed Peer 模式可以作为 P2P 集群中回源下载节点, 也就是整个集群中下载的根节点。 -
为镜像仓库或者其他 HTTP 下载任务提供代理服务。 -
下载任务基于 HTTP 或 HTTPS 或其他自定义协议。
使用场景流程说明如下:(当需要下载某一层镜像时)
-
docker在请求下载镜像时,通过配置docker http proxy代理,将请求转发到peer节点。 -
peer节点进行本地缓存判断,查看是否存在该层镜像; -
是,则直接响应。如图

-
如果当前peer不存在,将当前请求转发到scheduler; -
scheduler将判断seed peer中是否存在: -
是,则将对应的地址返回,通知peer去指定的seed peer拉取资源,如图:

-
否,则通知seed peer 回源拉取,拉取成功后,peer再进行拉取。
最长路径: docker -> peer -> seed peer -> 源站 -> seed peer -> peer -> docker
dragonfly操作实践(docker版)
由于k8s版本过于简单,封装了docker手动操作部分,这里讲源码版本如何使用。源码安装从上面已经了解到:docker pull通过http proxy 配置即可通过peer拉取镜像,那么操作就简单了。 步骤如下:
-
配置docker; -
安装依赖组件,mysql, redis, jaeger(为了研究操作路径以及代码); -
配置manager, scheduler, seed peer, peer;
详细步骤如下:
配置docker
-
配置http proxy
vi /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://127.0.0.1:65001"
Environment="HTTPS_PROXY=http://127.0.0.1:65001"
-
私有仓库的话,配置忽略证书insecure-registries;
vi /etc/docker/daemon.json
{
"insecure-registries": ["your.private.registry"]
}
重启docker:systemctl restart docker;
安装依赖
mysql:
docker run -d --name dragonfly-mysql --restart=always -p 3306:3306
--env MARIADB_USER="dragonfly"
--env MARIADB_PASSWORD="dragonfly"
--env MARIADB_DATABASE="manager"
--env MARIADB_ALLOW_EMPTY_ROOT_PASSWORD="yes"
mariadb:10.6
redis:
docker run -d --name dragonfly-redis --restart=always -p 6379:6379
redis:6-alpine
--requirepass "dragonfly"
jaeger:
docker run --rm --name jaeger
-e COLLECTOR_ZIPKIN_HOST_PORT=:9411
-p 6831:6831/udp
-p 6832:6832/udp
-p 5778:5778
-p 16686:16686
-p 4317:4317
-p 4318:4318
-p 14250:14250
-p 14268:14268
-p 14269:14269
-p 9411:9411
jaegertracing/all-in-one:1.48
配置组件
私有仓库的情况下,需要给dragonfly代理也配置一个私有证书;如果不配置,在拉取过程中,会偶发pull失败的情况,报错如下:
http: server gave HTTP response to HTTPS client
生成一个 CA 证书私钥。
openssl genrsa -out ca.key 2048
打开 openssl 配置文件 openssl.conf。设置 basicConstraints 为 true,然后您就能修改这些值。
[ req ]
#default_bits = 2048
#default_md = sha256
#default_keyfile = privkey.pem
distinguished_name = req_distinguished_name
attributes = req_attributes
extensions = v3_ca
req_extensions = v3_ca
[ req_distinguished_name ]
countryName = Country Name (2 letter code)
countryName_min = 2
countryName_max = 2
stateOrProvinceName = State or Province Name (full name)
localityName = Locality Name (eg, city)
0.organizationName = Organization Name (eg, company)
organizationalUnitName = Organizational Unit Name (eg, section)
commonName = Common Name (eg, fully qualified host name)
commonName_max = 64
emailAddress = Email Address
emailAddress_max = 64
[ req_attributes ]
challengePassword = A challenge password
challengePassword_min = 4
challengePassword_max = 20
[ v3_ca ]
basicConstraints = CA:TRUE
生成 CA 证书。
openssl req -new -key ca.key -nodes -out ca.csr -config openssl.conf
openssl x509 -req -days 36500 -extfile openssl.conf
-extensions v3_ca -in ca.csr -signkey ca.key -out ca.crt
配置只说明需要改的地方。
配置peer
jaeger: "http://127.0.0.1:14268/api/traces"
console: true # 打开可从窗口查看日志
scheduler: # 配置调度器
..... 省略
netAddrs:
- type: tcp
addr: 127.0.0.1:8002
proxy:
security:
insecure: true
tcpListen:
listen: 0.0.0.0
port: 65001
proxies:
- regx: blobs/sha256.*
hijackHTTPS:
# CA certificate's path used to hijack https requests
cert: ca.crt
key: ca.key
hosts:
- regx: your.private.registry
insecure: true
配置seed peer
jaeger: "http://127.0.0.1:14268/api/traces"
console: true # 打开可从窗口查看日志
scheduler:
enable: true
netAddrs:
- type: tcp
addr: 127.0.0.1:65003
# scheduler list refresh interval
refreshInterval: 10s
seedPeer:
# Dfdaemon enabled seed peer mode.
enable: true
# Seed peer type includes super, strong and weak.
type: super
# Seed peer cluster id.
clusterID: 1 # 全局唯一
配置scheduler
jaeger: "http://127.0.0.1:14268/api/traces"
console: true # 打开可从窗口查看日志
# Manager configuration.
manager:
# 配置manager 地址
addr: "127.0.0.1:65003"
# schedulerClusterID cluster id to which scheduler instance belongs.
schedulerClusterID: "1"
database: ##!!!!!! 必须和manager同一个redis
# Redis configuration.
redis:
addrs:
- "127.0.0.1:6379"
# Redis username.
username: ''
# Redis password.
password: dragonfly
# Redis brokerDB name.
brokerDB: 1
# Redis backendDB name.
backendDB: 2
server:
# # Advertise ip.
advertiseIP: 127.0.0.1
# # Listen ip.
# listenIP: 0.0.0.0
# Port is the ip and port scheduler server listens on.
port: 8002
配置manager
server:
# GRPC server configure.
grpc:
advertiseIP: 127.0.0.1
port:
start: 65003
end: 65003
# REST server configure
rest:
# REST server address
addr: :8888
# Database info used for server.
database:
# Database type, supported types include mysql, mariadb and postgres.
type: mysql
# Mysql configure.
mysql:
user: dragonfly
password: dragonfly
host: 127.0.0.1
port: 3306
dbname: manager
migrate: true
redis:
# Redis addresses.
addrs:
- "127.0.0.1:6379"
password: dragonfly
# Redis DB name.
db: 0
# Redis brokerDB name.
brokerDB: 1
# Redis backendDB name.
backendDB: 2
job:
preheat:
registryTimeout: 1m
tls: ##!!!!!预热必须将harbor仓库的证书放在这
caCert: "/etc/docker/certs.d/your.private.registry/ca.crt"
jaeger: "http://127.0.0.1:14268/api/traces"
console: true # 打开可从窗口查看日志
harbor预热机制
预热:顾名思义,需要使用的时候,它已经是可以使用的状态了。如,电热毯在我们上床前,它已经是热的了。对于我们harbor的使用场景,则是在k8s需要使用镜像的时候,harbor已经以前将镜像分发到了对应集群内了。(全网都找不到对应的概念,只能靠自己理解了)
如何使用预热
dragonfly2的使用逻辑如下: harbor配置策略–> 通知manager–>查询现有活动的scheduler集群–>创建任务–>scheduler调用seedpeer拉取镜像。
harbor配置如下配置分发实例为对应的项目配置P2P策略
基于事件,在有新的镜像时,会通知manager。
其他问题
我们怎么判断当前的镜像层已经缓存到了本地?dfdaemon将缓存默认存放在/var/lib/dragonfly目录下,名称为task名称; 通过查看源码,task名称的来源为:func taskIDV1(url string, meta *commonv1.UrlMeta, ignoreRange bool) 。 即对每一层算法计算出来的。 快速:可直接查看对应的日志即可。
原文始发于微信公众号(小唐云原生):K8S多集群镜像分发:dragonfly2(docker)
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/247524.html