Skip to content

K8s 架构师五大领域深度优化实战手册

网络 | 存储 | 调度 | 监控 | 安全等保 配合 面试手册模拟面试手册 使用


目录

  1. 网络方案优化
  2. 存储方案优化
  3. 调度资源均衡优化
  4. 监控可观测性优化
  5. 安全等保
  6. 面试高频追问与应答

1. 网络方案优化

1.1 我做过哪些网络优化 (总览)

优化方向具体项目效果
CNI升级替换Calico iptables → Cilium eBPFService延迟降低80%, CPU开销减少40%
DNS优化启用NodeLocal DNSCache + CoreDNS调优DNS解析P99从120ms降到5ms
Service优化iptables → IPVS, 连接池优化大规模Service下性能恒定
NetworkPolicy全集群网络策略治理攻击面缩小70%
多网络平面Multus CNI, 管理/业务/存储网络分离网络隔离, 带宽保障
Ingress/GatewayNginx Ingress → Envoy GatewayHTTP/2, gRPC原生支持, 可观测性增强
Service MeshIstio sidecar → ambient mesh数据面开销降低60%
跨集群网络Submariner/Clusternet跨集群Pod直连

1.2 CNI方案深度优化

1.2.1 Calico → Cilium 迁移实战

迁移背景:

  • 集群3000+节点, Service 5000+
  • Calico iptables模式下: iptables规则30万+条, 新建连接延迟 > 50ms
  • kube-proxy CPU使用率 > 2核, 成为瓶颈

迁移方案:

bash
# Step 1: 安装Cilium (与Calico并行, 双CNI模式)
helm install cilium cilium/cilium --version 1.15.0 \
  --namespace kube-system \
  --set cni.chainingMode=none \
  --set kubeProxyReplacement=true \
  --set k8sServiceHost=apiserver.example.com \
  --set k8sServicePort=6443 \
  --set bpf.masquerade=true \
  --set bpf.preallocateMaps=true \
  --set ipam.mode=cluster-pool \
  --set ipam.operator.clusterPoolIPv4PodCIDRList="10.244.0.0/16" \
  --set hubble.enabled=true \
  --set hubble.relay.enabled=true \
  --set hubble.ui.enabled=true \
  --set operator.replicas=2

# Step 2: 灰度验证
# 先在新节点池(只用Cilium)部署测试服务
# 压测对比: 吞吐量/延迟/CPU使用

# Step 3: 逐步迁移
# 新业务全部使用Cilium节点池
# 旧业务按命名空间分批迁移
# 最后下线Calico

Cilium关键优化配置:

yaml
# cilium-config ConfigMap
# eBPF性能优化
bpf-map-dynamic-size-ratio: "0.0025"    # 内存的0.25%用于BPF map
bpf-preallocate-maps: "true"             # 预分配BPF map, 避免运行时分配延迟
enable-bandwidth-manager: "true"         # 启用带宽管理 (EDT)
enable-local-redirect-policy: "true"     # 本地重定向 (NodeLocal DNS)

# 替代kube-proxy
kube-proxy-replacement: "true"
kube-proxy-replacement-healthz-bind-address: "0.0.0.0:10256"

# Socket级负载均衡 (跳过iptables)
socket-lb-tracing: "true"

# 路由优化: 同节点Pod走veth, 不走overlay
routing-mode: "tunnel"                   # 或 "native" (同L2)
tunnel-protocol: "geneve"               # geneve比vxlan性能好

# 连接追踪优化
bpf-ct-global-tcp-max: "524288"         # TCP连接追踪上限
bpf-ct-global-any-max: "262144"         # 非TCP连接追踪上限
bpf-ct-timeout-regular-tcp-fin: "10s"   # FIN超时
bpf-ct-timeout-regular-tcp: "21600s"    # ESTABLISHED超时

迁移效果:

指标Calico (iptables)Cilium (eBPF)提升
Service连接延迟P9952ms0.8ms-98%
kube-proxy CPU2.3核0 (被替代)-100%
iptables规则数300,000+0-100%
新建连接吞吐50K/s200K/s+300%

1.2.2 eBPF Socket级负载均衡

传统模式 (iptables/IPVS):
  Pod → Socket → TCP/IP Stack → iptables DNAT → 目标Pod
                                ↑ 内核网络栈开销大

eBPF Socket LB (Cilium):
  Pod → Socket → eBPF sock_ops → 直接DNAT → 目标Pod
                   ↑ 在内核socket层直接替换目标地址, 跳过整个网络栈
yaml
# 启用Socket LB (Cilium 1.14+)
socket-lb: "true"
socket-lb-tracing: "true"

# 对某些Namespace禁用 (兼容性)
socket-lb-host-namespace-only: "true"

1.3 DNS优化

1.3.1 NodeLocal DNSCache

优化前:                          优化后:
Pod → CoreDNS Pod                Pod → NodeLocal DNSCache (本机)
      (可能跨节点)                         ↓ (miss)
      conntrack冲突                   CoreDNS Pod
      P99: 120ms                      P99: 5ms
yaml
# NodeLocal DNSCache DaemonSet (K8s官方addon)
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: node-local-dns
  namespace: kube-system
spec:
  template:
    spec:
      containers:
      - name: node-cache
        image: registry.k8s.io/dns/k8s-dns-node-cache:1.23.1
        args:
        - "-localip"
        - "169.254.20.10"              # 虚拟IP, 绑定到每个节点
        - "-conf"
        - "/etc/Corefile"
        - "-upstreamsvc"
        - "kube-dns"                   # miss时转发到CoreDNS
        - "-skipteardown=false"
        - "-setupinterface=true"
        # Corefile优化
        # Corefile: |
        #   cluster.local:53 {
        #     errors
        #     cache {
        #       success 9984 30        # 成功缓存9984条, TTL 30s
        #       denial 9984 5          # 否定缓存9984条, TTL 5s
        #     }
        #     reload
        #     loop
        #     bind 169.254.20.10       # 绑定虚拟IP
        #     forward . 10.96.0.10     # CoreDNS ClusterIP
        #   }

1.3.2 CoreDNS调优

yaml
# CoreDNS ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: coredns
  namespace: kube-system
data:
  Corefile: |
    .:53 {
        errors
        health {
            lameduck 5s               # 优雅关闭
        }
        ready
        kubernetes cluster.local in-addr.arpa ip6.arpa {
            pods insecure              # insecure/disabled/verified
            fallthrough in-addr.arpa ip6.arpa
            ttl 30                     # DNS TTL
        }
        prometheus :9153              # metrics
        forward . /etc/resolv.conf {  # 外部DNS
            max_concurrent 5000       # 最大并发
            prefer_udp                 # 优先UDP
        }
        cache 30 {                    # 全局缓存30s
            success 65536             # 成功缓存上限
            denial 8192               # 否定缓存上限
        }
        loop
        reload
        loadbalance                    # 轮询返回
    }
    
    # 外部域名直连上游DNS (跳过缓存)
    example.com:53 {
        forward . 8.8.8.8 8.8.4.4
        cache 60
    }

---
# CoreDNS HPA
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: coredns-hpa
  namespace: kube-system
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: coredns
  minReplicas: 3
  maxReplicas: 20
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 60

DNS优化效果:

指标优化前优化后
DNS解析P99120ms<5ms
conntrack冲突频繁消除
CoreDNS QPS50K200K+
DNS超时率2%<0.01%

1.4 Service优化

1.4.1 IPVS替代iptables

yaml
# kube-proxy ConfigMap
apiVersion: v1
kind: ConfigMap
metadata:
  name: kube-proxy
  namespace: kube-system
data:
  config.conf: |
    mode: "ipvs"
    ipvs:
      scheduler: "wrr"              # wrr/wlc/sh/sed/nq
      syncPeriod: "30s"             # 规则同步周期
      minSyncPeriod: "10s"          # 最小同步周期
      tcpTimeout: "900s"            # TCP连接超时
      tcpFinTimeout: "30s"          # FIN超时
      udpTimeout: "300s"            # UDP超时
      strictARP: true               # 严格ARP (MetalLB需要)
    conntrack:
      maxPerCore: 131072            # 每核最大conntrack
      min: 131072                   # 最小conntrack
      tcpCloseWaitTimeout: "3600s"
      tcpEstablishedTimeout: "86400s"

1.4.2 连接池与Keep-Alive优化

yaml
# Service配置: 内部服务优化
apiVersion: v1
kind: Service
metadata:
  name: backend-service
  annotations:
    service.kubernetes.io/topology-mode: "Auto"  # 拓扑感知路由
