本文轉載自:宋淨超的部落格
本文介紹了 Istio 和 Kubernetes 中的一些服務和流量的抽象模型。雖然 Istio 一開始確定的抽象模型與對接的底層平臺無關,但目前來看基本繫結 Kubernetes,本文僅以 Kubernetes 說明。另外在 ServiceMesher 社群中最近有很多關於 Istio、Envoy、Kubernetes 之中的服務模型關係的討論,本文作為一個開篇說明,Kubernetes 和 Isito 之間有哪些共有的服務模型,Istio 在 Kubernetes 的服務模型之上又增加了什麼。
服務具有多個版本。在 CI/CD 過程中,同一個服務可能同時部署在多個環境中,如開發、生產和測試環境等,這些服務版本不一定具有不同的 API,可能只是一些小的更改導致的迭代版本。在 A/B 測試和灰度釋出中經常遇到這種情況。
Kubernetes 與 Istio 中共有的模型
因為 Istio 基本就是繫結在 Kubernetes 上,下面是我們熟知的 Kubernetes 及 Istio 中共有的服務模型。
上圖是 Kubernetes 中 iptables 代理模式(另外還有 IPVS 模式)下的 service 概念圖,管理員可以在 kube-proxy 中配置簡單的負載均衡,對整個 node 生效,無法配置到單個服務的負載均衡和其他微服務的高階功能,例如熔斷、限流、追蹤等,這些功能只能在應用中實現了,而在 Istio 的概念模型中完全去掉了 kube-proxy
這個元件,將其分散到每個應用 Pod 中同時部署的 Envoy 中實現。
下面列舉的是 Kubernetes 和 Istio 中共有的模型。
Service
這實際上跟 Kubernetes 中的 service 概念是一致的,請參考 Kubernetes 中的 service。Istio 推出了比 service 更復雜的模型 VirtualService
,這不單純是定義一個服務定義了,而是在服務之上定義了路由規則。
每個服務都有一個完全限定的域名(FQDN),監聽一個或多個埠。服務還可以有與其相關聯的單個負載均衡器或虛擬 IP 地址。針對 FQDN 的 DNS 查詢將解析為該負載均衡器或者虛擬 IP 的地址。
例如 Kubernetes 中一個服務為 foo.default.svc.cluster.local hostname
,虛擬 IP /ClusterIP 是 10.0.1.1,監聽的埠是 80 和 8080。
Endpoint
這裡指的是 Kubernetes 中的 endpoint,一個 endpoint 是實現了某服務的具體例項,一個服務可能有一個或者多個 Endpoint,表示為 IP 地址加埠,也可以為 DNS 名稱加埠。
其實到底哪些例項屬於同一個 service,還是需要 通過 label 匹配來選擇。
Label
服務的版本、對應的引用名稱等是通過 label 來標記的,例如下面 Kubernetes 中一個應用的 YAML 配置。
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: ratings-v1
spec:
replicas: 1
template:
metadata:
labels:
app: ratings
version: v1
spec:
containers:
- name: ratings
image: istio/examples-bookinfo-ratings-v1:1.8.0
imagePullPolicy: IfNotPresent
ports:
- containerPort: 9080複製程式碼
version: v1
標記該服務是 v1 版本,version
是一個約定俗稱的標籤,建議大家的服務上都帶上該標籤。
當然服務的 label 可以設定任意多個,這樣的好處是在做路由的時候可以根據標籤匹配來做細粒度的流量劃分。
控制皮膚 Envoy
Envoy 是 Istio 中預設的 proxy sidecar,負責服務間的流量管控、認證與安全加密、可觀察性等。Envoy 中有如下幾個重要概念。
上圖是 Envoy 的架構圖。
Cluster
叢集(cluster)是 Envoy 連線到的一組邏輯上相似的上游主機。Envoy 通過服務發現發現叢集中的成員。Envoy 可以通過主動執行狀況檢查來確定叢集成員的健康狀況。Envoy 如何將請求路由到叢集成員由負載均衡策略確定。
這個與 Kubernetes 中的 Service 概念類似,只不過 Kubernetes 中的服務發現中並不包含健康狀況檢查,而是通過配置 Pod 的 liveness 和 readiness 探針來實現,服務發現預設也是通過 DNS 來實現。
Listener
監聽器(listener)是可以由下游客戶端連線的命名網路位置(例如,埠、unix域套接字等)。Envoy 公開一個或多個下游主機連線的偵聽器。一般是每臺主機執行一個 Envoy,使用單程式執行,但是每個程式中可以啟動任意數量的 Listener(監聽器),目前只監聽 TCP,每個監聽器都獨立配置一定數量的(L3/L4)網路過濾器。Listenter 也可以通過 Listener Discovery Service(LDS)動態獲取。
Listener filter
Listener 使用 listener filter(監聽器過濾器)來操作連結的後設資料。它的作用是在不更改 Envoy 的核心功能的情況下新增更多的整合功能。Listener filter 的 API 相對簡單,因為這些過濾器最終是在新接受的套接字上執行。在鏈中可以互相銜接以支援更復雜的場景,例如呼叫速率限制。Envoy 已經包含了多個監聽器過濾器。
Istio 中增加的流量模型
VirtualService
、DestinationRule
、Gateway
、ServiceEntry
和 EnvoyFilter
都是 Istio 中為流量管理所建立的 CRD,這些概念其實是做路由管理,而 Kubernetes 中的 service 只是用來做服務發現,所以以上其實也不能成為 Istio 中的服務模型,但其實它們也是用來管理服務的,如果流量不能路由的建立的服務上面去,那服務的存在又有何意義?在 Service Mesh 真正的服務模型還是得從 Envoy 的 xDS 協議來看,其中包括了服務的流量治理,服務的斷點是通過 EDS 來配置的。
上圖是 Pilot 設計圖,來自Istio Pilot design overview。
Routing
Kubernetes 中的 service 是沒有任何路由屬性可以配置的,Istio 在設計之初就通過在同一個 Pod 中,在應用容器旁執行一個 sidecar proxy 來透明得實現細粒度的路由控制。
VirtualService
VirtualService
定義針對指定服務流量的路由規則。每個路由規則都針對特定協議的匹配規則。如果流量符合這些特徵,就會根據規則傳送到服務登錄檔中的目標服務(或者目標服務的子集或版本)。對於 A/B 測試和灰度釋出等場景,通常需要使用劃分 subset
,VirtualService 中根據 destination 中的 subset 配置來選擇路由,但是這些 subset 究竟對應哪些服務示例,這就需要 DestionationRule
。詳情請參考 VirtualService。
DestinationRule
DestinationRule
所定義的策略,決定了經過路由處理之後的流量的訪問策略。這些策略中可以定義負載均衡配置、連線池尺寸以及外部檢測(用於在負載均衡池中對不健康主機進行識別和驅逐)配置。詳情請參考 DestinationRule。
Gateway
Gateway
描述了一個負載均衡器,用於承載網格邊緣的進入和發出連線。這一規範中描述了一系列開放埠,以及這些埠所使用的協議、負載均衡的 SNI 配置等內容。
這個實際上就是定義服務網格的邊緣路由。詳情請參考 Gateway。
ServiceEntry
ServiceEntry
能夠在 Istio 內部的服務登錄檔中加入額外的條目,從而讓網格中自動發現的服務能夠訪問和路由到這些手工加入的服務。ServiceEntry
描述了服務的屬性(DNS 名稱、VIP、埠、協議以及端點)。這類服務可能是網格外的 API,或者是處於網格內部但卻不存在於平臺的服務登錄檔中的條目(例如需要和 Kubernetes 服務溝通的一組虛擬機器服務)。
如果沒有配置 ServiceEntry 的話,Istio 實際上是無法發現服務網格外部的服務的。
EnvoyFilter
EnvoyFilter
物件描述了針對代理服務的過濾器,這些過濾器可以定製由 Istio Pilot 生成的代理配置。這一功能一定要謹慎使用。錯誤的配置內容一旦完成傳播,可能會令整個服務網格進入癱瘓狀態。詳情請參考 EnvoyFilter。
Envoy 中的 listener 可以配置多個 filter,這也是一種通過 Istio 來擴充套件 Envoy 的機制。