详细介绍:K8s 安全机制全解析
2.7 Secret 与 ServiceAccount 的关系
3.4 绑定角色权限(RoleBinding / ClusterRoleBinding)
Step 4:创建 Role 与 RoleBinding(命名空间级权限)
如果 kubectl 返回 connection refused 或 The connection to the server localhost:8080 was refused:
额外补充:用 ServiceAccount 做应用访问(更常见的场景)
一、前言
在 Kubernetes(以下简称 K8s)集群中,安全机制是核心基础设施之一。 API Server 是整个系统的“中枢大脑”,所有控制与资源操作都要经过它。
因此,K8s 的安全体系可以理解为一套完整的“守门系统”,主要包括三层安全防线:
Authentication(认证):你是谁?
Authorization(鉴权):你能做什么?
Admission Control(准入控制):是否允许执行?
二、Authentication(认证机制)
在 K8s 集群中,任何访问 API Server 的请求都需要首先通过认证环节。 这一步确认请求者的身份是否可信。
2.1 支持的认证方式
| 类型 | 说明 | 安全等级 |
|---|---|---|
| HTTP Basic Auth | 使用 用户名:密码(Base64 编码)放入 HTTP Header | 低 |
| HTTP Token Auth | 通过 Header 携带 Token 进行认证(由 API Server 校验) | 中 |
| HTTPS 证书认证 | 采用双向 TLS 认证,基于 CA 根证书签发 | ✅ 高(推荐) |
HTTPS 证书认证是生产环境最安全、最标准的方式,可实现双向信任。
2.2 哪些访问需要认证
集群组件访问:如
kubectl、kubelet、kube-proxy。Pod 内访问:如
coredns、dashboard这类运行在 Pod 中的系统组件。
2.3 通信端口与安全性
| 组件 | 通信端口 | 是否加密 |
|---|---|---|
kube-apiserver | 6443 | ✅ HTTPS(双向认证) |
controller-manager、scheduler | 8080 | ⚠️ HTTP(非加密) |
kubectl、kubelet | 6443 | ✅ HTTPS |
2.4 证书的颁发方式
Kubernetes 提供两种方式生成证书:
手动签发:在二进制部署环境中手动生成并签发 CA 与客户端证书。
自动签发:当 kubelet 第一次加入集群时,用 bootstrap token 认证,Controller Manager 会自动为其颁发证书。
2.5 kubeconfig 文件结构
K8s 的认证核心文件是 ~/.kube/config,它包含三个部分:
| 部分 | 含义 |
|---|---|
| cluster | 集群信息(API Server 地址、CA 证书等) |
| user | 用户凭据(客户端证书与私钥) |
| context | 上下文绑定(集群 + 用户 + 命名空间) |
一个 kubeconfig 可以同时包含多个上下文,实现多集群管理。
2.6 ServiceAccount(服务账户)
ServiceAccount(简称 SA) 是专为 Pod 内应用访问 API Server 设计的身份机制。
每个命名空间默认存在一个 default SA,当创建 Pod 时系统会自动挂载认证信息:
/var/run/secrets/kubernetes.io/serviceaccount/
├── ca.crt # 集群 CA 根证书
├── namespace # 当前命名空间
└── token # JWT 签名的访问令牌
Pod 内程序通过这个 token 与 API Server 通信,实现安全认证。 这也是为什么 Pod 内可以直接使用 kubectl 或 API 客户端访问集群的原因。
2.7 Secret 与 ServiceAccount 的关系
K8s 中的 Secret 用于存储敏感信息。与 SA 相关的 Secret 主要有两类:
| 类型 | 说明 |
|---|---|
| service-account-token | 系统自动生成,用于认证 |
| Opaque | 用户自定义的密钥内容 |
每个 SA 会自动关联一个 service-account-token 类型的 Secret,其中包含:
token(由 API Server 私钥签名的 Token,用于服务端认证来访主体)ca.crt(CA 根证书,供客户端验证 API Server 的证书)namespace(该 service-account-token 的命名空间作用域)
三、Authorization(鉴权机制)
认证通过后,K8s 需要确定用户能做什么,即权限控制阶段。 这部分由 --authorization-mode 参数控制。
3.1 常见授权模式对比
| 模式 | 描述 | 特点 |
|---|---|---|
| AlwaysDeny | 拒绝所有请求 | 测试用 |
| AlwaysAllow | 允许所有请求 | 不安全 |
| ABAC(Attribute-Based) | 基于属性文件的静态规则授权 | 需重启 API Server |
| Webhook | 调用外部 REST 服务判断权限 | 灵活但复杂 |
| ✅ RBAC(Role-Based Access Control) | 基于角色的权限控制 | 官方推荐,动态可调 |
3.2 RBAC 四大核心对象
| 对象 | 级别 | 功能 |
|---|---|---|
| Role | 命名空间级 | 定义局部权限 |
| ClusterRole | 集群级 | 定义全局权限 |
| RoleBinding | 命名空间级 | 将角色绑定到用户/SA |
| ClusterRoleBinding | 集群级 | 全局绑定角色 |
⚙️ 注意:
使用 RoleBinding 绑定 ClusterRole 时仍仅作用于当前命名空间;
使用 ClusterRoleBinding 则可全局生效。
3.3 角色(Role/ClusterRole)示例
权限仅能累加(白名单),不存在“先有很多再减少”的黑名单模型。
Role 只能定义在 某个命名空间 内;跨命名空间请使用 ClusterRole。
Role 示例(只读访问 default 命名空间的 Pods):
apiVersion: rbac.authorization.k8s.io/v1 #指定 core API 组和版本
kind: Role #指定类型为 Role
metadata:
namespace: default #使用默认命名空间
name: pod-reader #Role 的名称
rules: #定义规则
- apiGroups: [""] #""表示 apiGroups 和 apiVersion 使用相同的 core API 组,即 rbac.authorization.k8s.io
resources: ["pods"] #资源对象为 Pod 类型
verbs: ["get", "watch", "list"] #被授予的操作权限
#以上配置的意义是,如果把 pod-reader 这个 Role 赋予给一个用户,那么这个用户将在 default 命名空间中具有对 Pod 资源对象 进行 get(获取)、watch(监听)、list(列出)这三个操作权限。
ClusterRole 示例(读取所有命名空间的 Secrets):
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# "namespace" 被忽略,因为 ClusterRoles 不受名字空间限制
name: secret-reader
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "watch", "list"]
3.4 绑定角色权限(RoleBinding / ClusterRoleBinding)
RoleBinding:在命名空间内将 Role/ClusterRole 赋予 User/Group/ServiceAccount。
ClusterRoleBinding:在全集群范围将 ClusterRole 赋予 User/Group/ServiceAccount。
(1)RoleBinding 示例(在 default 内授予用户 cy 读取 Pods 的 Role)
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
- kind: User
name: cy
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
#将 default 命名空间的 pod-reader Role 授予 cy 用户,此后 cy 用户在 default 命名空间中将具有 pod-reader 的权限
---------------------------------------------------------------
#示例2,在 `kube-public` 内给用户 `qh` 引用 ClusterRole `secret-reader`
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-secrets
namespace: kube-public
subjects:
- kind: User
name: qh
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
#以上 RoleBinding 引用了一个 ClusterRole,这个 ClusterRole 具有整个集群内对 secrets 的访问权限;但是其授权用户 qh 只能访问 kube-public 空间中的 secrets(因为 RoleBinding 定义在 kube-public 命名空间)

