一个计算机技术爱好者与学习者

0%

好好学Sealos:Sealos Hub私有容器镜像仓库

1. sealos hub简介

在使用sealos安装k8s时,会自动安装一个docker registry,它就是sealos hub,用于存储容器镜像。
sealos hub在集群中的主机名和端口为sealos.hub:5000,默认用户名admin,密码passw0rd

参考文档:

2. sealos hub部署方式

sealos hub会部署到宿主机上,我们可以通过systemctl对它进行管理。

查看registry状态:

1
systemctl status registry

配置文件路径:/etc/registry/registry_config.yml
密码路径:/etc/registry/registry_htpasswd

3. sealos hub原理

3.1. 存储容器镜像

sealos build 的过程中,如何知道软件中有哪些容器镜像?
因为我们需要把这些镜像缓存下来,不管是扫描用户的 yaml 文件还是用 helm template 之后扫描都是不完美的。首先不能确定用户的编排方式是什么,其次有些软件不把镜像地址写在编排文件中,而是通过自己的程序去拉起,无法保证 build 成功运行就一定没问题。

对于这个问题,sealos的处理方法比较原始,需要用户自己找到需要的容器镜像列表,写入到 images/shim/images-list.txt 文件中。

sealos build 打包集群镜像完成后,容器镜像就存储到了集群镜像中,在使用 sealos run 安装应用时,容器镜像就会被加载到本地存储 sealos hub仓库中。

参考文档:

3.2. 下载容器镜像

容器镜像被打包到了集群镜像里,sealos run时容器镜像被存储到了私有仓库sealos hub中。
此时,编排文件中写的容器镜像地址 和 私有仓库容器镜像地址 是不一致的,怎么保证用户从私有仓库中下载容器镜像?特别是怎么保证用户 alwayPull 的时候还是能够在私有仓库中下载到镜像?

对于这个问题,有两种解决方案:
第一种是 hack docker,让docker具备只要私有镜像仓库中有就直接从私有镜像中拉取,没有才去公网拉取镜像的能力。
第二种方案是无侵入 docker 的 proxy,把 docker 请求全部打给代理,让代理去决定如果私有仓库有就从私有仓库拉取。同时增强了 registry 的能力让 registry 可以 cache 多个远程仓库的能力。

sealos采用的是第二种方案:docker 的 proxy,image-cri-shim

image-cri-shim 是一个基于 CRI (Container Runtime Interface) 和 kubelet 的 gRPC (Google Remote Procedure Call) shim。CRI 是 Kubernetes 中用于与容器运行时进行交互的接口,而 kubelet 是负责维护容器运行状态和节点级别的资源管理的 Kubernetes 组件。

image-cri-shim 的主要功能是自动识别镜像名称,让用户在使用 Kubernetes 部署容器时无需手动指定镜像名称。这样可以降低用户的操作难度,提高部署容器的便利性。

在实际使用中,image-cri-shim 可以作为一个中间件,接收来自 kubelet 的请求,然后将请求转发给容器运行时。通过自动识别镜像名称,image-cri-shim 可以简化容器镜像的部署流程,减轻用户的操作负担。

1
/usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --config=/var/lib/kubelet/config.yaml --container-runtime=remote --container-runtime-endpoint=/var/run/cri-dockerd.sock --container-runtime=remote --pod-infra-container-image=sealos.hub:5000/pause:3.2 --runtime-request-timeout=15m --container-runtime-endpoint=unix:///var/run/cri-dockerd.sock --image-service-endpoint=unix:///var/run/image-cri-shim.sock

上面的kubelet启动命令中,通过指定 --image-service-endpoint=unix:///var/run/image-cri-shim.sock ,实现了 image-cri-shim 中间件的配置,很巧妙。

image-cri-shim 示例配置:

