istio基礎詳解


1.Istio介紹?

 

官方文檔:https://istio.io/docs/concepts/what-is-istio/

中文官方文檔:https://istio.io/zh/docs/concepts/what-is-istio/

Github地址:https://github.com/istio/istio/releases

 

1.1 Istio是什么?

 

官當解釋:

An open platform to connect, secure, control and observe services.

 

翻譯過來,就是”連接、安全加固、控制和觀察服務的開放平台“。開放平台就是指它本身是開源的,服務對應的是微服務,也可以粗略地理解為單個應用。

 

1、連接(Connect):智能控制服務之間的調用流量,能夠實現灰度升級、AB 測試和藍綠部署等功能

2、安全加固(Secure):自動為服務之間的調用提供認證、授權和加密。

3、控制(Control):應用用戶定義的 policy,保證資源在消費者中公平分配。

4、觀察(Observe):查看服務運行期間的各種數據,比如日志、監控和 tracing,了解服務的運行情況。

 

Istio是ServiceMesh的產品化落地,可以通過在現有的服務器新增部署邊車代理(sidecar proxy),應用程序不用改代碼,或者只需要改很少的代碼,就能實現如下基礎功能:

1、幫助微服務之間建立連接,幫助研發團隊更好的管理與監控微服務,並使得系統架構更加安全;

2、幫助微服務分層解耦,解耦后的proxy層能夠更加專注於提供基礎架構能力,例如:

(1)服務發現(discovery);

(2)負載均衡(load balancing);

(3)故障恢復(failure recovery);

(4)服務度量(metrics);

(5)服務監控(monitoring);

(6)A/B測試(A/B testing);

(7)灰度發布(canary rollouts);

(8)限流限速(rate limiting);

(9)訪問控制(access control);

(10)身份認證(end-to-end authentication)。

1.1.1 服務注冊和發現

 

RPC:RPC(Remote Procedure Call)遠程過程調用,簡單的理解是一個節點請求另一個節點提供的服務

1.1.2 負載均衡?

把前端的請求分發到后台多個服務器

 

1.1.3 故障恢復

出現故障具備自恢復的能力

 

1.1.4 服務度量

對於 HTTP,HTTP/2 和 GRPC 流量,Istio 生成以下指標:

1、請求計數(istio_requests_total):這是一個用於累加每個由 Istio 代理所處理請求的 COUNTER 指標。

2、請求持續時間(istio_request_duration_seconds):這是一個用於測量請求的持續時間的 DISTRIBUTION 指標。

3、請求大小(istio_request_bytes):這是一個用於測量 HTTP 請求 body 大小的 DISTRIBUTION 指標。

4、響應大小(istio_response_bytes):這是一個用於測量 HTTP 響應 body 大小的 DISTRIBUTION 指標。

對於 TCP 流量,Istio 生成以下指標:

1、Tcp 發送字節數(istio_tcp_sent_bytes_total):這是一個用於測量在 TCP 連接下響應期間發送的總字節數的 COUNTER 指標。

2、Tcp 接收字節數(istio_tcp_received_bytes_total):這是一個用於測量在 TCP 連接下請求期間接收的總字節數的COUNTER指標。

3、Tcp 打開連接數(istio_tcp_connections_opened_total):這是一個用於累加每個打開連接的 COUNTER 指標。

4、Tcp 關閉連接數 (istio_tcp_connections_closed_total) : 這是一個用於累加每個關閉連接的 COUNTER 指標。

 

1.1.5 灰度發布

灰度發布也叫金絲雀發布,起源是,礦井工人發現,金絲雀對瓦斯氣體很敏感,礦工會在下井之前,先放一只金絲雀到井中,如果金絲雀不叫了,就代表瓦斯濃度高。

 

 

在灰度發布開始后,先啟動一個新版本應用,但是並不直接將流量切過來,而是測試人員對新版本進行線上測試,啟動的這個新版本應用,就是我們的金絲雀。如果沒有問題,那么可以將少量的用戶流量導入到新版本上,然后再對新版本做運行狀態觀察,收集各種運行時數據,如果此時對新舊版本做各種數據對比,就是所謂的A/B測試。

當確認新版本運行良好后,再逐步將更多的流量導入到新版本上,在此期間,還可以不斷地調整新舊兩個版本的運行的服務器副本數量,以使得新版本能夠承受越來越大的流量壓力。直到將100%的流量都切換到新版本上,最后關閉剩下的老版本服務,完成灰度發布。

如果在灰度發布過程中(灰度期)發現了新版本有問題,就應該立即將流量切回老版本上,這樣,就會將負面影響控制在最小范圍內。

1.2 Istio核心特性

1、流控(traffic management)

斷路器(circuit breakers)、超時、重試、多路由規則、AB測試、灰度發布、按照百分比分配流量等。

 

2、安全(security)

加密、身份認證、服務到服務的權限控制、K8S里容器到容器的權限控制等。

 

3、可觀察(observability)

追蹤、監控、數據收集,通過控制后台全面了解上行下行流量,服務鏈路情況,服務運行情況,系統性能情況,國內微服務架構體系,這一塊做得比較缺乏。

 

4、平台無關系(platform support)

K8s,物理機,自己的虛機都沒問題。

 

5、集成與定制(integration and customization)

可定制化擴展功能。

1.2.1 斷路器

互動1:舉個生活中的例子解釋斷路器

當電路發生故障或異常時,伴隨着電流不斷升高,並且升高的電流有可能能損壞電路中的某些重要器件,也有可能燒毀電路甚至造成火災。若電路中正確地安置了保險絲,那么保險絲就會在電流異常升高到一定的高度和熱度的時候,自身熔斷切斷電流,從而起到保護電路安全運行的作用。

 

很多技術都是來源生活的,隨着社會進步,科技發展

 

 

斷路器也稱為服務熔斷,在多個服務調用的時候,服務A依賴服務B,服務B依賴服務C,如果服務C響應時間過長或者不可用,則會讓服務B占用太多系統資源,而服務A也依賴服B,同時也在占用大量的系統資源,造成系統雪崩的情況出現。 Istio 斷路器通過網格中的邊車對流量進行攔截判斷處理,避免了在代碼中侵入控制邏輯,非常方便的就實服務熔斷的能力。

 

在微服務架構中,在高並發情況下,如果請求數量達到一定極限(可以自己設置閾值),超出了設置的閾值,斷路器會自動開啟服務保護功能,然后通過服務降級的方式返回一個友好的提示給客戶端。假設當10個請求中,有10%失敗時,熔斷器就會打開,此時再調用此服務,將會直接返回失敗,不再調遠程服務。直到10s鍾之后,重新檢測該觸發條件,判斷是否把熔斷器關閉,或者繼續打開。

 

 

互動2:服務降級(提高用戶體驗效果)

比如電商平台,在針對618、雙11的時候會有一些秒殺場景,秒殺的時候請求量大,可能會返回報錯標志“當前請求人數多,請稍后重試”等,如果使用服務降級,無法提供服務的時候,消費者會調用降級的操作,返回服務不可用等信息,或者返回提前准備好的靜態頁面寫好的信息。

 

1.2.2 超時

什么時候需要用到超時?

在生產環境中經常會碰到由於調用方等待下游的響應過長,堆積大量的請求阻塞了自身服務,造成雪崩的情況,通過超時處理來避免由於無限期等待造成的故障,進而增強服務的可用性。

通過例子來理解

 

 

nginx 服務設置了超時時間為3秒,如果超出這個時間就不在等待,返回超時錯誤

httpd 服務設置了響應時間延遲5秒,任何請求都需要等待5秒后才能返回

client 通過訪問 nginx 服務去反向代理 httpd 服務,由於 httpd 服務需要5秒后才能返回,但nginx 服務只等待3秒,所以客戶端會提示超時錯誤。

1.2.3 重試