(2)ClusterRoleBinding 示例
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: read-secrets-global
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
什么是 Subject(主体)
在 RBAC 的世界里,Subject 表示“谁将被授予权限”。Subject 有三类:
User:外部或系统用户(通常是证书 CN、外部身份提供者中的用户名)。Group:用户组(便于把权限授予一组用户)。ServiceAccount:Kubernetes 内部的服务账户(用于 Pod 内部进程访问 API Server)。
示例(RoleBinding 中的 subjects):
subjects:
- kind: User
name: alice
apiGroup: rbac.authorization.k8s.io
- kind: Group
name: dev-team
apiGroup: rbac.authorization.k8s.io
- kind: ServiceAccount
name: myapp
namespace: app-namespace
注意:
ServiceAccount需要namespace字段(如果跨命名空间引用 SA,必须写明)。User/Group的名字按照认证系统决定(证书的CN、OIDC 的sub/preferred_username等)。system:前缀为系统保留,如system:masters是集群管理员组,普通用户勿滥用。
JWT 在 Kubernetes 中的角色
Kubernetes 使用 JWT(JSON Web Token)作为一种常见的 token 格式 —— 尤其体现在 ServiceAccount 的 token(早期是长期有效的 secret token,现代推荐用短期绑定 token / TokenRequest)。
1) JWT 的结构(3 部分)
JWT = header.payload.signature(都使用 base64url 编码):
header:算法(如
alg: RS256)和类型typ: JWT。payload(声明 claims):包含
iss(issuer)、sub(subject)、aud(audience)、exp(过期时间)、iat(签发时间)、以及 k8s 自定义字段(例如kubernetes.io/serviceaccount/namespace、kubernetes.io/serviceaccount/secret.name等)。signature:由签名密钥对 header+payload 计算得到,保证不可篡改。
2) 常见 claim(k8s 环境)
iss:token 的颁发者(例如kubernetes/serviceaccount或 API Server)。sub:主体(如system:serviceaccount:namespace:name)。aud:受众(token 能被哪些服务器接受,如kubernetes.default.svc.cluster.local)。exp:过期时间(UNIX 时间)。k8s 特有:
kubernetes.io/serviceaccount/namespace,kubernetes.io/serviceaccount/secret.name,kubernetes.io/serviceaccount/service-account.name等。常见 verbs / resources / apiGroups 速查
verbs:
get、list、watch、create、update、patch、delete、execresources(示例):
services、endpoints、pods、secrets、configmaps、crontabs、deployments、jobs、nodes、rolebindings、clusterroles、daemonsets、replicasets、statefulsets、horizontalpodautoscalers、replicationcontrollers、cronjobsapiGroups:
""(core)、apps、autoscaling、batch
3.6 子资源(Subresources)
有些资源有子资源,例如获取 Pod 日志:
GET /api/v1/namespaces/{namespace}/pods/{name}/log
RBAC 可对其精确控制:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: default
name: pod-and-pod-logs-reader
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list"]
四、Admission Control(准入控制)
通过认证与鉴权后,请求仍需经过 Admission Controller 检查。 它是一系列插件链,用于验证、修改或拒绝请求。
常见 Admission 插件
| 插件 | 功能 |
|---|---|
| NamespaceLifecycle | 管理命名空间生命周期 |
| LimitRanger | 控制资源限制 |
| ServiceAccount | 自动为 Pod 注入 SA |
| ResourceQuota | 命名空间配额管理 |
| NodeRestriction | 限制 Node 的注册与权限 |
| Mutating/ValidatingWebhook | 动态策略验证(如 OPA/Gatekeeper) |
五、实践案例:创建受限用户(命名空间级别权限)
目标:创建一个名为 ciallo 的用户,仅能在 yozusoft 命名空间管理 Pods。
Step 0:创建系统用户
useradd ciallo
passwd ciallo
# 切换为该用户尝试访问
su - ciallo
kubectl get pods
# The connection to the server localhost:8080 was refused - did you specify the right host or port?

