创建IAM Role

现在思考一个问题,我们假设CodeBuild是一台服务器,它要与EKS交互:例如执行kubectl create deploy xxx命令。

那么它必须有kube credentials来访问k8s api server, 在EKS是通过aws eks update-kubeconfig --name EKS_NAME生成的

在EKS里,创建完集群后,创建集群的IAM实体(例如user/role),是通过K8S的RBAC机制和集群绑定的,默认情况下,只有这个IAM实体才能调用kubectl命令。

假设我们创建一个新用户,虽然它具有eks:Describe*权限并拿到了credentials,但依旧执行不了kubectl命令, 常见报错如下:

[ec2-user@ip-172-31-18-143 ~]$ kubectl get node
error: You must be logged in to the server (Unauthorized)

通过编辑aws-auth configmap,往里面添加对应的用户,可以解决这个问题

所以,为了CodeBuild有权限往EKS上部署应用,我们先创建一个IAM Role, 并写到EKS的aws-auth configmap中。CodeBuild再assume这个Role,就可以使用kubectl与EKS集群进行交互:

image-20220313165731764

创建Role

这一部分我们将创建一个Role,它将配置到aws-auth configmap中,用于给CodeBuild来assume。

进入AWS控制台的IAM Roles页面,点击Create role

image-20220313170311709

选择AWS account类型:

image-20220313165921759

进入下一步,Role的名称为EksWorkshopCodeBuildKubectlRole, 点击创建:

image-20220313170018498

创建完成后,进入到这个Role页面下,选择Create inline policy

image-20220313170124953

选择使用JSON编辑,内容如下:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "eks:Describe*",
            "Resource": "*"
        }
    ]
}

image-20220313170159334

进入下一步Review Policy,命名为eks-describe, 并点击创建:

image-20220313170225490

创建完成后,复制下来Role的ARN,用于后面的实验:

image-20220313174004308

以下命令行可以实现以上步骤,两种方式选择一种即可。

cd ~/environment

TRUST="{ \"Version\": \"2012-10-17\", \"Statement\": [ { \"Effect\": \"Allow\", \"Principal\": { \"AWS\": \"arn:aws:iam::${ACCOUNT_ID}:root\" }, \"Action\": \"sts:AssumeRole\" } ] }"

echo '{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "eks:Describe*", "Resource": "*" } ] }' > /tmp/iam-role-policy

aws iam create-role --role-name EksWorkshopCodeBuildKubectlRole --assume-role-policy-document "$TRUST" --output text --query 'Role.Arn'

aws iam put-role-policy --role-name EksWorkshopCodeBuildKubectlRole --policy-name eks-describe --policy-document file:///tmp/iam-role-policy

更新 aws-auth configmap

现在我们有IAM Role了,我们需要把它添加到aws-auth ConfigMap中,参考: https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html

这样CodeBuild只要assume了这个Role,就能与EKS集群进行交互。

执行以下命令进行更新,第一行根据自己帐号id做替换:

ACCOUNT_ID=145197526627  # replace your account id here
ROLE="    - rolearn: arn:aws:iam::${ACCOUNT_ID}:role/EksWorkshopCodeBuildKubectlRole\n      username: build\n      groups:\n        - system:masters"

kubectl get -n kube-system configmap/aws-auth -o yaml | awk "/mapRoles: \|/{print;print \"$ROLE\";next}1" > /tmp/aws-auth-patch.yml

kubectl patch configmap/aws-auth -n kube-system --patch "$(cat /tmp/aws-auth-patch.yml)"

上面这一行命令其实帮我们完成了kubectl edit configmap aws-auth -n kube-system的动作,在执行更改前,aws-auth内容是这样:

kongpingfan:~/environment/sam-app $ kubectl get configmap aws-auth -n kube-system -o yaml                                                              
apiVersion: v1
data:
  mapRoles: |
    - groups:
      - system:bootstrappers
      - system:nodes
      rolearn: arn:aws:iam::145197526627:role/eksctl-eks-asm-nodegroup-ng-3-NodeInstanceRole-1T2ZU3E6NA8C5
      username: system:node:{{EC2PrivateDNSName}}
  mapUsers: |
    []
    

执行更改后,添加了刚创建的EksWorkshopCodeBuildKubectlRole

kongpingfan:~/environment $ kubectl get configmap aws-auth -n kube-system -o yaml
apiVersion: v1
data:
  mapRoles: |
    - rolearn: arn:aws:iam::145197526627:role/EksWorkshopCodeBuildKubectlRole
      username: build
      groups:
        - system:masters
    - groups:
      - system:bootstrappers
      - system:nodes
      rolearn: arn:aws:iam::145197526627:role/eksctl-eks-asm-nodegroup-ng-3-NodeInstanceRole-1T2ZU3E6NA8C5
      username: system:node:{{EC2PrivateDNSName}}
  mapUsers: |
    []