前言
本文系统阐述Kubernetes安全机制的核心架构与实践方法,详细解析API Server保护的三大关键环节:认证、鉴权和准入控制,以及如何通过RBAC实现细粒度权限管理。特别聚焦在实践中如何创建安全隔离的集群访问账号,适用于Kubernetes安全架构设计与运维人员。
- 安全机制说明
- 认证:身份
- 鉴权:权限
- 准入控制
- 实践:赋权普通用户操作k8s
理论部分
1_安全机制概述
安全机制:保护Kubernetes集群中API Server的三层防护体系,防止未授权访问和操作。
1.1_机制说明
安全体系设计原因:Kubernetes作为分布式集群管理工具,API Server是内部组件通信中介与外部控制入口,安全机制围绕保护API Server设计。
安全三大环节:
- 认证(Authentication):验证"你是谁",确认请求主体身份 --- 身份验证
- 鉴权(Authorization):确定"你能做什么",判定权限范围 --- 资源权限控制
- 准入控制(Admission Control):决定"是否允许该请求被接受",请求进一步校验 --- 二次验证
工作流程:
- 客户端(如kubectl)向API Server发送请求
- 请求通过三重安全关卡(认证→鉴权→准入控制)
- 所有关卡通过后,API Server才处理该请求
2_认证Authentication
2.1_认证方式
认证方式:API Server支持的三种主要认证方式。
| 认证方式 | 实现原理 | 特点 | 核心作用 |
|---|---|---|---|
| HTTP Token | HTTP Header携带难以仿冒的长Token | API Server维护Token与用户权限的映射。 | 授权访问特定API或资源 |
| HTTP Basic | Base64编码的用户名:密码放入Authorization字段 |
简单但安全性极低(密码明文传输,必须配合HTTPS) | 最基础的身份验证 |
| HTTPS证书 | 基于CA根证书签名的双向TLS认证 | 最严格,实现客户端与服务器的双向身份验证 | 建立通信双方的可信身份并加密通道 |
重要说明:
- Token与Basic认证仅支持服务端对客户端的单向认证
- HTTPS证书认证可实现双向认证(客户端与服务端互相验证)
2.2_认证对象
需要被认证的访问类型:
- Kubernetes组件对API Server的访问:kubectl、kubelet、kube-proxy
- 由Kubernetes管理的Pod对API Server的访问:coredns、dashboard等
端口与证书安全性:
- Controller Manager、Scheduler与API Server同机,常走非安全端口(如8080)
- kubectl、kubelet、kube-proxy访问API Server需HTTPS双向认证,端口使用6443
2.3_证书管理
证书颁发方式:
- 手动签发:二进制部署时,需与CA手动签发HTTPS证书
- 自动签发:kubelet首次访问用token认证,通过后由Controller Manager生成证书
kubeconfig:包含三类关键参数的配置文件
- 集群参数:CA证书、API Server地址
- 客户端参数:证书与私钥
- 上下文参数:集群名、用户名、命名空间
- kubectl默认位置:
~/.kube/config
Service Account (SA):用于Pod中容器访问API Server的身份标识
- 自动应对Pod动态创建/销毁场景
- 无需为每个Pod单独发证书
- 默认每个命名空间都有一个SA
2.4_Secret与SA的关系
Secret对象类型:
- service-account-token:保存ServiceAccount的令牌
- Opaque:保存用户自定义的保密信息
Service Account组成:
- Token:API Server私钥签名的Token
- ca.crt:CA根证书,验证API Server证书
- namespace:service-account-token的命名空间作用域
默认行为:
-
若创建Pod时未指定SA,将使用所属命名空间的default SA
-
系统自动将以下内容挂载到容器:
/var/run/secrets/kubernetes.io/serviceaccount/ ├── ca.crt ├── namespace └── token
小结
k8s 安全机制 3关
认证 鉴权 准入控制
认证
token 使用很长复杂的token(令牌)字符串 来做认证,通常是单向认证
basic 使用账号 密码的格式通过 base64编码和解码来做认证 通常是单向的认证
https 使用CA机构签发的证书进行https认证 可以实现双向认证
k8s 认证 组件 (**Controller Manager、Scheduler** **kubectl、kubelet、kube-proxy** 等)与apiserver通信,是使用https证书认证,默认使用6443进行通信 (未知Scheduler Controller 使用内部端口 8080 ),使用kubeconfig配置文件就知道使用什么证书连接到那个K8s的集群的APIserver
pod 形式 的组件 (dashboad coredns 外置存储常插件 比如 NFS provsisnor)与APIserver通信,使用serviceaccount作为pod服务的账号来访问APIserver 每个pod都会有 一个 serviceaccouint服务账号,可以创建pod资源时指定serviceaccouint字段
3_鉴权Authorization 重点
3.1_授权策略对比
授权策略 :API Server通过--authorization-mode参数配置。
| 策略 | 特点 | 适用场景 |
|---|---|---|
| AlwaysDeny | 拒绝所有请求 | 测试环境 |
| AlwaysAllow | 允许所有请求 | 无安全要求环境 |
| ABAC(淘汰) | 基于用户配置的属性的静态规则,繁琐需重启ApiServer。 | 简单权限需求 |
| Webhook | 外部REST服务鉴权,触发器钩子 | 统一外部认证系统 |
| RBAC | 基于角色的动态权限,细粒度,与资源模型一致。 | 生产环境默认(≥v1.6) |
RBAC核心优势:
- 覆盖资源(Pod/Deployment/Service)与非资源(元信息/状态)
- 由标准API资源对象构成,可用kubectl/API管理
- 运行时可调整,无需重启API Server(ABAC需重启)
3.2_RBAC资源对象
① RBAC引入的四个顶级对象
Role
- 命名空间级权限定义
- 定义特定命名空间的权限
ClusterRole - 集群级权限,跨命名空间。
- 定义集体集群范围内的所有权限
RoleBinding - 命名空间内将角色绑定到主体
- 将Role或ClusterRole绑定到特定命名空间的主体
ClusterRoleBinding - 集群级将角色绑定到主体
- 将ClusterRole绑定到整个集群范围内的主体
② 绑定规则
- RoleBinding可引用ClusterRole,但仍受命名空间限制
- ClusterRoleBinding只能绑定ClusterRole作用于全集群
③ 权限控制模型
- 仅能累加(白名单模型)
- 不存在"先权限多再减少"的黑名单机制
- Role仅限单一命名空间;ClusterRole可跨命名空间
3.3_角色与角色绑定
① 角色定义:
- Role:只定义在一个命名空间内的权限
- ClusterRole:可定义跨多个命名空间的权限
Role示例(在default命名空间读取Pod):
yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
ClusterRole示例(读取所有命名空间Secret):
yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
② 角色绑定:
- RoleBinding:将Role/ClusterRole绑定到主体(User/Group/SA),限于命名空间
- ClusterRoleBinding:在全集群范围绑定ClusterRole到主体
RoleBinding示例(将pod-reader绑定给jxc用户):
yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: jxc
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
③ 主体(Subject)类型
- User(用户)
- Group(用户组)
- ServiceAccount(服务账号)
- 系统保留前缀:system:*(管理员应避免普通用户使用)
④ 资源(Resources)定义
- K8s资源以名称字符串表示(如pods, services)
- 子资源:如pods/log
- API访问示例:
GET /api/v1/namespaces/{namespace}/pods/{name}/log - 在RBAC中使用"资源/子资源"控制访问
④ 常见权限
- verbs:get、list、watch、create、update、patch、delete、exec
- resources:services、pods、secrets、configmaps等
- apiGroups:""(core)、apps、autoscaling等
小结:
1、角色(Role/clusterRole)
Role: 定义 特定的命名空间内的权限
clusterRole:定义整体集群范围内的所有权限
2、角色绑定 (RoleBinding/clusterRolebing)
RoleBinding: 将Role或clusterRole绑定到特定(单)的命名空间内的用户、组或服务账号
clusterRolebing:将clusterRole绑定到整个集群范围内的用户、组或服务账号
主体(subject):
用户 (User) 组(Group) 服务账号(SerivceAccount)
权限管理
RBAC 基于 白名单 机制 只能增加权限 无法通过RBAC 直接减少权限
resource
http 调用 一个方法 get pull put
kubectl get pod 来获取 资源的信息 GET /api/v1/namespaces/pods
4_准入控制AdmissionControl
4.1_准入控制概述
Admission Control:API Server处理请求前的最后一道关卡。
工作机制:
- 一组插件链,请求依次通过该列表
- 若任意插件拒绝,整个请求即被拒绝
- 建议采用官方推荐的控制器组合
官方默认插件链:
不同版本有所不同
NamespaceLifecycle,LimitRanger,ServiceAccount,DefaultStorageClass,DefaultTolerationSeconds,MutatingAdmissionWebhook,ValidatingAdmissionWebhook,ResourceQuota,NodeRestriction
4.2_关键插件功能
重点插件说明 :
NamespaceLifecycle:
- 命名空间生命周期管理
- 阻止在不存在的命名空间创建对象
- 阻止删除系统命名空间
- 删除命名空间时级联清理
LimitRanger:
- 配额与限制管理
- 确保请求不超过该命名空间的LimitRange
ServiceAccount:
- 为Pod自动注入ServiceAccount
- 便于Pod访问API Server
ResourceQuota:
- 命名空间级高级配额
- 确保不超过该命名空间的ResourceQuota
NodeRestriction:
- 限制Node加入集群后的权限
- 遵循最小权限原则
官方文档:https://kubernetes.io/zh/docs/reference/access-authn-authz/admission-controllers/
实验部分
1_创建仅能管理指定命名空间的用户
1.1_准备工作
① 创建系统用户
- 创建操作系统层用户
shell
useradd jxc
echo qwer1234 | passwd --stdin jxc
# 切换用户验证
su - jxc
kubectl get pods
ini
The connection to the server localhost:8080 was refused - did you specify the right host or port?
连接到服务器 localhost:8080 被拒绝 - 您是否指定了正确的主机或端口?
useradd:创建系统用户
passwd:设置用户密码jxc用户还未配置kubeconfig所以访问失败,为正常现象
1.2_生成证书与kubeconfig
① 上传证书工具
- 从本地上传证书工具
cfssl、cfssljson、cfssl-certinfo到 Master节点主机的/usr/local/bin目录下
shell
# user@localhost
scp cfssl cfssljson cfssl-certinfo root@k8s-master01:/usr/local/bin/
CFSSL工具链是用于简单快速创建和管理TLS证书的命令行工具集。
cfss:l是核心生成器
cfssljson:负责拆分证书文件
cfssl-certinfo:用于查看证书信息
RSA/ECC非对称加密工具:
注释:RSA历史久远更常见,ECC更小更安全更现代。类似TLS是SSL的迭代产品。
| 工具 | 特点 | 适合场景 |
|---|---|---|
| OpenSSL | 老牌经典,功能全面,预装在多数系统 | 单次手动操作、故障排查、学习原理 |
| CFSSL | 现代,配置驱动,易于自动化 | 云平台、容器集群(如K8s)、需要批量签发证书 |
- 并赋予执行权限
shell。
# root@k8s-master
chmod +x /usr/local/bin/cfssl*
mkdir -p /opt/jxc && cd /opt/jxc
cfssl系列工具需提前安装并放置在PATH中
② 创建证书请求文件
shell
# root@k8s-master01:/opt/jxc
vim user-cert.sh
bash
#!/bin/bash
kube_user=jxc
cat > "$kube_user"-csr.json <<EOF
{
"CN": "$kube_user",
"hosts": [],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"ST": "BeiJing",
"L": "BeiJing",
"O": "k8s",
"OU": "System"
}
]
}
EOF
cd /etc/kubernetes/pki/
cfssl gencert -ca=ca.crt -ca-key=ca.key -profile=kubernetes /opt/$kube_user/"$kube_user"-csr.json | cfssljson -bare $kube_user
algo:algorithm(算法)的缩写
CN:作为User身份
names.O:作为Group身份(k8s)API Server会将CN作为User,names.O作为Group
"hosts": []:用户认证不需要填写,服务器/节点/Pod认证才需要补全hosts信息(IP/域名)。后面会warning警告,不必理会。
- 执行证书生成,会在
/etc/kubernetes/pki/生成证书:jxc-key.pem、jxc.pem、jxc.csr
shell
# root@k8s-master01:/opt/jxc
chmod +x user-cert.sh
./user-cert.sh
ls /opt/jxc /etc/kubernetes/pki/ | grep ^jxc
ini
jxc.csr
jxc-key.pem
jxc.pem
jxc-csr.json
jxc-csr.json:生成证书的申请配置模板 ,里面填写了你的身份信息和需求。
jxc-key.pem:你的私钥 ,是绝不能泄露的核心秘密,用来证明你的身份并对CSR签名。
jxc.csr:根据配置和私钥生成的证书请求文件 ,包含你的公钥和信息,并由私钥签名(数字签名),提交给CA机构用于申请证书。
jxc.pem:CA机构颁发给你的正式证书,包含了你的公钥和CA的签名,是公开的身份凭证。
③ 生成kubeconfig
- 创建kubeconfig生成脚本
shell
vim rbac-kubeconfig.sh
bash
#!/bin/bash
APISERVER=192.168.100.13 # 必须替换为实际API Server IP
kube_user=jxc # 替换为🗺的kube用户
kube_namespace=yjs1023 # 替换为实际的命名空间
# 设置集群参数
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="$kube_user".kubeconfig
# 设置客户端认证参数
kubectl config set-credentials "$kube_user" \
--client-key=/etc/kubernetes/pki/"$kube_user"-key.pem \
--client-certificate=/etc/kubernetes/pki/"$kube_user".pem \
--embed-certs=true \
--kubeconfig="$kube_user".kubeconfig
# 设置上下文参数
kubectl config set-context kubernetes \
--cluster=kubernetes \
--user="$kube_user" \
--namespace="$kube_namespace" \
--kubeconfig="$kube_user".kubeconfig
# 使用上下文参数生成 .kubeconfig 文件
kubectl config use-context kubernetes --kubeconfig="$kube_user".kubeconfig
设置集群参数、客户端认证参数和上下文
- 生成实际kubeconfig
shell
chmod +x rbac-kubeconfig.sh
./rbac-kubeconfig.sh
生成jxc.kubeconfig文件
1.3_权限配置
① 创建命名空间与应用配置
- 创建测试命名空间
shell
kubectl create namespace yjs1023
- 分发kubeconfig到用户目录
shell
mkdir -p /home/jxc/.kube
cp jxc.kubeconfig /home/jxc/.kube/config
chown -R jxc:jxc /home/jxc/.kube/
使jxc用户能使用此配置文件
② 创建RBAC规则
- 创建rbac.yaml权限配置文件
shell
vim rbac.yaml
yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: yjs1023
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: yjs1023
subjects:
- kind: User
name: jxc
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
定义jxc在yjs1023命名空间的权限:
- get/watch/list/create Pod
- 应用RBAC配置
shell
kubectl apply -f rbac.yaml
kubectl get role,rolebinding -n yjs1023
ini
NAME CREATED AT
role.rbac.authorization.k8s.io/pod-reader 2026-01-21T14:28:54Z
NAME ROLE AGE
rolebinding.rbac.authorization.k8s.io/read-pods Role/pod-reader 28s
1.4_权限验证
① 验证jxc各项权限
- 切换用户并创建测试Pod
shell
su - jxc
cat > role-rolebinding-test.yaml <<'YAML'
apiVersion: v1
kind: Pod
metadata:
name: role-rolebinding-test
spec:
containers:
- name: nginx
image: nginx
YAML
kubectl create -f role-rolebinding-test.yaml
kubectl get pods -o wide
预期输出:role-rolebinding-test成功创建并运行
- 测试跨命名空间访问
shell
kubectl get pods -n default
ini
Error from server (Forbidden): pods is forbidden: User "jxc" cannot list resource "pods" in API group "" in the namespace "default"
访问其他命名空间失败,权限受限
- 测试其他资源访问
shell
kubectl get svc
ini
Error from server (Forbidden): services is forbidden: User "jxc" cannot list resource "services" in API group "" in the namespace "yjs1023"
无权限查看Service资源
② 管理员视角验证
- root用户查看资源
shell
# root@k8s-master
kubectl get pods --all-namespaces -o wide
ini
NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
yjs1023 role-rolebinding-test 1/1 Running 0 5m2s 10.244.1.17 k8s-node01 <none> <none>
确认RoleBinding已生效
- 查看所有角色和绑定
shell
kubectl get role,rolebinding -n yjs1023
③ 可选:授予管理员权限
- 授予用户特定命名空间管理员权限
shell
kubectl create rolebinding jxc-admin-binding \
--clusterrole=admin \
--user=jxc \
--namespace=yjs1023
将集群admin角色绑定到用户,但限制在yjs1023命名空间
结语
如果想要有让一个pod 或者 Serivce secert configmap等 /普通用户 具有 接入 k8s =集群相关资源的操作权限
1、创建serviceaccount 或者 用户
2、做认证 token/证书认证
① serviceaccount 会自动 生成Serivceaccount token 的 secret 资源
② 用户需要创建证书,使用cfssl等工具通过CA证书和私钥文件 生成 证书和 私钥文件, 使用CA证书和私钥文件来去创建kubeconfig配置文件, 把kubeconfig配置文件导入用户的家目录中 目录名.kube/config文件中
3、做RBAC鉴权 Role|clusterRole 创建角色赋予给资源的操作权限(**resources**、verbs) Rolebinding|cluster Rolebinding 把主体(用户|组|服务账号)和角色进行绑定
此时切换用户后pod 或者用户具有相关的命名空间的中对相关子资源有了操作权限
API Server安全:Kubernetes通过认证、鉴权和准入控制三道防线保护API Server;6443端口是安全访问的关键门户。
RBAC架构:基于Role/ClusterRole定义权限,通过RoleBinding/ClusterRoleBinding进行绑定;实现命名空间级精细权限控制。
安全最佳实践:最小权限原则,通过SA管理Pod访问权限;RBAC结合NetworkPolicy实现纵深防御。
!question\] 请问Kubernetes安全体系的三个环节分别是什么? 认证(确认身份)、鉴权(确认权限)、准入控制(请求验证), 请求必须经过这三道关卡才能被API Server处理 \[!question\] 为什么说RBAC是生产环境的推荐选择? RBAC支持运行时调整权限,无需重启API Server;通过标准API资源管理;支持命名空间级和集群级权限控制 \[!question\] ServiceAccount自动产生哪些内容? 自动挂载三个文件到容器:token(认证令牌)、ca.crt(API Server根证书)、namespace(命名空间信息) \[!question\] 如何限制用户只能在特定命名空间操作? 通过Role+RoleBinding组合:Role定义命名空间内权限,RoleBinding将角色绑定到特定用户 \[!question\] AlwaysAllow和AlwaysDeny策略适用于什么场景? AlwaysAllow用于无安全要求或测试场景;AlwaysDeny用于安全测试,模拟拒绝所有请求环境