mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
2367 字
7 分钟
Kubernetes 安全:RBAC、Pod 安全与网络策略
2021-12-04

Kubernetes 的安全模型遵循纵深防御原则,从 API 访问控制到 Pod 运行时隔离,从网络策略到密钥管理,每一层都有独立的安全机制。即使某一层被突破,其他层仍然提供保护。

本章从 RBAC 权限模型出发,逐步深入 ServiceAccount 身份管理、Pod 安全标准、容器安全上下文、网络隔离和密钥管理,构建完整的 Kubernetes 安全知识体系。

一、Kubernetes 安全模型概览#

flowchart TB subgraph L1["第一层:API 访问控制"] AUTH["认证 Authentication<br/>你是谁?"] RBAC["RBAC Authorization<br/>你能做什么?"] ADM["准入控制 Admission<br/>这样做合规吗?"] end subgraph L2["第二层:Pod 运行时安全"] PSA["Pod Security Admission<br/>安全标准检查"] SC["SecurityContext<br/>容器权限限制"] end subgraph L3["第三层:网络隔离"] NP["NetworkPolicy<br/>Pod 间流量控制"] ING["Ingress TLS<br/>外部流量加密"] end subgraph L4["第四层:密钥管理"] ETCD["etcd 加密<br/>静态数据保护"] ESO["External Secrets<br/>外部密钥管理"] end L1 --> L2 --> L3 --> L4 style L1 fill:#e3f2fd,stroke:#1565c0 style L2 fill:#e8f5e9,stroke:#2e7d32 style L3 fill:#fff3e0,stroke:#e65100 style L4 fill:#f3e5f5,stroke:#6a1b9a

二、RBAC:基于角色的访问控制#

RBAC 是 Kubernetes 的核心授权机制,控制”谁可以对什么资源做什么操作”。

2.1 RBAC 四个核心对象#

graph TB SA["Subject<br/>用户/组/ServiceAccount"] -->|"绑定"| RB["RoleBinding<br/>Namespace 级别"] SA -->|"绑定"| CRB["ClusterRoleBinding<br/>集群级别"] RB --> R["Role<br/>Namespace 内权限"] RB --> CR["ClusterRole<br/>集群范围权限"] CRB --> CR style SA fill:#e3f2fd,stroke:#1565c0 style R fill:#c8e6c9,stroke:#2e7d32 style CR fill:#fff3e0,stroke:#e65100
对象作用范围说明
RoleNamespace定义 Namespace 内的权限规则
ClusterRole集群定义集群范围的权限规则
RoleBindingNamespace将 Subject 绑定到 Role/ClusterRole(Namespace 内生效)
ClusterRoleBinding集群将 Subject 绑定到 ClusterRole(集群范围生效)

2.2 Role 与 ClusterRole#

Role:Namespace 内的权限

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: production
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create"] # 允许 exec 进入容器
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["get", "list"]
resourceNames: ["nginx"] # 限制为特定资源名

ClusterRole:集群范围的权限

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: node-reader
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["namespaces"]
verbs: ["get", "list"]

2.3 RoleBinding 与 ClusterRoleBinding#

RoleBinding:将用户绑定到 Role(Namespace 内生效)

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: jane-pod-reader
namespace: production
subjects:
- kind: User
name: jane
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io

ClusterRoleBinding:将用户绑定到 ClusterRole(集群范围生效)

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-binding
subjects:
- kind: User
name: admin
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io

2.4 常见权限模式#

场景RoleBinding说明
开发者查看 PodRole (pod-reader)RoleBinding只能查看指定 Namespace 的 Pod
CI/CD 部署应用Role (deployer)RoleBinding可以管理 Deployment/Service
集群只读用户ClusterRole (view)ClusterRoleBinding可以查看所有 Namespace 的资源
集群管理员ClusterRole (cluster-admin)ClusterRoleBinding完全控制

2.5 RBAC 排查#

# 检查用户是否有权限执行操作
kubectl auth can-i get pods --as=jane -n production
kubectl auth can-i delete deployments --as=jane -n production
# 检查 ServiceAccount 的权限
kubectl auth can-i list secrets --as=system:serviceaccount:default:my-sa
# 查看 RoleBinding 详情
kubectl describe rolebinding jane-pod-reader -n production
# 查看 ClusterRole 的规则
kubectl describe clusterrole cluster-admin

三、ServiceAccount:Pod 的身份#

每个 Pod 都有一个 ServiceAccount,用于与 API Server 通信。ServiceAccount 是 RBAC 的 Subject 之一。

3.1 默认 ServiceAccount#

每个 Namespace 自动创建一个 default ServiceAccount:

