Kubernetes 安全配置:RBAC、Pod 安全与网络策略
yaml apiVersion: v1 kind: Namespace metadata: name: dev
apiVersion: v1 kind: ServiceAccount metadata: name: dev-reader namespace: dev
**2. 定义只读 Role**
```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: pod-reader
namespace: dev
rules:
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list", "watch"]
3. 绑定角色到 ServiceAccount
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods-binding
namespace: dev
subjects:
- kind: ServiceAccount
name: dev-reader
namespace: dev
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
此后,在 dev 命名空间中使用该 ServiceAccount 运行的 Pod 即可安全地查询 Pod 信息,无法执行任何修改操作。
RBAC 最佳实践
- 优先使用
ServiceAccount而非直接分发 kubeconfig 用户凭证。 - 为每个应用组件创建独立的 ServiceAccount,避免共用。
- 禁止使用
*通配符动词,明确列出所需操作。 - 定期审计
ClusterRoleBinding,移除不必要的高权限绑定。 - 利用工具(如
kubectl auth can-i)验证实际权限效果。
Pod 安全
Pod 安全机制限制容器运行时的权限,防止容器逃逸、宿主机资源访问等风险。
Pod 安全标准
Kubernetes 定义了三个内置安全级别:
- Privileged:无任何限制,允许特权容器、挂载宿主机路径等。仅用于系统级服务。
- Baseline:阻止已知的提权行为,如容器运行于
hostNetwork、挂载敏感宿主机目录,同时允许部分特权操作。适用于大多数应用。 - Restricted:严格遵循安全最佳实践,强制非 root 运行、只读根文件系统、禁止特权提升等。推荐用于所有非系统工作负载。
使用 Pod Security Admission (PSA) 实施策略
从 v1.25 起,PSA 取代旧的 PodSecurityPolicy,以命名空间标签进行控制。
# 为 dev 命名空间强制实施 Restricted 标准,违反准入则拒绝
kubectl label namespace dev pod-security.kubernetes.io/enforce=restricted
# 同时开启审计和告警模式,便于观测违规请求
kubectl label namespace dev pod-security.kubernetes.io/audit=restricted
kubectl label namespace dev pod-security.kubernetes.io/warn=restricted
标签组合 enforce、audit 和 warn 可渐进式推行。先使用 audit 和 warn 收集违规信息,再启用 enforce 硬阻断。
SecurityContext:精确控制容器安全
即使不使用全局 PSA,也可在 Pod/容器级别通过 securityContext 设置安全参数。
核心字段示例:
apiVersion: v1
kind: Pod
metadata:
name: secure-app
spec:
securityContext:
runAsNonRoot: true # 必须以非 root 用户运行
seccompProfile:
type: RuntimeDefault # 使用容器运行时的默认 seccomp 规则
containers:
- name: app
image: nginx:alpine
securityContext:
allowPrivilegeEscalation: false # 禁止权限提升
capabilities:
drop: ["ALL"] # 移除所有 Linux capabilities
add: ["NET_BIND_SERVICE"] # 仅添加必要的能力
readOnlyRootFilesystem: true # 根文件系统只读
runAsUser: 1000
runAsGroup: 3000
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {}
关键字段解释:
runAsNonRoot: true要求容器用户非 UID 0,防止获取宿主机 root 权限。capabilities.drop: ["ALL"]剥夺全部默认能力,再逐一添加必需能力。readOnlyRootFilesystem: true避免容器内部文件篡改,需要写入的目录需挂载卷。allowPrivilegeEscalation: false禁止通过 suid 二进制提升权限。
Pod 安全最佳实践
- 生产环境统一采用
Restricted标准。 - 所有容器镜像指定非 root 用户,或通过 Dockerfile
USER指令控制。 - 避免使用
privileged容器,除非明确需要(如网络插件)。 - 启用
RuntimeDefaultseccomp 和 AppArmor/SELinux 可选安全模块。 - 定期扫描镜像漏洞,并确保基础镜像最小化。
网络策略
网络策略类似于为 Pod 组配置的防火墙规则,控制入站(Ingress)和出站(Egress)流量。Kubernetes 默认未隔离 Pod 间通信,需显式创建策略。
前提条件
集群必须安装支持网络策略的网络插件,如 Calico、Cilium、Weave Net 等。Flannel 在不使用 Calico 网络策略引擎时不支持。
工作模型
网络策略通过标签选择器指定目标 Pod,并基于规则限制流量流向。
- Ingress 规则:定义哪些源可以访问目标 Pod。
- Egress 规则:定义目标 Pod 可以访问哪些外部资源。
实战:实现命名空间级隔离
场景:frontend 命名空间的 Pod 只能接受来自同一命名空间的请求,并只允许访问后端 API 的 backend 服务。
1. 默认拒绝所有入口流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: deny-all-ingress
namespace: frontend
spec:
podSelector: {} # 选择所有 Pod
policyTypes:
- Ingress
ingress: [] # 空规则拒绝所有入口流量
这一步骤确保没有预想的 Pod 不被暴露。
2. 允许来自同命名空间的请求
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-same-namespace
namespace: frontend
spec:
podSelector: {}
ingress:
- from:
- podSelector: {} # 允许同一命名空间内任何 Pod
3. 控制 Egress:只允许访问特定后端
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-backend-egress
namespace: frontend
spec:
podSelector:
matchLabels:
role: web # 仅对具有 role=web 的 Pod 生效
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
name: backend # 仅允许连接到具有标签 name=backend 的命名空间
podSelector:
matchLabels:
role: api # 且 Pod 标签为 role=api
ports:
- protocol: TCP
port: 8080
4. 允许 DNS 解析
集群 DNS 服务通常位于 kube-system 命名空间,需额外放行 UDP 53 端口,否则 Pod 无法解析服务名称。
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns-egress
namespace: frontend
spec:
podSelector: {}
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
ports:
- protocol: UDP
port: 53