最近在公司的线上服务器上发现了一个现象: 将某个node的kubelet短暂的停掉之后,其上的pod马上会被驱逐,这让笔者大吃一惊,印象之中,停掉kubelet后,该node会变为NotReady状态,随后controller-manger会经过一段时间才开始驱逐其上的pod。还有个参数专门来控制这个时间:

--pod-eviction-timeout The grace period for deleting pods on failed nodes. (default 5m0s)`

该参数默认值为5min, 也就是说当node NotReady之后,最少也得五分钟之后其上的pod才会被驱逐。但是现实情况明显不符合预期啊,这样就有点奇怪了。
鉴于该问题影响巨大,笔者果断开启了debug之旅。

首先我们从直接原因下手,需要了解一下当node NotReady之后,controller-manager是如何判断并驱逐其上的pod的,这部分工作是由node lifecycel controller模块负责。

node lifecycle controller 主要负责对node生命周期进行检查,判断node是否存活,如果长时间检测不到node心跳则驱逐其上的pod。在目前的版本(v1.16)中,默认开启了TaintBasedEvictions, TaintNodesByCondition这两个feature gate,则所有node生命周期管理都是通过condition + taint的方式进行管理。其主要逻辑由三部分组成:

  1. 不断地检查所有node状态,设置对应的condition
  2. 不断地根据node condition 设置对应的taint
  3. 不断地根据taint驱逐node上面的pod

想要详细了解node lifecycle controller工作机制的同学可以翻阅笔者上一篇文章: kubernetes中node心跳处理逻辑分析

查看代码发现--pod-eviction-timeout并未起作用,原来在v1.13版本之前TaintBasedEvictions功能还未开启,此时node not-ready之后,controller直接判断not-ready时间是否超过了--pod-eviction-timeout,超过就进行删除。而v1.13,TaintBasedEvictions功能开启之后就不会使用了该参数,转而使用了上面描述的condition+taint方案。也就是说node NotReady之后,pod的驱逐时间完全由每个pod toleration中 tolerationSecond决定,而不是由controller-manager的参数--pod-eviction-timeout统一决定。这样想想也合情合理,每个pod对于故障的容忍时间不同,tolerationSecond可以更加灵活地为每个pod指定不同的驱逐时间。

这样说来,所有的pod都需要设置一个toleration才对,查阅相关资料后发现,社区已经有了一个DefaultTolerationSeconds admisson controller自动地帮助我们设置toleration,每次创建更新pod, 在请求发送到apiserver之后会自动设置5min的默认toleration。

This admission controller sets the default forgiveness toleration for pods to tolerate the taints notready:NoExecute and unreachable:NoExecute for 5 minutes, if the pods don’t already have toleration for taints node.kubernetes.io/not-ready:NoExecute or node.alpha.kubernetes.io/unreachable:NoExecute.

文档上显示该admission controller默认开启,但是为什么我司的环境上面没有生效,仔细看了一下文档,是因为自己使用了一个deprecated的参数:--admission-control,使用这个参数的话必须显式指定所有要开启的admisson controller plugin列表。该参数在v1.10被废弃,由两个新的参数--enable-admission-plugins--disable-admission-plugins替换,这两个参数如果不指定的话会有默认值,其中DefaultTolerationSeconds就属于--enable-admission-plugins参数的默认值之一,也就是会默认开启该plugin。又是一个升级导致的坑! 正确修改了该参数之后,新创建的pod就会默认带上了toleration,DefaultTolerationSeconds adminssion controller plugin总算生效了。 

新创建的pod总算没有问题了,但是对于集群中已经存在的pod还没有toleration该怎么办? 显然社区对这种情况未做处理,DefaultTolerationSeconds是社区很早就开发的一个feature,但是TaintBasedEvictions是v1.13才默认开启,估计社区在开发时前后没有做好兼容。翻了下DefaultTolerationSecondsadminssion plugin源码,发现该plugin对于pod create, update操作都会设置toleration, 所以一般情况下, 我们升级集群的时候,总是能触发pod发生update,该toleration会自动添加上,无需过多操作,大可不必担心,心里知道有这个事情并检查一下就行。但是笔者的环境已经升级完成了,只能手动触发pod update了,思来想去,想要触发pod update又不能影响业务,给pod打label是一个比较好的方式,于是笔者写了一个脚本将集群中所有的pod都打了一个无关紧要的label, 触发uodate后就自动添加了toleration。

至此整个修复工作全部完成,回过头来仔细想想,kubernetes版本间升级挑战还是挺大的,兼容性问题防不胜防,很可能两个小版本间完全兼容,没任何问题,但是当一步步从低版本升级上来的时候问题就出现了,而且在兼容性测试的时候难以覆盖到每种情况,很可能需要很久问题才能暴露出来。对于这种情况,唯有掌握内部机理,熟读源码才能快速诊断,修复。

记一次kubernetes驱逐踩坑的更多相关文章

  1. Kubernetes探针踩坑记

    1. 荒腔走板 最近一两个月生产K8s集群频繁出现短时503 Service Temporarily Unavailable,还不能主动复现,相当郁闷,压力山大. HTTP 5xx响应状态码用于定义服 ...

  2. 记一次FTP下载踩坑的故(shi)事(gu)

    下班前领导忽然要求我将客户的日志服务器上一些日志拷贝到测试服务器中,不过领导只提供给我FTP的连接方式,很明显就是要我用FTP方式去做啦 一般来说FTP批量下载也就上网随便找个脚本的事,但是却成了我疯 ...

  3. Mac上使用Docker Desktop启动Kubernetes,踩坑后终于搞掂

    1 前言 Kubernetes又简称k8s,是Google开源的容器集群管理系统,最近也是火热.闲来无事(为了发文),捣鼓了一下,在Mac上搭建Kubernetes,遇到一些坑,也记录一下. 另外,D ...

  4. 记一次pm2的踩坑

    1.问题: 公司采用了自动发布平台,最近突然发现一个问题,上线完成后服务是能正常访问的,但是有一个节点访问的时候每两次中总是有一次404,通过nginx的access日志分析发现第一次正常访问有一次g ...

  5. Kubernetes实践踩坑系列(一).应用管理的难题

    应用管理的两大难题  今天我们主要讨论这两个方面的挑战: 对应用研发而言,K8s API 针对简单应用过于复杂,针对复杂应用难以上手: 对应用运维而言,K8s 的扩展能力难以管理:K8s 原生的 AP ...

  6. IdentityServer 部署踩坑记

    IdentityServer 部署踩坑记 Intro 周末终于部署了 IdentityServer 以及 IdentityServerAdmin 项目,踩了几个坑,在此记录分享一下. 部署架构 项目是 ...

  7. Spark踩坑记——Spark Streaming+Kafka

    [TOC] 前言 在WeTest舆情项目中,需要对每天千万级的游戏评论信息进行词频统计,在生产者一端,我们将数据按照每天的拉取时间存入了Kafka当中,而在消费者一端,我们利用了spark strea ...

  8. Spark踩坑记——数据库(Hbase+Mysql)

    [TOC] 前言 在使用Spark Streaming的过程中对于计算产生结果的进行持久化时,我们往往需要操作数据库,去统计或者改变一些值.最近一个实时消费者处理任务,在使用spark streami ...

  9. 记jQuery.fn.show的一次踩坑和问题排查

    最近很少已经很少用jQuery,因为主攻移动端,常用Zepto,其实很多细节和jQuery并不一样.最近又无意中接触到了PC的需求和IE6, 使用了jQuery,刚好踩坑了,特意记录一下. 本文内容如 ...

随机推荐

  1. mongodb学习(二)——基本的数据操作

    数据操作(重点) 数据库的核心--CRUD,增加和删除较为简单,查询和修改较复杂 查询 关系运算符 $gt 大于 $lt 小于 $gte 大于等于 $lte 小于等于 $eq | (key: valu ...

  2. Python 任务自动化工具:nox 的配置与 API

    英文 | Configuration & API 出处 | nox 官方文档 译者 | 豌豆花下猫@Python猫 Github地址:https://github.com/chinesehua ...

  3. git利用hooks实现自动部署

    准备工作: 1.一台虚拟linux环境和window 开始工作 1.安装git(略) 2.创建git用户和创建test.git裸仓库 [root@localhost ~]# useradd -m gi ...

  4. TypeScript 源码详细解读(3)词法2-标记解析

    在上一节主要介绍了单个字符的处理,现在我们已经有了对单个字符分析的能力,比如: 判断字符是否是换行符:isLineBreak 判断字符是否是空格:isWhiteSpaceSingleLine 判断字符 ...

  5. 田忌赛马 - dp

    Here is a famous story in Chinese history. That was about 2300 years ago. General Tian Ji was a high ...

  6. 第五篇:python购物车小程序开发demo

    功能:自定义工资水平,可选商品加购余额实时提醒用到的知识点:列表.if多分支.循环.高亮输出未解决bug删除商品后不能自动退出 代码如下: if shopping_list: shopping_lis ...

  7. Activiti 规则任务(businessRuleTask)

    Activiti 规则任务(businessRuleTask) 作者:Jesai 目前国内研究Activiti规则任务businessRuleTask)的文章在网上应该不超出3篇 小觑夜漫酒作伴,破晓 ...

  8. Scrapy定制起始请求

    Scrapy引擎来爬虫中取起始的URL 1.调用start_requests方法(父类),并获取返回值 2.将放回值变成迭代器,通过iter() 3.执行__next__()方法取值 4.把返回值全部 ...

  9. 网站 cache control 最佳实践

    推荐阅读: 2020年软件开发趋势 高并发案例 - 库存超发问题 负载均衡的分类及算法 异地多活架构 Postman 的替代品来了 有时,当第二次访问网站时,看起来比较怪,样式不正常. 通常,是因为 ...

  10. 到头来还是逃不开Java - Java13程序基础

    java程序基础 没有特殊说明,我的所有学习笔记都是从廖老师那里摘抄过来的,侵删 引言 兜兜转转到了大四,学过了C,C++,C#,Java,Python,学一门丢一门,到了最后还是要把Java捡起来. ...