K8S安全框架深度解析-从认证到RBAC实战完全指南

K8S安全框架深度解析:从认证到RBAC实战完全指南

导读 :Kubernetes 的安全体系是生产环境的基石。一个配置不当的集群,可能因为权限滥用、匿名访问或认证绕过导致严重的安全事故。本文从 API Server 的角度发,逐步拆解 认证 → 鉴权 → 准入控制 三层防线,并通过 静态令牌认证、X509 证书签发、RBAC 角色绑定、ServiceAccount 授权 四个递进式实战,帮你彻底掌握 K8S 安全框架。


一、API Server 访问控制全貌

Kubernetes API Server 是集群的唯一入口 ,所有对集群资源的操作(无论是 kubectl 命令、客户端 SDK 还是 Dashboard)最终都是向 API Server 发送 HTTPS 请求。因此,API Server 内置了一套插件化的访问控制机制,分为三层:

复制代码
客户端请求 ──→认证(Authentication) ──→鉴权(Authorization) ──→ 准入控制(Admission) ──→ etcd
                身份是谁?             能做什么操作?             操作内容合规吗?
层级 作用 逻辑 说明
认证 核验请求者身份 逻辑(任一插件成功即通过) 回答"你是谁"
鉴权 核验操作是否被许可 逻辑(任一插件授权即通过) 回答"你能做什么"
准入控制 检查操作内容合规性 逻辑(所有插件都必须通过) 回答"操作内容合规吗",仅对写请求有效

1.1 认证(Authentication)

认证过程回答的是 "你是谁" 的问题。K8S 支持多种认证方式,任何一个认证插件成功后即停止后续验证(或逻辑 )。如果所有插件都失败,请求将以匿名用户 system:anonymous 身份继续。

支持的主要认证策略:

认证方式 适用场景 说明
X.509 客户端证书 各组件间通信、管理员访问 双向 TLS,CN=用户名,O=用户组
静态令牌文件 测试、简单场景 --token-auth-file 加载 CSV 文件
Bootstrap 令牌 节点加入集群 kubeadm token 管理
ServiceAccount 令牌 Pod 内进程访问 API Server 自动挂载,内置启用
OIDC 令牌 企业统一认证 类似 OAuth2(微信/支付宝登录)
Webhook 令牌 外部认证集成 支持 LDAP、钉钉等
匿名请求 开发测试 生产环境建议禁用

1.2 鉴权(Authorization)

认证通过后,鉴权层判断该用户是否有权限执行请求的操作。K8S 同样采用或逻辑------任一授权插件允许即通过。

主要鉴权模式:

模式 说明
RBAC(推荐) 基于角色的访问控制,1.8+ 默认启用,本文重点
ABAC 基于属性的访问控制,维护成本高
Webhook 通过外部 HTTP 服务进行授权回调
Node 专门为 kubelet 设计的授权模式

1.3 准入控制(Admission Control)

准入控制在数据写入 etcd 之前做最后的检查,仅对写请求生效,分为两类:

  • Validating(校验):检查字段类型、值是否合法
  • Mutating(变更):自动补全或修正默认字段(如自动注入 Sidecar)

准入控制遵循与逻辑,所有插件都必须通过。


二、Kubernetes 用户体系

理解 K8S 的用户体系是掌握安全框架的前提。K8S 中的"用户"分为三类:

复制代码
┌─────────────────────────────────────────────────┐
│              Kubernetes 用户体系                   │
├──────────────────┬──────────────────────────────┤
│  Service Account │  Pod 内进程访问 API Server    │
│  (服务账号)       │  引用格式: system:serviceaccount│
│                  │  :<NS>:<SA_NAME>              │
├──────────────────┼──────────────────────────────┤
│  User Account    │  人(管理员/开发者)访问集群    │
│  (用户账号)       │  信息保存在 kubeconfig 文件中  │
│                  │  CN=用户名, O=用户组           │
├──────────────────┼──────────────────────────────┤
│  Anonymous       │  未提供认证信息的请求者         │
│  (匿名账号)       │  system:anonymous             │
│                  │  生产环境建议禁用               │
└──────────────────┴──────────────────────────────┘

