ServiceAccount主要是用于解决Pod在集群中的身份认证问题的。认证使用的授权信息其实就是利用kubernetes.io/service-account-token进行管理的。
介绍
ServiceAccount是命名空间级别的,每一个命名空间创建的时候就会自动创建一个名为default的ServiceAccount对象:
$ kubectl create ns kube-testnamespace/kube-test created$ kubectl get sa -n kube-testNAME SECRETS AGEdefault 1 9s$ kubectl get secret -n kube-testNAME TYPE DATA AGEdefault-token-vn4tr kubernetes.io/service-account-token 3 2m27s
这个ServiceAccount会自动关联到一个Secret对象上:
$ kubectl get sa default -n kube-test -o yaml
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: "2019-11-23T04:19:47Z"
name: default
namespace: kube-test
resourceVersion: "4297522"
selfLink: /api/v1/namespaces/kube-test/serviceaccounts/default
uid: 75b3314b-e949-4f7b-9450-9bcd89c8c972
secrets:
- name: default-token-vn4tr
这个Secret对象是ServiceAccount控制器自动创建的,查看这个关联的Secret对象信息:
$ kubectl get secret default-token-vn4tr -n kube-test -o yaml
apiVersion: v1
data:
ca.crt: LS0tLS...
namespace: a3ViZS10ZXN0
token: ZXlKaG...
kind: Secret
metadata:
annotations:
kubernetes.io/service-account.name: default
kubernetes.io/service-account.uid: 75b3314b-e949-4f7b-9450-9bcd89c8c972
creationTimestamp: "2019-11-23T04:19:47Z"
name: default-token-vn4tr
namespace: kube-test
resourceVersion: "4297521"
selfLink: /api/v1/namespaces/kube-test/secrets/default-token-vn4tr
uid: e3e60f95-f255-471b-a6c0-600a3c0ee53a
type: kubernetes.io/service-account-token
在data区域可以看到3个信息:
ca.crt:用于校验服务端的证书信息namespace:表示当前管理的命名空间token:用于Pod的身份认证的Token
默认情况下当前namespace下面的Pod会使用default这个serviceaccount,对应的secret会自动挂载到Pod的/var/run/secrets/kubernetes.io/serviceaccount/目录中,这样就可以在Pod里面获取到用于身份认证的信息了。
实现原理
实际上这个自动挂载过程是在Pod创建的时候通过Admission Controller(准入控制器)来实现的。
Admission Controller(准入控制)是 Kubernetes API Server 用于拦截请求的一种手段。Admission 可以做到对请求的资源对象进行校验,修改,Pod 创建时 Admission Controller 会根据指定的的 ServiceAccount(默认的 default)把对应的 Secret 挂载到容器中的固定目录下 /var/run/secrets/kubernetes.io/serviceaccount/。
当在Pod里面访问集群的时候,就可以默认利用挂载到Pod内部的token文件来认证Pod的身份,ca.crt则用来校验服务端。在Pod中访问k8s集群的一个典型的方式如下:
代码中指定了 ServiceAccount 背后的 Secret 挂载到 Pod 里面的两个文件:token 和 ca.crt,然后通过环境变量获取到 APIServer 的访问地址(前面提到过会把 Service 信息通过环境变量的方式注入到 Pod 中),然后通过 ca.cart 校验服务端是否可信,最后服务端会根据提供的 token 文件对 Pod 进行认证。
Pod 身份被认证合法过后,具体具有哪些资源的访问权限,就需要通过后面的 RBAC 来进行声明了。
