k8s常用資源之pod資源(三)
1108
2025-04-01
聲明:本文參考自《云原生王者之路集訓營》,是華為云云原生團隊精心打磨的云原生學習技術公開課,分為黃金、鉆石、王者三個階段,幫助廣大技術愛好者快速掌握云原生相關技能本課程為鉆石課程的第十三課,由華為云容器網格數據面技術專家Sam Zhang主講,深度解析Istio數據面(Envoy)架構
前言
本文分為5個章節進行介紹:
第1章 服務網格數據面Envoy介紹
第2章 Envoy原理及總體架構
第3章 Envoy啟動配置及xDS
第4章 Envoy網絡及線程模型、過濾器架構、HTTP請求流程
第5章 Envoy問題分析方法
希望本文可以對涉及Kubernetes、Istio等技術的應用開發者或者其他的云原生技術興趣愛好者提供幫助,如有問題可在評論下方進行交流
一、Envoy介紹
Envoy采用C++ 實現,本身為四層及七層代理,可以根據用戶應用請求內的數據進行高級服務治理能力,包括服務發現、路由、高級負載均衡、動態配置、鏈路安全及證書更新、目標健康檢查完整的可觀測性等
且前常見數據面主要有三種:Envoy、Linkerd、TraeficEnvoy由于高性能和擴展能力在數據面遙遙領先
Iptables使Pod間出入應用的流量均由Envoy代理,所以對應用來說完全透明支持主要常用網路協議 Http1/Http2/Tls/gRPC/Tcp等
從下圖可以看出 Envoy 主要通過透明的插入代理來攔截服務的進出流量,并且Envoy 之間打通了數據鏈路,,代理了服務的請求
二、Envoy原理及總體架構
可以修改全局注入參數作用于所有目標空間的 pod
1.啟動階段
istiod攔截pod創建請求,識別為指定popsace則根據configmap配置生成帶有Envoy兩個容器的創建POD請求,修改過的創建請求被kubelet接收,并在節點創建POD
istio-init容器添加用于配置容器網絡內iptables規則
istio-proxy容器啟動pilot-agent進程,使用UID=1337GID=1337創建Envoy啟動命令行與配置文件
可以通過自定義deployment內istio注解istio.io/inject:“false”跳過自動注入過程,或修改部分啟動參數
istio.io/config:"{concurrency:6}”#修改工作線程數,默認2
istio.io/proxylmage:"istio/proxyv2new:1.9.0"#修改默認注入鏡像
2.控制面通信
Pilot-agent進程本身創建UDS接收Envoy連接,用于證書更新下發并且與istiod建立證書更新通道
Envoy通過pilot-agent轉發機制與istiod建立長連接,通過xDS協議接收系統下發的-、路由、集群節點等更新信息
3.數據面通信
客戶端請求進入容器網絡,并被iptables規則攔截,經過DNAT后進入EnvoyvirtualOutbound-
virtualOutbound經過監聽過濾器恢復用于原始目標服務,并找到后端處理器處理新連接
后端處理器在配置中指定處理協議,根據協議相關的網絡過濾器處理讀取到的數據
如果為http協議,再經過請求過濾器處理http協議頭部,如路由選擇等功能并創建上游連接池
將修改及編碼后的http消息通過網絡發送到對端Envoy的容器網絡
lptables識別為入流量則進入virtuallnbound端口
類似恢復原始目標后,根據virtuallnbound配置的監聽過濾器找到對應的本地服務器地址,并發起localhost的請求
請求進入本地服務器內進行處理并返回響應
Envoy原理及總體架構-流量攔截
三、Envoy啟動配置及xDS
1.Envoy啟動配置及xDS
2.Envoy啟動配置及xDS-cont' (實操)
分為static resources及dynamic resources兩種配置,兩種方式查看Envoy配置
pilot-agent:訪問Envoy15000端口,指定url獲取:
kubectl exec-it $podname -c istio-proxy -- pilot-agent request GET /config_dump > config.json
istioctl需要根據Istio不同版本下載:
https://github.com/istio/istio/releases/download/1.9.5/istioct1-1.9.5-linux-amd64.tar.gz
istioctl pc listener $podname #輸出LDS
istioctl pc route $podname #輸出RDS
istioctl pc cluster $podname #輸出CDS
istioctl pc endpoint $podname #輸出EDS
istioctl pc secret $podname #輸出SDS
3.Envoy常用部署方式
四、Envoy網絡以及線程模型
主線程:
負責初始化Envoy并讀取解析配置文件
啟動gRPC-,并啟動xDS變化監聽
啟動日志寫入線程,每個目標日志文件有獨立線程負責輸出
啟動admin RESTful監聽,處理運行狀態輸出,prometheus收集等請求
定期將工作線程內監控數據stat進行合并
定期刷新DNS信息,加速域名解析
目標cluster內主機列表健康狀態判斷
worker線程:
通過啟動配置參數concurrency指定,不支持動態調整
啟動virtualoutbound/virtualinbound網絡監聽,每個工作線程都對此監聽端口進每個工作線程都對此監聽端口進行監聽,由內核隨機挑選監聽線程處理新連接
進行連接負載均衡處理后,選擇最終的業務-處理新連接
之后對于此連接的所有處理都在此線程進行,包括下游數據集解碼,路由選擇、上游數據編碼發送等
同時此工作線程還要處理定期觀測信息與主線程同步(通過異步加回調)、線程內配置及集群管理器狀態更新等工作
請求完成后延遲釋放內存,解決本次事件處理中回調所引用對象可以被安全訪問,并在下次處理中安全刪除
調度器通過epoll監控文件事件(網絡)及定時器事件進行排隊任務處理
線程間通信通過post接口發送任務,此任務通過定時器事件激活
線程間數據交換通過post更新TLS,這樣每個線程內代碼都不需要加鎖處理
每個線程的TLS對象本身只保存真實對象的共享指針進行讀操作,減少內存消耗
全局對象更新只發生在主線程,并通過COW方式通知工作線程進行指針修改
每個TLS slot通過allocateSlot分配,在使用前通過set在每個線程中創建一個拷貝并保存
7.在主線程中調用此slot的runOnAllThreads在所有線程中延遲執行回調,回調內更新每個線程內拷貝對象狀態
Envoy需要在運行中支持添加集群并監控每個集群內目標主機列表變化
監控到目標主機健康狀態變化時,需要通知到工作線程內主機可用狀態
當收到節點變化EDS消息時,需要通知到工作線程內新上線、下線主機
Envoy使用前面提到的TLS方式實現集群狀態更新,集群管理器保存一個TLS slot,類型為ThreadLocalClusterManagerimpl當節點變化,,,DNs解析更新,健康狀態變化時,將調用集群管理器的postThreadLocalClusterUpdate方法
此方法將延遲調用所有線程內ThreadLocalClusterManagerlmplslot的回調函數
此函數內將保存新clusterEntry對象的引用
下一輪請求解析時將從頭TLS中獲取到更新后的集群可用狀態
Envoy啟動時創建的Listener與工作線程綁定并啟動監聽(向libevent注冊Read回調onSocketEvent),并進入阻塞運行狀態,直到進程退出
當新連接到達時,內核網絡協議棧調用回調并創建新連接的Socket
通過ConnectionHandler調用監聽過濾器獲得真實訪問目標地址
根據目標地址匹配得到業務-后創建Connection連接對象
之后Connection對象再次向libevent 注冊Read/Write回調onFileEvent,并作為L4層過濾管理器處理onNewConnection,onData數據接收
對于HTTP協議,將繼續經過L7層編解碼處理后向上游發送請求
當請求處理完畢后,將調用deferredDelete刪除請求對象
使用I/0方式發送網絡數據,降低對線程內其他操作的阻塞
根據位置及作用類型,分為:
監聽過濾器(Network::ListenerFilter)
onAccept接收新連接,判斷協議類型,TLS握手,HTTP協議自動識別、提取連接地址信息
L4網絡過濾器
HTTP、Mysql、Dubbo協議處理、元數據交換,四層限流,開發調試支持等 onNewConnection新連接建立,可以決定是否拒絕
onData處理連接數據到達 onWrite處理連接數據發送
L7HTTP過濾器
售留等P請求頭,限流處理,Lua擴展、WASM擴展、開發調試支持、壓縮、元數據交換
decodeHeaders處理HTTP請求頭部 decodeData處理HTTP請求數據
decodeTrailers處理HTTP請求結束位置 encodeHeaders發送請求前編碼頭部 encodeData發送請求前編碼數據 encodeTrailers消息發送前編碼處理
過濾器中可以獲取連接對象并直接發送響應數據,同時可以返回Stoplteration結束過濾器迭代
實際使用過濾器根據Envoy靜態及動態配置注冊,并可以在運行中通過EnvoyFilter動態添加或刪除
lstio項目中Envoy代碼分為兩部分
Envoy原始項目的clone,在
https://github.com/istio/envoy.git
Istio中適配所使用的的插件
https://github.com/istio/proxy.git
編譯時由proxy項目作為入口,自動引用envoy項目
主要框架代碼位于envoy項目包含進程啟動,線程及網絡、主要過濾器框架,觀測數據處理等
啟動入口點位于envoy項目source/exe目錄下
proxy項目中主要提供metadata_exchange,stats等必要WASM擴展
envoy項目中過濾器插件主要位于source/extensions/filters,listener目錄包含監聽過濾器,network目錄包含L4層網絡過濾器,http目錄包含L7層HTTP過濾器
APP發出的請求被iptables攔截,并根據源信息判斷為outbound被DNAT后攔截進入Envoy 15001端口
15001上-通過ORIGINAL_DST獲取原始目標地址(服務的clusterlp),匹配業務-(不真正監聽網絡)地址并傳遞新建下游連接
下游連接過濾器判斷TLS,ALPN(業務協議名稱),HTTP版本后匹配到L4層http_connection_manager網絡過濾器
http_connection_manager使用http codec解碼http協議header/body/tailer等并觸發回調函數
http header/body處理回調中將調用L7層HTTP過濾器處理(可修改http原始請求等)最后調用Router過濾器
Router過濾器負責根據配置中路由部分及請求內url等進行匹配并找到目標cluster
根據cluster的負載均衡策略及當前可用POD實例信息,選擇最適合的目標POD地址,并創建此目標地址的連接池
根據連接池配置的最大可用連接數及允許的最大等待連接數等信息將下游請求與上游連接進行關聯
當連接準備好后對下游請求使用codec進行HTTP編碼,并發送到上游連接的L4層網絡過濾器
上游連接的L4層網絡過濾器使用metadata exchange傳輸本Envoy內保存的與App相關的元數據信息,包括POD名稱、用戶空間、cluster id等信息,之后將待發送請求通過Socket發送到網絡,經過iptables時判斷發送者為Envoy則不再攔截
目標POD收到從網絡進入的流量,通過iptables攔截后判斷為inbound并DNAT處理后,進入Envoy的15006端口
由于inbound方向流量的目標地址一定為本POD地址,無需再提取后轉到不同業務-,因此virtualinbound負責TLS、ALPN及HTTP協議版本判斷
http_connection manager網絡過濾器 htpcottmetadata exchate首先解析請求中包含的源POD元數據信息,并同時發送回本Envoy代理POD的元數據信息之后進入L4層 http_connection_manager網絡過濾器
L7層處理流程同outbound方向,區別為inbound通過Router匹配后的目標cluster所指向的上游地址為0.0.1
之后創建與本POD內業務容器的服務端口的Socket連接并完成請求發送
由于請求方向在建立時會保存下游與上游連接的雙向對應關系,因此Response匹配的對上游進行L7層過濾器解碼、通過Router關聯關系找到下游并編碼發送HTTP請求
以上所提到的EnvoyL4層網絡讀取及數據發送為全異步讀寫模式,采用網絡事件觸發機制完成響應數據的接收和發送
由于Router部分請求處理方向需要進行更多路由選擇計算及負載均衡計算工作,因此通常outbound方向處理較復雜,CPU消耗比inbound更高
四、Envoy問題分析方法
查看istio配置
查看listener:istioct pc listener backend-welink-649fdfd55d-2xhzw--port 8123 -o json
查看endpoint:istioctl pc endpoint backend-welink-649fdfd55d-2xhzw
打開運行期日志
Accesslog:格式
https://www.envoyproxy.io/docs/envoy/latest/configuration/observability/access log/usage
調試日志:pilot-agent request POST /logging?connection=trace
抓包
進入pod容器網絡空間執行tcpdump-ianyport(15001 or 8080)’-w fortio.cap
壓測工具
fortio load -qps 3000-c 128-t 60s --keepalive=false http://backend-welink:8123
perfrecord-F 2000-g-p $pid;perf script -i perf.data > out.perf; stackcollapse-perf.pl out.perf > out.folded; flamegraph.pl out.folded > cpu.svg
鏡像修改
編譯pilot-agentenvoy二進制后替換現有envoy鏡像并配置到自定義deployment的image中并添加annotation: sidecar.istioio/inject:“false”跳過自動注入邏輯覆蓋 istio.io/proxylmage:"istio/proxyv2new:1.9.0"#修改默認注入鏡像 docker save -o proxyv2.tar istio/proxyv2new:1.9.0 docker load -i proxyv2.tar·Dockerfile:
From istio/proxyv2:1.9.0
COPYenvoy /usr/local/bin/envoy
COPY pilot-agent /usr/local/bin/pilot-agent
五、Lstio數據面發展趨勢
現狀問題:
引入Sidecar模式,導致端到端時延增加、并隨著集群規模增加導致系統資源消耗上升,對大規模Istio集群的實際使用造成影響
運維難度增加,透明代理模式無法針對不同業務本身的特點定制監控能力,同時只能從業務容器外面收集應用的運行狀態
演進方式:
從Envoy自身1/0及線程模型、容器網絡協議棧優化提升端到端性能,降低tp90網絡時延
通過運行時拉取集群依賴服務及POD實例配置信息,同時考慮配置信息共享的方式,降低每Envoy資源消耗
增加更多運維監控維度及探測點,收集更全面的觀測信息同時支持對出現問題的Envoy進行旁路處理
六、總結
名稱
簡介
Envoy
基于C++11.14的高性能服務網格數據面代理
XDS
Envoy與上層控制面如istiod使用的基于gRPC的應用層協議,用于傳輸配置變更
自動注入及流量攔截
POD創建時,由istiod進行自動修改deplovment并將istio-init,istio-proxy容器注入到新創建POD內:當發生調用時,iptables規則將自動攔截出入流量進入Envov代理
線程模型
Envov采用每個工作線程獨立處理網絡及定時器事件,線程間無數據共享,提升性能
過濾器架構
Envov采用可擴展插件架構實現監聽過濾器、L4網絡過濾器、L7 HTTP過波器:同時支持基于L4/L7 WASM及L7 Lua過濾器的二次擴展
參考鏈接
相關內容的華為云官網鏈接:
https://support.huaweicloud.com/usermanual-cce/cce 01 0006.html
詳細ASM官網資料:
https://support.huaweicloud.com/istiol
Istio官方文檔:
https://istio.io/latest/docs/
envoy官方文檔:
https://www.envoyproxy.io/docs/envoy/latest/
本文整理自華為云社區【內容共創】活動第14期
https://bbs.huaweicloud.com/blogs/336904
任務23.
華為云云原生鉆石課程13:Istio數據面架構(Envoy)深度解析
上云必讀 云原生 Kubernetes
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。