騰訊雲容器團隊內部Istio專題分享

本文轉載自:zhongfox.github.io/2019/01/30/…html

今天分享的內容主要包括如下4個話題:java

  • 1 Service Mesh: 下一代微服務node

  • 2 Istio: 第二代 Service Meshnginx

  • 3 Istio 數據面git

  • 4 Istio 控制面github

首先我會和你們一塊兒過一下 Service Mesh的發展歷程, 並看看Istio 爲 Service Mesh 帶來了什麼, 這部分相對比較輕鬆. 接下來我將和你們分析一下Istio的主要架構, 重點是數據面和控制面的實現, 包括sidecar的注入, 流量攔截, xDS介紹, Istio流量模型, 分佈式跟蹤, Mixer 的適配器模型等等, 中間也會穿插着 istio的現場使用demo.golang

1. Service Mesh: 下一代微服務

  • 應用通訊模式演進算法

  • Service Mesh(服務網格)的出現docker

  • 第二代 Service Meshexpress

  • Service Mesh 的定義

  • Service Mesh 產品簡史

  • 國內Service Mesh 發展狀況

1.1 應用通訊模式演進: 網絡流控進入操做系統

在計算機網絡發展的初期, 開發人員須要在本身的代碼中處理服務器之間的網絡鏈接問題, 包括流量控制, 緩存隊列, 數據加密等. 在這段時間內底層網絡邏輯和業務邏輯是混雜在一塊兒.

隨着技術的發展,TCP/IP 等網絡標準的出現解決了流量控制等問題。儘管網絡邏輯代碼依然存在,但已經從應用程序裏抽離出來,成爲操做系統網絡層的一部分, 造成了經典的網絡分層模式.

1.2 應用通訊模式演進: 微服務架構的出現

微服務架構是更爲複雜的分佈式系統,它給運維帶來了更多挑戰, 這些挑戰主要包括資源的有效管理和服務之間的治理, 如:

  • 服務註冊, 服務發現

  • 服務伸縮

  • 健康檢查

  • 快速部署

  • 服務容錯: 斷路器, 限流, 隔離艙, 熔斷保護, 服務降級等等

  • 認證和受權

  • 灰度發佈方案

  • 服務調用可觀測性, 指標收集

  • 配置管理

在微服務架構的實現中,爲提高效率和下降門檻,應用開發者會基於微服務框架來實現微服務。微服務框架必定程度上爲使用者屏蔽了底層網絡的複雜性及分佈式場景下的不肯定性。經過API/SDK的方式提供服務註冊發現、服務RPC通訊、服務配置管理、服務負載均衡、路由限流、容錯、服務監控及治理、服務發佈及升級等通用能力, 比較典型的產品有:

  • 分佈式RPC通訊框架: COBRA, WebServices, Thrift, GRPC 等

  • 服務治理特定領域的類庫和解決方案: Hystrix, Zookeeper, Zipkin, Sentinel 等

  • 對多種方案進行整合的微服務框架: SpringCloud、Finagle、Dubbox 等

實施微服務的成本每每會超出企業的預期(內容多, 門檻高), 花在服務治理上的時間成本甚至可能高過進行產品研發的時間. 另外上述的方案會限制可用的工具、運行時和編程語言。微服務軟件庫通常專一於某個平臺, 這使得異構系統難以兼容, 存在重複的工做, 系統缺少可移植性.

Docker 和Kubernetes 技術的流行, 爲Pass資源的分配管理和服務的部署提供了新的解決方案, 可是微服務領域的其餘服務治理問題仍然存在.

1.3 Sidecar 模式的興起

Sidecar(有時會叫作agent) 在原有的客戶端和服務端之間加多了一個代理, 爲應用程序提供的額外的功能, 如服務發現, 路由代理, 認證受權, 鏈路跟蹤 等等.

業界使用Sidecar 的一些先例:

  • 2013 年,Airbnb 開發了Synapse 和 Nerve,是sidecar的一種開源實現

  • 2014 年, Netflix 發佈了Prana,它也是一個sidecar,可讓非 JVM 應用接入他們的 NetflixOSS 生態系統

1.4 Service Mesh(服務網格)的出現

直觀地看, Sidecar 到 Service Mesh 是一個規模的升級, 不過Service Mesh更強調的是:

  • 再也不將Sidecar(代理)視爲單獨的組件,而是強調由這些代理鏈接而造成的網絡

  • 基礎設施, 對應用程序透明

1.5 Service Mesh 定義

如下是Linkerd的CEO Willian Morgan給出的Service Mesh的定義:

A Service Mesh is a dedicated infrastructure layer for handling service-to-service communication. It’s responsible for the reliable delivery of requests through the complex topology of services that comprise a modern, cloud native application. In practice, the Service Mesh is typically implemented as an array of lightweight network proxies that are deployed alongside application code, without the application needing to be aware.

服務網格(Service Mesh)是致力於解決服務間通信的基礎設施層。它負責在現代雲原生應用程序的複雜服務拓撲來可靠地傳遞請求。實際上,Service Mesh 一般是經過一組輕量級網絡代理(Sidecar proxy),與應用程序代碼部署在一塊兒來實現,且對應用程序透明

1.6 第二代 Service Mesh

控制面板對每個代理實例瞭如指掌,經過控制面板能夠實現代理的訪問控制和度量指標收集, 提高了服務網格的可觀測性和管控能力, Istio 正是這類系統最爲突出的表明.

