k8s pod 抢占后陷入失败/关闭状态 (gke v1.20)

2024-01-11

TL;DR - gke 1.20 可抢占节点导致 Pod 僵尸化并导致失败/关闭

我们已经使用 GKE 几年了,集群中包含稳定节点池和可抢占节点池。最近,自 gke v1.20 以来,我们开始看到抢占的 Pod 进入奇怪的僵尸状态,它们被描述为:

状态:失败

原因: 关机

消息:节点正在关闭,正在驱逐 Pod

当这种情况开始发生时,我们确信这与我们的 Pod 未能在抢占时正确处理 SIGTERM 有关。我们决定通过将服务软件简化为一个大部分处于睡眠状态的简单服务来消除其问题根源:

/* eslint-disable no-console */
let exitNow = false

process.on( 'SIGINT', () => {
  console.log( 'INT shutting down gracefully' )
  exitNow = true
} )

process.on( 'SIGTERM', () => {
  console.log( 'TERM shutting down gracefully' )
  exitNow = true
} )

const sleep = ( seconds ) => {
  return new Promise( ( resolve ) => {
    setTimeout( resolve, seconds * 1000 )
  } )
}

const Main = async ( cycles = 120, delaySec = 5 ) => {
  console.log( `Starting ${cycles}, ${delaySec} second cycles` )

  for ( let i = 1; i <= cycles && !exitNow; i++ ) {
    console.log( `---> ${i} of ${cycles}` )
    await sleep( delaySec ) // eslint-disable-line
  }

  console.log( '*** Cycle Complete - exiting' )
  process.exit( 0 )
}

Main()

此代码使用 tini init 构建到 docker 映像中,以生成在 nodejs 下运行的 pod 进程(fermium-alpine 映像)。无论我们如何调整信号处理,吊舱似乎永远不会真正完全关闭,即使日志表明它们是这样的。

另一个奇怪的地方是,根据 Kubernetes Pod 日志,我们看到 Pod 终止开始,然后被取消:

2021-08-06 17:00:08.000 EDT 停止容器 preempt-pod

2021-08-06 17:02:41.000 EDT 取消删除 Pod preempt-pod

我们还尝试添加 preStop 15 秒延迟,只是为了看看是否有任何效果,但我们尝试的任何操作似乎都不重要 - 豆荚变成了僵尸。新副本在池中可用的其他节点上启动,因此它始终保持系统上成功运行的 Pod 的最小数量。

我们还使用 sim 维护事件来测试抢占周期:

gcloud 计算实例模拟维护事件节点 ID


在浏览了各种帖子后,我最终决定每 9 分钟运行一次 cronjob,以避免 pod 处于关闭状态超过 10 分钟后触发 AlertManager。对我来说,这仍然感觉像是一种 hack,但它确实有效,并且它迫使我深入研究 k8s cronjob 和 RBAC。

这篇文章让我走上了这条道路:如何删除 Kubernetes“关闭”pod https://stackoverflow.com/questions/68344231/how-to-remove-kubernetes-shutdown-pods