istio 重試機制就是如果調用服務失敗,Envoy 代理嘗試連接服務的最大次數。而默認情況下,Envoy 代理在失敗后並不會嘗試重新連接服務。

舉個例子:

 

 

 

客戶端調用 nginx,nginx 將請求轉發給 tomcat。tomcat 通過故障注入而中止對外服務,nginx 設置如果訪問 tomcat 失敗則會重試 3 次。

 

1.2.4 多路由規則

1、HTTP重定向(HTTPRedirect)

2、HTTP重寫(HTTPRewrite)

3、HTTP重試(HTTPRetry)

4、HTTP故障注入(HTTPFaultInjection)

5、HTTP跨域資源共享(CorsPolicy)

 

2.Istio架構

 istio服務網格從邏輯上分為數據平面和控制平面。

 

 

1、數據平面由一組以Sidecar方式部署的智能代理(Envoy+Polit-agent)組成。這些代理承載並控制微服務之間的所有網絡通信,管理入口和出口流量,類似於一線員工。 Sidecar 一般和業務容器綁定在一起(在Kubernets中以自動注入的方式注入到到業務pod中),來劫持業務應用容器的流量,並接受控制面組件的控制,同時會向控制面輸出日志、跟蹤及監控數據。

 

Envoy 和 pilot-agent 打在同一個鏡像中,即sidecar Proxy。

 

2、控制平面負責管理和配置代理來路由流量。

istio1.5+中使用了一個全新的部署模式,重建了控制平面,將原有的多個組件整合為一個單體結構istiod,這個組件是控制平面的核心,管理Istio的所有功能,主要包括Pilot、Mixer、Citadel等服務組件。

 

istiod是新版本中最大的變化,以一個單體組件替代了原有的架構,降低了復雜度和維護難度,但原有的多組件並不是被完全移除,而是在重構后以模塊的形式整合在一起組成了istiod。

 

結合下圖我們來理解Istio的各組件的功能及相互之間的協作方式。

 

1. 自動注入:在創建應用程序時自動注入 Sidecar代理Envoy程序。在 Kubernetes中創建 Pod時,Kube-apiserver調用控制面組件的 Sidecar-Injector服務,自動修改應用程序的描述信息並注入Sidecar。在真正創建Pod時,在創建業務容器的Pod中同時創建Sidecar容器。


2. 流量攔截:在Pod初始化時設置iptables 規則,基於配置的iptables規則攔截業務容器的Inbound流量和Outbound流量到Sidecar上。而應用程序感知不到Sidecar的存在,還以原本的方式 進行互相訪問。上圖中,流出frontend服務的流量會被 frontend服務側的 Envoy攔截,而當流量到達forecast容器時,Inbound流量被forecast 服務側的Envoy攔截。

 
3. 服務發現:服務發起方的 Envoy 調用控制面組件 Pilot 的服務發現接口獲取目標服務的實例列表。上圖中,frontend 服務側的 Envoy 通過 Pilot 的服務發現接口得到forecast服務各個實例的地址。

 


4. 負載均衡:服務發起方的Envoy根據配置的負載均衡策略選擇服務實例,並連接對應的實例地址。上圖中,數據面的各個Envoy從Pilot中獲取forecast服務的負載均衡配置,並執行負載均衡動作。

 


5. 流量治理:Envoy 從 Pilot 中獲取配置的流量規則,在攔截到 Inbound 流量和Outbound 流量時執行治理邏輯。上圖中, frontend 服務側的 Envoy 從 Pilot 中獲取流量治理規則,並根據該流量治理規則將不同特征的流量分發到forecast服務的v1或v2版本。


6. 訪問安全:在服務間訪問時通過雙方的Envoy進行雙向認證和通道加密,並基於服務的身份進行授權管理。上圖中,Pilot下發安全相關配置,在frontend服務和forecast服務的Envoy上自動加載證書和密鑰來實現雙向認證,其中的證書和密鑰由另一個管理面組件 Citadel維護。


7. 服務監測:在服務間通信時,通信雙方的Envoy都會連接管理面組件Mixer上報訪問數據,並通過Mixer將數據轉發給對應的監控后端。上圖中,frontend服務對forecast服務的訪問監控指標、日志和調用鏈都可以通過這種方式收集到對應的監控后端。

 


8. 策略執行:在進行服務訪問時,通過Mixer連接后端服務來控制服務間的訪問,判斷對訪問是放行還是拒絕。上圖中,Mixer 后端可以對接一個限流服務對從frontend服務到forecast服務的訪問進行速率控制等操作。


9. 外部訪問:在網格的入口處有一個Envoy扮演入口網關的角 色。上圖中,外部服務通過Gateway訪問入口服務 frontend,對 frontend服務的負載均衡和一些流量治理策略都在這個Gateway上執行。 

問題1:為什么代理會叫sidecar proxy?

 

 

 

看了上圖就容易懂了,sidecar和proxy相生相伴,就像摩托車(motor)與旁邊的車廂(sidecar)。未來,sidecar和proxy就指微服務進程解耦成兩個進程之后,提供基礎能力的那個代理進程。

3.istio組件詳解

Istio服務組件有很多,從上面的流程中基本能看出每個組件如何協作的,下面具體講解每個組件的具體用途和功能。

[root@xianchaomaster1 ~]# kubectl get svc -n istio-system |awk '{print $1}'
istio-egressgateway
istio-ingressgateway
istiod

3.1 Pilot

Pilot 是 Istio 的主要控制組件,下發指令控制客戶端。在整個系統中,Pilot 完成以下任務:

1、從 Kubernetes 或者其他平台的注冊中心獲取服務信息,完成服務發現過程。
2、讀取 Istio 的各項控制配置,在進行轉換之后,將其發給數據面進行實施。

 

Pilot 將配置內容下發給數據面的 Envoy,Envoy 根據 Pilot 指令,將路由、服務、監聽、集群等定義信息轉換為本地配置,完成控制行為的落地。

 

1)Pilot為Envoy提供服務發現

2)提供流量管理功能(例如,A/B 測試、金絲雀發布等)以及彈性功能(超時、重試、熔斷器等);

3)生成envoy配置

4)啟動envoy

5)監控並管理envoy的運行狀況,比如envoy出錯時pilot-agent負責重啟envoy,或者envoy配置變更后reload envoy

 

3.2 Envoy

Envoy是什么?

Envoy是用 C++ 開發的高性能代理,用於協調服務網格中所有服務的入站和出站流量。

Envoy有許多強大的功能,例如:

  • 動態服務發現
  • 負載均衡
  • TLS終端
  • HTTP/2與gRPC代理
  • 斷路器
  • 健康檢查
  • 流量拆分
  • 灰度發布
  • 故障注入

 

Istio中Envoy與服務什么關系?

為了便於理解Istio中Envoy與服務的關系,下圖為Envoy的拓撲圖,如圖所示:

 

Envoy和Service A同屬於一個Pod,共享網絡和命名空間,Envoy代理進出Pod A的流量,並將流量按照外部請求的規則作用於Service A中。

 

Pilot-agent是什么?

Envoy不直接跟k8s交互,通過 pilot-agent管理的

Pilot-agent進程根據K8S APIserver中的配置信息生成Envoy的配置文件,並負責啟動Envoy進程。

Envoy由Pilot-agent進程啟動,啟動后,Envoy讀取Pilot-agent為它生成的配置文件,然后根據該文件的配置獲取到Pilot的地址,通過數據面從pilot拉取動態配置信息,包括路由(route),監聽器(listener),服務集群(cluster)和服務端點(endpoint)。

 

3.3 Citadel

負責處理系統上不同服務之間的TLS通信。 Citadel充當證書頒發機構(CA),並生成證書以允許在數據平面中進行安全的mTLS通信。

 

