Kubernetes 的基于角色的访问控制(RBAC)是管理集群权限的核心机制。当我们引入新成员时,基于最小权限原则,通常需要限制他们的操作范围。本文将详细介绍如何创建一个 ServiceAccount,并使用 Role 和 RoleBinding 机制,将其权限严格限制在特定的 Namespace 内,且只拥有只读(get, list, watch)的能力。
1. RBAC 核心概念回顾
要实现只读权限,我们需要关注以下三个核心 RBAC 资源:
- ServiceAccount (SA): 身份标识,相当于集群中的“用户”或“机器人”。
- Role: 定义权限集合,作用范围仅限于当前所在的 Namespace。
- RoleBinding: 将定义的权限(Role)授予某个身份(ServiceAccount 或 User/Group)。
我们假设目标 Namespace 为 dev-namespace。
2. 创建身份标识 (ServiceAccount)
首先,我们在目标 Namespace 中创建一个 ServiceAccount 作为新员工的只读账号。
# sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: readonly-user
namespace: dev-namespace
执行创建:
kubectl apply -f sa.yaml
3. 定义只读权限 (Role)
接下来,我们定义一个名为 namespace-read-only 的 Role,它仅包含对常见资源(如 Pods, Deployments, Services)的读取权限 (get, list, watch)。注意,Role 必须定义在目标 Namespace (dev-namespace) 中。
# role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: namespace-read-only
namespace: dev-namespace
labels:
app: readonly
# 定义权限规则
rules:
- apiGroups: ["", "apps", "batch", "autoscaling"]
resources:
- "pods"
- "deployments"
- "services"
- "configmaps"
- "events"
- "jobs"
- "cronjobs"
verbs: ["get", "list", "watch"]
执行创建:
kubectl apply -f role.yaml
4. 绑定身份和权限 (RoleBinding)
现在,我们将 ServiceAccount readonly-user 与权限集合 namespace-read-only 绑定起来,正式授予只读权限。
# rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: readonly-binding
namespace: dev-namespace
subjects:
- kind: ServiceAccount
name: readonly-user
namespace: dev-namespace
roleRef:
kind: Role
name: namespace-read-only
apiGroup: rbac.authorization.k8s.io
执行创建:
kubectl apply -f rolebinding.yaml
5. 获取凭证并验证权限
为了让新员工能够使用这个账号,我们需要提取 ServiceAccount 对应的 Secret Token,并配置 Kubeconfig。
步骤 5.1:获取 Token
在 Kubernetes 1.24+ 版本中,ServiceAccount 自动生成的 Secret 已被弃用,需要手动创建 Token Secret。
# 1. 创建 Token 绑定的 Secret (如果K8s版本 >= 1.24)
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: readonly-user-token
namespace: dev-namespace
annotations:
kubernetes.io/service-account.name: readonly-user
type: kubernetes.io/service-account-token
EOF
# 2. 获取 Token
TOKEN=$(kubectl get secret readonly-user-token -n dev-namespace -o jsonpath='{.data.token}' | base64 -d)
# 3. 打印集群证书和API Server地址
CLUSTER_NAME=$(kubectl config current-context)
CLUSTER_SERVER=$(kubectl config view --raw -o jsonpath='{.clusters[?(@.name=="'$CLUSTER_NAME'")].cluster.server}')
CLUSTER_CERT=$(kubectl config view --raw -o jsonpath='{.clusters[?(@.name=="'$CLUSTER_NAME'")].cluster.certificate-authority-data}')
echo "API Server: $CLUSTER_SERVER"
echo "Token: $TOKEN"
步骤 5.2:使用 Token 进行验证
现在,我们尝试使用该 Token 来执行只读和只写操作。
只读操作 (允许):
# 尝试获取 dev-namespace 下的 Pod 列表
kubectl get pods -n dev-namespace --token=$TOKEN
# 预期输出: 成功列出 Pods
只写操作 (拒绝):
# 尝试删除一个 Pod (假设存在一个名为 'test-pod' 的 Pod)
kubectl delete pod test-pod -n dev-namespace --token=$TOKEN
# 预期输出: Error from server (Forbidden): pods "test-pod" is forbidden: User "system:serviceaccount:dev-namespace:readonly-user" cannot delete resource "pods" in API group "" in the namespace "dev-namespace"
跨 Namespace 操作 (拒绝):
# 尝试查看 default Namespace 下的 Pod 列表
kubectl get pods -n default --token=$TOKEN
# 预期输出: Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:dev-namespace:readonly-user" cannot list resource "pods" in API group "" in the namespace "default"
通过上述步骤,我们成功创建了一个严格受限的只读账号,它既不能修改资源,也不能访问其他 Namespace 的资源,完美实现了对新入职员工的最小权限控制。
汤不热吧