V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
blue7wings
V2EX  ›  Kubernetes

k8s 滚动更新,如何避免替换掉正在处理任务的 pod?

  •  
  •   blue7wings · 2021-06-09 17:38:50 +08:00 · 3961 次点击
    这是一个创建于 1271 天前的主题,其中的信息可能已经有所发展或是发生改变。
    因为 pod 是消耗队列,所以不希望滚动更新的时候,这个 pod 被替换掉,如何保证这个 pod 处理完队列的数据,然后再被自动更新呢? k8s 小白,希望大家能给点建议,谢谢啦
    21 条回复    2021-06-10 14:33:38 +08:00
    Tinet
        1
    Tinet  
       2021-06-09 17:43:36 +08:00
    把 pod 的优雅退出时间设置长一点?当然,你的应用要能捕获到退出信息,以便尽快结束当前正在处理的任务
    kakach
        2
    kakach  
       2021-06-09 17:45:37 +08:00
    不知道 k8s 终止一个 pod 前会不会停止处理新请求并等待一段时间,蹲一个大佬的解答
    mooyo
        3
    mooyo  
       2021-06-09 17:47:57 +08:00
    这个没法保证,因为要保证 pod 处理完再退出就需要从内向外的控制。但是可以调整你的程序来适配 k8s 的一系列信号来尽量避免这个问题。
    首先需要调整退出等待期,调长一点,给程序留一定的周转空间。 然后 k8s 可以给 pod 设置一个退出时执行的命令,通过这个命令告知你的服务赶紧结束掉手上的工作,结束不掉的部分持久化存起来,下一个 pod 拉出来接着做。
    thet
        4
    thet  
       2021-06-09 17:53:10 +08:00 via iPhone
    差不多就是一楼说的,主要你的程序要能捕获退出信号,然后处理完当前任务就退出。可以根据任务最大执行时间设置一下优雅退出时间,优雅退出时间到了后,不管容器内程序怎么样,容器都会被 kubelet 干掉。
    mindsucker
        5
    mindsucker  
       2021-06-09 18:23:51 +08:00
    可以看看优雅停机的相关资料,停机前会给 pid 为 1 的进程发送 TERM signal 命令,但是你的任务要有退出处理机制
    crclz
        6
    crclz  
       2021-06-09 18:29:54 +08:00   ❤️ 1
    换一种思路。一个健壮的程序应当能够完美应对以下情况:

    在断电 /断网后,数据库的完整性依然能够保证。

    这就要求你在处理任务的时候充分发挥事务和幂等性的作用。
    libook
        7
    libook  
       2021-06-09 18:30:33 +08:00
    可以设计成可恢复(或回滚重做)的事务,即便不主动杀 pod 也可能会存在程序崩溃的问题,这时候新运行的程序能够继续做完之前没做完的任务就行了。
    GopherDaily
        8
    GopherDaily  
       2021-06-09 18:38:11 +08:00
    graceful shutdown?
    jim9606
        9
    jim9606  
       2021-06-09 18:55:18 +08:00   ❤️ 5
    为了支持 graceful shutdown,你的程序应当捕获 SIGTERM 信号,在捕获该信号后开启 shutdown 工作,停止接受新任务。无论你是不是用容器都应当做到这点。

    k8s 默认也是这样的,delete 动作后向容器进程发送 SIGTERM,等待 ShutdownGracePeriod (可适当调大些)后仍未退出就会发送 SIGKILL (不可捕获)杀死进程
    defunct9
        10
    defunct9  
       2021-06-09 19:29:57 +08:00
    lifecycle:
    preStop:
    exec:
    command: ["/bin/sh", "-c", "sleep 20"]
    shiny
        11
    shiny  
       2021-06-09 19:34:32 +08:00
    哪怕不用 k8s,Docker 容器也需要考虑退出时的信号,但很多 Dockerfile 都没有考虑到这一点,以至于框架不能捕获 SIGTERM 信号做优雅退出
    heart4lor
        12
    heart4lor  
       2021-06-09 19:56:11 +08:00
    graceful shutdown 是一点,应用尽量做到无状态也很重要,现在其实很少有应用是完全无状态的
    NUT
        13
    NUT  
       2021-06-09 21:53:46 +08:00
    没法保证完全保证。需要做计算与存储分离。
    把队列信息放到 zk 或 etcd 或者 redis mysql 上线。然后做一个分布式调度 就行了。
    xuzhzzz
        14
    xuzhzzz  
       2021-06-10 00:26:22 +08:00
    这跟 k8s 无关,你的程序跑在哪里都得做到 graceful shutdown 啊
    fitmewell
        15
    fitmewell  
       2021-06-10 00:35:47 +08:00 via Android
    先停掉消费队列,然后监控完成后再调用 stop
    vhwwls
        16
    vhwwls  
       2021-06-10 01:42:31 +08:00
    楼上说的都对,这点 K8s 自己没有做,只能延长关闭 Pod 的等待期,其他的得从程序层面考量。
    Rwing
        17
    Rwing  
       2021-06-10 09:41:24 +08:00
    楼上说的都对,这点 K8s 自己没有做,只能延长关闭 Pod 的等待期,其他的得从程序层面考量。
    coderxy
        18
    coderxy  
       2021-06-10 09:57:35 +08:00
    优雅退出,k8s 在关闭某个 pod 前会发出一个 sigterm 的信号,服务接收到这个信号后自行优雅退出,如果发出指定后一段时间(好像默认是 10s ),服务还是在运行就会被 k8s 强制 kill
    jingslunt
        19
    jingslunt  
       2021-06-10 10:22:01 +08:00
    前面将的 lifecycle 生命周期其实就是 pod hook,滚动的时候加一个钩子,只有钩子执行完成才会执行容器的内容
    PiersSoCool
        20
    PiersSoCool  
       2021-06-10 13:21:35 +08:00
    1 、listen term signal
    2 、close http server
    3 、handle rest data

    我们的日志服务就是这么做的,从未丢过数据
    FingerLiu
        21
    FingerLiu  
       2021-06-10 14:33:38 +08:00
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   5189 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 05:41 · PVG 13:41 · LAX 21:41 · JFK 00:41
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.