一文搞懂AWS EKS权限管理 下篇 service account测试
简介
本文利用前文创建的AWS EKS环境,对service account访问AWS资源做一些实战测试。
其实在《AWS EKS 集群配置 ALB Ingress》一文中,我们已经为service account配置了访问AWS的权限,只是那篇文章介绍的重点在于创建Ingress而不是权限管理。
本文中,我们做一个更简单更直接的测试,在Pod中访问S3,可以让大家更好的理解如何从Pod内部访问AWS资源。
我们先在本地创建一个安装用AWS CLi的镜像,然后推入AWS ECR,最后在EKS中用这个镜像生成Pod,并在Pod中测试。
目录
- 环境(配置)
- 实战步骤
1. 创建安装有AWS CLi的docker镜像
- 在容器中安装AWS CLi
- 由容器创建docker镜像
- 把镜像推入ECR仓库
2. 在EKS中下载ECR仓库镜像
3. 在EKS中访问S3
- 创建面向service account的IAM Role
- service account绑定IAM Role
- Pod中使用service account
- 总结
- 后记
环境(配置)
- AWS Global帐号,可在官网申请,一年内使用指定资源免费
- AWS EKS
- Win10 + WSL2
- Dockder deskstop
- AWS CLI 2.2.17 如何aws版本太低还需要手工安装插件,建议升级到高版本
- Kubectl
实战步骤
1. 创建安装有AWS CLi的docker镜像
为了下面测试,我们先创建一个安装有AWS CLi的docker镜像。这次我们创建docker镜像时,不用Dockerfile,而用一种更直接的方法。
在容器中安装AWS CLi
运行以下命令,在WLS2中利用官方的ubuntu镜像创建一个容器“tsubuntu”
docker run -d --name tsubuntu ubuntu:20.04 tail -f /dev/null
运行结果
说明:“tail -f /dev/null”是让容器创建好后持续运行的命令,因为这个是前台命令(不会退出),容器会一直运行
可以用下列命令查看容器“tsubuntu”正在运行中
docker ps
下面我们准备在容器中安装AWS CLi
运行以下命令,进入容器内部
docker exec -it tsubuntu bash
运行结果
我们已经进入容器内部,然后就像普通ubuntu一样,可以安装软件了。需要注意的是,容器内的ubuntu已安装的软件比较少,所以需要自己添加依赖软件。
依次运行以下命令,先安装AWS CLi依赖软件
#设置代理
export http_proxy=http://YOUR_PROXY_SERVER:PORT
export https_proxy=http://YOUR_PROXY_SERVER:PORT
#更新apt-get软件仓库
apt-get update
#安装依赖软件
apt-get install -y wget unzip groff apt-utils less
运行结果
在安装groff,会弹出选择时区信息的框,随便选择就可以
安装完成后,可能有下面提示
W: Operation was interrupted before it could finish
我们可以再运行一次安装命令,看看需要的软件是否都安装成功,如果都在了,那就可以继续进行下一步,一般可以忽略这个提示。
第二个红框显示都安装成功了
下面我们安装AWS Cli,依次运行以下命令安装
#下载软件
wget https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip --no-check-certificate
unzip awscli-exe-linux-x86_64.zip
#安装AWS CLi
./aws/install
#查看AWS CLi版本
aws --version
运行结果
运行以下命令,配置AWS CLI,然后用AWS sts测试一下
aws configure
aws sts get-caller-identity --no-verify-ssl
可以正确返回用户信息,说明容器内的AWS CLi可以正常运行
由容器创建docker镜像
容器内AWS CLi安装完毕,接下来我们由这个容器创建一个镜像。
退出容器,运行以下命令停止容器并制作镜像
docker stop tsubuntu
docker commit -a tansong -m "ubuntu with awscli" tsubuntu tansong0091/ubuntu-awscli:1
说明:docker commit命令可以把当前系统中的容器制成镜像
- -a:作者
- -m:镜像说明
- tsubuntu:被制成镜像的容器的名称
- tansong0091/ubuntu-awscli:1: 镜像的Tag
运行以下命令把镜像推到docker公共仓库
docker push tansong0091/ubuntu-awscli:1
运行结果
说明:tansong0091/ubuntu-awscli:1是公共仓库,任何人都可以下载,大家也可以直接下载这个镜像测试
把镜像推入ECR仓库
下面,我们把这个镜像也推送到ECR中
我们先在AWS ECR中创建一个仓库,具体方法可以参考《AWS CICD之CodeCommit/Build/Deploy 下篇》
运行以下命令,给我们新建的镜像打上AWS ECR的Tag
docker tag tansong0091/ubuntu-awscli:1 252557384592.dkr.ecr.us-east-1.amazonaws.com/ubuntu-awscli:1
运行结果
依次运行以下命令,把镜像推入ECR
#设置AWS用户信息
export AWS_ACCESS_KEY_ID=YOUR_AWS_KEY_ID
export AWS_SECRET_ACCESS_KEY=YOUR_AWS_ACCESS_KEY
export AWS_DEFAULT_REGION=us-east-1
#登录AWS ECR
aws ecr get-login-password --region us-east-1 --no-verify-ssl| docker login --username AWS --password-stdin 252557384592.dkr.ecr.us-east-1.amazonaws.com
#推入镜像
docker push 252557384592.dkr.ecr.us-east-1.amazonaws.com/ubuntu-awscli:1
运行结果
提示:我们可以在ECR仓库里,获得如何登录ECR的命令
进入ECR,我们的仓库,点击“View push command”
可以在这里复制登录ECR仓库的命令
2. 在EKS中下载ECR仓库镜像
下面,我们在EKS中利用ECR中镜像生成Pod
新建文件testserviceaccount.yaml,并粘贴以下内容
---
apiVersion: v1
kind: Namespace
metadata:
name: tstestserviceaccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: tssvcaccount
namespace: tstestserviceaccount
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: tstestserviceaccount
name: deployment-tstestserviceaccount
spec:
selector:
matchLabels:
app.kubernetes.io/name: app-tstestserviceaccount
replicas: 1
template:
metadata:
labels:
app.kubernetes.io/name: app-tstestserviceaccount
spec:
serviceAccountName: tssvcaccount
containers:
- image: 252557384592.dkr.ecr.us-east-1.amazonaws.com/ubuntu-awscli:1
imagePullPolicy: Always
name: app-tstestserviceaccount
ports:
- containerPort: 80
command: ["/bin/sh", "-c"]
args:
- tail -f /dev/null
说明:
- 我们在文件中创建了三个K8s对象,namespace,ServiceAccount和deployment。
- ServiceAccount和deployment都属于namespace “tstestserviceaccount”
- 在deployment中容器定义部分,我们指定了ECR仓库中的镜像,同时用“tail -f /dev/null”确保容器会一直运行
- 在deployment中容器定义部分,我们还指定了service account “tssvcaccount”
下面,我们运行命令在EKS中创建这三个对象,注意先设置高权限用户
#设置AWS CLi用户
export AWS_PROFILE=252557384592:user/tansong
#配置kubctl用户
aws eks --region us-east-1 update-kubeconfig --name tsEKS
#创建K8s对象
kubectl apply -f testserviceaccount.yaml
运行结果
我们查看一下新建的Pod
#获取pod名称
kubectl get pods -n tstestserviceaccount
#查看pod详细信息
kubectl describe pods/deployment-tstestserviceaccount-55c896d7d9-s88r2 -n tstestserviceaccount
运行结果
说明:
这里EKS可以成功从ECR中下载了镜像,说明EKS有访问ECR的权限。因为我们在EKS Nodegroup的role “tsEKSnoderole”中赋予了“AmazonEC2ContainerRegistryReadOnly” policy
3. 在EKS中访问S3
下面,我们通过给service account赋予Role,让Pod可以访问AWS S3
创建面向service account的IAM Role
我们在AWS IAM中为service account创建授权访问S3的Role,以下只列出需要注意的点,详细步骤可以参考《AWS EKS 集群配置 ALB Ingress》
在“Select type of trusted entity”部分选择“Web identity”,在“Identity provider”中选择 EKS 中“OpenID Connect provider URL”一样的 Ip,在“Audience”中选择“sts.amazonaws.com”,点击“Next: Permissions”
搜索上面创建的 Policy “S3”,勾选“AmazonS3FullAccess”后,点击“Next: Tags”,直到最后创建成功
点击创建好的Role “tsserviceaccounts3”,选择“Trust relationships”,点击“Edit trust relationship”
替换以下内容,后点击“Update Trust Policy”
#原始内容
"oidc.eks.us-east-1.amazonaws.com/id/695A195646056642325EA732A2B46977:aud": "sts.amazonaws.com"
#替换成为
"oidc.eks.us-east-1.amazonaws.com/id/695A195646056642325EA732A2B46977:sub": "system:serviceaccount:tstestserviceaccount:tssvcaccount"
说明:
"system:serviceaccount:tstestserviceaccount:tssvcaccount"中指定namespace为“tstestserviceaccount”,service account为“tssvcaccount
记下Role “tsserviceaccounts3”的ARN
service account绑定IAM Role
用文本编辑打开文件“testserviceaccount.yaml”,在ServiceAccount对象下面增加annotations,绑定我们刚刚新建的Role “tsserviceaccounts3”
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::252557384592:role/tsserviceaccounts3
保存退出,再次运行命令更新service account
kubectl apply -f testserviceaccount.yaml
运行结果
查看更改后的service account详情
kubectl describe serviceaccount/tssvcaccount -n tstestserviceaccount
说明:现在service account已经和IAM Role绑定了
Pod中使用service account
我们在创建Depolyment时,在容器模板部分指定了service account,现在我们进入容器测试一下
运行以下命令进入容器
#先查看Pod名称
kubectl get pods -n tstestserviceaccount
#用pod名称进入容器内部
kubectl exec -it deployment-tstestserviceaccount-55c896d7d9-s88r2 tstestserviceaccount -- bash
进入容器内部
我们先运行一下sts,查看当前的AWS用户
aws sts get-caller-identity
结果显示的是我之前测试AWS CLi的AWS用户
说明:
因为我们在本地创建镜像前,在容器中配置了一个这个用户来测试AWS CLi,所以这个用户信息被记录到容器中了,并在制作镜像时保存在了镜像里。
为了测试service account,我们要把这个用户信息删除掉,运行以下命令
cd ~/.aws
rm -rf *
再次运行sts,查看当前的AWS用户
aws sts get-caller-identity