Citadel是 Istio的核心安全組件,提供了自動生 成、分發、輪換與撤銷密鑰和證書功能。Citadel一直監聽 Kube- apiserver,以 Secret的形式為每個服務都生成證書密鑰,並在Pod創建時掛載到Pod上,代理容器使用這些文件來做服務身份認證,進而代 理兩端服務實現雙向TLS認證、通道加密、訪問授權等安全功能。如圖 所示,frontend 服 務對 forecast 服務的訪問用到了HTTP方式,通過配置即可對服務增加認證功能,雙方的Envoy會建立雙向認證的TLS通道,從而在服務間啟用雙向認證的HTTPS。

 

3.4 Galley

Galley是istio的配置驗證、提取、處理和分發的組件。Galley是提供配置管理的服務。實現原理是通過k8s提供的ValidatingWebhook對配置進行驗證。

 

Galley使Istio可以與Kubernetes之外的其他環境一起工作,因為它可以將不同的配置數據轉換為Istio可以理解的通用格式。

 

3.5 Ingressgateway

Ingressgateway 就是入口處的 Gateway,從網格外訪問網格內的服務就是通過這個Gateway進行的。istio-ingressgateway是一個Loadbalancer類型的Service,不同於其他服務組件只有一兩個端 口,istio-ingressgateway 開放了一組端口,這些就是網格內服務的外部訪問端口。如下圖所示,網格入口網關istio-ingressgateway的負載和網格內的Sidecar是同樣的執行流程,也和網格內的其他 Sidecar一樣從 Pilot處接收流量規則並執行。

 

3.6 Sidecar-injector

Sidecar-injector是負責自動注入的組件,只要開啟了自動注 入,在Pod創建時就會自動調用istio-sidecar-injector向Pod中注入Sidecar 容器。
在 Kubernetes環境下,根據自動注入配置,Kube-apiserver在攔截到 Pod創建的請求時,會調用自動注入服務 istio-sidecar-injector 生成 Sidecar 容器的描述並將其插入原 Pod的定義中,這樣,在創建的 Pod 內除了包括業務容器,還包括 Sidecar容器,這個注入過程對用戶透明。

 

3.7 其他組件

除了以“istio”為前綴的Istio自有組件,在集群中一般還安裝Jaeger-agent、Jaeger-collector、Jaeger-query、Kiali、Prometheus、Grafana、 Tracing、Zipkin等組件,這些組件提供了Istio的調用鏈、監控等功能,可以選擇安裝來完成完整的服務監控管理功能。

4.在k8s平台安裝Istio 

4.1 准備安裝Istio是要的壓縮包

官網下載地址:
https://github.com/istio/istio/
官方訪問相對較慢,我在課件提供了壓縮包,大家最好用我的壓縮包,這樣做實驗才不會出問題
1、把壓縮包上傳到k8s的控制節點xianchaomaster1。手動解壓:
[root@xianchaomaster1 ~]# tar zxvf istio-1.10.1-linux-amd64.tar.gz

2、切換到istio包所在目錄下。tar zxvf istio-1.10.1-linux-amd64.tar.gz解壓的軟件包包名是istio-1.10.1,則:
cd istio-1.10.1
安裝目錄包含如下內容:
2)samples/目錄下,有示例應用程序
3)bin/目錄下,包含istioctl的客戶端文件。istioctl工具用於手動注入Envoy sidecar代理。

3、將istioctl客戶端路徑增加到path環境變量中,macOS 或 Linux 系統的增加方式如下:
export PATH=$PWD/bin:$PATH
4、把istioctl這個可執行文件拷貝到/usr/bin/目錄
cd /root/istio-1.10.1/bin/
cp -ar istioctl /usr/bin/

4.2 安裝istio

1.下載鏡像:
安裝istio需要的鏡像默認從官網拉取,但是官網的鏡像我們拉取會有問題,可以從課件下載鏡像,然后上傳到自己k8s集群的各個節點,通過docker load -i手動解壓鏡像:
docker load -i  examples-bookinfo-details.tar.gz      
docker load -i  examples-bookinfo-reviews-v1.tar.gz 
docker load -i  examples-bookinfo-productpage.tar.gz  
docker load -i  examples-bookinfo-reviews-v2.tar.gz
docker load -i  examples-bookinfo-ratings.tar.gz     
docker load -i  examples-bookinfo-reviews-v3.tar.gz
docker load -i  istio-1-10-1.tar.gz
docker load -i  engress-proxyv2-1-10-1.tar.gz
docker load -i  httpbin.tar.gz
2.安裝
在k8s的控制節點xianchaomaster1操作
istioctl install --set profile=demo -y
看到如下,說明istio初始化完成:
Detected that your cluster does not support third party JWT authentication. Falling back to less secure first party JWT. See https://istio.io/docs/ops/best-practices/security/#configure-third-party-service-account-tokens for details.
- Applying manifest for component Base...
✔ Finished applying manifest for component Base.
- Applying manifest for component Pilot...
✔ Finished applying manifest for component Pilot.
  Waiting for resources to become ready...
  Waiting for resources to become ready...
- Applying manifest for component EgressGateways...
- Applying manifest for component IngressGateways...
- Applying manifest for component AddonComponents...
✔ Finished applying manifest for component EgressGateways.
✔ Finished applying manifest for component IngressGateways.
✔ Finished applying manifest for component AddonComponents.

✔ Installation complete

3.驗證istio是否部署成功
kubectl get pods -n istio-system
顯示如下,說明部署成功
istio-egressgateway-d84f95b69-5gtdc     1/1     Running   0          15h
istio-ingressgateway-75f6d79f48-fhxjj   1/1     Running   0          15h
istiod-c9f6864c4-nrm82                  1/1     Running   0          15h

4.卸載istio集群,暫時不執行,記住這個命令即可
istioctl manifest generate --set profile=demo | kubectl delete -f -

5、通過Istio部署在線書店bookinfo

5.1 在線書店功能介紹

在線書店-bookinfo

該應用由四個單獨的微服務構成,這個應用模仿在線書店的一個分類,顯示一本書的信息,頁面上會顯示一本書的描述,書籍的細節(ISBN、頁數等),以及關於這本書的一些評論

Bookinfo應用分為四個單獨的微服務

1)productpage這個微服務會調用details和reviews兩個微服務,用來生成頁面;

2)details這個微服務中包含了書籍的信息;

3)reviews這個微服務中包含了書籍相關的評論,它還會調用ratings微服務;

4)ratings這個微服務中包含了由書籍評價組成的評級信息。

 

reviews微服務有3個版本

1)v1版本不會調用ratings服務;

2)v2版本會調用ratings服務,並使用1到5個黑色星形圖標來顯示評分信息;

3)v3版本會調用ratings服務,並使用1到5個紅色星形圖標來顯示評分信息。

 

下圖展示了這個應用的端到端架構

 

Bookinfo應用中的幾個微服務是由不同的語言編寫的。這些服務對istio並無依賴,但是構成了一個有代表性的服務網格的例子:它由多個服務、多個語言構成,並且reviews服務具有多個版本。

5.2 部署應用

要在Istio中運行這一應用,無需對應用自身做出任何改變。 只要簡單的在 Istio 環境中對服務進行配置和運行,具體一點說就是把 Envoy sidecar 注入到每個服務之中。 最終的部署結果將如下圖所示:

 

所有的微服務都和Envoy sidecar集成在一起,被集成服務所有的出入流量都被envoy sidecar 所劫持,這樣就為外部控制准備了所需的 Hook,然后就可以利用Istio控制平面為應用提供服務路由、遙測數據收集以及策略實施等功能。

5.3 啟動應用服務

