背景
很多企业为了安全性,线上除了业务网络外,是关闭了外网进出路线的。
但是我们在使用 docker 和 k8s 时, 又不可避免的会使用到很多 docker.io, ghcr.io, quay.io 等公网仓库的镜像。
该如何较好的拉取这些镜像呢?
内部镜像仓库
除非一次性项目,以后都不再管理了,否则都是有必要搭建一个内部的 镜像仓库的。
简单临时用一下这种情况, 推荐使用官方的 docker-registry 就可以。
一般情况下推荐还是搭建一个 Harbor, 在官方仓库的基础上增加了 https, 备份, 同步等一些功能。
如何把镜像上传到内部镜像仓库
方法一: 手动模式
- 本地 docker pull 镜像
- 本地导出镜像
- 上传镜像到服务器
- 服务器 load 镜像
- 服务器上 push 到镜像仓库
很麻烦是不?是真麻烦,稍微多更新几个镜像就受不了。
方法二: 脚本离线传输
弄个脚本将外部 Harbor 的镜像全导出来, 批量上传需要的镜像到内网, 内部再批量提交
方法三: 临时网络开关
推荐采用这种模式;
- 限制只允许 Harbor 出公网
- 需要更新和拉取外网镜像时开一下防火墙策略, 更新完成即把策略再关闭
- 开启网络策略后就可以立即手工做预热镜像, 不一定非得生产环境更新镜像时再拉取;
- 再严格一点可以部署2个 Harbor, 只临时开放一个测试环境的, 生产的从测试定时同步过来;
方法四: 推荐两套仓库的方案
- 部署一个 Harbor 作为内部镜像站,存放企业内部专有的镜像
- 部署一个 docker hub 的 registry-mirrors 只缓存外部的镜像
实践一: Harbor 自定义镜像站的镜像站
即允许 Harbor 访问外网的情况,配置一个镜像站。
一是减少了人员操作量,二是内部节点更新镜像时可以有份缓存,减少带宽消耗和时间。
创建步骤
-
Harbor 上创建一个 docker-hub 的仓库
位置在 系统管理-仓库管理, 只需要选择 提供者为 Docker Hub, 然后随便填个名字 就ok
-
创建一个自定义项目, 如 cproxy, 配置镜像代理,选择上一步创建的仓库即可
使用方法
假设内部私有仓库的域名为 registry.services.wait
拉取 Hub 根目录 library 下的镜像
docker pull registry.services.wait/cproxy/nginx:latest
拉取常规镜像
docker pull registry.services.wait/cproxy/project-name/nginx:latest
Harbor镜像站路径的问题
存在一个问题:
在 /etc/docker/daemon.json 文件中配置 registry-mirrors 时是不能使用路径的;
如 https://registry.services.wait/cproxy 是会报错的;
如果带上这个 cproxy 名字的话,那么所有外部的 yml 文件最后都得手动修改给加上;
还有很多隐藏的镜像(yml文件里面没有写的那种)就更麻烦了。
解决办法:
前置一个 nginx, 并且配置一个 vhost, 例如监听 mirrors-docker.services.wait
将这个域名反代到 registry.services.wait/cproxy 上面去
/etc/docker/daemon.json 文件的 registry-mirrors 就配置 https://mirrors-docker.services.wait 即可。
containerd 的 config.toml 里面是一样的镜像配置。
也就是内部的业务镜像配置的时候, 需要显式添加域名和项目地址,不走镜像站,如
image: registry.services.wait/group1/web1:v0.1
外部镜像可以不添加域名,从而走镜像站
image: nginx:latest
不过最后这一步我没有做成功,理论应该是可行的。遇到个小错误,nginx没有转发到 mirrors 去, 环境被铲了,下次有机会再部署排查一下。
实践二: 独立部署 docker-mirrors镜像站
推荐用这种模式
内部镜像写全路径,指向内部仓库域名和地址;
外部镜像走 registry-mirrors 的配置, 并内部 dns 指向到这台可以出公网的代理仓库节点上
|
|
|
|
如果是临时网络策略也不让开,那就只能外部pull,然后内部push了。
如果不想去修改那些yml文件, 则还是部署一个 mirrors registry,但按照普通模式部署。
没有这样试过, 感觉理论可行。