关键区别 :ServiceAccount 是 K8S 内置的资源类型,可以通过 kubectl 创建和管理;而 UserAccount 不是资源对象,其信息存储在外部文件(kubeconfig)或外部认证系统中。


三、实战一:静态令牌文件认证

静态令牌认证是最直观的认证方式,适合理解 K8S 认证流程。我们将创建一个 CSV 格式的令牌文件,配置 API Server 加载它,并通过令牌访问集群。

3.1 生成 Token

bash 复制代码
# 方式一:openssl 随机生成
echo "$(openssl rand -hex 3).$(openssl rand -hex 8)"
# 输出示例:01b202.d5c4210389cbff08

# 方式二:kubeadm 生成
kubeadm token generate
# 输出示例:jvt496.ls43vufojf45q73i

3.2 创建 Token CSV 文件

bash 复制代码
cat > /etc/kubernetes/pki/token.csv <<EOF
01b202.d5c4210389cbff08,test01,10001,k8s
497804.9fc391f505052952,test02,10002,k8s
8fd32c.0868709b9e5786a8,test03,10003,k3s
EOF

CSV 格式说明token,用户名,用户ID,用户组,共四个字段,用户组可选。

3.3 修改 API Server 加载 Token 文件

编辑 /etc/kubernetes/manifests/kube-apiserver.yaml,添加启动参数和卷挂载:

yaml 复制代码
spec:
  containers:
  - command:
    - kube-apiserver
    - --token-auth-file=/etc/kubernetes/pki/token.csv    # 添加此行
    ...
    volumeMounts:
    - mountPath: /etc/kubernetes/pki/token.csv            # 添加挂载
      name: static-token-file
      readOnly: true
  volumes:
  - hostPath:
      path: /etc/kubernetes/pki/token.csv
      type: File
    name: static-token-file

通过移动 YAML 文件触发 Pod 重建来重启 API Server:

bash 复制代码
mv /etc/kubernetes/manifests/kube-apiserver.yaml /opt/
mv /opt/kube-apiserver.yaml /etc/kubernetes/manifests/

# 等待 30s+,确认 API Server 就绪
kubectl get pods -n kube-system -l component=kube-apiserver -o wide

3.4 使用 Token 认证访问集群

bash 复制代码
# 场景1:使用有效 Token 认证(已通过认证,但未授权 → 403 Forbidden)
kubectl --server=https://10.0.0.231:6443 \
  --certificate-authority=/etc/kubernetes/pki/ca.crt \
  --token=01b202.d5c4210389cbff08 get nodes
# Error from server (Forbidden): User "test01" cannot list resource "nodes"

# 场景2:使用无效 Token(未通过认证 → 401 Unauthorized)
kubectl --server=https://10.0.0.231:6443 \
  --certificate-authority=/etc/kubernetes/pki/ca.crt \
  --token=invalid.token get nodes
# error: You must be logged in to the server (Unauthorized)

# 场景3:不提供任何认证信息(匿名用户 → 403 Forbidden)
kubectl --server=https://10.0.0.231:6443 \
  --certificate-authority=/etc/kubernetes/pki/ca.crt get nodes
# Error from server (Forbidden): User "system:anonymous" cannot list resource "nodes"

关键理解:这三个场景完美演示了认证与鉴权的区别。场景1认证通过(用户身份已识别为 test01),但鉴权失败(无权限);场景2认证未通过(Token 不存在);场景3被识别为匿名用户。

3.5 curl 基于 Token 的认证测试

bash 复制代码
# 有效 Token(认证通过,但无权限)
curl -k -H "Authorization: Bearer 01b202.d5c4210389cbff08" \
  https://10.0.0.231:6443/api/v1/pods
# 返回 403 Forbidden

# 无效 Token
curl -k -H "Authorization: Bearer invalid.token" \
  https://10.0.0.231:6443/api/v1/pods