1.進入istio安裝目錄。
2.istio默認自動注入 sidecar,需要¬¬為default命名空間打上標簽istio-injection=enabled
kubectl label namespace default istio-injection=enabled
3.使用kubectl部署應用
cd istio-1.10.1
kubectl apply -f samples/bookinfo/platform/kube/bookinfo.yaml
上面的命令會啟動全部的四個服務,其中也包括了 reviews 服務的三個版本(v1、v2 以及 v3)。
4.確認所有的服務和 Pod 都已經正確的定義和啟動:
kubectl get services
顯示如下
NAME                      TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                                     
details                   ClusterIP   10.109.124.202   <none>        9080/TCP                                    
productpage               ClusterIP   10.102.89.129    <none>        9080/TCP                                    
ratings                   ClusterIP   10.101.97.75     <none>        9080/TCP                                    
reviews                   ClusterIP   10.100.105.33    <none>        9080/TCP                                    
kubectl get pods 
顯示如下
NAME                              READY   STATUS    RESTARTS   AGE
details-v1-78d78fbddf-qssjb           2/2     Running   0          73m
productpage-v1-85b9bf9cd7-r699f     2/2     Running   0          73m
ratings-v1-6c9dbf6b45-77kv7          2/2     Running   0          73m
reviews-v1-564b97f875-2jtxq           2/2     Running   0          73m
reviews-v2-568c7c9d8f-f5css           2/2     Running   0          73m
reviews-v3-67b4988599-fxfzx           2/2     Running   0          73m
tomcat-deploy-59664bcb6f-5z4nn      1/1     Running   0          22h
tomcat-deploy-59664bcb6f-cgjbn       1/1     Running   0          22h
tomcat-deploy-59664bcb6f-n4tqq      1/1     Running   0          22h

5.確認 Bookinfo 應用是否正在運行,在某個Pod中用curl命令對應用發送請求,例如ratings:
kubectl exec -it $(kubectl get pod -l app=ratings -o jsonpath='{.items[0].metadata.name}') -c ratings -- curl productpage:9080/productpage | grep -o "<title>.*</title>"

顯示如下:

 

 

 

6.確定Ingress的IP和端口
現在Bookinfo服務已經啟動並運行,你需要使應用程序可以從Kubernetes集群外部訪問,例如從瀏覽器訪問,那可以用Istio Gateway來實現這個目標。
1)為應用程序定義gateway網關:
kubectl apply -f samples/bookinfo/networking/bookinfo-gateway.yaml
2)確認網關創建完成:
kubectl get gateway
顯示如下:
NAME               AGE
bookinfo-gateway   2m18s
3)確定ingress ip和端口
執行如下指令,明確自身 Kubernetes 集群環境支持外部負載均衡:
kubectl get svc istio-ingressgateway -n istio-system

 

 

 

如果EXTERNAL-IP值已設置,說明環境正在使用外部負載均衡,可以用其為ingress gateway 提供服務。 如果EXTERNAL-IP值為<none>(或持續顯示<pending>), 說明環境沒有提供外部負載均衡,無法使用ingress gateway。在這種情況下,你可以使用服務的NodePort訪問網關。

若自身環境未使用外部負載均衡器,需要通過 node port 訪問。可以通過以下命令獲取Istio Gateway的地址:

export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')

export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')

4)設置GATEWAY_URL
INGRESS_HOST=192.168.40.180
#192.168.40.180是安裝istio的機器,即k8s控制節點xianchaomaster1的ip
export GATEWAY_URL=$INGRESS_HOST:$INGRESS_PORT
echo $GATEWAY_URL 顯示如下:
192.168.40.180:30871

確認可以從集群外部訪問應用
可以用curl命令來確認是否能夠從集群外部訪問 Bookinfo 應用程序:
curl -s http://${GATEWAY_URL}/productpage | grep -o "<title>.*</title>"

顯示如下:

 

 

 

還可以用瀏覽器打開網址http://$GATEWAY_URL/productpage,也就是192.168.40.180:30871/productpage來瀏覽應用的 Web 頁面。如果刷新幾次應用的頁面,就會看到 productpage 頁面中會隨機展示 reviews 服務的不同版本的效果(紅色、黑色的星形或者沒有顯示)。

 

 

 

通過istio的ingressgateway訪問,官網:

https://istio.io/docs/examples/bookinfo/#determine-the-ingress-ip-and-port

擴展:添加外部IP-extertal-IP

[root@xianchaomaster1 ~]# kubectl edit svc istio-ingressgateway -n istio-system

 

 

 

[root@xianchaomaster1 ~]# kubectl get  service istio-ingressgateway -n istio-system

 

 

 

在windows機器上的C:\Windows\System32\drivers\etc\hosts里面最后一行加上如下域名解析:
192.168.40.180 productpage.xianchao.cn
在瀏覽器訪問:
http://productpage.xianchao.cn/productpage

5.4 卸載bookinfo服務
可以使用下面的命令來完成應用的刪除和清理了:
1.刪除路由規則,並銷毀應用的 Pod
sh samples/bookinfo/platform/kube/cleanup.sh
2.確認應用已經關停
kubectl get virtualservices     #-- there should be no virtual services
kubectl get destinationrules   #-- there should be no destination rules
kubectl get gateway           #-- there should be no gateway
kubectl get pods               #-- the Bookinfo pods should be deleted

6、通過Istio實現灰度發布

6.1 什么是灰度發布?

灰度發布也叫金絲雀部署 ,是指通過控制流量的比例,實現新老版本的逐步更替。
比如對於服務A 有 version1、 version2 兩個版本 , 當前兩個版本同時部署,但是version1比例90% ,version2比例10% ,看運行效果,如果效果好逐步調整流量占比 80~20 ,70~30 ·····10~90 ,0,100 ,最終version1版本下線。


灰度發布的特點:
1)新老板共存
2)可以實時根據反饋動態調整占比
3)理論上不存在服務完全宕機的情況。
4)適合於服務的平滑升級與動態更新。

 

6.2 使用istio進行金絲雀發布

下面實驗需要的鏡像包在課件,把canary-v2.tar.gz和canary-v1.tar.gz上傳到k8s工作節點,手動解壓:
[root@xianchaonode1 ~]# docker load -i canary-v2.tar.gz
[root@xianchaonode1 ~]# docker load -i canary-v1.tar.gz

創建金絲雀服務
cat deployment.yaml,內容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: appv1
  labels:
    app: v1
spec:
  replicas: 1
  selector:
    matchLabels:
      app: v1
      apply: canary
  template:
    metadata:
      labels:
        app: v1
        apply: canary
    spec:
      containers:
      - name: nginx
        image: xianchao/canary:v1
        ports:
        - containerPort: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: appv2
  labels:
    app: v2
spec:
  replicas: 1
  selector:
    matchLabels:
      app: v2
      apply: canary
  template:
    metadata:
      labels:
        app: v2
        apply: canary
    spec:
      containers:
      - name: nginx
        image: xianchao/canary:v2
        ports:
        - containerPort: 80


更新:
kubectl apply -f deployment.yaml

創建service
cat service.yaml文件,內容如下:
apiVersion: v1
kind: Service
metadata:
  name: canary
  labels:
    apply: canary
spec:
  selector:
    apply: canary
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

更新service.yaml文件
kubectl apply -f service.yaml

創建gateway
cat gateway.yaml文件,內容如下:

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: canary-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
- "*"

更新gateway.yaml
kubectl apply -f gateway.yaml
創建virtualservice
cat virtual.yaml,內容如下:

apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: canary
spec:
  hosts:
  - "*"
  gateways:
  - canary-gateway
  http:
  - route:
    - destination:
        host: canary.default.svc.cluster.local
        subset: v1
      weight: 90
    - destination:
        host: canary.default.svc.cluster.local
        subset: v2
      weight: 10
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: canary
spec:
  host: canary.default.svc.cluster.local
  subsets:
  - name: v1
    labels:
      app: v1
  - name: v2
    labels:
      app: v2
更新virtual.yaml文件
kubectl apply -f virtual.yaml

(5)獲取Ingress_port:
kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}'

