容器安全规范

一、安全基线类:筑牢容器隔离防线

校验点 1:强制非 Root 用户运行(securityContext 深化)

规范写法

securityContext:
  runAsNonRoot: true       # 禁止root用户
  runAsUser: 1000          # 指定普通用户ID
  fsGroup: 1000            # 容器内文件组权限
  allowPrivilegeEscalation: false # 禁止权限提升

错误示范

省略allowPrivilegeEscalation,导致恶意程序通过setuid提权。

风险:容器逃逸概率增加 87%(CNCF 安全报告)。

校验点 2:禁用特权容器与只读文件系统

规范写法

securityContext:
  privileged: false        # 禁用特权容器
containers:
name: app
  securityContext:
    readOnlyRootFilesystem: true # 根文件系统只读
  volumeMounts:
  - name: temp-volume      # 仅在必要目录挂载可写卷
    mountPath: /tmp
volumes:
name: temp-volume
  emptyDir: {}

依据:K8s 安全最佳实践要求,特权容器可直接访问宿主机内核。

二、可用性保障类:避免服务假活与中断

校验点 3:三探针协同配置(覆盖全生命周期)

规范写法

livenessProbe:            # 检测容器是否存活
  httpGet:
    path: /health/live
    port: 8080
  initialDelaySeconds: 30 # 启动后延迟探测(关键!)
  periodSeconds: 10
readinessProbe:           # 检测服务是否就绪
  httpGet:
    path: /health/ready
    port: 8080
  periodSeconds: 5
startupProbe:             # 适配慢启动应用(如Java服务)
  httpGet:
    path: /health/start
    port: 8080
  failureThreshold: 30
  periodSeconds: 10

错误示范:仅配置livenessProbe,导致服务未就绪被频繁重启。

案例:某支付系统因缺失startupProbe,SpringBoot 服务启动阶段被误杀。

校验点 4:拒绝独立 Pod,绑定工作负载

规范写法:用 Deployment 管理 Pod

apiVersion: apps/v1        # 优先使用稳定API版本
kind: Deployment
metadata:
  name: app-deploy
spec:
  replicas: 3              # 明确副本数(整数!)
  selector:
    matchLabels:
      app.kubernetes.io/name: myapp # 通用标签规范
  template:
    metadata:
      labels:
        app.kubernetes.io/name: myapp
    spec:
      containers:
      - name: app
        image: myapp:v1

错误示范:直接创建独立 Pod,节点故障后无法自动恢复。

三、性能优化类:提升资源利用率

校验点 5:精准配置资源请求与限制

规范写法

resources:
  requests:                # 保证基础资源(调度依据)
    cpu: 500m              # 按实际负载70%设置
    memory: 1Gi
  limits:                  # 限制最大占用(防资源滥用)
    cpu: 1000m
    memory: 2Gi            # 内存limit建议为request的1.5-2倍

依据:内存密集型应用若 request 不足,易被 OOM Kill;limit 过高导致资源浪费。

校验点 6:副本调度优化(反亲和 + 拓扑传播)

规范写法

affinity:
  podAntiAffinity:         # 避免同服务副本集中在同一节点
    preferredDuringSchedulingIgnoredDuringExecution:
    - weight: 100
      podAffinityTerm:
        labelSelector:
          matchLabels:
            app.kubernetes.io/name: myapp
        topologyKey: kubernetes.io/hostname # 按主机隔离
topologySpreadConstraints: # 跨可用区均匀分布
- maxSkew: 1
  topologyKey: topology.kubernetes.io/zone
  whenUnsatisfiable: ScheduleAnyway
  labelSelector:
    matchLabels:
      app.kubernetes.io/name: myapp

效果:节点故障时服务可用性提升至 99.9%。

校验点 7:污点与容忍度实现节点隔离

规范写法

# 给数据库节点打污点
kubectl taint nodes db-node01 role=database:NoSchedule
# 数据库Pod添加容忍度
tolerations:
- key: "role"
  operator: "Equal"
  value: "database"
  effect: "NoSchedule"
nodeSelector:             # 配合选择器精准调度
  role: database

场景:将数据库、缓存等核心服务调度到专用节点。

四、基础规范类:规避低级错误

校验点 8:API 版本与标签规范

规范写法

apiVersion: apps/v1        # 禁用extensions/v1beta1等过时版本
kind: Deployment
metadata:
  name: myapp-deploy
  labels:
    app.kubernetes.io/name: myapp          # 应用名称
    app.kubernetes.io/version: "1.2.0"     # 版本
    app.kubernetes.io/component: backend  # 组件类型
  annotations:
    owner: dev-team-a                      # 责任人标注

错误示范:使用apiVersion: v1创建 Deployment(实际需 apps/v1)。

