主题
K8s 架构师五大领域深度优化实战手册
目录
1. 网络方案优化
1.1 我做过哪些网络优化 (总览)
| 优化方向 | 具体项目 | 效果 |
|---|---|---|
| CNI升级替换 | Calico iptables → Cilium eBPF | Service延迟降低80%, CPU开销减少40% |
| DNS优化 | 启用NodeLocal DNSCache + CoreDNS调优 | DNS解析P99从120ms降到5ms |
| Service优化 | iptables → IPVS, 连接池优化 | 大规模Service下性能恒定 |
| NetworkPolicy | 全集群网络策略治理 | 攻击面缩小70% |
| 多网络平面 | Multus CNI, 管理/业务/存储网络分离 | 网络隔离, 带宽保障 |
| Ingress/Gateway | Nginx Ingress → Envoy Gateway | HTTP/2, gRPC原生支持, 可观测性增强 |
| Service Mesh | Istio 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节点池
# 旧业务按命名空间分批迁移
# 最后下线CalicoCilium关键优化配置:
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连接延迟P99 | 52ms | 0.8ms | -98% |
| kube-proxy CPU | 2.3核 | 0 (被替代) | -100% |
| iptables规则数 | 300,000+ | 0 | -100% |
| 新建连接吞吐 | 50K/s | 200K/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: 5msyaml
# 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: 60DNS优化效果:
| 指标 | 优化前 | 优化后 |
|---|---|---|
| DNS解析P99 | 120ms | <5ms |
| conntrack冲突 | 频繁 | 消除 |
| CoreDNS QPS | 50K | 200K+ |
| 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: Retain2.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缓存加速效果:
| 指标 | 直接读OSS | JuiceFS缓存 | 提升 |
|---|---|---|---|
| 首次读取 | 50MB/s | 50MB/s | 1x |
| 二次读取 | 50MB/s | 2000MB/s | 40x |
| Epoch训练时间 | 45min | 12min | 3.75x |
| 总训练时间 | 24h | 8h | 3x |
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: OnFailure2.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-202608223. 调度资源均衡优化
3.1 我做过哪些调度优化 (总览)
| 优化方向 | 具体项目 | 效果 |
|---|---|---|
| 在离线混部 | Koordinator混部方案 | CPU利用率30%→65% |
| Binpack调度 | 紧凑调度减少碎片 | 节点利用率提升25% |
| 拓扑感知 | NUMA/GPU拓扑感知 | 分布式训练性能提升35% |
| Gang Scheduling | Volcano 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延迟 | 15ms | 16ms | 无影响 |
| 离线任务完成率 | 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: true3.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: 1203.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: 84. 监控可观测性优化
4.1 我做过哪些监控优化 (总览)
| 优化方向 | 具体项目 | 效果 |
|---|---|---|
| 指标采集 | Prometheus联邦 + Thanos | 跨集群统一监控, 90天保留 |
| 告警治理 | 告警分级 + 静默 + 抑制 | 告警噪音降低80% |
| 日志优化 | EFK → Loki | 存储成本降低70% |
| 链路追踪 | Jaeger + OpenTelemetry | 故障定位时间<5分钟 |
| SLO体系 | SLI/SLO定义 + Error Budget | 可用性从99.9%→99.97% |
| GPU监控 | DCGM Exporter | GPU利用率/温度/功耗可视化 |
| 大盘建设 | 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: xxxPrometheus性能调优:
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-14.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-pvc5.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: WARNING5.6 等保2.0三级合规 (K8s场景)
等保2.0 (网络安全等级保护2.0) 是中国强制性安全标准, K8s平台需要通过三级等保测评。
5.6.1 等保要求与K8s对照表
| 等保要求 | 控制项 | K8s实施方案 | 工具 |
|---|---|---|---|
| 身份鉴别 | 用户身份认证 | OIDC/LDAP集成, 2FA | Dex + 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.3 | cert-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_SECRET2. 审计日志 - 等保要求全覆盖
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:
- RequestReceivedyaml
# 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=20003. 数据加密 - 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=true4. 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_35. 节点安全加固
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-change6. 面试高频追问与应答
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优化
NodeLocal DNSCache (最有效):
- 每个节点本地DNS缓存, 监听169.254.20.10
- 消除conntrack冲突 (UDP DNS是stateless的, 大量相同源端口导致冲突)
- 延迟从120ms降到<5ms
CoreDNS调优:
- HPA扩副本 (CPU 60%触发)
- cache插件: success 65536/30s, denial 8192/5s
- 分离CoreDNS Pod到专用节点 (高优先级)
应用层优化:
- DNS TTL感知: 客户端缓存 + 连接池
- ndots优化:
ndots:2(减少无效搜索域查询)yamldnsConfig: 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启动延迟 → 流量切换延迟
缩短指标采集周期:
- metrics-server:
--metric-resolution=15s(默认60s)- Prometheus:
scrape_interval: 15s缩短HPA决策周期:
yamlbehavior: scaleUp: stabilizationWindowSeconds: 0 # 扩容不等待 policies: - type: Percent value: 100 # 一次翻倍 periodSeconds: 153. **加速Pod启动:** - 镜像预拉取 (ImagePullJob/Eraser) - 多阶段构建减小镜像 (<100MB) - 使用init container预热 - 优化应用启动时间 (lazy init, 异步加载) 4. **流量平滑切换:** - readiness probe确保Pod就绪才接流量 - 使用Istio做流量渐进
Q: 如何防止缩容导致服务抖动?
缩容冷却:
yamlbehavior: scaleDown: stabilizationWindowSeconds: 300 # 5分钟稳定才缩 policies: - type: Pods value: 2 # 每次最多缩2个 periodSeconds: 120PDB保护:
yamlmaxUnavailable: 10% # 最多10%不可用优雅终止:
- preStop Hook: sleep 30s (等endpoint更新)
- terminationGracePeriodSeconds: 120
- 应用内优雅关闭: 先摘LB, 再排空连接
6.4 监控方向
Q: 监控数据量太大, Prometheus扛不住怎么办?
指标裁剪:
- 丢弃不需要的指标 (metric_relabel_configs drop)
- 降低采集频率 (15s → 30s)
- 限制高基数标签 (避免pod_name, container_id做标签)
分片采集:
- 多个Prometheus实例, 按namespace/集群分片
- 使用Prometheus Agent模式 (只采集不存储)
长期存储:
- Thanos Sidecar → S3长期存储
- 本地只保留7天, 历史查S3
替代方案:
- VictoriaMetrics: 单实例性能比Prometheus高3-5x
- Cortex: 水平扩展Prometheus
Q: 如何建设有效的告警体系?
我的方法论: 少而精 > 多而乱
- 告警分级: P0(立即)/P1(15min)/P2(1h)/P3(24h)
- 告警抑制: 根因告警发出后, 抑制衍生告警
- 告警静默: 维护窗口/已知问题设置静默
- 告警路由: 不同级别不同通道 (PagerDuty/钉钉/邮件)
- 告警复盘: 每周统计有效告警率, 清理无效告警
关键指标: 告警噪音比 < 20% (80%以上的告警需要行动) 如果 <50%, 说明告警太多, 需要治理
6.5 安全方向
Q: K8s中如何防止容器逃逸?
多层防护:
Pod Security Standards (第一层):
- restricted级别禁止privileged, hostPath, hostNetwork
- 强制runAsNonRoot, drop ALL capabilities
seccomp Profile (第二层):
yamlsecurityContext: seccompProfile: type: RuntimeDefault # 或自定义Profile
- 限制容器可调用的系统调用
AppArmor/SELinux (第三层):
- 强制访问控制, 限制文件/网络访问
gVisor/Kata (第四层, 强隔离):
- gVisor: 用户态内核, 拦截系统调用
- Kata: 轻量VM, 硬件级隔离
- 适用: 多租户, 运行不可信代码
运行时检测 (Falco):
- 检测异常行为: shell执行, 敏感文件访问, 异常网络连接
Q: 如何通过等保三级测评?
我主导过一次等保三级测评, 主要工作:
- 差距分析 (2周): 对照等保要求逐项检查, 输出差距清单
- 整改实施 (4周):
- 身份鉴别: 接入OIDC+2FA, 禁止密码登录
- 访问控制: RBAC最小化, NetworkPolicy全覆盖
- 安全审计: 审计日志全覆盖, 保留365天
- 入侵防范: Falco+Trivy+节点加固
- 数据加密: TLS全链路+Secret at Rest加密
- 文档准备 (2周): 安全管理制度, 操作规程, 应急预案
- 测评配合 (1周): 配合测评机构, 提供证据
最终得分: 89分 (合格线: 70分), 无高危项
附录: 五大领域优化效果总结
| 领域 | 关键项目 | 量化效果 |
|---|---|---|
| 网络 | Cilium eBPF + NodeLocal DNS | Service延迟-98%, DNS延迟-96% |
| 存储 | 分层存储 + JuiceFS缓存 | 存储成本-50%, AI训练3x加速 |
| 调度 | Koordinator混部 + Karpenter | CPU利用率30%→65%, 成本-40% |
| 监控 | Thanos联邦 + 告警治理 | 告警噪音-80%, 故障定位<5min |
| 安全 | PSS + Falco + 等保2.0 | 特权容器归零, 通过等保三级 |
面试建议:
- 每个领域准备1-2个深度案例, 带数据
- 强调"为什么这么做" (trade-off分析)
- 展示系统性思维: 不是单点优化, 而是体系化建设
- 诚实面对不足: "还有哪些没做好, 后续计划是什么"