# 返回 401 Unauthorized

# 无认证信息
curl -k https://10.0.0.231:6443
# 返回 403 Forbidden (system:anonymous)

四、实战二:X509 证书认证

X509 证书认证是 K8S 生产环境最常用的认证方式。通过自签名证书,将证书中的 CN 字段映射为用户名、O 字段映射为用户组。

4.1 认证流程

复制代码
客户端                          Master 节点
  │                                │
  ├─ 1.生成私钥 (openssl genrsa)    │
  ├─ 2.生成证书签发请求 CSR          │
  │    (CN=用户名, O=用户组)        │
  ├─ 3.CSR 进行 base64 编码 ───────→ 4.创建 CSR 资源
  │                                5.管理员批准 CSR
  │    ←──── 6.导出签发的证书 ─────  7.base64 解码证书
  │                                │
  ├─ 8.配置 kubeconfig 使用证书     │
  ├─ 9.kubectl 访问集群             │

4.2 客户端创建证书签发请求

bash 复制代码
# 1. 生成私钥
openssl genrsa -out test.key 2048

# 2. 生成 CSR(CN=用户名,O=用户组)
openssl req -new -key test.key -out test.csr \
  -subj "/CN=test/O=group"

# 3. 对 CSR 进行 base64 编码
cat test.csr | base64 | tr -d '\n'

4.3 Master 节点签发证书

yaml 复制代码
# csr-test.yaml
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: test-csr
spec:
  # 将 base64 编码的 CSR 内容粘贴到这里
  request: LS0tLS1CRUdJTi...(base64编码的CSR内容)
  # 签名者类型
  signerName: kubernetes.io/kube-apiserver-client
  # 证书有效期(单位:秒,86400 = 24小时)
  expirationSeconds: 86400
  # 密钥用途
  usages:
  - client auth
bash 复制代码
# 创建 CSR 资源
kubectl apply -f csr-test.yaml
kubectl get csr
# NAME        AGE   SIGNERNAME                            REQUESTOR          CONDITION
# test-csr   4s    kubernetes.io/kube-apiserver-client   kubernetes-admin   Pending

# 管理员批准 CSR
kubectl certificate approve test-csr
kubectl get csr
# test-csr   47s   kubernetes.io/kube-apiserver-client   Approved,Issued

# 导出签发的证书
kubectl get csr test-csr -o jsonpath='{.status.certificate}' \
  | base64 -d > test.crt

4.4 CSR 签名者类型说明

K8S 支持三种 CSR 签名者类型:

signerName 用途 自动批准
kubernetes.io/kube-apiserver-client 客户端证书(如管理员) 不自动批准
kubernetes.io/kube-apiserver-client-kubelet Kubelet 客户端证书 可自动批准
kubernetes.io/kubelet-serving Kubelet 服务端证书 不自动批准

4.5 配置 kubeconfig 使用证书

将签发的证书和私钥配置到 kubeconfig 中:

bash 复制代码
# 设置集群信息
kubectl config set-cluster my-cluster \
  --server=https://10.0.0.231:6443 \
  --certificate-authority=/etc/kubernetes/pki/ca.crt \
  --kubeconfig=/root/test-kubeconfig \
  --embed-certs

# 设置用户凭证(使用签发的证书和私钥)
kubectl config set-credentials test \
  --client-certificate=/root/test.crt \
  --client-key=/root/test.key \
  --kubeconfig=/root/test-kubeconfig \
  --embed-certs

# 设置上下文
kubectl config set-context test-context \
  --cluster=my-cluster \
  --user=test \
  --kubeconfig=/root/test-kubeconfig

# 切换当前上下文
kubectl config use-context test-context \
  --kubeconfig=/root/test-kubeconfig

测试访问:

bash 复制代码
# 认证成功(CN 被识别为用户名 "test",O 被识别为用户组 "group")
kubectl --kubeconfig=/root/test-kubeconfig get nodes
# Error from server (Forbidden): User "test" cannot list resource "nodes"
# 注意:此时虽然认证通过,但鉴权尚未配置,所以返回 403

