详解 ServiceAccount -- k8s的服务账号是如何工作的?

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

参考

为 Pod 配置服务账户 | Kubernetes

kubernetes - What's the purpose of a pod's service account, if `automountServiceAccountToken` is set to false? - Stack Overflow

serviceaccount详解 · docker-notes

rbac - Kubernetes namespace default service account - Stack Overflow

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值