kubectl get sa -n production
# NAME SECRETS AGE
# default 0 30d

Pod 未指定 ServiceAccount 时,自动使用 default

3.2 创建专用 ServiceAccount#

apiVersion: v1
kind: ServiceAccount
metadata:
name: api-reader
namespace: production
automountServiceAccountToken: true # 自动挂载 API Token
# Pod 使用专用 ServiceAccount
spec:
serviceAccountName: api-reader
containers:
- name: my-app
image: my-app:v1

3.3 Token 挂载机制#

较新版本(1.21+,需启用 ServiceAccountTokenProjection 特性门)可使用 TokenRequest API 生成短期 JWT Token,投影挂载到 Pod:

/var/run/secrets/kubernetes.io/serviceaccount

ca.crtAPI Server CA 证书

namespacePod 所在 Namespace

token短期 JWT Token(默认 1 小时有效期)

Token 自动轮换,kubelet 在 Token 过期前自动向 API Server 请求新 Token,Pod 无感知。

Note

本文的版本基线是 Kubernetes 1.21/1.22(2021 年底)。此时 ServiceAccount 仍会自动创建长期 Secret Token,TokenRequest API 已在 1.21 升级为默认启用,可生成短期 Token 作为更安全的替代。1.24 起,ServiceAccount 不再自动生成永久 Secret Token,长期 Token 只能手动创建 kubernetes.io/service-account-token 类型的 Secret 获取。如需显式创建长期 Token(如 CI/CD 场景),可手动创建该类型的 Secret。

四、Pod 安全标准与 Pod Security Admission#

Pod 安全标准定义了三种安全级别,Pod Security Admission 在 Namespace 级别强制执行。

4.1 三种安全级别#

级别说明典型限制
Privileged不受限制,完全特权允许特权容器、hostPath、hostNetwork
Baseline最小限制,阻止已知提权禁止特权容器、hostPID/hostIPC、新增能力
Restricted严格限制,安全最佳实践禁止所有特权、必须以非 root 运行、禁止新增能力

4.2 配置 Pod Security Admission#

apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
pod-security.kubernetes.io/enforce: restricted # 强制执行
pod-security.kubernetes.io/audit: restricted # 审计日志
pod-security.kubernetes.io/warn: restricted # 警告提示
pod-security.kubernetes.io/enforce-version: v1.21 # 使用 v1.21 版本标准
模式说明
enforce违反标准的 Pod 被拒绝创建
audit违反标准的 Pod 允许创建,但记录审计事件
warn违反标准的 Pod 允许创建,但 kubectl 输出警告

4.3 Restricted 级别的 Pod 配置#

下面这份配置同时落实了非 root 运行、能力裁剪和默认 seccomp,是 Restricted 级别的典型落地形态。seccompProfile 的 RuntimeDefault 表示使用容器运行时(containerd/CRI-O)内置的默认 seccomp 配置,它屏蔽了 cloneptracemount 等高危系统调用。

apiVersion: v1
kind: Pod
metadata:
name: secure-app
spec:
securityContext:
runAsNonRoot: true # 必须以非 root 运行
runAsUser: 1000
fsGroup: 2000
seccompProfile:
type: RuntimeDefault # 使用运行时默认 seccomp 配置(1.22 GA,1.19 起需手动开启特性门)
containers:
- name: app
image: my-app:v1
securityContext:
allowPrivilegeEscalation: false # 禁止提权
readOnlyRootFilesystem: true # 只读根文件系统
capabilities:
drop: ["ALL"] # 删除所有 Linux 能力
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {} # 临时目录用于写入
Important

默认 seccomp 并非一直存在。Kubernetes 1.19 之前,Pod 默认不带 seccompProfile,容器以容器运行时的原始默认(往往是不限制或仅容器运行时自带策略)运行。1.19 引入 RuntimeDefault,但需手动开启特性门;直到 1.22 才 GA 默认可用。这意味着历史集群上未显式声明 seccompProfile 的 Pod 并未受到这层保护,迁移老应用时要补上。

五、SecurityContext:容器安全上下文#

SecurityContext 定义 Pod 和容器的安全配置,控制容器的权限和隔离级别。

5.1 Pod 级别 vs 容器级别#

配置Pod 级别容器级别说明
runAsUser可(覆盖 Pod 级别)运行容器的 UID
runAsGroup运行容器的 GID
fsGroupVolume 的 GID
runAsNonRoot是否禁止 root 运行
seccompProfileseccomp 配置
capabilitiesLinux 能力管理
privileged是否为特权容器
readOnlyRootFilesystem根文件系统是否只读
allowPrivilegeEscalation是否允许提权(setuid)

