Skip to main content

云原生应用安全加固指南

·836 words·2 mins

概述
#

云原生应用安全是运维工作的重中之重,本文全面讲解安全加固措施。

容器安全
#

镜像安全
#

最小化镜像
#

# 不好的示例 - 使用完整基础镜像
FROM ubuntu:latest
RUN apt-get update && apt-get install -y curl wget vim
COPY . /app
CMD ["./app"]

# 好的示例 - 使用 alpine 镜像
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp

FROM alpine:latest
RUN apk add --no-cache ca-certificates
WORKDIR /app
COPY --from=builder /app/myapp .
USER nobody
CMD ["./myapp"]

镜像扫描
#

# 使用 Trivy 扫描镜像
docker run --rm -v /var/run/docker.sock:/var/run/docker.sock \
  aquasec/trivy:latest myapp:latest

# 使用 Snyk
snyk container test myapp:latest

# 集成到 CI/CD
trivy image --severity HIGH,CRITICAL myapp:latest && exit 1

安全配置
#

# pod-security-context.yaml
apiVersion: v1
kind: Pod
metadata:
  name: secure-pod
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    runAsGroup: 3000
    fsGroup: 2000
  containers:
  - name: app
    image: myapp:latest
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop:
          - ALL
    resources:
      limits:
        memory: "256Mi"
        cpu: "500m"
      requests:
        memory: "128Mi"
        cpu: "250m"

Kubernetes 安全
#

RBAC 配置
#

# role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

# rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: ServiceAccount
  name: my-app-sa
  namespace: default
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

NetworkPolicy
#

# network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: default
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress

# 允许特定流量
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-web-traffic
  namespace: default
spec:
  podSelector:
    matchLabels:
      app: web
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: frontend
    ports:
    - protocol: TCP
      port: 80

Pod Security Policy (已废弃)
#

使用 Pod Security Admission (PSA):

# namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: secure-namespace
  labels:
    pod-security.kubernetes.io/enforce: baseline
    pod-security.kubernetes.io/enforce-version: latest
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/warn: restricted

Secrets 管理
#

# 使用 sealed-secrets
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  name: db-credentials
  namespace: default
spec:
  encryptedData:
    username: AgBy...ifrg
    password: AgB...xyz
---

apiVersion: v1
kind: Secret
metadata:
  name: db-credentials
  namespace: default
type: Opaque

Helm 安全
#

# values.yaml
securityContext:
  enabled: true
  runAsNonRoot: true
  readOnlyRootFilesystem: true

podSecurityPolicy:
  enabled: true

secrets:
  useSecretStore: true  # 使用外部 secret 管理

证书管理
#

TLS 配置
#

# tls-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: tls-secret
  namespace: default
type: kubernetes.io/tls
data:
  tls.crt: LS0tLS1CRU...LR.SUCCESS
  tls.key: LS0tLS1CRU...L0tLS0t
---

# ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: tls-ingress
spec:
  tls:
  - hosts:
    - example.com
    secretName: tls-secret
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web
            port:
              number: 80

Let’s Encrypt 集成
#

# cert-manager.yaml
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    email: admin@example.com
    server: https://acme-v02.api.letsencrypt.org/directory
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
    - http01:
        ingress:
          class: nginx
---

# certificate.yaml
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: example-com
  namespace: default
spec:
  secretName: example-com-tls
  dnsNames:
  - example.com
  - www.example.com
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer

网络安全
#

Service Mesh
#

# istio-sidecar-injection.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: prod
  labels:
    istio-injection: enabled

mTLS 配置
#

#DestinationRule
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: enable-mtls
  namespace: default
spec:
  host: "*.default.svc.cluster.local"
  trafficPolicy:
    tls:
      mode: ISTIO_MUTUAL

审计日志
#

# audit-policy.yaml
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
- level: RequestResponse
  resources:
  - group: ""
    resources: ["secrets", "configmaps"]
  verbs: ["get", "list", "watch"]

- level: Metadata
  resources:
  - group: ""
    resources: ["pods"]

- level: Request
  resources:
  - group: ""
    resources: ["pods/log"]

安全扫描
#

静态分析
#

# kubesec 扫描
kubesec scan deployment.yaml

# kube-bench 检查
docker run --rm -i docker.io/aquasec/kube-bench:latest

运行时安全
#

# Falco 规则
- rule: Launch Privileged Container
  desc: Detect the initial process of a privileged container
  condition: container and privileged and seamonkey_spawn_process
  output: Privileged container launched (user=%user.name %container.info)
  priority: WARNING
  tags: [container, priv_esc, mitre_privilege_escalation]

最佳实践
#

1. 镜像管理
#

  • 使用最小化基础镜像
  • 定期扫描镜像漏洞
  • 不在镜像中硬编码密钥
  • 使用多阶段构建

2. 权限控制
#

  • RBAC 最小权限原则
  • 禁止特权容器
  • 只读文件系统

3. 网络隔离
#

  • NetworkPolicy 限制流量
  • 使用 Service Mesh
  • 启用 mTLS

4. 监控告警
#

  • 集成审计日志
  • 实时告警配置
  • 安全扫描自动化

总结
#

云原生安全需要纵深防御,从镜像到运行时全方位保护。