← 返回首页
🔧

容器安全:Docker和Kubernetes安全

📂 devops ⏱ 3 min 545 words

容器安全:Docker和Kubernetes安全

容器安全架构

容器安全层次:
  ├── 镜像安全: 扫描和验证镜像
  ├── 运行时安全: 容器运行时保护
  ├── 网络安全: 网络策略和隔离
  ├── 存储安全: 数据加密和访问控制
  └── 编排安全: Kubernetes安全配置

镜像安全

镜像扫描

# 使用Trivy扫描镜像
trivy image nginx:latest
trivy image --severity HIGH,CRITICAL nginx:latest

# 扫描本地镜像
trivy image -f json -o results.json myapp:latest

# 扫描并修复
trivy image --fix --remove myapp:latest

安全基础镜像

# 使用最小化基础镜像
FROM alpine:3.18

# 添加非root用户
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

# 设置文件权限
COPY --chown=appuser:appgroup app /app

# 切换到非root用户
USER appuser

# 运行应用
CMD ["/app/server"]

镜像签名验证

# 使用cosign签名镜像
cosign sign --key cosign.key myregistry/myapp:latest

# 验证签名
cosign verify --key cosign.pub myregistry/myapp:latest

# 在Kubernetes中验证
apiVersion: v1
kind: Pod
metadata:
  name: verified-app
spec:
  containers:
    - name: app
      image: myregistry/myapp:latest
  imagePullSecrets:
    - name: registry-credentials

运行时安全

Seccomp配置

{
  "defaultAction": "SCMP_ACT_ERRNO",
  "defaultErrnoRet": 1,
  "architectures": ["SCMP_ARCH_X86_64"],
  "syscalls": [
    {
      "names": [
        "accept", "access", "arch_prctl", "bind", "brk",
        "clone", "close", "connect", "dup", "epoll_create1",
        "epoll_ctl", "epoll_wait", "execve", "exit",
        "exit_group", "fcntl", "fstat", "futex",
        "getdents64", "getpid", "getsockname", "getsockopt",
        "ioctl", "listen", "mmap", "mprotect",
        "nanosleep", "newfstatat", "openat", "pipe",
        "poll", "prlimit64", "read", "recvfrom",
        "rt_sigaction", "rt_sigprocmask", "sendto",
        "set_robust_list", "set_tid_address", "setsockopt",
        "socket", "stat", "statfs", "write", "writev"
      ],
      "action": "SCMP_ACT_ALLOW"
    }
  ]
}

AppArmor配置

# /etc/apparmor.d/docker-nginx
#include <tunables/global>

profile docker-nginx flags=(attach_disconnected,mediate_deleted) {
  #include <abstractions/base>

  network inet tcp,
  network inet udp,

  deny /proc/sys/[^f]** w,
  deny /sys/[^f]** w,

  /app/** r,
  /app/server ix,

  /tmp/** rw,
  /var/log/nginx/** rw,
}

Kubernetes安全

Pod安全策略

# pod-security-policy.yaml
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: restricted
  annotations:
    seccomp.security.alpha.kubernetes.io/allowedProfiles: 'runtime/default'
    apparmor.security.alpha.kubernetes.io/allowedProfiles: 'runtime/default'
spec:
  privileged: false
  allowPrivilegeEscalation: false
  requiredDropCapabilities:
    - ALL
  volumes:
    - 'configMap'
    - 'emptyDir'
    - 'projected'
    - 'secret'
    - 'downwardAPI'
    - 'persistentVolumeClaim'
  hostNetwork: false
  hostIPC: false
  hostPID: false
  runAsUser:
    rule: 'MustRunAsNonRoot'
  seLinux:
    rule: 'RunAsAny'
  supplementalGroups:
    rule: 'MustRunAs'
    ranges:
      - min: 1
        max: 65535
  fsGroup:
    rule: 'RunAsAny'

RBAC配置

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

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: production
subjects:
  - kind: ServiceAccount
    name: default
    namespace: production
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

网络策略

# network-policy.yaml
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
      ports:
        - protocol: TCP
          port: 8080

密钥管理

Kubernetes Secrets加密

# encrypted-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: app-secret
  namespace: production
type: Opaque
data:
  username: YWRtaW4=  # base64 encoded
  password: cGFzc3dvcmQ=

使用外部密钥管理

# external-secrets.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: app-secret
  namespace: production
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secrets-manager
    kind: ClusterSecretStore
  target:
    name: app-secret
  data:
    - secretKey: username
      remoteRef:
        key: prod/app/credentials
        property: username
    - secretKey: password
      remoteRef:
        key: prod/app/credentials
        property: password

安全扫描

自动化安全扫描

# github-actions-security.yaml
name: Security Scan

on: [push, pull_request]

jobs:
  security-scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      
      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'myapp:${{ github.sha }}'
          format: 'sarif'
          output: 'trivy-results.sarif'
          severity: 'CRITICAL,HIGH'
      
      - name: Run Snyk security scan
        uses: snyk/actions/docker@master
        env:
          SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
        with:
          args: '--severity-threshold=high'

监控和审计

# falco-rules.yaml
- rule: Detect outbound connections to C2 servers
  desc: Detect connections to known command and control servers
  condition: >
    outbound and
    fd.sip.name in c2_servers
  output: >
    Outbound connection to C2 server
    (user=%user.name command=%proc.cmdline connection=%fd.name)
  priority: CRITICAL
  tags: [network, c2]

- rule: Container Drift Detected
  desc: Detect new executable created in running container
  condition: >
    evt.type = execve and
    container and
    proc.name != sysdig and
    not proc.name in (known_binaries)
  output: >
    Drift detected in container
    (user=%user.name container=%container.name command=%proc.cmdline)
  priority: WARNING

最佳实践

  1. 最小化基础镜像: 使用Alpine等最小化镜像
  2. 非root运行: 容器使用非root用户运行
  3. 只读文件系统: 设置只读根文件系统
  4. 资源限制: 设置CPU和内存限制
  5. 网络策略: 实施网络隔离策略
  6. 定期扫描: 定期扫描镜像和运行时漏洞