测试开发之路 测试开发之路--k8s 之 POD 详解 (二)

孙高飞 · 2019年01月12日 · 最后由 相信过程13 回复于 2024年02月07日 · 4725 次阅读

前言

上一篇我们讲了 K8S 中 POD 的一些基础,这一次我们继续来看一些 POD 其他玩法。

restartPolicy

K8S 在设计之初就是要做一套完善的平台。 所以针对其中的服务肯定是要支持高可用,灾难恢复,负载均衡等功能。 而 K8S 也确实提供了诸如 Deployment,Service 等资源对象来协助 POD 完成这些设计。 但是也需要 POD 本身拥有一些机制。restartPolicy 就是其中之一。这个功能就是 Kubernetes 里的 Pod 恢复机制。它是 Pod 的 Spec 部分的一个标准字段,默认值是 Always,意思是不论任何时候 POD 出现了异常,都一定会重新创建。当然用户还可以手动指定这个重启的策略。 它有 3 个值。

  • Always: 不论任何时候,只要 k8s 检测到 POD 不在运行状态,都会尝试重新创建它。
  • OnFailure:只要在 POD 中的容器出现异常时才重启容器, 如果容器是处于 complete 状态,也就是正常退出的状态,是不会重启的
  • Nerver:从来不重启容器。

注意:如果 POD 中存在多个容器 (不包括 pause 容器),那么只有所有容器都都进入异常状态后,POD 的状态才会是 Failure,否则仍然是 running 状态。

我们需要根据自己的业务形态来合理的设置这个值, 如果我们的容器是一个在线的服务,那么可能设置为默认的 Always 是比较合理的,因为我们期望它能够在异常的时候自动重启来保持服务状态, 当然如果我们是在测试环境中,可能希望这个值是 Nerver 比较好, 因为有些时候我们希望能保留现场。 而如果是离线的 task,比如运行一个测试任务,那么设置为 OnFailure 是比较合理的,也就是只有在出现异常的时候才会重跑任务,而程序正常退出处于 complete 状态的时候,是不会触发重启策略的。

探针

拥有了 restartPolicy 这种在出现异常时的恢复机制, 我们就为高可用打下了第一个基础。 那么接下来我们就要考虑另外一件事了, 就是我们如何发现 POD 出现了异常呢? 如果是一些比较严重的异常,比如 OOM 或者容器内 1 号进程异常退出。面对这种异常我们是不需要增加任何机制 k8s 就能检测到并根据 restartPolicy 进行重启。 但是我们面对的大多数情况都是 k8s 无法自动检测出的异常。比如容器内进程仍然存在,但是已经因为一些异常无法对外正常提供服务了。 所以为了解决这种健康检查问题,k8s 为我们提供了两种探针:livenessProbe 和 readnessProbe

  • readnessProbe:用来探后容器启动后服务是否达到 ready 状态,k8s 一旦探测到容器中的服务在启动后达到了可以对外服务的状态,就会将 POD 设置为 Running 状态,从此这个探针就会失效。 而如果在探针有效期内容器中的服务一直没有处于 ready 状态,就会把 POD 标记为异常状态并触发 POD 的 restartPolicy
  • livenessProbe:在容器启动后,周期性的持续对容器中的服务进行探活,如果发现容器内的服务处于异常状态,就会将 POD 标记为异常状态并触发 POD 的 restartPolicy

下面我们看一个例子:

livenessProbe:
  failureThreshold: 3
  periodSeconds: 5
  httpGet:
    path: /grid/console
    port: 4444
  initialDelaySeconds: 30
  timeoutSeconds: 5
readinessProbe:
  failureThreshold: 3
  periodSeconds: 5
  httpGet:
    path: /grid/console
    port: 4444
  initialDelaySeconds: 10
  timeoutSeconds: 5

上面是我使用 k8s 部署 selenium grid 时针对 hub pod 做的健康检查。我们来看看这两个探针是怎么玩的。 探针的方式有数种:

  • ExecAction:在 container 中执行指定的命令。当其执行成功时,将其退出码设置为 0;
  • TCPSocketAction:执行一个 TCP 检查使用 container 的 IP 地址和指定的端口作为 socket。如果端口处于打开状态视为成功;
  • HTTPGetAction:执行一个 HTTP 默认请求使用 container 的 IP 地址和指定的端口以及请求的路径作为 url,用户可以通过 host 参数设置请求的地址,通过 scheme 参数设置协议类型 (HTTP、HTTPS) 如果其响应代码在 200~400 之间,设为成功。

而我使用的是 httpGet 的方式,用来探测 grid hub 服务的健康状态。 我们看这两个探针的使用方式几乎是一样的, 连字段都一模一样。 不同的是他们的目标。 livenessProbe 是在容器运行时周期性的对服务进行探活,是一直不停的。 而 readinessProbe 只是用来探测容器中的服务是否启动成功, 一旦成功后就会失效。 他们分别再之后要说的关于 Service 的负载均衡策略中分别扮演了不同的角色。 这个之后我们再说。接下来我们看看在探针中常用的字段。

  • initialDelaySeconds:探针的初次探活的延迟时间, 也就是说在容器启动后多长的延迟时间后,探针才开始运作。很多服务的启动时间很长,所以需要设置这个参数来预留足够的时间,避免服务因为启动时间过长, 但是探针已经开始运作而导致了探针的失败。
  • failureThreshold:探测时连续失败几次视为探测异常。 这个算是一个重试机制,有些时候因为网络卡顿或者一些暂时性的原因,导致探测失败。 那么我们可以设置这个重试机制来增加容错性
  • periodSeconds:每一次探活的间隔时间
  • timeoutSeconds:探活时的超时时间
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!
共收到 1 条回复 时间 点赞

高飞老师,近期都在读你的书,关于探测服务异常需要的最长时间计算公式。gtp4.0 给出了另一个解释:这个公式(书中的公式)可能会误导认为每次失败探测都会消耗 periodSeconds 加上 timeoutSeconds 的时间,但实际上 timeoutSeconds 应该是在 periodSeconds 的周期内考虑的。periodSeconds 定义了两次探测尝试之间的间隔,而 timeoutSeconds 是探测尝试等待响应的时间。在大多数情况下,timeoutSeconds 小于 periodSeconds,且超时时间包含在周期时间内。
它给出的公式是:最长时间 = (failureThreshold - 1) * periodSeconds + timeoutSeconds

不知道是否正确呢

需要 登录 后方可回复, 如果你还没有账号请点击这里 注册