我已在 GKE 集群上设置了工作负载身份,现在我使用链接到具有适当权限的 IAM SA 的 Kubernetes SA。我检查过,当我使用 IAM SA 密钥文件时,它会获得我需要的访问权限。
但是,即使遵循 docs,它也会变得奇怪。
第一个建议的检查是运行此命令来检查元数据服务器响应:
$ curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/email
<sa_name>@<project_id>.iam.gserviceaccount.com
到目前为止,一切都很好。描述使用“配额项目”选项的下一段建议使用另一个命令,该命令应返回身份令牌。结果失败了:
$ curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token
Unable to generate access token; IAM returned 404 Not Found: Not found; Gaia id not found for email <sa_name>@<project_id>.iam.gserviceaccount.com
当我使用 .NET SDK 并调用此命令时,也会发生同样的情况:
var oidcToken1 = await cc.GetOidcTokenAsync(
OidcTokenOptions.FromTargetAudience(_serviceUrl),
cancellationToken
);
_addToken = async (request, token) => {
request.Headers.Authorization = new AuthenticationHeaderValue(
"Bearer",
await oidcToken1.GetAccessTokenAsync(cancellationToken: token)
);
};
当我使用 IAM SA JSON 密钥时,代码工作正常,但是当它在使用工作负载身份的 pod 中运行时,我收到与之前相同的消息:
Google.Apis.Auth.OAuth2.ServiceCredential Token has expired, trying to get a new one.
Google.Apis.Http.ConfigurableMessageHandler Request[00000001] (triesRemaining=3) URI: 'http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/identity?audience=https://<service_url>&format=full'
Google.Apis.Http.ConfigurableMessageHandler Response[00000001] Response status: NotFound 'Not Found'
Google.Apis.Http.ConfigurableMessageHandler Response[00000001] An abnormal response wasn't handled. Status code is NotFound
当我使用 Workload Identity 测试容器中的
gcloud auth application-default print-access-token
时,也会发生同样的情况:
错误:(gcloud.auth.application-default.print-access-token)刷新当前身份验证令牌时出现问题:(“无法检索http://metadata.google.internal/computeMetadata/v1/instance/ service-accounts/
@ .iam.gserviceaccount.com/token?scopes=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fcloud-platform 来自 Google 计算引擎元数据服务。状态:404 响应: b'无法生成访问令牌; IAM返回404 Not Found:未找到;找不到电子邮件 @ .iam.gserviceaccount.com 的 Gaia ID '”, )
我不知道还能做什么;似乎整件事都行不通。
我找到了。我犯了一个愚蠢的错误,输错了 Kubernetes 服务账户注释中配置的 IAM 服务账户名称。
Google 支持提供了故障排除指南,我遵循了这些指南,并且重要的是使用上一个命令的输出作为下一个命令的输入(如果适用)。当我尝试使用 Kubernetes 服务帐户注释中的值描述 IAM 服务帐户时,出现“SA not found”错误,这为我提供了解决问题的线索。
我怀疑你要么配置错误了一个步骤(服务帐户的东西特别粗糙),要么你遇到了车祸。
我无法重现您的问题。它对我有用。
BILLING="[YOUR-BILLING-ACCOUNT]"
Q="74552713"
PROJECT=$(whoami)-$(date +%y%m%d)-${Q}
gcloud projects create ${PROJECT}
gcloud beta billing projects link ${PROJECT} \
--billing-account=${BILLING}
gcloud services enable container.googleapis.com \
--project=${PROJECT}
POOL="${PROJECT}.svc.id.goog"
CLUSTER_PROJECT="${PROJECT}"
CLUSTER_NAME="cluster"
CLUSTER_LOCATION="us-west1-c"
# Gets the latest RAPID version
CLUSTER_VERSION=$(\
gcloud container get-server-config \
--project=${PROJECT} \
--zone=${CLUSTER_LOCATION} \
--flatten=channels \
--filter=channels.channel=RAPID \
--format="value(channels.validVersions[0])")
# My go-to test cluster config w/ workload-pool
gcloud beta container clusters create ${CLUSTER_NAME} \
--spot \
--no-enable-basic-auth \
--cluster-version=${CLUSTER_VERSION} \
--release-channel="rapid" \
--machine-type="e2-standard-2" \
--image-type="COS_CONTAINERD" \
--metadata=disable-legacy-endpoints=true \
--num-nodes=1 \
--addons=HorizontalPodAutoscaling,HttpLoadBalancing,GcePersistentDiskCsiDriver \
--enable-ip-alias \
--enable-autoupgrade \
--enable-autorepair \
--enable-managed-prometheus \
--enable-shielded-nodes \
--enable-vertical-pod-autoscaling \
--shielded-secure-boot \
--shielded-integrity-monitoring \
--no-enable-master-authorized-networks \
--max-surge-upgrade=1 \
--max-unavailable-upgrade=0 \
--node-locations=${CLUSTER_LOCATION} \
--zone=${CLUSTER_LOCATION} \
--project=${CLUSTER_PROJECT} \
--workload-pool=${POOL}
# Implicit
# gcloud container clusters get-credentials ${CLUSTER_NAME} ...
# Test that cluster's workloadPool matches expected value
GOT=$(\
gcloud container clusters describe ${CLUSTER_NAME} \
--zone=${CLUSTER_LOCATION} \
--project=${CLUSTER_PROJECT} \
--format="value(workloadIdentityConfig.workloadPool)")
WANT="${POOL}"
[ "${GOT}" == "${WANT}" ] && echo "true" || echo "false"
# Kubernetes == Google Cloud Service Account name
ACCOUNT="tester"
EMAIL="${ACCOUNT}@${PROJECT}.iam.gserviceaccount.com"
NAMESPACE="${Q}"
kubectl create namespace ${NAMESPACE}
kubectl create serviceaccount ${ACCOUNT} \
--namespace=${NAMESPACE}
gcloud iam service-accounts create ${ACCOUNT} \
--project=${PROJECT}
# Redundant for the purpose of this test
ROLE="roles/cloudprofiler.agent"
gcloud projects add-iam-policy-binding ${PROJECT} \
--member="serviceAccount:${EMAIL}" \
--role="${ROLE}"
# Allow Kubernetes robot to impersonate Cloud robot
gcloud iam service-accounts add-iam-policy-binding ${EMAIL} \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:${PROJECT}.svc.id.goog[${NAMESPACE}/${ACCOUNT}]"
# Updated IAM policy for serviceAccount [{EMAIL}].
# bindings:
# - members:
# - serviceAccount:{PROJECT}.svc.id.goog[{NAMESPACE}/{ACCOUNT}]
# role: roles/iam.workloadIdentityUser
# etag: BwXuOwsx9lk=
# version: 1
# Annotate Service Account
kubectl annotate serviceaccount ${ACCOUNT} \
--namespace=${NAMESPACE} \
iam.gke.io/gcp-service-account=${EMAIL}
# Update Pod specs
# spec:
# serviceAccountName: {ACCOUNT}
# nodeSelector:
# iam.gke.io/gke-metadata-server-enabled: "true"
POD="workload-identity-test"
echo "
apiVersion: v1
kind: Pod
metadata:
name: \"${POD}\"
namespace: \"${NAMESPACE}\"
spec:
containers:
- image: google/cloud-sdk:slim
name: \"${POD}\"
command: [\"sleep\",\"infinity\"]
serviceAccountName: \"${ACCOUNT}\"
nodeSelector:
iam.gke.io/gke-metadata-server-enabled: \"true\"
" | kubectl apply --filename=-
# Test that proxied (!) Metadata Service Account email matches
GOT=$(\
kubectl exec \
--stdin --tty \
${POD} \
--namespace=${NAMESPACE} \
-- /bin/bash -c 'curl --header "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/email')
WANT="${EMAIL}"
[ "${GOT}" == "${WANT}" ] && echo "true" || echo "false"
# Demonstrate that access-token is obtained
kubectl exec \
--stdin --tty \
${POD} \
--namespace=${NAMESPACE} \
-- /bin/bash -c 'curl --header "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token' \
| jq -r .access_token[0:15]
# ya29.c.b0Aa9Vdy
除了前面提到的问题之外,还有一项额外的检查(只是为了补充其他答案),我建议非常小心地命名 Kubernetes 服务帐户定义与实际服务帐户名称。
在实现此操作时,我们在 GCP 上将服务帐户命名为 GSA_NAME=
team-api
,Kubernetes 定义命名为 KSA_NAME=team-api-svc-ac
。
我们最终将政策定义为
gcloud iam service-accounts add-iam-policy-binding GSA_NAME@GSA_PROJECT.iam.gserviceaccount.com \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/GSA_NAME]"
当它应该是:
gcloud iam service-accounts add-iam-policy-binding GSA_NAME@GSA_PROJECT.iam.gserviceaccount.com \
--role roles/iam.workloadIdentityUser \
--member "serviceAccount:PROJECT_ID.svc.id.goog[NAMESPACE/KSA_NAME]"
您可以查看此示例的文档,但这是我们可以深入了解细节的步骤之一。
我在尝试使用不存在的服务帐户时遇到了此问题,请仔细检查您的服务帐户电子邮件,确保没有拼写错误。