1.7 Service Mesh 產品簡史

  • 2016 年 1 月 15 日,前 Twitter 的基礎設施工程師 William Morgan 和 Oliver Gould,在 GitHub 上發佈了 Linkerd 0.0.7 版本,採用Scala編寫, 他們同時組建了一個創業小公司 Buoyant,這是業界公認的第一個Service Mesh

  • 2016 年,Matt Klein在 Lyft 默默地進行 Envoy 的開發。Envoy 誕生的時間其實要比 Linkerd 更早一些,只是在 Lyft 內部不爲人所知

  • 2016 年 9 月 29 日在 SF Microservices 上,「Service Mesh」這個詞彙第一次在公開場合被使用。這標誌着「Service Mesh」這個詞,從 Buoyant 公司走向社區.

  • 2016 年 9 月 13 日,Matt Klein 宣佈 Envoy 在 GitHub 開源,直接發佈 1.0.0 版本。

  • 2016 年下半年,Linkerd 陸續發佈了 0.8 和 0.9 版本,開始支持 HTTP/2 和 gRPC,1.0 發佈在即;同時,藉助 Service Mesh 在社區的承認度,Linkerd 在年末開始申請加入 CNCF

  • 2017 年 1 月 23 日,Linkerd 加入 CNCF。

  • 2017 年 3 月 7 日,Linkerd 宣佈完成千億次產品請求

  • 2017 年 4 月 25 日,Linkerd 1.0 版本發佈

  • 2017 年 7 月 11 日,Linkerd 發佈版本 1.1.1,宣佈和 Istio 項目集成

  • 2017 年 9 月, nginx忽然宣佈要搞出一個Servicemesh來, Nginmesh: github.com/nginxinc/ng…, 能夠做爲istio的數據面, 不過這個項目目前處於不活躍開發(This project is no longer under active development)

  • 2017 年 12 月 5 日,Conduit 0.1.0 版本發佈

Envoy 和 Linkerd 都是在數據面上的實現, 屬於同一個層面的競爭, 是用 C++ 語言實現的,在性能和資源消耗上要比採用 Scala 語言實現的 Linkerd 小,這一點對於延遲敏感型和資源敏的服務尤其重要.

Envoy 對 做爲 Istio 的標準數據面實現, 其最主要的貢獻是提供了一套標準數據面API, 將服務信息和流量規則下發到數據面的sidecar中, 另外Envoy還支持熱重啓. Istio早期採用了Envoy v1 API,目前的版本中則使用V2 API,V1已被廢棄.

經過採用該標準API,Istio將控制面和數據面進行了解耦,爲多種數據面sidecar實現提供了可能性。事實上基於該標準API已經實現了多種Sidecar代理和Istio的集成,除Istio目前集成的Envoy外,還能夠和Linkerd, Nginmesh等第三方通訊代理進行集成,也能夠基於該API本身編寫Sidecar實現.

將控制面和數據面解耦是Istio後來居上,風頭超過Service mesh鼻祖Linkerd的一招妙棋。Istio站在了控制面的高度上,而Linkerd則成爲了可選的一種sidecar實現.

Conduit 的總體架構和 Istio 一致,借鑑了 Istio 數據平面 + 控制平面的設計,並且選擇了 Rust 編程語言來實現數據平面,以達成 Conduit 宣稱的更輕、更快和超低資源佔用.

1.8 似曾相識的競爭格局

Kubernetes Istio
領域 容器編排 服務網格
主要競品 Swarm, Mesos Linkerd, Conduit
主要盟友 RedHat, CoreOS IBM, Lyft
主要競爭對手 Docker 公司 Buoyant 公司
標準化 OCI: runtime spec, image spec XDS
插件化 CNI, CRI Istio CNI, Mixer Adapter
結果 Kubernetes 成爲容器編排事實標準 ?

google 主導的Kubernetes 在容器編排領域取得了完勝, 目前在服務網格領域的打法一模一樣, 社區對Istio前景也比較看好.

Istio CNI 計劃在1.1 做爲實驗特性, 用戶能夠經過擴展方式定製sidecar的網絡.

1.9 國內Service Mesh 發展狀況

  • 螞蟻金服開源SOFAMesh:

    • github.com/alipay/sofa…

    • 從istio fork

    • 使用Golang語言開發全新的Sidecar,替代Envoy

    • 爲了不Mixer帶來的性能瓶頸,合併Mixer部分功能進入Sidecar

    • Pilot和Citadel模塊進行了大幅的擴展和加強

    • 擴展RPC協議: SOFARPC/HSF/Dubbo

  • 華爲:

    • go-chassis: github.com/go-chassis/… golang 微服務框架, 支持istio平臺

    • mesher: github.com/go-mesh/mes… mesh 數據面解決方案

    • 國內首家提供Service Mesh公共服務的雲廠商

    • 目前(2019年1月)公有云Istio 產品線上已經支持申請公測, 產品形態比較完善

  • 騰訊雲 TSF:

    • 基於 Istio、envoy 進行改造

    • 支持 Kubernetes、虛擬機以及裸金屬的服務

    • 對 Istio 的能力進行了擴展和加強, 對 Consul 的完整適配

    • 對於其餘二進制協議進行擴展支持

  • 惟品會

    • OSP (Open Service Platform)

  • 新浪:

    • Motan: 是一套基於java開發的RPC框架, Weibo Mesh 是基於Motan

2. Istio: 第二代 Service Mesh

Istio來自希臘語,英文意思是「sail」, 意爲「啓航」

  • 2.1 Istio 架構

  • 2.2 核心功能

  • 2.3 Istio 演示: BookInfo

2.1 Istio 架構

Istio Architecture(圖片來自Isio官網文檔)

  • 數據面

    • Sidecar

  • 控制面

    • Pilot:服務發現、流量管理

    • Mixer:訪問控制、遙測

    • Citadel:終端用戶認證、流量加密

2.2 核心功能

  • 流量管理

  • 安全

  • 可觀察性

  • 多平臺支持

  • 集成和定製

下面是我對Istio架構總結的思惟導圖:

2.3 Istio 演示: BookInfo

如下是Istio官網經典的 BookInfo Demo, 這是一個多語言組成的異構微服務系統:

Bookinfo Application(圖片來自Isio官網文檔)

下面我將現場給你們進行演示, 從demo安裝開始, 並體驗一下istio的流控功能:

使用helm管理istio

下載istio release: istio.io/docs/setup/…

