背景
在离线场景中,向 K8S 集群部署服务成为一项挑战,我们需要考虑如何将镜像导入到所有工作节点,这是一项复杂的工作,更好的做法是在离线环境中部署一套私有的镜像仓库,考虑到业务 Pod 可能出现各种漂移情况,私有镜像仓库最好还要具备高可用。
本文介绍了一种无需进入节点操作,在离线环境中向 K8S 集群注入高可用的私有镜像仓库的方法。
方案特点
- Registry 被部署在 K8S 集群内
- Registry 具备高可用
- 无需为 Registry 提供可信证书
- 无需为节点配置私有仓库
insecure-registries
前置条件
- 一台内网互通的工作站
- 通过 APIServer 访问 K8S 集群的权限
- 集群支持 RWX 的持久化存储能力(如不考虑高可用,可以不用)
实施步骤
准备 registry 先锋实例
- 在工作站中导入
registry:2
镜像
docker load registry.tar.gz
- 在工作站中运行 registry 先锋实例
docker run --name registry -d -p 5000:5000 registry:2
- 将
registry:2
镜像推送到 registry 先锋实例
docker tag registry:2 127.0.0.1:5000/registry:2
docker push 127.0.0.1:5000/registry:2
- 准备
registry-service.yaml
清单文件
apiVersion: v1
kind: Service
metadata:
name: registry-service
spec:
type: NodePort
ports:
- name: http
protocol: TCP
port: 5000
targetPort: 5000
NodePort: 32445
---
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: registry-service
labels:
kubernetes.io/service-name: registry-service
addressType: IPv4
ports:
- name: http
appProtocol: http
protocol: TCP
port: 5000
endpoints:
- addresses:
- "<工作站 IP地址>"
- 将清单文件应用到集群
kubectl apply -f registry-service.yaml
向集群部署高可用的 registry 服务
- 准备
cluster-registry.yaml
清单文件
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: cluster-registry
labels:
app: cluster-registry
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 10Gi
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: cluster-registry
labels:
app: cluster-registry
spec:
selector:
matchLabels:
app: cluster-registry
template:
metadata:
labels:
app: cluster-registry
spec:
containers:
- name: cluster-registry
image: 127.0.0.1:32445/registry:2 # 此处是刻意使用 127.0.0.1 IP 地址,请勿删除
resources:
limits:
memory: 200Mi
requests:
cpu: 100m
memory: 200Mi
ports:
- containerPort: 5000
name: http
volumeMounts:
- name: registry
mountPath: /var/lib/registry
volumes:
- name: registry
persistentVolumeClaim:
claimName: cluster-registry
---
apiVersion: v1
kind: Service
metadata:
name: cluster-registry
spec:
selector:
app: cluster-registry
type: NodePort
sessionAffinity: "ClientIP"
sessionAffinityConfig:
clientIP:
timeoutSeconds: 10800
ports:
- name: http
protocol: TCP
port: 5000
targetPort: 5000
- 将清单文件应用到集群
kubectl create ns registry
kubectl apply -f cluster-registry.yaml -n registry
- 检查服务状态
检查 Pod 状态,确保 Pod 都已经 Running
kubectl get pod -n registry
清理 registry 先锋实例,服务反转
- 清理
Service
和EndpointSlice
kubectl delete -f registry-service.yaml
- 停止并删除工作站中的 registry 先锋实例
docker stop registry
docker rm registry
- 服务切换,将集群里的 registry 接管 32445 端口的流量
kubectl patch svc cluster-registry --type='json' -p='[{"op":"replace","path":"/spec/ports/0/nodePort","value":32445}]' -n registry
- 配置集群中 registry 的安全信任,打开 /etc/docker/daemon.json 文件,添加以下内容:
"insecure-registries": ["<任意节点IP>:32445"]
- 推送 registry:2 镜像到集群中的 registry 中
docker tag registry:2 <任意节点IP>:32445/registry:2
docker push <任意节点IP>:32445/registry:2
后续操作
在集群外访问 registry
可以通过 <任意节点 IP>:32445
进行访问
在集群内节点访问 registry
可以通过 127.0.0.1:32445
进行访问
部署服务时拉取镜像
可以通过 image: 127.0.0.1:32445/<镜像名称>:<版本号>
成功拉取到镜像