做者| 阿里雲智能事業羣技術專家牛秋霖(冬島)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。
**
這個健康檢查是調用的 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等技術領域、聚焦雲原生流行技術趨勢、雲原生大規模的落地實踐,作最懂雲原生開發者的技術公衆號。」