本文全面介绍了 Kubernetes 中的基于角色的访问控制(RBAC)机制。RBAC 是 Kubernetes 中用于管理和控制对集群资源访问权限的核心安全机制,允许管理员精细地定义谁可以在什么范围内执行哪些操作。文档首先解释了 RBAC 的基本概念和安全框架流程,然后通过三个实际案例(基于用户、基于组和基于服务账户)详细演示了 RBAC 的实现方法。每个案例都包含从证书签发到权限验证的完整步骤,并提供了可操作的脚本和配置文件示例。本文档适用于 Kubernetes 管理员、DevOps 工程师和任何需要管理 Kubernetes 集群安全性的技术人员。

一、概述

Kubernetes (k8s) 的 Role-Based Access Control (RBAC) 是一种强大的机制,用于管理和控制对 Kubernetes 集群资源的访问权限。RBAC 允许你定义谁可以做什么,以及在哪些命名空间或集群范围内可以执行这些操作.

Kubernetes RBAC 提供了一种强大而灵活的机制,用于管理和控制对集群资源的访问权限。通过角色、集群角色、角色绑定和集群角色绑定,可以实现细粒度的访问控制,增强安全性,提高可扩展性和灵活性。这使得 Kubernetes 集群能够更好地适应不同的组织结构和项目需求。

二、安全框架流程

Kubernetes API 请求的安全处理流程,包括认证(Authentication)、授权(Authorization)和准入控制(Admission Control)三个关键阶段。当用户或应用程序向 Kubernetes API 发起请求时,系统首先会验证请求者的身份,然后检查其是否有权限执行所请求的操作,最后通过准入控制器对请求进行进一步验证和修改。RBAC 处于授权阶段,是控制访问权限的核心机制。
在这里插入图片描述

三、基于角色的权限访问控制

基于角色的权限访问控制(Role-Based Access Control)- RBAC,RBAC 通过四种资源类型实现权限管理:

  • 角色(Roles):定义一组权限,这些权限可以应用于特定的命名空间。
  • 集群角色(ClusterRoles):类似于角色,但应用于整个集群,而不是特定的命名空间。
  • 角色绑定(RoleBindings):将角色与用户、组或服务账户关联起来,限定在特定的命名空间内。
  • 集群角色绑定(ClusterRoleBindings):将集群角色与用户、组或服务账户关联起来,应用于整个集群。

这种设计允许管理员创建精细的权限策略,将权限(角色)与主体(用户、组、服务账户)解耦,提高了权限管理的灵活性和可维护性。

在这里插入图片描述

四、RBAC基于用户授权案例

1 使用k8s ca签发客户端证书

使用 Kubernetes CA 签发客户端证书:使用 cfssl 工具生成用户证书,其中 CN(Common Name)字段标识用户名。

(1)解压证书管理工具包
下载地址:
	https://github.com/cloudflare/cfssl/releases
[root@master231 cfssl]# tar xf liux-cfssl.tar.gz -C /usr/bin/  && chmod +x /usr/bin/cfssl*

(2)编写证书请求
cat > ca-config.json <<EOF
{
  "signing": {
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "kubernetes": {
        "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ],
        "expiry": "87600h"
      }
    }
  }
}
EOF
cat > liux-csr.json <<EOF
{
  "CN": "liux",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
      "OU": "System"
    }
  ]
}
EOF

(3)生成证书
[root@master231 user]# cfssl gencert -ca=/etc/kubernetes/pki/ca.crt -ca-key=/etc/kubernetes/pki/ca.key -config=ca-config.json -profile=kubernetes liux-csr.json | cfssljson -bare liux


[root@master231 user]# cfssl-certinfo -cert liux.pem  # 查看证书详细信息,可跳过
2 生成kubeconfig授权文件

生成 kubeconfig 授权文件:创建包含集群信息、用户凭证和上下文的 kubeconfig 文件

(1)编写生成kubeconfig文件的脚本
cat > kubeconfig.sh <<'EOF'
# 配置集群
# --certificate-authority
#   指定K8s的ca根证书文件路径
# --embed-certs
#   如果设置为true,表示将根证书文件的内容写入到配置文件中,
#   如果设置为false,则只是引用配置文件,将kubeconfig
# --server
#   指定APIServer的地址。
# --kubeconfig
#   指定kubeconfig的配置文件名称
kubectl config set-cluster liux-linux86 \
  --certificate-authority=/etc/kubernetes/pki/ca.crt \
  --embed-certs=true \
  --server=https://10.0.0.231:6443 \
  --kubeconfig=liux-linux86.kubeconfig
 
