云平台将故障Pod流量下线通用思路与OpenShift操作实战

1 写在前边

自从公司项目前年上了 OpenShift 3.9 私有云平台,更新部署程序的确变得更加容易了。但是带来了很多复杂性,运维实施人员的学习曲线也陡然上升。

上云之前:在项目没上容器云的早期,应用服务集群往往是由一个 Nginx 作为负载均衡器,当有集群中有一个节点出现故障时,只需要将 Nginx 上负载均衡块 upstream 块中的故障节点地址移除,刷新 Nginx 即可达到快速响应,也能慢慢收集性能指标进行分析。

上云之后:在云上部署应用,应用容器生命周期由 Deployment 管理,多实例集群由 Service 负载流量 (本文暂时不谈服务网格)。当应用集群中某个Pod出现故障,通过 Deployment 或 Service 并不能直接把某个 Pod 从流量负载中移出,使用存活探针没办法收集性能指标(Pod 自动重启或重建),使用就绪探针需要开发可靠的就绪检测接口(严重依赖程序员)。以下是k8s部署简图

就绪探针:能从流量中移出无响应 Pod,严重依赖检测健康的接口可靠度。

存活探针:流量中移除无响应Pod,并重建或重启 Pod。

2 核心诉求

看了上边的内容,可明确的诉求有以下两点:

  1. 能够快速流量下线故障节点,给客户快速响应,客户无需长时间等待,提高客户满意度。
  2. 保留故障节点供深度分析故障原因。

3 梳理思路

3.1 流量从哪里来?

对于 Pod 而言,流量来自于 Service。初学 K8s 时,都会看到类似下边的图,大意是 Service 是通过 Selector 配置的 label 来匹配 Pod 的。

那么,Service 直接连接到了 Pod 上么?

这样说并不准确,Service 与 Pod 中间还有一种资源 —— Endpoints,Service 通过 Selector 将匹配到的 IP 和端口列表存入 Endpoints。当流量到达网络代理(KubeProxy)时,网络代理会从众多 Endpoints 中找出目标 Endpoints 并取出其中一个地址进行转发。

所以,流量能进入 Pod 和 Endpoints 关系很大,由 Service 维护 Endpoints,最终由网络代理建立网络转发规则。

3.2 如何切断流量?

我们知道 Endpoints 才是流量能否到达 Pod 的关键,将 Pod 移出 Endpoints 切断流量的具体的方法:

  • 通过变更 Service 匹配 label 来影响 Endpoints
    • 改变 label 的 Key 与 Value 都可以。
  • 就绪探针(Readiness Probe)配合可靠的检测接口
    • 就绪探针可以使检测失败的 Pod 临时移出 Endpoints,待检测通过再加回来。
    • 需要注意的是就绪探针需要可靠的检测接口,否则有可能出现反复上下线,导致明显卡顿感。

4 解决方案

4.1 临时解决方案

简单的探活接口 + 就绪探针 + 手动下线

适用场景

适用于业务应用没有可靠就绪检测接口,仅有简单的探活接口,配合就绪探针舒缓问题,等到人工介入,将正在反复流量上下线的程序快速移出 Endpoints。

配置方式

  • 就绪探针:推荐使用 HttpGet 类型,初始延迟(initial delay)按 Pod 开始启动到能提供服务时间加上 10s 左右为宜,检测周期(period)在10~20s内为宜,就绪探针接口配置为探活接口地址

特点

  • 优点
    • 简单,不需要开发人员投入太多。
  • 缺点
    • 出现故障时,Pod 会反复上下线,影响用户体验。
    • 需要人工介入。

4.2 长期解决方案

简单的探活接口 + 低频存活探针 + 可靠的就绪接口 + 就绪探针 + 手动下线

适用场景

适用于业务应用有可靠的就绪检测接口,有探活接口的情况。

  • 当 Pod 出现未就绪状态时,由就绪检测探针确定未就绪状态并将其自动流量下线。
    • 自动流量下线后,如果未经人工干预能自行恢复,则自动流量上线。
    • 自动流量下线后,如果出现无响应,存活探针检测连续3次失败,则自动重启或重建。
    • 在自动流量下线后与存活探针连续检测3次失败之前,手动下线移出管理(Deployment/Service/Health Check)供收集性能指标分析定位问题原因。
      • 低频存活检测有助于延长人工介入操作时间。
      • 当 Pod 重启或重建后,原始故障可能无法复现。
  • 当 Pod 突然出现无响应状态,存活探针检测连续3次失败,则自动重启或重建。

配置方式

  • 就绪探针:推荐使用 HttpGet 类型,初始延迟(initial delay)按 Pod 开始启动到能提供服务时间加上 10s 左右为宜,检测周期(period)在 10~20s 为宜,就绪探针接口配置为就绪检测接口地址
  • 存活探针:推荐使用 HttpGet 类型,初始延迟(initial delay)按 Pod 开始启动到能提供服务时间加上 60s 左右为宜,检测周期(period)在 20~30s 为宜,存活探针接口配置为探活检测接口地址

特点

  • 优点
    • 根据服务情况自动进行适当处理。
      • 未就绪则下线
      • 就绪则上线
      • 无响应重启/重建
    • 几乎无需人工介入,定位问题除外。
  • 缺点
    • 就绪检测接口需要开发人员精心设计。
      • 如就绪状态时返回200状态码,未就绪返回500状态码
      • 需要准确评估出应用的状态
    • 开发人员远程调试需要临时关闭存活探针。

5 OpenShift手动下线故障Pod操作步骤

本操作步骤基于通过变更 Service 匹配 label 来影响 Endpoints 的思路。

这里以测试环境 bi 程序举例,通过 Deployment 处的 ActionsEdit Yaml 打开如下界面,确定 Service 匹配的 label。

可以看到 selector 选择的 label 为 deloymentConfig: bi,这样我们就能确认 Pod 必须也有这个标签,那么我们去修改故障节点。

退出编辑 yaml 界面,可以看到该 Service 对应的 Pod 列表,这里以 bi-4-7dt6r 作为故障节点演示,点击 bi-4-7dt6r

进入 bi-4-7dt6r Pod 界面,依次点击 ActionsEdit yaml,我们找到与 Service 中同样的标签(注意大小写)

修改 deloymentConfig: bideloymentConfig: bi-debug,只要标签不同即可,然后 Save

回到 Service 界面,如下图,原来的 bi-4-7dt6r 已经不在负载列表中了

我们再去 Pods 界面查看 bi-4-7dt6r 是否依然存在,如图,原来的 Pod 依然存在。

主要目标——断开流量已经达成,至于为什么会创建了一个新的 Pod 呢?

打开这个应用的 Deployment yaml,我们可以看到:原来 Deployment 匹配 Pod 的标签也是 deloymentConfig: bi

这也很好解释自动创建新节点的原因了:由于 DeploymentConfig 查询不到它期待的3个 Pod 副本数,就创建了一个新的!

以上,今天要分享的内容都在这里了。如果本文对你有所启发,请为我送上一个赞吧!如有错漏处,还望评论告知一二!

我是 Hellxz,我们下次再见!

参考书目《Kubernetes in Action》

页面下部广告