在这篇文章中,我将向你展示如何在 Kubernetes 中使用 imagePullSecrets。
imagePullSecrets 简介
Kubernetes 在每个 Pod 或每个 Namespace 的基础上使用 imagePullSecrets 对私有容器注册表进行身份验证。要做到这一点,你需要创建一个秘密与凭据:
⚠️ 警告:
现在随着公共镜像仓库(如:docker.io 等)开始对匿名用户进行限流,配置公共仓库的身份认证也变得有必要。
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: ```bash 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 \ --docker-email=cuikaidong@foxmail.com BASH |
ℹ️ 信息:
如果 docker.io 启用了「2 阶段认证」,可能需要创建 Access Token(对应上面的
docker-password
,创建链接在这里:账号 -> 安全
现在我们可以在一个 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 YAML |
另一种方法是将它添加到命名空间的默认 ServiceAccount 中:
kubectl patch serviceaccount default \ -p "{\"imagePullSecrets\": [{\"name\": \"image-pull-secret\"}]}" \ -n <your-namespace> BASH |
在 K8S 集群范围使用 imagePullSecrets
我找到了一个叫做 imagepullsecret-patch
的工具,它可以在你所有的命名空间上做这个:
wget https://raw.githubusercontent.com/titansoft-pte-ltd/imagepullsecret-patcher/185aec934bd01fa9b6ade2c44624e5f2023e2784/deploy-example/kubernetes-manifest/1_rbac.yaml wget https://raw.githubusercontent.com/titansoft-pte-ltd/imagepullsecret-patcher/master/deploy-example/kubernetes-manifest/2_deployment.yaml kubectl create ns imagepullsecret-patcher BASH |
编辑下载的文件,一般需要修改 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 BASH |
这里背后创建的资源有:
- 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": "cuikaidong@foxmail.com", "auth": "Y2FzxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxWMy" }, "quay.io": { "auth": "ZWFzdxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxlXWmpNPQ==", "email": "" } } } JSON |
base64 编码后写到 secret 的 .dockerconfigjson
字段即可:
apiVersion: v1 kind: Secret metadata: name: image-pull-secret-src namespace: imagepullsecret-patcher data: .dockerconfigjson: >- eyJhdXRocyI6eyJkb2NrZXIuaW8iOnsidXNlcm5hbWUiOiJjYXNleWN1aSIsInB.............................................IiwiZW1haWwiOiIifX19 type: kubernetes.io/dockerconfigjson YAML |
启动后的 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]" LOG |
今后我们只需要更新 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 |