Knative Serving 健康检查机制分析

本文涉及的产品
性能测试 PTS,5000VUM额度
应用实时监控服务-应用监控,每月50GB免费额度
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
简介: 从头开发一个 Serverless 引擎并不是一件容易的事情,今天咱们就从 Knative 的健康检查说起。通过健康检查这一个点来看看 Serverless 模式和传统的模式都有哪些不同以及 Knative 针对 Serverless 场景都做了什么思考。

本文选自《Knative 云原生应用开发指南》
knative海报.png

从头开发一个 Serverless 引擎并不是一件容易的事情,今天咱们就从 Knative 的健康检查说起。通过健康检查这一个点来看看 Serverless 模式和传统的模式都有哪些不同以及 Knative 针对 Serverless 场景都做了什么思考。

Knative Serving 模块的核心原理如下图所示。下图中的 Route 可以理解成是 Istio Gateway 的角色。

  • 当缩容到零时进来的流量就会指到 Activator 上面
  • 当 Pod 数不为零时流量就会指到对应的 Pod 上面,此时流量不经过 Activator
  • 其中 Autoscaler 模块根据请求的 Metrics 信息实时动态的扩缩容

1.png

Knative 的 Pod 是由两个 Container 组成的: Queue-Proxy 和业务容器 user-container。架构如下:

2.png

咱们以 http1 为例进行说明。业务流量首先进入 Istio Gateway,然后会转发到 Queue-Proxy 的 8012 端口,Queue-Proxy 8012 再把请求转发到 user-container 的监听端口,至此一个业务请求的服务就算完成了。

粗略的介绍原理基本就是上面这样,现在咱们对几个细节进行深入的剖析看看其内部机制:

  • 为什么要引入 Queue-Proxy?
  • Pod 缩容到零的时候流量会转发到 Activator 上面,那么 Activator 是怎么处理这些请求的?
  • Knative 中的业务 Pod 有 Queue-Proxy 和 user-container,那么 Pod 的 readinessProber 和 LivenessProber 分别是怎么做的?Pod 的 readinessProber、 LivenessProber 和业务的健康状态是什么样的关系?
  • Istio Gateway 向 Pod 转发流量的时候是怎么选择 Pod 进行转发的?

为什么要引入 Queue-Proxy

Serverless 的一个核心诉求就是把业务的复杂度下沉到基础平台,让业务代码快速的迭代并且按需使用资源。不过现在更多的还是聚焦在按需使用资源层面。

如果想要按需使用资源我们就需要收集相关的 Metrics,并根据这些 Metrics 信息来指导资源的伸缩。Knative 首先实现的就是 KPA 策略,这个策略是根据请求数来判断是否需要扩容的。所以 Knative 需要有一个机制收集业务请求数量。除了业务请求数还有如下信息也是需要统一处理:

  • 访问日志的管理
  • Tracing
  • Pod 健康检查机制
  • 需要实现 Pod 和 Activator 的交互,当 Pod 缩容到零的时候如何接收 Activator 转发过来的流量
  • 其他诸如判断 Ingress 是否 Ready 的逻辑也是基于 Queue-Proxy 实现的

为了保持和业务的低耦合关系,还需要实现上述这些功能所以就引入了 Queue-Proxy 负责这些事情。这样可以在业务无感知的情况下把 Serverless 的功能实现。

从零到一的过程

当 Pod 缩容到零的时候流量会指到 Activator 上面,Activator 接收到流量以后会主动“通知”Autoscaler 做一个扩容的操作。扩容完成以后 Activator 会探测 Pod 的健康状态,需要等待第一个 Pod ready 之后才能把流量转发过来。所以这里就出现了第一个健康检查的逻辑:Activator 检查第一个 Pod 是否 ready

这个健康检查是调用的 Pod 8012 端口完成的,Activator 会发起 HTTP 的健康检查,并且设置  K-Network-Probe=queue Header,所以 Queue Container 中会根据 K-Network-Probe=queue 来判断这是来自 Activator 的检查,然后执行相应的逻辑。

参考阅读

VirtualService 的健康检查