spec:
  sessionAffinity: None              # 无状态服务关闭会话保持
  internalTrafficPolicy: Local       # 优先本地Pod (减少跨节点)
  ports:
  - port: 80
    targetPort: 8080

---
# 客户端侧: HTTP连接池
# Go示例
var httpClient = &http.Client{
    Transport: &http.Transport{
        MaxIdleConns:        100,              // 最大空闲连接
        MaxIdleConnsPerHost: 20,              // 每Host最大空闲
        IdleConnTimeout:     90 * time.Second,
        DisableKeepAlives:   false,            // 启用Keep-Alive
    },
    Timeout: 30 * time.Second,
}

1.5 Network Policy治理

yaml
# 默认拒绝所有入站 (零信任基础)
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
  namespace: production
spec:
  podSelector: {}                    # 所有Pod
  policyTypes:
  - Ingress

---
# 允许同命名空间通信
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-same-namespace
  namespace: production
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector: {}                # 同命名空间所有Pod

---
# 允许Ingress Controller访问
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-ingress-controller
  namespace: production
spec:
  podSelector:
    matchLabels:
      app: web-frontend
  policyTypes:
  - Ingress
  ingress:
  - from:
    - namespaceSelector:
        matchLabels:
          name: ingress-nginx
    ports:
    - protocol: TCP
      port: 8080

---
# Cilium高级: L7策略 (HTTP/gRPC)
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: api-rate-limit
  namespace: production
spec:
  endpointSelector:
    matchLabels:
      app: api-server
  ingress:
  - fromEndpoints:
    - matchLabels:
        role: frontend
    toPorts:
    - ports:
      - port: "8080"
        protocol: TCP
      rules:
        http:
        - method: GET
          path: "/api/v1/.*"
        - method: POST
          path: "/api/v1/orders"
          # HTTP级别精细控制

1.6 多网络平面 (Multus CNI)

yaml
# Multus CNI: 一个Pod多网卡
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
  name: storage-network
  namespace: default
spec:
  config: |
    {
      "cniVersion": "0.3.1",
      "type": "macvlan",
      "master": "eth1",              # 存储网络物理网卡
      "mode": "bridge",
      "ipam": {
        "type": "host-local",
        "subnet": "192.168.100.0/24",
        "rangeStart": "192.168.100.100",
        "rangeEnd": "192.168.100.200",
        "gateway": "192.168.100.1"
      }
    }

---
# Pod使用多网卡
apiVersion: v1
kind: Pod
metadata:
  name: database-pod
  annotations:
    k8s.v1.cni.cncf.io/networks: |
      [
        {"name": "storage-network", "interface": "eth1"},
        {"name": "management-network", "interface": "eth2"}
      ]
spec:
  containers:
  - name: database
    image: postgres:16
    # eth0: 业务网络 (默认)
    # eth1: 存储网络 (高带宽, 低延迟)
    # eth2: 管理网络 (监控/备份)

多网络平面应用场景:

  • 存储网络: 数据库/Ceph流量走独立高带宽网络
  • 管理网络: 监控/日志/备份走独立网络, 隔离故障域
  • DPDK/SR-IOV: 高性能数据面走专用网卡

2. 存储方案优化

2.1 我做过哪些存储优化 (总览)

优化方向具体项目效果
CSI选型Ceph RBD → CephFS分层满足不同访问模式需求
缓存加速Alluxio/JuiceFS缓存层AI训练数据加载速度提升10x
存储分层冷热数据分层, NVMe/SSD/HDD存储成本降低50%
性能调优块大小/fscache/mount参数IOPS提升3x
数据保护快照/备份/容灾RPO<15min
动态供给StorageClass + 自动扩容运维效率提升

2.2 存储分层架构

┌─────────────────────────────────────────────────────────┐
│                    存储分层架构                           │
├──────────┬──────────┬──────────┬────────────────────────┤
│ 热数据层  │ 温数据层  │ 冷数据层  │ 归档层                  │
│ NVMe SSD │ SATA SSD │ HDD/对象  │ S3 Glacier/OSS Archive │
│ <7天     │ 7-30天   │ 30-180天 │ >180天                  │
│ 数据库    │ 日志索引  │ 历史数据  │ 备份归档                 │
│ 高性能    │ 中等性能  │ 低成本    │ 极低成本                 │
└──────────┴──────────┴──────────┴────────────────────────┘
yaml
# StorageClass: 热数据 (NVMe)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ceph-rbd-nvme
  annotations:
    storageclass.kubernetes.io/is-default-class: "false"
provisioner: rbd.csi.ceph.com
parameters:
  clusterID: ceph-cluster
  pool: nvme-pool                 # NVMe池
  imageFormat: "2"
  imageFeatures: layering,exclusive-lock,object-map,fast-diff
  csi.storage.k8s.io/provisioner-secret-name: ceph-admin
  csi.storage.k8s.io/provisioner-secret-namespace: ceph-csi
reclaimPolicy: Retain
allowVolumeExpansion: true        # 支持动态扩容
volumeBindingMode: WaitForFirstConsumer  # 延迟绑定, 调度后再创建

---
# StorageClass: 温数据 (SSD)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ceph-rbd-ssd
provisioner: rbd.csi.ceph.com
parameters:
  clusterID: ceph-cluster
  pool: ssd-pool                  # SSD池
  imageFormat: "2"
  imageFeatures: layering
reclaimPolicy: Retain
allowVolumeExpansion: true

---
# StorageClass: 冷数据 (HDD)
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: cephfs-hdd
provisioner: cephfs.csi.ceph.com
parameters:
  clusterID: ceph-cluster
  fsName: cephfs-hdd              # HDD文件系统
reclaimPolicy: Retain

2.3 AI训练数据缓存加速

yaml
# Alluxio/JuiceFS 缓存层
# 场景: AI训练数据在对象存储(OSS/S3), 读取慢
# 方案: 本地SSD缓存热数据

# JuiceFS CSI配置
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: juicefs-sc
provisioner: csi.juicefs.com
parameters:
  csi.storage.k8s.io/provisioner-secret-name: juicefs-secret
  csi.storage.k8s.io/provisioner-secret-namespace: kube-system
  csi.storage.k8s.io/node-publish-secret-name: juicefs-secret
  csi.storage.k8s.io/node-publish-secret-namespace: kube-system
  juicefs/mount-options: >-
    cache-size=50000               # 本地缓存50GB
    cache-dir=/data/juicefs-cache
    buffer-size=300                # 读写缓冲300MB
    prefetch=1                     # 预读
    writeback                      # 异步写回

---
# 训练Job使用缓存
apiVersion: batch/v1
kind: Job
metadata:
  name: model-training
spec:
  template:
    spec:
      containers:
      - name: trainer
        image: pytorch/pytorch:2.2.0-cuda12.1-cudnn8-runtime
        volumeMounts:
        - name: training-data
          mountPath: /data
          readOnly: true
      volumes:
      - name: training-data
        persistentVolumeClaim:
          claimName: training-dataset-pvc  # JuiceFS PVC

缓存加速效果:

指标直接读OSSJuiceFS缓存提升
首次读取50MB/s50MB/s1x
二次读取50MB/s2000MB/s40x
Epoch训练时间45min12min3.75x
总训练时间24h8h3x

2.4 Ceph性能调优

bash
# Ceph OSD调优 (针对K8s场景)

# 1. 网络优化
ceph config set osd ms_async_op_threads 4         # 异步操作线程
ceph config set osd ms_type async+posix           # 异步消息

# 2. 内存优化
ceph config set osd osd_memory_target 8589934592  # 8GB per OSD
ceph config set osd osd_memory_cache_min 2147483648  # 2GB最小缓存

# 3. 写入优化
ceph config set osd osd_op_threads 8              # 操作线程
ceph config set osd osd_recovery_max_active 3     # 恢复并发
ceph config set osd osd_max_backfills 3           # 回填并发

# 4. Journal/WAL分离 (NVMe for WAL)
ceph config set osd bluestore_block_db_path /dev/nvme0n1  # DB on NVMe
ceph config set osd bluestore_block_wal_path /dev/nvme0n1 # WAL on NVMe

# 5. 压缩 (冷数据)
ceph config set osd bluestore_compression_algorithm zstd
ceph config set osd bluestore_compression_mode aggressive  # HDD池
ceph config set osd bluestore_compression_mode passive     # SSD池
yaml
# PVC Mount参数优化
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: database-data
spec:
  storageClassName: ceph-rbd-nvme
  accessModes: [ReadWriteOnce]
  resources:
    requests:
      storage: 500Gi

---
# Pod挂载优化
apiVersion: v1
kind: Pod
metadata:
  name: database