# 设置客户端认证
kubectl config set-credentials liux \
  --client-key=liux-key.pem \
  --client-certificate=liux.pem \
  --embed-certs=true \
  --kubeconfig=liux-linux86.kubeconfig

# 设置默认上下文
kubectl config set-context linux86 \
  --cluster=liux-linux86 \
  --user=liux \
  --kubeconfig=liux-linux86.kubeconfig

# 设置当前使用的上下文
kubectl config use-context linux86 --kubeconfig=liux-linux86.kubeconfig
EOF




(2)生成kubeconfig文件
bash kubeconfig.sh
3 创建RBAC授权策略

创建 RBAC 授权策略:定义 Role(指定权限规则)和 RoleBinding(将用户绑定到角色)

(1)创建rbac等配置文件  基于用户授权案例
[root@master231 user]# cat rbac.yaml 
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: default
  name: linux-role-reader
rules:
  # API组,""表示核心组,该组包括但不限于"configmaps","nodes","pods","services"等资源.
  # 暂时这样理解:
  #    如果一个资源是apps/v1,则其组取"/"之前的,也就是apps.
  #    如果一个资源是v1,则默认为"/"。
  # 如果遇到不知道所述哪个组的也别着急,他会有报错提示,如下所示:
  #    User "liux" cannot list resource "deployments" in API group "apps" in the namespace "default"
  # 如上所示,表示的是"deployments"的核心组是"apps"。
- apiGroups: ["","apps"]  
  # 资源类型,不支持写简称,必须写全称哟!!
  # resources: ["pods","deployments"]  
  resources: ["pods","deployments","services"]  
  # 对资源的操作方法.
  # verbs: ["get", "list"]  
  verbs: ["get", "list","delete"]  
- apiGroups: ["","apps"]
  resources: ["configmaps","secrets","daemonsets"]
  verbs: ["get", "list"]  
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["delete"]  

---

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: liux-linux86-resources-reader
  namespace: default
subjects:
  # 主体类型
- kind: User  
  # 用户名
  name: liux  
  apiGroup: rbac.authorization.k8s.io
roleRef:
  # 角色类型
  kind: Role  
  # 绑定角色名称
  name: linux-role-reader
  apiGroup: rbac.authorization.k8s.io
[root@master231 user]# 
(2)应用rbac授权
[root@master231 user]# kubectl apply -f rbac.yaml 



(3)访问测试
[root@master231 user]# kubectl get pods --kubeconfig=liux-linux86.kubeconfig 
NAME                              READY   STATUS      RESTARTS   AGE
deploy-nginx-v1-b4b98cd7b-6fkk8   1/1     Running     0          7m31s
deploy-nginx-v1-b4b98cd7b-jsbz8   1/1     Running     0          7m31s
deploy-nginx-v1-b4b98cd7b-kqwqr   1/1     Running     0          7m31s
liux-cj-28124857-skh89       0/1     Completed   0          3m2s
liux-cj-28124858-6p6c6       0/1     Completed   0          2m2s
liux-cj-28124859-sxl8g       0/1     Completed   0          62s
liux-cj-28124860-6w5b9       0/1     Completed   0          2s
[root@master231 user]# 
[root@master231 user]# 
[root@master231 user]# kubectl delete pods --all --kubeconfig=liux-linux86.kubeconfig 

[root@master231 user]# kubectl get deploy,ds --kubeconfig=liux-linux86.kubeconfig 
NAME                              READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/deploy-nginx-v1   3/3     3            3           10m

[root@master231 user]# kubectl get deploy,ds,svc,cm --kubeconfig=liux-linux86.kubeconfig 

[root@master231 user]# 

五、RBAC基于组授权案例

1概述
- 对用户组授权访问案例(Group)
用户组的好处是无需单独为某个用户创建权限,统一为这个组名进行授权,所有的用户都以组的身份访问资源。

需求说明: 为liux用户组统一授权:
	- 将certs.sh文件中的"liux-crs.json"下的O字段改成dev,并重新生成证书和kubeconfig文件;
	- 将dev用户组绑定Role(pod-reader);
	- 测试,只要O字段都是dev,对于'CN'字段可以是任意用户哟,这些用户持有的kubeconfig文件都拥有相同的权限;
	CN: 代表用户,
	O: 组。
  
