k8s从私有仓库拉取镜像创建pod时ImagePullBackOff
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了k8s从私有仓库拉取镜像创建pod时ImagePullBackOff相关的知识,希望对你有一定的参考价值。
参考技术A假如我们自己搭建了私有仓库,并在其中上传了需要使用的镜像。这时候我们在k8s集群的机器上,通过 docker pull 是能拉取到私有仓库镜像的。但是k8s是获取不到docker的私有仓库的认证信息的,这时候就会出现ImagePullBackOff的问题。
yaml文件的imagePullPolicy支持Always、IfNotPresent和Never三种方式,如果不写默认就是Always,所以我们可以在临时使用的机器上通过 docker pull 把需要的镜像拉下来,然后设置imagePullPolicy为IfNotPresent或者Never,这样k8s就不会去pull镜像。
如果设置imagePullPolicy为Always,就算你通过 docker pull 预先把需要的镜像拉下来了,k8s还是会去pull镜像,并且拉取不了就报错。
如果是实际生产,这个方法明显有很多问题,所以是 临时 。
官方文档
Kubernetes中部署Docker registry2.7.1并通过containerd实现拉取镜像到应用Pod的部署
这里主要介绍一下私有仓库(HTTPS)在Kubernetes中部署的问题,由于Kubernetes将弃用docker,因此这里主要介绍以下使用containerd替换docker后如何从私有仓库拉取镜像并完成镜像的部署。
下载registry2.7.1的镜像文件
说明:在使用registry2.3.1的话会有一个严重的问题,问题就是在yaml或者在命令行通过ctr和crictl命令拉取镜像时携带的sha256值和私有仓库中镜像存储的实际sha256不一致,因此会报找不到镜像的问题:not found: not found的错误,所以尽量使用2.7.1版本以上的镜像,并且2.7.1版本以上的仓库支持加密镜像的存储。
docker pull registry:2.7.1
生成证书文件
这里说明一下:由于containerd默认的仓库为docker.io,因此在创建私有仓库时使用IP地址才会在后面的操作中避开它自动连接到默认仓库的问题,因此在制作证书的这步就要提前考虑好该问题,因为在证书制作的过程中CN字段的值就要设置为IP地址。
# 在集群中某个节点找个位置新建一个文件夹
mkdir docker-registry
cd docker-registry
mkdir certs
# 生成2048位的私钥,也可以生成4096位的,看自己需求
openssl genrsa -out Yuan.key 2048
# 生成证书请求文件
openssl req -new -key Yuan.key -subj "/CN=10.131.82.53" -out Yuan.csr
# 将IP地址写入一个文件,为了解决上述所说的那个问题
echo subjectAltName = IP:10.131.82.53>extfile.cnf
# 这里的ca我就使用了集群自带的,在/etc/kubernetes/pki/下
openssl x509 -req -in Yuan.csr -CA ca.crt -CAkey ca.key -CAcreateserial -extfile extfile.cnf -out Yuan.crt -days 5000
# 查看证书信息
openssl x509 -in Yuan.crt -noout -text
# 将生存的证书信息追加到系统的证书管理文件后
cat Yuan.crt >> /etc/pki/tls/certs/ca-bundle.crt
在大概中间的位置会看到一个类似下图的信息:
不然会报如下的错误:
x509: cannot validate certificate for 10.131.82.53 because it doesn\\\'t contain any IP SANs
生成密码认证文件
yum install httpd-tools
mkdir auth
htpasswd -Bbn Yuan Abcd123456 > /home/docker-registry/auth/htpasswd
部署私有仓库
编写部署文件
docker-registry.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: docker-registry
namespace: default
spec:
selector:
matchLabels:
app: docker-registry
spec:
nodeSelector:
kubernetes.io/hostname: master1
containers:
- name: docker-registry
image: docker.io/library/registry:2.3.1
imagePullPolicy: IfNotPresent
ports:
- containerPort: 8443
env:
- name: REGISTRY_HTTP_ADDR
value: "0.0.0.0:8443"
- name: REGISTRY_HTTP_TLS_CERTIFICATE
value: "/certs/Yuan.crt"
- name: REGISTRY_HTTP_TLS_KEY
value: "/certs/Yuan.key"
- name: REGISTRY_AUTH
value: "htpasswd"
- name: REGISTRY_AUTH_HTPASSWD_PATH
value: "/auth/htpasswd"
- name: REGISTRY_AUTH_HTPASSWD_REALM
value: "Registry Realm"
volumeMounts:
- name: reg-data
mountPath: /vat/lib/registry
- name: reg-auth
mountPath: /auth
- name: reg-certs
mountPath: /certs
volumes:
- name: reg-data
hostPath:
path: /home/docker-registry/images
- name: reg-auth
hostPath:
path: /home/docker-registry/auth
- name: reg-certs
hostPath:
path: /home/docker-registry/certs
---
apiVersion: v1
kind: Service
metadata:
name: docker-registry
namespace: default
spec:
type: NodePort
ports:
- port: 8443
targetPort: 8443
nodePort: 443
protocol: TCP
selector:
app: docker-registry
部署私有仓库
kubectl apply -f docker-registry.yaml
#如果报错如下
Invalid value: 443: provided port is not in the valid range. The range of valid ports is 30000-32767
#解决方法为修改apiserver的启动参数
vim /etc/kubernetes/manifests/kube-apiserver.yaml
# 添加如下配置
- --service-node-port-range=1-65535
curl访问仓库
# 查看仓库信息
curl -k -u Yuan:Abcd123456 -X GET https://10.131.82.53:443/v2/_catalog
在另一台机器docker登陆
docker login 10.131.82.53:443 -u Yuan -p Abcd123456
# 报错如下
Error response from daemon: Get https://10.131.82.53:443/v2/: x509: certificate signed by unknown authority
# 解决方法如下
vi /etc/docker/daemon.json
# 添加
{
"insecure-registries": ["10.131.82.53:443"]
}
systemctl daemon-reload
systemctl restart docker
# push镜像到仓库
docker tag nginx:v1 10.131.82.53:443/nginx:v1
docker push 10.131.82.53:443/nginx:v1
# 从仓库pull镜像
docker pull 10.131.82.53:443/nginx:v1
curl 查看仓库中的镜像
# 查看仓库中镜像
curl -k -u Yuan:Abcd123456 -X GET https://10.131.82.53:443/v2/nginx/tags/list
ctr命令push镜像(crictl没有push命令)
# 查看本地仓库的镜像
ctr -n k8s.io i ls -q
# 任意选一个修改tag
ctr -n k8s.io tag docker.io/foo-apiserver:latest 10.131.82.53:443/foo-apiserver:latest
# push镜像到仓库
ctr -n k8s.io push 10.131.82.53:443/foo-apiserver:latest -k --user Yuan:Abcd123456
ctr命令pull镜像
# 从仓库pull镜像
ctr i pull 10.131.82.53:443/foo-apiserver:latest --user Yuan:Abcd123456
crictl命令pull镜像
# 从仓库pull镜像
crictl pull 10.131.82.53:443/foo-apiserver:latest --creds Yuan:Abcd123456
# 如果使用registry2.3.1版本镜像仓库时会报错如下
pulling image: rpc error: code = NotFound desc = failed to pull and unpack image: ...sha256:2f...... not found: not found
# 因为crictl命令无法跳过ssl认证,因此会报错如下
x509: certificate signed by unknown authority
# 则需要修改/etc/containerd/config.toml文件
[plugins."io.containerd.grpc.v1.cri".registry]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
endpoint = ["https://registry-1.docker.io"]
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."10.131.82.53:443"]
endpoint = ["https://10.131.82.53:443"]
[plugins."io.containerd.grpc.v1.cri".registry.configs]
[plugins."io.containerd.grpc.v1.cri".registry.configs."10.131.82.53:443".tls]
insecure_skip_verify = true
[plugins."io.containerd.grpc.v1.cri".registry.configs]
[plugins."io.containerd.grpc.v1.cri".registry.configs."10.131.82.53:443".auth]
username = "Yuan"
password = "Abcd123456"
至此,我们已经完成了基本所有的验证工作,下面就写一个yaml文件验证一下我们搭建的私有仓库是否能正常提供服务
部署应用验证私有仓库
编写部署应用的Pod的yaml文件
pod-pull-test.yaml
apiVersion: v1
kind: Pod
metadata:
name: pod-pull-test
spec:
nodeSelector:
kubernetes.io/hostname: master1
containers:
- name: pod-pull-test
image: 10.131.82.53:443/nginx:v1
imagePullPolicy: Always
imagePullSecrets:
- name: registrykey
其中最后两行是访问仓库的服务地址及认证信息
kubectl create secret docker-registry registrykey --docker-server=10.131.82.53:443 --docker-username=Yuan --docker-password=Abcd123456 --docker-email=Yuan_sr@163.com
通过执行kubectl apply -f pod-pull-test.yaml即可从私有仓库拉取镜像部署应用
以上是关于k8s从私有仓库拉取镜像创建pod时ImagePullBackOff的主要内容,如果未能解决你的问题,请参考以下文章