5.2 Linux Capabilities#

Linux 将 root 权限拆分为细粒度的能力(Capabilities)。Kubernetes 允许精确控制容器拥有的能力:

securityContext:
capabilities:
add: ["NET_BIND_SERVICE"] # 允许绑定 1024 以下端口
drop: ["ALL"] # 删除所有其他能力
常见能力说明风险等级
NET_BIND_SERVICE绑定 1024 以下端口
CHOWN修改文件所有者
NET_RAW使用原始套接字(ping 等)
SYS_ADMIN系统管理操作
SYS_PTRACE追踪进程
Warning

privileged: true 等同于拥有所有 Linux 能力,容器几乎可以访问宿主机的所有设备,实际绕过了 Namespace 和大部分 cgroup 隔离。仅在系统组件(如 CNI 插件、CSI 插件)中使用。

容器安全没有”绝对安全”。即使按 Restricted 配置裁剪了能力和 seccomp,容器与宿主仍共享同一个 Linux 内核,内核漏洞(如 Dirty Pipe、Dirty COW)就是宿主逃逸的攻击面。几条常被忽视的逃逸路径:/dev/shm 默认挂载在容器与宿主之间不共享 IPC Namespace 时仍可能成为副作用通道;hostPath 卷把宿主目录塞进容器,等于把宿主文件系统暴露给容器内进程;特权容器内的 mknod/ptrace 能直接操作宿主设备。所以 Pod Security Admission 的 Restricted 级别同时禁止了 hostPath、hostPID、hostIPC 和特权容器,这不是洁癖,是堵具体的逃逸路径。要真正隔离,得用 Kata Containers 这类基于轻量虚拟机的运行时,或开启 User Namespace 让容器内的 root 映射成宿主的非特权 UID(1.25 起逐步稳定)。

六、NetworkPolicy:网络隔离#

NetworkPolicy 在 L3/L4 层控制 Pod 间的网络流量。未配置任何策略时,所有 Pod 可以互相通信;但只要 Namespace 中存在一条匹配某 Pod 的 NetworkPolicy,该 Pod 的流量就立刻切换到白名单模式,只允许显式声明的流量。这种”一旦有策略就收紧”的语义,让分阶段推行隔离的团队容易踩坑:你给了一个应用加策略,本意是只影响它,结果它和未加策略的 Pod 之间流量也变了行为。

6.1 默认拒绝所有入站#

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
namespace: production
spec:
podSelector: {} # 空选择器 = Namespace 内所有 Pod
policyTypes:
- Ingress # 拒绝所有入站

6.2 分层网络策略#

graph TB subgraph 前端层["Frontend<br/>app=web"] WEB["Pod: web"] end subgraph API层["API<br/>app=api"] API["Pod: api"] end subgraph 数据层["Data<br/>app=mysql"] DB["Pod: mysql"] end WEB -->|"允许 :80"| API API -->|"允许 :3306"| DB OTHER["其他 Pod"] -->|"拒绝"| API OTHER2["其他 Pod"] -->|"拒绝"| DB style 前端层 fill:#e3f2fd,stroke:#1565c0 style API层 fill:#e8f5e9,stroke:#2e7d32 style 数据层 fill:#fff3e0,stroke:#e65100
# API 层策略:只允许 Frontend 访问
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-policy
namespace: production
spec:
podSelector:
matchLabels:
app: api
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: web
ports:
- port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: mysql
ports:
- port: 3306
- to: # 允许 DNS 解析
- namespaceSelector: {}
ports:
- port: 53
protocol: UDP

6.3 跨 Namespace 策略#

# 允许 monitoring Namespace 的 Pod 访问 metrics
ingress:
- from:
- namespaceSelector:
matchLabels:
name: monitoring
podSelector:
matchLabels:
app: prometheus
ports:
- port: 9090
Note

namespaceSelectorpodSelector 在同一个 from 列表项中是 AND 关系,必须同时满足。不同列表项之间是 OR 关系。

七、Secret 加密与外部密钥管理#

7.1 etcd 静态加密#

默认情况下,Secret 在 etcd 中以 Base64 明文存储。启用加密后,Secret 写入 etcd 前会被加密:

# EncryptionConfiguration
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-32-byte-key>
- identity: {} # 回退到明文(用于读取未加密的旧数据)
# 配置 API Server 使用加密配置
kube-apiserver --encryption-provider-config=/etc/kubernetes/encryption-config.yaml

7.2 External Secrets Operator#

将密钥管理委托给外部系统(如 HashiCorp Vault、AWS Secrets Manager),通过 External Secrets Operator 同步到 Kubernetes Secret:

