Pod 一直处于Pending状态?可能是拓扑约束的问题

Sealos 公众号已接入了 GPT-4,完全免费!欢迎前来调戏👇

19595201b2e26eae331b07cf4e271063.png

原文链接:https://juejin.cn/post/7245179553886486584

起因:今天在部署组件的时候,发现组件的 pod 一直处于 Pending 状态,报错显示的原因是:不满足 Pod 拓扑分布约束,看了代码发现是原来同事给组件新增了 Pod 拓扑约束。对于 Pod 拓扑约束,我先前并没有认真了解过,刚好可以借这个排查问题的机会深入了解什么是 Pod 拓扑约束。

文档参考:

kubernetes.io/zh-cn/docs/…[1]

文档参考主要是上述两篇 k8s 官方的文档,建议英文功底好的可以直接看第二篇文档。

API 定义

topologySpreadConstraints 是一个 Pod Spec 层级的字段,其定义的结构体如下:

spec:
  topologySpreadConstraints:
  - maxSkew: <integer>
    topologyKey: <string>
    whenUnsatisfiable: <string>
    labelSelector: <object>

在官方文档里还描述了许多 beta 特性的字段,但如果是刚上手 Pod 拓扑约束的小伙伴,可以从这上面的四个基本字段入手,先把这四个字段的含义吃透。

12266365fbe3ac59eb8c11ecd2f552fe.jpeg
  • labelSelector:labelSelector 是用来寻找匹配标签的 Pod,对于每一个拓扑域来说,k8s 调度器会计算其中匹配 labelSelector 的 Pod 数量。在上图中,我们定义的拓扑约束只针对含有 label app=foo 的 Pod 生效。

  • topologyKey:topologyKey 用于一个拓扑域,这个值通常情况下是定义在节点上的标签。在上图中,我们定义的拓扑域就是 zone,也就是含有 zone 这个 label 的节点才算在我们的拓扑域中。

  • maxSkew:maxSkew 指的就是 Pod 分布在不同的拓扑域中的数量差异。maxSkew 要求其设定的值大于 0,其值越小,说明我们期望 Pod 能够越均衡地打散分布在拓扑域中,其值越大,则反之。在上图中,如果新的 Pod 调度到 Zone1 中,则 Zone1 和 Zone2 的 skew 就是 3-0=3,如果新的 Pod 调度到 Zone2 中,则 Zone1 和 Zone2 的 skew 就是 2-1=1.

  • whenUnsatisfiable:whenUnsatisfiable 指当 skew 不满足 maxSkew 时,调度器会执行的动作,可选值为:

    • DoNotSchedule:(默认值)不调度。

    • ScheduleAnyway:仍然调度,但会趋向于调度到使 skew 最小的拓扑域中。

了解到这里,我就已经排查出来调度不上去的原因了:集群是一个两节点的集群(1master+1worker),但这两个节点属于同一个可用区,但有一点奇怪的是,按照算法,应该会有一个 Pod 调度上去,另一个 Pod 处于 Pending 状态,但现实却是两个 Pod 都处于 Pending 状态。继续看代码,我发现了同事不仅用了 topologySpreadConstraints,还结合了亲和性反亲和性一起使用。

拓扑分布约束 and 亲和性反亲和性

Pod 拓扑约束可以结合亲和和反亲和特性一起使用,达到更丰富的效果,以实际业务场景中的代码为例:

affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            - labelSelector:
                matchLabels:
                  app.kubernetes.io/name: app-server
              topologyKey: kubernetes.io/hostname
      schedulerName: default-scheduler
     topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: topology.kubernetes.io/zone
          whenUnsatisfiable: DoNotSchedulable
          labelSelector:
            matchLabels:
              app.kubernetes.io/instance: app-server
              app.kubernetes.io/name: app-server

可以看到,我们设置了 Pod  反亲和性,禁止符合条件的 Pod 调度到同一个节点上(可能是出于容灾或其他方面的考虑),再看 Pod 拓扑约束,要求 Pod 均匀地分布在每个可用区中,且每个可用区之间符合条件的 Pod 的数量差值最大为 1,如果不满足的条件下,禁止调度。(强打散 Pod 到每个可用区中,可能是出于网络带宽,cpu 内存等资源角度的考虑)。

因此,在仅有两个节点的集群中,且这两个节点还是属于同一个可用区的情况下,无法满足上述的调度条件,因此两个 Pod 均处于 Pending 状态。

解决方式有两种,可以设置 maxSkew 的值为 2,或者设置 whenUnsatisfiable 的值为 ScheduleAnyway。

引用链接

[1]

kubernetes.io/zh-cn/docs/…: https://kubernetes.io/blog/2020/05/introducing-podtopologyspread/

关于 Sealos

Sealos 是一款以 Kubernetes 为内核的云操作系统发行版。它以云原生的方式,抛弃了传统的云计算架构,转向以 Kubernetes 为云内核的新架构,使企业能够像使用个人电脑一样简单地使用云。

🌟GitHub:https://github.com/labring/sealos

🏠官网:https://sealos.io

💻开发者论坛:https://forum.laf.run

关注 Sealos 公众号与我们一同成长👇👇👇

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值