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仓库中。
参考文档:
- 揭秘sealer背后实现整个集群一键交付的奥秘 | 龙蜥技术
- Sealos Run 的工作原理
- 《sealos制作MySQL集群镜像》
- 《sealos制作 kube-prometheus-stack 集群镜像》
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 | shim: /var/run/image-cri-shim.sock |
配置说明:
- 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 | systemctl start image-cri-shim |
参考文档:
4. sealos hub弱密码问题
4.1. 问题描述
sealos hub的默认admin密码为passw0rd,是一个弱密码,可能会被漏洞扫描工具扫描出来,因此最好改成强密码。
4.2. 解决办法(错误)
修改 /etc/registry/registry_htpasswd 密码本文件中的admin用户的密码。
1 | htpasswd -Bb /etc/registry/registry_htpasswd admin xxx |
修改密码后,每个主机都使用新密码重新登录一下registry。
1 | docker logout 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 | wget https://github.com/labring/sealos/releases/download/v4.2.3/sealos_4.2.3_linux_amd64.tar.gz |
此外,修改完registry密码后,还需要修改 ~/.sealos/default/Clusterfile 中的registry密码配置,以便在新增节点时使用新密码。
1 | status: |
上面的配置,在实测时并没有生效,不知道应该修改哪里的配置,留个坑。
新增节点时,最终采用的方案是先改回原密码passw0rd,新增节点后密码再改回。
对于4.2.0之前的版本,如果想要手动修改密码的话,所有机器的 registry.yml 还有 image-shim 以及 containerd 的配置应该都需要改,比较麻烦。