• 使用DragonFly进行智能镜像分发


    Dragonfly 是一款基于 P2P 的智能镜像和文件分发工具。它旨在提高文件传输的效率和速率,最大限度地利用网络带宽,尤其是在分发大量数据时,例如应用分发、缓存分发、日志分发和镜像分发。


    在阿里巴巴,Dragonfly 每个月会被调用 20 亿次,分发的数据量高达 3.4PB。Dragonfly 已成为阿里巴巴基础设施中的重要一环。


    尽管容器技术大部分时候简化了运维工作,但是它也带来了一些挑战:例如镜像分发的效率问题,尤其是必须在多个主机上复制镜像分发时。


    Dragonfly 在这种场景下能够完美支持 Docker 和 PouchContainer。它也兼容其他格式的容器。相比原生方式,它能将容器分发速度提高 57 倍,并让 Registry 网络出口流量降低 99.5%。
    Dragonfly 能让所有类型的文件、镜像或数据分发变得简单而经济。


    更多请通过官方文档了解。

    纯Docker部署

    这里采用多机部署,方案如下:

    应用 IP
    服务端 172.17.100.120
    客户端 172.17.100.121
    客户端 172.17.100.122

    部署服务端

    以docker方式部署,命令如下:

    docker run -d --name supernode --restart=always -p 8001:8001 -p 8002:8002 
        dragonflyoss/supernode:0.3.0 -Dsupernode.advertiseIp=172.17.100.120
    

    部署客户端

    准备配置文件
    Dragonfly 的配置文件默认位于 /etc/dragonfly 目录下,使用容器部署客户端时,需要将配置文件挂载到容器内。
    为客户端配置 Dragonfly Supernode 地址:

    cat <<EOD > /etc/dragonfly/dfget.yml
    nodes:
        - 172.17.100.120
    EOD
    

    启动客户端
    docker run -d --name dfclient --restart=always -p 65001:65001 
        -v /etc/dragonfly:/etc/dragonfly 
        dragonflyoss/dfclient:v0.3.0 --registry https://index.docker.io
    

    registry是仓库地址,这里使用的官方仓库

    修改Docker Daemon配置

    我们需要修改 Dragonfly 客户端机器(dfclient0, dfclient1)上 Docker Daemon 配置,通过 mirror 方式来使用 Dragonfly 进行镜像的拉取。
    在配置文件 /etc/docker/daemon.json 中添加或更新如下配置项:

    {
      "registry-mirrors": ["http://127.0.0.1:65001"]
    }
    

    然后重启Docker

    systemctl restart docker
    

    拉取镜像测试

    在任意一台客户端上进行测试,比如:

    docker pull tomcat
    

    验证

    查看client端的日志,如果输出如下,则表示是通过DragonFly来传输的。

    docker exec dfclient grep 'downloading piece' /root/.small-dragonfly/logs/dfclient.log
    
    2020-06-20 15:56:49.813 INFO sign:146-1592668602.159 : downloading piece:{"taskID":"4d977359836129ce2eec4b8418a7042c47db547a239e2a577ddc787ee177289c","superNode":"172.17.100.120","dstCid":"cdnnode:172.17.100.120~4d977359836129ce2eec4b8418a7042c47db547a239e2a577ddc787ee177289c","range":"0-4194303","result":503,"status":701,"pieceSize":4194304,"pieceNum":0}
    

    如果需要查看镜像是否通过其他 peer 节点来完成传输,可以执行以下命令:

    docker exec dfclient grep 'downloading piece' /root/.small-dragonfly/logs/dfclient.log | grep -v cdnnode
    

    如果以上命令没有输出结果,则说明镜像没有通过其他peer节点完成传输,否则说明通过其他peer节点完成传输。

    在Kubernetes中部署

    服务端以Deployment的形式部署

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: supernode
      name: supernode
      namespace: kube-system
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: supernode
      template:
        metadata:
          labels:
            app: supernode
          annotations:
            scheduler.alpha.kubernetes.io/critical-pod: ""
        spec:
          containers:
          - image: dragonflyoss/supernode:0.3.0
            name: supernode
            ports:
            - containerPort: 8080
              hostPort: 8080
              name: tomcat
              protocol: TCP
            - containerPort: 8001
              hostPort: 8001
              name: register
              protocol: TCP
            - containerPort: 8002
              hostPort: 8002
              name: download
              protocol: TCP
            volumeMounts:
            - mountPath: /etc/localtime
              name: ltime
            - mountPath: /home/admin/supernode/logs/
              name: log
            - mountPath: /home/admin/supernode/repo/
              name: data
          hostNetwork: true
          dnsPolicy: ClusterFirstWithHostNet
          restartPolicy: Always
          tolerations:
          - effect: NoExecute
            operator: Exists
          - effect: NoSchedule
            operator: Exists
          nodeSelector:
            node-role.kubernetes.io/master: ""
          volumes:
          - hostPath:
              path: /etc/localtime
              type: ""
            name: ltime
          - hostPath:
              path: /data/log/supernode
              type: DirectoryOrCreate
            name: log
          - hostPath:
              path: /data/supernode/repo/
              type: DirectoryOrCreate
            name: data
    
    ---
    kind: Service
    apiVersion: v1
    metadata:
      name: supernode
      namespace: kube-system
    spec:
      selector:
        app: supernode
      ports:
      - name: register
        protocol: TCP
        port: 8001
        targetPort: 8001
      - name: download
        protocol: TCP
        port: 8002
        targetPort: 8002
    

    以hostNetwork的形式部署在master上。

    部署过后可以看到supernode已经正常启动了。

    # kubectl get pod -n kube-system | grep supernode
    supernode-86dc99f6d5-mblck                 1/1     Running   0          4m1s
    


    客户端以daemonSet的形式部署,yaml文件如下:

    apiVersion: apps/v1
    kind: DaemonSet
    metadata:
      name: dfdaemon
      namespace: kube-system
    spec:
      selector:
        matchLabels:
          app: dfdaemon
      template:
        metadata:
          annotations:
            scheduler.alpha.kubernetes.io/critical-pod: ""
          labels:
            app: dfdaemon
        spec:
          containers:
          - image: dragonflyoss/dfclient:v0.3.0
            name: dfdaemon
            imagePullPolicy: IfNotPresent
            args:
            - --registry https://index.docker.io
            resources:
              requests:
                cpu: 250m
            volumeMounts:
            - mountPath: /etc/dragonfly/dfget.yml
              subPath: dfget.yml
              name: dragonconf
          hostNetwork: true
          dnsPolicy: ClusterFirstWithHostNet
          restartPolicy: Always
          tolerations:
          - effect: NoExecute
            operator: Exists
          - effect: NoSchedule
            operator: Exists
          volumes:
          - name: dragonconf
            configMap:
              name: dragonfly-conf
    

    配置文件我们以configMap的形式挂载,所以我们还需要编写一个configMap的yaml文件,如下:

    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: dragonfly-conf
      namespace: kube-system
    data:
      dfget.yml: |
        nodes:
        - 172.17.100.120
    

    部署过后观察结果

    # kubectl get pod -n kube-system | grep dfdaemon
    dfdaemon-mj4p6                             1/1     Running   0          3m51s
    dfdaemon-wgq5d                             1/1     Running   0          3m51s
    dfdaemon-wljt6                             1/1     Running   0          3m51s
    


    然后修改docker daemon的配置,如下:

    {
      "registry-mirrors": ["http://127.0.0.1:65001"]
    }
    

    重启docker

    systemctl restart docker
    


    现在我们来拉取镜像测试,并观察日志输出。
    下载镜像(在master上测试的):

    docker pull nginx
    

    然后观察日志

    kubectl exec  -n kube-system dfdaemon-wgq5d  grep 'downloading piece' /root/.small-dragonfly/logs/dfclient.log
    

    看到日志输出如下,表示成功

    2020-06-20 17:14:54.578 INFO sign:128-1592673287.190 : downloading piece:{"taskID":"089dc52627a346df2a2ff67f6c07497167b35c4bad2bca1e9aad087441116982","superNode":"172.17.100.120","dstCid":"cdnnode:192.168.235.192~089dc52627a346df2a2ff67f6c07497167b35c4bad2bca1e9aad087441116982","range":"0-4194303","result":503,"status":701,"pieceSize":4194304,"pieceNum":0}
    

    今天的测试就到这里,我这是自己的小集群实验室,效果其实并不明显,在大集群效果可能更好。

  • 相关阅读:
    超链接标签、链接地址、锚文本及图片标签
    有序无序列表,div盛放逻辑版块,table表格
    函数的默认值与动态参数arguments的总结
    浏览器中常见的html语义化标签
    html基本介绍,了解html与css,html语法和结构
    js函数与作用域,了解函数基本概念
    JavaScrip流程控制之switch选择,for循环
    JavaScript之if流程控制演练,if写在区间内怎么解决
    JavaScript数据类型typeof()和转换
    C++走向远洋——60(十四周阅读程序、STL中的简单容器和迭代器)
  • 原文地址:https://www.cnblogs.com/coolops/p/13171956.html
Copyright © 2020-2023  润新知