最近在公司的线上服务器上发现了一个现象: 将某个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. DP- 01背包问题

    这个01背包 , 理解了一天才勉强懂点 , 写个博客  (  推荐   http://blog.csdn.net/insistgogo/article/details/8579597) 题目 : 有N ...

  2. @Controller和@RestController

    @RestController=@Controller+@ResponseBody 1.使用RestController时,返回到前端的内容是Return里的内容,无法返回jsp/html等页面, 此 ...

  3. Nginx. 用http访问https跨域

    用http 访问 https域名, 报跨越问题 解决方法: 在nginx相应服务的转发配置下添加: add_header 'Access-Control-Allow-Origin' 'http://i ...

  4. 【Java面试】Mybatis篇

    1.MyBatis编程步骤是什么样的? ① 创建SqlSessionFactory ② 通过SqlSessionFactory创建SqlSession ③ 通过sqlsession执行数据库操作 ④  ...

  5. CQBZOJ 避开怪兽

    题目描述 给出一个N行M列的地图,地图形成一个有N*M个格子的矩阵.地图中的空地用'.'表示.其中某些格子有怪兽,用'+'表示.某人要从起点格子'V'走到终点格子'J',他可以向上.下.左.右四个方向 ...

  6. 简单实现Android手机“全局可调试”(ro.debuggable = 1)的方法【锤子坚果3】

    在Android真机上调试程序有一个前提,就是这个apk包必须有 debuggable=true 的属性才行.而除了自己开发的apk能够控制打包属性之外,其他的程序发行之后显然不会设这个值为 true ...

  7. 【自制操作系统06】终于开始用 C 语言了,第一行内核代码!

    一.整理下到目前为止的流程图 写到这,终于才把一些苦力活都干完了,也终于到了我们的内核代码部分,也终于开始第一次用 c 语言写代码了!为了这个阶段性的胜利,以及更好地进入内核部分,下图贴一张到目前为止 ...

  8. 19_05_01校内训练[polygon]

    题意 把一个边长为1的正n边形放到一个正m边形中,要求m边形完全覆盖n边形,可以有交点,并且中心重合.求正m边形的最小边长,至少精确到6位.要求logn计算. 思考 先考虑m|n的情况. 我们知道,正 ...

  9. DFS或BFS(深度优先搜索或广度优先搜索遍历无向图)-04-无向图-岛屿数量

    给定一个由 '1'(陆地)和 '0'(水)组成的的二维网格,计算岛屿的数量.一个岛被水包围,并且它是通过水平方向或垂直方向上相邻的陆地连接而成的.你可以假设网格的四个边均被水包围. 示例 1: 输入: ...

  10. JavaScript 注意

    字符串常用方法: 除.length外 都要加括号  trimLeft   trimRight      L和R要大写. .charAt 类似索引,超出范围为空 ,注意 (At)大小写. 注意 1.st ...