Step 1:生成用户 CSR 与证书
ciallo-csr.json(注意 CN 将作为 k8s User 名称,names[].O 会作为 Group):
# 下载最新版本(根据需要可去 GitHub 查看最新版本)
wget https://github.com/cloudflare/cfssl/releases/download/v1.6.5/cfssl_1.6.5_linux_amd64
wget https://github.com/cloudflare/cfssl/releases/download/v1.6.5/cfssljson_1.6.5_linux_amd64
# 添加执行权限
chmod +x cfssl_1.6.5_linux_amd64 cfssljson_1.6.5_linux_amd64
# 移动到 /usr/local/bin
sudo mv cfssl_1.6.5_linux_amd64 /usr/local/bin/cfssl
sudo mv cfssljson_1.6.5_linux_amd64 /usr/local/bin/cfssljson
mkdir -p /opt/ciallo && cd /opt/ciallo
------------------------------------------------------------
vim user-cert.sh
#######################
cat > ciallo-csr.json <

Step 2:生成 kubeconfig
借助 kubectl config 创建专属 kubeconfig(示例脚本):
cd /opt/ciallo
vim rbac-kubeconfig.sh
APISERVER=$1
# 设置集群参数
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=ciallo.kubeconfig
# 设置客户端认证参数
kubectl config set-credentials ciallo \
--client-key=/etc/kubernetes/pki/ciallo-key.pem \
--client-certificate=/etc/kubernetes/pki/ciallo.pem \
--embed-certs=true \
--kubeconfig=ciallo.kubeconfig
# 设置上下文参数
kubectl config set-context kubernetes \
--cluster=kubernetes \
--user=ciallo \
--namespace=yozusoft \
--kubeconfig=ciallo.kubeconfig
# 使用上下文参数生成 ciallo.kubeconfig 文件
kubectl config use-context kubernetes --kubeconfig=ciallo.kubeconfig