spec:
  containers:
  - name: postgres
    volumeMounts:
    - name: data
      mountPath: /var/lib/postgresql/data
  volumes:
  - name: data
    persistentVolumeClaim:
      claimName: database-data
  # ext4挂载优化 (通过StorageClass或CSI配置)
  # mountOptions:
  # - noatime           # 不更新访问时间
  # - nodiratime        # 不更新目录访问时间
  # - barrier=0         # 关闭barrier (有UPS/电池时)
  # - discard           # TRIM支持 (SSD)

2.5 数据保护与快照

yaml
# VolumeSnapshotClass
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshotClass
metadata:
  name: ceph-rbd-snapclass
driver: rbd.csi.ceph.com
deletionPolicy: Retain
parameters:
  clusterID: ceph-cluster
  csi.storage.k8s.io/snapshotter-secret-name: ceph-admin
  csi.storage.k8s.io/snapshotter-secret-namespace: ceph-csi

---
# 定时快照 (VolumeSnapshot + CronJob)
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: db-snapshot-20260822
spec:
  volumeSnapshotClassName: ceph-rbd-snapclass
  source:
    persistentVolumeClaimName: database-data

---
# 自动快照CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
  name: volume-snapshot-cronjob
  namespace: production
spec:
  schedule: "0 2 * * *"           # 每天凌晨2点
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: snapshot-admin
          containers:
          - name: snapshot
            image: bitnami/kubectl:latest
            command:
            - /bin/sh
            - -c
            - |
              SNAP_NAME="db-snap-$(date +%Y%m%d-%H%M)"
              kubectl create -f - <<EOF
              apiVersion: snapshot.storage.k8s.io/v1
              kind: VolumeSnapshot
              metadata:
                name: $SNAP_NAME
                namespace: production
              spec:
                volumeSnapshotClassName: ceph-rbd-snapclass
                source:
                  persistentVolumeClaimName: database-data
              EOF
              # 删除7天前的快照
              kubectl get volumesnapshot -n production \
                -o jsonpath='{.items[?(@.metadata.creationTimestamp<"'$(date -d '7 days ago' -Iseconds)'")]}' \
                | xargs kubectl delete volumesnapshot -n production
          restartPolicy: OnFailure

2.6 Velero 备份与容灾

bash
# 安装Velero
velero install \
  --provider aws \
  --plugins velero/velero-plugin-for-aws:v1.8.0 \
  --bucket k8s-backup \
  --backup-location-config region=cn-east-1,s3Url=https://s3.example.com \
  --snapshot-location-config region=cn-east-1 \
  --secret-file ./credentials-velero

# 定时备份
velero schedule create daily-backup \
  --schedule="0 3 * * *" \
  --ttl 168h \
  --include-namespaces production,staging \
  --snapshot-volumes \
  --snapshot-move-data              # 跨区域复制

# 恢复
velero restore create --from-backup daily-backup-20260822

3. 调度资源均衡优化

3.1 我做过哪些调度优化 (总览)

优化方向具体项目效果
在离线混部Koordinator混部方案CPU利用率30%→65%
Binpack调度紧凑调度减少碎片节点利用率提升25%
拓扑感知NUMA/GPU拓扑感知分布式训练性能提升35%
Gang SchedulingVolcano Gang调度AI训练任务可靠性99.9%
弹性伸缩HPA+VPA+CA+Karpenter成本降低40%, 弹性<2min
抢占策略优先级抢占+公平共享核心业务SLA保障
调度器扩展自定义调度插件业务定制调度逻辑

3.2 在离线混部方案 (Koordinator)

yaml
# Koordinator 混部架构
# ┌──────────────────────────────────────────────────────┐
# │                    Kubernetes Node                     │
# ├──────────────────────┬─────────────────────────────────┤
# │    在线服务 (Prod)    │       离线任务 (Batch)           │
# │    Priority: 9000+   │       Priority: <1000           │
# │    QoS: Guaranteed   │       QoS: BestEffort          │
# │    CPU request: 40%  │       使用Prod空闲资源           │
# │    Memory request: 50%│      可被随时压制/驱逐          │
# ├──────────────────────┴─────────────────────────────────┤
# │              Koordinator Agent (koordlet)               │
# │   - 实时采集在线服务延迟 (P99)                          │
# │   - 动态调整离线任务CPU/内存上限 (cgroup)               │
# │   - 在线延迟超标时立即压制离线任务                      │
# │   - 资源超卖比动态计算                                 │
# └────────────────────────────────────────────────────────┘

# ClusterColocationProfile
apiVersion: config.koordinator.sh/v1alpha1
kind: ClusterColocationProfile
metadata:
  name: colocation-profile-batch
spec:
  namespaceSelector:
    matchLabels:
      koordinator.sh/enable-colocation: "true"
  selector:
    matchLabels:
      app.kubernetes.io/type: batch
  # 离线任务资源转换
  coordinator:                           
    cpu: 100%                           # 100%使用在线空闲CPU
    memory: 80%                         # 80%使用在线空闲内存
    resourceQoS: BE                     # Best Effort
  # 自动注入
  patch:
    spec:
      priorityClassName: koord-batch     # 低优先级
      schedulerName: koord-scheduler
  # 压制策略
  qosClass: BE
  labels:
    koordinator.sh/qosClass: BE

---
# 离线任务示例
apiVersion: batch/v1
kind: Job
metadata:
  name: data-processing
  labels:
    app.kubernetes.io/type: batch       # 匹配ColocationProfile
spec:
  template:
    spec:
      containers:
      - name: processor
        resources:
          # 不需要设置requests/limits, 由Profile自动注入
          # 实际使用: 在线服务未使用的CPU和内存
          requests:
            kubernetes.io/batch-cpu: "4000"    # 4核 (Koordinator自定义资源)
            kubernetes.io/batch-memory: "8Gi"

混部压制策略 (关键!):

yaml
# NodeMetric: Koordinator实时监控
# koordlet每5秒采集一次:
# - 在线服务CPU/Memory实际使用
# - 在线服务P99延迟
# - 离线任务资源使用

# 压制逻辑:
# 1. 在线CPU使用率 > 70% → 离线CPU限制降低到20%
# 2. 在线P99延迟 > SLO阈值 → 立即驱逐离线任务
# 3. 内存使用率 > 85% → 触发离线任务OOM
# 4. CPU CFS burst受限 → 通过cgroup cpu.max控制

# 节点标注 (koordinator自动计算)
# node.koordinator.sh/batch-cpu: "12000"     # 可分配给离线的CPU (毫核)
# node.koordinator.sh/batch-memory: "24Gi"   # 可分配给离线的内存

混部效果:

指标混部前混部后提升
CPU利用率30%65%+117%
内存利用率40%72%+80%
月成本¥500万¥300万-40%
在线P99延迟15ms16ms无影响
离线任务完成率95%98%+3%

3.3 Binpack调度 (紧凑调度)

yaml
# kube-scheduler插件配置: NodeResourcesFit + LeastAllocated/MostAllocated
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: default-scheduler
  plugins:
    score:
      enabled:
      - name: NodeResourcesFit
        weight: 5
  pluginConfig:
  - name: NodeResourcesFit
    args:
      scoringStrategy:
        type: MostAllocated          # Binpack: 优先填满节点
        # LeastAllocated: 分散调度 (默认)
        # MostAllocated: 紧凑调度 (Binpack)
        resources:
        - name: cpu
          weight: 1
        - name: memory
          weight: 1
        - name: nvidia.com/gpu
          weight: 3                  # GPU权重更高, 优先Binpack GPU节点

---
# Descheduler: 定期重平衡
apiVersion: descheduler/v1alpha2
kind: DeschedulerPolicy
profiles:
- name: default
  strategies:
    LowNodeUtilization:              # 低利用率节点驱逐
      enabled: true
      params:
        nodeResourceUtilizationThresholds:
          thresholds:
            cpu: 20                  # CPU利用率<20%视为低
            memory: 20
            pods: 20
          targetThresholds:
            cpu: 70                  # 目标利用率70%
            memory: 70
            pods: 70
    RemoveDuplicates:                # 去除重复Pod (同一RS的Pod在同一节点)
      enabled: true
    RemovePodsViolatingTopologySpreadConstraint:
      enabled: true

3.4 弹性伸缩全栈方案