Knative Revision 部署完成以后就会自动创建一个 Ingress(以前叫做 ClusterIngress), 这个 Ingress 最终会被 Ingress Controller 解析成 Istio 的 VirtualService 配置,然后 Istio  Gateway 才能把相应的流量转发给相关的 Revision。

所以每添加一个新的 Revision 都需要同步创建 Ingress 和 Istio 的 VirtualService ,而 VirtualService 是没有状态表示 Istio 的管理的 Envoy 是否配置生效的能力的。所以 Ingress Controller 需要发起一个 http 请求来监测 VirtualService 是否 ready。这个 http 的检查最终也会打到 Pod 的 8012 端口上。标识 Header 是 K-Network-Probe=probe 。Queue-Proxy 需要基于此来判断,然后执行相应的逻辑。

相关代码如下所示:

https://github.com/knative/serving/blob/master/pkg/network/probe_handler.go#L37

3.png

https://github.com/knative/serving/blob/master/pkg/reconciler/ingress/status.go#L348

4.png

参考阅读

Gateway 通过这个健康检查来判断 Pod 是否可可以提供服务

Kubelet 的健康检查

Knative 最终生成的 Pod 是需要落实到 Kubernetes 集群的,Kubernetes 中 Pod 有两个健康检查的机制 ReadinessProber 和 LivenessProber。其中 LivenessProber 是判断 Pod 是否活着,如果检查失败 Kubelet 就会尝试重启 Container,ReadinessProber 是来判断业务是否 Ready,只有业务 Ready 的情况下才会把 Pod 挂载到 Kubernetes Service 的 EndPoint 中,这样可以保证 Pod 故障时对业务无损。

那么问题来了,Knative 的 Pod 中默认会有两个 Container:Queue-Proxy 和 user-container 。前面两个健康检查机制你应该也发现了,流量的“前半路径”需要通过 Queue-Proxy 来判断是否可以转发流量到当前 Pod,而在 Kubernetes 的机制中 Pod 是否加入 Kubernetes Service EndPoint 中完全是由 ReadinessProber 的结果决定的。而这两个机制是独立的,所以我们需要有一种方案来把这两个机制协调一致。这也是 Knative 作为一个 Serverless 编排引擎是需要对流量做更精细的控制要解决的问题。所以 Knative 最终是把 user-container 的 ReadinessProber 收敛到 Queue-Proxy 中,通过 Queue-Proxy 的结果来决定 Pod 的状态。

另外 https://github.com/knative/serving/issues/2912 这个 Issue 中也提到在启动 istio 的情况下,kubelet 发起的 tcp 检查可能会被 Envoy 拦截,所以给 user-container 配置 TCP 探测器判断 user-container 是否 ready也是不准的。这也是需要把 Readiness 收敛到 Queue-Proxy 的一个动机。

Knative 收敛 user-container 健康检查能力的方法是:

  • 置空 user-container 的 ReadinessProber
  • 把 user-container 的 ReadinessProber 配置的 json String 配置到 Queue-Proxy 的 env 中
  • Queue-Proxy 的 Readinessprober 命令里面解析  user-container 的 ReadinessProber 的 json String 然后实现健康检查逻辑。并且这个检查的机制和前面提到的 Activator 的健康检查机制合并到了一起。这样做也保证了 Activator 向 Pod 转发流量时 user-container 一定是  Ready 状态

参考阅读

使用方法

如下所示可以在 Knative Service 中定义 Readiness

apiVersion: serving.knative.dev/v1alpha1
kind: Service
metadata:
  name: readiness-prober
spec:
  template:
    metadata:
      labels:
        app: helloworld-go
    spec:
      containers:
        - image: registry.cn-hangzhou.aliyuncs.com/knative-sample/helloworld-go:160e4db7
          readinessProbe:
            httpGet:
              path: /
            initialDelaySeconds: 3

但是需要说明两点:

  1. 和原生的 Kubernetes Pod Readiness 配置相比,Knative 中 timeoutSeconds、failureThreshold、periodSeconds 和 successThreshold 如果要配置就要一起配置,并且不能为零,否则 Knative webhook 校验无法通过。并且如果设置了 periodSeconds 那么一旦出现一次 Success,就再也不会去探测 user-container(不建议设置 periodSeconds,应该让系统自动处理 )
  2. 如果 periodSeconds 没有配置那么就会使用默认的探测策略,默认配置如下