1
2
3
4
5
6
7
8
9
10
11
shim: /var/run/image-cri-shim.sock
cri: /run/containerd/containerd.sock
address: http://sealos.hub:5000
force: true
debug: true
timeout: 15m
auth: admin:passw0rd

registries:
- address: http://172.18.1.38:5000
auth: admin:passw0rd

配置说明:

  • shim: 指定 image-cri-shim 的 UNIX 套接字文件路径。这个路径用于与 kubelet 之间的通信。
  • cri: 指定容器运行时(如 containerd)的 UNIX 套接字文件路径。image-cri-shim 会使用这个路径与容器运行时进行通信。
  • address: 定义镜像仓库的地址。在本例中,镜像仓库地址为 http://sealos.hub:5000。
  • force: 设置为 true 时,image-cri-shim 会在强制启动shim,无需等待cri启动后启动。
  • debug: 设置为 true 时,启用调试模式,输出更多的日志信息。
  • timeout: 定义镜像操作的超时时间。在本例中,超时时间为 15 分钟(15m)。
  • auth: 定义用于访问镜像仓库的身份验证凭据。在本例中,用户名为 admin,密码为 passw0rd。

此外,配置文件还包含了一个 registries 列表,用于定义其他镜像仓库及其身份验证凭据,以便 sealos hub 从其他镜像仓库拉取镜像。在这个例子中,只有一个其他仓库:

  • address: 该仓库的地址为 http://172.18.1.38:5000。
  • auth: 用于访问该仓库的身份验证凭据。在本例中,用户名为 admin,密码为 passw0rd。 这个配置文件为 image-cri-shim 提供了所需的信息,以便正确地与 kubelet 和容器运行时(如 containerd)进行通信,以及访问和管理镜像仓库。

image-cri-shim 通常作为一个系统服务运行。

1
2
3
4
systemctl start image-cri-shim
systemctl stop image-cri-shim
systemctl restart image-cri-shim
systemctl status image-cri-shim

参考文档:

4. sealos hub弱密码问题

4.1. 问题描述

sealos hub的默认admin密码为passw0rd,是一个弱密码,可能会被漏洞扫描工具扫描出来,因此最好改成强密码。

4.2. 解决办法(错误)

修改 /etc/registry/registry_htpasswd 密码本文件中的admin用户的密码。

1
2
3
htpasswd -Bb /etc/registry/registry_htpasswd admin xxx

systemctl restart registry

修改密码后,每个主机都使用新密码重新登录一下registry。

1
2
docker logout sealos.hub:5000
docker login sealos.hub:5000

PS:htpasswd的安装使用方法,参考文档《shell命令之htpasswd》

4.3. 新的问题

使用 htpasswd 修改了 /etc/registry/registry_htpasswd 中的密码,docker login也可以使用新密码登录了,但是查看registry日志,很多请求还是使用旧密码,而且主机重启后很多原本正常running的pod无法拉取镜像了。
看来我们上面修改sealos hub密码的方法并不正确。

4.4. 解决办法(正确)

sealos群里咨询大佬们,获悉可以使用最新版本的sealos来修改registry密码。
参考文档:

1
2
3
wget https://github.com/labring/sealos/releases/download/v4.2.3/sealos_4.2.3_linux_amd64.tar.gz
tar -xzvf sealos_4.2.3_linux_amd64.tar.gz sealos
./sealos registry passwd

此外,修改完registry密码后,还需要修改 ~/.sealos/default/Clusterfile 中的registry密码配置,以便在新增节点时使用新密码。

1
2
3
4
5
status:
mounts:
- env:
registryDomain: sealos.hub
registryPassword: new_password

上面的配置,在实测时并没有生效,不知道应该修改哪里的配置,留个坑。
新增节点时,最终采用的方案是先改回原密码passw0rd,新增节点后密码再改回。

对于4.2.0之前的版本,如果想要手动修改密码的话,所有机器的 registry.yml 还有 image-shim 以及 containerd 的配置应该都需要改,比较麻烦。