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集群。

附:官方文档参考

相关推荐
liming4953 小时前
k8s 安装 kuboardV3 报错
云原生·容器·kubernetes
Guheyunyi5 小时前
风险感知中枢:监测预警系统的架构与核心
大数据·运维·安全·重构·架构·自动化
lingggggaaaa8 小时前
小迪安全v2023学习笔记(一百三十四讲)—— Windows权限提升篇&数据库篇&MySQL&MSSQL&Oracle&自动化项目
java·数据库·windows·笔记·学习·安全·网络安全
明灯L10 小时前
《Kubernetes 集群搭建全指南:从核心概念到环境部署!》
云原生·容器·kubernetes
insight^tkk10 小时前
【Docker】记录一次使用docker部署dify网段冲突的问题
运维·人工智能·docker·ai·容器
江湖人称小鱼哥10 小时前
WSL + Docker 网络访问详解
网络·docker·容器·wsl
韩宏伟10 小时前
使用 Loki + Promtail + Grafana 实现 Docker 容器日志采集与可视化
docker·容器·grafana
FreeBuf_10 小时前
Spring两大漏洞可导致泄露敏感信息及安全防护绕过(CVE-2025-41253/41254)
java·安全·spring
荣光波比11 小时前
K8S(十五)—— 企业级K8s集群管理实践:Rancher安装配置与核心功能实操
容器·kubernetes·rancher