一、场景描述
在部署Kubernetes集群时,面临的一个主要问题是镜像下载。许多镜像存储在k8s.gcr.io仓库中,然而由于国内的网络防火墙(GFW)的影响,无法直接访问该网站。尽管一些镜像可以通过阿里云的 k8s.gcr.io 同步解决国内无法下载GCR镜像的问题,但是仍有一些镜像无法在阿里云镜像仓库中找到。在这种情况下,我们需要采取一些措施来自行解决这个问题。
二、操作流程
- 购买一台国外的云服务器并且没有被墙,用来搭建docker镜像仓库代理服务
- 准备一个域名,然后到腾讯云或者阿里云上申请一个免费的证书;如果有多个代理的地址则要配置多个二级域名,然后购买一个通配符证书(说明:如果你使用cloudflare进行DNS解析,开启CF代理就不需要单独购买证书了,CF会免费提供https服务)
- 安装Nginx,配置域名和证书,然后反代我们的Registry容器服务
- 安装部署Docker和docker-compose
三、基础环境安装
(1)添加YUM源
[root@proxy ~]# yum update
[root@proxy ~]# yum install -y yum-utils device-mapper-persistent-data lvm2
[root@proxy ~]# yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
(2)安装 Docker
#可以查看所有仓库中所有docker版本,并选择特定版本安装
[root@proxy ~]# yum list docker-ce --showduplicates | sort -r
[root@proxy ~]# yum install -y docker-ce
(3)启动 Docker
[root@proxy ~]# systemctl enable docker && systemctl start docker
(4)安装 Docker Compose
[root@proxy ~]# curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
[root@proxy ~]# chmod +x /usr/local/bin/docker-compose
[root@proxy ~]# ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
[root@proxy ~]# docker-compose --version
四、部署镜像仓库代理
(1)创建账号密码【可选】
配置账号密码:我们在进行拉
[root@proxy ~]# docker run --rm --entrypoint \
htpasswd httpd:2 -Bbn \
username passwd > /root/registry/htpasswd
(2)添加docker-compose.yml文件
- 使用密码的话请把注释取消
[root@proxy ~]# mkdir -p /data/registry-proxy && cd $_
[root@proxy registry-proxy]# vim docker-compose.yaml
version: '3'
services:
# docker.io
docker-hub:
container_name: reg-docker-hub
image: registry:latest
restart: always
environment:
- REGISTRY_STORAGE_DELETE_ENABLED=true
#- REGISTRY_AUTH=htpasswd
#- REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd
#- REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm
# 这里是config.yml文件,为了在宿主机内区分多个代理地址修改配置文件名称
volumes:
- ./docker-hub.yml:/etc/docker/registry/config.yml
- ~/data/registry:/var/lib/registry
#- ./htpasswd:/auth/htpasswd
ports:
- 51000:5000
networks:
- registry-net
# gcr.io
ghcr:
container_name: reg-ghcr
image: registry:latest
restart: always
#environment:
#- REGISTRY_AUTH=htpasswd
#- REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd
#- REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm
volumes:
- ./ghcr.yml:/etc/docker/registry/config.yml
- ~/data/registry:/var/lib/registry
#- ./htpasswd:/auth/htpasswd
ports:
- 52000:5000
networks:
- registry-net
# k8s.gcr.io
k8s-gcr:
container_name: reg-k8s-gcr
image: registry:latest
restart: always
#environment:
#- REGISTRY_AUTH=htpasswd
#- REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd
#- REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm
volumes:
- ./k8s-ghcr.yml:/etc/docker/registry/config.yml
- ~/data/registry:/var/lib/registry
#- ./htpasswd:/auth/htpasswd
ports:
- 53000:5000
networks:
- registry-net
ui:
container_name: reg-ui
image: dqzboy/docker-registry-ui:latest
restart: always
links:
- docker-hub:reg-docker-hub
ports:
- 50000:80
environment:
- REGISTRY_TITLE=My Private Docker Registry
- NGINX_PROXY_PASS_URL=http://reg-docker-hub:5000
- DELETE_IMAGES=true
- SHOW_CONTENT_DIGEST=true
- SINGLE_REGISTRY=true
networks:
- registry-net
networks:
registry-net:
(3)添加config.yml文件
官方
注意:每个容器挂载对应的config.yml,这里名称与上面compose.yml文件定义的挂载的名称保持一致;下面只是其中一个示例配置,其他的配置也一样,只需要更改 remoteurl 代理的地址即可
[root@proxy registry-proxy]# vim docker-hub.yml
version: 0.1
log:
fields:
service: registry
storage:
cache:
blobdescriptor: inmemory
filesystem:
rootdirectory: /var/lib/registry
http:
addr: :5000
headers:
Access-Control-Expose-Headers: ['Docker-Content-Digest']
Access-Control-Allow-Methods: ['HEAD', 'GET', 'OPTIONS', 'DELETE']
Access-Control-Allow-Origin: ['*']
X-Content-Type-Options: [nosniff]
health:
storagedriver:
enabled: true
interval: 10s
threshold: 3
# remoteurl填写我们要代理的地址,如果需要登入,则要填写账号和密码
proxy:
remoteurl: https://registry-1.docker.io
username:
password:
(4)启动容器服务
[root@proxy registry-proxy]# docker-compose up -d
# 检查启动容器状态
[root@proxy registry-proxy]# docker ps

