zoukankan      html  css  js  c++  java
  • Docker 镜像加速

    部署参考文章

    建议先查看此文档后,再继续查看此文档

    https://fuckcloudnative.io/posts/docker-registry-proxy/
    https://blog.kiko.space/2018/07/26/ubuntu-install-caddy/
    

    其他借鉴文档

    https://fuckcloudnative.io/posts/use-envoy-proxy-access-google/
    https://fuckcloudnative.io/envoy-handbook/docs/gettingstarted/setup/
    

    0. 部署背景

    • 在使用 Docker 和 Kubernetes 时,我们经常需要访问 gcr.io 和 quay.io 镜像仓库,由于众所周知的原因,这些镜像仓库在中国都无法访问,唯一能访问的是 Docker Hub,但速度也是奇慢无比。

    • 为了能够顺利访问 gcr.io 等镜像仓库,我们需要在墙外自己搭建一个类镜像仓库代理站点。直接反代可以保证获取到的镜像是最新最全的,比缓存靠谱多了。

    1. 前提条件

    • 一台能够施展魔法的服务器
    • 一个域名

    2. 代理方案

    • quay.io 和 Docker Hub 很好代理,可以直接使用 Envoy 的 host_rewrite_literal 参数(这是新版本的参数,如果你使用旧版本的 Envoy,参数应该是 host_rewrite),当 Envoy 将请求转发给上游集群时,会直接将头文件中的 host 改为指定的值。比如,如果上游集群是 quay.io,就将头文件改为 quay.io。

    • envoy中文文档

    https://github.com/yangchuansheng/envoy-handbook
    
    • gcr.io 稍微有点难办,因为它在连接的时候需要二次认证,即使你通过反代服务器 pull 镜像,它还是会再次访问 gcr.io 进行验证,然后才可以通过反代服务器 pull 镜像。这就有点尴尬了,要是能访问 gcr.io,还要什么反代啊。。。

    • 但是 Docker 官方有一个 registry 镜像,可以通过设置参数 remoteurl 将其作为远端仓库的缓存仓库,这样当你通过这个私有仓库的地址拉取镜像时,registry 会先将镜像缓存到本地存储,然后再提供给拉取的客户端(有可能这两个步骤是同时的,我也不太清楚)。

    • 我们可以先部署一个私有 registry,然后将 remoteurl 设为 https://gcr.io 最后再通过 Envoy 反代,基本上就可以了。

    3. 框架

    域名访问最好基于https访问,此处未使用人工手动生产证书方式,而使用caddy生成证书,以及证书配置验证

    1)Caddy服务:自动生成证书,并自动配置https,然后代理请求到envoy服务
    
    2)envoy服务:(可以在envoy中配置https服务,但需要手动生产证书,此时可以不用Caddy服务<此处使用caddy实现自动配置https>),识别从Caddy来的请求,然后区分域名,代理到不同的后端服务
    
    3)registry服务:作为缓存仓库,响应envoy服务发送过来的grc网站相关的请求
    

    4. Caddy服务部署

    详细部署,可以查看官方文档,或此文档:https://blog.kiko.space/2018/07/26/ubuntu-install-caddy/

    • 安装caddy
    https://blog.kiko.space/2018/07/26/ubuntu-install-caddy/
    
    • 配置域名以及https
    # cat /etc/caddy/Caddyfile
    quay.xxx.com gcr.xxx.com docker.xxx.com {
    
        tls xxxxx@gmail.com  # 自动配置https,并生成证书
        gzip
    
        proxy / 127.0.0.1:18080 {   # 把 quay gcr dockerhub 的请求代理到envoy中
            transparent
        }
    }
    
    ## 18080端口为envoy服务暴露端口
    

    5. envoy服务部署

    • envoy 通过文件动态更新配置
    # mkdir /data/envoy
    # cd /data/envoy
    
    ## bootstrap 配置
    # vim envoy.yaml
    node:
      id: node0
      cluster: cluster0
    dynamic_resources:  # 动态加载配置文件
      lds_config:
        path: /etc/envoy/lds.yaml  # 加载 lds.yaml 文档
      cds_config:
        path: /etc/envoy/cds.yaml  # 加载 cds.yaml 文档
    admin:
      access_log_path: "/dev/stdout"
      address:
        socket_address:
          address: "0.0.0.0"
          port_value: 15001
    
    ## lds.yaml配置
    # vim lds.yaml
    version_info: "0"
    resources:
    - "@type": type.googleapis.com/envoy.config.listener.v3.Listener
      name: listener_http
      address:
        socket_address:
          address: 0.0.0.0
          port_value: 18080   # quay gcr docker 服务启动端口
      filter_chains:
      - filters:
        - name: envoy.filters.network.http_connection_manager
          typed_config:
            "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
            stat_prefix: ingress_http
            codec_type: AUTO
            access_log:
              name: envoy.access_loggers.file
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.access_loggers.file.v3.FileAccessLog
                path: /dev/stdout
            route_config:
              name: https_route
              response_headers_to_add:
              - header:
                  key: Strict-Transport-Security
                  value: "max-age=15552000; includeSubdomains; preload"
              virtual_hosts:  # 配置的代理域名主机
              - name: gcr     # gcr服务代理
                domains:
                - gcr.xxx.com    # 服务使用的域名,其他项目可修改为其他域名
                routes:
                - match:
                    prefix: "/"
                  route:
                    cluster: gcr
                    timeout: 600s
              - name: quay    # quay服务代理
                domains:
                - quay.xxx.com    # 服务使用的域名
                routes:
                - match:
                    prefix: "/"
                  route:
                    cluster: quay
                    host_rewrite_literal: quay.io    #  Envoy 将请求转发给上游集群时,会直接将头文件中的 host 改为指定的值。比如,如果上游集群是 quay.io,就将头文件改为 quay.io
              - name: docker   # docker hub服务代理
                domains:
                - docker.xxx.com    # 服务使用的域名
                routes:
                - match:
                    prefix: "/"
                  route:
                    cluster: dockerhub
                    host_rewrite_literal: registry-1.docker.io
            http_filters:
            - name: envoy.filters.http.router
    

    提醒:这里使用的是 v3 版本的 API,v2 版本的 API 即将被废弃

    ## cds.yaml配文件
    # vim cds.yaml
    version_info: "0"
    resources:
    - "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster
      name: gcr
      connect_timeout: 1s
      type: strict_dns
      dns_lookup_family: V4_ONLY
      lb_policy: ROUND_ROBIN
      load_assignment:
        cluster_name: gcr
        endpoints:
        - lb_endpoints:
          - endpoint:
              address:
                socket_address:
                  address: 127.0.0.1  # registry地址和端口
                  port_value: 5000
    - "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster
      name: dockerhub
      connect_timeout: 15s
      type: logical_dns
      dns_lookup_family: V4_ONLY
      dns_resolvers:
        socket_address:
          address: 8.8.8.8
          port_value: 53
      lb_policy: ROUND_ROBIN
      load_assignment:
        cluster_name: dockerhub
        endpoints:
        - lb_endpoints:
          - endpoint:
              address:
                socket_address:
                  address: registry-1.docker.io    # dockerhub 对应的后端域名
                  port_value: 443
      transport_socket:
        name: envoy.transport_sockets.tls
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
          sni: registry-1.docker.io
    - "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster
      name: quay
      connect_timeout: 15s
      type: logical_dns
      dns_lookup_family: V4_ONLY
      dns_resolvers:
        socket_address:
          address: 8.8.8.8
          port_value: 53
      lb_policy: ROUND_ROBIN
      load_assignment:
        cluster_name: quay
        endpoints:
        - lb_endpoints:
          - endpoint:
              address:
                socket_address:
                  address: quay.io   # quay 对应的后端域名
                  port_value: 443
      transport_socket:
        name: envoy.transport_sockets.tls
        typed_config:
          "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
          sni: quay.io
    
    • 启动Envoy服务
    # docker run --name envoy -d -v /data/envoy:/etc/envoy --net=host envoyproxy/envoy:v1.14-latest
    

    配置好了 Envoy 之后,就可以通过代理服务器拉取 Docker Huquay.io 的镜像了。然后来解决 gcr.io 镜像的难题。

    6. registry 服务部署

    • 手动生成配置文件,需要添加registry的代理配置
    # mkdir -pv /data/registry/
    # cd /data/registry/
    
    # vim config.yml
    version: 0.1
    log:
      fields:
        service: registry
    storage:
      cache:
        blobdescriptor: inmemory
      filesystem:
        rootdirectory: /var/lib/registry
    http:
      addr: :5000
      headers:
        X-Content-Type-Options: [nosniff]
    health:
      storagedriver:
        enabled: true
        interval: 10s
        threshold: 3
    proxy:     # 启动 registry 的代理功能
      remoteurl: https://gcr.io
    
    
    • 启动服务
    # docker run --name registry -p 5000:5000 -v /data/registry/config.yml:/etc/docker/registry/config.yml -v /data/registry:/var/lib/registry -d registry:2.6.2
    
    • 回过头来看看 Envoy 的配置中关于 gcr 的部分,先来看看 LDS:
    virtual_hosts:
    - name: gcr
      domains:
      - gcr.xxx.com
      routes:
      - match:
          prefix: "/"
        route:
          cluster: gcr
          timeout: 600s
    
    • 再来看看 CDS:
    - "@type": type.googleapis.com/envoy.config.cluster.v3.Cluster
      name: gcr
      connect_timeout: 1s
      type: strict_dns
      dns_lookup_family: V4_ONLY
      lb_policy: ROUND_ROBIN
      load_assignment:
        cluster_name: gcr
        endpoints:
        - lb_endpoints:
          - endpoint:
              address:
                socket_address:
                  address: 127.0.0.1
                  port_value: 5000
    
    ## 这里的 address 使用的是服务的访问地址
    

    请求 gcr.xxx.com,首先会把请求代理到 registry 容器, registry 配置了代理,所以 registry 会去下载镜像并缓存到本地,然后响应 gcr.xxx.com 的请求,所以配置好后,使用 gcr.xxx.com 可以下载gcr镜像了

    7. Docker 加速配置使用

    • 现在可以通过代理服务器来拉取公共镜像了。

    对于 Docker Hub 来说,只需要将 docker.io 换成 docker.xxx.com 就行了,比如你想拉取 nginx:alpine 镜像,可以使用下面的命令:

    # docker pull docker.xxx.com/library/nginx:alpine
    

    对于 quay.io 来说,只需要将 quay.io 换成 quay.xxx.com 就行了,比如你想拉取 quay.io/coreos/kube-state-metrics:v1.5.0 镜像,可以使用下面的命令:

    # docker pull quay.xxx.com/coreos/kube-state-metrics:v1.5.0
    

    对于 gcr.io 来说,只需要将 gcr.io 换成 gcr.xxx.com 就行了,比如你想拉取 gcr.io/google-containers/etcd:3.2.24 镜像,可以使用下面的命令:

    # docker pull gcr.xxx.com/google-containers/etcd:3.2.24
    

    8. Docker 配置

    当然,Docker 是可以设置 registry mirror 的,但只支持 Docker Hub。可以修改配置文件 /etc/docker/daemon.json,添加下面的内容:

    {
        "registry-mirrors": [
            "https://docker.xxx.com"
        ]
    }
    

    然后重启 Docker 服务,就可以直接拉取 Docker Hub 的镜像了,不需要显示指定代理服务器的地址,Docker 服务本身会自动通过代理服务器去拉取镜像。比如:

    # docker pull nginx:alpine
    # docker pull docker.io/library/nginx:alpine
    

    Containerd 就比较简单了,它支持任意 registry 的 mirror,只需要修改配置文件 /etc/containerd/config.toml,添加如下的配置:

    [plugins.cri.registry.mirrors]
      [plugins.cri.registry.mirrors."docker.io"]
        endpoint = ["https://docker.xxx.com"]
      [plugins.cri.registry.mirrors."quay.io"]
        endpoint = ["https://quay.xxx.com"]
      [plugins.cri.registry.mirrors."gcr.io"]
        endpoint = ["https://gcr.xxx.com"]
    

    重启 Containerd 服务后,就可以直接拉取 Docker Hubgcr.ioquay.io 的镜像了,不需要修改任何前缀,Containerd 会根据配置自动选择相应的代理 URL 拉取镜像。

  • 相关阅读:
    HBase学习笔记-基础(一)
    系统架构师之旅(一)——软件架构设计:程序员向架构师转型必备总结
    高效程序员的特征:聪明,懒惰
    TOMCAT源码分析(启动框架)
    Java线程池的原理及几类线程池的介绍
    Java 并发:Executors 和线程池
    Memcache基础教程
    发邮件
    图片验证码
    上传图片添加水印
  • 原文地址:https://www.cnblogs.com/evescn/p/13094704.html
Copyright © 2011-2022 走看看