Pod 亲和性
学习目标
- 理解 Pod 亲和性和反亲和性的概念
- 掌握 podAffinity 和 podAntiAffinity 的使用
- 了解 topologyKey 的作用
核心概念
一句话解释
Pod 亲和性控制 Pod 之间的调度关系:亲和性让 Pod 靠近运行,反亲和性让 Pod 分散运行。
两种类型
┌─────────────────────────────────────────────────────────┐
│ Pod 亲和性类型 │
├─────────────────────────────────────────────────────────┤
│ │
│ podAffinity(亲和性) │
│ ┌─────────────────────────────────────────┐ │
│ │ 让 Pod 与其他 Pod 靠近运行 │ │
│ │ 例:Web 服务与 Redis 部署在同一节点 │ │
│ └─────────────────────────────────────────┘ │
│ │
│ podAntiAffinity(反亲和性) │
│ ┌─────────────────────────────────────────┐ │
│ │ 让 Pod 远离其他 Pod 运行 │ │
│ │ 例:同一服务的副本分散到不同节点 │ │
│ └─────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
YAML 语法
apiVersion: v1
kind: Pod
metadata:
name: my-pod
labels:
app: web
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- cache
topologyKey: kubernetes.io/hostname
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web
topologyKey: kubernetes.io/hostname
containers:
- name: web
image: nginx
topologyKey 解释
topologyKey 定义"靠近"或"远离"的范围
┌─────────────────────────────────────────────────────────┐
│ topologyKey 示例 │
├─────────────────────────────────────────────────────────┤
│ │
│ kubernetes.io/hostname │
│ ┌─────────────────────────────────────────┐ │
│ │ 范围:单个节点 │ │
│ │ 应用:Pod 部署在同一节点/不同节点 │ │
│ └─────────────────────────────────────────┘ │
│ │
│ topology.kubernetes.io/zone │
│ ┌─────────────────────────────────────────┐ │
│ │ 范围:同一可用区 │ │
│ │ 应用:Pod 分散到不同可用区 │ │
│ └─────────────────────────────────────────┘ │
│ │
│ kubernetes.io/os │
│ ┌─────────────────────────────────────────┐ │
│ │ 范围:同一操作系统 │ │
│ │ 应用:OS 特定工作负载 │ │
│ └─────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
亲和性示例
# 示例:Web 服务靠近 Redis 运行
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- redis
topologyKey: kubernetes.io/hostname
containers:
- name: web
image: nginx
反亲和性示例
# 示例:同一服务的副本分散到不同节点
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-ha
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web
topologyKey: kubernetes.io/hostname
containers:
- name: web
image: nginx
调度流程示例
场景:3 个 web 副本,使用 podAntiAffinity 分散到不同节点
现有集群:
┌─────────┬─────────┬─────────┐
│ Node1 │ Node2 │ Node3 │
│ │ │ │
└─────────┴─────────┴─────────┘
调度过程:
1. web-pod-1 → Node1(无反亲和性限制)
2. web-pod-2 → 检查反亲和性
- Node1: 有 app=web 的 Pod,不满足
- Node2: 无 app=web 的 Pod,满足 → 调度到 Node2
3. web-pod-3 → 检查反亲和性
- Node1: 有 app=web 的 Pod,不满足
- Node2: 有 app=web 的 Pod,不满足
- Node3: 无 app=web 的 Pod,满足 → 调度到 Node3
结果:
┌─────────┬─────────┬─────────┐
│ Node1 │ Node2 │ Node3 │
│ web-1 │ web-2 │ web-3 │
└─────────┴─────────┴─────────┘
操作符和表达式
# 使用 matchLabels(简单匹配)
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app: redis
topologyKey: kubernetes.io/hostname
# 使用 matchExpressions(复杂匹配)
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- redis
- memcached
- key: version
operator: NotIn
values:
- v1
topologyKey: kubernetes.io/hostname
实践练习
练习 1:Pod 亲和性
# 创建 Redis 部署
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis
spec:
replicas: 1
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: redis
---
# 创建靠近 Redis 的 Web 部署
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-near-redis
spec:
replicas: 2
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- redis
topologyKey: kubernetes.io/hostname
containers:
- name: web
image: nginx
# 部署并验证
kubectl apply -f pod-affinity.yaml
kubectl get pods -o wide
# web-near-redis 的 Pod 应该与 redis 在同一节点
练习 2:Pod 反亲和性(高可用)
# pod-antiaffinity-ha.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-ha
spec:
replicas: 3
selector:
matchLabels:
app: web
tier: frontend
template:
metadata:
labels:
app: web
tier: frontend
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web
- key: tier
operator: In
values:
- frontend
topologyKey: kubernetes.io/hostname
containers:
- name: web
image: nginx
练习 3:跨可用区反亲和性
# pod-antiaffinity-zone.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-multi-zone
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web
topologyKey: topology.kubernetes.io/zone
containers:
- name: web
image: nginx
练习 4:组合亲和性和反亲和性
# pod-affinity-combined.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-app
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
affinity:
# 靠近缓存服务
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 80
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app
operator: In
values:
- cache
topologyKey: kubernetes.io/hostname
# 分散到不同节点
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web
topologyKey: kubernetes.io/hostname
containers:
- name: web
image: nginx
常见使用场景
1. 高可用部署
- 使用 podAntiAffinity 将副本分散到不同节点/可用区
- 避免单点故障
2. 数据本地化
- 使用 podAffinity 让应用靠近数据源
- 减少网络延迟
3. 微服务协作
- 相关服务部署在同一节点/可用区
- 提高通信效率
4. 资源隔离
- 不同租户的工作负载分散到不同节点
- 使用 podAntiAffinity 实现隔离
小结
| 要点 | 说明 |
|---|---|
| podAffinity | 让 Pod 靠近其他 Pod 运行 |
| podAntiAffinity | 让 Pod 远离其他 Pod 运行 |
| topologyKey | 定义靠近/远离的范围 |
| required | 硬性要求,必须满足 |
| preferred | 软性偏好,尽量满足 |
| 使用场景 | 高可用、数据本地化、资源隔离 |
练习编辑器
bash
Loading...