K8S多集群镜像分发:dragonfly2(docker)

你将在本文学到什么?

  • 多k8s集群镜像分发方案
  • dragonfly2的理解
  • harbor的预热机制
  • dragonfly2的使用以及排障

K8S多集群镜像分发问题

在边缘云架构的生产环境下,演进过程中,一开始的镜像分发方案如下:K8S多集群镜像分发:dragonfly2(docker)每个边缘集群都存在节点的harbor仓库,进行缓存操作,当边缘集群集体崩溃重启过程中,不会引发所有worker上中心仓拉取镜像。 带来的问题是:

  • 每套环境一个harbor,引起的部署,维护的困难。
  • harbor的复制策略比较简单,无法单例执行。并且重试非常占用中心仓带宽。

那么面对这种场景存在以下两种方案:

  • harbor仓库分级复制策略
  • P2P镜像分发策略

harbor仓库分级复制策略,存在以下问题:

  • 如何进行分级划分。
  • 升级过程,如果节点所处的是第三级,如何触发复制策略加速缓存。
  • 每个节点增加了安全暴露面。
  • 节点的不断增加,后续是否需要3级,4级,5级,维护管理成本指数增加。

所以在项目中,我的选择是 dragonfly2的P2P镜像分发策略。

dragonfly2是什么

在理解过程中,首先需要搞懂以下几个问题:

  1. p2p是什么?
  2. 镜像的分层拉取策略。

什么是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架构

K8S多集群镜像分发:dragonfly2(docker)组件包括: Manager: 多dragonfly2调度节点进行管理,提供了UI管理界面,镜像预热机制。 Scheduler:

  • 基于机器学习的多场景自适应智能 P2P 节点调度, 为当前下载节点选择最优父节点。
  • 构建 P2P 下载网络的有向无环图。
  • 根据不同特征值评估节点下载能力, 剔除异常节点。
  • 当下载失败情况,主动通知 Dfdaemon 进行回源下载。

DfDaemon:(分为peer, seed peer)

  • 基于 GRPC 提供下载功能, 并提供多源适配能力。
  • 开启 Seed Peer 模式可以作为 P2P 集群中回源下载节点, 也就是整个集群中下载的根节点。
  • 为镜像仓库或者其他 HTTP 下载任务提供代理服务。
  • 下载任务基于 HTTP 或 HTTPS 或其他自定义协议。

使用场景流程说明如下:(当需要下载某一层镜像时)

  1. docker在请求下载镜像时,通过配置docker http proxy代理,将请求转发到peer节点。
  2. peer节点进行本地缓存判断,查看是否存在该层镜像;
    1. 是,则直接响应。如图
K8S多集群镜像分发:dragonfly2(docker)
image.png
  1. 如果当前peer不存在,将当前请求转发到scheduler;
  2. scheduler将判断seed peer中是否存在:
    1. 是,则将对应的地址返回,通知peer去指定的seed peer拉取资源,如图:
K8S多集群镜像分发:dragonfly2(docker)
image.png
  1. 否,则通知seed peer 回源拉取,拉取成功后,peer再进行拉取。

K8S多集群镜像分发:dragonfly2(docker)最长路径: docker -> peer -> seed peer -> 源站 -> seed peer -> peer -> docker

dragonfly操作实践(docker版)

由于k8s版本过于简单,封装了docker手动操作部分,这里讲源码版本如何使用。源码安装从上面已经了解到:docker pull通过http proxy 配置即可通过peer拉取镜像,那么操作就简单了。 步骤如下:

  1. 配置docker;
  2. 安装依赖组件,mysql, redis, jaeger(为了研究操作路径以及代码);
  3. 配置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配置如下配置分发实例K8S多集群镜像分发:dragonfly2(docker)为对应的项目配置P2P策略K8S多集群镜像分发:dragonfly2(docker)基于事件,在有新的镜像时,会通知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

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!