顯示結果是30871
驗證金絲雀發布效果:
for i in `seq 1 100`; do curl 192.168.40.180:30871;done > 1.txt
打開1.txt可以看到結果有90次出現v1,10次出現canary-v2,符合我們預先設計的流量走向。

7、istio核心資源解讀

官網:

https://istio.io/latest/docs/concepts/traffic-management/

7.1 Gateway

在Kubernetes環境中,Ingress controller用於管理進入集群的流量。在Istio服務網格中 Istio Ingress Gateway承擔相應的角色,它使用新的配置模型(Gateway 和 VirtualServices)完成流量管理的功能。通過下圖做一個總的描述

 

1、用戶向某端口發出請求

2、負載均衡器監聽端口,並將請求轉發到集群中的某個節點上。Istio Ingress Gateway Service 會監聽集群節點端口的請求

3、Istio Ingress Gateway Service 將請求交給Istio Ingress Gateway Pod 處理。IngressGateway Pod 通過 Gateway 和 VirtualService 配置規則處理請求。其中,Gateway 用來配置端口、協議和證書;VirtualService 用來配置一些路由信息(找到請求對應處理的服務App Service)

4、Istio Ingress Gateway Pod將請求轉給App Service

5、最終的請求會交給App Service 關聯的App Deployment處理

cat gateway.yaml
apiVersion: networking.istio.io/v1beta1 
kind: Gateway
metadata:
  name: canary-gateway
spec:
  selector:
    istio: ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
- "*"

 

網關是一個運行在網格邊緣的負載均衡器,用於接收傳入或傳出的HTTP/TCP連接。主要工作是接受外部請求,把請求轉發到內部服務。網格邊緣的Ingress 流量,會通過對應的 Istio IngressGateway Controller 進入到集群內部。

 在上面這個yaml里我們配置了一個監聽80端口的入口網關,它會將80端口的http流量導入到集群內對應的Virtual Service上。

 注意:hosts:

- "*"

*表示通配符,通過任何域名都可以訪問

7.2 VirtualService

VirtualService是Istio流量治理的一個核心配置,可以說是Istio流量治理中最重要、最復雜的。VirtualService在形式上表示一個虛擬服務,將滿足條件的流量都轉發到對應的服務后端,這個服務后端可以是一個服務,也可以是在DestinationRule中定義的服務的子集。

cat virtual.yaml
apiVersion:  networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: canary
spec:
  hosts:
  - "*"
  gateways:
  - canary-gateway
  http:
  - route:
    - destination:
        host: canary.default.svc.cluster.local
        subset: v1
      weight: 90
    - destination:
        host: canary.default.svc.cluster.local
        subset: v2
      weight: 10

這個虛擬服務會收到上一個gateway中所有80端口來的http流量。

 

VirtualService 主要由以下部分組成

1、hosts:虛擬主機名稱,如果在 Kubernetes 集群中,則這個主機名可以是service服務名。

hosts字段列出了virtual service的虛擬主機。它是客戶端向服務發送請求時使用的一個或多個地址,通過該字段提供的地址訪問virtual service,進而訪問后端服務。在集群內部(網格內)使用時通常與kubernetes的Service同名;當需要在集群外部(網格外)訪問時,該字段為gateway請求的地址,即與gateway的hosts字段相同。

hosts:

- reviews

virtual service的主機名可以是IP地址、DNS名稱,也可以是短名稱(例如Kubernetes服務短名稱),該名稱會被隱式或顯式解析為全限定域名(FQDN),具體取決於istio依賴的平台。可以使用前綴通配符(“*”)為所有匹配的服務創建一組路由規則。virtual service的hosts不一定是Istio服務注冊表的一部分,它們只是虛擬目的地,允許用戶為網格無法路由到的虛擬主機建立流量模型。

 

virtual service的hosts短域名在解析為完整的域名時,補齊的namespace是VirtualService所在的命名空間,而非Service所在的命名空間。如上例的hosts會被解析為:reviews.default.svc.cluster.local。

 

hosts:

  - "*"

*表示通配符,任何域名都可以

如在虛擬機配置hosts文件

192.168.40.180   xianchaomaster1 hello.com.cn

這樣就可以在虛擬機通過域名hello.com.cn訪問istio內部的服務了

 

擴展:virtualservice配置路由規則

路由規則的功能是:滿足http.match條件的流量都被路由到http.route.destination,執行重定向(HTTPRedirect)、重寫(HTTPRewrite)、重試(HTTPRetry)、故障注入(HTTPFaultInjection)、跨站(CorsPolicy)策略等。HTTPRoute不僅可以做路由匹配,還可以做一些寫操作來修改請求本身。

如下:

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: reviews
spec:
  hosts:
  - reviews
  http:
  - match:
    - headers:
        end-user:
          exact: jason
    route:
    - destination:
        host: reviews
        subset: v2
  - route:
    - destination:
        host: reviews
        subset: v3

 在 http 字段包含了虛擬服務的路由規則,用來描述匹配條件和路由行為,它們把 HTTP/1.1、HTTP2 和 gRPC 等流量發送到 hosts 字段指定的目標。

 示例中的第一個路由規則有一個條件,以 match 字段開始。此路由接收來自 ”jason“ 用戶的所有請求,把請求發送到destination指定的v2子集。

7.2.1 路由規則優先級

在上面例子中,不滿足第一個路由規則的流量均流向一個默認的目標,該目標在第二條規則中指定。因此,第二條規則沒有 match 條件,直接將流量導向 v3 子集。

7.2.2 多路由規則解讀

詳細配置可參考:

https://istio.io/latest/zh/docs/reference/config/networking/virtual-service/#HTTPMatchRequest

apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: bookinfo
spec:
  hosts:
    - bookinfo.com
  http:
  - match:
    - uri:
        prefix: /reviews
    route:
    - destination:
        host: reviews
  - match:
    - uri:
        prefix: /ratings
    route:
    - destination:
        host: ratings

路由規則是將特定流量子集路由到指定目標地址的工具。可以在流量端口、header 字段、URI 等內容上設置匹配條件。例如,上面這個虛擬服務讓用戶發送請求到兩個獨立的服務:ratings 和 reviews,相當於訪問http://bookinfo.com/ratings 和http://bookinfo.com/ reviews,虛擬服務規則根據請求的 URI 把請求路由到特定的目標地址。

2、Gateway:流量來源網關。

3、路由:

路由的destination字段指定了匹配條件的流量的實際地址。與virtual service的主機不同,該host必須是存在於istio的服務注冊表(如kubernetes services,consul services等)中的真實目的地或由ServiceEntries聲明的hosts,否則Envoy不知道應該將流量發送到哪里。它可以是一個帶代理的網格服務或使用service entry添加的非網格服務。在kubernetes作為平台的情況下,host表示名為kubernetes的service名稱:

 - destination:

        host: canary.default.svc.cluster.local

        subset: v1

      weight: 90

7.3 DestinationRule

destination rule是istio流量路由功能的重要組成部分。一個virtual service可以看作是如何將流量分發給特定的目的地,然后調用destination rule來配置分發到該目的地的流量。destination rule在virtual service的路由規則之后起作用(即在virtual service的math->route-destination之后起作用,此時流量已經分發到真實的service上),應用於真實的目的地。

可以使用destination rule來指定命名的服務子集,例如根據版本對服務的實例進行分組,然后通過virtual service的路由規則中的服務子集將控制流量分發到不同服務的實例中。

cat DestinationRule.yaml
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: canary
spec:
  host: canary.default.svc.cluster.local
  subsets:
  - name: v1
    labels:
      app: v1
  - name: v2
    labels:
      app: v2

在虛擬服務中使用Hosts配置默認綁定的路由地址,用http.route字段,設置http進入的路由地址,可以看到,上面導入到了目標規則為v1和v2的子集。

v1子集對應的是具有如下標簽的pod:
selector:
    matchLabels:
      app: v1

流量控制流程:

