Kubernetes安全加固
约 1551 字大约 5 分钟
kubernetessecurity
2025-08-18
概述
Kubernetes 集群的安全性涉及多个层面:从集群基础设施到工作负载运行时。一个未经加固的 K8s 集群可能导致容器逃逸、权限提升、数据泄露等严重安全事件。本文将系统介绍 Kubernetes 安全加固的关键领域。
Kubernetes 安全层次
Pod Security Standards
Kubernetes 1.25+ 内置了 Pod Security Admission,替代了已废弃的 PodSecurityPolicy。
三个安全级别
# Namespace 级别应用 Pod Security Standards
apiVersion: v1
kind: Namespace
metadata:
name: production
labels:
# Restricted: 最严格,遵循当前 Pod 加固最佳实践
pod-security.kubernetes.io/enforce: restricted
pod-security.kubernetes.io/enforce-version: latest
# 警告模式(不阻止,仅警告)
pod-security.kubernetes.io/warn: restricted
# 审计模式(记录到审计日志)
pod-security.kubernetes.io/audit: restrictedRestricted 级别的安全 Pod 配置
apiVersion: v1
kind: Pod
metadata:
name: secure-app
spec:
securityContext:
runAsNonRoot: true # 禁止以 root 运行
seccompProfile:
type: RuntimeDefault # 启用 seccomp
containers:
- name: app
image: myapp:v1.2.3@sha256:abc123... # 使用摘要固定镜像
securityContext:
allowPrivilegeEscalation: false # 禁止权限提升
readOnlyRootFilesystem: true # 只读根文件系统
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 1000
capabilities:
drop:
- ALL # 丢弃所有 Linux capabilities
seccompProfile:
type: RuntimeDefault
resources:
limits:
cpu: "500m"
memory: "256Mi"
requests:
cpu: "100m"
memory: "128Mi"
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir: {} # 可写临时目录
automountServiceAccountToken: false # 不自动挂载 SA TokenNetwork Policy
# 默认拒绝所有入站和出站流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: production
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
---
# 仅允许特定流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-frontend-to-backend
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
- namespaceSelector:
matchLabels:
name: production
ports:
- protocol: TCP
port: 8080
---
# 限制出站:只允许访问特定服务和 DNS
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: backend-egress
namespace: production
spec:
podSelector:
matchLabels:
app: backend
policyTypes:
- Egress
egress:
- to:
- podSelector:
matchLabels:
app: database
ports:
- protocol: TCP
port: 5432
- to: # 允许 DNS 解析
- namespaceSelector: {}
podSelector:
matchLabels:
k8s-app: kube-dns
ports:
- protocol: UDP
port: 53RBAC 最小权限
# 只读权限 Role
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: ["configmaps"]
verbs: ["get", "list"]
---
# 绑定到 ServiceAccount
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: app-pod-reader
namespace: production
subjects:
- kind: ServiceAccount
name: app-sa
namespace: production
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.io
---
# 应用使用的 ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: app-sa
namespace: production
automountServiceAccountToken: false # 默认不挂载 tokenRBAC 审计
# 检查过度权限
# 查找 ClusterRoleBinding 绑定到 cluster-admin
kubectl get clusterrolebindings -o json | \
jq '.items[] | select(.roleRef.name == "cluster-admin") | .metadata.name'
# 检查是否有使用通配符的 Role
kubectl get roles,clusterroles -A -o json | \
jq '.items[] | select(.rules[]?.resources[]? == "*" or .rules[]?.verbs[]? == "*") | .metadata.name'
# 使用 rakkess 查看实际权限
kubectl access-matrix --sa production:app-sa -n productionSecrets 加密
# 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: {} # fallback: 不加密(用于读取旧数据)# 推荐:使用 External Secrets Operator 集成外部密钥管理
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: app-secrets
namespace: production
spec:
refreshInterval: 1h
secretStoreRef:
name: vault-backend
kind: ClusterSecretStore
target:
name: app-secrets
data:
- secretKey: database-url
remoteRef:
key: production/database
property: connection_string
- secretKey: api-key
remoteRef:
key: production/api
property: keyAdmission Controller
Kyverno 策略引擎
# 强制要求镜像来自可信仓库
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: restrict-image-registries
spec:
validationFailureAction: Enforce
rules:
- name: validate-registries
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Images must be from approved registries"
pattern:
spec:
containers:
- image: "registry.example.com/*"
---
# 强制要求资源限制
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-resource-limits
spec:
validationFailureAction: Enforce
rules:
- name: check-limits
match:
any:
- resources:
kinds:
- Pod
validate:
message: "CPU and memory limits are required"
pattern:
spec:
containers:
- resources:
limits:
memory: "?*"
cpu: "?*"镜像安全扫描
# 使用 Trivy 扫描容器镜像漏洞
trivy image myapp:v1.2.3
# 只显示高危和严重漏洞
trivy image --severity HIGH,CRITICAL myapp:v1.2.3
# CI/CD 中设置阈值
trivy image --exit-code 1 --severity CRITICAL myapp:v1.2.3# Kyverno: 集成镜像签名验证 (Cosign/Sigstore)
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: verify-image-signature
spec:
validationFailureAction: Enforce
rules:
- name: verify-cosign
match:
any:
- resources:
kinds:
- Pod
verifyImages:
- imageReferences:
- "registry.example.com/*"
attestors:
- entries:
- keyless:
issuer: "https://token.actions.githubusercontent.com"
subject: "https://github.com/myorg/*"运行时安全
# Falco 规则:检测容器内异常行为
- rule: Terminal shell in container
desc: Detect shell opened in container
condition: >
spawned_process and container
and shell_procs
and proc.tty != 0
output: >
Shell opened in container
(user=%user.name container=%container.name
shell=%proc.name parent=%proc.pname)
priority: WARNING
tags: [container, shell, mitre_execution]
- rule: Read sensitive file in container
desc: Detect read of sensitive files
condition: >
open_read and container
and sensitive_files
output: >
Sensitive file read in container
(file=%fd.name container=%container.name)
priority: WARNINGCIS Benchmark 检查
# 使用 kube-bench 运行 CIS Kubernetes Benchmark
docker run --pid=host -v /etc:/etc:ro -v /var:/var:ro \
aquasec/kube-bench:latest run --targets master
# 检查项示例
# [PASS] 1.1.1 Ensure API server pod spec file permissions are 644
# [FAIL] 1.2.6 Ensure --kubelet-certificate-authority is set
# [WARN] 1.2.10 Ensure admission control plugin AlwaysPullImages is set安全加固清单
最佳实践
- 启用 Pod Security Standards (Restricted),所有生产 namespace 强制执行
- 默认拒绝网络流量,使用 NetworkPolicy 精确控制 Pod 间通信
- 最小权限 RBAC,避免使用 cluster-admin,定期审计权限
- 镜像安全:使用摘要固定镜像版本,扫描漏洞,验证签名
- 加密 etcd 中的 Secrets,或使用外部密钥管理系统
- 禁止自动挂载 ServiceAccount Token,仅在需要时显式挂载
- 部署 Admission Controller(Kyverno/OPA)强制执行安全策略
- 启用审计日志和运行时监控(Falco),及时发现异常行为
贡献者
更新日志
2026/3/14 13:09
查看所有更新日志
9f6c2-feat: organize wiki content and refresh site setup于