要点:证书中的 CN 字段会被识别为用户名,O 字段会被识别为用户组。这个映射关系是 RBAC 鉴权的基础。


五、RBAC 授权机制详解

RBAC(Role-Based Access Control)是 K8S 1.8 之后默认启用且推荐的授权模式。它的核心思想是:不直接给用户授权,而是将权限绑定到角色上,再将角色绑定给用户

5.1 RBAC 四大资源

复制代码
┌──────────────────────────────────────────────────┐
│                    RBAC 资源模型                    │
│                                                  │
│   Role ──────┐                                   │
│              ├──→ RoleBinding ──→ (User/Group/SA)│
│   ClusterRole┼                                   │
│              ├──→ ClusterRoleBinding → (User/...) │
│              │                                   │
│              └──→ RoleBinding ──→ (User/Group/SA) │
│                 (ClusterRole 降级使用)             │
└──────────────────────────────────────────────────┘
资源 作用范围 说明
Role 命名空间级别 定义在某个命名空间内的权限
ClusterRole 集群级别 定义集群范围的权限,也可用于命名空间
RoleBinding 命名空间级别 将 Role 或 ClusterRole 绑定到用户/组/SA
ClusterRoleBinding 集群级别 将 ClusterRole 绑定到用户/组/SA

关键区别 :Role + RoleBinding = 命名空间级权限;ClusterRole + ClusterRoleBinding = 集群级权限。但 ClusterRole 也可以通过 RoleBinding 绑定,此时 ClusterRole 的权限会被限制在 RoleBinding 所在的命名空间内。

5.2 K8S 内置的 ClusterRole

K8S 自带了几个常用的系统级 ClusterRole:

ClusterRole 权限范围 典型用途
cluster-admin 超级管理员,所有权限 集群管理员
admin 命名空间管理员(不含资源配额) 命名空间负责人
edit 命名空间内读写权限(不含角色/绑定) 开发者
view 命名空间内只读权限 只读用户

六、实战三:RBAC 角色绑定

6.1 创建只读角色(Role + RoleBinding)

给用户 test 授予 kube-public 命名空间的只读权限:

yaml 复制代码
# reader-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: reader
  namespace: kube-public
rules:
- apiGroups: ["", "apps"]
  resources: ["pods", "deployments", "services"]
  verbs: ["get", "list", "watch"]
yaml 复制代码
# reader-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: reader-bind
  namespace: kube-public
subjects:
- kind: User
  name: test
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: reader
  apiGroup: rbac.authorization.k8s.io
bash 复制代码
kubectl apply -f reader-role.yaml
kubectl apply -f reader-binding.yaml

测试验证:

bash 复制代码
kubectl --kubeconfig=/root/test-kubeconfig get pods -n kube-public
# 可以查看 Pod 列表(只读权限生效)

kubectl --kubeconfig=/root/test-kubeconfig delete pod <pod-name> -n kube-public
# Error from server (Forbidden): 用户无删除权限(verbs 中没有 "delete")

6.2 使用 ClusterRole(集群级权限)

创建集群级别的管理员角色:

yaml 复制代码
# admin-clusterrole.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: admin
rules:
- apiGroups: ["", "apps", "extensions"]
  resources: ["*"]
  verbs: ["*"]
yaml 复制代码
# admin-clusterrolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-bind
subjects:
- kind: User
  name: test
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: admin
  apiGroup: rbac.authorization.k8s.io

生产提示resources: ["*"] + verbs: ["*"] 表示对所有资源拥有所有操作权限,在生产环境中应严格控制 ,遵循最小权限原则

6.3 快捷绑定内置 ClusterRole

如果只是需要标准权限,可以直接绑定内置的 ClusterRole,无需自定义:

bash 复制代码
# 将 view 角色绑定给 test 用户(所有命名空间只读)
kubectl create clusterrolebinding test-view-binding \
  --clusterrole=view \
  --user=test

# 将 admin 角色绑定给 test 用户(所有命名空间管理)
kubectl create clusterrolebinding test-admin-binding \
  --clusterrole=admin \
  --user=test

# 将 edit 角色绑定给 ServiceAccount
kubectl create rolebinding sa-edit-binding \
  --clusterrole=edit \
  --serviceaccount=kube-public:test01 \
  --namespace=kube-public

七、实战四:ServiceAccount + RBAC

ServiceAccount 是 K8S 中为 Pod 内进程设计的身份。Pod 默认会自动挂载所在命名空间的 default ServiceAccount。

7.1 创建 ServiceAccount 并绑定权限

yaml 复制代码
# sa.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: test01
  namespace: kube-public
yaml 复制代码
# sa-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: reader-bind
subjects:
- kind: ServiceAccount
  name: test01
  namespace: kube-public
roleRef:
  kind: ClusterRole
  name: reader
  apiGroup: rbac.authorization.k8s.io
bash 复制代码
kubectl apply -f sa.yaml
kubectl apply -f sa-rolebinding.yaml

7.2 在 Pod 中使用 ServiceAccount

yaml 复制代码
# pod-with-sa.yaml
apiVersion: v1
kind: Pod
metadata:
  name: pods-sa
  namespace: kube-public
spec:
  serviceAccountName: test01    # 指定使用自定义 SA
  containers:
  - name: test-container
    image: nginx:1.20
    command: ["/bin/sh", "-c", "sleep 3600"]

Pod 启动后,K8S 会自动将 SA 的 Token 以文件形式挂载到容器内:

复制代码
/var/run/secrets/kubernetes.io/serviceaccount/
├── ca.crt          # API Server 的 CA 证书
├── namespace       # 当前命名空间
└── token           # SA 的 Bearer Token

7.3 在 Pod 内通过 Python SDK 访问 API Server

以下示例展示 Pod 内的进程如何使用自动挂载的 SA Token 访问 API Server:

python 复制代码
# view-k8s-resources.py
from kubernetes import client, config

# Pod 内自动使用挂载的 SA Token
config.load_incluster_config()

apps_api = client.AppsV1Api()
core_api = client.CoreV1Api()

try:
    print("###### Deployment列表 ######")
    for dp in apps_api.list_namespaced_deployment("kube-public").items:
        print(dp.metadata.name)
except:
    print("没有权限访问Deployment资源!")

try:
    print("###### Pod列表 ######")
    for po in core_api.list_namespaced_pod("kube-public").items:
        print(po.metadata.name)
except:
    print("没有权限访问Pod资源!")

将此脚本放入 Pod 中执行:

bash 复制代码
# 进入 Pod 并执行
kubectl -n kube-public exec -it <pod-name> -- python3 view-k8s-resources.py

# 输出示例(有权限时):
# ###### Deployment列表 ######
# xiuxian
# ###### Pod列表 ######
# pods-sa
# xiuxian-6ffc4f5fd7-m9tf2

7.4 验证权限回收

删除 RoleBinding 后,Pod 内的访问将被拒绝:

bash 复制代码
# 删除绑定
kubectl delete clusterrolebinding reader-boy-bind

# 再次在 Pod 内执行脚本
kubectl -n kube-public exec -it <pod-name> -- python3 view-k8s-resources.py
# ###### Deployment列表 ######
# 没有权限访问Deployment资源!
# ###### Pod列表 ######
# 没有权限访问Pod资源!

权限即时生效:RBAC 的权限变更在 API Server 层面即时生效,无需重启 Pod。删除 RoleBinding 后,使用该 SA 的 Pod 立即失去相应权限。


八、生产环境最佳实践

8.1 安全配置检查清单

检查项 推荐做法 命令
禁用匿名访问 --anonymous-auth=false 检查 API Server 启动参数
启用 RBAC --authorization-mode=RBAC K8S 1.8+ 默认启用
启用准入控制 --enable-admission-plugins=NodeRestriction,... 按需启用
审计日志 --audit-log-path=/var/log/audit.log 记录所有 API 请求
最小权限原则 按需分配 Role,避免 resources: ["*"] 定期审查 RoleBinding
SA 自动挂载 对不需要访问 API Server 的 Pod 设为 false automountServiceAccountToken: false

