tft每日頭條

 > 生活

 > istio和微服務有什麼不同

istio和微服務有什麼不同

生活 更新时间:2024-06-29 10:17:08

Istio is the future!基本上,我相信對雲原生技術趨勢有些微判斷的同學,都會有這個覺悟。其背後的邏輯其實是比較簡單的:當容器集群,特别是K8S成為事實上的标準之後,應用必然會不斷的複雜化,服務治理肯定會成為強需求。

Istio的現狀是,聊的人很多,用的人其實很少。所以導緻我們能看到的文章,講道理的很多,講實際踩坑經驗的極少。

阿裡雲售後團隊作為一線踩坑團隊,分享問題排查經驗,我們責無旁貸。這篇文章,我就跟大家聊一個簡單Istio問題的排查過程,權當抛磚。

二分之一活的微服務

問題是這樣的,用戶在自己的測試集群裡安裝了Istio,并依照官方文檔部署bookinfo應用來上手Istio。部署之後,用戶執行kubectl get pods命令,發現所有的pods都隻有二分之一個容器是READY的。

istio和微服務有什麼不同(Istio從懵圈到熟練)1

如果從來都沒有注意過READY這一列的話,我們大概會有兩個疑惑:2在這裡是什麼意思,以及1/2到底意味着什麼。

簡單來講,這裡的READY列,給出的是每個pod内部容器的readiness,即就緒狀态。每個集群節點上的kubelet會根據容器本身readiness規則的定義,分别是tcp、http或exec的方式,來确認對應容器的readiness情況。

更具體一點,kubelet作為運行在每個節點上的進程,以tcp/http的方式(節點網絡命名空間到pod網絡命名空間)訪問容器定義的接口,或者在容器的namespace裡執行exec定義的命令,來确定容器是否就緒。

istio和微服務有什麼不同(Istio從懵圈到熟練)2

這裡的2說明這些pod裡都有兩個容器,1/2則表示,每個pod裡隻有一個容器是就緒的,即通過readiness測試的。關于2這一點,我們下一節會深入講,這裡我們先看一下,為什麼所有的pod裡,都有一個容器沒有就緒。

使用kubectl工具拉取第一個details pod的編排模闆,可以看到這個pod裡兩個容器,隻有一個定義了readiness probe。對于未定義readiness probe的容器,kubelet認為,隻要容器裡的進程開始運行,容器就進入就緒狀态了。所以1/2個就緒pod,意味着,有定義readiness probe的容器,沒有通過kubelet的測試。

沒有通過readiness probe測試的是istio-proxy這個容器。它的readiness probe規則定義如下。

istio和微服務有什麼不同(Istio從懵圈到熟練)3

我們登錄這個pod所在的節點,用curl工具來模拟kubelet訪問下邊的uri,測試istio-proxy的就緒狀态。

istio和微服務有什麼不同(Istio從懵圈到熟練)4

繞不過去的大圖

上一節我們描述了問題現象,但是留下一個問題,就是pod裡的容器個數為什麼是2。雖然每個pod本質上至少有兩個容器,一個是占位符容器pause,另一個是真正的工作容器,但是我們在使用kubectl命令獲取pod列表的時候,READY列是不包括pause容器的。

這裡的另外一個容器,其實就是服務網格的核心概念sidercar。其實把這個容器叫做sidecar,某種意義上是不能反映這個容器的本質的。Sidecar容器本質上是反向代理,它本來是一個pod訪問其他服務後端pod的負載均衡。

istio和微服務有什麼不同(Istio從懵圈到熟練)5

然而,當我們為集群中的每一個pod,都“随身”攜帶一個反向代理的時候,pod和反向代理就變成了服務網格。正如下邊這張經典大圖所示。這張圖實在有點難畫,所以隻能借用,繞不過去。

istio和微服務有什麼不同(Istio從懵圈到熟練)6

所以sidecar模式,其實是“自帶通信員”模式。這裡比較有趣的是,在我們把sidecar和pod綁定在一塊的時候,sidecar在出流量轉發時扮演着反向代理的角色,而在入流量接收的時候,可以做超過反向代理職責的一些事情。這點我們會在其他文章裡讨論。

Istio在K8S基礎上實現了服務網格,Isito使用的sidecar容器就是第一節提到的,沒有就緒的容器。所以這個問題,其實就是服務網格内部,所有的sidecar容器都沒有就緒。

代理與代理的生命周期管理

上一節我們看到,istio中的每個pod,都自帶了反向代理sidecar。我們遇到的問題是,所有的sidecar都沒有就緒。我們也看到readiness probe定義的,判斷sidecar容器就緒的方式就是訪問下邊這個接口。

http://<pod ip>:15020/healthz/ready

接下來,我們深入看下pod,以及其sidecar的組成及原理。在服務網格裡,一個pod内部除了本身處理業務的容器之外,還有istio-proxy這個sidecar容器。正常情況下,istio-proxy會啟動兩個進程,pilot-agent和envoy。

如下圖,envoy是實際上負責流量管理等功能的代理,從業務容器出、入的數據流,都必須要經過envoy;而pilot-agent負責維護envoy的靜态配置,以及管理envoy的生命周期。這裡的動态配置部分,我們在下一節會展開來講。

istio和微服務有什麼不同(Istio從懵圈到熟練)7

我們可以使用下邊的命令進入pod的istio-proxy容器做進一步排查。這裡的一個小技巧,是我們可以以用戶1337,使用特權模式進入istio-proxy容器,如此就可以使用iptables等隻能在特權模式下運行的命令。