Gateway->VirtaulService->TCP/HTTP Router->DestinationWeight->Subset:Port

8、istio核心功能演示

8.1 斷路器

官網:

https://istio.io/latest/zh/docs/tasks/traffic-management/circuit-breaking/

 

斷路器是創建彈性微服務應用程序的重要模式。斷路器使應用程序可以適應網絡故障和延遲等網絡不良影響。

 

測試斷路器:

1、在k8s集群創建后端服務

[root@xianchaomaster1 istio-1.10.1]# cat samples/httpbin/httpbin.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: httpbin
---
apiVersion: v1
kind: Service
metadata:
  name: httpbin
  labels:
    app: httpbin
    service: httpbin
spec:
  ports:
  - name: http
    port: 8000
    targetPort: 80
  selector:
    app: httpbin
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
      version: v1
  template:
    metadata:
      labels:
        app: httpbin
        version: v1
    spec:
      serviceAccountName: httpbin
      containers:
      - image: docker.io/kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        ports:
        - containerPort: 80
#把httpbin.tar.gz上傳到xianchaonode1節點,手動解壓:
[root@xianchaonode1 ~]# docker load -i httpbin.tar.gz
[root@xianchaomaster1 istio-1.10.1]# kubectl apply -f samples/httpbin/httpbin.yaml
#該httpbin應用程序充當后端服務。

2、配置斷路器

#創建一個目標規則,在調用httpbin服務時應用斷路器設置:

[root@xianchaomaster1 istio-1.10.1]# vim destination.yaml 
apiVersion:  networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: httpbin
spec:
  host: httpbin
  trafficPolicy:
    connectionPool:
#連接池(TCP | HTTP)配置,例如:連接數、並發請求等
      tcp:
        maxConnections: 1  
#TCP連接池中的最大連接請求數,當超過這個值,會返回503代碼。如兩個請求過來,就會有一個請求返回503。
      http:
        http1MaxPendingRequests: 1   
#連接到目標主機的最大掛起請求數,也就是待處理請求數。這里的目標指的是 virtualservice 路由規則中配置的 destination。
        maxRequestsPerConnection: 1 
#連接池中每個連接最多處理1個請求后就關閉,並根據需要重新創建連接池中的連接
    outlierDetection:
#異常檢測配置,傳統意義上的熔斷配置,即對規定時間內服務錯誤數的監測
      consecutiveGatewayErrors: 1
#連續錯誤數1,即連續返回502-504狀態碼的Http請求錯誤數 
      interval: 1s
#錯誤異常的掃描間隔1s,即在interval(1s)內連續發生consecutiveGatewayErrors(1)個錯誤,則觸發服務熔斷
      baseEjectionTime: 3m
#基本驅逐時間3分鍾,實際驅逐時間為baseEjectionTime*驅逐次數
      maxEjectionPercent: 100
#最大驅逐百分比100%

[root@xianchaomaster1 istio-1.10.1]# kubectl apply -f destination.yaml 
destinationrule.networking.istio.io/httpbin created

3、添加客戶端訪問httpbin服務

創建一個客戶端以將流量發送給httpbin服務。該客戶端是一個簡單的負載測試客戶端,Fortio可以控制連接數,並發數和HTTP調用延遲。使用此客戶端來“跳閘”在DestinationRule中設置的斷路器策略。

#通過執行下面的命令部署fortio客戶端:
#把fortio.tar.gz上傳到xianchaonode1節點,手動解壓:
[root@xianchaonode1 ~]# docker load -i fortio.tar.gz
[root@xianchaomaster1 istio-1.10.1]# kubectl apply -f  samples/httpbin/sample-client/fortio-deploy.yaml

#通過kubectl執行下面的命令,使用fortio客戶端工具調用httpbin:
[root@xianchaomaster1 istio-1.10.1]# kubectl get pods 
NAME                              READY   STATUS    RESTARTS   AGE
appv1-77b5cbd5cc-bmch2            2/2     Running   0          28m
appv2-f78cb577-n7rhc              2/2     Running   0          28m
details-v1-847c7999fb-htd2z       2/2     Running   0          28m
fortio-deploy-576dbdfbc4-z28m7    2/2     Running   0          3m32s
httpbin-74fb669cc6-hqtzl          2/2     Running   0          15m
productpage-v1-5f7cf79d5d-6d4lx   2/2     Running   0          28m
ratings-v1-7c46bc6f4d-sfqnz       2/2     Running   0          28m
reviews-v1-549967c688-pr8gh       2/2     Running   0          28m
reviews-v2-cf9c5bfcd-tn5z5        2/2     Running   0          28m
reviews-v3-556dbb4456-dxt4r       2/2     Running   0          28m

[root@xianchaomaster1 istio-1.10.1]# kubectl exec  fortio-deploy-576dbdfbc4-z28m7   -c fortio -- /usr/bin/fortio curl  http://httpbin:8000/get
#顯示如下:
HTTP/1.1 200 OK
server: envoy
date: Mon, 03 May 2021 02:28:06 GMT
content-type: application/json
content-length: 622
access-control-allow-origin: *
access-control-allow-credentials: true
x-envoy-upstream-service-time: 2

{
  "args": {}, 
  "headers": {
    "Content-Length": "0", 
    "Host": "httpbin:8000", 
    "User-Agent": "fortio.org/fortio-1.11.3", 
    "X-B3-Parentspanid": "4631e62a6cd0b167", 
    "X-B3-Sampled": "1", 
    "X-B3-Spanid": "6d20afff1671aa89", 
    "X-B3-Traceid": "6f4ddb61363d04d54631e62a6cd0b167", 
    "X-Envoy-Attempt-Count": "1", 
    "X-Forwarded-Client-Cert": "By=spiffe://cluster.local/ns/default/sa/httpbin;Hash=498edf0dcb7f6e74f40735869a9912eca62d61fb21dbc190943c1c19dbf01c18;Subject=\"\";URI=spiffe://cluster.local/ns/default/sa/default"
  }, 
  "origin": "127.0.0.1", 
  "url": "http://httpbin:8000/get"
}

4、觸發斷路器

在DestinationRule設置中,指定了maxConnections: 1和 http1MaxPendingRequests: 1。這些規則表明,如果超過一個以上的連接並發請求,則istio-proxy在為進一步的請求和連接打開路由時,應該會看到下面的情況 。

以兩個並發連接(-c 2)和發送20個請求(-n 20)調用服務:

[root@xianchaomaster1 istio-1.10.1]# kubectl exec -it fortio-deploy-576dbdfbc4-z28m7  -c fortio -- /usr/bin/fortio load  -c 2 -qps 0 -n 20 -loglevel Warning http://httpbin:8000/get

#顯示如下:
02:31:00 I logger.go:127> Log level is now 3 Warning (was 2 Info)
Fortio 1.11.3 running at 0 queries per second, 6->6 procs, for 20 calls: http://httpbin:8000/get
Starting at max qps with 2 thread(s) [gomax 6] for exactly 20 calls (10 per thread + 0)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
02:31:00 W http_client.go:693> Parsed non ok code 503 (HTTP/1.1 503)
Ended after 69.506935ms : 20 calls. qps=287.74
Aggregated Function Time : count 20 avg 0.0054352091 +/- 0.01077 min 0.000474314 max 0.04968864 sum 0.108704183
# range, mid point, percentile, count
>= 0.000474314 <= 0.001 , 0.000737157 , 35.00, 7
> 0.001 <= 0.002 , 0.0015 , 50.00, 3
> 0.002 <= 0.003 , 0.0025 , 65.00, 3
> 0.004 <= 0.005 , 0.0045 , 75.00, 2
> 0.005 <= 0.006 , 0.0055 , 85.00, 2
> 0.007 <= 0.008 , 0.0075 , 90.00, 1
> 0.016 <= 0.018 , 0.017 , 95.00, 1
> 0.045 <= 0.0496886 , 0.0473443 , 100.00, 1
# target 50% 0.002
# target 75% 0.005
# target 90% 0.008
# target 99% 0.0487509
# target 99.9% 0.0495949
Sockets used: 16 (for perfect keepalive, would be 2)
Jitter: false
Code 200 : 4 (20.0 %)
Code 503 : 16 (80.0 %)
#只有20%成功了,其余的都斷開了
Response Header Sizes : count 20 avg 46 +/- 92 min 0 max 230 sum 920
Response Body/Total Sizes : count 20 avg 292.8 +/- 279.6 min 153 max 852 sum 5856
All done 20 calls (plus 0 warmup) 5.435 ms avg, 287.7 qps