安裝istio:
1kubectl apply -f install/kubernetes/helm/istio/templates/crds.yaml2helm install install/kubernetes/helm/istio --name istio --namespace istio-system複製代碼

注意事項, 若要開啓sidecar自動注入功能, 須要:

  • 確保 kube-apiserver 啓動參數 開啓了ValidatingAdmissionWebhook 和 MutatingAdmissionWebhook

  • 給namespace 增長 label: kubectl label namespace default istio-injection=enabled

  • 同時還要保證 kube-apiserver 的 aggregator layer 開啓: --enable-aggregator-routing=true 且證書和api server連通性正確設置.

如需卸載istio:
1helm delete --purge istio2kubectl delete -f install/kubernetes/helm/istio/templates/crds.yaml -n istio-system複製代碼

更多安裝選擇請參考: istio.io/docs/setup/…

安裝Bookinfo Demo:

Bookinfo 是一個多語言異構的微服務demo, 其中 productpage 微服務會調用 details 和 reviews 兩個微服務, reviews 會調用ratings 微服務, reviews 微服務有 3 個版本. 關於此項目更多細節請參考: istio.io/docs/exampl…

部署應用:
1kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml複製代碼

這將建立 productpage, details, ratings, reviews 對應的deployments 和 service, 其中reviews 有三個deployments, 表明三個不一樣的版本.

1 % kubectl get pod2NAME                           READY     STATUS    RESTARTS   AGE3details-v1-6865b9b99d-mnxbt    2/2       Running   0          1m4productpage-v1-f8c8fb8-zjbhh   2/2       Running   0          59s5ratings-v1-77f657f55d-95rcz    2/2       Running   0          1m6reviews-v1-6b7f6db5c5-zqvkn    2/2       Running   0          59s7reviews-v2-7ff5966b99-lw72l    2/2       Running   0          59s8reviews-v3-5df889bcff-w9v7g    2/2       Running   0          59s9​10 % kubectl get svc11NAME          TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE12details       ClusterIP   172.18.255.240   <none>        9080/TCP   1m13productpage   ClusterIP   172.18.255.137   <none>        9080/TCP   1m14ratings       ClusterIP   172.18.255.41    <none>        9080/TCP   1m15reviews       ClusterIP   172.18.255.140   <none>        9080/TCP   1m複製代碼

對入口流量進行配置:

1kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml複製代碼

該操做會建立bookinfo-gateway 的Gateway, 並將流量發送到productpage服務

1kubectl get gateway2NAME               AGE3bookinfo-gateway   1m複製代碼

此時經過bookinfo-gateway 對應的LB或者nodeport 訪問/productpage 頁面, 能夠看到三個版本的reviews服務在隨機切換

基於權重的路由

經過CRD DestinationRule建立3 個reviews 子版本:

1kubectl apply -f samples/bookinfo/networking/destination-rule-reviews.yaml複製代碼

經過CRD VirtualService 調整個 reviews 服務子版本的流量比例, 設置 v1 和 v3 各佔 50%

1kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-50-v3.yaml複製代碼

刷新頁面, 能夠看到沒法再看到reviews v2的內容, 頁面在v1和v3之間切換.

基於內容路由

修改reviews CRD, 將jason 登陸的用戶版本路由到v2, 其餘用戶路由到版本v3.

1kubectl apply -f samples/bookinfo/networking/virtual-service-reviews-jason-v2-v3.yaml複製代碼

刷新頁面, 使用jason登陸的用戶, 將看到v2 黑色星星版本, 其餘用戶將看到v3 紅色星星版本.

更多BookInfo 示例, 請參閱: istio.io/docs/exampl…, 若要刪除應用: 執行腳本 ./samples/bookinfo/platform/kube/cleanup.sh

3. Istio 數據面

  • 3.1 數據面組件

  • 3.2 sidecar 流量劫持原理

  • 3.3 數據面標準API: xDS

  • 3.4 分佈式跟蹤

3.1 數據面組件

Istio 注入sidecar實現:

注入Pod內容:

  • istio-init: 經過配置iptables來劫持Pod中的流量

  • istio-proxy: 兩個進程pilot-agent和envoy, pilot-agent 進行初始化並啓動envoy

Sidecar 自動注入實現

Istio 利用 Kubernetes Dynamic Admission Webhooks 對pod 進行sidecar注入

查看istio 對這2個Webhooks 的配置 ValidatingWebhookConfiguration 和 MutatingWebhookConfiguration:

1% kubectl get ValidatingWebhookConfiguration -oyaml2% kubectl get mutatingWebhookConfiguration -oyaml複製代碼

能夠看出:

  • 命名空間istio-system 中的服務 istio-galley, 經過路由/admitpilot, 處理config.istio.io部分, rbac.istio.io, authentication.istio.io, networking.istio.io等資源的Validating 工做

  • 命名空間istio-system 中的服務 istio-galley, 經過路由/admitmixer, 處理其餘config.istio.io資源的Validating 工做

  • 命名空間istio-system 中的服務 istio-sidecar-injector, 經過路由/inject, 處理其餘v1/pods的CREATE, 同時須要知足命名空間istio-injection: enabled

istio-init

數據面的每一個Pod會被注入一個名爲istio-init 的initContainer, initContrainer是K8S提供的機制,用於在Pod中執行一些初始化任務.在Initialcontainer執行完畢並退出後,纔會啓動Pod中的其它container.

1initContainers:2- image: docker.io/istio/proxy_init:1.0.53  args:4  - -p5  - "15001"6  - -u7  - "1337"8  - -m9  - REDIRECT10  - -i11  - '*'12  - -x13  - ""14  - -b15  - "9080"16  - -d17  - ""複製代碼

istio-init ENTRYPOINT 和 args 組合的啓動命令:

1/usr/local/bin/istio-iptables.sh -p 15001 -u 1337 -m REDIRECT -i '*' -x "" -b 9080 -d ""複製代碼

istio-iptables.sh 源碼地址爲 github.com/istio/istio…