以及由此产生的 cronjob 规范:

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: pod-accessor-role
  namespace: default
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods"]
  verbs: ["get", "delete", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: pod-access
  namespace: default
subjects:
- kind: ServiceAccount
  name: cronjob-sa
  namespace: default
roleRef:
  kind: Role
  name: pod-accessor-role
  apiGroup: ""
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: cronjob-sa
  namespace: default
---
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: cron-zombie-killer
  namespace: default
spec:
  schedule: "*/9 * * * *"
  successfulJobsHistoryLimit: 1
  jobTemplate:
    spec:
      template:
        metadata:
          name: cron-zombie-killer
          namespace: default
        spec:
          serviceAccountName: cronjob-sa
          restartPolicy: Never
          containers:
          - name: cron-zombie-killer
            imagePullPolicy: IfNotPresent
            image: bitnami/kubectl
            command:
              - "/bin/sh"
            args:
              - "-c"
              - "kubectl get pods -n default --field-selector='status.phase==Failed' -o name | xargs kubectl delete -n default 2> /dev/null"
status: {}

请注意,将 stderr 重定向到 /dev/null 只是为了避免当 kubectl get 找不到任何处于失败状态的 pod 时 kubectl delete 的错误输出。

Update添加了角色中缺少的“删除”动词,并添加了缺少的 RoleBinding

Update添加了 imagePullPolicy

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

k8s pod 抢占后陷入失败/关闭状态 (gke v1.20) 的相关文章

随机推荐

  • Rails 在新控制器中结合 RESTful 方法

    我有一个 Rails 应用程序 其中users create projects 目前 这些是嵌套的 并作为单独的操作完成 Auser寄存器 然后从project仪表板创建一个新的project 为了提高转化率 以及跟踪来自 adwords
  • PySpark - 将单个整数列表与列表列进行比较

    我正在尝试检查 Spark 数据帧 带有列表的列 中的哪些条目包含给定列表中最大数量的值 我想出的最好的方法是迭代数据框rdd foreach 并使用 python 比较给定列表与每个条目set1 intersection set2 我的问
  • ??空合并运算符 --> 合并是什么意思?

    我很想撒谎说英语是我的第二语言 但事实是我只是不知道 合并 是什么意思 我知道什么 在 C 中是 does 但这个名字对我来说没有意义 我查了一下这个词 我知道它是 加入 的同义词 空连接运算符 仍然没有意义 有人可以启发我吗 我很想撒谎说
  • 如何使用UIAppearance外观WhenContainedIn:

    我注意到在 iOS5 中我们可以通过以下方式自定义 UIKit 控件UIAppearance我开始使用它 我想用appearanceWhenContainedIn 定制UINavigationBar s tintColor在不同的班级 例如
  • 使用 puppeteer 和 MutationObserver 检测 DOM 更改

    我想检测某些加载页面上的 DOM 更改 例如 本地新闻页面上添加的新文章 并在检测后执行某些操作 发送电子邮件 在此示例中 我尝试检测子节点是否已从父节点 目标 div 节点 添加或删除 并在检测后在控制台中输出某些内容 我需要实现暴露功能
  • 在python中读取大csv文件的行

    我有一个非常大的 csv 文件 无法完全加载到内存中 所以我想一块一块地读取它 将其转换为numpy数组 然后再做一些处理 我已经检查过了 在Python中读取大文件的惰性方法 https stackoverflow com questio
  • 如何在谷歌应用程序引擎(Python)中使用numpy

    根据官方文档 numpy 作为谷歌应用程序引擎中的库支持here https developers google com appengine docs python tools libraries27 经过几次尝试后我无法导入它 有人可以分
  • 如何使用 Matplotlib 在对数刻度上显示次要刻度标签

    有谁知道如何使用 Python Matplotlib 以对数刻度显示次要刻度的标签 您可以使用plt tick params axis y which minor 设置小刻度并使用matplotlib ticker FormatStrFor
  • JSON 服务在失败/错误时应返回什么

    我正在用 C ashx 文件 编写 JSON 服务 成功请求服务后 我会返回一些 JSON 数据 如果请求失败 要么是因为抛出了异常 例如数据库超时 要么是因为请求在某种程度上是错误的 例如作为参数给出了数据库中不存在的 ID 服务应该如何
  • 将 Swagger Java 对象转换为 JSON/YAML

    我需要阅读 修改并重新生成 JSON YAML swagger 文件文档 我已经使用 Swagger Parser 反序列化了一个 JSON 文件 并且有一个 Swagger Java 对象 其中原始 JSON 数据已正确映射 现在 我需要
  • Dynamics CRM 视图中的串联/计算列

    我是 MS Dynamics 的新手 我想知道是否有一种方法可以将列添加到视图中 该视图是其他一些列的串联 例如 Firstname Lastname As Fullname 似乎没有一个明显的 优雅的 解决方案 我看到的所有建议都建议使用
  • 如何替换默认的 SortArgumentResolver

    我需要添加private static final Sort sortById new Sort Sort Direction DESC ID 每一个Pageable 我想 最好的方法是创建装饰器 适配器SortArgumentResolv
  • sqrt(float) 有标准返回类型吗?

    我注意到 appleclang v14 0 0 在将浮点输入传递给时似乎返回单精度浮点cmath s sqrt 当切换到 gcc clang 时 我很惊讶地得到了不同的结果 这是我的最小可重现示例 include
  • Hibernate 与连接表的一对多关系,并在连接表中添加列

    我正在寻找一种在两个表之间建立 OneToMany 关系并在连接表中具有额外属性的方法 但我找不到太多有用的示例 抱歉 如果这听起来很蹩脚 但有人能给我建议一个好方法吗 如果连接表中有其他列 则它不再是连接表 并且您需要一种方法来获取和设置
  • 将对象数组及其属性转换为数组

    我尝试了几种地图功能 但找不到合适的方法来获得我想要的东西 案例如下 Object Results Array 3 Results Array 3 0 2 0 Object id null name Rick upper 0 67 1 Ob
  • 为什么关闭窗口时没有触发componentWillUnmount?

    有人会认为componentWillUnmount https reactjs org docs react component html componentwillunmountin React 会在关闭应用程序时触发 根据文档 comp
  • Firebase、Swift:返回类型上的可空性说明符冲突,“nullable”与现有说明符“nonnull”冲突

    警告已进入火力地堡 3 6 0 Xcode 8 斯威夫特 3 这些是 Firebase 类 class FIROptions class FIRAuthCredential class FIRUserProfileChangeRequest
  • 取消鼠标投影以获得 3D 世界坐标 Libgdx

    我的问题 如何让 3D 模型随着鼠标光标移动 并将模型的 y 位置保持在 0 使用 Libgdx 我尝试过的 我正在尝试让 3D 模型跟随我的光标 目前 我只是让模型随着鼠标的 x 和 y 坐标移动 并添加乘数和相机位置等因素 这不是很好
  • HTML5 电话号码验证与模式

    我正在使用 HTML5 表单验证来验证来自印度的电话号码 印度的电话号码长度为 10 位 以 7 8 或 9 开头 例如 7878787878 9898989898 8678678878 这些电话号码有效 但是 1212121212 343
  • k8s pod 抢占后陷入失败/关闭状态 (gke v1.20)

    TL DR gke 1 20 可抢占节点导致 Pod 僵尸化并导致失败 关闭 我们已经使用 GKE 几年了 集群中包含稳定节点池和可抢占节点池 最近 自 gke v1 20 以来 我们开始看到抢占的 Pod 进入奇怪的僵尸状态 它们被描述为