首页 > 其他分享 >Pod 打散调度

Pod 打散调度

时间:2022-12-14 22:35:19浏览次数:55  
标签:kubernetes 调度 nginx io 打散 Pod 节点

将 Pod 打散调度到不同地方,可避免因软硬件故障、光纤故障、断电或自然灾害等因素导致服务不可用,以实现服务的高可用部署。

Kubernetes 支持两种方式将 Pod 打散调度:

  • Pod 反亲和 (Pod Anti-Affinity)
  • Pod 拓扑分布约束 (Pod Topology Spread Constraints)

本文介绍两种方式的用法示例与对比总结。

使用 podAntiAffinity

将 Pod 强制打散调度到不同节点上(强反亲和),以避免单点故障:

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- topologyKey: kubernetes.io/hostname
labelSelector:
matchLabels:
app: nginx
containers:
- name: nginx
image: nginx
  • ​labelSelector.matchLabels​​ 替换成选中 Pod 实际使用的 label。
  • ​topologyKey​​: 节点的某个 label 的 key,能代表节点所处拓扑域,可以用 ​​Well-Known Labels​​,常用的是 ​​kubernetes.io/hostname​​ (节点维度)、​​topology.kubernetes.io/zone​​ (可用区/机房 维度)。也可以自行手动为节点打上自定义的 label 来定义拓扑域,比如 ​​rack​​ (机架维度)、​​machine​​ (物理机维度)、​​switch​​ (交换机维度)。
  • 若不希望用强制,可以使用弱反亲和,让 Pod 尽量调度到不同节点:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- podAffinityTerm:
topologyKey: kubernetes.io/hostname
weight: 100

将 Pod 强制打散调度到不同可用区(机房),以实现跨机房容灾:

将 ​​kubernetes.io/hostname​​​ 换成 ​​topology.kubernetes.io/zone​​,其余同上。

使用 topologySpreadConstraints

将 Pod 最大程度上均匀的打散调度到各个节点上:

apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
labelSelector:
- matchLabels:
app: nginx
containers:
- name: nginx
image: nginx
  • ​topologyKey​​: 与 podAntiAffinity 中配置类似。
  • ​labelSelector​​: 与 podAntiAffinity 中配置类似,只是这里可以支持选中多组 pod 的 label。
  • ​maxSkew​​: 必须是大于零的整数,表示能容忍不同拓扑域中 Pod 数量差异的最大值。这里的 1 意味着只允许相差 1 个 Pod。
  • ​whenUnsatisfiable​​: 指示不满足条件时如何处理。​​DoNotSchedule​​ 不调度 (保持 Pending),类似强反亲和;​​ScheduleAnyway​​ 表示要调度,类似弱反亲和;

以上配置连起来解释: 将所有 nginx 的 Pod 严格均匀打散调度到不同节点上,不同节点上 nginx 的副本数量最多只能相差 1 个,如果有节点因其它因素无法调度更多的 Pod (比如资源不足),那么就让剩余的 nginx 副本 Pending。

所以,如果要在所有节点中严格打散,通常不太可取,可以加下 nodeAffinity,只在部分资源充足的节点严格打散:

    spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: io
operator: In
values:
- high
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
labelSelector:
- matchLabels:
app: nginx

或者类似弱反亲和, 将 Pod 尽量均匀的打散调度到各个节点上,不强制 (DoNotSchedule 改为 ScheduleAnyway):

    spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
- matchLabels:
app: nginx

如果集群节点支持跨可用区,也可以 将 Pod 尽量均匀的打散调度到各个可用区 以实现更高级别的高可用 (topologyKey 改为 ​​topology.kubernetes.io/zone​​):

    spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: ScheduleAnyway
labelSelector:
- matchLabels:
app: nginx

更进一步地,可以 将 Pod 尽量均匀的打散调度到各个可用区的同时,在可用区内部各节点也尽量打散:

    spec:
topologySpreadConstraints:
- maxSkew: 1
topologyKey: topology.kubernetes.io/zone
whenUnsatisfiable: ScheduleAnyway
labelSelector:
- matchLabels:
app: nginx
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: ScheduleAnyway
labelSelector:
- matchLabels:
app: nginx

小结

从示例能明显看出,​​topologySpreadConstraints​​​ 比 ​​podAntiAffinity​​​ 功能更强,提供了提供更精细的调度控制,我们可以理解成 ​​topologySpreadConstraints​​​ 是 ​​podAntiAffinity​​​ 的升级版。​​topologySpreadConstraints​​​ 特性在 K8S v1.18 默认启用,所以建议 v1.18 及其以上的集群使用 ​​topologySpreadConstraints​​ 来打散 Pod 的分布以提高服务可用性。

参考资料


标签:kubernetes,调度,nginx,io,打散,Pod,节点
From: https://blog.51cto.com/zhaochengsheng/5938400

相关文章

  • Pod常见的状态和重启策略
    常见的pod状态pod常见的状态:第一阶段挂起(Pending):1、正在创建Pod但是Pod中的容器还没有全部被创建完成,处于此状态的Pod应该检查Pod依赖的存储是否有权限挂载、镜像是否......
  • 生产k8s 批量处理pod
    清理非running的podkubectlgetpod-owide--all-namespaces|awk'{if($4!="Running"){cmd="kubectl-n"$1"deletepod"$2;system(cmd)}}'清理非Evicted的podkube......
  • Linux 安装 [docker/podman]
    podman不需要守护进程,不需要root权限,docker需要守护进程,需要root权限创建容器;安装docker要求系统为64位、系统内核版本为3.10以上,可以使用以下命令查看uname-r4.18.......
  • 什么是Pod?
    Pod是Kubernetes中最小的单元,它由一组、一个或多个容器组成,每个Pod还包含了一个Pause容器,Pause容器是Pod的父容器,主要负责僵尸进程的回收管理,通过Pause容器可以使同一个Pod......
  • 定义一个Pod
    apiVersion:v1#必选,API的版本号kind:Pod      #必选,类型Podmetadata:      #必选,元数据 name:nginx  #必选,符合RFC1035规范的Pod名称 n......
  • Pod与Service介绍
    Podk8s中的最小部署单元,不是一个程序/进程,而是一个环境(包括容器、存储、网络ip:port、容器配置)。其中可以运行1个或多个container(docker或其他容器),在一个pod内部的contain......
  • 2016 CocosPods安装教程
    CocoaPods简介CocoaPods是一个管理Swift和Objective-C的Cocoa项目的依赖工具。它现在有超过一万八千多个库,可以优雅地帮助你扩展你的项目。简单的说,就是替你管理Swift和Obje......
  • K8S Pod status的状态分析 扩容及缩容
    K8SPodstatus的状态分析CrashLoopBackOff:容器退出,kubelet正在将它重启InvalidImageName:无法解析镜像名称ImageInspectError:无法校验镜像ErrImageNeverPull:策略......
  • 关于Linux中作业调度 crond 和 systemd.timer 使用场景的一些笔记
    写在前面分享一些​​systemd.timer​​相关的笔记博文内容涉及:​​systemd.timer​​的一些介绍​​cron​​​VS​​systemd.timer​​区别如何创建​​syst......
  • 如何远程调试k8s里的jettypod
     ​课程内容:各种k8s部署方式。包括minikube部署,kubeadm部署,kubeasz部署,rancher部署,k3s部署。包括开发测试环境部署k8s,和生产环境部署k8s。介绍主要的k8s资源的使用配置和命......