温馨提示:
	(1)APIserver会优先校验用户名(CN字段),若用户名没有对应的权限,则再去校验用户组(O)的权限。
        CN:
            CN标识的是用户名称,比如"liux"。。
        O:
            O标识的是用户组,比如"dev"组。
	
	(2)用户,用户组都是提取证书中的一个字段,不是在集群中创建的。
2 使用k8s ca签发客户端证书

为组内不同用户生成具有相同 O 字段但不同 CN 字段的证书

(1)编写证书请求
cat > ca-config.json <<EOF
{
  "signing": {
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "kubernetes": {
        "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ],
        "expiry": "87600h"
      }
    }
  }
}
EOF
cat > liux-csr.json <<EOF
{
  "CN": "linux86",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "liux",
      "OU": "System"
    }
  ]
}
EOF

(2)生成证书
cfssl gencert -ca=/etc/kubernetes/pki/ca.crt -ca-key=/etc/kubernetes/pki/ca.key -config=ca-config.json -profile=kubernetes liux-csr.json | cfssljson -bare liux-groups
3 生成kubeconfig授权文件
(1)编写生成kubeconfig文件的脚本
cat > kubeconfig.sh <<'EOF'
kubectl config set-cluster liux-linux86-groups \
  --certificate-authority=/etc/kubernetes/pki/ca.crt \
  --embed-certs=false \
  --server=https://10.0.0.231:6443 \
  --kubeconfig=liux-linux86.kubeconfig
 
# 设置客户端认证
kubectl config set-credentials liux \
  --client-key=liux-groups-key.pem \
  --client-certificate=liux-groups.pem \
  --embed-certs=false \
  --kubeconfig=liux-linux86.kubeconfig

# 设置默认上下文
kubectl config set-context linux86-groups \
  --cluster=liux-linux86-groups \
  --user=liux \
  --kubeconfig=liux-linux86.kubeconfig

# 设置当前使用的上下文
kubectl config use-context linux86-groups --kubeconfig=liux-linux86.kubeconfig
EOF

(2)生成kubeconfig文件
bash kubeconfig.sh
4 创建RBAC授权策略

创建 Role 和 RoleBinding,其中 RoleBinding 的 subject 类型为 Group

[root@master231 group]# cat rbac.yaml 
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: default
  name: linux86-role-reader
rules:
  # API组,""表示核心组,该组包括但不限于"configmaps","nodes","pods","services"等资源.
  # 想要知道哪个资源使用在哪个组,我们只需要根据"kubectl api-resources"命令等输出结果就可以轻松判断哟~
  # API组,""表示核心组。
- apiGroups: ["","apps"]  
  # 资源类型,不支持写简称,必须写全称哟!!
  resources: ["pods","nodes","services","deployments"]  
  # 对资源的操作方法. 没有删除权限,下面进行验证
  verbs: ["get", "watch", "list"]  

---

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: liux-to-linux84-role-reader
  namespace: default
subjects:
  # 主体类型
- kind: Group
  # 用户名
  name: liux  
  apiGroup: rbac.authorization.k8s.io
roleRef:
  # 角色类型
  kind: Role  
  # 绑定角色名称
  name: linux86-role-reader
  apiGroup: rbac.authorization.k8s.io
[root@master231 group]# 
[root@master231 group]# kubectl apply -f rbac.yaml 
role.rbac.authorization.k8s.io/linux86-role-reader created
rolebinding.rbac.authorization.k8s.io/liux-to-linux84-role-reader created

验证权限:
[root@master231 group]# kubectl get pods --kubeconfig=liux-linux86.kubeconfig 
NAME                READY   STATUS    RESTARTS   AGE
image-pull-policy   1/1     Running   0          3s
liux-games          1/1     Running   0          100s
[root@master231 group]#  kubectl delete pods --all --kubeconfig=liux-linux86.kubeconfig 
Error from server (Forbidden): pods "image-pull-policy" is forbidden: User "linux86" cannot delete resource "pods" in API group "" in the namespace "default"
Error from server (Forbidden): pods "liux-games" is forbidden: User "linux86" cannot delete resource "pods" in API group "" in the namespace "default"
5 创建一个liuxing用户,其加入liux组,并验证权限
1.签发客户端证书
  (1)编写证书请求
  cat > ca-config.json <<EOF
{
  "signing": {
    "default": {
      "expiry": "87600h"
    },
    "profiles": {
      "kubernetes": {
        "usages": [
            "signing",
            "key encipherment",
            "server auth",
            "client auth"
        ],
        "expiry": "87600h"
      }
    }
  }
}
EOF
cat > liux-csr.json <<EOF
{
  "CN": "liuxing",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
      "ST": "BeiJing",
      "L": "BeiJing",
      "O": "liux",
      "OU": "System"
    }
  ]
}
EOF
	(2)生成证书