timeoutSeconds: 60
            failureThreshold: 3
            periodSeconds: 10
            successThreshold: 1

从这个使用方式上来看其实 Knative 是在逐渐收敛 user-container 配置,因为在 Serverless 模式中需要系统自动化处理很多逻辑,这些“系统行为”就不需要麻烦用户了。

小结

前面提到的三种健康检查机制的对比关系:

Probe Request Source Path Extra features comment
Activator probe requests :8012 With header K-Network-Probe=queue. Expected queue as response body. Probe requests from Activator before it proxies external requests
VirtualService/Gateway probe requests :8012 With header K-Network-Probe=probe and non-empty K-Network-Hash header This is used to detect which version of a VirtualService an Envoy Pod is currently serving. They are proxied from VirtualService to activator/queue-proxy.
Kubelet probe requests :8012 With non-empty K-Kubelet-Probe header or with header user-agent=kube-probe/* I don't think currently kubectl sends probe requests to this path. We can delete it. Correct me if I was wrong.

阿里巴巴云原生关注微服务、Serverless、容器、Service Mesh 等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,做最懂云原生开发者的技术圈。”

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
3月前
|
运维 Kubernetes Serverless
Kubernetes 的架构问题之在ECI中Logtail agent作为Hidecar实现如何解决
Kubernetes 的架构问题之在ECI中Logtail agent作为Hidecar实现如何解决
89 3
|
6月前
|
存储 Kubernetes 监控
Kubernetes(k8s)集群健康检查常用的五种指标
Kubernetes(k8s)集群健康检查常用的五种指标
928 1
|
存储 Kubernetes 中间件
【无服务器架构】Knative Serving 介绍
【无服务器架构】Knative Serving 介绍
|
Kubernetes 监控 Cloud Native
容器服务 ACK 结合 MSE Ingress,让集群入口流量管理更丰富、更容易
阿里云容器服务 Kubernetes 版(简称容器服务 ACK)提供高性能的容器化应用管理服务,让用户轻松高效地在云端运行 Kubernetes 容器化应用。
容器服务 ACK 结合 MSE Ingress,让集群入口流量管理更丰富、更容易
|
监控 Kubernetes Cloud Native
容器服务ACK结合MSE Ingress,让集群入口流量管理更丰富、更容易
作为Ingress Controller新选择MSE Ingress,我们始终立足用户视角,从用户真实业务场景出发,不断完善和优化Ingress使用体验,后续我们会持续在产品的性能、易用性、稳定性和生态方面持续打磨,以便用户无门槛的享受到云原生技术的红利。
容器服务ACK结合MSE Ingress,让集群入口流量管理更丰富、更容易
|
Kubernetes 负载均衡 Java
Istio:服务发现和Pilot的架构机制
Istio:服务发现和Pilot的架构机制
1939 0
Istio:服务发现和Pilot的架构机制
|
Kubernetes 监控 测试技术
knative serving 组件分析
knative serving 组件分析。
374 0
|
Dragonfly 运维 Kubernetes
在大规模 Kubernetes 集群上实现高 SLO 的方法
随着 Kubernetes 集群规模和复杂性的增加,集群越来越难以保证高效率、低延迟的交付 pod。本文将分享蚂蚁金服在设计 SLO 架构和实现高 SLO 的方法和经验。
在大规模 Kubernetes 集群上实现高 SLO 的方法
|
弹性计算 调度 混合部署
ACK Istio ingress gateway 生产调优
istio ingress gateway 生产配置调优
2806 0
ACK Istio ingress gateway 生产调优
|
算法 Perl 容器
Knative 基本功能深入剖析:Knative Serving 自动扩缩容 Autoscaler
Knative Serving 默认情况下,提供了开箱即用的快速、基于请求的自动扩缩容功能 - Knative Pod Autoscaler(KPA)。下面带你体验如何在 Knative 中玩转 Autoscaler。