(5)配置Ngin原文链接:https://www.dqzboy.com x反代
[root@proxy ~]# cd /etc/nginx/conf.d/
[root@proxy conf.d]# vim registry-proxy.conf
server {
listen 80;
listen 443 ssl;
#填写绑定证书的域名
server_name ui.xxx.com;
#证书文件名称
ssl_certificate xxx.com_bundle.crt;
#私钥文件名称
ssl_certificate_key xxx.com.key;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
#请按照以下协议配置
ssl_protocols TLSv1.2 TLSv1.3;
#请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
ssl_buffer_size 8k;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;
location / {
proxy_pass http://localhost:50000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Nginx-Proxy true;
proxy_buffering off;
proxy_redirect off;
}
}
server {
listen 80;
listen 443 ssl;
#填写绑定证书的域名
server_name hub.xxx.com;
#证书文件名称
ssl_certificate xxx.com_bundle.crt;
#私钥文件名称
ssl_certificate_key xxx.com.key;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
#请按照以下协议配置
ssl_protocols TLSv1.2 TLSv1.3;
#请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
ssl_buffer_size 8k;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;
location / {
proxy_pass http://localhost:51000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Nginx-Proxy true;
proxy_buffering off;
proxy_redirect off;
}
}
server {
listen 80;
listen 443 ssl;
#填写绑定证书的域名
server_name gcr.xxx.com;
#证书文件名称
ssl_certificate xxx.com_bundle.crt;
#私钥文件名称
ssl_certificate_key xxx.com.key;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
#请按照以下协议配置
ssl_protocols TLSv1.2 TLSv1.3;
#请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
ssl_buffer_size 8k;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;
location / {
proxy_pass http://localhost:52000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Nginx-Proxy true;
proxy_buffering off;
proxy_redirect off;
}
}
server {
listen 80;
listen 443 ssl;
#填写绑定证书的域名
server_name k8sgcr.xxx.com;
#证书文件名称
ssl_certificate xxx.com_bundle.crt;
#私钥文件名称
ssl_certificate_key xxx.com.key;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
#请按照以下协议配置
ssl_protocols TLSv1.2 TLSv1.3;
#请按照以下套件配置,配置加密套件,写法遵循 openssl 标准。
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
ssl_buffer_size 8k;
proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;
location / {
proxy_pass http://localhost:53000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Nginx-Proxy true;
proxy_buffering off;
proxy_redirect off;
}
}
# 重载Nginx配置
nginx -t
nginx -s reload
(6)解析域名
- 将我们在Nginx配置的域名,在DNS服务商商进行解析,解析到部署镜像代理仓库的服务器上;
- 通过访问UI地址可以查看镜像仓库缓存的镜像;
- 通过使用对应的代理域名来下载我们之前无法下载的镜像。
(7)使用镜像仓库代理
# 比如我们要下载镜像:gcr.io/google-containers/pause:3.1
# 可以通过镜像代理仓库地址下载:
[root@proxy ~]# docker pull gcr.xxx.com/google-containers/pause:3.1
访问 UI 页面就可以看到上面我们下载的镜像已经被缓存了

(8)修改docker配置
- 在docker的
daemon.json
配置文件中添加上docker.io的代理域名,然后重启docker程序
[root@BJ-Cloud ~]# vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://hub.xxx.com"],
"log-opts": {
"max-size": "100m",
"max-file": "5"
}
}
#重启docker
systemctl restart docker
(9)kubeadm配置镜像代理
如果你用 kubeadm 部署 Kubernetes 集群,可以在 kubeadm 配置文件中设置镜像地址为你的搭建的代理仓库的域名地址
~]# cat kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: v1.25.1
......
imageRepository: k8sgcr.xxx.com/google-containers
谢谢大佬分享,可以使用
这台服务器应该是国外的吧