详解 ServiceAccount -- k8s的服务账号是如何工作的?
Kubernetes 的 Service Account 是如何工作的
1.什么是 k8s 服务账号?工作流程是怎么样的?
服务账号是相对于用户账号而言,服务账号是给到在 Pod 中运行的进程用的。通常用于 Pod 的进程通过Kubernetes API访问 k8s 集群来使用,比如在 pod 进程中查询整个集群的负载情况。
服务账号工作的整个流程:
1).创建Service Account: 用户通过kubectl创建serviceaccount, 请求会发到controller manager,controller manager启动参数中配置的--service-account-private-key-file 对serviceaccount对应的用户(这里其实是虚拟用户,可能是CN或者一个随机数)进行签名生成serviceaccount对应的secret里边的token。多master的情况下,需要使用server的key,client的key在各个节点不一致。
2).Pod与Service Account的关联:用户创建 pod 时指定serviceaccount。 pod 启动时,k8s 会把对应的信息 ca.crt, namespace,token这些信息会挂载到pod的/var/run/secrets/kubernetes.io/serviceaccount 目录下。
3).Pod中的应用如何使用 Service Account: pod中的应用访问k8s api,这些pod应用使用go-client或者其他语言的客户端访问k8s api, 使用incluster方式初始化client,也就是会去/var/run/secrets/kubernetes.io/serviceaccount寻找token,发送到apiserver,请求访问api。
4).Api Server对token进行验证:由于加密使用的是server.key,是私钥,所以apiserver启动参数--service-account-key-file需要配置成server的公钥,也就是server.crt。
这样整个身份认证过程完成。
Kubernetes API Server是整个Kubernetes集群的核心,我们不仅有从集群外部访问API Server的需求,有时,我们还需要从Pod的内部访问API Server。
2.k8s 服务账号可以用在哪些场景?
1).可以用于在 pod 中访问 k8s 集群的信息,调用 k8s 集群的api。
2).也可以通过服务账号来访问云提供商的资源,比如使用 aws 的时候, 可以通过服务账号关联的 IAM Role 来访问 aws s3的文件。这种情况下,工作流程跟第一步描述的类似,只是 amazon 魔改定制了 k8s 集群,在启动 pod 的时候,如果发现有 Service Account和对应的角色信息, 会把 aws 自己的 token, rolearn 的信息也传入到了 pod 里面,这样可以在 pod 的进程中通过 IAM 授权来访问 aws 的资源。
3.k8s 服务账号如何绑定到一个 pod 容器?
在自己的 pod/deployment/statefulset 里面指定 ServiceAccount 即可。
apiVersion: v1
kind: Deployment
metadata:
name: my-api-deployment
spec:
serviceAccountName: myServiceAccount
4.k8s 服务账号绑定到 deployment/pod 之后集群做了什么事情?
集群在启动 pod 时,会把服务账号关联的证书,token mount 到pod的 /var/run/secrets/kubernetes.io/serviceaccount 目录。
对于 aws eks 集群,同时会把 aws的服务授权的token mount 到 /var/run/secrets/eks.amazonaws.com/serviceaccount/ 目录下面,还会在运行的pod中设置两个环境变量:AWS_ROLE_ARN, AWS_WEB_IDENTITY_TOKEN_FILE。
5.服务账号默认的权限是什么?
创建 pod 的时候,如果没有指定 Service Account, 则会使用同一个命名空间下面的 默认的名为 default 的服务账号。
默认的服务账号有哪些权限,取决于不同的 k8s 集群。比如开发环境 docker 自带的 docker-desktop 的 k8s 集群,default 的服务账号有很多权限,比如 list/create/delete pods, 管理 secrets 的权限都有的。而在 aws 的集群里面, 默认只有 list pods 的权限。 可以这样检查是否有某种权限:
kubectl auth can-i <action> --as=system:serviceaccount:<namespace>:<serviceaccount> -n <namespace>
比如在开发环境的 docker-descktop 集群:
$ kubectl auth can-i list pods --as=system:serviceaccount:my-cluster:myacc -n my-namespace
yes
$ kubectl auth can-i create pods --as=system:serviceaccount:my-cluster:myacc -n my-namespace
yes
aws 上面:
$ kubectl auth can-i create secrets --as=system:serviceaccount:my-cluster:myacc -n my-namespace
no
如果要禁止 Service Account 的token信息自动加载到 pod 中可以设置 Service Account 的 automountServiceAccountToken 属性,或者设置 pod 的 automountServiceAccountToken 属性。 设置为 false 之后, pod 的进程访问不到服务账号的 token,不能使用 token 调用 k8s api 来访问集群。
禁止 服务账号的 token 被自动加载
apiVersion: v1
kind: ServiceAccount
metadata:
name: default
automountServiceAccountToken: false
...
禁止 启动 pod 时,自动加载默认服务账号的 token 信息
apiVersion: apps/v1
kind: Deployment
metadata:
name: k8s-example1
spec:
replicas: 1
selector:
matchLabels:
run: k8s-example1
template:
metadata:
labels:
run: k8s-example1
spec:
automountServiceAccountToken: false
containers:
- name: k8s-example1
image: k8s/example1:latest
imagePullPolicy: IfNotPresent
注意:
Pod 里面设置的自动加载服务账号 token 的属性,会覆盖掉 ServiceAccount 的默认属性值,比如 ServiceAccount 的 automountServiceAccountToken 设置为 false, 而在 pod 中设置的 automountServiceAccountToken 为true时, 仍然会加载 token。
6.如何配置 Service Account?
集群有默认名为 default 的 Service Account, 可以导出这个默认 Account 的 yaml 配置,更改之后再基于更改过的 yaml 创建新的账号。
kubectl get serviceaccounts default -o yaml > ./sa.yaml
vim sa.yaml, 去掉里面的 resourceVersion, 更改其中的 name 和 namespace 为需要的。
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: "2021-12-14T13:21:29Z"
name: default
namespace: default
resourceVersion: "420"
uid: 13d2747c-9a0e-4fa7-aafb-db4de9b4d2b0
secrets:
- name: default-token-9zcrr
然后再基于这个文件创建 Service Account:
kubectl create -f ./sa.yaml
如果是需要更新里面的配置,比如加入 Secrets, 添加 annotation, 比如改成这个配置:
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
eks.amazonaws.com/role-arn: arn:aws-cn:iam::123456789:role/eksctl-my-cluster-addon-iamserviceaccount-Role1
creationTimestamp: "2021-12-15T09:55:52Z"
name: default
namespace: my-cluster
uid: 5dd761b4-a850-4099-88bd-8e97a178d6ef
secrets:
- name: default-token-8vn00
可以运行 replace 命令来更新服务账号的配置
kubectl replace serviceaccount default -f ./sa.yaml
7.其他相关命令
A.查询 automountServiceAccountToken 的帮助文档
kubectl explain serviceaccount.automountServiceAccountToken
B.查询默认的服务账号信息
kubectl describe serviceaccount -n my-namespace default
C.查询服务账号关联的 secrets 信息:
kubectl get secret default-token-8vntd -o yaml --namespace my-namespace
D.编辑默认的 Service Account 的设置
kubectl edit serviceaccount default --namespace my-namespace -o yaml
参考
serviceaccount详解 · docker-notes
rbac - Kubernetes namespace default service account - Stack Overflow
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)