docker exec -ti -u 1337 --privileged <istio-proxy container id> bash

這裡的1337用戶,其實是sidecar鏡像裡定義的一個同名用戶istio-proxy,默認sidecar容器使用這個用戶。如果我們在以上命令中,不使用用戶選項u,則特權模式實際上是賦予root用戶的,所以我們在進入容器之後,需切換到root用戶執行特權命令。

進入容器之後,我們使用netstat命令查看監聽,我們會發現,監聽readiness probe端口15020的,其實是pilot-agent進程。

istio-proxy@details-v1-68868454f5-94hzd:/$ netstat -lnpt Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:15090 0.0.0.0:* LISTEN 19/envoy tcp 0 0 127.0.0.1:15000 0.0.0.0:* LISTEN 19/envoy tcp 0 0 0.0.0.0:9080 0.0.0.0:* LISTEN - tcp6 0 0 :::15020 :::* LISTEN 1/pilot-agent

我們在istio-proxy内部訪問readiness probe接口,一樣會得到503的錯誤。

就緒檢查的實現

了解了sidecar的代理,以及管理代理生命周期的pilot-agent進程,我們可以稍微思考一下pilot-agent應該怎麼去實現healthz/ready這個接口。顯然,如果這個接口返回OK的話,那不僅意味着pilot-agent是就緒的,而必須确保代理是工作的。

實際上pilot-agent就緒檢查接口的實現正是如此。這個接口在收到請求之後,會去調用代理envoy的server_info接口。調用所使用的的IP是localhost。這個非常好理解,因為這是同一個pod内部進程通信。使用的端口是envoy的proxyAdminPort,即15000。

istio和微服務有什麼不同(Istio從懵圈到熟練)8

有了以上的知識準備之後,我們來看下istio-proxy這個容器的日志。實際上,在容器日志裡,一直在重複輸出一個報錯,這句報錯分為兩部分,其中Envoy proxy is NOT ready這部分是pilot agent在響應healthz/ready接口的時候輸出的信息,即Envoy代理沒有就緒;而剩下的config not received from Pilot (is Pilot running?): cds updates: 0 successful, 0 rejected; lds updates: 0 successful, 0 rejected這部分,是pilot-agent通過proxyAdminPort訪問server_info的時候帶回的信息,看起來是envoy沒有辦法從Pilot獲取配置。

Envoy proxy is NOT ready: config not received from Pilot (is Pilot running?): cds updates: 0 successful, 0 rejected; lds updates: 0 successful, 0 rejected.

到這裡,建議大家回退看下上一節的插圖,在上一節我們選擇性的忽略是Pilot到envoy這條虛線,即動态配置。這裡的報錯,實際上是envoy從控制面Pilot獲取動态配置失敗。

控制面和數據面

目前為止,這個問題其實已經很清楚了。在進一步分析問題之前,我聊一下我對控制面和數據面的理解。控制面數據面模式,可以說無處不在。我們這裡舉兩個極端的例子。

第一個例子,是dhcp服務器。我們都知道,在局域網中的電腦,可以通過配置dhcp來獲取ip地址,這個例子中,dhcp服務器統一管理,動态分配ip地址給網絡中的電腦,這裡的dhcp服務器就是控制面,而每個動态獲取ip的電腦就是數據面。

第二個例子,是電影劇本,和電影的演出。劇本可以認為是控制面,而電影的演出,包括演員的每一句對白,電影場景布置等,都可以看做是數據面。

我之所以認為這是兩個極端,是因為在第一個例子中,控制面僅僅影響了電腦的一個屬性,而第二個例子,控制面幾乎是數據面的一個完整的抽象和拷貝,影響數據面的方方面面。Istio服務網格的控制面是比較靠近第二個例子的情況,如下圖。

istio和微服務有什麼不同(Istio從懵圈到熟練)9

Istio的控制面Pilot使用grpc協議對外暴露接口istio-pilot.istio-system:15010,而envoy無法從Pilot處獲取動态配置的原因,是在所有的pod中,集群dns都無法使用。

簡單的原因

這個問題的原因其實比較簡單,在sidecar容器istio-proxy裡,envoy不能訪問Pilot的原因是集群dns無法解析istio-pilot.istio-system這個服務名字。在容器裡看到resolv.conf配置的dns服務器是172.19.0.10,這個是集群默認的kube-dns服務地址。

istio和微服務有什麼不同(Istio從懵圈到熟練)10

但是客戶删除重建了kube-dns服務,且沒有指定服務IP,這導緻,實際上集群dns的地址改變了,這也是為什麼所有的sidecar都無法訪問Pilot。

istio和微服務有什麼不同(Istio從懵圈到熟練)11

最後,通過修改kube-dns服務,指定IP地址,sidecar恢複正常。

istio和微服務有什麼不同(Istio從懵圈到熟練)12

結論

這其實是一個比較簡單的問題,排查過程其實也就幾分鐘。但是寫這篇文章,有點感覺是在看長安十二時辰,短短幾分鐘的排查過程,寫完整背後的原理,前因後果,卻花了幾個小時。這是Istio文章的第一篇,希望在大家排查問題的時候,有所幫助。

作者:shengdong

,

更多精彩资讯请关注tft每日頭條,我们将持续为您更新最新资讯!

查看全部

相关生活资讯推荐

热门生活资讯推荐

网友关注

Copyright 2023-2024 - www.tftnews.com All Rights Reserved