8.2 超時

 

在生產環境中經常會碰到由於調用方等待下游的響應過長,堆積大量的請求阻塞了自身服務,造成雪崩的情況,通過通過超時處理來避免由於無限期等待造成的故障,進而增強服務的可用性,Istio 使用虛擬服務來優雅實現超時處理。

下面例子模擬客戶端調用 nginx,nginx 將請求轉發給 tomcat。nginx 服務設置了超時時間為2秒,如果超出這個時間就不在等待,返回超時錯誤。tomcat服務設置了響應時間延遲10秒,任何請求都需要等待10秒后才能返回。client 通過訪問 nginx 服務去反向代理 tomcat服務,由於 tomcat服務需要10秒后才能返回,但nginx 服務只等待2秒,所以客戶端會提示超時錯誤。

#把busybox.tar.gz、 nginx.tar.gz、 tomcat-app.tar.gz上傳到xianchaonode1節點,手動解壓:
[root@xianchaonode1 ~]# docker load -i nginx.tar.gz 
[root@xianchaonode1 ~]# docker load -i busybox.tar.gz 
[root@xianchaonode1 ~]# docker load -i tomcat-app.tar.gz 
[root@xianchaomaster1 ~]# mkdir /root/timeout
[root@xianchaomaster1 ~]# cd /root/timeout/
[root@xianchaomaster1 timeout]# cat nginx-deployment.yaml 
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  labels:
    server: nginx
    app: web
spec:
  replicas: 1
  selector:
    matchLabels:
      server: nginx
      app: web
  template:
    metadata:
      name: nginx
      labels: 
        server: nginx
        app: web
    spec:
      containers:
      - name: nginx
        image: nginx:1.14-alpine
        imagePullPolicy: IfNotPresent
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tomcat
  labels:
    server: tomcat
    app: web
spec:
  replicas: 1
  selector:
    matchLabels:
      server: tomcat
      app: web
  template:
    metadata:
      name: tomcat
      labels: 
        server: tomcat
        app: web
    spec:
      containers:
      - name: tomcat
        image: docker.io/kubeguide/tomcat-app:v1 
        imagePullPolicy: IfNotPresent

[root@xianchaomaster1 timeout]# cat nginx-tomcat-svc.yaml 
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-svc
spec:
  selector:
    server: nginx
  ports:
  - name: http
    port: 80
    targetPort: 80
    protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
  name: tomcat-svc
spec:
  selector:
    server: tomcat
  ports:
  - name: http
    port: 8080
    targetPort: 8080
    protocol: TCP

[root@xianchaomaster1 timeout]# cat virtual-tomcat.yaml 
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: nginx-vs
spec:
  hosts:
  - nginx-svc
  http:
  - route:
    - destination: 
        host: nginx-svc
    timeout: 2s
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: tomcat-vs
spec:
  hosts:
  - tomcat-svc
  http:
  - fault:
      delay:
        percentage:
          value: 100
        fixedDelay: 10s
    route:
    - destination:
        host: tomcat-svc
#virtual-tomcat.yaml資源清單重點知識講解
第一:故障注入:
http:
- fault:
    delay:
      percentage:
      value: 100
   fixedDelay: 10s
該設置說明每次調用 tomcat-svc 的 k8s service,都會延遲10s才會調用。
第二:調用超時:
hosts:
- nginx-svc
  http:
  - route:
    - destination:
      host: nginx-svc
    timeout: 2s
該設置說明調用 nginx-svc 的 k8s service,請求超時時間是 2s。

#部署tomcat、nginx服務
需要對nginx-deployment.yaml資源文件進行 Istio 注入,將 nginx、tomcat 都放入到網格中。可以采用手工注入 Istio 方式。
[root@xianchaomaster1 timeout]# kubectl apply -f nginx-deployment.yaml
執行成功后,通過 kubectl get pods 查看 Istio 注入情況:
[root@xianchaomaster1 timeout]# kubectl get pods
NAME                              READY   STATUS             RESTARTS   AGE
nginx-tomcat-7dd6f74846-48g9f      2/2     Running   0          6m36s
tomcat-86ddb8f5c9-h6jdl            2/2     Running              0           53s

#部署nginx和tomcat的service 
[root@xianchaomaster1 timeout]# kubectl apply -f nginx-tomcat-svc.yaml
#部署虛擬服務
[root@xianchaomaster1 timeout]# kubectl apply -f virtual-tomcat.yaml

#設置超時時間

[root@xianchaomaster1 timeout]# kubectl exec -it nginx-tomcat-7dd6f74846-48g9f --  sh
# apt-get update
# apt-get install vim -y
/ # vim /etc/nginx/conf.d/default.conf

 

proxy_pass http://tomcat-svc:8080;
proxy_http_version 1.1;
編輯完后,再執行如下語句驗證配置和讓配置生效:
/ # nginx -t
/ # nginx -s reload

這樣,整個樣例配置和部署都完成了。

#驗證超時
登錄client,執行如下語句:
[root@xianchaomaster1 timeout]# kubectl run busybox --image busybox:1.28 --restart=Never --rm -it busybox -- sh
/ # time wget -q -O - http://nginx-svc
wget: server returned error: HTTP/1.1 408 Request Timeout
Command exited with non-zero status 1
real    0m 2.02s
user    0m 0.00s
sys    0m 0.00s

/ # while true; do wget -q -O - http://nginx-svc; done
wget: server returned error: HTTP/1.1 504 Gateway Timeout
wget: server returned error: HTTP/1.1 504 Gateway Timeout
wget: server returned error: HTTP/1.1 504 Gateway Timeout
wget: server returned error: HTTP/1.1 504 Gateway Timeout
wget: server returned error: HTTP/1.1 408 Request Timeout

每隔2秒,由於 nginx 服務的超時時間到了而 tomcat未有響應,則提示返回超時錯誤。

驗證故障注入效果,執行如下語句:
/ # time wget -q -O - http://tomcat-svc
wget: server returned error: HTTP/1.1 503 Service Unavailable
Command exited with non-zero status 1
real    0m 10.02s
user    0m 0.00s
sys    0m 0.01s
執行之后10s才會有結果

8.3 故障注入和重試

Istio 重試機制就是如果調用服務失敗,Envoy 代理嘗試連接服務的最大次數。而默認情況下,Envoy 代理在失敗后並不會嘗試重新連接服務,除非我們啟動 Istio 重試機制。

下面例子模擬客戶端調用 nginx,nginx 將請求轉發給 tomcat。tomcat 通過故障注入而中止對外服務,nginx 設置如果訪問 tomcat 失敗則會重試 3 次。

 

[root@xianchaomaster1 attemp]# cd /root/timeout/
[root@xianchaomaster1 timeout]# kubectl delete -f .
[root@xianchaomaster1 timeout]# kubectl apply -f nginx-deployment.yaml 
[root@xianchaomaster1 timeout]# kubectl apply -f nginx-tomcat-svc.yaml 
[root@xianchaomaster1 ~]# kubectl get pods
NAME                              READY   STATUS    RESTARTS   AGE
busybox                           2/2     Running   0          55m
nginx-7f6496574c-zbtqj            2/2     Running   0          10m
tomcat-86ddb8f5c9-dqxcq           2/2     Running   0          35m