8.2 RBAC 权限设计原则

  1. 最小权限原则:只授予完成工作所需的最小权限集
  2. 命名空间隔离:不同环境的资源分命名空间管理,通过 Role 控制边界
  3. 使用内置角色优先view/edit/admin 覆盖大多数场景
  4. 定期审计:检查是否存在过度授权的 ClusterRoleBinding
  5. 命名规范:Role 和 RoleBinding 的命名应能体现其用途

8.3 禁用 Pod 默认 SA 的 API 访问

对于不需要访问 API Server 的 Pod(如纯计算任务),应禁用 SA Token 自动挂载:

yaml 复制代码
apiVersion: v1
kind: ServiceAccount
metadata:
  name: no-api-access
  namespace: production
automountServiceAccountToken: false    # 禁用自动挂载
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
  namespace: production
spec:
  template:
    spec:
      serviceAccountName: no-api-access
      automountServiceAccountToken: false    # Pod 级别也可设置

8.4 多集群管理方案

在生产环境中,通常需要管理多套 K8S 集群。kubectl 天然支持通过 kubeconfig 管理多集群:

bash 复制代码
# 配置多集群的 kubeconfig
kubectl config set-cluster cluster-a --server=https://10.0.0.231:6443 ...
kubectl config set-cluster cluster-b --server=https://10.0.0.240:8443 ...

# 创建上下文
kubectl config set-context ctx-a --cluster=cluster-a --user=user-a
kubectl config set-context ctx-b --cluster=cluster-b --user=user-b

# 切换集群
kubectl config use-context ctx-a
kubectl get nodes

kubectl config use-context ctx-b
kubectl get nodes

常用多集群管理工具:

工具 特点
kubectl 官方 CLI,通过 kubeconfig 管理多集群
Kuboard 免费 Web UI,最多 3 个集群
KubeSphere 功能全面的国产管理平台
Rancher 企业级多集群管理
云平台 ACK/TKE/CCE 等托管服务

十、总结

K8S 安全框架是一个分层防御体系:

  1. 认证层确认"你是谁"(X509/Token/SA)
  2. 鉴权层判断"你能做什么"(RBAC:Role → RoleBinding → Subject)
  3. 准入控制层检查"操作合规吗"(Validating/Mutating)

生产环境中,建议按照最小权限原则设计 RBAC 策略,禁用匿名访问,定期审计权限配置,并使用专用 ServiceAccount 替代默认 SA。掌握这些内容,你就能构建一个安全、可控的 K8S 集群。

相关推荐
古城小栈1 小时前
K8s 核心知识 讲解
docker·容器·kubernetes
杨云龙UP1 小时前
MySQL主库高峰期备份引发504故障:从库手动切换接管 + 主从恢复同步 + Docker版DB2重启实战_2026-05-17
linux·运维·数据库·mysql·docker·容器·centos
六月雨滴1 小时前
Oracle 数据库网络安全
数据库·安全·dba
xiaoxue..1 小时前
详解:XSS 攻击和 CSRF 攻击
安全·面试·xss·csrf
闵孚龙2 小时前
Claude Code Hooks 用户自定义拦截点全解析:AI Agent 自动化、安全治理、插件扩展、可观测性核心机制
人工智能·安全·自动化
黎阳之光2 小时前
数智孪生,全景可视——黎阳之光透明仓库,重构智慧仓储新范式
大数据·人工智能·算法·安全·数字孪生
Arman_2 小时前
Rust 客户端安全上传下载微软 Azure Blob:rusty-cat SAS 预签名实战
安全·microsoft·rust·azure·断点续传
jran-2 小时前
Docker 架构&命令
运维·docker·容器
祁白_2 小时前
[HCTF 2018]WarmUp1
安全·渗透·测试·ctf·writeup