K8s 如何通过harbor 拉取镜像?
K8S 在那些情况下需要进行镜像的拉取?
- 在需要进行新的pod的调度时,基于镜像拉取策略,完成镜像的获取:
- Always: 在任何情况下都需要重新拉取镜像
- 即使设置为总是进行镜像拉取,也不代表每一次都需要重新进行镜像的完成拉取
- 容器镜像的层次结构决定了镜像的每一层都有一个唯一不重复的ID
- 每一次进行镜像拉取的操作时,都需要对比本地和仓库中镜像层的ID,只有在ID 不一致的情况下,才会重新拉取不一致的层
- 主要的使用场景,pod的镜像默认使用最新版镜像,即tag为latest,而tag为latest的镜像会不断更新,在最新版镜像更新的时候,重新拉取镜像。
- IfNotPresent: 在需要调度pod的节点上不存在镜像的情况下,才会进行镜像的拉取
- Always: 在任何情况下都需要重新拉取镜像
- 过程如下:
- 客户端发出后指令要求调度一个pod,并制定了pod的镜像
- K8S的APIserver将pod调度的指令转发给对应的控制器
- 控制器创建pod运行需要的基本配置
- 调度器决定新创建的pod应该在那个工作节点上运行
- 对应工作节点上的kubelet 来完成pod的最终的创建,这里就包括拉取镜像、启动容器等
- Kubelet 对应的容器运行时(OCI) 使用的是 containerd 服务,
- 如果k8s 需要从harbor中拉取镜像重点是,配置各个工作节点使用harbor。
配置过程如下:
- 需要在工作节点上,基于工作节点使用的OCI ,配置OCI 使用harbor的tsl证书
- 如果需要拉取私有仓库的镜像,那么还需要提前设置好,登录仓库使用的用户名密码的信息
在k8s的工作节点:
[root@node1 ~]# vim +162 /etc/containerd/config.toml
// 指定仓库的配置路径,该路径下基于不同仓库对应的域名和IP地址创建子目录,以保存不同仓库的配置和访问证书等。
[root@node1 ~]# mkdir /etc/containerd/certs.d/harbor.mydomain.com -p
[root@node1 ~]# vim /etc/containerd/certs.d/harbor.mydomain.com/hosts.toml
[root@node1 ~]# cat /etc/containerd/certs.d/harbor.mydomain.com/hosts.toml
server = "https://harbor.mydomain.com"
[host."https://harbor.mydomain.com"]
capabilities = ["pull", "resolve", "push"]
ca = "ca.crt"
client = [["harbor.mydomain.com.cert","harbor.mydomain.com.key"]]
在harbor节点上分发证书:
[root@harbor certs]# scp ca.crt root@192.168.110.11:/etc/containerd/certs.d/harbor.mydomain.com/
root@192.168.110.11's password:
ca.crt 100% 2065 1.2MB/s 00:00
[root@harbor certs]# scp harbor.mydomain.com.key root@192.168.110.11:/etc/containerd/certs.d/harbor.mydomain.com/
root@192.168.110.11's password:
harbor.mydomain.com.key 100% 3268 1.8MB/s 00:00
[root@harbor certs]# scp harbor.mydomain.com.cert root@192.168.110.11:/etc/containerd/certs.d/harbor.mydomain.com/
root@192.168.110.11's password:
harbor.mydomain.com.cert 100% 2179 1.1MB/s 00:00
返回k8s 工作节点,重启服务:
[root@node1 ~]# systemctl restart containerd.service
将改变配置分配给其他工作节点:
首先现在其他工作节点上创建配置目录
[root@node2 ~]# mkdir /etc/containerd/certs.d/harbor.mydomain.com -p
在node1上进行配置文件变更的同步:
[root@node1 ~]# scp /etc/containerd/certs.d/harbor.mydomain.com/* root@node2:/etc/containerd/certs.d/harbor.mydomain.com/
Node2 检查文件是否同步完成:
[root@node2 ~]# ls /etc/containerd/certs.d/harbor.mydomain.com/
ca.crt harbor.mydomain.com.cert harbor.mydomain.com.key hosts.toml
[root@node2 ~]# systemctl restart containerd.service
返回k8s 控制节点:
- 创建harbor仓库访问记录
[root@control ~]# source .kube/k8s_bash_completion [root@control ~]# kubectl create secret docker-registry harbor-admin-registry \ > --docker-server=https://harbor.mydomain.com \ > --docker-username=admin \ > --docker-password=Harbor12345
- 将harbor仓库域名解析同步到其他节点
-
[root@control ~]# vim /etc/hosts
# 添加一行即可
[root@control ~]# scp /etc/hosts root@node1:/etc/hosts
root@node1's password:
hosts 100% 259 463.5KB/s 00:00
[root@control ~]# scp /etc/hosts root@node2:/etc/hosts
root@node2's password:
hosts 100% 259 259.2KB/s 00:00
3.部署一个使用harbor仓库中镜像的应用
[root@control ~]# vim nginx-deployment.yml
[root@control ~]# cat nginx-deployment.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
imagePullSecrets:
- name: harbor-admin-registry
dnsPolicy: ClusterFirst
containers:
- name: nginx
image: harbor.mydomain.com/myproject/nginx:1.19.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
返回harbor仓库确保仓库中存在上面配置文件指定的镜像:
如果没有的话,可以选择上传:
在harbor节点上,进行一下操作:
[root@harbor harbor]# docker pull nginx:1.19.1
[root@harbor harbor]# docker tag nginx:1.19.1 harbor.mydomain.com/myproject/nginx:1.19.1
[root@harbor harbor]# docker push harbor.mydomain.com/myproject/nginx:1.19.1
#报错可能是缺少认证
# 查看一下是不是有用户的认证信息
[root@harbor harbor]# ls ~/.docker/config.json
/root/.docker/config.json
[root@harbor harbor]# cat ~/.docker/config.json
{
"auths": {
"harbor.mydomain.com": {
"auth": "YWRtaW46SGFyYm9yMTIzNDU="
}
}
}
# 没有的话,需要登录到仓库,来生成认证信息缓存
[root@harbor harbor]# docker login harbor.mydomain.com
# 按照提示输入用户名 密码即可
回到控制节点:
[root@control ~]# kubectl get deployments.apps
NAME READY UP-TO-DATE AVAILABLE AGE
test-nginx 3/3 3 3 2d
[root@control ~]# kubectl apply -f nginx-deployment.yml
deployment.apps/nginx-deployment created
[root@control ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-6f7b4fb9b9-cxnrm 0/1 ErrImagePull 0 7s // 报错的原因是第一次的配置文件存在错误,修正错误后,稍等片刻pod会自动恢复
nginx-deployment-6f7b4fb9b9-mbqgn 0/1 ErrImagePull 0 7s
nginx-deployment-6f7b4fb9b9-zkjsm 0/1 ErrImagePull 0 7s
test-nginx-bb78867bf-7drv4 1/1 Running 4 (60m ago) 2d
test-nginx-bb78867bf-fgd5l 1/1 Running 3 (19h ago) 2d
test-nginx-bb78867bf-gzd9v 1/1 Running 3 (19h ago) 2d
修正错误后:
[root@control ~]# kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-deployment-6f7b4fb9b9-cxnrm 1/1 Running 0 2m54s 10.244.1.112 node1 <none> <none>
nginx-deployment-6f7b4fb9b9-mbqgn 0/1 ImagePullBackOff 0 2m54s 10.244.2.133 node2 <none> <none>
nginx-deployment-6f7b4fb9b9-zkjsm 0/1 ImagePullBackOff 0 2m54s 10.244.2.134 node2 <none> <none>
test-nginx-bb78867bf-7drv4 1/1 Running 4 (63m ago) 2d 10.244.2.131 node2 <none> <none>
test-nginx-bb78867bf-fgd5l 1/1 Running 3 (19h ago) 2d 10.244.1.102 node1 <none> <none>
test-nginx-bb78867bf-gzd9v 1/1 Running 3 (19h ago) 2d 10.244.1.101 node1 <none> <none>
[root@control ~]# kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deployment-6f7b4fb9b9-cxnrm 1/1 Running 0 3m27s
nginx-deployment-6f7b4fb9b9-mbqgn 1/1 Running 0 3m27s
nginx-deployment-6f7b4fb9b9-zkjsm 1/1 Running 0 3m27s
test-nginx-bb78867bf-7drv4 1/1 Running 4 (64m ago) 2d
test-nginx-bb78867bf-fgd5l 1/1 Running 3 (19h ago) 2d
test-nginx-bb78867bf-gzd9v 1/1 Running 3 (19h ago) 2d
请尝试更新一下目前pod的镜像,进行一次滚动更新。
延申: 目前harbor 与K8S 分别部署到不同的主机中,或者换一句话说 harbor没有直接在k8s平台来运行,如果需要将harbor部署到K8S平台中,可以直接通过控制器部署,也可以结合专门的部署工具helm 来提高部署的自动化程度。Harbor不管是通过docker compose 还是通过 k8s 平台部署,都需要通过重点考虑存储的持久化问题,毕竟谁也不想平台断电或者重启后,原本保存的镜像不见了。