mobile wallpaper 1mobile wallpaper 2mobile wallpaper 3mobile wallpaper 4
1611 字
5 分钟
Kubernetes 安全:RBAC、Pod 安全与网络策略
2024-01-26

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 挂载机制#

Kubernetes 1.24+ 使用 TokenRequest API 生成短期 JWT Token,自动挂载到 Pod:

/var/run/secrets/kubernetes.io/serviceaccount/
├── ca.crt # API Server CA 证书
├── namespace # Pod 所在 Namespace
└── token # 短期 JWT Token(默认 1 小时有效期)

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

Note

Kubernetes 1.24 之前,ServiceAccount 自动创建长期 Secret Token。1.24+ 不再自动创建,改用 TokenRequest API 生成短期 Token。如果需要长期 Token(如 CI/CD 场景),需要手动创建 Secret 类型为 kubernetes.io/service-account-token

四、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.29 # 使用 v1.29 版本标准
模式说明
enforce违反标准的 Pod 被拒绝创建
audit违反标准的 Pod 允许创建,但记录审计事件
warn违反标准的 Pod 允许创建,但 kubectl 输出警告

4.3 Restricted 级别的 Pod 配置#

apiVersion: v1
kind: Pod
metadata:
name: secure-app
spec:
securityContext:
runAsNonRoot: true # 必须以非 root 运行
runAsUser: 1000
fsGroup: 2000
seccompProfile:
type: RuntimeDefault # 使用默认 seccomp 配置
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: {} # 临时目录用于写入

五、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 能力,容器几乎可以访问宿主机的所有设备。仅在系统组件(如 CNI 插件、CSI 插件)中使用。

六、NetworkPolicy:网络隔离#

NetworkPolicy 在 L3/L4 层控制 Pod 间的网络流量。默认情况下,所有 Pod 可以互相通信——NetworkPolicy 实现白名单机制,只允许显式声明的流量。

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不信任静态存储

安全不是一次性配置,而是持续的过程。定期审计 RBAC 权限、更新安全标准、扫描镜像漏洞、审查 NetworkPolicy,才能保持集群的安全态势。

支持与分享

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

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

部分信息可能已经过时