在Kubernetes中为第三方API创建自动续期的Token Secret
每个Kubernetes命名空间里默认存在的default-token-XXXX(类型为kubernetes.io/service-account-token),是K8s自动为默认服务账户生成的认证Token,供Pod内进程调用K8s API时使用,K8s会自动维护这个Token的有效性。
如果要给第三方API(比如AWS/GCP的API)实现类似的自动Token管理——让Token每12小时自动更新,业务直接从Secret取有效Token,不需要手动维护,可以按以下步骤实现:
核心逻辑
创建专用Secret存储第三方API的Token,用CronJob定期检查Token状态,若即将过期则调用第三方API生成新Token并更新Secret。业务Pod只需挂载这个Secret就能拿到有效Token。
具体步骤
1. 创建初始Secret
先手动建一个用来存Token的Secret(后续由CronJob自动更新):
kubectl create secret generic ourapi-token-demo --from-literal=token="临时初始Token"
2. 编写Token更新脚本
以AWS STS临时Token为例
脚本会调用AWS STS生成有效期12小时的临时Token,然后更新K8s Secret:
#!/bin/bash # 调用AWS STS生成临时Token(需确保执行脚本的身份有sts:GetSessionToken权限) AWS_RESPONSE=$(aws sts get-session-token --duration-seconds 43200) NEW_TOKEN=$(echo $AWS_RESPONSE | jq -r '.Credentials.SessionToken') ACCESS_KEY=$(echo $AWS_RESPONSE | jq -r '.Credentials.AccessKeyId') SECRET_KEY=$(echo $AWS_RESPONSE | jq -r '.Credentials.SecretAccessKey') # 更新Secret,用dry-run+apply避免重复创建 kubectl create secret generic ourapi-token-demo \ --from-literal=token="$NEW_TOKEN" \ --from-literal=access-key="$ACCESS_KEY" \ --from-literal=secret-key="$SECRET_KEY" \ --dry-run=client -o yaml | kubectl apply -f -
以GCP访问Token为例
GCP的访问Token默认有效期1小时,脚本可以每55分钟更新一次:
#!/bin/bash # 获取GCP访问Token(需确保执行身份有对应API权限) NEW_TOKEN=$(gcloud auth print-access-token) # 更新Secret kubectl create secret generic ourapi-token-demo \ --from-literal=token="$NEW_TOKEN" \ --dry-run=client -o yaml | kubectl apply -f -
3. 部署CronJob定期执行脚本
写一个CronJob配置,设置执行频率(比如AWS设为每11小时一次,提前1小时更新避免Token过期;GCP设为每55分钟一次):
apiVersion: batch/v1 kind: CronJob metadata: name: ourapi-token-updater spec: schedule: "0 */11 * * *" # AWS用这个,每11小时执行一次;GCP改成"*/55 * * * *" jobTemplate: spec: template: spec: serviceAccountName: token-updater-sa # 绑定了云厂商权限的服务账户 containers: - name: token-updater image: amazon/aws-cli:latest # AWS用这个镜像,GCP换google/cloud-sdk:latest command: ["/bin/sh", "-c"] args: - | # 直接把上面的脚本内容放这里,或者挂载ConfigMap存脚本更方便 AWS_RESPONSE=$(aws sts get-session-token --duration-seconds 43200) NEW_TOKEN=$(echo $AWS_RESPONSE | jq -r '.Credentials.SessionToken') ACCESS_KEY=$(echo $AWS_RESPONSE | jq -r '.Credentials.AccessKeyId') SECRET_KEY=$(echo $AWS_RESPONSE | jq -r '.Credentials.SecretAccessKey') kubectl create secret generic ourapi-token-demo --from-literal=token="$NEW_TOKEN" --from-literal=access-key="$ACCESS_KEY" --from-literal=secret-key="$SECRET_KEY" --dry-run=client -o yaml | kubectl apply -f - restartPolicy: OnFailure
4. 配置必要权限
需要给CronJob用的服务账户token-updater-sa配两类权限:
- 云厂商IAM权限:比如AWS要给
sts:GetSessionToken权限,GCP要给获取访问Token的权限,可以通过IAM角色绑定到K8s服务账户实现。 - K8s权限:允许更新指定的Secret,用Role和RoleBinding配置:
apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: secret-updater-role rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "create", "update", "patch"] resourceNames: ["ourapi-token-demo"] # 指定要更新的Secret名称 --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: secret-updater-binding subjects: - kind: ServiceAccount name: token-updater-sa namespace: default # 替换成你的命名空间 roleRef: kind: Role name: secret-updater-role apiGroup: rbac.authorization.k8s.io
5. 业务Pod使用Token
业务Pod通过Volume挂载这个Secret,直接读取Token文件即可:
apiVersion: v1 kind: Pod metadata: name: business-app-pod spec: containers: - name: business-container image: your-app-image:latest volumeMounts: - name: ourapi-token mountPath: /var/run/secrets/ourapi readOnly: true volumes: - name: ourapi-token secret: secretName: ourapi-token-demo
容器内可以从/var/run/secrets/ourapi/token读取最新的有效Token,业务代码直接用这个路径即可。
内容的提问来源于stack exchange,提问作者NPatel

