一、Dragonfly 的介绍

1.1 介绍

Dragonfly是一个开源的P2P镜像和文件分发系统,主要用于加速容器镜像和文件的分发。
它通过P2P(点对点)传输方式,极大地提高了镜像和文件的分发效率,并减少了带宽消耗和对中心化存储的依赖。
在应用分发、缓存分发、日志分发和镜像分发等领域被大规模使用。

在大型容器化环境中,容器镜像的分发是一个关键环节。
传统的镜像拉取方式存在速度慢、带宽消耗大等问题,特别是在大规模集群中,镜像拉取延迟会对应用的启动速度
和整体性能产生显著影响。为了解决这些问题,可以使用Dragonfly进行镜像预热优化分发。

Dragonfly提供高效、稳定、安全的基于 P2P 技术的文件分发和镜像加速系统,并且是云原生架构中镜像加速领域的
标准解决方案以及最佳实践。
     目前,主要专注于:
     简单:定义明确、面向用户的 API(HTTP),对所有容器引擎均无侵入性;
     高效:种子对等支持,基于P2P的文件分发,节省企业带宽;
     智能化:主机级限速,主机检测智能流量控制;
     安全:阻止传输加密,支持HTTPS连接。

Dragonfly现在为云原生计算机基金会托管作为孵化级项目。


官网

https://d7y.io/

文档

https://d7y.io/zh/docs/next/

github

https://github.com/dragonflyoss/Dragonfly2

1.2 工作原理

镜像预热:在实际使用镜像前,先将镜像从远程仓库拉取到本地缓存,并在P2P网络中分发给其他节点。

P2P传输:在节点之间,通过P2P方式进行镜像块的分发,避免集中拉取带来的网络瓶颈。

分片下载:将大文件或镜像分成多个小块进行并行下载,进一步提高下载速度。

本地缓存:每个节点都会将拉取的镜像块缓存到本地,后续节点可以直接从本地缓存中获取数据,提高数据访问速度。


1.3 优势

高效的镜像分发:通过P2P方式进行镜像块分发,避免了集中拉取的网络瓶颈,提高镜像拉取速度。

节省带宽:通过节点间的P2P传输,减少对中心仓库的带宽消耗,优化网络资源利用。

快速镜像预热:通过预先将镜像拉取到本地缓存,减少应用启动时的镜像拉取延迟。

高可用性:即使部分节点失效,其他节点仍能通过P2P网络获取数据,保证系统的高可用性。


1.4 架构

Dragonfly架构主要分为四部分Manager,Scheduler,Seed Peer以及Peer各司其职组成P2P下载网络。

Manager:Manager在多P2P集群部署的时候扮演管理者的角色。主要提供动态配置管理以及数据收集等功能。也包含了前端控制台,方便用户进行可视化操作集群。

Scheduler:为当前下载节点寻找一组最优父节点。在适当时候触发Seed Peer进行回源下载或让Peer进行回源下载。

Seed Peer:提供上传跟下载能力。并提供可以被Scheduler主动触发回源,可以作为P2P节点中的根节点。

Peer:提供上传跟下载能力。

第十九节  Dragonfly镜像加速_flink

Manager组件:

1、用户管理:提供RBAC及用户态管理功能;

2、维护P2P集群关系:Manager管理整个P2P集群关系,保证Seed Peer集群和Scheduler集群为1:N的关系,

并且选择最优Scheduler提供Dfdaemon使用;

3、异步任务管理:提供统一异步任务管理,支持预热等功能;

4、监控集群:监控整个P2P集群的运行状态,剔除异常节点;

5、可视化UI:提供可视化管理界面,方便管理;


scheduler组件:

1、调度:基于Peer之间的网络、带宽流量等进行调度,组建有向无循环图为当前调度Peer寻找最优父节点

2、回源:通过当前Peer下载情况,若异常或无父节点则主动通知Peer回源

3、任务状态:维护Peer中下载的任务状态,主动推进其状态变更

4、下载任务优化:针对不同的下载任务进行优化处理,分为Tiny、Small、Normal类型

5、预热:实现镜像和对象存储的预热,文件同步任务分发


Seed Peer组件:

Dfdaemon打开种子对等模式可用作P2P集群中的回源下载对等点,

这是整个集群中用于下载的根对等方。

P2P客户端提供上传和下载功能。

当集群内任务首次下载,Scheduler会触发Seed Peer回源。