1$ istio-iptables.sh -p PORT -u UID -g GID [-m mode] [-b ports] [-d ports] [-i CIDR] [-x CIDR] [-h]2  -p: 指定重定向全部 TCP 流量的 Envoy 端口(默認爲 $ENVOY_PORT = 15001)3  -u: 指定未應用重定向的用戶的 UID。一般,這是代理容器的 UID(默認爲 $ENVOY_USER 的 uid,istio_proxy 的 uid 或 1337)4  -g: 指定未應用重定向的用戶的 GID。(與 -u param 相同的默認值)5  -m: 指定入站鏈接重定向到 Envoy 的模式,「REDIRECT」 或 「TPROXY」(默認爲 $ISTIO_INBOUND_INTERCEPTION_MODE)6  -b: 逗號分隔的入站端口列表,其流量將重定向到 Envoy(可選)。使用通配符 「*」 表示重定向全部端口。爲空時表示禁用全部入站重定向(默認爲 $ISTIO_INBOUND_PORTS)7  -d: 指定要從重定向到 Envoy 中排除(可選)的入站端口列表,以逗號格式分隔。使用通配符「*」 表示重定向全部入站流量(默認爲 $ISTIO_LOCAL_EXCLUDE_PORTS)8  -i: 指定重定向到 Envoy(可選)的 IP 地址範圍,以逗號分隔的 CIDR 格式列表。使用通配符 「*」 表示重定向全部出站流量。空列表將禁用全部出站重定向(默認爲 $ISTIO_SERVICE_CIDR)9  -x: 指定將從重定向中排除的 IP 地址範圍,以逗號分隔的 CIDR 格式列表。使用通配符 「*」 表示重定向全部出站流量(默認爲 $ISTIO_SERVICE_EXCLUDE_CIDR)。10​11環境變量位於 $ISTIO_SIDECAR_CONFIG(默認在:/var/lib/istio/envoy/sidecar.env)複製代碼

istio-init 經過配置iptable來劫持Pod中的流量:

  • 參數-p 15001: Pod中的數據流量被iptable攔截,併發向15001端口, 該端口將由 envoy 監聽

  • 參數-u 1337: 用於排除用戶ID爲1337,即Envoy自身的流量,以免Iptable把Envoy發出的數據又重定向到Envoy, UID 爲 1337,即 Envoy 所處的用戶空間,這也是 istio-proxy 容器默認使用的用戶, 見Sidecar istio-proxy 配置參數securityContext.runAsUser

  • 參數-b 9080 -d "": 入站端口控制, 將全部訪問 9080 端口(即應用容器的端口)的流量重定向到 Envoy 代理

  • 參數-i '*' -x "": 出站IP控制, 將全部出站流量都重定向到 Envoy 代理

Init 容器初始化完畢後就會自動終止,可是 Init 容器初始化結果(iptables)會保留到應用容器和 Sidecar 容器中.

istio-proxy

istio-proxy 以 sidecar 的形式注入到應用容器所在的pod中, 簡化的注入yaml:

1- image: docker.io/istio/proxyv2:1.0.52  name: istio-proxy3  args:4  - proxy5  - sidecar6  - --configPath7  - /etc/istio/proxy8  - --binaryPath9  - /usr/local/bin/envoy10  - --serviceCluster11  - ratings12  - --drainDuration13  - 45s14  - --parentShutdownDuration15  - 1m0s16  - --discoveryAddress17  - istio-pilot.istio-system:1500718  - --discoveryRefreshDelay19  - 1s20  - --zipkinAddress21  - zipkin.istio-system:941122  - --connectTimeout23  - 10s24  - --proxyAdminPort25  - "15000"26  - --controlPlaneAuthPolicy27  - NONE28  env:29    ......30  ports:31  - containerPort: 1509032    name: http-envoy-prom33    protocol: TCP34  securityContext:35    runAsUser: 133736    ......複製代碼

istio-proxy容器中有兩個進程pilot-agent和envoy:

1~ % kubectl exec productpage-v1-f8c8fb8-wgmzk -c istio-proxy -- ps -ef2UID        PID  PPID  C STIME TTY          TIME CMD3istio-p+     1     0  0 Jan03 ?        00:00:27 /usr/local/bin/pilot-agent proxy sidecar --configPath /etc/istio/proxy --binaryPath /usr/local/bin/envoy --serviceCluster productpage --drainDuration 45s --parentShutdownDuration 1m0s --discoveryAddress istio-pilot.istio-system:15007 --discoveryRefreshDelay 1s --zipkinAddress zipkin.istio-system:9411 --connectTimeout 10s --proxyAdminPort 15000 --controlPlaneAuthPolicy NONE4istio-p+    21     1  0 Jan03 ?        01:26:24 /usr/local/bin/envoy -c /etc/istio/proxy/envoy-rev0.json --restart-epoch 0 --drain-time-s 45 --parent-shutdown-time-s 60 --service-cluster productpage --service-node sidecar~172.18.3.12~productpage-v1-f8c8fb8-wgmzk.default~default.svc.cluster.local --max-obj-name-len 189 --allow-unknown-fields -l warn --v2-config-only複製代碼

能夠看到:

  • /usr/local/bin/pilot-agent/usr/local/bin/envoy 的父進程, Pilot-agent進程根據啓動參數和K8S API Server中的配置信息生成Envoy的初始配置文件(/etc/istio/proxy/envoy-rev0.json),並負責啓動Envoy進程

  • pilot-agent 的啓動參數裏包括: discoveryAddress(pilot服務地址), Envoy 二進制文件的位置, 服務集羣名, 監控指標上報地址, Envoy 的管理端口, 熱重啓時間等

