彻底解决 gcr、quay、DockerHub 镜像下载难题
在使用 Docker 和 Kubernetes 时,我们经常需要访问 gcr.io 和 quay.io 镜像仓库,由于众所周知的原因,这些镜像仓库在中国都无法访问,唯一能访问的是 Docker Hub,但速度也是奇慢无比。gcr.azk8s.cn 是 gcr.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.io 和 Docker Hub 很好代理,可以直接使用 Envoy 的 host_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 Hub 和 quay.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 Hub、gcr.io 和 quay.io 的镜像了,不需要修改任何前缀,Containerd 会根据配置自动选择相应的代理 URL 拉取镜像。
6. 费用评估
好了,现在我们来评估一下这一切的费用。首先你得有一个会魔法的服务器,国内的肯定不用考虑了,必须选择国外的,而且到国内的速度还过得去的,最低最低不会低于 30 人民币/月 吧。除此之外,你还得拥有一个个人域名,这个价格不好说,总而言之,加起来肯定不会低于 30 吧,多数人肯定是下不去这个手的。没关系,我有一个更便宜的方案,我已经部署好了一切,你可以直接用我的服务,当然我也是自己买的服务器,每个月也是要花钱的,如果你真的想用,只需要每月支付 3 元,以此来保障我每个月的服务器费用。当然肯定不止你一个人,我可能还会赚点钱,但最多不允许超过 40 人,如果人数特别多,我可能会考虑加服务器。这个需要你自己考虑清楚,有意者扫描下方的二维码加入交流群:

如果二维码已过期,可以加我微信拉你进群。
微信公众号
扫一扫下面的二维码关注微信公众号,在公众号中回复◉加群◉即可加入我们的云原生交流群,和孙宏亮、张馆长、阳明等大佬一起探讨云原生技术

彻底解决 gcr、quay、DockerHub 镜像下载难题的更多相关文章
- 解决k8s gcr.io被墙下载不了镜像的问题
gcr.io镜像 根据开源项目: https://github.com/anjia0532/gcr.io_mirror 作者将gcr.io相关镜像pull下来,然后push到docker官方仓库htt ...
- 【解决】k8s 1.15.2 镜像下载方案
k8s 国内镜像下载方案 众所周知,国内是不太容易下载k8s.gcr.io站点的镜像的 一.第一种方案:Azure中国镜像站 http://mirror.azure.cn/help/gcr-proxy ...
- 解决从dockerhub上下载debian:jessie失败
解决从dockerhub上下载debian:jessie失败 笔者使用docker build 构建镜像出现下面的错误 Step 1/12 : FROM debian:jessie Get https ...
- Genymotion虚拟镜像下载慢或者失败的解决办法
Genymotion虚拟镜像下载慢或者失败的解决办法 http://files2.genymotion.com/dists/8.0.0/ova/genymotion_vbox86p_8.0_18061 ...
- [容器]gcr.io镜像下载
下载gcr.io的镜像hosts文件 把下面两行加入到/etc/hosts中. 更多在这里http://wst.so/files/hosts 61.91.161.217 gcr.io 61.91.1 ...
- k8s.gcr.io、gcr.io仓库的镜像下载
镜像下载.域名解析.时间同步请点击 阿里巴巴开源镜像站 获取这类镜像的方法一般有2种: 1.通过拉取国内镜像仓库的内容(操作简单直接拉取即可,缺点是镜像的版本更新可能较慢,可能无法获取最新的镜像) 2 ...
- 使用kubeadm安装kubernetes/部署前准备/flannel网络插件/镜像下载/
本文内容参考<kuberneters进阶实战>/马哥的新书/推荐 部署前的准备 主机名称解析 分布式系统环境中的多主机通信通常基于主机名称进行,这在IP地址存在变化的可能性时为主机提供了固 ...
- 通过镜像下载最新Android源码
参考了这两篇博客: http://blog.sina.com.cn/s/blog_70b9730f01016peg.html http://www.cnblogs.com/act262/p/41790 ...
- Jexus Web Server 完全傻瓜化图文配置教程(基于Ubuntu 12.04.3 64位)[内含Hyper-v 2012虚拟机镜像下载地址]
1. 前言 近日有感许多新朋友想尝试使用Jexus,不过绝大多数都困惑徘徊在Linux如何安装啊,如何编译Mono啊,如何配置Jexus啊...等等基础问题,于是昨日向宇内流云兄提议,不如搞几个配置好 ...
- Windows 8.1 系统ISO镜像下载或自Win8应用商店升级方法
1)下载 -- 面向全体用户的Win8.1预览版ISO镜像下载(28日开放): 安装时请输入微软官方提供给大家的产品密钥:NTTX3-RV7VB-T7X7F-WQYYY-9Y92F. 64位简体中文版 ...
随机推荐
- 基于Raft算法的DLedger-Library分析
1 背景 在分布式系统应用中,高可用.一致性是经常面临的问题,针对不同的应用场景,我们会选择不同的架构方式,比如master-slave.基于ZooKeeper选主.随着时间的推移,出现了基于Raft ...
- SpringBoot内容协商机制
1.是什么? SpringBoot内容协商机制是一种实现了内容协商(Content Negotiation)的Web服务器,它可以根据客户端请求的不同,将响应返回给客户端. 在传统的Web服务器中,如 ...
- jextract的使用
写这个博客的目的:新人去看jextract的官网是看不懂的,就算看懂了也不会使用,一头雾水,我会从0开始教如何使用,如何搭配java去调用c函数. 首先我们得了解jextract是什么,官网的解释是一 ...
- 内核模块(.ko) 开发入门
内核模块时指的是在操作系统内核中动态加载的一段代码,它可以扩展和增强操作系统的功能.内核模块通常用于为操作系统添加新的设备驱动程序.文件系统.网络协议栈等功能. 内核模块是以二进制形式存在的(*.ko ...
- 2023.3 Idea配置Tomcat环境
tomcat配置 下载tomcat 先到官网(按住Ctrl再左键点击直接打开官网)下载64位的tomcat,网速慢就用魔法下 创建项目.模块 打开idea(我用的是最新的idea的专业版,ui有点变化 ...
- 听说生鲜领军企业k8s集群都上云了,鱼会飞了?
在这个中秋都和国庆在一起的双节里,我们的小明还在辛辛苦苦的找工作,听说他经历了一段"难忘"的面试. 小明面对着面试官的"层层拷问",游刃有余的化解了这些难题. ...
- zabbix-server 报错记录
数据库磁盘满导至zabbix挂了 登陆zabbix页面提示错误信息,查看系统磁盘: /目录已满,导致mariadb数据库无法正常运行,如果有介质将会一直收取: 解决方法:扩容/目录,达到理想值,重启m ...
- dfs之迭代加深
为什么要用迭代加深 \(dfs\) 每次会选择搜索树的一个分支,不断深入,直到达到递归边界条件:但这种搜索策略带有一定的缺陷性: 如果搜索树的某一个分支中的节点个数特别多,但是答案并不在这棵子树里面, ...
- SQL Server系列:系统函数之聚合函数
聚合函数:指对一组值执行计算,并返回单个值.除了 Count(统计函数) 外,聚合函数都会忽略 Null 值 聚合函数经常与 SELECT 语句的 GROUP BY 子句一起使用 1.Avg():返回 ...
- 华为云GaussDB打造最可信的数据库,给世界一个更优选择
近日,第14届中国数据库技术大会(DTCC2023)在北京国际会议中心顺利举行.大会以"数智赋能 共筑未来"为主题,邀请了上百位行业专家,一起探讨新时代下各类型数据库的最新动态和应 ...