Step 3:创建命名空间与 kubeconfig 上下文
kubectl create namespace yozusoft
chmod +x rbac-kubeconfig.sh
./rbac-kubeconfig.sh 192.168.10.10
# 分发 kubeconfig
mkdir -p /home/ciallo/.kube
cp ciallo.kubeconfig /home/ciallo/.kube/config
chown -R ciallo:ciallo /home/ciallo/.kube/
# 查看 kubeconfig
cat ciallo.kubeconfig
Step 4:创建 Role 与 RoleBinding(命名空间级权限)
rbac.yaml:
vim rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: yozusoft
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: yozusoft
subjects:
- kind: User
name: ciallo
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
应用:
kubectl apply -f rbac.yaml
kubectl get role,rolebinding -n yozusoft
# role.rbac.authorization.k8s.io/pod-reader 32s
# rolebinding.rbac.authorization.k8s.io/read-pods 32s

Step 5:验证(切换到 ciallo 用户执行操作)
su - ciallo
# 创建 Pod(允许)
cat > pod-test.yaml <<'YAML'
apiVersion: v1
kind: Pod
metadata:
name: pod-test
spec:
containers:
- name: nginx
image: nginx
YAML
kubectl create -f pod-test.yaml
kubectl get pods -o wide
# NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
# pod-test 1/1 Running 0 114s 10.244.2.2 node02
# 访问 svc(拒绝)
kubectl get svc
# Error from server (Forbidden): services is forbidden: User "ciallo" cannot list resource "services" in API group "" in the namespace "kgc"
# 访问 default 命名空间(拒绝)
kubectl get pods -n default
# Error from server (Forbidden): pods is forbidden: User "ciallo" cannot list resource "pods" in API group "" in the namespace "default"


Step 6:管理员侧检查(确认 RBAC 生效)
# root 用户查看:
kubectl get pods --all-namespaces -o wide
# NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE
# yozusoft pod-test 1/1 Running 0 107s 10.244.2.2 node01
# ...
# 可见 RoleBinding 生效:用户仅能管理指定命名空间资源。

可选:授予命名空间管理员(如果需要)
kubectl create rolebinding ciallo-admin-binding \
--clusterrole=admin \
--user=ciallo \
--namespace=yozusoft
撤销 / 收回访问(重要)
1. 删除 RoleBinding / Role
kubectl delete rolebinding read-pods -n yozusoft
kubectl delete role pod-reader -n yozusoft
2. 撤销用户证书(若用证书认证)
证书撤销在 k8s 中通常不是单条 API;常见做法:
从发布方(CA)撤销证书并更新信任链(更换 CA 或更新 CRL),或
在 API Server 端配置认证 webhook 去校验白名单(例如把该证书列入拒绝名单)。 若只是要阻止一个 kubeconfig,删除或收回 kubeconfig 是立即有效的(用户客户端失去凭证)。
3. 删除 kubeconfig(分发到用户机器上)
rm -rf /home/ciallo/.kube/config
审计与排错建议
查看拒绝原因(管理侧)
启用并查看 API Server 审计日志(若已开启 audit policy):
审计日志会显示 user, verb, resource, namespace, responseStatus,便于定位被拒绝请求的主体与原因。
常见排错命令
查看用户信息(以 admin 身份):
kubectl auth can-i create pods --as=ciallo -n yozusoft
kubectl auth can-i list services --as=ciallo -n yozusoft
在集群上以 target user 模拟权限检查:
kubectl auth can-i get pods --as=ciallo -n yozusoft
如果 kubectl 返回 connection refused 或 The connection to the server localhost:8080 was refused:
检查 kubeconfig server 地址是否正确(kubectl config view)。
检查 API Server 是否运行并监听 6443,防火墙规则是否允许访问。
额外补充:用 ServiceAccount 做应用访问(更常见的场景)
如果目标是给应用(而不是人)授权,推荐使用 ServiceAccount 而非给 Pod 注入用户 kubeconfig:
创建 SA、Role、RoleBinding:
kubectl create sa myapp -n yozusoft
# Role (pod-reader) 与 RoleBinding 绑定到 ServiceAccount
kubectl apply -f - <
Pod 使用 serviceAccountName: myapp,并建议使用 TokenRequest / projected short-lived tokens,而不是长-lived Secrets。
六、总结(Summary)
安全层级 功能 关键组件 认证(Authentication) 验证用户身份 Token / Cert / SA 鉴权(Authorization) 权限控制 RBAC / Webhook 准入控制(Admission) 最终验证与策略控制 Admission Plugins
✅ 安全最佳实践建议:
使用 TLS 双向认证 确保通信安全;
启用 RBAC 实现最小权限原则;
配合 Admission Webhook 做策略审查;
为每个微服务/用户单独创建 ServiceAccount 或 kubeconfig;
搭配 NetworkPolicy / WAF / 限速 加强集群防御。
浙公网安备 33010602011771号