
一般情况下,Kubernetes从docker hub拉取镜像,不过在局域网环境中,有时候会碰到互联网访问瓶颈,难以访问docker hub。
在这种情况下,你可以在集群里面搭建一个私有镜像仓库,把自己的镜像放在上面,即使没有互联网,也不会影响你更新和拉取自己的镜像文件。
说一下K3S集群下面怎么搭建。操作系统Debian 12 ,K3S 1.28.4。
一、安装私有镜像仓库
1.生成证书和认证文件
在master1节点上,运行
mkdir -p /registry && cd "$_"
mkdir certs
openssl req -x509 -newkey rsa:4096 -days 365 -nodes -sha256 -keyout certs/tls.key -out certs/tls.crt -subj "/CN=docker-registry" -addext "subjectAltName = DNS:docker-registry"
apt install apache2-utils
mkdir auth
htpasswd -Bbn myuser mypasswd > auth/htpasswd
其中 myuser和mypasswd是访问仓库的用户名和密码,根据实际情况修改。
2.生成证书和认证密钥
kubectl create secret tls certs-secret --cert=/registry/certs/tls.crt --key=/registry/certs/tls.key
kubectl create secret generic auth-secret --from-file=/registry/auth/htpasswd
3.为私有镜像仓库准备PV和PVC
把下列内容保存到文件registry-volume.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: docker-repo-pv
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: /tmp/repository
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: docker-repo-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
运行下列命令生效
kubectl create -f registry-volume.yaml
4. 部署镜像仓库pod和service
把下列内容保存到文件docker-registry-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: docker-registry-pod
labels:
app: registry
spec:
containers:
- name: registry
image: registry:2
volumeMounts:
- name: repo-vol
mountPath: "/var/lib/registry"
- name: certs-vol
mountPath: "/certs"
readOnly: true
- name: auth-vol
mountPath: "/auth"
readOnly: true
env:
- name: REGISTRY_AUTH
value: "htpasswd"
- name: REGISTRY_AUTH_HTPASSWD_REALM
value: "Registry Realm"
- name: REGISTRY_AUTH_HTPASSWD_PATH
value: "/auth/htpasswd"
- name: REGISTRY_HTTP_TLS_CERTIFICATE
value: "/certs/tls.crt"
- name: REGISTRY_HTTP_TLS_KEY
value: "/certs/tls.key"
volumes:
- name: repo-vol
persistentVolumeClaim:
claimName: docker-repo-pvc
- name: certs-vol
secret:
secretName: certs-secret
- name: auth-vol
secret:
secretName: auth-secret
---
apiVersion: v1
kind: Service
metadata:
name: docker-registry
spec:
selector:
app: registry
ports:
- port: 5000
targetPort: 5000
运行下列命令生效
kubectl create -f docker-registry-pod.yaml
5. 修改每台主机的hosts文件,把证书文件复制到每个主机节点
首先,启用每台主机的ssh root登录。
登录到集群的每台主机上,修改/etc/ssh/sshd_config文件, 添加一行
PermitRootLogin yes
运行 systemctl restart sshd 生效。
在master1主机上,运行
kubectl get svc docker-registry
得到私有仓库service的IP地址。
然后运行
export REGISTRY_NAME="docker-registry"
export REGISTRY_IP="<docker-registry-service-ip>"
其中<docker-registry-service-ip>是私有仓库service的IP地址,根据实际情况修改。
运行
for x in $(kubectl get nodes -o jsonpath='{ $.items[*].status.addresses[?(@.type=="InternalIP")].address }'); do ssh root@$x "echo '$REGISTRY_IP $REGISTRY_NAME' >> /etc/hosts"; done
修改每台主机的hosts文件,把主机名docker-registry添加进去。
运行
for x in $(kubectl get nodes -o jsonpath='{ $.items[*].status.addresses[?(@.type=="InternalIP")].address }'); do scp /registry/certs/* root@$x:/usr/local/share/ca-certificates/; ssh root@$x "update-ca-certificates"; done
把证书文件复制到每台主机,更新主机的根证书。
6. 创建k3s 仓库注册文件
把下列内容保存到文件/etc/rancher/k3s/registries.yaml
mirrors:
docker-registry:5000:
endpoint:
- "https://docker-registry:5000/v2"
configs:
docker-registry:5000:
auth:
username: myuser
password: mypasswd
tls:
ca_file: "/usr/local/share/ca-certificates/tls.crt"
key_file: "/usr/local/share/ca-certificates/tls.key"
cert_file: "/usr/local/share/ca-certificates/tls.key"
其中myuser和mypasswd是访问仓库的用户名和密码,根据实际情况修改。
运行
for x in $(kubectl get nodes -o jsonpath='{ $.items[*].status.addresses[?(@.type=="InternalIP")].address }'); do ssh root@$x "mkdir /etc/rancher/k3s/"; scp /etc/rancher/k3s/registries.yaml root@$x:/etc/rancher/k3s/; done
把文件复制到每台主机。
在每台主机上运行systemctl restart k3s 或者systemctl restart k3s-agent生效。
运行
kubectl create secret docker-registry reg-cred-secret --docker-server=$REGISTRY_NAME:5000 --docker-username=myuser --docker-password=mypasswd
生成仓库访问密钥。其中myuser和mypasswd是访问仓库的用户名和密码,根据实际情况修改。
至此,私有镜像仓库安装部署完成。
二、测试
1. 把镜像文件上传到私有镜像仓库
运行
crictl pull nginx
ctr image tag docker.io/library/nginx:latest docker-registry:5000/mynginx:v1
ctr image push --platform linux/amd64 --user myuser:mypasswd docker-registry:5000/mynginx:v1
其中myuser和mypasswd是访问仓库的用户名和密码,根据实际情况修改。
2. 从私有镜像仓库拉取并运行镜像
运行
kubectl run nginx-pod --image=docker-registry:5000/mynginx:v1 --overrides='{ "apiVersion": "v1", "spec": { "imagePullSecrets": [{"name": "reg-cred-secret"}] } }'
运行
kubectl get pods -o wide
观察nginx-pod的运行情况,记下它的内部IP地址。
运行
curl <nginx-pod-ip>:80
其中nginx-pod-ip是nginx-pod的内部IP,根据实际情况修改。
运行结果应该是返回nginx的HTML首页代码。
测试完成。
参考: