Kubernetes 设计模式之生命周期管理

由云原生平台管理的容器化应用对其生命周期没有控制权,要想成为优秀的云原生化 ,它们必须监听管理平台发出的事件,并相应地调整其生命周期。托管生命周期模式描述了应用程序如何能够并且应该对这些生命周期事件做出反应。

1 存在问题

健康探针我们解释了为什么容器要为不同的健康检查提供API。健康检查API是平台不断探查以获取应用洞察力的只读endpoints。它是平台从应用中提取信息的一种机制。

除了监控容器的状态外,平台有时可能会发出命令,并期望应用程序对此做出反应。在策略和外部因素的驱动下,云原生平台可能会在任何时刻决定启动或停止其管理的应用程序。容器化应用要决定哪些事件是重要的,要做出反应以及如何反应。但实际上,这是一个API,平台是用来和应用进行通信和发送命令的。另外,如果应用程序不需要这项服务,他们可以自由地从生命周期管理中获益,或者忽略它。

2 解决方案

我们看到,只检查进程状态并不能很好地显示应用程序的健康状况。这就是为什么有不同的API来监控容器的健康状况。同样,只使用进程模型来运行和停止一个进程是不够好的。现实世界中的应用需要更多的细粒度交互和生命周期管理能力。有些应用需要帮助预热,有些应用需要优雅而不带缓存的关闭程序。对于这种和其他用例,一些事件,如图1-1所示,由平台发出,容器可以监听并在需要时做出反应。Kubernetes 设计模式之生命周期管理

应用程序的部署单元是一个Pod。你已经知道,一个Pod由一个或多个容器组成。在Pod层面,还有其他的构造,比如init容器、init Container(以及defer-containers,截止到目前还在提案阶段),可以帮助管理容器的生命周期。我们在本章中描述的事件和钩子都是应用在单个容器级别而不是Pod级别。

2.1 SIGTERM Signal

每当Kubernetes决定关闭一个容器时,无论是因为它所属的Pod正在关闭,还是仅仅是一个失败的liveness探测导致容器重新启动,容器都会收到一个SIGTERM信号。SIGTERM是在Kubernetes发出更突然的SIGKILL信号之前,温柔地戳一下容器,让它干净利落地关闭。一旦收到SIGTERM信号,应用程序应该尽快关闭。对于一些应用来说,这可能是一个快速的终止,而其他一些应用可能必须完成其飞行中的请求,释放开放的连接,并清理临时文件,这可能需要稍长的时间。在所有的情况下,对SIGTERM做出反应是以正确时刻和干净的方式关闭容器。

2.2 SIGKILL Signal

如果容器进程在发出SIGTERM信号后还没有关闭,则会被下面的SIGKILL信号强制关闭。Kubernetes不会立即发送SIGKILL信号,而是在发出SIGTERM信号后默认等待30秒的宽限期。这个宽限期可以使用.spec.terminalGracePeriodSeconds字段为每个Pod定义,但不能保证,因为它可以在向Kubernetes发出命令时被覆盖。这里的目的应该是设计和实现容器化应用,使其具有短暂性的快速启动和关闭进程。

2.3 Poststart Hook

只使用过程信号来管理生命周期是有一定局限性的。这就是为什么Kubernetes提供了额外的生命周期钩子,如postStart和preStop。包含postStart钩子的Pod清单看起来像例1-1中的那个。

实例1-1,容器中配置poststart hook
apiVersion: v1
kind: Pod
metadata:
name: post-start-hook
spec:
containers:
- image: k8spatterns/random-generator:1.0
name: random-generator
lifecycle:
postStart:
exec:
command:
- sh
- -c
- sleep 30 && echo "Wake up!" > /tmp/postStart_done

postStart命令在这里等待30秒。sleep只是模拟任何可能在这里运行的冗长启动代码。另外,它在这里使用一个触发器文件与主应用程序同步,主应用程序是并行启动的。

postStart 命令在容器创建后与主容器的进程异步执行。即使许多应用程序的初始化和预热逻辑可以作为容器启动步骤的一部分来实现,postStart仍然涵盖了一些用例。postStart动作是一个阻塞调用,容器状态保持为Waiting,直到postStart处理程序完成,这又使Pod状态保持为Pending状态。postStart的这种性质可以用来延迟容器的启动状态,同时给容器主进程初始化的时间。

postStart的另一个用途是当Pod不满足某些前提条件时,防止容器启动。例如,当postStart钩子通过返回一个非零的退出代码来指示错误时,主容器进程会被Kubernetes杀死。

postStart和preStophook调用机制类似于所述的健康探针,并支持这些处理程序类型。

  • exec  直接在容器中运行指令
  • httpGet  对一个Pod容器监听的端口执行HTTP GET请求。

你必须非常小心地执行postStart钩子中的关键逻辑,因为它的执行没有保证。由于钩子是与容器进程并行运行的,所以钩子有可能在容器启动之前就被执行了。另外,钩子的目的是至少有一次语义,所以实现必须照顾到重复的执行。另一个需要注意的方面是,平台不会对没有到达处理程序的HTTP请求失败执行任何重试尝。

2.4 Prestop Hook

preStop 钩子是在容器被终止之前向其发送的阻塞调用,它与 SIGTERM 信号具有相同的语义,在无法对 SIGTERM 作出反应时,应使用它来优雅关闭容器。它与SIGTERM信号具有相同的语义,当无法对SIGTERM作出反应时,它应该被用来启动容器的优雅关闭。例 1-2 中的 preStop 动作必须在删除容器的调用被发送到容器运行时之前完成,后者会触发 SIGTERM 通知。

1-2. 容器中配置preStop Hook
apiVersion: v1
kind: Pod
metadata:
name: pre-stop-hook
spec:
containers:
- image: k8spatterns/random-generator:1.0
name: random-generator
lifecycle:
preStop:
httpGet:
port: 8080
path: /shutdown

即使preStop正在阻塞,按住它或返回一个不成功的结果并不能阻止容器被删除和进程被杀死。preStop只是一个方便的替代SIGTERM信号的优雅应用,仅此而已。它还提供了与我们之前介绍的postStart钩子相同的处理程序类型和保证。

2.5 Other Lifecycle Controls

在本章中,到目前为止,我们已经关注了当容器生命周期事件发生时允许执行命令的钩子。但另一种机制不是在容器层面,而是在Pod层面,允许执行初始化指令。

Init容器,深入浅出,但这里我们简单介绍一下,将其与生命周期钩子进行比较。与普通的应用容器不同,init容器按顺序运行,一直运行到完成,并且在Pod中任何一个应用容器启动之前运行。这些保证允许使用init容器进行Pod级初始化任务。生命周期钩子和init容器都以不同的粒度(分别在容器级和Pod级)运行,可以在某些情况下交替使用,或者在其他情况下相互补充。表1-1总结了两者的主要区别。Kubernetes 设计模式之生命周期管理

除了当你需要特定的时间保证时,使用哪种机制没有严格的规定。我们可以完全跳过生命周期钩子和初始化容器,使用bash脚本来执行特定的操作,作为容器启动或关闭命令的一部分。这是有可能的,但它会将容器与脚本紧密耦合,并将其变成维护的噩梦。

我们还可以使用 Kubernetes 生命周期钩子来执行本章所述的一些动作。另外,我们还可以更进一步,运行使用init容器执行各个动作的容器。在这个序列中,这些选项越来越需要更多的提升,但同时也提供了更强的保障,并实现了重用。

理解容器和Pod生命周期的阶段和可用钩子对于创建Kubernetes管理的应用来说是至关重要的。

3 讨论

云原生平台提供的主要好处之一是能够在潜在的不可靠的云基础设施之上可靠和可预测地运行和扩展应用程序。这些平台为在其上运行的应用程序提供了一系列限制和共识。为了有利于应用程序,云原生平台提供的所有功能都遵守这些机制。处理和响应这些事件可以确保您的应用程序可以优雅地启动和关闭,对消费服务的影响最小。目前,在其基本形式下,这意味着容器应该像任何设计良好的POSIX进程一样行为。在未来,可能会有更多的事件给应用程序提示,当它即将被放大,或要求释放资源以防止被关闭。重要的是要进入这样的思维模式:应用程序的生命周期不再由人控制,而是由平台完全自动化。


原文始发于微信公众号(云原生内经):Kubernetes 设计模式之生命周期管理

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由半码博客整理,本文链接:https://www.bmabk.com/index.php/post/167987.html

(0)

及时掌握行业动态,欢迎加入几百人的后端技术交流群:


相关推荐

  • Google IO —饭后小菜

    Google预览AR眼镜 Google发布会最后还预览Google正在开发中的AR眼镜,戴上以后可以实时显示对方讲话时的字幕,并且可以用作翻译使用。 ❝ 在谷歌展示之前,有报道称这…

    2023年1月15日
    0025
  • Spring AOP 的应用示例

    基于 Spring AOP 实现的 通用实验组件 AB实验/AB测试:https://www.jianshu.com/p/7caa224c2c80 本文主要讲解SpringAOP的…

    2023年4月18日
    0045
  • smtplib、email实现邮件发送

    Python实现发送邮件主要用到smtplib和email模块,其中: smtplib模块主要负责发送邮件的动作、连接邮箱服务器和登录邮箱等操作。 email模块用于管理电子邮件消…

    2024年2月29日
    0011
  • 开放式远程教学平台Edrys

    【突发状况】:主站 vercel 部署失败,根源应该还是在 Github 上,所以今天的文章只有 https://laosu.ga 上才能看到,不想再装 Vercel CLI,等恢…

    2023年1月6日
    0049
  • JavaScript中的this关键字

    在JavaScript中,this关键字是一个非常重要的概念。它在不同的上下文中有不同的含义,可以引用不同的对象。理解this关键字的正确使用方法对于编写高效的JavaScript…

    2023年11月10日
    0038
  • java获取到heapdump文件后,如何快速分析?

    原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,非公众号转载保留此声明。 简介 在之前的OOM问题复盘之后,本周,又一Java服务出现了内存问题,这次问题不严重,只会…

    2023年11月6日
    0074
  • 词向量之ELMO——Transformer时代的LSTM拥趸者

    朋友们好,我是Zarc。 “上期介绍了NNLM、Word2Vec、FastText、GloVe这些静态的预训练词向量模型,这些模型的本质上都是将一个词在整合整个语料库的…

    2023年2月2日
    0049
  • Docker释放磁盘空间以及优化性能

    在Docker的日常使用中,我们或许偶尔遇到下面这些情况: $ docker-compose ps[27142] INTERNAL ERROR: cannot create tem…

    2023年8月3日
    00157
  • Elasticsearch文档写入、更新、删除操作

    ES的文档类比关系型数据库中的表数据,添加的数据格式为json格式。本节介绍文档的写入、更新、删除操作。文档的查询操作内容较多,后面会单独写一篇文章详细介绍。以下演示实例均在win…

    2023年12月17日
    0076
  • Redis-事务与持久化

    Redis中的事务与持久化 Redis中的事务 事务的定义 Redis事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来…

    2022年10月30日
    0046

发表回复

登录后才能评论