在 Kubernetes 中,如何使用 Workload Identity 绑定代理?
解读
面试官真正想考察的是:
- 你是否理解 Workload Identity(WI) 在 Google Kubernetes Engine(GKE)中的定位——把 K8s ServiceAccount 映射成 Google IAM ServiceAccount,从而让 Pod 以“云原生”方式调用任何 Google Cloud API,包括 Cloud SQL。
- 你是否能把“绑定代理”这一动作落地:即 让 Cloud SQL Auth Proxy 容器以 WI 身份启动,而不是把 JSON 密钥挂在磁盘或环境变量里。
- 你是否清楚国内网络环境下 GKE 与 Google IAM 的连通性(需合规专线或 VPN),以及 IAM 条件绑定、最小权限、Pod 级隔离 等安全细节。
回答时要体现“零密钥、零运维、可审计”三大优势,并给出可复制的 YAML 片段,才能打动考官。
知识点
- Workload Identity 原理:GKE 元数据服务器把 Pod 的 K8s ServiceAccount 令牌换成 Google STS 令牌,最终拿到 IAM 凭据。
- Cloud SQL Auth Proxy 工作模式:Sidecar 容器通过 Unix Socket 或 TCP 暴露 3307/5432/1433 端口,代表应用与 Cloud SQL 实例建立 TLS 加密的 IAM 认证通道。
- IAM 最小权限:只需授予代理使用的 Google ServiceAccount 角色 roles/cloudsql.client(国内项目常加条件
resource.name == "//sqladmin.googleapis.com/projects/xxx/instances/yyy")。 - 国内落地差异:
– GKE 集群需 开启 Workload Identity 池(国内项目池命名格式PROJECT_ID.svc.id.goog)。
– 若无法直连oauth2.googleapis.com,需在 VPC 出口 NAT 或 Cloud VPN 放通accounts.google.com:443与sqladmin.googleapis.com:443。 - Terraform 模板:用
google_service_account_iam_binding把roles/iam.workloadIdentityUser绑定到 K8s ServiceAccount 的 member 字符串serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]。 - 安全加固:
– 给 Pod 加securityContext.fsGroup=65534保证 Socket 可读。
– 用 PodDisruptionBudget 保证代理容器先于业务容器终止,防止连接闪断。
答案
步骤一:创建 Google ServiceAccount 并授权
export PROJECT_ID=my-gcp-project
export SQL_INSTANCE=my-project:us-central1:mydb
gcloud iam service-accounts create sql-proxy-gsa \
--display-name="GKE Cloud SQL proxy identity"
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:sql-proxy-gsa@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="roles/cloudsql.client"
步骤二:启用集群 Workload Identity 并建立映射
gcloud container clusters create my-cluster \
--region=us-central1 \
--workload-pool=${PROJECT_ID}.svc.id.goog
kubectl create namespace demo
kubectl create serviceaccount sql-proxy-ksa -n demo
gcloud iam service-accounts add-iam-policy-binding \
sql-proxy-gsa@${PROJECT_ID}.iam.gserviceaccount.com \
--role=roles/iam.workloadIdentityUser \
--member="serviceAccount:${PROJECT_ID}.svc.id.goog[demo/sql-proxy-ksa]"
kubectl annotate serviceaccount -n demo sql-proxy-ksa \
iam.gke.io/gcp-service-account=sql-proxy-gsa@${PROJECT_ID}.iam.gserviceaccount.com
步骤三:部署带代理的 Pod(以 MySQL 为例)
apiVersion: apps/v1
kind: Deployment
metadata:
name: webapp
namespace: demo
spec:
replicas: 2
selector:
matchLabels: {app: webapp}
template:
metadata:
labels: {app: webapp}
spec:
serviceAccountName: sql-proxy-ksa # 关键:使用已绑定 WI 的 KSA
containers:
- name: app
image: registry.cn-shanghai.aliyuncs.com/myrepo/app:1.2.0
env:
- name: DB_SOCKET
value: "/cloudsql/my-project:us-central1:mydb"
- name: cloudsql-proxy
image: gcr.io/cloudsql-docker/gce-proxy:1.33.0
command: ["/cloud_sql_proxy",
"-instances=my-project:us-central1:mydb=tcp:0.0.0.0:3307",
"-use_http_health_check",
"-credential_file="] # 空值即强制走 WI
securityContext:
runAsNonRoot: true
runAsUser: 65534
resources:
requests: {cpu: "50m", memory: "64Mi"}
步骤四:验证
kubectl exec -n demo deploy/webapp -c app -- \
mysql -u myuser -p --host=127.0.0.1 --port=3307 --ssl-mode=REQUIRED
若成功登录,说明 Workload Identity 已代替传统密钥完成代理认证。
拓展思考
- 多集群复用:把 IAM 条件绑定 到
attribute.kubernetes_namespace可实现同一 Google ServiceAccount 被多个 GKE 集群共享,但每个集群只能访问指定命名空间,降低密钥爆炸风险。 - 审计与排障:国内项目常因 VPC 出口 IP 变化 导致 STS 调用失败,可在 Cloud Logging 过滤
protoPayload.methodName="GenerateAccessToken"查看拒绝原因;同时给代理加-verbose=true把日志打到 stdout,便于在 阿里云日志服务 SLS 做二次聚合。 - 零信任延伸:结合 Binary Authorization 与 IAM Conditions,可限定只有 签名校验通过且来自指定命名空间 的 Pod 才能拿到 Cloud SQL 访问令牌,实现“代码-身份-网络”三重校验,满足国内金融云合规要求。