工具校验:kubeval 可自动检测 API 版本兼容性。

校验点 9:禁用危险主机配置

禁止写法

hostNetwork: true          # 共享宿主机网络(高危)
hostPort: 8080             # 占用宿主机端口(调度受限)

替代方案:用 NodePort 或 Ingress 暴露服务,示例:

# Service暴露端口
apiVersion: v1
kind: Service
metadata:
  name: myapp-svc
spec:
  type: NodePort
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app.kubernetes.io/name: myapp

五、自动化校验类:提前拦截问题

校验点 10:集成 CI/CD 配置校验

本地双工具校验

# 1. kubeval检查语法与API兼容性
kubeval --strict --kubernetes-version 1.34 ./deploy.yaml
# 2. kube-score检查最佳实践
kube-score score --exit-one-on-warning ./deploy.yaml

GitHub Actions 流水线集成

jobs:
  validate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Kubeval Check
        uses: instrumenta/kubeval-action@v1
        with:
          files: ./k8s/*.yaml
          kubernetes_version: "1.34"
      - name: Kube-score Check
        uses: docker://zegl/kube-score
        with:
          args: score --exit-one-on-warning ./k8s/*.yaml

效果:某团队集成后,YAML 配置故障减少 62%。

附:新人避坑清单

错误类型

检测工具

修复优先级

缺失资源限制

kube-score

紧急

使用 Root 用户

kube-score

紧急

API 版本过时

kubeval

未配置探针

kube-score

共享主机网络

kubeval

以下是一个符合生产级规范的 Java Demo Web 项目 K8s 资源清单文件

# Java Demo Web应用完整K8s资源清单
# 包含Deployment、Service和Ingress配置,遵循生产级最佳实践

# 1. Deployment配置 - 管理应用Pod的创建和更新
apiVersion: apps/v1  # 使用稳定的API版本,避免使用过时的beta版本
kind: Deployment
metadata:
  name: java-demo-web  # 部署名称
  namespace: demo-apps  # 指定命名空间,便于资源隔离
  labels:
    app.kubernetes.io/name: java-demo-web  # 标准化标签 - 应用名称
    app.kubernetes.io/version: "1.0.0"     # 标准化标签 - 应用版本
    app.kubernetes.io/component: web       # 标准化标签 - 组件类型
    app.kubernetes.io/part-of: demo-system # 标准化标签 - 所属系统
  annotations:
    owner: dev-team-java  # 标注负责人/团队
    deployment-date: "2025-09-24"  # 部署日期
spec:
  replicas: 3  # 生产环境建议至少3个副本,保证高可用
  selector:
    matchLabels:
      app.kubernetes.io/name: java-demo-web  # 与Pod标签匹配
  strategy:
    rollingUpdate:
      maxSurge: 1        # 滚动更新时允许超出期望副本数的最大数量
      maxUnavailable: 0  # 滚动更新时允许不可用的最大副本数,生产环境建议0
    type: RollingUpdate  # 使用滚动更新策略,避免服务中断
  template:
    metadata:
      labels:
        app.kubernetes.io/name: java-demo-web  # 必须与selector匹配
        app.kubernetes.io/version: "1.0.0"
    spec:
      # 节点亲和性配置 - 优先调度到具有特定标签的节点
      affinity:
        # 反亲和性配置 - 避免同一应用的副本调度到同一节点
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 100
            podAffinityTerm:
              labelSelector:
                matchLabels:
                  app.kubernetes.io/name: java-demo-web
              topologyKey: kubernetes.io/hostname  # 按主机名隔离
        # 节点选择器 - 调度到标记为应用节点的服务器
        nodeAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
          - weight: 50
            preference:
              matchExpressions:
              - key: node-type
                operator: In
                values:
                - application

      # 拓扑分布约束 - 跨可用区均匀分布副本
      topologySpreadConstraints:
      - maxSkew: 1  # 不同拓扑域之间的最大差异
        topologyKey: topology.kubernetes.io/zone  # 按可用区分布
        whenUnsatisfiable: ScheduleAnyway  # 无法满足时仍调度
        labelSelector:
          matchLabels:
            app.kubernetes.io/name: java-demo-web

      # 安全上下文配置 - 容器级安全控制
      securityContext:
        runAsNonRoot: true  # 禁止以root用户运行
        runAsUser: 1000     # 指定运行用户ID
        runAsGroup: 1000    # 指定运行用户组ID
        fsGroup: 1000       # 文件系统组ID,控制挂载卷的权限
        fsGroupChangePolicy: "OnRootMismatch"  # 仅在根目录权限不匹配时更改
        allowPrivilegeEscalation: false  # 禁止权限提升
        seccompProfile:
          type: RuntimeDefault  # 使用默认的seccomp配置文件

      containers:
      - name: java-demo-web  # 容器名称
        image: registry.example.com/demo/java-web:1.0.0  # 使用私有仓库镜像
        imagePullPolicy: IfNotPresent  # 镜像拉取策略

        # 容器级安全上下文
        securityContext:
          privileged: false  # 禁用特权容器
          readOnlyRootFilesystem: true  # 根文件系统设为只读,增强安全性
          allowPrivilegeEscalation: false  # 禁止权限提升
          capabilities:
            drop: ["ALL"]  # 移除所有Linux capabilities

        # 资源请求与限制 - 防止资源争抢和资源浪费
        resources:
          requests:  # 资源请求,作为调度依据
            cpu: 500m  # Java应用建议至少500m CPU
            memory: 1Gi  # 根据应用实际需求调整
          limits:  # 资源限制,防止资源滥用
            cpu: 1000m  # 限制最大CPU使用
            memory: 2Gi  # 内存限制建议为请求的1.5-2倍

        # 环境变量配置 - 外部化配置
        env:
        - name: SPRING_PROFILES_ACTIVE
          value: "prod"  # 激活生产环境配置
        - name: JAVA_OPTS
          value: "-Xms512m -Xmx1g"  # Java虚拟机参数

        # 健康检查探针配置
        # 启动探针 - 适用于启动较慢的Java应用
        startupProbe:
          httpGet:
            path: /actuator/health  # Spring Boot Actuator健康检查端点
            port: 8080
          initialDelaySeconds: 30  # 启动30秒后开始探测
          periodSeconds: 10        # 每10秒探测一次
          failureThreshold: 12     # 允许12次失败(总等待2分钟)

        # 存活探针 - 检测容器是否存活
        livenessProbe:
          httpGet:
            path: /actuator/health/liveness
            port: 8080
          initialDelaySeconds: 60  # 初始化延迟,确保应用已启动
          periodSeconds: 10        # 探测周期
          timeoutSeconds: 5        # 超时时间
          successThreshold: 1      # 成功阈值
          failureThreshold: 3      # 失败阈值

        # 就绪探针 - 检测应用是否准备好接收流量
        readinessProbe:
          httpGet:
            path: /actuator/health/readiness
            port: 8080
          initialDelaySeconds: 45  # 初始化延迟
          periodSeconds: 5         # 更频繁的探测
          timeoutSeconds: 3
          successThreshold: 1
          failureThreshold: 2

        # 端口配置
        ports:
        - containerPort: 8080
          name: http
          protocol: TCP

        # 挂载卷配置 - 为需要写入的目录提供可写存储
        volumeMounts:
        - name: tmp-volume
          mountPath: /tmp  # Java应用通常需要/tmp可写
        - name: logs-volume
          mountPath: /app/logs  # 日志目录
        - name: config-volume
          mountPath: /app/config  # 配置文件目录

      # 卷定义
      volumes:
      - name: tmp-volume
        emptyDir: {}  # 临时存储,Pod删除时数据丢失
      - name: logs-volume
        emptyDir: 
          medium: Memory  # 内存中存储日志,提高性能
      - name: config-volume
        configMap:
          name: java-demo-web-config  # 引用ConfigMap中的配置

      # 镜像拉取密钥 - 如果使用私有仓库
      imagePullSecrets:
      - name: registry-credentials

# 2. Service配置 - 暴露应用并提供固定访问点
apiVersion: v1
kind: Service
metadata:
  name: java-demo-web-svc
  namespace: demo-apps
  labels:
    app.kubernetes.io/name: java-demo-web
spec:
  selector:
    app.kubernetes.io/name: java-demo-web  # 关联到对应的Pod
  ports:
  - port: 80                # Service暴露的端口
    targetPort: http        # 对应Pod的端口名称
    protocol: TCP
    name: http
  type: ClusterIP  # 仅在集群内部可访问,外部通过Ingress访问

# 3. Ingress配置 - 管理外部访问
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: java-demo-web-ingress
  namespace: demo-apps
  annotations:
    kubernetes.io/ingress.class: nginx  # 指定Ingress控制器
    nginx.ingress.kubernetes.io/ssl-redirect: "true"  # 强制HTTPS
    nginx.ingress.kubernetes.io/proxy-read-timeout: "60"  # 超时设置
    cert-manager.io/cluster-issuer: "letsencrypt-prod"  # 自动证书管理
spec:
  tls:
  - hosts:
    - demo-web.example.com  # 域名
    secretName: demo-web-tls  # 存储TLS证书的Secret
  rules:
  - host: demo-web.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: java-demo-web-svc  # 关联到Service
            port:
              name: http

Last updated