云原生安全

返回 云原生

云原生安全遵循 Zero Trust(零信任) 原则:默认不信任任何请求,无论来自内部还是外部,每次访问都需要验证。

安全分层

┌─────────────────────────────────────────────┐
│  外部安全:WAF、DDoS、CDN                    │
├─────────────────────────────────────────────┤
│  传输安全:TLS、mTLS                         │
├─────────────────────────────────────────────┤
│  身份安全:RBAC、OIDC、ServiceAccount        │
├─────────────────────────────────────────────┤
│  网络安全:NetworkPolicy、Service Mesh       │
├─────────────────────────────────────────────┤
│  运行时安全:Falco、Seccomp、AppArmor        │
├─────────────────────────────────────────────┤
│  供应链安全:镜像扫描、SBOM、签名验证         │
└─────────────────────────────────────────────┘

Zero Trust 模型

传统安全:“内网是可信的” Zero Trust:“永不信任,持续验证”

传统:
  外部 → 防火墙 → 内网(自由通行)

Zero Trust:
  外部 → 验证 → 服务 A
                  │ 访问服务 B
                  ▼ 再次验证(mTLS + RBAC)
               服务 B

四要素:

  1. 验证所有用户:不因为在内网就免验证
  2. 验证所有设备:设备需注册、合规
  3. 最小权限:每个服务只能访问自己需要的资源
  4. 持续监控:假设已被攻破,实时检测异常

mTLS(双向 TLS)

Service Mesh(Istio)自动为服务间通信启用 mTLS:

服务 A                         服务 B
  │                               │
  │ 1. 发起连接                   │
  │──────────────────────────────►│
  │                               │
  │ 2. 服务 B 发送证书             │
  │◄──────────────────────────────│
  │ 3. 服务 A 验证 B 的证书        │
  │                               │
  │ 4. 服务 A 发送自己的证书       │
  │──────────────────────────────►│
  │ 5. 服务 B 验证 A 的证书        │
  │                               │
  │ 6. 双向验证通过,加密通信      │

证书由 Istio Citadel 自动颁发和轮换,无需手动管理。

K8s RBAC

Role-Based Access Control,控制谁能对 K8s 资源做什么操作:

ServiceAccount(身份)
      │ 绑定
      ▼
RoleBinding / ClusterRoleBinding
      │ 关联
      ▼
Role / ClusterRole(权限规则)
      │ 定义
      ▼
Resources + Verbs(如:pods / get,list,watch)

最小权限原则示例:

# order-service 只能读取自己命名空间的 ConfigMap
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: order-service-role
  namespace: prod
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  verbs: ["get", "list"]

Secret 管理

K8s Secret 默认只是 Base64 编码,不是加密。生产环境需要专门的 Secret 管理工具。

HashiCorp Vault

应用启动
   │
   ▼
向 Vault 请求 Secret(携带 K8s ServiceAccount Token)
   │
   ▼
Vault 验证身份(K8s Auth Method)
   │
   ▼
返回动态 Secret(短期有效,自动轮换)
   │
   ▼
应用使用 Secret,过期后重新申请

动态 Secret 优势: 数据库密码每次申请都不同,即使泄露也很快失效。

云厂商 KMS

工具特点
AWS Secrets Manager自动轮换,与 EKS 深度集成
阿里云 KMS国内合规,密钥硬件保护
HashiCorp Vault多云通用,开源
SealedSecretGitOps 友好,加密后存 Git

SealedSecret(GitOps 场景)

Secret(明文)
   │ kubeseal 加密
   ▼
SealedSecret(密文,可安全存 Git)
   │ 推送到 Git
   ▼
ArgoCD 部署到 K8s
   │ Controller 解密
   ▼
普通 Secret(集群内使用)

镜像安全(供应链安全)

代码提交
   │
CI 构建镜像
   │
   ▼
Trivy / Snyk 扫描
   ├── OS 包漏洞(CVE 数据库)
   ├── 依赖漏洞(npm / Maven / pip)
   ├── Dockerfile 最佳实践检查
   └── 敏感信息扫描(hardcoded secrets)
   │
   ▼
镜像签名(Cosign)
   │
   ▼
推送到 Registry
   │
   ▼
K8s 准入控制(Kyverno / OPA)验证签名

Dockerfile 安全实践:

# ✅ 使用非 root 用户
FROM eclipse-temurin:21-jre
RUN useradd -m appuser
USER appuser
 
# ✅ 使用最小基础镜像(distroless)
FROM gcr.io/distroless/java21
 
# ❌ 避免 root 运行
# USER root

运行时安全

Falco(异常行为检测)

Pod 运行时
   │ 系统调用监控(eBPF / 内核模块)
   ▼
Falco 规则引擎
   │ 匹配规则:容器内执行 shell、读取 /etc/passwd...
   ▼
   ├── 告警到 Slack / SIEM
   └── 自动响应(杀掉 Pod)

典型检测规则:

  • 容器内执行 bash / sh
  • 读取 /etc/shadow/proc/1/environ
  • 向外网发起异常连接
  • 挂载宿主机敏感目录

K8s 准入控制

kubectl apply
   │
   ▼
kube-apiserver
   │
   ▼
Admission Webhook(Kyverno / OPA Gatekeeper)
   │
   ├── 验证(Validate):不符合策略 → 拒绝
   └── 变更(Mutate):自动注入 Sidecar、修改配置

Kyverno 策略示例(禁止 latest 镜像):

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: disallow-latest-tag
spec:
  rules:
  - name: require-image-tag
    match:
      resources:
        kinds: [Pod]
    validate:
      message: "镜像必须指定具体版本号,不允许使用 latest"
      pattern:
        spec:
          containers:
          - image: "!*:latest"

NetworkPolicy(网络隔离)

# 只允许 order-service 访问 payment-service
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: payment-network-policy
  namespace: prod
spec:
  podSelector:
    matchLabels:
      app: payment-service
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: order-service
    ports:
    - port: 8080

默认拒绝所有,只开放必要端口,实现最小网络权限。