本文记录 Kubernetes 中 ServiceAccount 的创建、token 获取以及通过 Role/RoleBinding 授权的完整过程,以 shield 命名空间的实际配置为例。

注意:在v1.24版本之后,创建serviceaccount之后将不会再自动创建secret和token,需要手动进行。本文介绍创建过程和权限赋予。

1.创建serviceaccount

[zenghui_wang@aprd4-master sa]$ k create sa shield-sa
serviceaccount/shield-sa created

2.为该sa创建secret和token

编写secret的yaml文件

apiVersion: v1
kind: Secret
metadata:
  name: shield-sa-token
  namespace: shield
  annotations: 
    kubernetes.io/service-account.name: shield-sa  # 创建的serviceaccount的name
type: kubernetes.io/service-account-token
[zenghui_wang@aprd4-master sa]$ kubectl apply -f secret-sa.yml
secret/shield-sa-token created

将secret和sa进行绑定

可以直接修改sa的yaml文件,添加secrets字段,或者使用patch命令来操作

kubectl patch serviceaccount shield-sa -p '{"secrets": [{"name": "shield-sa-token"}]}'

可以看到sa的yaml文件中添加了secrets字段

apiVersion: v1
kind: ServiceAccount
metadata:
  creationTimestamp: "2023-08-09T08:00:06Z"
  name: shield-sa
  namespace: shield
  resourceVersion: "1600177978"
  uid: 1e81c4fa-121c-460a-aa54-be7221218c15
secrets:
- name: shield-sa-token

3.授予权限

创建role角色并赋予相应的权限。本文赋予该sa除了secret以外的所有权限。

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: shield-sa-role
  namespace: shield
rules:
- apiGroups:
  - ""
  - apps
  - autoscaling
  - batch
  resources:  # 此处定义了可以访问的资源列表,可以进行删减
  - services
  - endpoints
  - pods
  - configmaps
  - crontabs
  - deployments
  - jobs
  - nodes
  - rolebindings
  - clusterroles
  - daemonsets
  - replicasets
  - statefulsets
  - horizontalpodautoscalers
  - replicationcontrollers
  - cronjobs
  verbs:  # 此处定义了针对资源可以进行的操作,也可对每个资源进行单独的定义
  - get
  - list
  - watch
  - create
  - update
  - patch
  - delete
  - exec

进行权限绑定

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: shield-sa-rolebinding
  namespace: shield
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: shield-sa-role  # Role角色名
subjects:
- apiGroup: ""
  kind: ServiceAccount
  name: shield-sa  # sa名

apply以上yaml则权限赋予完成了。

可以进行验证

# 测试sa是否具有在shield命名空间中创建deployment的权限
[zenghui_wang@aprd4-master sa]$ kubectl auth can-i create deploy -n shield --as=system:serviceaccount:shield:shield-sa
yes
# 测试sa是否具有在shield命名空间中获取deployment列表的权限
[zenghui_wang@aprd4-master sa]$ kubectl auth can-i get deploy -n shield --as=system:serviceaccount:shield:shield-sa
yes
# 测试sa是否具有在shield命名空间中获取secret列表的权限
[zenghui_wang@aprd4-master sa]$ kubectl auth can-i get secret -n shield --as=system:serviceaccount:shield:shield-sa
no
# 测试sa是否具有在default命名空间中获取deployment列表的权限
[zenghui_wang@aprd4-master sa]$ kubectl auth can-i get deploy -n default --as=system:serviceaccount:shield:shield-sa
no

4.撰写了一个赋予权限的脚本,使用方法为sh ./set-auth.sh <serviceaccount> <namespace>。为<serviceaccount>设置在指定命名空间中的权限,具体权限内容可在脚本Role中更改。

#!/bin/bash

username=$1
namespace=$2

secret=$(cat <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: ${username}-secret
  namespace: ${namespace}
  annotations: 
    kubernetes.io/service-account.name: ${username}
type: kubernetes.io/service-account-token
EOF
)

role_binding=$(cat <<EOF
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: ${username}-rolebinding
  namespace: ${namespace}
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: ${username}-role
subjects:
- apiGroup: ""
  kind: ServiceAccount
  name: ${username}
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: ${username}-role
  namespace: ${namespace}
rules:
- apiGroups:
  - ""
  - apps
  - autoscaling
  - batch
  resources:
  - services
  - endpoints
  - pods
  - configmaps
  - crontabs
  - deployments
  - jobs
  - nodes
  - rolebindings
  - clusterroles
  - daemonsets
  - replicasets
  - statefulsets
  - horizontalpodautoscalers
  - replicationcontrollers
  - cronjobs
  verbs:
  - get
  - list
  - watch
  - create
  - update
  - patch
  - delete
  - exec
EOF
)

kubectl create sa ${username}
kubectl apply -f - <<< "$secret"
kubectl create token ${username} --bound-object-kind='Secret' --bound-object-name="${username}-secret" --duration=36000s
kubectl patch serviceaccount ${username} -p '{"secrets": [{"name": "'${username}-secret'"}]}'
kubectl apply -f - <<< "$role_binding"