┌───────────────────────────────────────────────────────────────┐
│                    弹性伸缩全栈方案                             │
├───────────┬───────────────┬──────────────┬────────────────────┤
│ Pod水平伸缩 │  Pod垂直伸缩   │   节点伸缩    │   智能伸缩          │
│ HPA       │ VPA           │ Cluster      │ Karpenter          │
│ 自定义指标  │ 推荐模式       │  Autoscaler  │ 按需节点供给        │
│ 预测性HPA  │ 离线分析       │ 节点组管理    │ Binpack调度         │
│ Scheduled  │               │ Spot实例     │ Spot优先            │
│  HPA       │               │              │                    │
└───────────┴───────────────┴──────────────┴────────────────────┘

Karpenter (替代Cluster Autoscaler)

yaml
# NodePool: 定义节点供给策略
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
  name: general-purpose
spec:
  disruption:
    consolidationPolicy: WhenUnderutilized  # 低利用率时整合
    expireAfter: 720h                       # 节点最长存活30天
  limits:
    cpu: "1000"
    memory: 2000Gi
  template:
    spec:
      requirements:
      - key: "karpenter.k8s.aws/instance-category"
        operator: In
        values: ["c", "m", "r"]            # 计算/内存/均衡型
      - key: "karpenter.k8s.aws/instance-generation"
        operator: Gt
        values: ["5"]                      # 5代以上实例
      - key: "kubernetes.io/arch"
        operator: In
        values: ["amd64"]
      - key: "karpenter.sh/capacity-type"
        operator: In
        values: ["spot", "on-demand"]      # Spot优先
      nodeClassRef:
        name: default
  weight: 100                              # 优先级

---
# GPU节点池
apiVersion: karpenter.sh/v1beta1
kind: NodePool
metadata:
  name: gpu-pool
spec:
  disruption:
    consolidationPolicy: WhenEmpty
    consolidateAfter: 5m                   # 空闲5分钟后缩
  limits:
    nvidia.com/gpu: "64"
  template:
    spec:
      requirements:
      - key: "karpenter.k8s.aws/instance-family"
        operator: In
        values: ["p4d", "p5"]              # GPU实例
      - key: "karpenter.sh/capacity-type"
        operator: In
        values: ["on-demand"]              # GPU不用Spot (稳定性)
      taints:
      - key: "nvidia.com/gpu"
        effect: "NoSchedule"
      nodeClassRef:
        name: gpu
  weight: 50

预测性HPA (KEDA + Prometheus)

yaml
# KEDA ScaledObject: 基于自定义指标
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: web-service-scaler
spec:
  scaleTargetRef:
    name: web-service
  minReplicaCount: 5
  maxReplicaCount: 100
  pollingInterval: 10
  cooldownPeriod: 300                      # 缩容冷却5分钟
  triggers:
  # QPS触发器
  - type: prometheus
    metadata:
      serverAddress: http://prometheus:9090
      metricName: http_requests_per_second
      query: sum(rate(http_requests_total{service="web"}[2m]))
      threshold: "5000"                    # 每副本5000 QPS
      activationThreshold: "100"
  # 延迟触发器
  - type: prometheus
    metadata:
      serverAddress: http://prometheus:9090
      metricName: http_request_duration_p99
      query: histogram_quantile(0.99, sum(rate(http_request_duration_bucket{service="web"}[5m])) by (le))
      threshold: "500"                     # P99延迟>500ms触发扩容
      activationThreshold: "50"
  # Cron触发器 (工作日白天多开)
  - type: cron
    metadata:
      timezone: Asia/Shanghai
      start: 0 8 * * 1-5                   # 周一到周五8点
      end: 0 20 * * 1-5                    # 周一到周五20点
      desiredReplicas: "20"
  advanced:
    horizontalPodAutoscalerConfig:
      behavior:
        scaleUp:
          stabilizationWindowSeconds: 30
          policies:
          - type: Percent
            value: 50
            periodSeconds: 60
        scaleDown:
          stabilizationWindowSeconds: 300
          policies:
          - type: Pods
            value: 5
            periodSeconds: 120

3.5 Gang Scheduling (Volcano)

yaml
# 分布式训练: 所有Worker必须同时调度
apiVersion: scheduling.volcano.sh/v1beta1
kind: PodGroup
metadata:
  name: llm-training
spec:
  minMember: 8                            # 至少8个Pod同时调度
  minResources:
    nvidia.com/gpu: 64                    # 至少64块GPU
  queue: gpu-training-queue
  priorityClassName: high-priority
  
---
# 队列管理 (多团队公平共享)
apiVersion: scheduling.volcano.sh/v1beta1
kind: Queue
metadata:
  name: gpu-training-queue
spec:
  weight: 50                              # 权重50 (相对其他队列)
  reclaimable: true                       # 空闲资源可回收
  capability:                             # 上限
    nvidia.com/gpu: 64
  guarantee:                              # 保障
    nvidia.com/gpu: 16                    # 至少16块GPU

---
# PyTorchJob使用Volcano
apiVersion: kubeflow.org/v1
kind: PyTorchJob
metadata:
  name: llm-finetune
spec:
  runPolicy:
    schedulingPolicy:
      minAvailable: 8                     # Gang Scheduling
      queue: gpu-training-queue
      priorityClass: high-priority
  pytorchReplicaSpecs:
    Master:
      replicas: 1
      template:
        spec:
          schedulerName: volcano          # 使用Volcano调度器
          containers:
          - name: pytorch
            resources:
              limits:
                nvidia.com/gpu: 8
    Worker:
      replicas: 7
      template:
        spec:
          schedulerName: volcano
          containers:
          - name: pytorch
            resources:
              limits:
                nvidia.com/gpu: 8

4. 监控可观测性优化

4.1 我做过哪些监控优化 (总览)

优化方向具体项目效果
指标采集Prometheus联邦 + Thanos跨集群统一监控, 90天保留
告警治理告警分级 + 静默 + 抑制告警噪音降低80%
日志优化EFK → Loki存储成本降低70%
链路追踪Jaeger + OpenTelemetry故障定位时间<5分钟
SLO体系SLI/SLO定义 + Error Budget可用性从99.9%→99.97%
GPU监控DCGM ExporterGPU利用率/温度/功耗可视化
大盘建设Grafana统一大盘全局一览, 5秒定位问题

4.2 Prometheus联邦架构

┌─────────────────────────────────────────────────────────────────┐
│                    Thanos (全局查询层)                            │
│  ┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────────────┐│
│  │ Thanos   │  │ Thanos   │  │ Thanos   │  │ Thanos           ││
│  │ Query    │  │ Store    │  │ Compact  │  │ Bucket           ││
│  │ (全局查询)│  │ (历史查询)│  │ (压缩)   │  │ (长期存储)        ││
│  └──────────┘  └──────────┘  └──────────┘  └──────────────────┘│
└──────────────────────────┬──────────────────────────────────────┘

        ┌──────────────────┼──────────────────┐
        │                  │                  │
┌───────┴───────┐  ┌───────┴───────┐  ┌───────┴───────┐
│ 集群A          │  │ 集群B          │  │ 集群C          │
│ Prometheus     │  │ Prometheus     │  │ Prometheus     │
│ + Thanos       │  │ + Thanos       │  │ + Thanos       │
│   Sidecar      │  │   Sidecar      │  │   Sidecar      │
│ (本地保留7天)   │  │ (本地保留7天)   │  │ (本地保留7天)   │
└───────────────┘  └───────────────┘  └───────────────┘
yaml
# Thanos Sidecar配置 (每个Prometheus实例旁)
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: prometheus
  namespace: monitoring
spec:
  template:
    spec:
      containers:
      - name: prometheus
        image: prom/prometheus:v2.51.0
        args:
        - "--config.file=/etc/prometheus/prometheus.yml"
        - "--storage.tsdb.path=/prometheus"
        - "--storage.tsdb.retention.time=7d"      # 本地保留7天
        - "--storage.tsdb.min-block-duration=2h"
        - "--storage.tsdb.max-block-duration=2h"
        - "--web.enable-lifecycle"
        - "--web.enable-admin-api"
      - name: thanos-sidecar
        image: quay.io/thanos/thanos:v0.34.0
        args:
        - sidecar
        - "--tsdb.path=/prometheus"
        - "--prometheus.url=http://localhost:9090"
        - "--objstore.config-file=/etc/thanos/objstore.yml"
        - "--grpc-address=0.0.0.0:10901"
        - "--http-address=0.0.0.0:10902"
        volumeMounts:
        - name: prometheus-data
          mountPath: /prometheus
        - name: thanos-objstore
          mountPath: /etc/thanos

# 对象存储配置 (S3/OSS/MinIO)
# objstore.yml:
type: S3
config:
  bucket: thanos-long-term
  endpoint: s3.example.com
  access_key: xxx
  secret_key: xxx

Prometheus性能调优:

