如何配置权限使CronJob能够删除/修改Kubernetes Secret?
你的Pod日志暴露了三个核心问题,逐个解决即可:
1. 修复ServiceAccount的Kubernetes权限问题
当前secrets-manager服务账号没有操作Secret的权限,需要创建Role和RoleBinding赋予它对应权限:
创建Role(允许操作Secret)
创建secret-manager-role.yaml文件:
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: secret-manager-role namespace: default rules: - apiGroups: [""] resources: ["secrets"] verbs: ["delete", "create", "get"]
创建RoleBinding(绑定到ServiceAccount)
创建secret-manager-binding.yaml文件:
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: secret-manager-binding namespace: default subjects: - kind: ServiceAccount name: secrets-manager namespace: default roleRef: kind: Role name: secret-manager-role apiGroup: rbac.authorization.k8s.io
应用这两个配置:
kubectl apply -f secret-manager-role.yaml kubectl apply -f secret-manager-binding.yaml
2. 解决aws命令不存在的问题
你使用的bitnami/kubectl:latest镜像未预装AWS CLI,有两种可行方案:
方案一:替换为预装kubectl和AWS CLI的镜像
修改CronJob中的容器镜像为alpine/k8s:1.29.0(版本号可根据你的K8s集群版本调整):
containers: - name: refresh-aws-secret image: alpine/k8s:1.29.0 imagePullPolicy: IfNotPresent
方案二:在启动命令中安装AWS CLI
如果坚持使用原镜像,在command中先安装AWS CLI(基于Alpine系统):
- /bin/sh - -c - |- apk add --no-cache aws-cli && \ kubectl delete secret --ignore-not-found ${SECRET_NAME} && \ kubectl create secret docker-registry ${SECRET_NAME} \ --docker-server=123456789.dkr.ecr.us-east-1.amazonaws.com \ --docker-username=AWS \ --docker-password=$(aws ecr get-login-password --region us-east-1)
注意:给aws ecr get-login-password加上--region us-east-1参数,避免因区域配置缺失导致失败。
3. 赋予Pod访问ECR的AWS权限
要成功执行aws ecr get-login-password,Pod需要对应AWS权限,推荐使用IAM Roles for Service Accounts (IRSA)(适用于EKS集群):
- 创建一个IAM Role,其权限策略包含
ecr:GetAuthorizationToken权限:
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "ecr:GetAuthorizationToken", "Resource": "*" } ] }
- 给
secrets-manager服务账号添加注解,关联这个IAM Role:
kubectl annotate sa secrets-manager eks.amazonaws.com/role-arn=arn:aws:iam::123456789012:role/your-ecr-access-role
替换arn:aws:iam::123456789012:role/your-ecr-access-role为你的实际IAM Role ARN。
如果是非EKS集群,可将AWS凭证(AWS_ACCESS_KEY_ID和AWS_SECRET_ACCESS_KEY)存入K8s Secret,然后挂载到Pod的环境变量中,但这种方式安全性较低,不推荐生产环境使用。
最终修改后的CronJob配置示例
apiVersion: batch/v1 kind: CronJob metadata: name: refresh-aws-secret namespace: default spec: schedule: "* */6 * * *" # 每6小时执行一次 jobTemplate: spec: template: spec: restartPolicy: OnFailure serviceAccount: secrets-manager containers: - name: refresh-aws-secret image: alpine/k8s:1.29.0 imagePullPolicy: IfNotPresent env: - name: SECRET_NAME value: regcred command: - /bin/sh - -c - |- kubectl delete secret --ignore-not-found ${SECRET_NAME} kubectl create secret docker-registry ${SECRET_NAME} \ --docker-server=123456789.dkr.ecr.us-east-1.amazonaws.com \ --docker-username=AWS \ --docker-password=$(aws ecr get-login-password --region us-east-1)
应用修改后的CronJob:
kubectl apply -f /opt/aws.yml
内容的提问来源于stack exchange,提问作者Peter Penzov