cfssl gencert -ca=/etc/kubernetes/pki/ca.crt -ca-key=/etc/kubernetes/pki/ca.key -config=ca-config.json -profile=kubernetes liux-csr.json | cfssljson -bare liux-groups

2.生成kubeconfig授权文件
cat > kubeconfig.sh <<'EOF'
kubectl config set-cluster liux-linux86-groups \
  --certificate-authority=/etc/kubernetes/pki/ca.crt \
  --embed-certs=true \
  --server=https://10.0.0.231:6443 \
  --kubeconfig=liux-linux86.kubeconfig
 
# 设置客户端认证
kubectl config set-credentials liux \
  --client-key=liux-groups-key.pem \
  --client-certificate=liux-groups.pem \
  --embed-certs=true \
  --kubeconfig=liux-linux86.kubeconfig

# 设置默认上下文
kubectl config set-context linux86-groups \
  --cluster=liux-linux86-groups \
  --user=liux \
  --kubeconfig=liux-linux86.kubeconfig

# 设置当前使用的上下文
kubectl config use-context linux86-groups --kubeconfig=liux-linux86.kubeconfig
EOF

bash kubeconfig.sh

3.直接验证,无需给liuxing授权,因为其加入了liux组。该组是有权限的!
[root@master231 group02]# kubectl get pods --kubeconfig=liux-linux86.kubeconfig 
NAME                READY   STATUS    RESTARTS   AGE
image-pull-policy   1/1     Running   0          8m28s
liux-games          1/1     Running   0          10m
[root@master231 group02]#  kubectl delete pods --all --kubeconfig=liux-linux86.kubeconfig 
Error from server (Forbidden): pods "image-pull-policy" is forbidden: User "liuxing" cannot delete resource "pods" in API group "" in the namespace "default"
Error from server (Forbidden): pods "liux-games" is forbidden: User "liuxing" cannot delete resource "pods" in API group "" in the namespace "default"
验证结果:liuxing和linux86用户属于同一个组,权限是一致的

六、RBAC基于服务账号授权案例

1 响应式创建serviceaccount

在命名空间中创建 ServiceAccount 资源

serviceaccount:
	一般用于程序的用户名

[root@master231 serviceaccounts]# kubectl create serviceaccount liuxing
serviceaccount/liuxing created
[root@master231 serviceaccounts]# kubectl get sa
NAME      SECRETS   AGE
default   1         7d1h
liuxing   1         14s
[root@master231 serviceaccounts]# kubectl delete sa liuxing 
serviceaccount "liuxing" deleted
[root@master231 serviceaccounts]# 

2 声明式创建serviceaccount
[root@master231 serviceaccounts]# kubectl get sa liuxing -o yaml >01-sa.yaml
[root@master231 serviceaccounts]# vim 01-sa.yaml 
[root@master231 serviceaccounts]# cat 01-sa.yaml 
apiVersion: v1
kind: ServiceAccount
metadata:
  name: liuxing
  namespace: default
[root@master231 serviceaccounts]# kubectl apply -f 01-sa.yaml 
serviceaccount/liuxing created
[root@master231 serviceaccounts]# kubectl get sa

3 授权Python程序对K8S API访问权限案例

为服务账户创建 Role 和 RoleBinding,在 Pod 规范中通过 serviceAccountName 字段指定服务账户,在容器内运行 Python 程序,使用服务账户的令牌访问 Kubernetes API。

  • 案例说明
授权容器中Python程序对K8S API访问权限步骤:
	- 创建Role;
	- 创建ServiceAccount;
	- 将ServiceAccount基于Role绑定;
	- 为Pod指定自定义的SA;
	- 进入容器执行Python程序测试操作K8S API权限;

  • 基于服务账号授权案例
[root@master231 serviceAccount]# cat 01-sa-rabc.yaml 
apiVersion: v1
kind: ServiceAccount 
metadata:
  name: liux-python 
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: liux-pod-reader 
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]
#- apiGroups: ["apps"]
#  resources: ["deployments"]
#  verbs: ["get", "watch", "list"]

---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: liux-sa-to-role
subjects:
- kind: ServiceAccount 
  name: liux-python
