天天看點

Knative Serving 健康檢查機制分析

Knative Serving 健康檢查機制分析

作者|  阿裡雲智能事業群技術專家牛秋霖(冬島)

導讀:從頭開發一個Serverless引擎并不是一件容易的事情,今天咱們就從Knative的健康檢查說起。通過健康檢查這一個點來看看Serverless模式和傳統的模式都有哪些不同,以及Knative針對Serverless場景都做了什麼思考。

Knative Serving 子產品的核心原理如下圖所示,圖中的 Route 可以了解成是 Istio Gateway 的角色。

  • 當縮容到零時進來的流量就會指到 Activator 上面;
  • 當 Pod 數不為零時流量就會指到對應的 Pod 上面,此時流量不經過 Activator;
  • 其中 Autoscaler 子產品根據請求的 Metrics 資訊實時動态的擴縮容。
Knative Serving 健康檢查機制分析

Knative 的 Pod 是由兩個 Container 組成的:Queue-Proxy 和業務容器 user-container。架構如下:

Knative Serving 健康檢查機制分析

咱們以 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 需要基于此來判斷,然後執行相應的邏輯。

相關代碼如下所示:

Knative Serving 健康檢查機制分析
圖檔來源
Knative Serving 健康檢查機制分析

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 的狀态。

另外

這個 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 模式中需要系統自動化處理很多邏輯,這些“系統行為”就不需要麻煩使用者了。

小結

前面提到的三種健康檢查機制的對比關系:

Knative Serving 健康檢查機制分析
“ 阿裡巴巴雲原生微信公衆号(ID:Alicloudnative)關注微服務、Serverless、容器、Service Mesh等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,做最懂雲原生開發者的技術公衆号。”