TOC
简介
Zot 是思科开源的遵循 OCI 规范的容器镜像仓库,目前捐赠给了 CNCF,是 Sandbox 级别项目.
本文主要讲述作为镜像代理仓库下的应用场景.
部署
Kubernetes
前提
- helm
- kubernetes cluster
这里使用 kind 来创建一个研究用的 K8S 单节点集群.
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
apiServerAddress: "0.0.0.0"
apiServerPort: 6443
containerdConfigPatches:
- |-
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."gcr.io"]
endpoint = ["https://gcr.lank8s.cn"]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."registry.k8s.io"]
endpoint = ["https://registry.lank8s.cn"]
nodes:
- role: control-plane
extraMounts:
- hostPath: /var/log/tmp
containerPath: /var/log
extraPortMappings:
- containerPort: 5000
hostPort: 31150
listenAddress: "0.0.0.0"
开始部署
原本是想使用官方的 helm chart 来部署 zot,但是官方 helm 还处于比较早期的阶段,因此这里自己写了一个 yaml 文件来部署 zot.
TODO 配置固定的 nodePort 端口号,用于测试访问.
开启认证
默认情况下,所有用户都可以做任何操作,包括 读取/创建/更新/删除,在镜像代理仓库的场景下,这显然是不合理的,匿名用户只需要具备读权限即可.而管理员则具备其他权限,例如删除操作.
到目前为止 Zot 几种认证:
客户端
- TLS 证书认证 (basic TLS 和 mTLS)
- HTTP basic 认证
- HTTP bearer 认证
服务器端
- LDAP
- httpasswd
当同时配置了 LDAP 和 httpasswd 时,优先使用 LDAP 认证,如果 LDAP 服务不可用时,回退到 httpasswd 认证机制.
实战
本文使用 HTTP basic 认证作为演示效果.
首先需要在 zot 的配置文件中开启 httpasswd 方式的认证:
...
"http": {
...
"auth": {
"htpasswd": {
"path": "/tmp/htpasswd"
}
}
}
...
先创建一个管理员用户, 账号和密码都是 admin
htpasswd -bc /tmp/htpasswd admin admin
首先拉取一下镜像,
docker pull localhost:10015/kube-proxy:v1.26.0
尝试用匿名用户来删除镜像:
curl -X DELETE http://localhost:10015/v2/kube-proxy/manifests/v1.26.0
可以看到会提示没权限,添加用户密码后再尝试一次:
echo -n admin:admin | base64
curl -X DELETE -H "Authorization: Basic: " http://localhost:10015/v2/kube-proxy/manifests/v1.26.0
可以看到,请求返回成功了,检查一下镜像数据是否还在:
这时候已经没有镜像数据了,从 Zot 的日志中也可以看到相关删除操作的提示:
扩展
“extensions”: { “metrics”: {}, “sync”: {}, “search”: {}, “scrub”: {}, “lint”: {} }
实际案例
lank8s
目前 lank8s 服务已经从 distribution 仓库切换到了 Zot 镜像仓库.对于 lank8s 来说,Zot 的一个比较大的吸引力是可以对多个容器镜像仓库代理,在 Distribution 的 repo 中早有人提了这个功能 issue,但是一直没有人来实现这部分内容.
{
"extensions": {
"scrub": {
"enable": true,
"interval": "3h"
},
"sync": {
"enable": true,
"registries": [
{
"urls": [
"https://gcr.lank8s.cn"
],
"onDemand": true,
"tlsVerify": true,
"maxRetries": 2,
"retryDelay": "5m",
"content": [
{
"prefix": "/google-containers/*"
}]
},
{
"urls": [
"https://registry.lank8s.cn"
],
"onDemand": true,
"tlsVerify": true,
"maxRetries": 2,
"retryDelay": "5m"
}
]
}
}
}
上面的配置示例是当拉取镜像时(例如 kube-proxy:v1.26.0)如果 Zot 本地没有镜像信息则会同时从上游registry.lank8s.cn
,
拉取,为什么没有从另一个上游gcr.lank8s.cn
拉取镜像呢?是因为在字段content
中配置了prefix
,只有前缀为 google-containers
的容器镜像才会从上游 gcr.lank8s.cn
拉取镜像.
kind local registry
目前我在使用 kind 创建 k8s 集群做一些实验时,也是使用了 zot 作为实验时拉取到的容器镜像的持久化管理,避免每次用 kind 创建一个新的 k8s 测试集群环境时总是要拉取一次镜像.
可以看看为containerd配置仓库镜像这篇文章中关于这部分的内容.
官方文档: https://kind.sigs.k8s.io/docs/user/local-registry/
初体验
用户不友好
下面列出几个不太友好的地方.
-
当从上游同步镜像时是阻塞整个镜像下载过程的,需要等待 Zot 将镜像从上游整个下载到本地之后,才会让客户端继续镜像的下载.而 Distribution 是分步同步的,因此可以很快的给到客户端响应,用户体验会相对较好.(目前每次都会从上游下载镜像,相当于重复下载了,相关 issue 在这里 )
-
作为镜像代理模式工作时不支持S3存储.
-
同步多个上游镜像源时无法分开存储,例如上游 1 的数据存储在路径 A,上游 2 的数据存储在路径 B. 有一个subpath的功能,不过这个针对的是 namespace 级别的.
无法直接使用 docker push
当然这不代表有问题,因为 Zot 项目的设计原则就是 OCI 镜像仓库,不实现任何供应商相关的协议,当然也包括 Docker.
使用 skopeo 来将镜像 push 到 zot 当中.
从下面的命令来看,可以看到 docker push时会失败.
oem@lan:~$ docker push localhost:10014/kube-proxy:v1.26.1
The push refers to repository [localhost:10014/kube-proxy]
524ce886e20a: Pushed
8342c4e13d7f: Layer already exists
manifest invalid: manifest invalid
接下来使用 skopeo 来推送镜像到本地的 zot 镜像仓库,这里直接使用 skopeo copy 命令,会先下载镜像,然后 push 到 zot,推送过程很顺利.
oem@lan:~$ docker run --rm quay.io/skopeo/stable copy docker://registry.lank8s.cn/kube-proxy:v1.26.0 docker://192.168.31.13:10014/kube-proxy:v1.26.0 --insecure-policy --dest-tls-verify=false
Getting image source signatures
Copying blob sha256:7b2002b165df1a6be480139f99889c43327387546e29a86ea16824b777da12e4
Copying blob sha256:33905e809db95cdd940d3db7fc8f1486243bf738f5cd712b8f62b105be60dad6
Copying config sha256:556768f31eb1d6673ce1d1fc0ace1e814fc40eee9923275ba3a82635159afc69
Writing manifest to image destination
Writing manifest to image destination
Copying config sha256:a8401234c2d642ee82eb5ef43e29ecf86cbd194fb986721865222965904a4a41
Writing manifest to image destination
Storing signatures
总结
总体来说 Zot 在轻量级要求的场景下还是很不错的,例如目前 lank8scn 服务使用 Zot 来同步上游 gcr.io
和 registry.k8s.io
部分镜像.
微信公众号
扫描下面的二维码关注我们的微信公众号,第一时间查看最新内容。同时也可以关注我的Github,看看我都在了解什么技术,在页面底部可以找到我的Github。
温馨提示
本文还在持续创作中,如果你对本文主题感兴趣可以加我微信好友进行催更,博客下方可以找到我的微信联系方式 :)