yaml
# prometheus.yml
scrape_configs:
- job_name: kubernetes-pods
  scrape_interval: 30s                    # 默认15s, 降到30s减少压力
  scrape_timeout: 10s
  sample_limit: 5000                      # 每目标最多5000个指标
  metric_relabel_configs:
  # 丢弃不需要的指标 (减少存储)
  - source_labels: [__name__]
    regex: 'go_.*|promhttp_.*'
    action: drop
  # 高基数指标裁剪
  - source_labels: [__name__]
    regex: 'apiserver_request_duration_seconds_bucket'
    action: keep

global:
  evaluation_interval: 30s               # 规则评估间隔
  scrape_interval: 30s
  external_labels:                        # 联邦标识
    cluster: prod-cluster-a
    region: cn-east-1

4.3 告警治理

yaml
# 告警分级体系
# P0 (立即处理): 集群不可用, 核心服务宕机
# P1 (15分钟内): 服务降级, 单点故障
# P2 (1小时内): 性能下降, 资源告警
# P3 (24小时内): 信息性告警, 趋势预警

# Alertmanager配置
apiVersion: v1
kind: ConfigMap
metadata:
  name: alertmanager-config
  namespace: monitoring
data:
  alertmanager.yml: |
    global:
      resolve_timeout: 5m
      
    # 告警抑制 (避免级联告警风暴)
    inhibit_rules:
    # 节点宕机时, 抑制该节点上所有Pod告警
    - source_matchers:
      - severity = critical
      - alertname = NodeDown
      target_matchers:
      - severity =~ warning|info
      equal: ["instance"]
    
    # 集群API Server不可用时, 抑制所有Pod告警
    - source_matchers:
      - alertname = APIServerDown
      target_matchers:
      - severity =~ warning|info
    
    # 路由
    route:
      receiver: default
      group_by: [cluster, namespace, alertname]
      group_wait: 30s                    # 等30秒收集同组告警
      group_interval: 5m                 # 同组告警间隔5分钟
      repeat_interval: 4h                # 重复告警间隔4小时
      routes:
      - matchers:
        - severity = critical
        receiver: pagerduty-critical
        group_wait: 10s                  # P0告警10秒就发
        repeat_interval: 1h
      - matchers:
        - severity = warning
        receiver: dingtalk-warning
        repeat_interval: 4h
      - matchers:
        - severity = info
        receiver: dingtalk-info
        repeat_interval: 12h
    
    receivers:
    - name: pagerduty-critical
      pagerduty_configs:
      - service_key: xxx
        severity: critical
    - name: dingtalk-warning
      webhook_configs:
      - url: http://dingtalk-bot:8080/warning
    - name: dingtalk-info
      webhook_configs:
      - url: http://dingtalk-bot:8080/info

---
# 告警规则示例
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: k8s-cluster-rules
  namespace: monitoring
spec:
  groups:
  - name: cluster-health
    rules:
    # P0: 节点宕机
    - alert: NodeDown
      expr: up{job="node-exporter"} == 0
      for: 2m
      labels:
        severity: critical
      annotations:
        summary: "节点 {{ $labels.instance }} 宕机"
        runbook: "https://wiki.example.com/runbook/node-down"
    
    # P1: Pod频繁重启
    - alert: PodCrashLooping
      expr: increase(kube_pod_container_status_restarts_total[1h]) > 5
      for: 5m
      labels:
        severity: warning
      annotations:
        summary: "Pod {{ $labels.namespace }}/{{ $labels.pod }} 1小时重启{{ $value }}次"
    
    # P2: CPU Throttling严重
    - alert: CPUThrottlingHigh
      expr: |
        sum(rate(container_cpu_cfs_throttled_periods_total{container!=""}[5m])) by (namespace, pod, container)
        / sum(rate(container_cpu_cfs_periods_total{container!=""}[5m])) by (namespace, pod, container)
        > 0.5
      for: 10m
      labels:
        severity: warning
      annotations:
        summary: "{{ $labels.pod }} CPU限流率超过50%, 建议增加CPU limit"

4.4 SLO体系与Error Budget

yaml
# SLI/SLO定义
# 服务: web-api
# SLI: 成功率 = 成功请求数 / 总请求数 (排除参数错误)
# SLO: 99.9% (月)
# Error Budget: 0.1% = 43.2分钟/月

# Sloth (SLO管理工具) 定义
apiVersion: sloth.k8s.nginx.com/v1alpha1
kind: PrometheusServiceLevel
metadata:
  name: web-api-slo
  namespace: production
spec:
  service: web-api
  slos:
  - name: availability
    objective: 99.9
    sli:
      events:
        error_query: |
          sum(rate(http_requests_total{service="web-api", code=~"5.."}[{{.window}}]))
        total_query: |
          sum(rate(http_requests_total{service="web-api"}[{{.window}}]))
    alerting:
      name: WebAPIAvailability
      page_alert:
        labels:
          severity: critical
        annotations:
          summary: "web-api可用性低于99.9%"
      ticket_alert:
        labels:
          severity: warning
        annotations:
          summary: "web-api Error Budget消耗过快"

---
# Error Budget看板 (Grafana)
# 计算公式: remaining_budget = 1 - (error_rate / (1 - slo_target))
# remaining_budget > 0: 安全 (可以发布)
# remaining_budget < 0: 危险 (冻结发布, 专注稳定性)

# 月度Error Budget报告
# 本月: 成功率99.93%, SLO 99.9%, Error Budget剩余30%
# 上月: 成功率99.87%, SLO 99.9%, Error Budget超支 → 冻结发布2周

4.5 GPU监控 (DCGM Exporter)

yaml
# NVIDIA DCGM Exporter DaemonSet
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: dcgm-exporter
  namespace: monitoring
spec:
  selector:
    matchLabels:
      app: dcgm-exporter
  template:
    spec:
      nodeSelector:
        nvidia.com/gpu.present: "true"
      tolerations:
      - key: nvidia.com/gpu
        operator: Exists
        effect: NoSchedule
      containers:
      - name: dcgm-exporter
        image: nvcr.io/nvidia/k8s/dcgm-exporter:3.3.5-3.4.1-ubuntu22.04
        env:
        - name: DCGM_EXPORTER_LISTEN
          value: ":9400"
        - name: DCGM_EXPORTER_KUBERNETES
          value: "true"
        ports:
        - name: metrics
          containerPort: 9400
        securityContext:
          privileged: true               # DCGM需要特权

# 关键GPU指标:
# DCGM_FI_DEV_GPU_UTIL         - GPU利用率 (%)
# DCGM_FI_DEV_FB_USED          - 显存使用 (MB)
# DCGM_FI_DEV_FB_FREE          - 显存空闲 (MB)
# DCGM_FI_DEV_GPU_TEMP         - GPU温度 (C)
# DCGM_FI_DEV_POWER_USAGE      - 功耗 (W)
# DCGM_FI_DEV_SM_CLOCK         - SM频率 (MHz)
# DCGM_FI_DEV_MEM_CLOCK        - 显存频率 (MHz)
# DCGM_FI_PROF_PIPE_TENSOR_ACTIVE - Tensor Core利用率
# DCGM_FI_PROF_NVLINK_TX_BYTES   - NVLink发送 (B/s)
# DCGM_FI_PROF_NVLINK_RX_BYTES   - NVLink接收 (B/s)

# Grafana GPU看板:
# Row 1: GPU利用率热力图 (每节点每卡)
# Row 2: 显存使用率趋势
# Row 3: GPU温度与功耗
# Row 4: NVLink带宽使用
# Row 5: 按Namespace/Job统计GPU使用

4.6 链路追踪 (OpenTelemetry)

yaml
# OpenTelemetry Collector
apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
  name: otel-collector
  namespace: observability
spec:
  mode: deployment
  replicas: 3
  config: |
    receivers:
      otlp:
        protocols:
          grpc:
            endpoint: 0.0.0.0:4317
          http:
            endpoint: 0.0.0.0:4318
    
    processors:
      batch:
        timeout: 5s
        send_batch_size: 1024
      memory_limiter:
        limit_mib: 4096
        spike_limit_mib: 1024
      attributes:
        actions:
        - key: environment
          value: production
          action: upsert
    
    exporters:
      otlp/jaeger:
        endpoint: jaeger-collector:4317
        tls:
          insecure: true
      prometheus:
        endpoint: 0.0.0.0:8889
      otlp/tempo:
        endpoint: tempo:4317
    
    service:
      pipelines:
        traces:
          receivers: [otlp]
          processors: [batch, memory_limiter, attributes]
          exporters: [otlp/jaeger, otlp/tempo]
        metrics:
          receivers: [otlp]
          processors: [batch]
          exporters: [prometheus]

