场景

当我们需要部署应用至多个 AWS 账号下的多个 EKS 集群(Prod, Stage, Dev, etc)。结合安全最佳实践,kubectl 所在的 EC2 尽量避免配置明文的 IAM
access key, secret key,以增强安全性,同时需要做到简化管理,避免频繁进行手工配置临时 token 等操作。

解决方案&配置步骤

假设 kubectl 所在的 EC2 云主机(Jenkins server)在 A 账号,EKS 集群在 B 账号,可在两个账号里通过 AWS console 分别创建一个 AWS role:
1.A 账号的 role(假设叫 jenkins-eks-role)用于 attach 到 EC2 云主机上。创建该 role 时,选择trust entity 是 AWS Service-EC2, IAM policy 具备 sts:assumerole 权限,能够 assume 所有 EKS
集群环境的 AWS 账号里的 role。
请参考以下示例 IAM Policy (可进一步根据需求定制):

{
 "Version": "2012-10-17",
 "Statement": {
 "Effect": "Allow",
 "Action": "sts:AssumeRole",
 "Resource": "*"
 }}

该 role 创建好后,记录 role-arn(第 2 步用到), 即可将它 attach 到 EC2 主机。
关于对某一台 EC2 实例 attach role 的操作请参考:
https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazonec2.html#attach-iam-role
2.B 账号的 role(假设叫 jenkins-role), 创建时 trust entity 选择’Another AWS account‘并填入 B
账号的 ID, IAM policy 可以空白,trust relationship policy 设置为信任 A 账号的 jenkins-eksrole.
请参考以下示例 Trust Policy:

{
 "Version": "2012-10-17",
 "Statement": [
 {
 "Effect": "Allow",
 "Principal": { "AWS": "<arn-of-jenkins-eks-role>" },
 "Action": "sts:AssumeRole",
 }]
 }

创建后记录该 role arn,第 3 步会用到。
3.在 B 账号下,为第 2 步创建的 role 赋予 eks 集群权限(符合 k8s 的 RBAC 权限定义,非
IAM policy 的权限)。详细步骤可参考:
https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html
文档中提到的 Configmap 文件在这里类似以下格式(假设第 2 步生成的 Role ARN 是 ‘arn:aws:iam::111122223333:role/jenkins-role’):

apiVersion: v1
data:
 mapRoles: |
 - rolearn: arn:aws:iam::111122223333:role/jenkins-role
 groups:
 - <system:masters>

4.用 B 账号具有 eks 权限的 IAM user(如 admin user),在一个具有 AWS 命令行工具的环
境下(如用于运维的 EC2 主机)做如下 aws 命令行操作,以生成 B 账号 EKS 集群的
kubeconfig 文件:
aws eks --region update-kubeconfig --name <cluster_name> --role-arn

查看该文件,
cat ~/.kube/config
看看内容格式是否类似以下 (重点关注 users 下面的内容):

apiVersion: v1
clusters:
- cluster:
 certificate-authority-data: 
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUN5RENDQWJDZ0F3SUJBZ0lCQURBTkJna3Foa2
lHOXcwQkFRc0ZBREFWTVJNd0VRWSXlOVEEyTU <此处省略 n 个字
符>VZUVBYROFRlYnhMzhaVWhvUXQzWT00VSVElGSUNBVEUtLS0tLQo=
 server: https://0AFEC856BC419483532423344A5B414DB9.gr5.cn-northwest-
1.eks.amazonaws.com.cn
 name: zhy1.cn-northwest-1.eksctl.io
contexts:
- context:
 cluster: zhy1.cn-northwest-1.eksctl.io
 user: bob@zhy1.cn-northwest-1.eksctl.io
 name: bob@zhy1.cn-northwest-1.eksctl.io
current-context: bob@zhy1.cn-northwest-1.eksctl.io
kind: Config
preferences: {}
users:
- name: bob@zhy1.cn-northwest-1.eksctl.io
 user:
 exec:
 apiVersion: client.authentication.k8s.io/v1alpha1
 args:
 - eks
 - get-token
 - --cluster-name
 - zhy1
 - --region
 - cn-northwest-1
 - --role-arn
 - arn:aws:iam:: 111122223333:role/jenkins-role
 command: aws
 env:
 - name: AWS_STS_REGIONAL_ENDPOINTS
 value: regional

注意到 B 账号的 jenkins-role 已经在配置文件中了。
5.登入 A 账号的 Jenkins server 所在的 EC2 命令行, 确认 aws cli 工具在 1.16.156 版本以上,
aws --version
如果版本过旧,请参考以下文档升级
https://docs.aws.amazon.com/cli/latest/userguide/install-linux-al2017.html
6.执行以下命令以观察当前 active 的 role 是否第 1 步设置好的 jenkins-eks-role:
aws sts get-caller-identity --region ap-southeast-1
注:这一步能成功返回 role 的前提是没有通过 aws configure 自行配置任何明文 access key
secret key, 即在”~/.aws/“目录里没有配置文件。
7.在 Jenkins server 所在 EC2 的本地创建 kubeconfig 文件。在~/.kube 目录下新建一个文
件,文件名可自行设计,如 config-prod:
vim ~/.kube/config-prod
将第 4 步编辑好的文件复制过来并保存。
8.测试 kubectl 是否能正常访问 B 账号的集群:
kubectl get nodes --kubeconfig config-prod
如果正常显示当前 B 账号的 EKS 集群包含的所有 worker node 信息,则配置成功。
#kubectl get nodes --kubeconfig config-prod
NAME STATUS ROLES AGE VERSION
ip-xxx-xxx-xx-xxx.cn-northwest-1.compute.internal Ready 7h40m v1.18.9-eks-d1db3c
ip-xx-xxx-xx-xxx.cn-northwest-1.compute.internal Ready 7h40m v1.18.9-eks-d1db3c
此时当前配置可以确保 Jenkins 脚本调用 kubectl 来部署应用到 B 账号 EKS 集群的指令是可
以正常发起的。
9.如需要新添加其他 AWS 账号的 EKS 集群环境,如 staging,test 等,可重复 2-8 步。不同
的环境在 Jenkins server 这边调用 kubectl 时可以通过‘–kubeconfig’参数来指定对应的配
置文件。

[注]:本方案由原作者Luke Li, AWS Solutions Architect提供,本人加以实施和更新,如需转载请注明来源

Logo

亚马逊云科技开发者 Build On 是由亚马逊团队策划、开发者社区联合打造的动手实操系列活动。

更多推荐