做者| 阿里云智能事业群技术专家牛秋霖(冬岛)git
导读:从头开发一个Serverless引擎并非一件容易的事情,今天我们就从Knative的健康检查提及。经过健康检查这一个点来看看Serverless模式和传统的模式都有哪些不一样,以及Knative针对Serverless场景都作了什么思考。github
Knative Serving 模块的核心原理以下图所示,图中的 Route 能够理解成是 Istio Gateway 的角色。web
Knative 的 Pod 是由两个 Container 组成的:Queue-Proxy 和业务容器 user-container。架构以下:json
我们以 http1 为例进行说明:业务流量首先进入 Istio Gateway,而后会转发到 Queue-Proxy 的 8012 端口,Queue-Proxy 8012 再把请求转发到 user-container 的监听端口,至此一个业务请求的服务就算完成了。api
粗略的介绍原理基本就是上面这样,如今我们对几个细节进行深刻的剖析看看其内部机制:微信
Serverless 的一个核心诉求就是把业务的复杂度下沉到基础平台,让业务代码快速迭代而且按需使用资源。不过如今更多的仍是聚焦在按需使用资源层面。架构
若是想要按需使用资源咱们就须要收集相关的 Metrics,并根据这些 Metrics 信息来指导资源的伸缩。Knative 首先实现的就是 KPA 策略,这个策略是根据请求数来判断是否须要扩容的。因此 Knative 须要有一个机制收集业务请求数量。除了业务请求数还有以下信息也是须要统一处理:app
为了保持和业务的低耦合关系,还须要实现上述这些功能,因此就引入了 Queue-Proxy 负责这些事情。这样能够在业务无感知的状况下把 Serverless 的功能实现。less
当 Pod 缩容到零的时候流量会指到 Activator 上面,Activator 接收到流量之后会主动“通知”Autoscaler 作一个扩容的操做。扩容完成之后 Activator 会探测 Pod 的健康状态,须要等待第一个 Pod ready 以后才能把流量转发过来。因此这里就出现了第一个健康检查的逻辑:Activator 检查第一个 Pod 是否 ready。<br />**<br />这个健康检查是调用的 Pod 8012 端口完成的,Activator 会发起 HTTP 的健康检查,而且设置 K-Network-Probe=queue Header,因此 Queue Container 中会根据 K-Network-Probe=queue 来判断这是来自 Activator 的检查,而后执行相应的逻辑。tcp
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 须要基于此来判断,而后执行相应的逻辑。
相关代码以下所示:
Gateway 经过这个健康检查来判断 Pod 是否能够提供服务。
Knative 最终生成的 Pod 是须要落实到 Kubernetes 集群的,Kubernetes 中 Pod 有两个健康检查的机制:ReadinessProber 和 LivenessProber。
那么问题来了,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 的状态。
另外这个 Issue 中也提到在启动 istio 的状况下,kubelet 发起的 tcp 检查可能会被 Envoy 拦截,因此给 user-container 配置 TCP 探测器判断 user-container 是否 ready 也是不许的。这也是须要把 Readiness 收敛到 Queue-Proxy 的一个动机。
Knative 收敛 user-container 健康检查能力的方法是:
以下所示能够在 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
须要说明两点:
和原生的 Kubernetes Pod Readiness 配置相比,Knative 中 timeoutSeconds、failureThreshold、periodSeconds 和 successThreshold 若是要配置就要一块儿配置,而且不能为零,不然 Knative webhook 校验没法经过。而且若是设置了 periodSeconds,那么一旦出现一次 Success,就不再会去探测 user-container(不建议设置 periodSeconds,应该让系统自动处理)。
若是 periodSeconds 没有配置那么就会使用默认的探测策略,默认配置以下:
timeoutSeconds: 60 failureThreshold: 3 periodSeconds: 10 successThreshold: 1
从这个使用方式上来看,其实 Knative 是在逐渐收敛 user-container 配置,由于在 Serverless 模式中须要系统自动化处理不少逻辑,这些“系统行为”就不须要麻烦用户了。
前面提到的三种健康检查机制的对比关系:
“ 阿里巴巴云原生微信公众号(ID:Alicloudnative)关注微服务、Serverless、容器、Service Mesh等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,作最懂云原生开发者的技术公众号。”