# ExternalSecret 示例
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-credentials
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-backend
kind: ClusterSecretStore
target:
name: db-credentials # 同步创建的 Kubernetes Secret 名称
data:
- secretKey: password # Kubernetes Secret 中的键
remoteRef:
key: secret/data/db # Vault 中的路径
property: password # Vault 中的字段

7.3 Sealed Secrets#

Sealed Secrets 允许将加密的 Secret 安全地提交到 Git:

# 安装 kubeseal CLI
kubeseal --format yaml < secret.yaml > sealed-secret.yaml
# sealed-secret.yaml 可以安全提交到 Git
# 集群中的 Sealed Secrets Controller 解密并创建真正的 Secret
kubectl apply -f sealed-secret.yaml

八、安全最佳实践清单#

维度最佳实践优先级
RBAC最小权限原则,避免使用 cluster-admin
RBAC定期审计 RoleBinding/ClusterRoleBinding
ServiceAccount为每个应用创建专用 SA,不使用 default
Pod 安全Namespace 设置 restricted 安全标准
Pod 安全容器以非 root 运行,删除所有能力
Pod 安全根文件系统设为只读
网络隔离Namespace 设置默认拒绝 NetworkPolicy
网络隔离分层网络策略,只允许必要的流量
密钥管理启用 etcd 静态加密
密钥管理使用 External Secrets 对接 Vault
密钥管理不将 Secret YAML 提交到 Git
镜像安全使用最小基础镜像(distroless/alpine)
镜像安全定期扫描镜像漏洞(Trivy/Grype)
审计启用 API Server 审计日志

总结#

把四层防御的核心机制拎出来对照,安全原则在各层之间是一致的:尽量收紧默认行为,让”能做”的边界逼近”必须做”的边界。

安全层核心机制关键原则
API 访问控制认证 + RBAC + 准入控制最小权限
Pod 运行时安全Pod Security Admission + SecurityContext纵深防御
网络隔离NetworkPolicy一旦配置即收紧
密钥管理etcd 加密 + External Secrets不信任静态存储

K8s 安全的核心挑战是默认配置过于宽松:ServiceAccount 自动挂载 token 让每个 Pod 都能调用 API Server、Pod 默认无 securityContext 可以以 root 运行、未配置策略时所有 Pod 默认互通。加固的第一步不是添加安全工具,而是收紧这些默认行为,设置 automountServiceAccountToken: false、enforce Pod Security Standards、给 Namespace 加 default-deny NetworkPolicy。

支持与分享

如果这篇文章对你有帮助,欢迎支持作者或分享给更多人

Kubernetes 安全:RBAC、Pod 安全与网络策略
https://blog.souloss.cn/posts/kubernetes/k8s-rbac-security/
作者
Souloss
发布于
2021-12-04
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

相关文章 智能推荐
1
Kubernetes 服务发现与网络基础
云原生 深入 Kubernetes 服务发现与网络,Service 四种类型详解、Endpoints 与 EndpointSlice、Ingress 与 Ingress Controller、集群 DNS 服务发现、kube-proxy 的 iptables 与 IPVS 模式、NetworkPolicy 网络隔离,理解流量从客户端到 Pod 的路由机制。
2
Kubernetes 网络
云原生 全面讲解 Kubernetes 网络体系,Pod 网络(CNI)、Service 网络(kube-proxy / iptables / ipvs)、Ingress 流量入口,以及 Flannel、Calico、Cilium 三大 CNI 插件的对比。
3
Kubernetes 核心概念:Pod、Node 与控制面
云原生 深入 Kubernetes 核心概念,从控制面组件(API Server、etcd、Scheduler、Controller Manager)到工作节点组件(kubelet、kube-proxy),再到 Pod、Node、Namespace、Label 与 Selector 的设计哲学,理解声明式 API 与控制器模式的协作机制。
4
Kubernetes 配置与存储:ConfigMap、Secret 与 PV/PVC
云原生 深入 Kubernetes 配置与存储体系,ConfigMap 配置管理、Secret 敏感信息、Volume 存储卷、PV/PVC 持久化存储、StorageClass 动态供给,理解配置与代码分离的设计哲学和存储的完整生命周期。
5
Kubernetes 工作负载:从 Pod 到 Deployment
云原生 深入 Kubernetes 工作负载体系,Pod 生命周期与探针、ReplicaSet 副本管理、Deployment 滚动更新与回滚、StatefulSet 有状态应用、DaemonSet 节点守护、Job/CronJob 批处理、HPA 自动扩缩容,理解每种工作负载的设计意图与适用场景。