hello云胜

技术与生活

0%

k8s部署deployment,harbor私有项目拉取镜像失败的问题

问题背景:

之前我们部署应用,镜像仓库时自己搭建的harbor,并且使用了的项目都设置为了公开。

这样做确实不规范,所以我们要求所有项目使用自己的私有harbor仓库项目。

然后测试在容器环境下部署deployment时,遇到一个问题。

从私有项目拉取镜像会失败,因为没有通过鉴权。

之前是让用户在页面上自己创建secret,

这种做法让人有点不爽,解决方案如下

  1. 通过kubectl创建secret

    secret的类型是docker-registry

1
kubectl create secret docker-registry harborpaas -n ns001 --docker-server=harbor-test.xxx.net --docker-username=paas --docker-password=XXXXX --docker-email=xxx@xxx.com

​ 我这里创建的secret的名字就是harborpaas

​ 注意后面要用-n 指定namespace,后面是几个关键参数

  1. deployment的yaml文件修改

    加上imagePullSecrets字段

1
2
3
4
5
6
7
8
9
10
apiVersion: apps/v1
kind: Deployment
...
spec:
template:
spec:
containers:
image: $REGISTRY/$HARBOR_NAMESPACE/$APP_NAME:$APP_VERSION-$COMMIT_ID
imagePullSecrets:
- name: harborpaas

注意imagePullSecrets和containers是同级的

这样之后的cicd自动化部署流程就通了。

另外,注意,随着公共镜像仓库(如:docker.io 等)开始对匿名用户进行限流,配置公共仓库的身份认证也变得有必要。我之前就经常遇到docker pull镜像,pull不下来的情况。。这样配置一下也ok了。imagePullSecrets是个列表,可以配置多个secret。

如果不想改yaml文件,还有另一个办法

就是把这个imagePullSecrets添加到命名空间的默认 ServiceAccount 中:

1
2
3
kubectl patch serviceaccount default \
-p "{\"imagePullSecrets\": [{\"name\": \"harborpaas\"}]}" \
-n <your-namespace>

使用了这个ServiceAccount对象创建出来的pod就自然而然通过认证获取到镜像;

原理如下:

如果spec.serviceAccount域没有被设置,那么Kubernetes默认使用名称为default的Service Account。

如果在Pod中没有指定ImagePullSecrets,那么这个spec.serviceAccount域指定的Service Account的ImagePullSecrets会自动加入到该Pod中