如何在 K8S 集群範圍使用 imagePullSecret?
- 2022 年 11 月 29 日
- 筆記
- docker, Kubernetes, 雲原生
在這篇文章中,我將向你展示如何在 Kubernetes 中使用 imagePullSecrets。
imagePullSecrets 簡介
Kubernetes 在每個 Pod 或每個 Namespace 的基礎上使用 imagePullSecrets 對私有容器註冊表進行身份驗證。要做到這一點,你需要創建一個秘密與憑據:
{% note warning %}
⚠️ 警告:
現在隨著公共鏡像倉庫(如:docker.io 等)開始對匿名用戶進行限流,配置公共倉庫的身份認證也變得有必要。
{% endnote %}
kubectl create secret docker-registry image-pull-secret \
-n <your-namespace> \
--docker-server=<your-registry-server> \
--docker-username=<your-name> \
--docker-password=<your-password> \
--docker-email=<your-email>
例如配置 docker.io 的 pull secret:
kubectl create secret docker-registry image-pull-secret-src \
-n imagepullsecret-patcher \
--docker-server=docker.io \
--docker-username=caseycui \
--docker-password=c874d654-xxxx-40c6-xxxx-xxxxxxxx89c2 \
[email protected]
{% note info %}
ℹ️ 資訊:
如果 docker.io 啟用了「2 階段認證」,可能需要創建 Access Token(對應上面的 docker-password
,創建鏈接在這裡:帳號 -> 安全
{% endnote %}
現在我們可以在一個 pod 中使用這個 secret 來下載 docker 鏡像:
apiVersion: v1
kind: Pod
metadata:
name: busybox
namespace: private-registry-test
spec:
containers:
- name: my-app
image: my-private-registry.infra/busybox:v1
imagePullSecrets:
- name: image-pull-secret
另一種方法是將它添加到命名空間的默認 ServiceAccount 中:
kubectl patch serviceaccount default \
-p "{\"imagePullSecrets\": [{\"name\": \"image-pull-secret\"}]}" \
-n <your-namespace>
在 K8S 集群範圍使用 imagePullSecrets
我找到了一個叫做 imagepullsecret-patch
的工具,它可以在你所有的命名空間上做這個:
wget //raw.githubusercontent.com/titansoft-pte-ltd/imagepullsecret-patcher/185aec934bd01fa9b6ade2c44624e5f2023e2784/deploy-example/kubernetes-manifest/1_rbac.yaml
wget //raw.githubusercontent.com/titansoft-pte-ltd/imagepullsecret-patcher/master/deploy-example/kubernetes-manifest/2_deployment.yaml
kubectl create ns imagepullsecret-patcher
編輯下載的文件,一般需要修改image-pull-secret-src
的內容,這個 pull secret 就會應用到 K8S 集群範圍。
nano 1_rbac.yaml
nano 2_deployment.yaml
kubectl apply -f 1_rbac.yaml
kubectl apply -f 2_deployment.yaml
這裡背後創建的資源有:
- NameSpace
- RBAC 許可權相關:
imagepullsecret-patcher
ServiceAccountimagepullsecret-patcher
ClusterRole,具有對 service account 和 secret 的所有許可權imagepullsecret-patcher
ClusterRoleBinding,為imagepullsecret-patcher
ServiceAccount 賦予imagepullsecret-patcher
ClusterRole 的許可權。
- 全局 pull secret
image-pull-secret-src
,裡面是你的 K8S 全局包含的所有的鏡像庫地址和認證資訊。 - Deployment
imagepullsecret-patcher
,指定 ServiceAccount 是imagepullsecret-patcher
就有了操作 service account 和 secret 的所有許可權,並將上面的 secret 掛載到 Deployment pod 內。
可以包含多個鏡像庫地址和認證資訊,如:
{
"auths": {
"docker.io": {
"username": "caseycui",
"password": "c874xxxxxxxxxxxxxxxx1f89c2",
"email": "[email protected]",
"auth": "Y2FzxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxWMy"
},
"quay.io": {
"auth": "ZWFzdxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxlXWmpNPQ==",
"email": ""
}
}
}
base64 編碼後寫到 secret 的 .dockerconfigjson
欄位即可:
apiVersion: v1
kind: Secret
metadata:
name: image-pull-secret-src
namespace: imagepullsecret-patcher
data:
.dockerconfigjson: >-
eyJhdXRocyI6eyJkb2NrZXIuaW8iOnsidXNlcm5hbWUiOiJjYXNleWN1aSIsInB.............................................IiwiZW1haWwiOiIifX19
type: kubernetes.io/dockerconfigjson
啟動後的 pod 會在所有 NameSpace 下創建 image-pull-secret
secret(內容來自於image-pull-secret-src
) 並把它 patch 到 default
service account 及該 K8S 集群的所有 ServiceAccount 里,日誌如下:
time="2022-01-12T16:07:30Z" level=info msg="Application started"
time="2022-01-12T16:07:30Z" level=info msg="[default] Created secret"
time="2022-01-12T16:07:30Z" level=info msg="[default] Patched imagePullSecrets to service account [default]"
time="2022-01-12T16:07:30Z" level=info msg="[kube-system] Created secret"
time="2022-01-12T16:07:31Z" level=info msg="[kube-system] Patched imagePullSecrets to service account [node-controller]"
...
time="2022-01-12T16:07:37Z" level=info msg="[kube-public] Created secret"
time="2022-01-12T16:07:37Z" level=info msg="[kube-public] Patched imagePullSecrets to service account [default]"
time="2022-01-12T16:07:38Z" level=info msg="[kube-node-lease] Created secret"
time="2022-01-12T16:07:38Z" level=info msg="[kube-node-lease] Patched imagePullSecrets to service account [default]"
time="2022-01-12T16:07:38Z" level=info msg="[prometheus] Created secret"
time="2022-01-12T16:07:39Z" level=info msg="[prometheus] Patched imagePullSecrets to service account [default]"
...
time="2022-01-12T16:07:41Z" level=info msg="[imagepullsecret-patcher] Created secret"
time="2022-01-12T16:07:41Z" level=info msg="[imagepullsecret-patcher] Patched imagePullSecrets to service account [default]"
time="2022-01-12T16:07:41Z" level=info msg="[imagepullsecret-patcher] Patched imagePullSecrets to service account [imagepullsecret-patcher]"
今後我們只需要更新 image-pull-secret-src
這一個即可了。👍️👍️👍️
Kyverno policy
Kyverno policy 可以實現同樣的效果:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: sync-secret
spec:
background: false
rules:
- name: sync-image-pull-secret
match:
resources:
kinds:
- Namespace
generate:
kind: Secret
name: image-pull-secret
namespace: "{{request.object.metadata.name}}"
synchronize: true
clone:
namespace: default
name: image-pull-secret
---
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: mutate-imagepullsecret
spec:
rules:
- name: mutate-imagepullsecret
match:
resources:
kinds:
- Pod
mutate:
patchStrategicMerge:
spec:
imagePullSecrets:
- name: image-pull-secret ## imagePullSecret that you created with docker hub pro account
(containers):
- (image): "*" ## match all container images