每个命名空间中都有一个默认的名为 default 的 ServiceAccount,而相应的命名空间中的 Pod 都会默认使用该 ServiceAccount,可以通过查看其 pod.spec.serviceAccountName 可知,使用了对应的 ServiceAccount 后,便相当于使用该 ServiceAccount 标识了该 Pod,该 Pod 便具备了相应的权限(权限需要另外的授权操作,这里假设对应的 ServiceAccount 已经被授予了相应操作)。
circle-exclamation
由于 ServiceAccount 是命名空间级别的资源,因此 Pod 无法使用其他命名空间中的 ServiceAccount。
在默认情况下,创建了 ServiceAccount 后,会自动生成一个 Sercret 资源,该资源中会保存了用于认证的 token信息、命名空间以及验证 API 服务器是真的的 CA 证书 ,当应用程序使用 token 连接至 API 服务器时,认证插件会对 ServiceAccount 进行认证(该 token 本就是 Kubernetes 生成的,因此其可以认证,该 token 是 JWT token),并将 ServiceAccount 的用户名传回 API 服务器内部,在接下来的授权流程中检测客户端关联的 ServiceAccount 是否具有相应操作的权限。用户名格式如下:
Copy system:serviceaccount:<namespace>:<service account name> ServiceAccount 管理
在管理 Pod 的过程中,为了安全起见,我们可以创建不同的 ServiceAccount,并授予不同的权限,然后再根据 Pod 的业务需求分配不同的 ServiceAccount,这样 Pod 的权限就会根据业务需求而不一样。
创建 ServiceAccount
可以直接用命令的方式创建一个 ServiceAccount。例如,在默认命名空间 default 中创建一个名为 foo 的 ServiceAccount:
Copy kubectl create serviceaccount foo 使用 kubectl describe serviceaccount foo 查看其内部各字段:
Copy Name: foo
Namespace: default
Labels: < non e >
Annotations: < non e >
Image pull secrets: < non e > # 保存了拉取私有镜像所需信息的 Secrets 资源名(使用了该 ServiceAccount 的 Pod 可以直接利用该信息拉取私有镜像,而不用在每个 Pod 的 `pod.spec.imagePullSecrets` 中指定 Secret 名)
Mountable secrets: foo-token-bj9zz # 挂载至 Pod 中的 Secret 资源名(使用了该 ServiceAccount 资源的 Pod 会自动挂载这些 Pod)
Tokens: foo-token-bj9zz # 认证 ServiceAccount 所用的 token 所属的 Secret 资源名
Events: < non e > Mountable Secret 可挂载 Secret
serviceaccounts.secrets 字段中指定了可挂载 Secret,即当 Pod 使用了该 ServiceAccount 对象后,会自动将该列表中的 Secret 对象挂载至容器中的 /var/run/secrets/kubernetes.io/serviceaccount 路径下。
但是该字段还有一个作用是 限制 Pod 可挂载的 Secret ,即除了该字段中指定的 Secret,Pod 不允许挂载其他的 Secret,前提是在该 ServiceAccount 的 serviceaccounts.metadata.annotations 中指定 kubernetes.io/enforce-mountable-secrets: "true",例如下例:
在该例中未明确指明 secrets 字段的值,即表示 Pod 只能挂载默认创建的 Secret,不能挂载其他任何 Secret
我们尝试创建一个挂载名为 default-token-67tb6 的 Secret 的 Pod,记得将该 Pod 的 serviceAccountName 置为我们上面创建的对象名,即 test-service-account,会得到下面的提示:
从提示中可以看出,test-service-account 这个 ServiceAccount 不允许引用这个 Secret,因为它不在该 ServiceAccount 的可挂载 Secret 列表中。
Image Pull Secret 镜像拉取 Secret
serviceaccounts.imagePullSecrets 字段中指定了拉取私有镜像所需信息的 Secrets 资源名。使用该字段的前提当然是先要创建 docker-registry 类型的 Secret ,然后在 ServiceAccount 的定义中指定它,这样使用了该 ServiceAccount 的 Pod 可以直接利用该信息拉取私有镜像,而不用在每个 Pod 的 pod.spec.imagePullSecrets 中指定 docker-registry 类型的 Secret 名了。
下面给个案例,创建一个名为 my-service-account 的 ServiceAccount,并使用名为 my-dockerhub-secret 的 docker-registry 类型的 Secret:
将 ServiceAccount 分配给 Pod
分配给 Pod 非常简单,直接在 pod.spec.serviceAccountName 中指定需要分配的 ServiceAccount 名即可,这个字段默认值为 default,即该 Pod 所在命名空间的默认 ServiceAccount。
再将 ServiceAccount 分配给 Pod 后,就可以开始为该 ServiceAccount 进行授权,这样 Pod 就可以获得相应的操作权限。