---
# 应用侧: 自动注入 (OpenTelemetry Operator)
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
  name: otel-instrumentation
  namespace: production
spec:
  exporter:
    endpoint: http://otel-collector:4317
  sampler:
    type: parentbased_traceidratio
    argument: "0.1"                     # 10%采样率
  propagators:
  - tracecontext
  - baggage
  java:
    image: ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-java:1.32.0
  python:
    image: ghcr.io/open-telemetry/opentelemetry-operator/autoinstrumentation-python:0.43b0
  go:
    image: ghcr.io/open-telemetry/opentelemetry-go-instrumentation/autoinstrumentation-go:v0.10.0

# Pod注解自动注入
# instrumentation.opentelemetry.io/inject-java: "true"
# instrumentation.opentelemetry.io/inject-python: "true"

5. 安全等保

5.1 我做过哪些安全优化 (总览)

优化方向具体项目效果
Pod安全标准Pod Security Standards全覆盖特权容器从50+降到0
网络隔离NetworkPolicy零信任东西向攻击面缩小70%
镜像安全Trivy扫描 + cosign签名高危漏洞上线率0%
RBAC治理最小权限 + 审计超权ServiceAccount归零
运行时安全Falco运行时检测异常行为实时告警
等保2.0三级等保合规通过等保测评
密钥管理External Secrets + Vault明文密码清零
审计日志API Server审计 + 合规报告全操作可追溯

5.2 Pod Security Standards (PSS)

yaml
# 三级安全标准:
# privileged: 无限制 (仅系统组件)
# baseline:   最小限制 (防止已知提权)
# restricted: 最严格 (安全加固最佳实践)

# Namespace级别强制执行
apiVersion: v1
kind: Namespace
metadata:
  name: production
  labels:
    # 强制执行restricted级别
    pod-security.kubernetes.io/enforce: restricted
    pod-security.kubernetes.io/enforce-version: latest
    # 审计记录 (不阻止, 但记录)
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/audit-version: latest
    # 告警提示
    pod-security.kubernetes.io/warn: restricted
    pod-security.kubernetes.io/warn-version: latest

---
# restricted级别要求 (自动拒绝不合规Pod):
# - 禁止特权容器 (privileged: false)
# - 禁止hostNetwork/hostPID/hostIPC
# - 禁止hostPath挂载
# - 禁止特权端口 (<1024)
# - 必须runAsNonRoot: true
# - 必须readOnlyRootFilesystem: true (推荐)
# - 禁止所有capabilities (drop: ALL)
# - seccompProfile: RuntimeDefault 或 Localhost
# - allowPrivilegeEscalation: false

# 合规Pod示例
apiVersion: v1
kind: Pod
metadata:
  name: secure-app
  namespace: production
spec:
  securityContext:
    runAsNonRoot: true
    runAsUser: 1000
    runAsGroup: 1000
    fsGroup: 1000
    seccompProfile:
      type: RuntimeDefault
  containers:
  - name: app
    image: my-app:v1.0.0@sha256:abc123...   # 固定digest, 不用tag
    securityContext:
      allowPrivilegeEscalation: false
      readOnlyRootFilesystem: true
      capabilities:
        drop: ["ALL"]                        # 删除所有capabilities
    resources:
      requests:
        cpu: "500m"
        memory: "512Mi"
      limits:
        cpu: "2"
        memory: "2Gi"
    volumeMounts:
    - name: tmp
      mountPath: /tmp                        # 可写tmp目录
    - name: app-data
      mountPath: /data
  volumes:
  - name: tmp
    emptyDir:
      sizeLimit: 100Mi
  - name: app-data
    persistentVolumeClaim:
      claimName: app-data-pvc

5.3 镜像安全全链路

构建 → 扫描 → 签名 → 准入 → 运行时
  │      │      │      │       │
  │      │      │      │       └─ Falco运行时监控
  │      │      │      └─ OPA/Kyverno准入策略
  │      │      └─ Cosign签名验证
  │      └─ Trivy/Grype漏洞扫描
  └─ 多阶段构建, 最小化镜像
yaml
# Kyverno: 镜像准入策略
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: image-security-policy
spec:
  validationFailureAction: Enforce       # Enforce/Audit
  background: true
  rules:
  # 规则1: 禁止使用latest标签
  - name: deny-latest-tag
    match:
      any:
      - resources:
          kinds: [Pod]
    validate:
      message: "禁止使用latest标签, 请使用语义化版本"
      pattern:
        spec:
          containers:
          - image: "!*:latest"
  
  # 规则2: 必须使用可信镜像仓库
  - name: restrict-image-registries
    match:
      any:
      - resources:
          kinds: [Pod]
    validate:
      message: "镜像必须来自可信仓库"
      pattern:
        spec:
          containers:
          - image: "harbor.example.com/* | registry.k8s.io/*"
  
  # 规则3: 必须通过漏洞扫描
  - name: require-vulnerability-scan
    match:
      any:
      - resources:
          kinds: [Pod]
    validate:
      message: "镜像必须通过漏洞扫描 (无Critical/High漏洞)"
      deny:
        conditions:
          all:
          - key: "{{ images.containers.*.digest }}"
            operator: AnyNotIn
            value: "{{ scan_results.passed_images }}"
  
  # 规则4: 必须验证cosign签名
  - name: verify-image-signature
    match:
      any:
      - resources:
          kinds: [Pod]
          namespaces: ["production"]
    verifyImages:
    - imageReferences:
      - "harbor.example.com/*"
      attestors:
      - entries:
        - keys:
            publicKeys: |
              -----BEGIN PUBLIC KEY-----
              MFkwEwYHKoZIzj0CAQYIKoZ... (cosign公钥)
              -----END PUBLIC KEY-----
  
  # 规则5: 禁止特权容器
  - name: deny-privileged
    match:
      any:
      - resources:
          kinds: [Pod]
    validate:
      message: "禁止特权容器"
      pattern:
        spec:
          containers:
          - securityContext:
              privileged: "false"

---
# CI/CD中的镜像扫描 (Tekton Task)
apiVersion: tekton.dev/v1beta1
kind: Task
metadata:
  name: trivy-scan
spec:
  params:
  - name: image
    type: string
  - name: severity
    default: "CRITICAL,HIGH"
  steps:
  - name: scan
    image: aquasec/trivy:0.50.0
    script: |
      trivy image \
        --severity $(params.severity) \
        --exit-code 1 \
        --format table \
        $(params.image)
      # exit-code 1: 发现高危漏洞则失败, 阻止部署

5.4 RBAC最小权限治理

bash
# 1. 审计现有权限
# 查看所有ClusterRoleBinding
kubectl get clusterrolebinding -o json | jq -r '.items[] | 
  select(.roleRef.name == "cluster-admin") | .subjects[].name'

# 查看某ServiceAccount的权限
kubectl auth can-i --list --as=system:serviceaccount:production:app-sa

# 2. 识别过度授权
# 查找绑定了cluster-admin的ServiceAccount
kubectl get clusterrolebinding -o json | jq -r '
  .items[] | select(.roleRef.name == "cluster-admin") | 
  {name: .metadata.name, subjects: .subjects}
'
yaml
# 最小权限ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
  name: app-sa
  namespace: production
automountServiceAccountToken: false       # 不自动挂载Token

---
# 精确Role (仅允许读取ConfigMap和Secret)
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: app-reader
  namespace: production
rules:
- apiGroups: [""]
  resources: ["configmaps"]
  resourceNames: ["app-config"]          # 只允许访问指定ConfigMap
  verbs: ["get"]                         # 只读
- apiGroups: [""]
  resources: ["secrets"]
  resourceNames: ["app-secret"]          # 只允许访问指定Secret
  verbs: ["get"]

---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: app-reader-binding
  namespace: production
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: app-reader
subjects:
- kind: ServiceAccount
  name: app-sa
  namespace: production

---
# Pod使用指定ServiceAccount
apiVersion: v1
kind: Pod
metadata:
  name: app
  namespace: production
spec:
  serviceAccountName: app-sa
  automountServiceAccountToken: false
  containers:
  - name: app
    image: my-app:v1
    # 需要Token时通过ProjectedVolume显式挂载
    volumeMounts:
    - name: sa-token
      mountPath: /var/run/secrets/tokens
      readOnly: true
  volumes:
  - name: sa-token
    projected:
      sources:
      - serviceAccountToken:
          path: token
          audience: my-api              # 限定audience
          expirationSeconds: 3600       # 1小时过期

5.5 运行时安全 (Falco)

yaml
# Falco DaemonSet
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: falco
  namespace: falco
