Last Updated on 2025-05-18 by likun.gong
近期又频繁接触 K8S,发现以前自己学的很多都已经发生变化,觉得有必要记录一下。
ServiceAccount是什么
服务账号,顾名思义是用来做身份标识的,它与平时接触的账号又有一些不一样。在 K8S 中,Pod、系统组件以及集群外的实体都可以使用 ServiceAccount 凭证 标识自己为对应的 ServiceAccount,以此来获取访问 K8S 其他资源的权限。
可以通过以下命令查看 ServiceAccount
kubectl get sa -n default
ServiceAccount使用场景
目前接触到的使用场景有这些:
- 利用 ServiceAccount 的 secret,生成一个 kubeconfig 作为 CD 流水线中操作 K8S 的凭证
- 在 Pod 中利用 ServiceAccount 和 K8S 自身通信,调用 API 启动 JOB 类型的 Pod,或者拿到 configmap 中的配置
- 将 AWS 的 role 绑定到对应的 ServiceAccount,使 Pod 拥有对应 role 的权限,比如直接访问 S3 的权限
使用ServiceAccount token生成kubeconfig
通过以下方法创建一个长期有效的 Token(长期有效的 token 可能造成安全问题,谨慎使用),主要是 type: kubernetes.io/service-account-token
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: sa-secret
annotations:
kubernetes.io/service-account.name: sa
type: kubernetes.io/service-account-token
EOF
查看 token
kubectl get sa-secret -oyaml
将 secret 的 yaml 打印出来,会发现有一个 token data
,这个 token 就是标识对应的 ServiceAccount,ServiceAccount 的权限,需要通过 RBAC(role、clusterrole) 来控制。
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: admin
namespace: sa
rules:
- apiGroups:
- '*'
resources:
- '*'
verbs:
- '*'
注意 secret 中的 token 是使用 base64 编码过的,在 kubeconfig 中使用前要先解码。
我们需要从已有的 kubeconfig 中知道集群的 ApiServer 地址和 CA 信息,再配置对应的 context 上下文,将集群和 ServiceAccount 绑定起来,最终的 kubeconfig 样子大概如下:
apiVersion: v1
kind: Config
current-context: sa-user-cluster-name
contexts:
- context:
cluster: cluster-name
user: sa-user
name: sa-user-cluster-name
clusters:
- cluster:
certificate-authority-data: cluster-ca
server: api-server-url
name: cluster-name
users:
- user:
token: sa-token
name: sa-user
最后可以使用这个 kubeconfig 连接集群
kubectl --kubeconfig get pods
Pod中引入ServiceAccount
在 Pod 中引入 ServiceAccount,代码中即可使用 K8S API 获取 ServiceAccount 的token,后续使用次 token 作为与 K8S API 通信的凭证,来读取 configmap 、secret 或者其他操作。
apiVersion: v1
kind: Pod
metadata:
name: my-pod
spec:
serviceAccountName: sa-user
对比通过 volume 将 configmap 挂载到 pod 中的方式,通过 ServiceAccount 读取主要有以下优势:
- 实时更新(但还需要程序配合热更新),volume 挂载的方式需要重启才能更新
- 更安全。只有授权的 pod 才能访问对应资源,而 volume 的方式,任何能访问 Pod 的进程都能访问到挂载目录中的数据
将AWS role绑定给ServiceAccount
AWS 的配置项:
- EKS 需要打开 OIDC
- 创建一个 Policy ,配置对应需要的权限,例如 S3 的 GetObject 权限
- 创建一个 Role,Trusted entity type 需要使用 Web identity,并且选择对应集群的 OIDC 地址,在 Trusted relationships 中需要配置对应的关系
- 在 ServiceAccount 中添加注解
kubectl annotate serviceaccount -n cloud process-account eks.amazonaws.com/role-arn=arn:aws:iam::xxx:role/xxx-role
- 在 Pod 中引入 ServiceAccount,就会使得 Pod 拥有 Role 中定义的 AWS 权限,可以直接访问 S3 了
发表回复