AWS-EKS-15--EKS权限管理(下)Pod 是如何调用 AWS 资源的
摘要
-
本文介绍为EKS集群的 Pod 调用 AWS 资源的方法
-
参考资料:
原理解析
-
在Pod中访问AWS资源,如获取S3中的文件,将ingress绑定到ELB,等等,这些操作都需要被授予相应的权限才可以正常访问。
-
在AWS IAM中的Role可以被授权给基于OIDC身份提供商的外部用户,而在EKS集群中的pod对于AWS IAM来说就属于外部用户,AWS会通过IAM OIDC对这些外部用户的有效性进行校验。
-
前文已经介绍过如何为EKS创建 IAM OIDC 身份提供商,在EKS(K8s)中,并不是直接对Pod进行权限校验,而是ServcieAccount,在 K8s 中,ServiceAccount 是一种用于身份验证和授权的机制,它为 Pod 提供了一个身份标识。每个 Pod 都与一个 ServiceAccount 相关联,并且可以使用该 ServiceAccount 获取与其关联的身份凭据。
-
在EKS(K8s)中可以将ServcieAccount与AWS IAM Role进行绑定,同时将ServcieAccount与Pod进行关联,这样Pod也就具备了相应的IAM Role。
-
EKS(K8s)的 ServcieAccount 通过 Idp(EKS OpenID Connect provider)获得 ID_token并将其发送给 IAM Identity providers ,IAM Identity providers负责获取OIDC的key并验证ID_token的有效性。
-
当ServcieAccount通过IAM OIDC身份校验后,关联的Pod就可以使用相对应的Role获得访问AWS资源的权限。
-
创建Pod时,如果没有为其指定关联的ServcieAccount,则默认使用Pod所在Namespace下的名称为
default
的ServcieAccount,创建Namespace时会自动为其创建该缺省的ServcieAccount,默认其没有绑定任何IAM Role,则缺省继承NodeGroup的IAM Role,NodeGroup的IAM Role是在创建EKS集群时自动创建的,其具有对ECR存储库的只读访问、允许Amazon EKS工作节点连接到Amazon EKS群集等权限。
-
Amazon EKS Pod Identity Webhook 会查看与 service account 关联的 Pods,并向 Pod 提供下列环境变量
- AWS_ROLE_ARN=arn:aws:iam::<ACCOUNT_ID>:role/<IAM_ROLE_NAME>
- AWS_WEB_IDENTITY_TOKEN_FILE=/var/run/secrets/eks.amazonaws.com/serviceaccount/token
-
AWS_ROLE_ARN
就是绑定到ServiceAccount上的IAM Role,AWS_WEB_IDENTITY_TOKEN_FILE
就是要发送给IAM Identity providers的ID_token。 -
默认只有以 root 用户运行的容器才有权限访问 web identity token 文件,当以其它用户运行容器时,需要用 fsGroup 指定一个 groupID。在 Amazon EKS 中,可以将 fsGroup 设置为 65534。这是 Kubernetes 中的推荐做法,因为这个值对应于 nobody 用户和 nogroup 组的 ID。使用 fsGroup: 65534 将确保容器中的非 root 用户具有适当的权限来访问 Web Identity Token 文件。
案例分析
-
前面在安装 AWS Load Balancer Controller 附加组件时,通过如下方式进行授权
1 | $ curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.7/docs/install/iam_policy.json |
-
上面是先通过
aws iam create-policy
命令创建了一个策略,然后通过eksctl create iamserviceaccount
命令为EKS(K8s)创建了一个ServiceAccount,同时创建了一个IAM Role与ServiceAccount绑定,并将该Role与上面创建的策略进行关联。 -
所以实际上,上面的一个命令干了四件事
-
1.创建了一个名称为
AmazonEKSLoadBalancerControllerRole
的IAM角色并关联新建的名称为AWSLoadBalancerControllerIAMPolicy
的策略
-
2.在k8s的
kube-system
namespace下创建了一个名称为aws-load-balancer-controller
的ServiceAccount
1
2
3$ k get sa -n kube-system aws-load-balancer-controller
NAME SECRETS AGE
aws-load-balancer-controller 0 9d- 3.在名称为
AmazonEKSLoadBalancerControllerRole
的IAM角色的信任关系中指定认证方式为OIDC,并且关联名称为aws-load-balancer-controller
的ServiceAccount。
-
4.在名称为
aws-load-balancer-controller
的ServiceAccount中关联上面的角色AmazonEKSLoadBalancerControllerRole
,就是添加注释eks.amazonaws.com/role-arn: arn:aws:iam::743263909644:role/AmazonEKSLoadBalancerControll
。
1
2
3
4
5
6
7
8
9
10
11
12
13$ k edit sa -n kube-system aws-load-balancer-controller
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::743263909644:role/AmazonEKSLoadBalancerControll
creationTimestamp: "2023-07-04T09:20:41Z"
labels:
app.kubernetes.io/managed-by: eksctl
name: aws-load-balancer-controller
namespace: kube-system
resourceVersion: "1707669"
uid: 857200a6-2e16-4939-bbbc-483dd579acbb -
-
然后在创建Pod时,为Pod指定
serviceAccountName: aws-load-balancer-controller
- 默认情况下,在 Kubernetes 中启动的 Pod 不会以 root 用户身份运行,所以在使用基于 OIDC 的身份认证时,当以非 root 用户运行容器时,可以使用 fsGroup 来指定一个组 ID(group ID),以便容器中的用户具有访问 Web Identity Token 文件的权限。在 Amazon EKS 中,可以将 fsGroup 设置为 65534。这是 Kubernetes 中的推荐做法,因为这个值对应于 nobody 用户和 nogroup 组的 ID。使用 fsGroup: 65534 将确保容器中的非 root 用户具有适当的权限来访问 Web Identity Token 文件,确保容器中的用户具有访问
/var/run/secrets/eks.amazonaws.com/serviceaccount/token
文件的权限。
- 默认情况下,在 Kubernetes 中启动的 Pod 不会以 root 用户身份运行,所以在使用基于 OIDC 的身份认证时,当以非 root 用户运行容器时,可以使用 fsGroup 来指定一个组 ID(group ID),以便容器中的用户具有访问 Web Identity Token 文件的权限。在 Amazon EKS 中,可以将 fsGroup 设置为 65534。这是 Kubernetes 中的推荐做法,因为这个值对应于 nobody 用户和 nogroup 组的 ID。使用 fsGroup: 65534 将确保容器中的非 root 用户具有适当的权限来访问 Web Identity Token 文件,确保容器中的用户具有访问
1 | $ kubectl edit deployment -n kube-system aws-load-balancer-controller |
使用aws命令创建角色并关联SA
- 创建Policy
1 | $ curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.7/docs/install/iam_policy.json |
- 创建
trust-policy.json
,用于描述IAM Role的信任关系
1 | { |
上述配置中的 “Condition” 部分是用于在 IAM 角色的信任策略中定义条件。该条件会限制什么样的令牌可以被信任并用于角色的身份验证和授权。
具体来说,“Condition” 对象中的 “StringEquals” 表示字符串相等的条件比较。它包含两个键值对,每个键值对都描述了一个条件。
“oidc.eks.us-west-2.amazonaws.com/id/1029FF88CB872B6B7A1CC65D44191A56:aud”: “sts.amazonaws.com”:这个条件表示 OIDC 令牌中的 “aud”(受众)字段必须与 “sts.amazonaws.com” 相等。也就是说,令牌的受众必须是 AWS Security Token Service (STS)。
“oidc.eks.us-west-2.amazonaws.com/id/1029FF88CB872B6B7A1CC65D44191A56:sub”: “system:serviceaccount:kube-system:aws-load-balancer-controller”:这个条件表示 OIDC 令牌中的 “sub”(主题)字段必须与 “system:serviceaccount:kube-system:aws-load-balancer-controller” 相等。也就是说,令牌的主题必须是 kube-system 命名空间下的 aws-load-balancer-controller Service Account。
这些条件的目的是确保只有满足这两个条件的 OIDC 令牌才能被信任,并被用于通过 OIDC 进行的身份验证和授权操作。这样可以限制对角色的访问,仅允许特定的 OIDC 令牌来获取访问权限。
- 创建 IAM Role
1 | $ aws iam create-role \ |
-
为 Role 添加 Policy
1 | $ aws iam attach-role-policy \ |
-
创建SA
1 | $ kubectl create serviceaccount aws-load-balancer-controller -n kube-system |
-
为SA绑定IAM Role
1 | $ kubectl annotate serviceaccount aws-load-balancer-controller \ |
动手实践
-
搞明白了上面的原理,我们只需要按照上面那的步骤做就可以了,接下来就以Pod访问S3为例进行说明。
-
创建新的策略或使用现有策略,这里我们使用已有的策略
arn:aws:iam::aws:policy/AmazonS3FullAccess
-
使用
eksctl create iamserviceaccount
创建Service和IAM Role,并将它们进行绑定关联
1 | $ eksctl create iamserviceaccount \ |
-
创建一个已经安装过AWS CLI的Pod,这里镜像就使用
amazon/aws-cli
,注意要指定serviceAccountName: test-s3-sa-new
1 | apiVersion: apps/v1 |
1 | # 部署 |