spec:
  template:
    spec:
      containers:
      - name: falco
        image: falcosecurity/falco:0.37.1
        securityContext:
          privileged: true               # Falco需要内核访问
        env:
        - name: FALCO_MODERN_BPF
          value: "true"                  # 使用eBPF探针
        volumeMounts:
        - name: boot
          mountPath: /host/boot
          readOnly: true
        - name: dev
          mountPath: /host/dev
        - name: proc
          mountPath: /host/proc
          readOnly: true

---
# Falco自定义规则
# falco_rules_local.yaml
custom_rules:
  # 检测容器内shell执行
  - rule: Terminal Shell in Container
    desc: 检测到容器内执行交互式shell
    condition: >
      spawned_process and container and
      shell_procs and proc.tty != 0
    output: >
      容器内Shell执行检测 (user=%user.name container=%container.name
      shell=%proc.name parent=%proc.pname cmdline=%proc.cmdline)
    priority: WARNING
    tags: [container, shell, mitre_execution]

  # 检测敏感文件读取
  - rule: Read Sensitive File
    desc: 检测到读取敏感文件
    condition: >
      open_read and container and
      (fd.name startswith /etc/shadow or
       fd.name startswith /etc/passwd or
       fd.name startswith /root/.ssh)
    output: >
      敏感文件读取 (user=%user.name file=%fd.name container=%container.name)
    priority: CRITICAL

  # 检测异常网络连接
  - rule: Outbound Connection to Crypto Mining
    desc: 检测到挖矿连接
    condition: >
      outbound and container and
      (fd.sip.name contains "mining" or
       fd.sport in (3333, 4444, 5555, 8888))
    output: >
      可疑挖矿连接 (container=%container.name dest=%fd.name)
    priority: CRITICAL

  # 检测K8s API异常调用
  - rule: K8s Service Account Token Misuse
    desc: 服务账号Token异常使用
    condition: >
      open_read and container and
      fd.name contains "serviceaccount/token" and
      not proc.name in (known_sa_consumers)
    output: >
      SA Token异常访问 (proc=%proc.name file=%fd.name container=%container.name)
    priority: WARNING

5.6 等保2.0三级合规 (K8s场景)

等保2.0 (网络安全等级保护2.0) 是中国强制性安全标准, K8s平台需要通过三级等保测评。

5.6.1 等保要求与K8s对照表

等保要求控制项K8s实施方案工具
身份鉴别用户身份认证OIDC/LDAP集成, 2FADex + OpenLDAP
身份鉴别登录失败处理登录限制+锁定Dex rate limiting
身份鉴别鉴别信息传输加密TLS全链路加密cert-manager
访问控制最小权限RBAC精细化Kyverno策略
访问控制默认拒绝NetworkPolicy零信任Cilium NP
访问控制特权账号管理cluster-admin审计audit-log + OPA
安全审计操作审计API Server审计日志审计日志 + Fluentd
安全审计审计日志保护日志不可篡改日志写入WORM存储
入侵防范最小安装精简节点组件最小化OS + 关闭非必要端口
入侵防范漏洞管理定期扫描+补丁Trivy + 节点补丁
入侵防范恶意代码防范镜像扫描+签名Trivy + cosign
入侵防范运行时检测容器行为监控Falco
数据完整性传输完整性TLS 1.3cert-manager
数据保密性敏感数据加密Secret加密存储Sealed Secrets + Vault
数据保密性数据备份恢复定时备份+异地容灾Velero
个人信息保护数据脱敏日志脱敏+数据分类Fluentd filter

5.6.2 等保关键实施细节

1. 身份鉴别 - OIDC集成

yaml
# kube-apiserver启动参数
--oidc-issuer-url=https://dex.example.com
--oidc-client-id=kubernetes
--oidc-username-claim=email
--oidc-groups-claim=groups
--oidc-ca-file=/etc/kubernetes/pki/dex-ca.crt

# Dex OIDC配置
apiVersion: dex.coreos.com/v1
kind: OAuth2Client
metadata:
  name: kubernetes
spec:
  redirectURIs:
  - https://login.example.com/callback
  public: false
  secretEnv: CLIENT_SECRET

2. 审计日志 - 等保要求全覆盖

yaml
# API Server审计策略
apiVersion: audit.k8s.io/v1
kind: Policy
rules:
# 记录所有写操作
- level: RequestResponse
  verbs: ["create", "update", "patch", "delete"]
  resources:
  - group: ""
    resources: ["pods", "services", "configmaps", "secrets"]
  - group: "apps"
    resources: ["deployments", "statefulsets", "daemonsets"]
  - group: "rbac.authorization.k8s.io"
    resources: ["*"]                    # RBAC变更全记录

# 记录所有认证事件
- level: Metadata
  resources:
  - group: ""
    resources: ["*"]
  users: ["system:anonymous"]

# Secret读取记录
- level: RequestResponse
  resources:
  - group: ""
    resources: ["secrets"]
  verbs: ["get", "list", "watch"]

# 默认: 元数据级别
- level: Metadata
  omitStages:
  - RequestReceived
yaml
# kube-apiserver审计日志配置
--audit-policy-file=/etc/kubernetes/audit-policy.yaml
--audit-log-path=/var/log/kubernetes/audit.log
--audit-log-maxage=365                   # 保留365天 (等保要求>=180天)
--audit-log-maxbackup=100
--audit-log-maxsize=200                  # 200MB per file
--audit-log-mode=batch                   # 批量写入, 高性能
--audit-log-batch-max-size=2000
--audit-log-batch-buffer-size=2000

3. 数据加密 - Secret at Rest

yaml
# kube-apiserver加密配置
# encryption-config.yaml
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
  - secrets
  - configmaps                          # 也加密ConfigMap
  providers:
  - aescbc:                             # AES-CBC加密
      keys:
      - name: key1
        secret: <base64-encoded-32-byte-key>
  - identity: {}                        # fallback (明文, 解密旧数据用)

# kube-apiserver启动参数
--encryption-provider-config=/etc/kubernetes/encryption-config.yaml
--encryption-provider-config-automatic-reload=true

4. TLS全链路加密

全链路TLS:
  用户 → LB(TLS) → Ingress(TLS) → Service(mTLS) → Pod
  
  ① Ingress TLS: cert-manager自动签发
  ② Service Mesh mTLS: Istio/Cilium自动管理
  ③ etcd TLS: 证书双向认证
  ④ kubelet TLS: 证书双向认证
  ⑤ API Server TLS: 证书双向认证
yaml
# cert-manager自动签发证书
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: web-api-cert
  namespace: production
spec:
  secretName: web-api-tls
  issuerRef:
    name: letsencrypt-prod            # 或内部CA
    kind: ClusterIssuer
  dnsNames:
  - api.example.com
  - api.internal.example.com
  duration: 2160h                      # 90天
  renewBefore: 720h                    # 30天前续期

---
# Cilium mTLS (Transparent Encryption)
apiVersion: cilium.io/v2
kind: CiliumClusterwideEnvoyConfig
metadata:
  name: mtls-policy
spec:
  resources:
  - "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
    common_tls_context:
      tls_params:
        tls_minimum_protocol_version: TLSv1_3

5. 节点安全加固

bash
# OS级安全加固 (等保三级要求)
# 1. 关闭不必要端口和服务
systemctl disable bluetooth cups avahi-daemon
systemctl stop bluetooth cups avahi-daemon

# 2. SSH加固
sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/#MaxAuthTries 6/MaxAuthTries 3/' /etc/ssh/sshd_config
sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config

# 3. 内核安全参数
sysctl -w <<EOF
kernel.randomize_va_space=2            # ASLR
net.ipv4.conf.all.rp_filter=1          # 反向路径过滤
net.ipv4.conf.all.accept_redirects=0   # 禁止ICMP重定向
net.ipv4.conf.all.send_redirects=0     # 禁止发送重定向
net.ipv4.ip_forward=1                  # K8s需要
net.ipv4.conf.all.accept_source_route=0 # 禁止源路由
net.ipv4.tcp_syncookies=1              # SYN Flood保护
kernel.dmesg_restrict=1                # 限制dmesg访问
kernel.kptr_restrict=2                 # 隐藏内核指针
EOF

# 4. 文件系统安全
chmod 700 /root
chmod 600 /etc/shadow
chattr +i /etc/passwd                   # 不可变 (需维护时解除)
chattr +i /etc/group

# 5. 审计daemon
systemctl enable auditd
systemctl start auditd
# /etc/audit/rules.d/k8s.rules
-w /etc/kubernetes -p wa -k k8s-config-change
-w /var/lib/kubelet -p wa -k kubelet-change
-w /etc/docker -p wa -k docker-change

6. 面试高频追问与应答

6.1 网络方向

Q: Calico BGP和IPIP模式有什么区别? 什么场景选哪个?

BGP Direct Routing (同L2/同子网):

  • Pod流量直接路由, 不封装, 性能最好
  • 需要底层网络支持BGP (交换机/路由器配BGP)
  • Pod IP需要在网络中可路由
  • 适用: 裸金属集群, 自建机房, 同L2网络

IPIP/VXLAN封装 (跨L3):

  • Pod流量封装在宿主机IP中, 不依赖底层网络
  • 封装有5-10%性能开销 (IPIP< VxLAN)
  • 适用: 云厂商环境, 跨子网/跨AZ

我的实践: 生产用BGP Direct (裸金属, 性能优先), 开发测试用VxLAN (云环境, 简单易管理)

Q: 大规模下DNS解析慢怎么优化?

优化链路: NodeLocal DNSCache → CoreDNS调优 → 上游DNS优化

  1. NodeLocal DNSCache (最有效):

    • 每个节点本地DNS缓存, 监听169.254.20.10
    • 消除conntrack冲突 (UDP DNS是stateless的, 大量相同源端口导致冲突)
    • 延迟从120ms降到<5ms
  2. CoreDNS调优:

    • HPA扩副本 (CPU 60%触发)
    • cache插件: success 65536/30s, denial 8192/5s
    • 分离CoreDNS Pod到专用节点 (高优先级)
  3. 应用层优化:

    • DNS TTL感知: 客户端缓存 + 连接池
    • ndots优化: ndots:2 (减少无效搜索域查询)
    yaml
    dnsConfig:
      options:
      - name: ndots
        value: "2"           # 默认5, 导致每个短域名查询5次
      - name: single-request-reopen
        value: ""            # 避免IPv4/IPv6并发问题
      - name: timeout
        value: "2"
      - name: attempts
        value: "2"

6.2 存储方向

Q: RWO和RWX存储分别用什么方案?

RWO (ReadWriteOnce): 块存储

  • Ceph RBD: 高性能, 支持快照/克隆
  • AWS EBS / 阿里云ESSD: 云盘
  • 适用: 数据库, 有状态服务

RWX (ReadWriteMany): 文件存储/对象存储

  • CephFS: POSIX兼容, 多读多写
  • NFS: 简单但不推荐生产 (单点)
  • JuiceFS: 对象存储+元数据引擎, 高性能RWX
  • 适用: AI训练共享数据, 日志采集, 配置共享

我的实践:

  • 数据库: Ceph RBD (RWO, NVMe池)
  • AI训练数据: JuiceFS (RWX, S3+本地缓存)
  • 日志: CephFS (RWX, SSD池)
  • 配置: ConfigMap (不挂载PV)

Q: 如何实现PVC动态扩容?

yaml
# 1. StorageClass允许扩容
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: ceph-rbd-ssd
provisioner: rbd.csi.ceph.com
allowVolumeExpansion: true          # 关键!

# 2. 扩容PVC
kubectl patch pvc database-data -p '{"spec":{"resources":{"requests":{"storage":"1Ti"}}}}'

# 3. 文件系统自动扩容 (CSI driver支持)
# Ceph RBD CSI自动resize fs, 无需手动操作
# 有些CSI需要Pod重启才能生效

6.3 调度方向

Q: HPA延迟大怎么优化?

优化链路: 指标采集延迟 → 伸缩决策延迟 → Pod启动延迟 → 流量切换延迟

  1. 缩短指标采集周期:

    • metrics-server: --metric-resolution=15s (默认60s)
    • Prometheus: scrape_interval: 15s
  2. 缩短HPA决策周期:

    yaml
    behavior:
      scaleUp:
        stabilizationWindowSeconds: 0    # 扩容不等待
        policies:
        - type: Percent
          value: 100                     # 一次翻倍
          periodSeconds: 15

3. **加速Pod启动:**
 - 镜像预拉取 (ImagePullJob/Eraser)
 - 多阶段构建减小镜像 (<100MB)
 - 使用init container预热
 - 优化应用启动时间 (lazy init, 异步加载)

4. **流量平滑切换:**
 - readiness probe确保Pod就绪才接流量
 - 使用Istio做流量渐进

Q: 如何防止缩容导致服务抖动?

  1. 缩容冷却:

    yaml
    behavior:
      scaleDown:
        stabilizationWindowSeconds: 300  # 5分钟稳定才缩
        policies:
        - type: Pods
          value: 2                       # 每次最多缩2个
          periodSeconds: 120
  2. PDB保护:

    yaml
    maxUnavailable: 10%                  # 最多10%不可用
  3. 优雅终止:

    • preStop Hook: sleep 30s (等endpoint更新)
    • terminationGracePeriodSeconds: 120
    • 应用内优雅关闭: 先摘LB, 再排空连接

6.4 监控方向

Q: 监控数据量太大, Prometheus扛不住怎么办?

  1. 指标裁剪:

    • 丢弃不需要的指标 (metric_relabel_configs drop)
    • 降低采集频率 (15s → 30s)
    • 限制高基数标签 (避免pod_name, container_id做标签)
  2. 分片采集:

    • 多个Prometheus实例, 按namespace/集群分片
    • 使用Prometheus Agent模式 (只采集不存储)
  3. 长期存储:

    • Thanos Sidecar → S3长期存储
    • 本地只保留7天, 历史查S3
  4. 替代方案:

    • VictoriaMetrics: 单实例性能比Prometheus高3-5x
    • Cortex: 水平扩展Prometheus

Q: 如何建设有效的告警体系?

我的方法论: 少而精 > 多而乱

  1. 告警分级: P0(立即)/P1(15min)/P2(1h)/P3(24h)
  2. 告警抑制: 根因告警发出后, 抑制衍生告警
  3. 告警静默: 维护窗口/已知问题设置静默
  4. 告警路由: 不同级别不同通道 (PagerDuty/钉钉/邮件)
  5. 告警复盘: 每周统计有效告警率, 清理无效告警

关键指标: 告警噪音比 < 20% (80%以上的告警需要行动) 如果 <50%, 说明告警太多, 需要治理

6.5 安全方向

Q: K8s中如何防止容器逃逸?

多层防护:

  1. Pod Security Standards (第一层):

    • restricted级别禁止privileged, hostPath, hostNetwork
    • 强制runAsNonRoot, drop ALL capabilities
  2. seccomp Profile (第二层):

    yaml
    securityContext:
      seccompProfile:
        type: RuntimeDefault             # 或自定义Profile
    • 限制容器可调用的系统调用
  3. AppArmor/SELinux (第三层):

    • 强制访问控制, 限制文件/网络访问
  4. gVisor/Kata (第四层, 强隔离):

    • gVisor: 用户态内核, 拦截系统调用
    • Kata: 轻量VM, 硬件级隔离
    • 适用: 多租户, 运行不可信代码
  5. 运行时检测 (Falco):

    • 检测异常行为: shell执行, 敏感文件访问, 异常网络连接

Q: 如何通过等保三级测评?

我主导过一次等保三级测评, 主要工作:

  1. 差距分析 (2周): 对照等保要求逐项检查, 输出差距清单
  2. 整改实施 (4周):
    • 身份鉴别: 接入OIDC+2FA, 禁止密码登录
    • 访问控制: RBAC最小化, NetworkPolicy全覆盖
    • 安全审计: 审计日志全覆盖, 保留365天
    • 入侵防范: Falco+Trivy+节点加固
    • 数据加密: TLS全链路+Secret at Rest加密
  3. 文档准备 (2周): 安全管理制度, 操作规程, 应急预案
  4. 测评配合 (1周): 配合测评机构, 提供证据

最终得分: 89分 (合格线: 70分), 无高危项


附录: 五大领域优化效果总结

领域关键项目量化效果
网络Cilium eBPF + NodeLocal DNSService延迟-98%, DNS延迟-96%
存储分层存储 + JuiceFS缓存存储成本-50%, AI训练3x加速
调度Koordinator混部 + KarpenterCPU利用率30%→65%, 成本-40%
监控Thanos联邦 + 告警治理告警噪音-80%, 故障定位<5min
安全PSS + Falco + 等保2.0特权容器归零, 通过等保三级

面试建议:

  • 每个领域准备1-2个深度案例, 带数据
  • 强调"为什么这么做" (trade-off分析)
  • 展示系统性思维: 不是单点优化, 而是体系化建设
  • 诚实面对不足: "还有哪些没做好, 后续计划是什么"

本手册配合 面试手册模拟面试手册 使用