彻底解决 gcr、quay、DockerHub 镜像下载难题 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
yangchuansheng33
V2EX    推广

彻底解决 gcr、quay、DockerHub 镜像下载难题

  •  
  •   yangchuansheng33 2020-06-30 10:19:36 +08:00 6488 次点击
    是一个创建于 1933 天前的主题,其中的信息可能已经有所发展或是发生改变。

    原文链接:https://fuckcloudnative.io/posts/docker-registry-proxy/

    在使用 Docker 和 Kubernetes 时,我们经常需要访问 gcr.ioquay.io 镜像仓库,由于众所周知的原因,这些镜像仓库在中国都无法访问,唯一能访问的是 Docker Hub,但速度也是奇慢无比。gcr.azk8s.cngcr.io 镜像仓库的代理站点,原来可以通过 gcr.azk8s.cn 访问 gcr.io 仓库里的镜像,但是目前 *.azk8s.cn 已经仅限于 Azure 中国的 IP 使用,不再对外提供服务了。国内其他的镜像加速方案大多都是采用定时同步的方式来缓存,不能保证及时更新,ustc 和七牛云等镜像加速器我都试过了,非常不靠谱,很多镜像都没有。

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

    1. 前提条件


    • 一台能够施展魔法的服务器(你懂得,可以直接访问 gcr.io
    • 一个域名和域名相关的 SSL 证书( docker pull 镜像时需要验证域名证书),一般用 Let's Encrypt 就够了。

    2. 代理方案


    quay.ioDocker Hub 很好代理,可以直接使用 Envoyhost_rewrite_literal 参数(这是新版本的参数,如果你使用旧版本的 Envoy,参数应该是 host_rewrite ),当 Envoy 将请求转发给上游集群时,会直接将头文件中的 host 改为指定的值。比如,如果上游集群是 quay.io ,就将头文件改为 quay.io。我之前写过的 使用 Envoy 反向代理谷歌搜索 用的就是此方案。什么?你是 Envoy 小白?莫慌,我已经为你们准备了一本 Envoy 从入门到放弃 的电子书,快快点击下方的链接学习去吧(记得给我一个 star 哦)~~

    gcr.io 稍微有点难办,因为它在连接的时候需要二次认证,即使你通过反代服务器 pull 镜像,它还是会再次访问 gcr.io 进行验证,然后才可以通过反代服务器 pull 镜像。这就有点尴尬了,我特么要是能访问 gcr.io ,还要什么反代啊。。。话说 Docker 官方不是有一个 registry 镜像吗,可以通过设置参数 remoteurl 将其作为远端仓库的缓存仓库,这样当你通过这个私有仓库的地址拉取镜像时,regiistry 会先将镜像缓存到本地存储,然后再提供给拉取的客户端(有可能这两个步骤是同时的,我也不太清楚)。我们可以先部署一个私有 registry,然后将 remoteurl 设为 https://gcr.io,最后再通过 Envoy 反代,基本上就可以了。

    3. 代理配置


    方案确定了之后,就可以动手配置了。还是使用我之前反复提到的方法:通过文件动态更新配置。如果你不是很清楚我在说什么,请参考 Envoy 基础教程:基于文件系统动态更新配置。这里我就直接贴配置了。

    bootstrap 配置:

    # envoy.yaml node: id: node0 cluster: cluster0 dynamic_resources: lds_config: path: /etc/envoy/lds.yaml cds_config: path: /etc/envoy/cds.yaml admin: access_log_path: "/dev/stdout" address: socket_address: address: "0.0.0.0" port_value: 15001 

    LDS 的配置:

    # 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: 80 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: http_route virtual_hosts: - name: default domains: - "*" routes: - match: prefix: "/" redirect: https_redirect: true port_redirect: 443 response_code: "FOUND" http_filters: - name: envoy.filters.http.router - "@type": type.googleapis.com/envoy.config.listener.v3.Listener name: listener_https address: socket_address: address: 0.0.0.0 port_value: 443 listener_filters: - name: "envoy.filters.listener.tls_inspector" typed_config: {} filter_chains: - transport_socket: name: envoy.transport_sockets.tls typed_config: "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.DownstreamTlsContext common_tls_context: alpn_protocols: h2,http/1.1 tls_certificates: - certificate_chain: filename: "/root/.acme.sh/xxx.com/fullchain.cer" private_key: filename: "/root/.acme.sh/xxx.com/xxx.com.key" 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_https codec_type: AUTO use_remote_address: true 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 domains: - gcr.xxx.com routes: - match: prefix: "/" route: cluster: gcr timeout: 600s - name: quay domains: - quay.xxx.com routes: - match: prefix: "/" route: cluster: quay host_rewrite_literal: quay.io - name: docker domains: - docker.xxx.com routes: - match: prefix: "/" route: cluster: dockerhub host_rewrite_literal: registry-1.docker.io http_filters: - name: envoy.filters.http.router typed_config: "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router 

    友情提醒:我这里使用的是 v3 版本的 API,v2 版本的 API 即将被废弃,请奔走相告。

    CDS 的配置:

    # 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: gcr.default 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 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 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 Hubquay.io 的镜像了。最后来解决 gcr.io 镜像的难题。

    4. registry 配置


    首先需要部署一个私有的 registry,如果你只有一台服务器(我想大多数人应该只会买一台吧),可以使用 docker-compose,我这里是使用 Kubernetes 部署的,首先需要准备一个部署清单:

    # registry-proxy.yaml apiVersion: apps/v1 kind: Deployment metadata: name: gcr labels: app: gcr spec: replicas: 1 selector: matchLabels: app: gcr template: metadata: labels: app: gcr spec: nodeSelector: kubernetes.io/hostname: blog-k3s03 tolerations: - key: node-role.kubernetes.io/ingress operator: Exists effect: NoSchedule hostNetwork: false containers: - name: gcr image: findsec/registry-proxy:latest env: - name: PROXY_REMOTE_URL value: https://gcr.io ports: - containerPort: 5000 hostPort: 5000 protocol: TCP volumeMounts: - mountPath: /etc/localtime name: localtime - mountPath: /var/lib/registry name: registry volumes: - name: localtime hostPath: path: /etc/localtime - name: registry hostPath: path: /var/lib/registry --- apiVersion: v1 kind: Service metadata: name: gcr labels: app: gcr spec: sessionAffinity: ClientIP selector: app: gcr ports: - protocol: TCP name: http port: 5000 targetPort: 5000 

    然后将其部署到 Kubernetes 集群中:

    $ kubectl apply -f registry-proxy.yaml 

    现在再回过头来看看 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: gcr.default port_value: 5000 

    这里的 address 使用的是 Kubernetes 集群内部域名,其他部署方式请自己斟酌。

    最后,给服务器换个新内核,开启 BBR 加速不过分吧?不然你的镜像拉取仍然是龟速。

    5. 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 

    当然,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 = ["http://gcr.xxx.com"] 

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

    6. 费用评估


    好了,现在我们来评估一下这一切的费用。首先你得有一个会魔法的服务器,国内的肯定不用考虑了,必须选择国外的,而且到国内的速度还过得去的,最低最低不会低于 30 人民币 /月 吧。除此之外,你还得拥有一个个人域名,这个价格不好说,总而言之,加起来肯定不会低于 30 吧,多数人肯定是下不去这个手的。没关系,我有一个更便宜的方案,我已经部署好了一切,你可以直接用我的服务,当然我也是自己买的服务器,每个月也是要花钱的,如果你真的想用,只需要每月支付 3 元,以此来保障我每个月的服务器费用。当然肯定不止你一个人,我可能还会赚点钱,但最多不允许超过 40 人,如果人数特别多,我可能会考虑加服务器。这个需要你自己考虑清楚,有意者扫描下方的二维码加入交流群:

    gcr 镜像加速服务

    如果二维码已过期,可以加我微信拉你进群。

    33 条回复    2020-06-30 23:52:26 +08:00
    guyeu
        1
    guyeu  
       2020-06-30 10:50:00 +08:00   3
    @Livid 这是广告吧
    marquina
        2
    marquina  
       2020-06-30 10:52:25 +08:00 via Android   1
    彻底解决(指透明代理
    privil
        3
    privil  
       2020-06-30 11:00:14 +08:00
    搞那么复杂……我只需搞一个稳定的 http 代理 https://lakelight.net/2019/03/27/k8s-cache.html
    yangchuansheng33
        4
    yangchuansheng33  
    OP
       2020-06-30 11:36:08 +08:00
    @privil 你和我的方法是一个意思,只不过我把配置文件都贴出来了,看起来比较多而已
    defunct9
        5
    defunct9  
       2020-06-30 11:36:55 +08:00
    搞得这么复杂,为了炫技而炫技,纯属无聊
    yangchuansheng33
        6
    yangchuansheng33  
    OP
       2020-06-30 11:39:16 +08:00
    @marquina 你要知道,绝大多数人是不懂透明代理的玩法的,我可以直接喂到他们嘴里
    pmispig
        7
    pmispig  
       2020-06-30 11:39:34 +08:00
    纯粹是为了赚钱吧,最方便的就是开个临时实例推到 dockerhub
    isnullstring
        8
    isnullstring  
       2020-06-30 11:39:52 +08:00
    还行,适合懒得动手
    yangchuansheng33
        9
    yangchuansheng33  
    OP
       2020-06-30 11:40:43 +08:00
    @defunct9 复杂要看对谁而言,对用户来说一点也不复杂,直接用就好了
    yangchuansheng33
        10
    yangchuansheng33  
    OP
       2020-06-30 11:41:08 +08:00
    @pmispig 你自己算一下我能不能赚钱
    yangchuansheng33
        11
    yangchuansheng33  
    OP
       2020-06-30 11:42:07 +08:00 via Android
    @pmispig 关键是 dockerhub 也慢
    yov123456
        12
    yov123456  
       2020-06-30 12:27:05 +08:00 via iPhone
    surge 开个增强模式(
    whileFalse
        13
    whileFalse  
       2020-06-30 13:25:00 +08:00
    @yov123456 服务器怎么办,在云上装个黑苹果?
    Rwing
        14
    Rwing  
       2020-06-30 13:28:30 +08:00
    挺好的 支持一下
    herozzm
        15
    herozzm  
       2020-06-30 13:29:53 +08:00 via Android
    路由器全局爬梯子
    listenerri
        16
    listenerri  
       2020-06-30 14:38:38 +08:00   1
    感觉还行吧,不能算是广告,楼主解决了一个普遍痛点,但由于为此要付出一些代价,所以找有相同痛点的人一起分担一下,可以理解;但是我觉得有点标题党,我进来时想要发现点奇技淫巧的,结果你跟我说让我用你的代理吧。
    shenlanAZ
        17
    shenlanAZ  
       2020-06-30 14:46:49 +08:00
    为啥不能再网线前面插个透明代理 这样你连 google 的时候都不用再进行配置了。

    而且 不需要域名 不需要这么多复杂的步骤。。。。。

    解决问题从简单的方式解决不好么。。。
    somefree
        18
    somefree  
       2020-06-30 14:52:32 +08:00   1
    看了看回复, 好像没人提镜像加速站的, 补充一个

    ```
    # 第一行 原始的镜像坐标
    # 第二行 加速后的镜像坐标

    docker pull xxx:yyy
    docker pull dockerhub.azk8s.cn/library/xxx:yyy

    docker pull xxx/yyy:zz
    docker pull dockerhub.azk8s.cn/xxx/yyy:zz

    docker pull gcr.io/xxx/yyy:zzz
    docker pull gcr.azk8s.cn/xxx/yyy:zzz

    docker pull k8s.gcr.io/xxx:yyy
    docker pull gcr.azk8s.cn/google-containers/xxx:yyy

    docker pull quay.io/xxx/yyy:zzz
    docker pull quay.azk8s.cn/xxx/yyy:zzz
    ```
    millson
        19
    millson  
       2020-06-30 14:55:54 +08:00
    @somefree azure 的已经不提供外部访问
    somefree
        20
    somefree  
       2020-06-30 15:07:00 +08:00
    @millson 果然, 好久没碰过了, 但是也还有别的加速站点呀, 查了查, 网易加速:hub-mirror.c.163.com, DaoCloud 道客云:daocloud.io, 不过我还没试过这两个
    dullwit
        21
    dullwit  
       2020-06-30 15:10:14 +08:00
    docker 跑个 clash,写个 iptables 规则,局域网和 docker 的流量都进 tun
    mcone
        22
    mcone  
       2020-06-30 16:38:23 +08:00   1
    @Livid 疑似推广
    至少不适合这个节点
    yangchuansheng33
        23
    yangchuansheng33  
    OP
       2020-06-30 16:53:28 +08:00 via Android
    @listenerri 并没有啊,我告诉你方案了,我只是说如果你舍不得花那么多钱,才用我的啊
    yangchuansheng33
        24
    yangchuansheng33  
    OP
       2020-06-30 16:55:40 +08:00 via Android
    @shenlanAZ 你思考的方向有问题,对于我来说这样是很简单,对于大众来说,很少人会这个,我的思考方向是大众,顺便一个月可能还能赚回其他 VPS 的钱(赚多少钱不可能,如果人多撑死了几十块),多好
    Illusionary
        25
    Illusionary  
       2020-06-30 16:57:37 +08:00
    图样,有境外服务器谁不会弄? 直接在路由器配置境外 ip 走代理就完事了,搞这些花里胡哨
    yangchuansheng33
        26
    yangchuansheng33  
    OP
       2020-06-30 17:01:53 +08:00 via Android
    @Illusionary 看我上面的回复,这些方案只适合我个人用,不适合我推广给大众
    chenxinwri9212
        27
    chenxinwri9212  
       2020-06-30 17:02:04 +08:00
    @Illusionary (づ)づ
    yangchuansheng33
        28
    yangchuansheng33  
    OP
       2020-06-30 17:03:13 +08:00 via Android
    @Illusionary 你说的这些你觉得我不知道吗?可以看我网站置顶的博客
    yangchuansheng33
        29
    yangchuansheng33  
    OP
       2020-06-30 17:08:43 +08:00 via Android
    @somefree 这些 dockerhub 的镜像都不全,且不支持 gcr 和 quay
    cs419
        30
    cs419  
       2020-06-30 19:24:55 +08:00
    通常搭 k8s 的时候需要访问 gcr 仓库
    这 envoy 直接部署到 k8s 上做反代??
    所以说:是先有鸡,还是先有蛋

    大部分人都用的 nginx
    这里还得学 envoy
    人生苦短,envoy 是拥有远超 nginx 的性能?
    yangchuansheng33
        31
    yangchuansheng33  
    OP
       2020-06-30 20:05:14 +08:00 via Android
    @cs419 仔细看完了再问问题,我没有怂恿大家部署到 k8s 上,毕竟大多数人没有那么多公有云资源,我只是描述了我自己是这么干的。

    关于 envoy,见仁见智,你用习惯了 Nginx 可以继续用,我用不习惯就用 envoy,这个不重要,我只是提供一个思路
    d5
        32
    d5  
       2020-06-30 20:12:43 +08:00
    @somefree “从小”就用 daocloud,dao xxx 大法好,哈哈哈哈
    icecrack
        33
    icecrack  
       2020-06-30 23:52:26 +08:00
    楼主教程不错,如果自己不想搭,还有现成服务。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     961 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 26ms UTC 19:01 PVG 03:01 LAX 12:01 JFK 15:01
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86