harbor
harbor主要是用来存储容器镜像的开源项目,也就是所谓的容器镜像仓库,跟OpenStack的glance功能类似,不同的是后者存放的是虚拟机镜像。
harbor除了可以存储容器镜像,还可以存储chart,chart是容器环境下的应用打包格式,类似于centos下的rpm包,ubuntu下的debian包。
下图是harbor的架构图
这两种资源都需要放在存储介质上,镜像和chart可以分开用不同的存储,也可以使用相同的存储后端,这里主要讨论一下镜像的存储。
从上图可以看到harbor对镜像的实际存储使用的是docker原生的registry,那研究harbor的镜像存储,就是研究docker registry的镜像存储。一般都存放在本地文件系统上,
即后端存储driver使用filesystem,由于harbor是跑在容器里的,此driver根据具体实现又可分为以下三种情况:
- (1)服务器本地存储:这种方式就是把服务器本地文件目录挂载到容器中做为harbor存储镜像的位置
- (2)ceph rbd pv:这种方式首先通过k8s的pvc申请一个ceph rbd卷,然后把rbd卷mount到服务器,最后再把这个目录挂载到容器中
- (3)ceph cephfs pv:这种方式直接使用cephfs功能,通过pvc申请一个cephfs中的一个目录,然后mount到服务器,最后在把这个目录挂载到容器中
简单说明一下这三种:第一种不是共享存储,是harbor高可用的拦路虎;第二种ceph rbd卷出于数据一致性的考虑,不能同时挂载在对各宿主机上,也是harbor高可用的拦路虎;第三种cephfs是共享存储,通过文件系统是可以进行多挂载,同时读写,但是由于cephfs storageclass driver不是官方指定的,可能driver质量还不够高,同时cephfs本身也质疑比较多(不过社区一致在对cephfs投入很大)
好像没有一种比较十全十美的,那还有其他的driver吗?
ceph rgw可用否
ceph一共就三种应用,块、文件、对象,前两种都试过了,那ceph的rgw对象存储可以使用不,看了一下docker registry中的driver是用s3,ceph的rgw是支持s3的,那应该可以?!不过网上搜了一下好多人说,都有问题,一直卡主retry,比如一下连接:https://github.com/docker/distribution/issues/2189,
小甲以为这个问题应该解决了,毕竟这是2017的issue,先实验试一下
docker registry接ceph rgw s3实验
- 版本:
1
2
3harbor
docker registry(distribution) 2.6.2
aws-sdk-go
docker registry后来v2版改名叫distribution,上面表是实验使用的代码版本
- 配置:
distribution配置1
2
3
4
5
6
7s3:
region: us-east-1
bucket: gkkbucket1
accesskey: tstackqwer666
secretkey: tstackqwer666
regionendpoint: http://10.85.46.87:8080
secure: false
10.85.46.87:8080是ceph rgw的地址
docker的/etc/docker/daemon.json配置如下:
1 | { |
192.168.127.1:5000是distribution服务的地址,也就是让docker使用私有镜像仓库
docker tag scratch:latest 192.168.127.1:5000/scratch:1.11
实验结果:registry接s3有问题
运行distribution,然后docker push私有镜像,实验表明确实还存在问题,一致在retry
假装有图。
网上没有解决办法,那就手撸一下。
调试及分析
1.首先制作一个只有一层的镜像,要不然distribution调试的时候请求会很多,眼花缭乱,不要给自己添麻烦,
这里使用如下命令制作一个只有一层的镜像1
tar cv --files-from /dev/null | docker import - scratch
2.设置tag
1
docker tag scratch:latest 192.168.127.1:5000/scratch:1.11
通过调试发现docker registry是先上传数据,最后再上传manifest,通过调试发现
1 | 192.168.127.133 - - [23/Mar/2019:20:30:45 +0800] "PUT /v2/docker.io/alpine/blobs/uploads/4f495fbb-876f-43b7-8aad-166701220985?_state=BbHh5XVtlX93j2I3vYVRWNluZ96_3wIhkMKd-9W3YeB7Ik5hbWUiOiJkb2NrZXIuaW8vYWxwaW5lIiwiVVVJRCI6IjRmNDk1ZmJiLTg3NmYtNDNiNy04YWFkLTE2NjcwMTIyMDk4NSIsIk9mZnNldCI6Mjc1NDcyOCwiU3RhcnRlZEF0IjoiMjAxOS0wMy0yM1QxMjozMDozNVoifQ%3D%3D&digest=sha256%3A6c40cc604d8e4c121adcb6b0bfe8bb038815c350980090e74aa5a6423f8f82c0 HTTP/1.1" 201 0 "" "docker/1.13.1 go/go1.10.3 kernel/3.10.0-327.el7.x86_64 os/linux arch/amd64 UpstreamClient(Docker-Client/1.13.1 \\(linux\\))" |
在这里卡主了,上面有一个url从定向,
ceph rgw的日志如下:
首先请求包认证错误,怎么会认证错误呢,再查看请求头发现这请求奇怪
rgw请求的s3 v4认证怎么在这个QUERY_STRING字段,这个字段一般是url后面的查询条件,小甲思考3秒,可能是url重定向导致,屡一下可能是这样
- 1.docker向distribution发送了一个head请求
- 2.distribution接收到请求之后,进行了url重定向,把signure认证放在了url查询部分,放在location中返回docker
- 3.docker根据返回请求中location中的重定向的url,也就是上面ceph rgw的地址,然后发送请求,可是docker没有调用任何s3的sdk,所以不会进行s3的signure算法,直接head发给了ceph rgw
- 4.ceph rgw接收到head请求,还是根据s3的v4认证,所以报错了。
后面调试代码发现问题确实是这样。
修改方法
那如何修改呢,其实修改很简单,只要把url直接抛异常就可以,这个filesystem也是这样处理的。小甲本来的想法是新建一个结构体,继承现有的s3 driver,然后重载URLFor函数就可以,但是发现s3的driver是包外不可见,这就无法继承,最后通过增加一个配置参数,是否是使用的ceph s3还是aws s3,在使用ceph s3的时候直接抛异常退出URLFor函数。
#等等还没结束
docker push和pull现在都可以正常了,但是镜像的删除也有问题,那镜像是怎么删除的呢?
- 1.调用api删除
- 2.distribution 运行garbage-collect命令
发现有问题,ceph接受不到请求,调试了好久发现是distribution中vendor目录下的aws-sdk-go版本比较老,小甲用较高的版本就可以了
这下应该结束了吧,no no no
distribution master问题
小甲又下载了distribution的master分支试了一下,发现前面的修改之后docker push/pull都ok,删除换了高版本的aws-sdk-go还是有问题,什么问题呢?
- 1.空指针异常,What?
在doWalk函数中出现了空指针,这个函数在distribution 2.6.2中还没有 - 2.代码分析从ceph返回来的
ListObjectsV2Output这个对象的KeyCount这个成员是一个空指针,而代码中使用这个进行了运算导致了错误,看来distribution确实没有验证ceph - 3.修改也比较简单,通过之前加的一个ceph配置对ceph的请求情况做一下特殊处理就可以了。
修改代码后重新编译
编译修改后的代码成二进制可执行文件
重新制作harbor-registry镜像
使用dockerfile生成新的镜像
1 | FROM test:v1.7.0 |
chart配置修改
修改harbor/values.yaml文件
1 | imageChartStorage: |