提供主动触发回源能力,可以作为P2P节点中的根节点



Peer组件:

使用dfdaemon部署,基于c/s架构,提供命令下载工具,以及提供任务下载功能的

正在运行的守护程序。P2P客户端,提供上传和下载功能


Dfget组件:

客户端命令行下载工具,和Daemon之间为c/S模式

Dragonfly怎么运行

当下载一个镜像或文件时,通过 Peer 的 HTTP Proxy 将下载请求代理到 Dragonfly。

Peer 首先会向 Scheduler 注册 Task, Scheduler 会查看 Task 的信息,判断 Task

是否在 P2P 集群内第一次下载, 如果是第一次下载优先触发 Seed Peer 进行回源下载,

并且下载过程中对 Task 基于 Piece 级别切分。注册成功后 Peer 会和 Scheduler 建立

双向流, 然后将 Seed Peer 调度给 Peer 进行下载。Seed Peer 和 Peer 之间下载传输

基于 Piece 级别进行流式传输。Peer 每下载成功一个 Piece, 会将信息上报给 Scheduler  

供下次调度使用。如果 Task 在 P2P 集群内非第一次下载,那么 Scheduler 会调度其他 Peer  

给当前 Peer 下载。 Peer 从不同的 Peer 下载 Piece,拼接并返回整个文件,那么 P2P 下载就完成了。

第十九节  Dragonfly镜像加速_docker_02



二、Dragonfly 的部署

2.1 拉取代码部署

拉取源码

Dragonfly支持docker-compose、Helm、源码三种安装方式。

因为Harbor是使用docker-compose部署的,所以本处也使用docker-compose部署Dragonfly

下载最新版本:
git  clone  https://github.com/dragonflyoss/Dragonfly2.git
cd   /root/Dragonfly2/deploy/docker-compose/

声明环境变量指定当前主机IP
export IP=192.168.80.28  &&  echo $IP

第十九节  Dragonfly镜像加速_docker_03

第十九节  Dragonfly镜像加速_docker_04

修改docker 配置文件

cat /etc/docker/daemon.json
-----------------------
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "registry-mirrors": [
    "https://docker.1panel.live",
    "http://192.168.80.28",      //新增
    "https://docker.m.daocloud.io",
    "https://huecker.io"
  ],
  "insecure-registries":["http://192.168.80.28"],  //改为harbor机器IP
  "max-concurrent-downloads": 10,
  "log-driver": "json-file",
  "log-level": "warn",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
    },
  "data-root": "/var/lib/docker"
}
----------------------------------
重新启动docker
systemctl daemon-reload
systemctl restart docker

重新启动harbor
cd  /usr/local/harbor/
docker-compose down
docker-compose  up -d
docker-compose ps

修改Dragonfly中的docker-compose.yaml文件

cd  /root/Dragonfly2/deploy/docker-compose
cp  docker-compose.yaml   docker-compose.yaml.bak