Envoy配置初始化流程:

  1. Pilot-agent根據啓動參數和K8S API Server中的配置信息生成Envoy的初始配置文件envoy-rev0.json,該文件告訴Envoy從xDS server中獲取動態配置信息,並配置了xDS server的地址信息,即控制面的Pilot

  2. Pilot-agent使用envoy-rev0.json啓動Envoy進程

  3. Envoy根據初始配置得到Pilot地址,採用xDS接口從Pilot獲取到Listener,Cluster,Route等d動態配置信息

  4. Envoy根據獲取到的動態配置啓動Listener,並根據Listener的配置,結合Route和Cluster對攔截到的流量進行處理

查看envoy 初始配置文件:

1kubectl exec productpage-v1-f8c8fb8-wgmzk -c istio-proxy -- cat /etc/istio/proxy/envoy-rev0.json複製代碼

3.2 sidecar 流量劫持原理

sidecar 既要做爲服務消費者端的正向代理,又要做爲服務提供者端的反向代理, 具體攔截過程以下:

  • Pod 所在的network namespace內, 除了envoy發出的流量外, iptables規則會對進入和發出的流量都進行攔截,經過nat redirect重定向到Envoy監聽的15001端口.

  • envoy 會根據從Pilot拿到的 XDS 規則, 對流量進行轉發.

  • envoy 的 listener 0.0.0.0:15001 接收進出 Pod 的全部流量,而後將請求移交給對應的virtual listener

  • 對於本pod的服務, 有一個http listener podIP+端口 接受inbound 流量

  • 每一個service+非http端口, 監聽器配對的 Outbound 非 HTTP 流量

  • 每一個service+http端口, 有一個http listener: 0.0.0.0+端口 接受outbound流量

整個攔截轉發過程對業務容器是透明的, 業務容器仍然使用 Service 域名和端口進行通訊, service 域名仍然會轉換爲service IP, 但service IP 在sidecar 中會被直接轉換爲 pod IP, 從容器中出去的流量已經使用了pod IP會直接轉發到對應的Pod, 對比傳統kubernetes 服務機制, service IP 轉換爲Pod IP 在node上進行, 由 kube-proxy維護的iptables實現.

3.3 數據面標準API: xDS

xDS是一類發現服務的總稱,包含LDS,RDS,CDS,EDS以及 SDS。Envoy經過xDS API能夠動態獲取Listener(監聽器), Route(路由),Cluster(集羣),Endpoint(集羣成員)以 及Secret(證書)配置

xDS API 涉及的概念:

  • Host

  • Downstream

  • Upstream

  • Listener

  • Cluster

Envoy 配置熱更新: 配置的動態變動,而不須要重啓 Envoy:

  1. 新老進程採用基本的RPC協議使用Unix Domain Socket通信.

  2. 新進程啓動並完成全部初始化工做後,向老進程請求監聽套接字的副本.

  3. 新進程接管套接字後,通知老進程關閉套接字.

  4. 通知老進程終止本身.

xDS 調試

Pilot在9093端口提供了下述調試接口:

1# What is sent to envoy2# Listeners and routes3curl $PILOT/debug/adsz4​5# Endpoints6curl $PILOT/debug/edsz7​8# Clusters9curl $PILOT/debug/cdsz複製代碼

Sidecar Envoy 也提供了管理接口,缺省爲localhost的15000端口,能夠獲取listener,cluster以及完整的配置數據

能夠經過如下命令查看支持的調試接口:

1kubectl exec productpage-v1-f8c8fb8-zjbhh -c istio-proxy curl http://127.0.0.1:15000/help複製代碼

或者forward到本地就行調試

1kubectl port-forward productpage-v1-f8c8fb8-zjbhh 15000複製代碼

相關的調試接口:

1http://127.0.0.1:150002http://127.0.0.1:15000/help3http://127.0.0.1:15000/config_dump4http://127.0.0.1:15000/listeners5http://127.0.0.1:15000/clusters複製代碼

使用istioctl 查看代理配置:

1istioctl pc {xDS類型}  {POD_NAME} {過濾條件} {-o json/yaml}2​3eg:4istioctl pc routes productpage-v1-f8c8fb8-zjbhh --name 9080 -o json複製代碼

xDS 類型包括: listener, route, cluster, endpoint

對xDS 進行分析: productpage 訪問 reviews 服務

查看 product 的全部listener:

1% istioctl pc listener  productpage-v1-f8c8fb8-zjbhh2ADDRESS            PORT      TYPE3172.18.255.178     15011     TCP4172.18.255.194     44134     TCP5172.18.255.110     443       TCP6172.18.255.190     50000     TCP7172.18.255.203     853       TCP8172.18.255.2       443       TCP9172.18.255.239     16686     TCP100.0.0.0            80        TCP11172.18.255.215     3306      TCP12172.18.255.203     31400     TCP13172.18.255.111     443       TCP14172.18.255.203     8060      TCP15172.18.255.203     443       TCP16172.18.255.40      443       TCP17172.18.255.1       443       TCP18172.18.255.53      53        TCP19172.18.255.203     15011     TCP20172.18.255.105     14268     TCP21172.18.255.125     42422     TCP22172.18.255.105     14267     TCP23172.18.255.52      80        TCP240.0.0.0            15010     HTTP250.0.0.0            9411      HTTP260.0.0.0            8060      HTTP270.0.0.0            9080      HTTP280.0.0.0            15004     HTTP290.0.0.0            20001     HTTP300.0.0.0            9093      HTTP310.0.0.0            8080      HTTP320.0.0.0            15030     HTTP330.0.0.0            9091      HTTP340.0.0.0            9090      HTTP350.0.0.0            15031     HTTP360.0.0.0            3000      HTTP370.0.0.0            15001     TCP38172.18.3.50        9080      HTTP 這是當前pod ip 暴露的服務地址, 會路由到迴環地址, 各個pod 會不同複製代碼

envoy 流量入口的listener:

