1. 前言
《Harbor入门篇》一文中,我们已经安装配置好了Harbor。
本文中,我们来学习一下怎样在K8S中配置使用imagePullSecrets,从Harbor或者其他私有镜像仓库拉取镜像。
参考文档:
2. 创建imagePullSecrets
创建一个docker-registry类型的secret,名字为harbor-secret
1 2 3 4
| kubectl create secret docker-registry harbor-secret \ --docker-server=harbor.voidking.com \ --docker-username=admin \ --docker-password=Harbor12345
|
3. 使用imagePullSecrets
1 2 3 4 5 6 7 8 9 10 11 12 13
| apiVersion: v1 kind: Pod metadata: name: testpod spec: containers: - name: busybox image: harbor.voidking.com/voidking/busybox:1.31 command: - sleep - "3600" imagePullSecrets: - name: harbor-secret
|
4. 给pod添加默认imagePullSecrets
上面的配置,已经可以正常从harbor镜像仓库拉取镜像了。
但是,每个pod都需要指定一下imagePullSecrets,也是比较麻烦。
这里我们可以在命名空间默认sa中添加imagePullSecrets,这样我们就不用在pod中指定imagePullSecrets了,创建pod时会自动注入。
1 2 3
| kubectl patch serviceaccount default \ -p "{\"imagePullSecrets\": [{\"name\": \"docker-secret\"}]}" \ -n <your-namespace>
|
5. 全局配置imagePullSecrets
如果新增了namespace,那么这个namespace就需要单独添加一次imagePullSecrets,而且这个namespace的sa也需要添加imagePullSecrets。
这里可以使用imagepullsecret-patcher来简化我们的工作,参考文档:
1、获取 dockerconfigjson
1 2 3 4 5 6
| kubectl create secret docker-registry harbor-secret \ --docker-server=harbor.voidking.com \ --docker-username=admin \ --docker-password=Harbor12345 \ --dry-run=client -oyaml
|
获取到 dockerconfigjson ,填入到下一步的 deployment.yaml 文件中。
2、准备资源清单
- namespace.yaml,定义namespace
- rbac.yaml,定义sa权限
- deployment,定义imagepullsecret-patcher服务
namespace.yaml 内容如下:
1 2 3 4
| apiVersion: v1 kind: Namespace metadata: name: imagepullsecret-patcher
|
rbac.yaml 内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| apiVersion: v1 kind: ServiceAccount metadata: name: imagepullsecret-patcher namespace: imagepullsecret-patcher --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: labels: k8s-app: imagepullsecret-patcher name: imagepullsecret-patcher rules: - apiGroups: - "" resources: - secrets - serviceaccounts verbs: - list - patch - create - get - delete - apiGroups: - "" resources: - namespaces verbs: - list - get --- apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: imagepullsecret-patcher roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: imagepullsecret-patcher subjects: - kind: ServiceAccount name: imagepullsecret-patcher namespace: imagepullsecret-patcher
|
deployment.yaml 内容如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
| apiVersion: v1 kind: Secret type: kubernetes.io/dockerconfigjson metadata: name: image-pull-secret-src namespace: imagepullsecret-patcher data: .dockerconfigjson: eyJhdXRocyI6eyJoYXJib3Iudm9pZGtpbmcuY29tIjp7InVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6IkhhcmJvcjEyMzQ1IiwiYXV0aCI6IllXUnRhVzQ2U0dGeVltOXlNVEl6TkRVPSJ9fX0= --- apiVersion: apps/v1 kind: Deployment metadata: name: imagepullsecret-patcher namespace: imagepullsecret-patcher labels: name: imagepullsecret-patcher spec: replicas: 1 selector: matchLabels: name: imagepullsecret-patcher template: metadata: labels: name: imagepullsecret-patcher spec: automountServiceAccountToken: true serviceAccountName: imagepullsecret-patcher containers: - name: imagepullsecret-patcher image: "quay.io/titansoft/imagepullsecret-patcher:v0.14" env: - name: CONFIG_FORCE value: "true" - name: CONFIG_DEBUG value: "false" - name: CONFIG_ALLSERVICEACCOUNT value: "true" - name: CONFIG_DOCKERCONFIGJSONPATH value: "/app/secrets/.dockerconfigjson" - name: CONFIG_SECRETNAME value: "harbor-secret" volumeMounts: - name: src-dockerconfigjson mountPath: "/app/secrets" readOnly: true resources: requests: cpu: 0.1 memory: 15Mi limits: cpu: 0.2 memory: 30Mi volumes: - name: src-dockerconfigjson secret: secretName: image-pull-secret-src
|
其中dockerconfigjson改成上一步中获取到的dockerconfigjson,CONFIG_SECRETNAME变量的value改成期望的secret名称。
3、安装imagepullsecret-patcher
1 2 3
| kubectl apply -f namespace.yaml kubectl apply -f rbac.yaml kubectl apply -f deployment.yaml
|
4、查看安装
1 2 3
| kubectl get all -n imagepullsecret-patcher kubectl get sa -n imagepullsecret-patcher kubectl get sa default -n imagepullsecret-patcher -oyaml
|
可以发现,harbor-secret
已经注入到了sa中。
6. 修改imagePullSecrets
有时候,我们需要修改imagePullSecrets,比如修改用户名和密码。这时可以直接修改 image-pull-secret-src 这个secret,修改完成后,imagepullsecret-patcher会自动完成所有namespace下的 harbor-secret 的修改。
1
| kubectl edit secret image-pull-secret-src -n imagepullsecret-patcher
|
7. 删除imagePullSecrets
有时候,我们需要替换imagePullSecrets,比如imagePullSecrets名称发生了变更。这时就需要删除原本的imagePullSecrets。
单个sa删除imagePullSecrets方法:
1 2
| INDEX=$(kubectl get sa default -n imagepullsecret-patcher -o json | jq '.imagePullSecrets | map(.name == "harbor-secret") | index(true)') kubectl patch sa default --type=json -p="[{'op': 'remove', 'path': '/imagePullSecrets/$INDEX'}]" -n imagepullsecret-patcher
|
批量sa删除imagePullSecrets方法:
1 2 3 4 5 6 7
| #!/bin/bash kubectl get ns | awk '{print $1}' | grep -v "NAME" > namespace.txt
for namespace in `cat namespace.txt`;do INDEX=$(kubectl get sa default -n $namespace -o json | jq '.imagePullSecrets | map(.name == "harbor-secret") | index(true)') kubectl patch sa default --type=json -p="[{'op': 'remove', 'path': '/imagePullSecrets/$INDEX'}]" -n $namespace done
|
8. 添加多个imagePullSecrets
问:如果有多个镜像仓库需要配置imagePullSecrets,该怎么处理?
答:可以把多个imagePullSecrets写入到同一个dockerconfigjson。
8.1. dockerconfigjson解析
dockerconfigjson是一个base64加密的字符串,执行
1
| echo "eyJhdXRocyI6eyJoYXJib3Iudm9pZGtpbmcuY29tIjp7InVzZXJuYW1lIjoiYWRtaW4iLCJwYXNzd29yZCI6IkhhcmJvcjEyMzQ1IiwiYXV0aCI6IllXUnRhVzQ2U0dGeVltOXlNVEl6TkRVPSJ9fX0=" | base64 -d
|
结果为:
1
| {"auths":{"harbor.voidking.com":{"username":"admin","password":"Harbor12345","auth":"YWRtaW46SGFyYm9yMTIzNDU="}}}
|
实际上,它的结构和docker login
后产生的$HOME/.docker/config.json
完全一致。
其中,auth的value也是base64加密的字符串,执行
1
| echo "YWRtaW46SGFyYm9yMTIzNDU=" | base64 -d
|
结果为:
8.2. dockerconfigjson拼接
知道了dockerconfigjson的结构,那么我们可以知道,如果有多个imagePullSecrets,我们可以自己拼接一个dockerconfigjson明文字符串,然后进行base64加密。
dockerconfigjson1 内容为:
1
| {"auths":{"harbor.voidking.com":{"username":"admin","password":"Harbor12345","auth":"YWRtaW46SGFyYm9yMTIzNDU="}}}
|
dockerconfigjson2 内容为:
1 2 3 4 5 6 7 8 9
| { "auths": { "harbor1.voidking.com": { "username": "haojin", "password": "haojin123", "auth": "aGFvamluOmhhb2ppbjEyMwo=" } } }
|
那么 dockerconfigjson1 和 dockerconfigjson2 可以拼接成一个明文dockerconfigjson:
1
| jq -n 'reduce inputs as $i ({}; . * $i)' dockerconfigjson1 dockerconfigjson2 | jq -c
|
然后通过base64加密,就是我们需要的加密后的dockerconfigjson。
1
| jq -n 'reduce inputs as $i ({}; . * $i)' dockerconfigjson1 dockerconfigjson2 | jq -c | base64 | tr -d '\n'
|
参考文档: