一、K8s资源调度那些事儿
咱们玩Kubernetes的都知道,集群资源就像小区停车位——有限且抢手。怎么让Pod停到最合适的"车位"上?今天咱们就聊聊调度优化的三大法宝:亲和性配置、污点容忍和PriorityClass。
举个栗子,假设你有个电商应用,订单服务(order-service)和Redis缓存最好部署在同一个节点上减少网络延迟。这时候就需要亲和性配置:
# 技术栈:Kubernetes 1.24+
apiVersion: apps/v1
kind: Deployment
metadata:
name: order-service
spec:
template:
spec:
affinity:
podAffinity: # Pod亲和性
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values: ["redis-cache"] # 必须和redis-cache同节点
topologyKey: kubernetes.io/hostname
二、亲和性配置的七十二变
亲和性分两种:硬亲和(required)和软亲和(preferred)。硬亲和就像强制婚配,不满足条件就罢工;软亲和则是优先考虑,实在不行也能凑合。
再看个复杂点的例子——让日志收集器(filebeat)避开数据库节点:
# 技术栈:Kubernetes 1.20+
affinity:
podAntiAffinity: # Pod反亲和
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100 # 优先级权重
podAffinityTerm:
labelSelector:
matchLabels:
app: mysql
topologyKey: kubernetes.io/hostname
注意事项:
- topologyKey不要乱用,比如用zone做拓扑域可能导致跨机房调度
- 节点亲和性(nodeAffinity)更适合硬件绑定的场景,比如需要SSD的Pod
三、污点与容忍的生存法则
节点污点(Taint)就像挂了个"内有恶犬"的牌子,没有对应容忍度(Toleration)的Pod别想进来。典型场景:
# 给GPU节点打污点
kubectl taint nodes gpu-node-1 hardware=gpu:NoSchedule
# 技术栈:Kubernetes 1.18+
# 只有带这个容忍的Pod能调度到GPU节点
tolerations:
- key: "hardware"
operator: "Equal"
value: "gpu"
effect: "NoSchedule"
更灵活的用法是结合effect:
- NoSchedule:坚决不容忍
- PreferNoSchedule:尽量不调度
- NoExecute:已经运行的Pod也可能被驱逐
四、优先级管理的权力游戏
PriorityClass就像VIP卡,高优先级的Pod可以插队甚至挤走低优先级Pod。生产环境必备配置:
# 技术栈:Kubernetes 1.19+
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: mission-critical
value: 1000000 # 数值越大优先级越高
globalDefault: false
description: "关键业务Pod专用"
# 在Deployment中引用
priorityClassName: mission-critical
实战技巧:
- 系统预留优先级(system-cluster-critical)的值是2000000000
- 普通业务建议使用1000000-10000000区间
- 记得设置PodDisruptionBudget防止重要服务被意外驱逐
五、组合拳实战案例
来看个综合应用场景:某AI训练平台需要调度到带GPU的专属节点,且训练任务要优先于数据分析任务:
# 技术栈:Kubernetes 1.22+
apiVersion: apps/v1
kind: Deployment
metadata:
name: ai-training
spec:
template:
spec:
priorityClassName: gpu-task
tolerations:
- key: "nvidia.com/gpu"
operator: "Exists"
effect: "NoSchedule"
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: gpu-type
operator: In
values: ["a100"]
六、技术选型与避坑指南
应用场景对比:
- 亲和性:微服务拓扑管理、数据本地化
- 污点容忍:专用硬件调度、节点隔离
- 优先级:关键业务保障、资源抢占
常见坑点:
- 亲和性配置过多会导致调度性能下降(建议不超过5条规则)
- 没设置Pod反亲和可能导致单点故障(比如所有Redis实例挤在同一节点)
- 优先级滥用可能引发"优先级反转"问题
七、总结与最佳实践
经过这些年的实战,我总结出三条黄金法则:
- 像城市规划一样设计调度策略:重要服务放核心区,普通服务放郊区
- 给关键业务配置PriorityClass+PDB双保险
- 定期用kube-scheduler-simulator做调度策略测试
最后送大家一个诊断命令锦囊:
# 查看调度失败原因
kubectl describe pod <pod-name> | grep -A10 Events
# 模拟调度过程
kubectl get pods <pod-name> -o json | jq .spec | kubectl-scheduler-simulator
记住,好的调度策略就像优秀的交通管制,既要有规则也要留弹性空间。
评论