k8s优雅停机的探索

1.问题背景:

    我们项目里用到了dubbo分布式框架,使用了redis注册中心,当服务shutdown时,没有向注册中心注销服务,也没有向consumer unregister;导致在服务重启后,第一次连接继续连接老的服务ip上并无法连接;

2.问题原因:

    ①阿里云的托管k8s集群当时还不支持shutdown hook,以及shutdown gracefully;
    ②kubelet发送kill命令(TERM signal)给容器类的1号进程,如果你运行的程序在别的进程上,那么就接受不到kill命令。
    ③启动服务使用 $ sh script.sh 命令在sh脚本中直接用 java -jar 命令启动,导致java进程不是1号进程。

3.解决办法:

    第一步,切换为支持shutdown gracefully的k8s集群
    第二步,还是使用 $ sh script.sh 方式启动程序,不过启动命令改为 exec java -jar,让java程序运行在1号进程。

4.知识点:

①Linux kill命令

Linux kill命令用于删除执行中的程序或工作;

kill [-s <信息名称或编号>][程序PID] 或 kill [-l <信息编号>]

执行kill(默认kill -15)命令,系统会发送一个SIGTERM信号给对应的程序。当程序接收到该signal信号后,一般会先释放资源,然后自行停止进程;当然也可能最终阻塞住没有结束;
执行kill -9 命令,系统给对应程序发送的信号是SIGKILL,即exit。会强制终结进程,不会有任何其他操作;

②Kubernetes优雅停机策略

Kubernetes在终结pods的时候,默认会向每个container的1号进程发送TERM signal,优雅停机默认会容许30秒的停机周期;于此同时负载均衡也会将正在终结的pod从Endpoint中移除,这样就不会有新的流量流进将会被移除的pod

③shell,exec,source的区别

$ sh script.sh 执行脚本时,当前shell是父进程,生成一个子shell进程,在子shell中执行脚本。脚本执行完毕,退出子shell,回到当前shell
$ source script.sh 方式,在当前上下文中执行脚本,不会生成新的进程。脚本执行完毕,回到当前shell
exec command 方式,会用command进程替换当前shell进程,并且保持PID不变。执行完毕,直接退出,不回到之前的shell环境。

5.参考文献:

  shell,exec,source执行脚本的区别
  Pod Lifecycle

posted on 2020-05-07 10:18  mindSucker  阅读(1500)  评论(0编辑  收藏  举报