K8S(十二)—— Kubernetes安全机制深度解析与实践:从认证到RBAC授权

文章目录

  • 前言
  • 一、Kubernetes安全机制概述
    • [1.1 核心设计原则](#1.1 核心设计原则)
    • [1.2 安全访问流程](#1.2 安全访问流程)
  • 二、认证(Authentication):确认"你是谁"
    • [2.1 支持的认证方式](#2.1 支持的认证方式)
    • [2.2 需要认证的访问类型](#2.2 需要认证的访问类型)
    • [2.3 端口与证书安全规范](#2.3 端口与证书安全规范)
    • [2.4 证书颁发方式](#2.4 证书颁发方式)
    • [2.5 kubeconfig:认证信息的载体](#2.5 kubeconfig:认证信息的载体)
      • [2.5.1 kubeconfig核心组成](#2.5.1 kubeconfig核心组成)
      • [2.5.2 常用操作](#2.5.2 常用操作)
    • [2.6 Service Account(SA):Pod的身份标识](#2.6 Service Account(SA):Pod的身份标识)
      • [2.6.1 SA的核心特性](#2.6.1 SA的核心特性)
    • [2.7 Secret与SA的关联](#2.7 Secret与SA的关联)
      • [2.7.1 Secret的核心类型](#2.7.1 Secret的核心类型)
      • [2.7.2 SA与Secret的自动挂载](#2.7.2 SA与Secret的自动挂载)
      • [2.7.3 验证挂载结果](#2.7.3 验证挂载结果)
  • 三、鉴权(Authorization):确认"你能做什么"
    • [3.1 常见鉴权策略对比](#3.1 常见鉴权策略对比)
      • [3.1.1 RBAC的核心优势](#3.1.1 RBAC的核心优势)
    • [3.2 RBAC的核心资源对象](#3.2 RBAC的核心资源对象)
    • [3.3 角色定义:Role与ClusterRole](#3.3 角色定义:Role与ClusterRole)
      • [3.3.1 Role:命名空间级角色](#3.3.1 Role:命名空间级角色)
      • [3.3.2 ClusterRole:集群级角色](#3.3.2 ClusterRole:集群级角色)
    • [3.4 角色绑定:RoleBinding与ClusterRoleBinding](#3.4 角色绑定:RoleBinding与ClusterRoleBinding)
    • [3.5 主体(Subject)与JWT](#3.5 主体(Subject)与JWT)
      • [3.5.1 主体类型](#3.5.1 主体类型)
      • [3.5.2 JWT与SA认证](#3.5.2 JWT与SA认证)
    • [3.6 资源(Resources)与操作:RBAC权限的细粒度控制](#3.6 资源(Resources)与操作:RBAC权限的细粒度控制)
      • [3.6.1 子资源的权限控制](#3.6.1 子资源的权限控制)
      • [3.6.2 常用权限配置速查](#3.6.2 常用权限配置速查)
  • [四、准入控制(Admission Control):确认"请求是否合规"](#四、准入控制(Admission Control):确认“请求是否合规”)
    • [4.1 准入插件的核心作用](#4.1 准入插件的核心作用)
    • [4.2 推荐准入插件列表(生产环境)](#4.2 推荐准入插件列表(生产环境))
    • [4.3 核心插件功能说明](#4.3 核心插件功能说明)
  • 五、实战:创建仅管理指定命名空间的用户
    • [5.1 步骤1:创建系统用户](#5.1 步骤1:创建系统用户)
    • [5.2 步骤2:生成HTTPS证书与kubeconfig](#5.2 步骤2:生成HTTPS证书与kubeconfig)
      • [5.2.1 安装证书生成工具](#5.2.1 安装证书生成工具)
      • [5.2.2 生成证书签名请求(CSR)](#5.2.2 生成证书签名请求(CSR))
      • [5.2.3 执行脚本生成证书](#5.2.3 执行脚本生成证书)
      • [5.2.4 生成kubeconfig文件](#5.2.4 生成kubeconfig文件)
    • [5.3 步骤3:创建命名空间与分发kubeconfig](#5.3 步骤3:创建命名空间与分发kubeconfig)
      • [5.3.1 创建目标命名空间`yjs0805`](#5.3.1 创建目标命名空间yjs0805)
      • [5.3.2 执行脚本生成kubeconfig](#5.3.2 执行脚本生成kubeconfig)
      • [5.3.3 分发kubeconfig到`zhangsan`用户目录](#5.3.3 分发kubeconfig到zhangsan用户目录)
    • [5.4 步骤4:配置RBAC授权(Role + RoleBinding)](#5.4 步骤4:配置RBAC授权(Role + RoleBinding))
      • [5.4.1 创建RBAC配置文件`rbac.yaml`](#5.4.1 创建RBAC配置文件rbac.yaml)
      • [5.4.2 应用RBAC配置并验证](#5.4.2 应用RBAC配置并验证)
    • [5.5 步骤5:验证用户权限](#5.5 步骤5:验证用户权限)
      • [5.5.1 验证允许的操作(创建与查看Pod)](#5.5.1 验证允许的操作(创建与查看Pod))
      • [5.5.2 验证拒绝的操作(访问其他资源或命名空间)](#5.5.2 验证拒绝的操作(访问其他资源或命名空间))
    • [5.6 步骤6:管理员侧验证权限生效](#5.6 步骤6:管理员侧验证权限生效)
    • [5.7 可选:授予命名空间管理员权限](#5.7 可选:授予命名空间管理员权限)
  • 总结
  • 附:官方文档参考

前言

在云原生时代,Kubernetes作为分布式集群的核心管理平台,其安全性直接决定了整个集群的稳定与数据安全。Kubernetes的安全设计围绕API Server 展开------作为内部组件通信的中介与外部控制的唯一入口,所有客户端(如kubectl、Pod、组件)对集群资源的操作,都必须通过API Server的三重安全校验。

本文将从认证-鉴权-准入控制三道核心关卡切入,系统讲解Kubernetes安全机制的原理,并通过实战案例演示如何创建仅具备指定命名空间权限的用户,帮助开发者和运维人员构建更安全的K8s集群环境。

一、Kubernetes安全机制概述

Kubernetes 作为分布式集群的管理工具,Kubernetes安全的核心目标是确保只有合法主体能对集群资源执行合规操作,其安全流程通过API Server的三层校验实现,任何一层校验失败,请求都会被直接拒绝。

1.1 核心设计原则

Kubernetes安全机制遵循最小权限与"分层防御"原则:

  • 最小权限:每个主体(用户、组件、Pod)仅获得完成其工作所需的最小权限;
  • 分层防御:通过认证-鉴权-准入控制三层校验,形成递进式安全屏障,避免单一环节失效导致整体安全突破。

1.2 安全访问流程

当客户端(如kubectl、Pod)向API Server发起资源请求时,需依次通过以下三层校验:

  1. 认证(Authentication):验证"请求者是谁",确认请求者的身份合法性;
  2. 鉴权(Authorization):验证"请求者能做什么",判断身份是否有权执行请求的操作;
  3. 准入控制(Admission Control):验证"请求是否符合集群规则",对请求进行变更或拦截(如配额校验、命名空间合法性校验)。

二、认证(Authentication):确认"你是谁"

认证是Kubernetes安全的第一道关卡,用于识别请求者的身份。API Server支持多种认证方式,不同场景下可选择适配的认证方案。

2.1 支持的认证方式

API Server通过启动参数配置认证插件,常见认证方式如下:

  • HTTP Token认证:客户端在HTTP请求头中携带一个长字符串Token,API Server通过内置或外部存储的"Token-用户名"映射关系验证身份;优点是实现简单,缺点是Token易泄露且无过期机制;
  • HTTP Basic认证 :客户端将"用户名:密码"通过Base64编码后,放入Authorization请求头;优点是配置简单,缺点是Base64编码可逆,安全性较低,仅适用于测试环境;
  • HTTPS证书认证(推荐) :基于CA根证书签名的双向TLS认证,是Kubernetes最严格的认证方式。客户端需携带CA签名的证书,API Server同时验证客户端证书与自身证书,确保双向身份合法。

注意:Token认证与Basic认证仅支持"服务端对客户端"的单向认证,无法验证服务端身份;HTTPS证书认证可实现双向认证,是生产环境的首选方案。

2.2 需要认证的访问类型

Kubernetes集群中,所有访问API Server的主体都需通过认证,主要分为两类:

  • Kubernetes组件访问 :包括kubectl(命令行工具)、kubelet(节点代理)、kube-proxy(网络代理)、Controller Manager(控制器管理器)、Scheduler(调度器);
  • Pod访问 :包括以Pod形式运行的集群内部组件(如corednsdashboard),这类访问需通过"Service Account"实现身份认证。

2.3 端口与证书安全规范

API Server默认提供两个端口,对应不同的安全级别:

  • 非安全端口(8080) :仅用于集群内部同机组件通信(如Controller ManagerScheduler与API Server同机部署时),不对外暴露,无需认证;
  • 安全端口(6443) :对外暴露的唯一端口,所有外部访问(如kubectlkubeletkube-proxy)必须通过HTTPS双向认证,是生产环境的核心访问端口。

2.4 证书颁发方式

HTTPS证书的颁发分为"手动签发"与"自动签发"两种,适配不同部署场景:

  • 手动签发 :二进制部署Kubernetes时,需通过CA根证书手动为API Server、kubectl等组件签发证书;优点是可控性高,缺点是操作繁琐,不适用于动态组件(如Pod);
  • 自动签发kubelet首次访问API Server时,先通过Token临时认证;认证通过后,由Controller Manager自动为其签发长期证书,后续kubelet将使用该证书进行认证;优点是适配动态组件,减少人工操作。

2.5 kubeconfig:认证信息的载体

kubeconfig是Kubernetes客户端(如kubectlkubelet)连接API Server的配置文件,包含集群信息、客户端认证信息与上下文参数,是认证流程的核心载体。

2.5.1 kubeconfig核心组成

  • 集群参数:CA根证书(用于验证API Server身份)、API Server地址;
  • 客户端参数:客户端证书与私钥(用于API Server验证客户端身份);
  • 上下文参数:默认集群名、用户名、命名空间(指定客户端默认操作的集群与命名空间)。
  • 通过指定不同 kubeconfig,组件(如 kubeletkube-proxy)可切换不同集群并连接到 API Server。
  • 既是集群描述 ,也是认证信息 的载体。kubectl 默认位置:~/.kube/config

2.5.2 常用操作

kubectl默认读取~/.kube/config路径的kubeconfig文件,可通过--kubeconfig参数指定自定义配置文件:

bash 复制代码
# 使用自定义kubeconfig文件访问集群
kubectl get pods --kubeconfig /path/to/your/kubeconfig

2.6 Service Account(SA):Pod的身份标识

由于Pod是动态创建与销毁的,无法为每个Pod手动签发证书,因此Kubernetes引入Service Account(SA),专门用于Pod访问API Server的身份认证。

2.6.1 SA的核心特性

  • 每个命名空间默认创建一个default SA;
  • 创建Pod时,若未显式指定SA,Pod将自动使用所属命名空间的default SA;
  • SA的认证信息通过Secret挂载到Pod内部,供容器使用。

2.7 Secret与SA的关联

Kubernetes通过Secret 存储SA的认证信息,其中与SA直接关联的是service-account-token类型的Secret。

2.7.1 Secret的核心类型

  • service-account-token:存储SA的认证Token、CA根证书与命名空间信息,用于Pod访问API Server;
  • Opaque:存储用户自定义的敏感信息(如密码、密钥),需手动创建与挂载。

2.7.2 SA与Secret的自动挂载

创建Pod后,Kubernetes会自动将SA关联的service-account-token Secret挂载到Pod的/var/run/secrets/kubernetes.io/serviceaccount/路径下,挂载内容包括:

  • ca.crt:CA根证书,用于Pod验证API Server身份;
  • namespace:SA所属的命名空间;
  • token:SA的认证Token,用于API Server验证Pod身份。

这也是Service Account 的三个组成部分

bash 复制代码
/var/run/secrets/kubernetes.io/serviceaccount/
  ├─ ca.crt
  ├─ namespace
  └─ token

2.7.3 验证挂载结果

通过以下命令可查看Pod内挂载的SA认证信息:

bash 复制代码
# 1. 查看命名空间下的SA
kubectl get sa
# 输出示例(default命名空间默认SA)
NAME      SECRETS   AGE
default   1         6d21h

# 2. 查看kube-system命名空间的kube-proxy Pod
kubectl get po -n kube-system
# 示例输出
NAME                               READY   STATUS    RESTARTS   AGE
kube-proxy-hgghd                   1/1     Running   0          6d21h
kube-proxy-hsc69                   1/1     Running   4          6d21h
kube-proxy-vwxc6                   1/1     Running   0          6d21h

# 3. 查看挂载的SA认证文件
kubectl exec -it kube-proxy-xxxx -n kube-system sh -- ls /var/run/secrets/kubernetes.io/serviceaccount/
# 输出:ca.crt  namespace  token

三、鉴权(Authorization):确认"你能做什么"

鉴权是Kubernetes安全的第二道关卡,在认证通过后,判断请求者是否有权执行目标操作(如"查看Pod""创建Deployment")。API Server通过--authorization-mode参数配置鉴权策略,其中RBAC(基于角色的访问控制) 是Kubernetes 1.6+版本的默认且推荐的鉴权方案。

3.1 常见鉴权策略对比

Kubernetes支持多种鉴权策略,不同策略的适用场景差异较大:

鉴权策略 核心逻辑 优点 缺点 适用场景
AlwaysDeny 拒绝所有请求 实现简单 无实际业务价值 测试环境(验证拒绝逻辑)
AlwaysAllow 允许所有请求 无需配置 完全无安全防护 测试环境(快速部署)
ABAC(属性基) 基于用户、资源、操作的属性配置静态规则 规则细粒度高 配置繁琐,修改需重启API Server 复杂且固定的权限场景
Webhook 调用外部REST服务判断权限 权限逻辑与集群解耦 依赖外部服务,增加延迟与故障点 跨集群统一权限管理
RBAC(角色基) 基于"角色-权限-用户"的动态绑定 动态调整、细粒度高、无需重启API Server 需理解角色与绑定关系 生产环境(默认推荐)

3.1.1 RBAC的核心优势

RBAC成为生产环境首选的原因在于其三大特性:

  1. 覆盖全场景 :支持对资源型对象(如Pod、Service)与非资源型对象(如集群状态、元信息)的权限控制;
  2. 方便管理 :权限通过Kubernetes API资源对象(Role、RoleBinding等)定义,可用 kubectl/API 管理;
  3. 动态调整 :可通过kubectl或API实时修改,无需重启API Server(ABAC 需重启);

3.2 RBAC的核心资源对象

RBAC通过4个顶级API资源对象实现权限管理,分为"角色定义"与"角色绑定"两类:

  • 角色定义对象 :定义"有哪些权限";
    • Role:命名空间级角色,权限仅作用于所属命名空间;
    • ClusterRole:集群级角色,权限可作用于全集群或跨命名空间;
  • 角色绑定对象 :定义"谁拥有这些权限";
    • RoleBinding:命名空间级绑定,将Role/ClusterRole的权限赋予指定主体(用户、用户组、SA),权限仅作用于所属命名空间;
    • ClusterRoleBinding:集群级绑定,将ClusterRole的权限赋予指定主体,权限作用于全集群。

关键注意点:若用RoleBinding绑定ClusterRole,权限仍受RoleBinding所属命名空间限制;仅当用ClusterRoleBinding绑定ClusterRole时,权限才作用于全集群。

3.3 角色定义:Role与ClusterRole

角色的核心是"权限规则(Rules)",规则由apiGroups(API组)、resources(资源类型)、verbs(操作类型)三部分组成。

注意点

  • 权限仅能累加(白名单),不存在"先有很多再减少"的黑名单模型。
  • Role 只能定义在 某个命名空间 内;跨命名空间请使用 ClusterRole

3.3.1 Role:命名空间级角色

Role仅作用于其所属的命名空间,无法对跨命名空间资源生效。以下示例定义一个在default命名空间中"读取Pod"的Role:

yaml 复制代码
apiVersion: rbac.authorization.k8s.io/v1  # RBAC API组与版本
kind: Role                                 # 资源类型为Role
metadata:
  namespace: default                       # 作用于default命名空间
  name: pod-reader                         # Role名称
rules:                                     # 权限规则列表
- apiGroups: [""]                          #""表示 apiGroups 和 apiVersion 使用相同的 core API 组,即 rbac.authorization.k8s.io
  resources: ["pods"]                      # 资源类型为Pod
  verbs: ["get", "watch", "list"]          # 允许的操作:获取、监听、列出Pod

#以上配置的意义是,如果把 pod-reader 这个 Role 赋予给一个用户,那么这个用户将在 default 命名空间中具有对 Pod 资源对象 进行 get(获取)、watch(监听)、list(列出)这三个操作权限。

3.3.2 ClusterRole:集群级角色

ClusterRole不受命名空间限制,可作用于全集群,支持对"集群级资源"(如Node)、"跨命名空间资源"(如Secret)的权限定义。以下示例定义一个"读取全集群Secret"的ClusterRole:

yaml 复制代码
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole                          # 资源类型为ClusterRole
metadata:
  name: secret-reader                      # ClusterRole名称(无namespace字段)
rules:
- apiGroups: [""]
  resources: ["secrets"]                   # 资源类型为Secret
  verbs: ["get", "watch", "list"]          # 允许的操作:获取、监听、列出Secret

3.4 角色绑定:RoleBinding与ClusterRoleBinding

角色绑定的核心是"将角色的权限赋予主体",主体(Subject)包括User(用户)、Group(用户组)、ServiceAccount(服务账号)三类

3.4.1 RoleBinding:命名空间级绑定

RoleBinding仅在其所属命名空间内生效,可绑定Role或ClusterRole(绑定ClusterRole时,权限仍受命名空间限制)。

示例1:绑定Role到用户

default命名空间的pod-reader Role赋予用户zhangsan,使其仅能在default命名空间读取Pod:

yaml 复制代码
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods                          # RoleBinding名称
  namespace: default                       # 作用于default命名空间
subjects:                                  # 主体列表(被授权者)
- kind: User                               # 主体类型为用户
  name: zhangsan                           # 用户名
  apiGroup: rbac.authorization.k8s.io      # 主体所属API组
roleRef:                                   # 引用的角色(授权来源)
  kind: Role                               # 引用的角色类型为Role
  name: pod-reader                         # 引用的Role名称
  apiGroup: rbac.authorization.k8s.io      # 角色所属API组

#将 default 命名空间的 pod-reader Role 授予 zhangsan 用户,此后 zhangsan 用户在 default 命名空间中将具有 pod-reader 的权限。
示例2:绑定ClusterRole到用户

通过RoleBinding引用secret-reader ClusterRole,将"读取Secret"的权限赋予用户lisi,但仅作用于kube-public命名空间:

yaml 复制代码
# RoleBinding 同样可以引用 ClusterRole 来对当前 namespace 内 User、Group 或 ServiceAccount 进行授权
# 这种操作允许集群管理员在整个集群内定义一些通用的 ClusterRole,然后在不同的 namespace 中使用 RoleBinding 来引用。
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-secrets                       # RoleBinding名称
  namespace: kube-public                   # 作用于kube-public命名空间
subjects:
- kind: User
  name: lisi
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole                        # 引用的角色类型为ClusterRole
  name: secret-reader                      # 引用的ClusterRole名称
  apiGroup: rbac.authorization.k8s.io

注意:尽管secret-reader ClusterRole本身具备全集群读取Secret的权限,但RoleBinding的namespace: kube-public限制了lisi仅能在kube-public命名空间读取Secret。

3.4.2 ClusterRoleBinding:集群级绑定

ClusterRoleBinding作用于全集群,仅能绑定ClusterRole,将权限赋予主体后,主体可在所有命名空间执行对应操作。

示例:绑定ClusterRole到用户组

secret-reader ClusterRole赋予manager用户组,使其所有成员能在全集群读取Secret:

yaml 复制代码
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: read-secrets-global                # ClusterRoleBinding名称
subjects:
- kind: Group                              # 主体类型为用户组
  name: manager                            # 用户组名称
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: secret-reader
  apiGroup: rbac.authorization.k8s.io

#以上 ClusterRoleBinding 授权 manager 组内所有用户在全部命名空间中对 secrets 进行访问。

3.5 主体(Subject)与JWT

3.5.1 主体类型

RBAC支持三类主体(Subject),覆盖所有访问集群的场景:

  • User(用户):由外部系统管理(如LDAP、证书CN字段),Kubernetes不提供内置用户管理功能;
  • Group(用户组) :用于批量授权,如system:masters组(默认集群管理员组);
  • ServiceAccount(服务账号):用于Pod访问API Server,由Kubernetes自动管理。

注意:

  • system:前缀为Kubernetes系统保留前缀,普通用户/用户组应避免使用,以防与系统权限冲突。
  • Pod 使用 SA认证时,其 service-account-token中的 JWT 保存用户信息;结合 Role/ClusterRole + (Cluster)RoleBinding完成权限绑定。

3.5.2 JWT与SA认证

Pod使用SA认证时,其挂载的token文件是一个JWT(JSON Web Token),包含以下核心信息:

  • 主体身份(SA名称与命名空间);
  • 签发者(API Server);
  • 过期时间。

API Server验证JWT的签名(通过自身私钥)后,提取主体信息,再结合Role/ClusterRole与绑定关系判断权限。

3.6 资源(Resources)与操作:RBAC权限的细粒度控制

RBAC的权限规则通过"资源(resources)"与"操作(verbs)"定义,支持对资源的细粒度控制,包括"子资源"(如Pod的log)。

API 中对 Pod 日志的请求 URL 样例如下:

bash 复制代码
GET /api/v1/namespaces/{namespace}/pods/{name}/log

3.6.1 子资源的权限控制

部分资源包含"子资源",如Pod的log(日志)、exec(执行命令),需通过资源/子资源格式定义权限。以下示例定义一个"读取Pod与Pod日志"的Role:

yaml 复制代码
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
  resources: ["pods", "pods/log"]  # 同时授权Pod与Pod的log子资源
  verbs: ["get", "list"]           # 允许获取Pod与Pod日志

3.6.2 常用权限配置速查

类别 常用值
verbs(操作) get(获取)、list(列出)、watch(监听)、create(创建)、update(更新)、delete(删除)、exec(执行命令)
resources(资源) podsservicessecretsconfigmapsdeploymentsdaemonsetsnodesnamespaces
apiGroups(API组) ""(核心组)、apps(Deployment/StatefulSet所属组)、autoscaling(HPA所属组)、batch(CronJob所属组)

四、准入控制(Admission Control):确认"请求是否合规"

准入控制是Kubernetes安全的第三道关卡,通过一组"准入插件(Admission Controller)"对请求进行校验与修改。请求通过认证与鉴权后,将依次经过所有准入插件的校验,任何一个插件拒绝请求,整个请求都会被驳回

4.1 准入插件的核心作用

准入插件分为两类:

  • 验证型插件(Validating):仅校验请求是否合规(如配额是否充足、命名空间是否存在),不修改请求;
  • 修改型插件(Mutating):在请求合规的前提下,自动修改请求内容(如为Pod自动注入SA、设置默认存储类)。

4.2 推荐准入插件列表(生产环境)

Kubernetes官方推荐的准入插件组合(不同版本略有差异)如下,可通过API Server启动参数--enable-admission-plugins配置:

复制代码
NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,NodeRestriction

4.3 核心插件功能说明

插件名称 类型 核心功能
NamespaceLifecycle 验证型 管理命名空间生命周期:拒绝在不存在的命名空间创建资源;禁止删除系统命名空间;删除命名空间时级联清理资源
LimitRanger 验证/修改型 基于LimitRange配置,为Pod设置默认资源限制(如CPU/内存);拒绝超过限制的资源请求
ServiceAccount 修改型 为未指定SA的Pod自动注入所属命名空间的default SA;自动挂载SA关联的Secret
DefaultStorageClass 修改型 为未指定存储类的PVC自动设置默认存储类
ResourceQuota 验证型 基于ResourceQuota配置,限制命名空间的总资源使用(如最大Pod数量、总CPU配额);拒绝超过配额的请求
NodeRestriction 验证型 限制Node组件的权限,仅允许Node修改自身相关资源(如Node、Pod绑定),防止Node越权

官方文档参考:https://kubernetes.io/zh/docs/reference/access-authn-authz/admission-controllers/

五、实战:创建仅管理指定命名空间的用户

本节通过实战演示如何创建用户zhangsan,使其仅能在yjs0805命名空间对Pod执行get/watch/list/create操作,深入理解RBAC的权限控制逻辑。

5.1 步骤1:创建系统用户

首先在集群控制节点创建Linux系统用户zhangsan(Kubernetes的User需与系统用户关联):

bash 复制代码
# 1. 创建系统用户zhangsan
useradd zhangsan

# 2. 设置用户密码(按提示输入密码)
passwd zhangsan

# 3. 切换到zhangsan用户,尝试访问集群(此时未配置认证信息,访问会失败)
su - zhangsan
kubectl get pods

# 预期输出(失败):
# The connection to the server localhost:8080 was refused - did you specify the right host or port?

5.2 步骤2:生成HTTPS证书与kubeconfig

Kubernetes通过证书识别User身份(证书的CN字段为用户名,O字段为用户组),需先为zhangsan生成证书,再创建对应的kubeconfig文件。

5.2.1 安装证书生成工具

使用cfssl工具生成证书,需先下载并安装:

bash 复制代码
# 1. 下载cfssl工具(切换到root用户执行)
wget https://github.com/cloudflare/cfssl/releases/download/v1.6.4/cfssl_1.6.4_linux_amd64 -O /usr/local/bin/cfssl
wget https://github.com/cloudflare/cfssl/releases/download/v1.6.4/cfssljson_1.6.4_linux_amd64 -O /usr/local/bin/cfssljson
wget https://github.com/cloudflare/cfssl/releases/download/v1.6.4/cfssl-certinfo_1.6.4_linux_amd64 -O /usr/local/bin/cfssl-certinfo

# 或者
传证书工具至 /usr/local/bin:cfssl、cfssljson、cfssl-certinfo

# 2. 赋予执行权限
chmod +x /usr/local/bin/cfssl*

5.2.2 生成证书签名请求(CSR)

创建证书申请文件,指定用户名(CN: zhangsan)与用户组(O: k8s):

bash 复制代码
# 1. 创建工作目录(root用户执行)
mkdir -p /opt/zhangsan && cd /opt/zhangsan

# 2. 创建证书申请脚本user-cert.sh
vim user-cert.sh

脚本内容如下(CN为用户名,O为用户组,需与后续RBAC绑定的主体一致):

bash 复制代码
#! /bin/bash
# 生成证书签名请求(CSR)配置文件
cat > zhangsan-csr.json <<EOF
{
  "CN": "zhangsan",                # 用户名(Kubernetes User)
  "hosts": [],                     # 证书生效的主机列表,空表示所有主机
  "key": {
    "algo": "rsa",                 # 密钥算法
    "size": 2048                   # 密钥长度
  },
  "names": [
    {
      "C": "CN",                   # 国家
      "ST": "BeiJing",             # 省份
      "L": "BeiJing",              # 城市
      "O": "k8s",                  # 用户组(Kubernetes Group)
      "OU": "System"               # 组织单元
    }
  ]
}
EOF
#API Server 会把客户端证书的 CN 字段作为 User,把 names.O 字段作为 Group
# 使用集群CA根证书签发用户证书(CA证书默认路径为/etc/kubernetes/pki/)
cd /etc/kubernetes/pki/
cfssl gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes /opt/zhangsan/zhangsan-csr.json | cfssljson -bare zhangsan

======================================================================================
#! /bin/bash
cat > zhangsan-csr.json <<EOF
{
  "CN": "zhangsan",
  "hosts": [],
  "key": {
    "algo": "rsa",
    "size": 2048
  },
  "names": [
    {
      "C": "CN",
	  "ST": "BeiJing",
      "L": "BeiJing",
      "O": "k8s",
	  "OU": "System"
    }
  ]
}
EOF
#API Server 会把客户端证书的 CN 字段作为 User,把 names.O 字段作为 Group
cd /etc/kubernetes/pki/
cfssl gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes /opt/zhangsan/zhangsan-csr.json | cfssljson -bare zhangsan

5.2.3 执行脚本生成证书

bash 复制代码
# 1. 赋予脚本执行权限
chmod +x user-cert.sh

# 2. 执行脚本生成证书
./user-cert.sh

#/etc/kubernetes/pki/ 目录中会生成 zhangsan-key.pem、zhangsan.pem、
# 3. 查看生成的证书文件(在/etc/kubernetes/pki/目录下)
ls /etc/kubernetes/pki/zhangsan*
# 预期输出:zhangsan.csr(证书签名请求)、zhangsan-key.pem(用户私钥)、zhangsan.pem(用户证书)

5.2.4 生成kubeconfig文件

创建kubeconfig脚本,为zhangsan配置集群信息、客户端认证信息与默认上下文:

bash 复制代码
# 1. 在/opt/zhangsan目录创建kubeconfig脚本rbac-kubeconfig.sh
cd /opt/zhangsan
vim rbac-kubeconfig.sh

脚本内容如下(需将192.168.10.14替换为你的API Server地址):

bash 复制代码
#!/bin/bash
# 接收API Server地址作为参数(如./rbac-kubeconfig.sh 192.168.10.14)
APISERVER=$1

# 设置集群参数(指定CA证书与API Server地址)
export KUBE_APISERVER="https://$APISERVER:6443"
kubectl config set-cluster kubernetes \
  --certificate-authority=/etc/kubernetes/pki/ca.crt \
  --embed-certs=true \
  --server=${KUBE_APISERVER} \
  --kubeconfig=zhangsan.kubeconfig

# 设置客户端认证参数(指定用户证书与私钥)
kubectl config set-credentials zhangsan \
  --client-key=/etc/kubernetes/pki/zhangsan-key.pem \
  --client-certificate=/etc/kubernetes/pki/zhangsan.pem \
  --embed-certs=true \
  --kubeconfig=zhangsan.kubeconfig

# 设置上下文参数(默认集群、用户、命名空间)
kubectl config set-context kubernetes \
  --cluster=kubernetes \
  --user=zhangsan \
  --namespace=yjs0805 \
  --kubeconfig=zhangsan.kubeconfig

# 激活上下文(设置默认使用的上下文)
kubectl config use-context kubernetes --kubeconfig=zhangsan.kubeconfig

5.3 步骤3:创建命名空间与分发kubeconfig

5.3.1 创建目标命名空间yjs0805

bash 复制代码
# root用户执行,创建命名空间
kubectl create namespace yjs0805

# 验证命名空间是否创建成功
kubectl get ns yjs0805
# 预期输出:NAME       STATUS   AGE
#          yjs0805   Active   10s

5.3.2 执行脚本生成kubeconfig

bash 复制代码
# 1. 赋予脚本执行权限
chmod +x rbac-kubeconfig.sh

# 2. 执行脚本(替换192.168.10.14为你的API Server地址)
./rbac-kubeconfig.sh 192.168.10.14

# 3. 查看生成的kubeconfig文件
ls zhangsan.kubeconfig
# 预期输出:zhangsan.kubeconfig

5.3.3 分发kubeconfig到zhangsan用户目录

将生成的zhangsan.kubeconfig文件复制到zhangsan用户的默认kubeconfig路径(~/.kube/config):

bash 复制代码
# 1. 为zhangsan用户创建.kube目录
mkdir -p /home/zhangsan/.kube

# 2. 复制kubeconfig文件
cp zhangsan.kubeconfig /home/zhangsan/.kube/config

# 3. 修改文件权限(确保zhangsan用户拥有读写权限)
chown -R zhangsan:zhangsan /home/zhangsan/.kube/

# 4. 查看 kubeconfig
cat zhangsan-kubeconfig

5.4 步骤4:配置RBAC授权(Role + RoleBinding)

创建Role定义"yjs0805命名空间的Pod操作权限",再通过RoleBinding将Role赋予zhangsan用户。

5.4.1 创建RBAC配置文件rbac.yaml

bash 复制代码
# root用户执行,创建rbac.yaml文件
vim rbac.yaml

文件内容如下:

yaml 复制代码
# 定义Role:在yjs0805命名空间对Pod执行get/watch/list/create操作
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: yjs0805  # 作用于yjs0805命名空间
  name: pod-reader    # Role名称
rules:
- apiGroups: [""]
  resources: ["pods"] # 资源类型为Pod
  verbs: ["get", "watch", "list", "create"] # 允许的操作
---
# 定义RoleBinding:将pod-reader Role赋予zhangsan用户
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods     # RoleBinding名称
  namespace: yjs0805  # 作用于yjs0805命名空间
subjects:
- kind: User          # 主体类型为用户
  name: zhangsan      # 用户名(与证书CN字段一致)
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role          # 引用的角色类型为Role
  name: pod-reader    # 引用的Role名称
  apiGroup: rbac.authorization.k8s.io
======================================================================================
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: yjs0805
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list", "create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: yjs0805
subjects:
- kind: User
  name: zhangsan
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

5.4.2 应用RBAC配置并验证

bash 复制代码
# 1. 应用RBAC配置
kubectl apply -f rbac.yaml

# 2. 验证Role与RoleBinding是否创建成功
kubectl get role,rolebinding -n yjs0805
# 预期输出:
# role.rbac.authorization.k8s.io/pod-reader   2025-10-18T08:20:12Z
# rolebinding.rbac.authorization.k8s.io/read-pods   Role/pod-reader   37s

5.5 步骤5:验证用户权限

切换到zhangsan用户,验证其权限是否符合预期(仅能在yjs0805命名空间操作Pod,无其他权限)。

5.5.1 验证允许的操作(创建与查看Pod)

bash 复制代码
# 1. 切换到zhangsan用户
su - zhangsan

# 2. 创建测试Pod的配置文件pod-test.yaml
cat > pod-test.yaml <<'YAML'
apiVersion: v1
kind: Pod
metadata:
  name: pod-test
spec:
  containers:
    - name: nginx
      image: nginx  # 使用nginx镜像
YAML

# 3. 在yjs0805命名空间创建Pod(允许)
kubectl create -f pod-test.yaml

# 4. 查看yjs0805命名空间的Pod(允许)
kubectl get pods -o wide
# 预期输出:
# NAME       READY   STATUS    RESTARTS   AGE    IP           NODE     NOMINATED NODE   READINESS GATES
# pod-test   1/1     Running   0          2m     10.244.2.2   node02   <none>           <none>

5.5.2 验证拒绝的操作(访问其他资源或命名空间)

bash 复制代码
# 1. 尝试查看yjs0805命名空间的Service(拒绝,无Service权限)
kubectl get svc
# 预期输出(失败):
# Error from server (Forbidden): services is forbidden: User "zhangsan" cannot list resource "services" in API group "" in the namespace "yjs0805"

# 2. 尝试查看default命名空间的Pod(拒绝,无跨命名空间权限)
kubectl get pods -n default
# 预期输出(失败):
# Error from server (Forbidden): pods is forbidden: User "zhangsan" cannot list resource "pods" in API group "" in the namespace "default"

5.6 步骤6:管理员侧验证权限生效

切换到root用户(集群管理员),验证zhangsan创建的Pod仅存在于yjs0805命名空间:

bash 复制代码
# 1. 切换到root用户
exit  # 退出zhangsan用户,回到root用户

# 2. 查看全集群的Pod
kubectl get pods --all-namespaces -o wide
# 预期输出(仅yjs0805命名空间有pod-test):
# NAMESPACE  NAME       READY   STATUS    RESTARTS   AGE    IP           NODE
# yjs0805    pod-test   1/1     Running   0          5m     10.244.2.2   node02

5.7 可选:授予命名空间管理员权限

若需让zhangsan具备yjs0805命名空间的"管理员权限"(可操作所有资源),可通过RoleBinding引用Kubernetes内置的admin ClusterRole:

bash 复制代码
# root用户执行,将admin ClusterRole赋予zhangsan用户(仅作用于yjs0805命名空间)
kubectl create rolebinding zhangsan-admin-binding \
  --clusterrole=admin \
  --user=zhangsan \
  --namespace=yjs0805

# 验证绑定结果
kubectl get rolebinding -n yjs0805
# 预期输出:
# NAME                     ROLE                AGE
# read-pods                Role/pod-reader     10m
# zhangsan-admin-binding   ClusterRole/admin   30s

总结

Kubernetes的安全机制通过"认证-鉴权-准入控制"三层防御,构建了从"身份验证"到"权限控制"再到"请求合规"的完整安全体系:

  1. 认证:通过证书、Token等方式确认"请求者是谁",是安全的基础;
  2. 鉴权:通过RBAC实现"细粒度权限控制",确保主体仅能执行必要操作,是安全的核心;
  3. 准入控制:通过插件链对请求进行"合规校验与自动修改",是安全的补充屏障。

在实际生产环境中,需重点关注以下几点:

  • 优先使用HTTPS证书认证,避免Token或Basic认证;
  • 基于RBAC配置最小权限,避免过度授权(如不随意将cluster-admin权限赋予普通用户);
  • 启用官方推荐的准入插件,尤其是ResourceQuota(配额控制)与NodeRestriction(Node权限限制);
  • 定期轮换证书与Token,避免长期泄露导致安全风险。

通过本文的理论讲解与实战演示,相信你已掌握Kubernetes安全机制的核心原理与配置方法,可根据实际业务需求构建更安全、更可靠的K8s集群。

附:官方文档参考

相关推荐
用户962377954484 小时前
DVWA 靶场实验报告 (High Level)
安全
数据智能老司机7 小时前
用于进攻性网络安全的智能体 AI——在 n8n 中构建你的第一个 AI 工作流
人工智能·安全·agent
数据智能老司机7 小时前
用于进攻性网络安全的智能体 AI——智能体 AI 入门
人工智能·安全·agent
用户962377954489 小时前
DVWA 靶场实验报告 (Medium Level)
安全
red1giant_star9 小时前
S2-067 漏洞复现:Struts2 S2-067 文件上传路径穿越漏洞
安全
用户9623779544812 小时前
DVWA Weak Session IDs High 的 Cookie dvwaSession 为什么刷新不出来?
安全
蝎子莱莱爱打怪1 天前
GitLab CI/CD + Docker Registry + K8s 部署完整实战指南
后端·docker·kubernetes
cipher2 天前
ERC-4626 通胀攻击:DeFi 金库的"捐款陷阱"
前端·后端·安全
蝎子莱莱爱打怪4 天前
Centos7中一键安装K8s集群以及Rancher安装记录
运维·后端·kubernetes
崔小汤呀5 天前
Docker部署Nacos
docker·容器