Kri*_*isT 9 amazon-web-services aws-cli kubernetes eksctl external-dns
我一直在尝试使用 k8s-sig 组提供的指南运行外部 dns pod。我遵循了指南的每一步,并得到了以下错误。
time="2021-02-27T13:27:20Z" level=error msg="records retrieval failed: failed to list hosted zones: WebIdentityErr: failed to retrieve credentials\ncaused by: AccessDenied: Not authorized to perform sts:AssumeRoleWithWebIdentity\n\tstatus code: 403, request id: 87a3ca86-ceb0-47be-8f90-25d0c2de9f48"
Run Code Online (Sandbox Code Playgroud)
我使用 Terraform 创建了 AWS IAM 策略,并成功创建了它。除了我使用过的服务帐户的 IAM 角色之外eksctl
,其他所有内容都是通过 Terraform 生成的。
但是后来我看到了这篇文章,它说使用 awscli 创建 AWS IAM 策略可以消除这个错误。所以我删除了使用 Terraform 创建的策略,并使用 awscli 重新创建它。然而,它抛出了同样的错误错误。
下面是我的外部 dns yaml 文件。
apiVersion: v1
kind: ServiceAccount
metadata:
name: external-dns
# If you're using Amazon EKS with IAM Roles for Service Accounts, specify the following annotation.
# Otherwise, you may safely omit it.
annotations:
# Substitute your account ID and IAM service role name below.
eks.amazonaws.com/role-arn: arn:aws:iam::268xxxxxxx:role/eksctl-ats-Eks1-addon-iamserviceaccoun-Role1-WMLL93xxxx
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
name: external-dns
rules:
- apiGroups: [""]
resources: ["services","endpoints","pods"]
verbs: ["get","watch","list"]
- apiGroups: ["extensions","networking.k8s.io"]
resources: ["ingresses"]
verbs: ["get","watch","list"]
- apiGroups: [""]
resources: ["nodes"]
verbs: ["list","watch"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: external-dns-viewer
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: external-dns
subjects:
- kind: ServiceAccount
name: external-dns
namespace: default
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: external-dns
spec:
strategy:
type: Recreate
selector:
matchLabels:
app: external-dns
template:
metadata:
labels:
app: external-dns
spec:
serviceAccountName: external-dns
containers:
- name: external-dns
image: k8s.gcr.io/external-dns/external-dns:v0.7.6
args:
- --source=service
- --source=ingress
- --domain-filter=xyz.com # will make ExternalDNS see only the hosted zones matching provided domain, omit to process all available hosted zones
- --provider=aws
- --policy=upsert-only # would prevent ExternalDNS from deleting any records, omit to enable full synchronization
- --aws-zone-type=public # only look at public hosted zones (valid values are public, private or no value for both)
- --registry=txt
- --txt-owner-id=Z0471542U7WSPZxxxx
securityContext:
fsGroup: 65534 # For ExternalDNS to be able to read Kubernetes and AWS token files
Run Code Online (Sandbox Code Playgroud)
我正在挠头,因为网络中的任何地方都没有针对此错误的适当解决方案。希望在本论坛中找到解决此问题的方法。
最终结果必须显示如下内容并填写托管区域中的记录。
time="2020-05-05T02:57:31Z" level=info msg="All records are already up to date"
Run Code Online (Sandbox Code Playgroud)
我也遇到了这个错误。
问题在于信任关系的定义。
您可以在一些官方的 aws 教程(像这样)中看到以下设置:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::${AWS_ACCOUNT_ID}:oidc-provider/${OIDC_PROVIDER}"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"${OIDC_PROVIDER}:sub": "system:serviceaccount:<my-namespace>:<my-service-account>"
}
}
}
]
}
Run Code Online (Sandbox Code Playgroud)
失败的选项 1
我的问题是我在零件my-service-account
的末尾传递了错误的值。${OIDC_PROVIDER}:sub
Condition
失败的选项 2
在上一次修复之后 - 我仍然面临同样的错误 - 通过遵循这个 aws 教程解决了这个问题,该教程显示了使用 eksctl 和以下命令的输出:
eksctl create iamserviceaccount \
--name my-serviceaccount \
--namespace <your-ns> \
--cluster <your-cluster-name> \
--attach-policy-arn arn:aws:iam::aws:policy/AmazonS3ReadOnlyAccess \
--approve
Run Code Online (Sandbox Code Playgroud)
当您查看AWS Web 控制台的信任关系选项卡中的输出时- 您可以看到添加了一个附加条件,后缀为:aud
,值为sts.amazonaws.com
:
所以这需要在"${OIDC_PROVIDER}:sub"
条件之后添加。
小智 5
我能够从 Kubernetes Slack 获得帮助(向@Rob Del 致敬),这就是我们的想法。文章中的 k8s rbac 没有任何问题,问题在于 IAM 角色的编写方式。我正在使用 Terraform v0.12.24,但我相信类似于以下 .tf 的内容应该适用于 Terraform v0.14:
data "aws_caller_identity" "current" {}
resource "aws_iam_role" "external_dns_role" {
name = "external-dns"
assume_role_policy = jsonencode({
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": format(
"arn:aws:iam::${data.aws_caller_identity.current.account_id}:%s",
replace(
"${aws_eks_cluster.<YOUR_CLUSTER_NAME>.identity[0].oidc[0].issuer}",
"https://",
"oidc-provider/"
)
)
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
format(
"%s:sub",
trimprefix(
"${aws_eks_cluster.<YOUR_CLUSTER_NAME>.identity[0].oidc[0].issuer}",
"https://"
)
) : "system:serviceaccount:default:external-dns"
}
}
}
]
})
}
Run Code Online (Sandbox Code Playgroud)
上面的 .tf 假设您使用 terraform 创建了 eks 集群,并且使用external-dns 教程中的rbac 清单。
我这里有几种可能性。
首先,您的集群是否有与其关联的 OIDC 提供商?没有它,IRSA 将无法工作。
您可以在 AWS 控制台中或通过 CLI 使用以下命令进行检查:
aws eks describe-cluster --name {name} --query "cluster.identity.oidc.issuer"
第一的
删除iamserviceaccount
,重新创建它,ServiceAccount
从您的外部 DNS 清单(整个第一部分)中删除定义并重新应用它。
eksctl delete iamserviceaccount --name {name} --namespace {namespace} --cluster {cluster}
eksctl create iamserviceaccount --name {name} --namespace {namespace} --cluster
{cluster} --attach-policy-arn {policy-arn} --approve --override-existing-serviceaccounts
kubectl apply -n {namespace} -f {your-externaldns-manifest.yaml}
Run Code Online (Sandbox Code Playgroud)
可能会发生一些冲突,因为您通过在外部 DNS 清单中eksctl createiamserviceaccount
指定 a 来覆盖您创建的内容。ServiceAccount
第二
将集群升级到 v1.19(如果尚不存在):
eksctl upgrade cluster --name {name}
将向您展示将要做什么;
eksctl upgrade cluster --name {name} --approve
会做的
第三
一些文档建议除了设置之外securityContext.fsGroup: 65534
,您还需要设置securityContext.runAsUser: 0
。
归档时间: |
|
查看次数: |
4449 次 |
最近记录: |