K8s(7)知识(3) Pod亲和性,调度,生命周期
一、 Pod 调度策略深度解析
Kubernetes 的默认调度器(default-scheduler)通过三个核心步骤将 Pod 分配到节点上:
-
预选(Predicates):排除不满足基本条件的节点(如内存不足、端口冲突)。
-
优选(Priorities):在剩余节点中,根据权重进行打分(如选择资源利用率低的节点)。
-
绑定:将 Pod 绑定到得分最高的节点。
除了默认的调度逻辑,我们可以通过以下策略控制 Pod 的去向:
1. 节点标签与调度
-
指定节点名称调度(硬指定)
-
特点:绕过调度器,强制 Pod 运行在特定节点。
-
场景:测试环境或特殊硬件需求的节点。
-
配置:在
spec.nodeName中指定节点名。
-
-
指定节点标签调度(软指定)
-
特点:通过节点标签(Labels)进行匹配,需经过调度器。
-
逻辑步骤:
-
给节点打标签:
kubectl label nodes <node-name> <key>=<value> -
编辑 Pod YAML,使用
nodeSelector指定标签。
-
-
2. 亲和性策略(Affinity)
亲和性用于表达“偏好”或“强制要求”,分为节点亲和性(Node Affinity)和Pod 亲和性(Pod Affinity)。
-
节点亲和性 (
nodeAffinity)-
作用:让 Pod 倾向于运行在带有特定标签的节点上。
-
策略类型:
-
requiredDuringSchedulingIgnoredDuringExecution:硬策略,必须满足,否则 Pod 处于 Pending 状态。 -
preferredDuringSchedulingIgnoredDuringExecution:软策略,尽量满足,不满足也能运行。
-
-
匹配逻辑(操作符):
-
In,NotIn:包含/不包含(最常用)。 -
Exists,DoesNotExist:存在/不存在(只需判断键,无需值)。 -
Gt,Lt:大于/小于(针对整数值)。
-
-
-
Pod 亲和性 (
podAffinity)-
作用:让 Pod 倾向于与其他 Pod 运行在同一拓扑域(如同一节点、同一可用区)。
-
场景:微服务间的低延迟通信(如前端与后端同节点)。
-
反亲和性 (
podAntiAffinity):让 Pod 尽量不与其他 Pod 运行在同一拓扑域。 -
核心配置:
-
labelSelector:选择哪些 Pod 的标签作为参照。 -
topologyKey:定义“拓扑域”的键(通常使用kubernetes.io/hostname表示节点级别,或使用云平台标签表示可用区级别)。
-
-
3. 实战示例
-
示例 1:节点亲和性(软策略)
yaml
yaml
affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 preference: matchExpressions: - key: env operator: In values: [ "production" ]-
解释:尽量将 Pod 调度到
env=production的节点,如果没有,也可以运行在其他节点。
-
-
示例 2:Pod 反亲和性(硬策略)
yaml
yaml
affinity: podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app operator: In values: [ "myapp" ] topologyKey: kubernetes.io/hostname-
解释:强制要求同一个节点上不能运行两个
app=myapp的 Pod(实现高可用,避免单点故障)。
-
二、 污点与容忍度(Taints & Tolerations)
污点是节点的属性,用于排斥 Pod;容忍度是 Pod 的属性,用于允许被调度到有污点的节点。
1. 污点的作用
-
NoSchedule:不将 Pod 调度到带有该污点的节点(除非 Pod 有容忍度)。
-
PreferNoSchedule:尽量避免调度,但不是强制。
-
NoExecute:不调度新 Pod,并驱逐节点上已有的 Pod(除非 Pod 有容忍度)。
2. 设置污点
bash
bash
kubectl taint node <node-name> <key>=<value>:<effect>
-
示例:
bash
bash
kubectl taint node k8s-node01 key1=value1:NoSchedule
3. 容忍度(Tolerations)
在 Pod 的 YAML 中添加 tolerations字段,允许 Pod 被调度到有特定污点的节点。
-
配置示例:
yaml
yaml
tolerations: - key: "key1" operator: "Equal" value: "value1" effect: "NoSchedule" -
解释:该 Pod 可以容忍
key1=value1:NoSchedule的污点,因此可以被调度到k8s-node01。
4. 典型应用场景
-
专用节点:给 GPU 节点打上
dedicated=gpu:NoSchedule污点,只有带有容忍度的 Pod(如 AI 训练任务)才能运行。 -
维护模式:给节点打上
maintenance=true:NoExecute污点,驱逐所有非必要 Pod,进行维护。 -
弹性伸缩:在云平台上,通过污点标记节点即将被销毁,让 Pod 自动迁移。
四、Pod 生命周期(Lifecycle)深度解析
调度完成 ≠ Pod 可用,Pod 生命周期决定了容器何时启动、何时就绪、何时销毁。
1️⃣ Pod 的状态流转(Phase)
|
状态 |
说明 |
|---|---|
|
|
Pod 已被创建,但尚未调度成功或镜像未拉取 |
|
|
正在创建容器 |
|
|
至少一个容器正在运行 |
|
|
所有容器正常退出(适用于 Job) |
|
|
至少一个容器非正常退出 |
|
|
无法获取 Pod 状态(通常是节点失联) |
📌 调度发生在 Pending 阶段
2️⃣ 容器状态(ContainerStatus)
bash
bash
kubectl describe pod <pod-name>
|
状态 |
含义 |
|---|---|
|
|
等待启动(镜像拉取、初始化) |
|
|
容器正在运行 |
|
|
容器已退出 |
常见原因:
-
ImagePullBackOff -
CrashLoopBackOff -
Completed
3️⃣ Pod 生命周期核心阶段
纯文本
纯文本
Pod 创建
↓
调度(Scheduler)
↓
Pod 进入 Pending
↓
Init Container(初始化容器)
↓
主容器启动
↓
PostStart Hook(可选)
↓
Readiness Probe 成功 → 接收流量
↓
Liveness Probe 失败 → 重启容器
↓
PreStop Hook(可选)
↓
Pod 删除 / 驱逐
4️⃣ Init Container(初始化容器)
✅ 在主容器启动前执行,按顺序运行
特点:
-
必须全部成功才会启动主容器
-
常用于:
-
数据库初始化
-
配置文件准备
-
依赖服务等待
-
yaml
yaml
spec:
initContainers:
- name: init-db
image: busybox
command: ["sh", "-c", "until nslookup mysql; do sleep 2; done"]
5️⃣ 容器探针(Probes)—— 决定 Pod 是否“可用”
✅ 三种探针
|
探针 |
作用 |
|---|---|
|
|
判断容器是否存活(失败则重启) |
|
|
判断容器是否就绪(失败则摘除流量) |
|
|
防止慢启动应用被误判为失败 |
示例
yaml
yaml
livenessProbe:
httpGet:
path: /health
port: 8080
periodSeconds: 10
readinessProbe:
tcpSocket:
port: 8080
initialDelaySeconds: 5
📌 调度器不关心探针结果,Service 才关心 Readiness
6️⃣ 生命周期钩子(Hooks)
|
Hook |
触发时机 |
|---|---|
|
|
容器启动后立即执行 |
|
|
容器终止前执行 |
yaml
yaml
lifecycle:
postStart:
exec:
command: ["sh", "-c", "echo Hello > /tmp/hello"]
preStop:
exec:
command: ["sh", "-c", "sleep 10"]
📌 优雅删除 Pod 的关键机制
7️⃣ Pod 删除流程(Graceful Shutdown)
纯文本
纯文本
kubectl delete pod
↓
Pod 标记为 Terminating
↓
执行 preStop Hook
↓
发送 SIGTERM
↓
等待 terminationGracePeriodSeconds(默认 30s)
↓
发送 SIGKILL
yaml
yaml
spec:
terminationGracePeriodSeconds: 60
8️⃣ 重启策略(RestartPolicy)
|
策略 |
行为 |
|---|---|
|
|
容器退出即重启 |
|
|
非 0 退出码才重启 |
|
|
永不重启 |
yaml
yaml
spec:
restartPolicy: OnFailure
📌 Job / CronJob 必须使用 Never 或 OnFailure
9️⃣ 生命周期与调度、亲和性的关系
|
组件 |
关注点 |
|---|---|
|
Scheduler |
只关心 调度前 |
|
Lifecycle |
关注 调度后 → 运行 → 销毁 |
|
Affinity |
影响 Pod 去哪 |
|
Probe |
影响 Pod 是否可用 |
|
Taint/Toleration |
影响 是否允许调度 |
🔟 总结速记表
|
阶段 |
关键机制 |
|---|---|
|
调度前 |
亲和性、污点、资源请求 |
|
启动期 |
InitContainer、postStart |
|
运行期 |
liveness / readiness / startup |
|
删除期 |
preStop、SIGTERM、优雅下线 |
三、 综合实战场景
场景:我们有一个 Redis 集群,希望:
-
Redis Pod 尽量运行在可用区 A(杭州)。
-
Redis Pod 之间不能运行在同一节点(避免单点故障)。
-
只有带有
redis-role=master标签的节点才能运行 Redis Pod。
YAML 配置:
yaml
yaml
apiVersion: v1
kind: Pod
metadata:
name: redis-pod
labels:
app: redis
spec:
containers:
- name: redis
image: redis:latest
affinity:
# 1. 节点亲和性:尽量运行在可用区A(假设可用区A的标签是 zone=hangzhou)
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: zone
operator: In
values: [ "hangzhou" ]
# 2. Pod反亲和性:不能运行在同一节点
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values: [ "redis" ]
topologyKey: kubernetes.io/hostname
# 3. 节点亲和性(硬策略):必须运行在带有 redis-role=master 标签的节点
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- matchExpressions:
- key: redis-role
operator: In
values: [ "master" ]
四、 总结
|
概念 |
作用 |
方向 |
示例 |
|---|---|---|---|
|
节点亲和性 |
Pod 倾向于运行在特定标签的节点 |
Pod → Node |
|
|
Pod 亲和性 |
Pod 倾向于与其他 Pod 同拓扑域 |
Pod → Pod |
同节点、同可用区 |
|
Pod 反亲和性 |
Pod 倾向于不与其他 Pod 同拓扑域 |
Pod → Pod |
不同节点、不同可用区 |
|
污点 (Taint) |
节点排斥 Pod |
Node → Pod |
|
|
容忍度 (Toleration) |
Pod 允许被调度到有污点的节点 |
Pod → Node |
容忍 |
通过合理组合亲和性和污点,可以实现复杂的调度策略,满足生产环境的高可用、资源隔离、成本优化等需求。
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐

所有评论(0)