vim docker-compose.yaml
----------------------
version: "3"
services:
  redis:
    image: redis:6-alpine
    container_name: redis_dragonfly   ///改名字,避免redis冲突
    command: >
      --requirepass dragonfly
    healthcheck:
      test: ["CMD", "redis-cli", "-a", "dragonfly", "ping"]
      interval: 1s
      timeout: 2s
      retries: 30
    ports:
      - 6379:6379

  mysql:
    image: mariadb:10.6
    container_name: dragonfly-mysql
    environment:
      - MARIADB_USER=dragonfly
      - MARIADB_PASSWORD=dragonfly
      - MARIADB_DATABASE=manager
      - MARIADB_ALLOW_EMPTY_ROOT_PASSWORD=yes
    healthcheck:
      test: ["CMD-SHELL", "mysqladmin status"]
      interval: 1s
      timeout: 2s
      retries: 30
    ports:
      - 3306:3306

  manager:
    image: dragonflyoss/manager:latest
    container_name: dragonfly-manager
    depends_on:
      - redis
      - mysql
    restart: always
    volumes:
      - ./log/manager:/var/log/dragonfly/manager
      - ./config/manager.yaml:/etc/dragonfly/manager.yaml:ro
    healthcheck:
      test: ["CMD-SHELL", "/bin/grpc_health_probe -addr=:65003 || exit 1"]
      interval: 1s
      timeout: 2s
      retries: 30
    ports:
      - 65003:65003
      - 8080:8080

  dfdaemon:
    image: dragonflyoss/dfdaemon:latest
    depends_on:
      - manager
      - scheduler
      - seed-peer
    container_name: dragonfly-seed-peer
    restart: always
    healthcheck:
      test: ["CMD-SHELL", "/bin/grpc_health_probe -addr=:65000 || exit 1"]
      interval: 1s
      timeout: 2s
      retries: 30
    volumes:
      - ./log/peer:/var/log/dragonfly/daemon
      - ./config/dfget.yaml:/etc/dragonfly/dfget.yaml:ro
    ports:
      - 65000:65000
      - 65001:65001
      - 65002:65002

  scheduler:
    image: dragonflyoss/scheduler:latest
    depends_on:
      - manager
    container_name: dragonfly-scheduler
    restart: always
    healthcheck:
      test: ["CMD-SHELL", "/bin/grpc_health_probe -addr=:8002 || exit 1"]
      interval: 1s
      timeout: 2s
      retries: 30
    volumes:
      - ./log/scheduler:/var/log/dragonfly/scheduler
      - ./config/scheduler.yaml:/etc/dragonfly/scheduler.yaml:ro
    ports:
      - 8002:8002

  seed-peer:
    image: dragonflyoss/dfdaemon:latest
    depends_on:
      - manager
      - scheduler
    container_name: dragonfly-dfdaemon
    restart: always
    healthcheck:
      test: ["CMD-SHELL", "/bin/grpc_health_probe -addr=:65006 || exit 1"]
      interval: 1s
      timeout: 2s
      retries: 30
    volumes:
      - ./log/seed-peer:/var/log/dragonfly/daemon
      - ./config/seed-peer.yaml:/etc/dragonfly/dfget.yaml:ro
    ports:
      - 65006:65006
      - 65007:65007
      - 65008:65008
--------------------------------------
运行脚本,执行安装
./run.sh

cd  /root/Dragonfly2/deploy/docker-compose
docker-compose down
docker-compose  up -d
docker-compose 

第十九节  Dragonfly镜像加速_flink_05


2.2 测试

打开页面测试:
http://192.168.80.28:8080

用户名:root     
密码:   dragonfly

第十九节  Dragonfly镜像加速_flink_06

第十九节  Dragonfly镜像加速_redis_07

第十九节  Dragonfly镜像加速_redis_08

第十九节  Dragonfly镜像加速_flink_09

第十九节  Dragonfly镜像加速_docker_10


三、与harbor 集成

第十九节  Dragonfly镜像加速_redis_11

第十九节  Dragonfly镜像加速_flink_12

第十九节  Dragonfly镜像加速_flink_13

p2p预热

第十九节  Dragonfly镜像加速_docker_14

第十九节  Dragonfly镜像加速_flink_15

第十九节  Dragonfly镜像加速_flink_16

修改镜像绑定IP
vim  /etc/docker/daemon.json
-------------------------------
"insecure-registries":["http://192.168.80.28"],
-------------------------------
service docker restart
************由于本次测试都在28机器上,不再修改

登录仓库
docker login http://192.168.80.28
用户名/密码:
admin/123456

第十九节  Dragonfly镜像加速_docker_17

第十九节  Dragonfly镜像加速_redis_18

docker  pull  flink:latest

docker  tag   docker.io/library/flink:latest   192.168.80.28/lyc-images-project/flink:latest

docker  push   192.168.80.28/lyc-images-project/flink:latest

第十九节  Dragonfly镜像加速_flink_19

第十九节  Dragonfly镜像加速_redis_20

第十九节  Dragonfly镜像加速_redis_21

那我们删掉后,重新再下载/推送1次,看是否加速?

删掉harbor库的finlk镜像

第十九节  Dragonfly镜像加速_redis_22

删掉镜像

第十九节  Dragonfly镜像加速_docker_23

重新pull镜像,查看是否加速下载

docker  pull  flink:latest

docker  tag   docker.io/library/flink:latest   192.168.80.28/lyc-images-project/flink:latest

docker  push   192.168.80.28/lyc-images-project/flink:latest

第十九节  Dragonfly镜像加速_flink_24

第十九节  Dragonfly镜像加速_flink_25

总结

测试下来,第二次拉取镜像确实比第一次要快,P2P加速还是有效果的,尤其是拉取的镜像比较大的情况下。