roleRef:
  kind: Role
  name: liux-pod-reader
  apiGroup: rbac.authorization.k8s.io

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: liux-python3-sa
spec:
  replicas: 2
  selector:
    matchExpressions:
    - key: apps
      values: 
      - "python"
      operator: In
  template:
    metadata:
      labels:
         apps: python
    spec:
      # 指定sa的名称,请确认该账号是有权限访问K8S集群的哟!
      serviceAccountName: liux-python
      containers:
      - image: harbor.liux.com/liux-tools/python:3.9.16-alpine3.16
        name: c1
        command:
        - tail 
        - -f
        - /etc/hosts
[root@master231 serviceAccount]# 
[root@master231 serviceAccount]# kubectl apply -f 01-sa-rabc.yaml 
serviceaccount/liux-python created
role.rbac.authorization.k8s.io/liux-pod-reader created
rolebinding.rbac.authorization.k8s.io/liux-sa-to-role created
deployment.apps/liux-python3-sa created
[root@master231 serviceAccount]# 

	
	
- 编写Python程序,进入到"python"Pod所在的容器执行以下Python代码即可!
[root@master231 serviceaccounts]# kubectl get pods
NAME                               READY   STATUS    RESTARTS   AGE
image-pull-policy                  1/1     Running   0          28m
liux-games                         1/1     Running   0          30m
liux-python3-sa-55d4576b8d-7shzp   1/1     Running   0          6m31s
liux-python3-sa-55d4576b8d-n4n89   1/1     Running   0          6m31s
[root@master231 serviceaccounts]# kubectl exec -it liux-python3-sa-55d4576b8d-7shzp -- sh

/ # pip install kubernetes -i https://pypi.tuna.tsinghua.edu.cn/simple/

/ # cat > view-k8s.py <<'EOF'
from kubernetes import client, config

with open('/var/run/secrets/kubernetes.io/serviceaccount/token') as f:
     token = f.read()

configuration = client.Configuration()
configuration.host = "https://kubernetes"  # APISERVER地址
configuration.ssl_ca_cert="/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"  # CA证书 
configuration.verify_ssl = True   # 启用证书验证
configuration.api_key = {"authorization": "Bearer " + token}  # 指定Token字符串
client.Configuration.set_default(configuration)
apps_api = client.AppsV1Api() 
core_api = client.CoreV1Api() 
try:
  print("###### Deployment列表 ######")
  # 列出default命名空间所有deployment名称
  for dp in apps_api.list_namespaced_deployment("default").items:
    print(dp.metadata.name)
except:
  print("没有权限访问Deployment资源!")

try:
  # 列出default命名空间所有pod名称
  print("###### Pod列表 ######")
  for po in core_api.list_namespaced_pod("default").items:
    print(po.metadata.name)
except:
  print("没有权限访问Pod资源!")
EOF

/ # python view-k8s.py
###### Deployment列表 ######
没有权限访问Deployment资源!
###### Pod列表 ######
liux-python3-sa-55d4576b8d-7shzp
liux-python3-sa-55d4576b8d-n4n89

七、总结

Kubernetes RBAC 提供了一个强大、灵活且细粒度的权限管理系统,是保障 Kubernetes 集群安全的关键组件。通过本文档的学习,我们可以得出以下关键点:

RBAC 的核心价值:RBAC 通过角色抽象和绑定机制,实现了权限与主体的解耦,使权限管理更加灵活和可维护。

三种授权策略

  • 用户授权:适用于需要为特定人员分配权限的场景
  • 组授权:适用于需要为团队或部门统一分配权限的场景,提高了管理效率
  • 服务账户授权:适用于应用程序和服务访问 Kubernetes API 的场景,是最佳实践

实践建议

  • 遵循最小权限原则,只为用户或应用程序分配完成任务所需的最小权限
  • 优先使用组授权和服务账户授权,减少单个用户权限管理的工作量
  • 定期审计 RBAC 配置,确保权限设置符合安全策略
  • 使用命名空间隔离不同环境或团队的资源,结合 RBAC 实现多租户安全

技术要点

  • 理解证书中 CN 和 O 字段的含义:CN 标识用户,O 标识组
  • 掌握 kubectl config 命令生成和管理 kubeconfig 文件
  • 熟悉 Role/ClusterRole 和 RoleBinding/ClusterRoleBinding 的配置语法
  • 了解服务账户令牌的自动挂载机制

通过合理配置 RBAC,组织可以确保 Kubernetes 集群的安全性,防止未授权访问,同时为不同团队和应用程序提供适当的访问权限,支持安全的协作和创新。本文档提供的案例和脚本可以作为实际部署 RBAC 策略的参考模板,帮助读者快速掌握 Kubernetes 权限管理的实践技能。

更多推荐