1% istioctl pc listener  productpage-v1-f8c8fb8-zjbhh --address 0.0.0.0 --port 15001 -o json2[3    {4        "name": "virtual",5        "address": {6            "socketAddress": {7                "address": "0.0.0.0",8                "portValue": 150019            }10        },11        "filterChains": [12            {13                "filters": [14                    {15                        "name": "envoy.tcp_proxy",16                        "config": {17                            "cluster": "BlackHoleCluster",18                            "stat_prefix": "BlackHoleCluster"19                        }20                    }21                ]22            }23        ],24        "useOriginalDst": true # 這意味着它將請求交給最符合請求原始目標的監聽器。若是找不到任何匹配的虛擬監聽器,它會將請求發送給返回 404 的 BlackHoleCluster25 }26]複製代碼

如下是reviews的全部pod IP

1 % kubectl get ep reviews2NAME      ENDPOINTS                                            AGE3reviews   172.18.2.35:9080,172.18.3.48:9080,172.18.3.49:9080   1d複製代碼

對於目的地址是以上ip的http訪問, 這些 ip 並無對應的listener, 所以會經過端口9080 匹配到listener 0.0.0.0 9080

查看listener 0.0.0.0 9080:

1% istioctl pc listener  productpage-v1-f8c8fb8-zjbhh --address 0.0.0.0 --port 9080 -ojson2    {3        "name": "0.0.0.0_9080",4        "address": {5            "socketAddress": {6                "address": "0.0.0.0",7                "portValue": 90808            }9        },10        ......11​12                            "rds": {13                                "config_source": {14                                    "ads": {}15                                },16                                "route_config_name": "9080"17                            },18                            ......複製代碼

查看名爲9080 的 route:

1% istioctl pc routes  productpage-v1-f8c8fb8-zjbhh --name 9080 -o json2​3[4    {5        "name": "9080",6        "virtualHosts": [7            {8                "name": "details.default.svc.cluster.local:9080",9                "domains": [10                    "details.default.svc.cluster.local",11                    "details.default.svc.cluster.local:9080",12                    "details",13                    "details:9080",14                    "details.default.svc.cluster",15                    "details.default.svc.cluster:9080",16                    "details.default.svc",17                    "details.default.svc:9080",18                    "details.default",19                    "details.default:9080",20                    "172.18.255.240",21                    "172.18.255.240:9080"22                ],23                "routes": [24                    {25                        "match": {26                            "prefix": "/"27                        },28                        "route": {29                            "cluster": "outbound|9080||details.default.svc.cluster.local",30                            "timeout": "0.000s",31                            "maxGrpcTimeout": "0.000s"32                        },33                        ......34            {35                "name": "productpage.default.svc.cluster.local:9080",36                "domains": [37                    "productpage.default.svc.cluster.local",38                    "productpage.default.svc.cluster.local:9080",39                    "productpage",40                    "productpage:9080",41                    "productpage.default.svc.cluster",42                    "productpage.default.svc.cluster:9080",43                    "productpage.default.svc",44                    "productpage.default.svc:9080",45                    "productpage.default",46                    "productpage.default:9080",47                    "172.18.255.137",48                    "172.18.255.137:9080"49                ],50                "routes": [ ...... ]51            },52            {53                "name": "ratings.default.svc.cluster.local:9080",54                "domains": [55                    "ratings.default.svc.cluster.local",56                    "ratings.default.svc.cluster.local:9080",57                    "ratings",58                    "ratings:9080",59                    "ratings.default.svc.cluster",60                    "ratings.default.svc.cluster:9080",61                    "ratings.default.svc",62                    "ratings.default.svc:9080",63                    "ratings.default",64                    "ratings.default:9080",65                    "172.18.255.41",66                    "172.18.255.41:9080"67                ],68                "routes": [ ...... ]69            },70            {71                "name": "reviews.default.svc.cluster.local:9080",72                "domains": [73                    "reviews.default.svc.cluster.local",74                    "reviews.default.svc.cluster.local:9080",75                    "reviews",76                    "reviews:9080",77                    "reviews.default.svc.cluster",78                    "reviews.default.svc.cluster:9080",79                    "reviews.default.svc",80                    "reviews.default.svc:9080",81                    "reviews.default",82                    "reviews.default:9080",83                    "172.18.255.140",84                    "172.18.255.140:9080"85                ],86                "routes": [87                    {88                        "match": {89                            "prefix": "/",90                            "headers": [91                                {92                                    "name": "end-user",93                                    "exactMatch": "jason"94                                }95                            ]96                        },97                        "route": {98                            "cluster": "outbound|9080|v2|reviews.default.svc.cluster.local",99                            "timeout": "0.000s",100                            "maxGrpcTimeout": "0.000s"101                        },102                        ......103                    },104                    {105                        "match": {106                            "prefix": "/"107                        },108                        "route": {109                            "cluster": "outbound|9080|v3|reviews.default.svc.cluster.local",110                            "timeout": "0.000s",111                            "maxGrpcTimeout": "0.000s"112                        },113                        .......114                    }115                ]116            }117        ],118        "validateClusters": false119    }120]複製代碼

能夠看到, 在9080 這個route 中, 包含全部這個端口的http 路由信息, 經過virtualHosts列表進行服務域名分發到各個cluster.

查看virtualHosts reviews.default.svc.cluster.local:9080 中的routes信息, 能夠看到jason 路由到了cluster outbound|9080|v2|reviews.default.svc.cluster.local

查看該cluster:

1% istioctl pc cluster productpage-v1-f8c8fb8-zjbhh --fqdn reviews.default.svc.cluster.local --subset v2 -o json2[3    {4        "name": "outbound|9080|v2|reviews.default.svc.cluster.local",5        "type": "EDS",6        "edsClusterConfig": {7            "edsConfig": {8                "ads": {}9            },10            "serviceName": "outbound|9080|v2|reviews.default.svc.cluster.local"11        },12        "connectTimeout": "1.000s",13        "lbPolicy": "RANDOM",14        "circuitBreakers": {15            "thresholds": [16                {}17            ]18        }19    }20]複製代碼

查看其對應的endpoint:

1 % istioctl pc endpoint productpage-v1-f8c8fb8-zjbhh --cluster 'outbound|9080|v2|reviews.default.svc.cluster.local'2ENDPOINT             STATUS      CLUSTER3172.18.2.35:9080     HEALTHY     outbound|9080|v2|reviews.default.svc.cluster.local複製代碼

該endpoint 即爲 reviews 服務 V2 對應的 pod IP

XDS服務接口的最終一致性考慮

遵循 make before break 模型

3.4 分佈式跟蹤

如下是分佈式全鏈路跟蹤示意圖:

一個典型的Trace案例(圖片來自opentracing文檔中文版)

Jaeger 是Uber 開源的全鏈路跟蹤系統, 符合OpenTracing協議, OpenTracing 和 Jaeger 均是CNCF 成員項目, 如下是Jaeger 架構的示意圖:

Jaeger 架構示意圖(圖片來自Jaeger官方文檔)

分佈式跟蹤系統讓開發者可以獲得可視化的調用流程展現。這對複雜的微服務系統進行問題排查和性能優化時相當重要.

Envoy 原生支持http 鏈路跟蹤:

  • 生成 Request ID:Envoy 會在須要的時候生成 UUID,並操做名爲 [x-request-id] 的 HTTP Header。應用能夠轉發這個 Header 用於統一的記錄和跟蹤.

  • 支持集成外部跟蹤服務:Envoy 支持可插接的外部跟蹤可視化服務。目前支持有:

    • LightStep

    • Zipkin 或者 Zipkin 兼容的後端(好比說 Jaeger)

    • Datadog

  • 客戶端跟蹤 ID 鏈接:x-client-trace-id Header 能夠用來把不信任的請求 ID 鏈接到受信的 x-request-id Header 上

跟蹤上下文信息的傳播

  • 無論使用的是哪一個跟蹤服務,都應該傳播 x-request-id,這樣在被調用服務中啓動相關性的記錄

  • 若是使用的是 Zipkin,Envoy 要傳播的是 B3 Header。(x-b3-traceid, x-b3-spanid, x-b3-parentspanid, x-b3-sampled, 以及 x-b3-flags. x-b3-sampled)

  • 上下文跟蹤並不是零修改, 在調用下游服務時, 上游應用應該自行傳播跟蹤相關的 HTTP Header

4. Istio 控制面

  • 4.1 Pilot 架構

  • 4.2 流量管理模型

  • 4.3 故障處理

  • 4.4 Mixer 架構

  • 4.5 Mixer適配器模型

  • 4.6 Mixer 緩存機制

4.1 Pilot 架構

Pilot Architecture(圖片來自Isio官網文檔)

  • Rules API: 對外封裝統一的 API,供服務的開發者或者運維人員調用,能夠用於流量控制。

  • Envoy API: 對內封裝統一的 API,供 Envoy 調用以獲取註冊信息、流量控制信息等。

  • 抽象模型層: 對服務的註冊信息、流量控制規則等進行抽象,使其描述與平臺無關。

  • 平臺適配層: 用於適配各個平臺如 Kubernetes、Mesos、Cloud Foundry 等,把平臺特定的註冊信息、資源信息等轉換成抽象模型層定義的平臺無關的描述。例如,Pilot 中的 Kubernetes 適配器實現必要的控制器來 watch Kubernetes API server 中 pod 註冊信息、ingress 資源以及用於存儲流量管理規則的第三方資源的更改

4.2 流量管理模型

  • VirtualService

  • DestinationRule

  • ServiceEntry

  • Gateway

VirtualService

VirtualService 中定義了一系列針對指定服務的流量路由規則。每一個路由規則都是針對特定協議的匹配規則。若是流量符合這些特徵,就會根據規則發送到服務註冊表中的目標服務, 或者目標服務的子集或版本, 匹配規則中還包含了對流量發起方的定義,這樣一來,規則還能夠針對特定客戶上下文進行定製.

Gateway

Gateway 描述了一個負載均衡器,用於承載網格邊緣的進入和發出鏈接。這一規範中描述了一系列開放端口,以及這些端口所使用的協議、負載均衡的 SNI 配置等內容

ServiceEntry

Istio 服務網格內部會維護一個與平臺無關的使用通用模型表示的服務註冊表,當你的服務網格須要訪問外部服務的時候,就須要使用 ServiceEntry 來添加服務註冊, 這類服務多是網格外的 API,或者是處於網格內部但卻不存在於平臺的服務註冊表中的條目(例如須要和 Kubernetes 服務溝通的一組虛擬機服務).

EnvoyFilter

EnvoyFilter 描述了針對代理服務的過濾器,用來定製由 Istio Pilot 生成的代理配置.

Kubernetes Ingress vs Istio Gateway

  • 合併了L4-6和L7的規範, 對傳統技術棧用戶的應用遷入不方便

  • 表現力不足:

    • 只能對 service、port、HTTP 路徑等有限字段匹配來路由流量

    • 端口只支持默認80/443

Istio Gateway:·

  • 定義了四層到六層的負載均衡屬性 (一般是SecOps或NetOps關注的內容)

    • 端口

    • 端口所使用的協議(HTTP, HTTPS, GRPC, HTTP2, MONGO, TCP, TLS)

    • Hosts

    • TLS SNI header 路由支持

    • TLS 配置支持(http 自動301, 證書等)

    • ip / unix domain socket

Kubernetes, Istio, Envoy xDS 模型對比

如下是對Kubernetes, Istio, Envoy xDS 模型的不嚴格對比

Kubernetes Istio Envoy xDS
入口流量 Ingress GateWay Listener
服務定義 Service - Cluster+Listener
外部服務定義 - ServiceEntry Cluster+Listener
版本定義 - DestinationRule Cluster+Listener
版本路由 - VirtualService Route
實例 Endpoint - Endpoint

Kubernetes 和 Istio 服務尋址的區別:

Kubernetes:

  1. kube-dns: service domain -> service ip

  2. kube-proxy(node iptables): service ip -> pod ip

Istio:

  1. kube-dns: service domain -> service ip

  2. sidecar envoy: service ip -> pod ip

4.3 故障處理

隨着微服務的拆分粒度加強, 服務調用會增多, 更復雜, 扇入 扇出, 調用失敗的風險增長, 如下是常見的服務容錯處理方式:

控制端 目的 實現 Istio
超時 client 保護client 請求等待超時/請求運行超時 timeout
重試 client 容忍server臨時錯誤, 保證業務總體可用性 重試次數/重試的超時時間 retries.attempts, retries.perTryTimeout
熔斷 client 下降性能差的服務或實例的影響 一般會結合超時+重試, 動態進行服務狀態決策(Open/Closed/Half-Open) trafficPolicy.outlierDetection
降級 client 保證業務主要功能可用 主邏輯失敗採用備用邏輯的過程(鏡像服務分級, 調用備用服務, 或者返回mock數據) 暫不支持, 須要業務代碼按需實現
隔離 client 防止異常server佔用過多client資源 隔離對不一樣服務調用的資源依賴: 線程池隔離/信號量隔離 暫不支持
冪等 server 容忍client重試, 保證數據一致性 惟一ID/加鎖/事務等手段 暫不支持, 須要業務代碼按需實現
限流 server 保護server 經常使用算法: 計數器, 漏桶, 令牌桶 trafficPolicy.connectionPool

Istio 沒有無降級處理支持: Istio能夠提升網格中服務的可靠性和可用性。可是,應用程序仍然須要處理故障(錯誤)並採起適當的回退操做。例如,當負載均衡池中的全部實例都失敗時,Envoy 將返回 HTTP 503。應用程序有責任實現必要的邏輯,對這種來自上游服務的 HTTP 503 錯誤作出合適的響應。

4.4 Mixer 架構

Mixer Topology(圖片來自Isio官網文檔)

Istio 的四大功能點鏈接, 安全, 控制, 觀察, 其中「控制」和「觀察」的功能主要都是由Mixer組件來提供, Mixer 在Istio中角色:

  • 功能上: 負責策略控制和遙測收集

  • 架構上:提供插件模型,能夠擴展和定製

4.5 Mixer Adapter 模型

  • Attribute

  • Template

  • Adapter

  • Instance

  • Handler

  • Rule

Attribute

Attribute 是策略和遙測功能中有關請求和環境的基本數據, 是用於描述特定服務請求或請求環境的屬性的一小段數據。例如,屬性能夠指定特定請求的大小、操做的響應代碼、請求來自的 IP 地址等.

  • Istio 中的主要屬性生產者是 Envoy,但專用的 Mixer 適配器也能夠生成屬性

  • 屬性詞彙表見: Attribute Vocabulary

  • 數據流向: envoy -> mixer

Template

Template 是對 adapter 的數據格式和處理接口的抽象, Template定義了:

  • 當處理請求時發送給adapter 的數據格式

  • adapter 必須實現的gRPC service 接口

每一個Template 經過 template.proto 進行定義:

  • 名爲Template 的一個message

  • Name: 經過template所在的package name自動生成

  • template_variety: 可選Check, Report, Quota or AttributeGenerator, 決定了adapter必須實現的方法. 同時決定了在mixer的什麼階段要生成template對應的instance:

    • Check: 在Mixer’s Check API call時建立併發送instance

    • Report: 在Mixer’s Report API call時建立併發送instance

    • Quota: 在Mixer’s Check API call時建立併發送instance(查詢配額時)

    • AttributeGenerator: for both Check, Report Mixer API calls

Istio 內置的Templates: istio.io/docs/refere…

Adapter

封裝了 Mixer 和特定外部基礎設施後端進行交互的必要接口,例如 Prometheus 或者 Stackdriver

  • 定義了須要處理的模板(在yaml中配置template)

  • 定義了處理某個Template數據格式的GRPC接口

  • 定義 Adapter須要的配置格式(Params)

  • 能夠同時處理多個數據(instance)

Istio 內置的Adapter: istio.io/docs/refere…

Instance

表明符合某個Template定義的數據格式的具體實現, 該具體實現由用戶配置的 CRD, CRD 定義了將Attributes 轉換爲具體instance 的規則, 支持屬性表達式

  • Instance CRD 是Template 中定義的數據格式 + 屬性轉換器

  • 內置的Instance 類型(其實就是內置 Template): Templates

  • 屬性表達式見: Expression Language

  • 數據流向: mixer -> adapter 實例

Handler

用戶配置的 CRD, 爲具體Adapter提供一個具體配置, 對應Adapter的可運行實例

Rule

用戶配置的 CRD, 配置一組規則,這些規則描述了什麼時候調用特定(經過Handler對應的)適配器及哪些Instance

結語

計算機科學中的全部問題,均可以用另外一個層來解決,除了層數太多的問題

Kubernetes 自己已經很複雜, Istio 爲了更高層控制的抽象, 又增長了不少概念. 複雜度堪比kubernetes.

能夠看出istio 設計精良, 在處理微服務的複雜場景有不少優秀之處, 不過目前istio目前的短板仍是很明顯, 高度的抽象帶來了不少性能的損耗, 社區如今也有不少優化的方向, 像螞蟻金服開源的SofaMesh 主要是去精簡層, 試圖在sidecar裏去作不少mixer 的事情, 減小sidecar和mixer的同步請求依賴, 而一些其餘的sidecar 網絡方案, 更多的是考慮去優化層, 優化sidecar 這一層的性能開銷.

在Istio 1.0 以前, 主要仍是以功能的實現爲主, 不事後面隨着社區的積極投入, 相信Istio的性能會有長足的提高.

筆者以前從事過多年的服務治理相關的工做, 過程當中切身體會到微服務治理的痛點, 因此也比較關注 service mesh的發展, 我的對istio也很是看好, 恰好今年咱們中心容器產品今年也有這方面的計劃, 期待咱們能在這個方向進行一些產品和技術的深耕.

參考資料:

相關文章
相關標籤/搜索