[root@xianchaomaster1 timeout]# cat virtual-attempt.yaml 
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: nginx-vs
spec:
  hosts:
  - nginx-svc
  http:
  - route:
    - destination: 
        host: nginx-svc
    retries:
      attempts: 3
      perTryTimeout: 2s
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: tomcat-vs
spec:
  hosts:
  - tomcat-svc
  http:
  - fault:
      abort:
        percentage:
          value: 100
        httpStatus: 503
    route:
    - destination:
        host: tomcat-svc
[root@xianchaomaster1 timeout]# kubectl apply -f virtual-attempt.yaml
虛擬服務資源清單解讀:
第一:故障注入。該虛擬服務的作用對象就是 tomcat-svc。使用此故障注入后,在網格中該 tomcat 就是不可用的。
abort:
        percentage:
          value: 100
        httpStatus: 503

abort是模擬tomcat服務始終不可用,該設置說明每次調用 tomcat-svc 的 k8s service,100%都會返回錯誤狀態碼503。

第二:調用超時:
hosts:
- nginx-svc
  http:
  - route:
    - destination:
      host: nginx-svc
    reties:
      attempts: 3 
      perTryTimeout: 2s
該設置說明調用 nginx-svc 的 k8s service,在初始調用失敗后最多重試 3 次來連接到服務子集,每個重試都有 2 秒的超時。 

[root@xianchaomaster1 timeout]# kubectl exec -it nginx-tomcat-7dd6f74846-rdqqf -- /bin/sh
# apt-get update
# apt-get install vim -y
/ # vi /etc/nginx/conf.d/default.conf

 

/ # nginx -t
/ # nginx -s reload

#驗證重試是否生效
[root@xianchaomaster1 timeout]#  kubectl run busybox --image busybox:1.28 --restart=Never --rm -it busybox -- sh

/ # wget -q -O - http://nginx-svc 

[root@xianchaomaster1 timeout]# kubectl logs -f nginx-tomcat-7dd6f74846-rdqqf  -c istio-proxy
#執行結果如下:

由上圖可知,重試設置生效。

9、分布式追蹤系統-jaeger

1.什么是分布式追蹤?

分布式追蹤最早由谷歌的Dapper普及開來,它本質上是具有在微服務的整個生命周期中追蹤請求的能力。分布式追蹤(Distributed Tracing)主要用於記錄整個請求鏈的信息。

 

2.為什么要分布式追蹤?

當業務微服務化后,一次業務請求,可能會涉及到多個微服務,分布式跟蹤可以對跨多個分布式服務網格的1個請求進行追蹤分析,並通過可視化的方式深入地了解請求的延遲,序列化和並發,充分地了解服務流量實況,從而快速地排查和定位問題。在微服務應用中,一個完整的業務往往需要調用多個服務才能完成,服務之間就產生了交互。當出現故障時,如何找到問題的根源非常重要。追蹤系統可以清晰地展示出請求的整個調用鏈以及每一步的耗時,方便查找問題所在。

 

3.分布式追蹤系統-jaeger

Jaeger是一個開源的分布式追蹤系統,它可以在復雜的分布式系統中進行監控和故障排查。Jaeger的主要功能包括分布式請求監控、性能調優、故障分析和服務依賴分析等。

 

Jaeger組件介紹:

jaeger-agent:

負責發送的進程,對spans進行處理並發送給collector,監聽spans的UDP 發送。這層作為基礎組件部署在主機上,Agent將Client Library和Collector解耦,為ClientLibrary屏蔽了路由和發現Collector的細節。

 

jaeger-collector:

收集追蹤 spans,並通過管道對追蹤數據進行處理。當前的管道支持追蹤的驗證、索引、轉換,最后存儲數據

 

jaeger-query:

從存儲中檢索追蹤信息並通過 UI 展示

 

data store:

追蹤信息的存儲

 

4.使用jaeger

kubectl get svc -n istio-system | grep jaeger  

顯示如下:
jaeger-agent                ClusterIP   None             <none>        5775/UDP,6831/UDP,6832/UDP                                                                                                                   55d
jaeger-collector            ClusterIP   10.99.194.57     <none>        14267/TCP,14268/TCP,14250/TCP                                                                                                                55d
jaeger-collector-headless   ClusterIP   None             <none>        14250/TCP                                                                                                                                    55d
jaeger-query                ClusterIP   10.107.192.115   <none>        16686/TCP

修改jaeger-query的type類型為nodePort
kubectl edit svc jaeger-query -n istio-system

把type: ClusterIP變成type: NodePort

kubectl get svc -n istio-system | grep jaeger-query

顯示如下:
jaeger-query                NodePort    10.107.192.115   <none>        16686:31450/TCP  

在瀏覽器訪問:
192.168.40.180:31450
5.查看追蹤數據
在Jaeger左側版面的Service下拉列表中選擇v1.default,單擊Find Traces按鈕,會看到如下圖

 

 

單擊右側的URL進入詳細頁,可以看到具體的服務調用情況,並且能夠了解每個服務的耗時

 

6. 追蹤上下文傳遞

Istio 利用 Envoy 的分布式追蹤功能提供了開箱即用的追蹤集成。確切地說,Istio 提供了安裝各種追蹤后端服務的選項,並且通過配置代理來自動發送追蹤 span 到追蹤后端服務。盡管 Istio 代理能夠自動發送 span,但是他們需要一些附加線索才能將整個追蹤鏈路關聯到一起。所以當代理發送 span 信息的時候,應用需要附加適當的 HTTP 請求頭信息,這樣才能夠把多個 span 正確的關聯到同一個追蹤上。

要做到這一點,應用程序從傳入請求到任何傳出的請求中需要包含以下請求頭參數:

x-request-id

x-b3-traceid

x-b3-spanid

x-b3-parentspanid

x-b3-sampled

x-b3-flags

x-ot-span-context

 

10、分布式追蹤系統-kiali

Kiali是Istio服務網格的可視化工具,它主要的功能是用可視化的界面來觀察微服務系統以及服務之間的關系。Kiali功能如下。

1)服務拓撲圖:這是Kiali最主要的功能,提供了一個總的服務視圖,可以實時地顯示命名空間下服務之間的調用和層級關系,以及負載情況。·

2)服務列表視圖:展示了系統中所有的服務,以及它們的健康狀況和出錯率。· 工作負載視圖:展示服務的負載情況。

3)Istio配置視圖:展示了所有的Istio配置對象。

Kiali的架構比較簡單,如下圖,它分為前端和后端兩部分。后端以容器的方式運行在應用平台,負責獲取和處理數據,並發送給前端;前端是一個典型的Web應用,由React和TypeScript實現,負責展示后端發送過來的數據。對Kiali來說Istio是必須存在的系統,它類似於Kiali的宿主。雖然它們可以分開部署,但沒有了Istio,Kiali是不能工作的。

 

2.使用:
kubectl get svc -n istio-system | grep kiali

顯示如下:
kiali                       ClusterIP   10.106.61.5      <none>        20001/TCP

修改kiali的type類型為nodePort
kubectl edit svc kiali -n istio-system

把type: ClusterIP變成type: NodePort

kubectl get svc -n istio-system | grep kiali

顯示如下:
kiali                       NodePort    10.106.61.5      <none>        20001:32514/TCP

在瀏覽器訪問192.168.40.180:32514

 

 

Username:admin

Password: admin

 

輸入用戶名和密碼之后出現如下界面:

Kiali是一個非常強大的可視化工具,可以讓用戶清晰和直觀地了解到Istio服務網格中的服務以及服務之間的關系。除了服務拓撲圖外,它還提供了健康檢查、指標數據顯示和配置驗證等功能。強烈推薦把Kiali作為必選項添加到服務網格中,來幫助監控和觀測網格中服務的工作情況。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM