摘要:,托管于騰訊云容器平臺(tái)容器編排工具。適配我們目前的服務(wù)部署在騰訊云托管,節(jié)點(diǎn)使用核的網(wǎng)絡(luò)增強(qiáng)型機(jī)器,所有的后端服務(wù)都以部署,集群外部署高可用支持集群內(nèi)服務(wù)發(fā)現(xiàn),數(shù)據(jù)庫(kù)以為主,消息隊(duì)列采用。
距離2017年的見(jiàn)聞技術(shù)架構(gòu)調(diào)整接近2年,隨著業(yè)務(wù)線的發(fā)展,見(jiàn)聞技術(shù)部的項(xiàng)目數(shù)量、項(xiàng)目架構(gòu)類型、基礎(chǔ)設(shè)施規(guī)模、服務(wù)變更頻率都在不斷地增長(zhǎng),帶給SRE的挑戰(zhàn)是如何能更快地助力于開(kāi)發(fā)人員更快更穩(wěn)定地部署服務(wù),保障線上服務(wù)的穩(wěn)定。
我們的后端開(kāi)發(fā)團(tuán)隊(duì)仍然以Golang為主,不同業(yè)務(wù)線的技術(shù)選型不盡相同,同時(shí)存在Python,Java服務(wù),這就需要SRE提供更易接入的微服務(wù)基礎(chǔ)組件,常見(jiàn)的方案就是為每種語(yǔ)言提供適配的微服務(wù)基礎(chǔ)組件,但痛點(diǎn)是基礎(chǔ)組件更新維護(hù)的成本較高。
為了解決痛點(diǎn),我們將目光放到服務(wù)網(wǎng)格,它能利用基礎(chǔ)設(shè)施下沉解決多語(yǔ)言基礎(chǔ)庫(kù)依賴問(wèn)題,不同的語(yǔ)言不需要再引入各種不同的服務(wù)發(fā)現(xiàn)、監(jiān)控等依賴庫(kù),只需簡(jiǎn)單的配置并運(yùn)行在給定的環(huán)境下,就能享有以上功能,同時(shí)網(wǎng)絡(luò)作為最重要的通信組件,可以基于它實(shí)現(xiàn)很多復(fù)雜的功能,譬如根據(jù)不同可用區(qū)進(jìn)行的智能路由、服務(wù)熔斷降級(jí)等。
為此,我們調(diào)研了一些服務(wù)網(wǎng)格方案,包括Istio、Linkerd,基于我們的當(dāng)前的后端架構(gòu)特點(diǎn):
服務(wù)通信協(xié)議主要基于gRPC、HTTP
基于Kubernetes的Docker部署
擁抱開(kāi)源,使用了Prometheus、Grafana作為監(jiān)控,Zipkin作為鏈路追蹤等
對(duì)比下來(lái),Istio擁有更多活躍的開(kāi)源貢獻(xiàn)者,迭代速度快,以及Istio架構(gòu)可行性討論,我們選擇Istio作為實(shí)踐方案。
架構(gòu)這張圖介紹了見(jiàn)聞典型的服務(wù)網(wǎng)格架構(gòu),左半圖介紹了一個(gè)用戶請(qǐng)求是如何處理,右半圖介紹運(yùn)維系統(tǒng)是如何監(jiān)控服務(wù),若無(wú)特殊說(shuō)明,服務(wù)都是部署在騰訊云托管Kubernetes。
組件一覽
Go(1.11)
后端語(yǔ)言。
Docker(17.12.1-ce)
容器技術(shù)。
Kubernetes(1.10.5,托管于騰訊云容器平臺(tái))
容器編排工具。
Istio(1.0.0)
服務(wù)網(wǎng)格開(kāi)源方案,支持與Kubernetes集成。
Ingress, Proxy(Istio 1.0.0)
服務(wù)流量轉(zhuǎn)發(fā)、智能代理,基于Envoy實(shí)現(xiàn),Istio二次開(kāi)發(fā)Proxy。
Pilot Discovery(Istio 1.0.5)
負(fù)責(zé)服務(wù)發(fā)現(xiàn),通過(guò)監(jiān)聽(tīng)Kubernetes中Service、Pod等資源維護(hù)服務(wù)映射表。
Mixer Policy(Istio 1.0.5)
管理服務(wù)之間訪問(wèn)權(quán)限,提供gRPC形式的Check接口。
Mixer Telemetry(Istio 1.0.5)
負(fù)責(zé)接收服務(wù)指標(biāo)數(shù)據(jù),提供gRPC形式的Report接口。
Citadel
負(fù)責(zé)管理代理證書。
Dashboard
基于Kubernetes Dashboard二次開(kāi)發(fā)的Istio Dashboard,負(fù)責(zé)管理Istio服務(wù)發(fā)布,配置變更等。
Grafana
負(fù)責(zé)監(jiān)控?cái)?shù)據(jù)可視化。
Prometheus
時(shí)序數(shù)據(jù)庫(kù),常用于監(jiān)控系統(tǒng)。
Jaeger
負(fù)責(zé)服務(wù)鏈路追蹤,組件包括collector、Jaeger UI。
Cassandra
分布式NoSQL數(shù)據(jù)庫(kù),用于Jaeger指標(biāo)數(shù)據(jù)存儲(chǔ)。
我們先從用戶請(qǐng)求端開(kāi)始,用戶的請(qǐng)求通過(guò)Tencent 4層LB轉(zhuǎn)發(fā)到基于Envoy的Istio Ingress,Ingress根據(jù)配置將請(qǐng)求路由到Service A所在的Pod
Service A所在Pod接收Ingress請(qǐng)求
訪問(wèn)Service A的請(qǐng)求會(huì)先到達(dá)Proxy再由它轉(zhuǎn)發(fā)到Service A進(jìn)程
Service A向Service B發(fā)出的請(qǐng)求被iptables路由到Proxy(下文會(huì)提到iptables的初始化)
Proxy進(jìn)程發(fā)起對(duì)Service B所在Pod的請(qǐng)求
Proxy進(jìn)程同步請(qǐng)求Mixer Policy服務(wù),檢查是否允許訪問(wèn)Service B,檢查通過(guò),開(kāi)始請(qǐng)求
Proxy進(jìn)程記錄請(qǐng)求的指標(biāo)(QPS,Latency,Status Code分布等),異步并批量上報(bào)到Mixer Telemetry服務(wù),這里是客戶端指標(biāo)。
Service B所在Pod接收請(qǐng)求
Service B Proxy接收請(qǐng)求并路由到Service B所在進(jìn)程
Proxy進(jìn)程記錄請(qǐng)求的指標(biāo)(QPS,Latency,Status Code分布等),異步并批量上報(bào)到Mixer Telemetry服務(wù),這里是服務(wù)端指標(biāo)。
Service B進(jìn)程處理完請(qǐng)求并返回
數(shù)據(jù)原路返回到用戶端
以上的流程可以觀察到,服務(wù)之間通信完全依靠Proxy進(jìn)程完成,Proxy進(jìn)程接管同一個(gè)Pod中服務(wù)的出入流量,完成請(qǐng)求的路由。
架構(gòu)可行性通過(guò)架構(gòu)圖以及以上流程,我們拆分出以下關(guān)鍵組件,觀察其性能、可用性、拓展性。
Istio Ingress高性能,可拓展
Istio Ingress用來(lái)處理用戶入流量,使用Envoy實(shí)現(xiàn),轉(zhuǎn)發(fā)性能高。掛載在負(fù)載均衡后,通過(guò)增加實(shí)例實(shí)現(xiàn)可拓展。
Istio Proxy隨應(yīng)用部署,輕微性能損耗,可隨應(yīng)用數(shù)量拓展
Istio Proxy以Sidecar形式隨應(yīng)用一起部署,增加2次流量轉(zhuǎn)發(fā),存在性能損耗。
性能: 4核8G服務(wù)器,上面運(yùn)行Proxy服務(wù)和API服務(wù),API服務(wù)只返回ok字樣。(此測(cè)試只測(cè)試極限QPS)
多帶帶測(cè)試API服務(wù)的QPS在59k+,平均延時(shí)在1.68ms,CPU占用4核。
通過(guò)代理訪問(wèn)的QPS7k+,平均延時(shí)14.97ms,代理CPU占用2核,API服務(wù)CPU占用2核。
CPU消耗以及轉(zhuǎn)發(fā)消耗降低了QPS,增加了延時(shí),通過(guò)增加機(jī)器核數(shù)并增加服務(wù)部署數(shù)量緩解該問(wèn)題,經(jīng)過(guò)測(cè)試環(huán)境測(cè)試,延時(shí)可以接受。
可用性:基于Envoy,我們認(rèn)為Envoy的可用性高于應(yīng)用。依賴Pilot Discovery進(jìn)行服務(wù)路由,可用性受Pilot Discovery影響。
拓展性:Sidecar形式,隨應(yīng)用數(shù)拓展
Istio Policy服務(wù)可拓展,但同步調(diào)用存在風(fēng)險(xiǎn)
Istio Policy需要在服務(wù)調(diào)用前訪問(wèn),是同步請(qǐng)求,會(huì)增加服務(wù)調(diào)用延時(shí),通過(guò)拓展服務(wù)數(shù)量增加處理能力。屬于可選服務(wù),見(jiàn)聞生產(chǎn)未使用該組件。
性能: 未測(cè)試
可用性:若開(kāi)啟Policy,必須保證Policy高可用,否則正常服務(wù)將不可用
拓展性:增加實(shí)例數(shù)量進(jìn)行拓展
Istio Telemetry監(jiān)控收集服務(wù)
性能: 從監(jiān)控上觀察Report 5000qps,使用25核,響應(yīng)時(shí)間p99在72ms。異步調(diào)用不影響應(yīng)用的響應(yīng)時(shí)間。
可用性:Telemetry不影響服務(wù)可用性
拓展性:增加實(shí)例數(shù)量進(jìn)行拓展
Pilot Discovery
性能: 服務(wù)發(fā)現(xiàn)組件1.0.5版本經(jīng)過(guò)監(jiān)控觀察,300個(gè)Service,1000個(gè)Pod,服務(wù)變更次數(shù)1天100次,平均CPU消耗在0.01核,內(nèi)存占用在1G以內(nèi)。
可用性: 在服務(wù)更新時(shí)需要保證可用,否則新創(chuàng)建的Pod無(wú)法獲取最新路由規(guī)則,對(duì)于已運(yùn)行Pod由于Proxy存在路由緩存不受Pilot Discovery關(guān)閉的影響。
拓展性:增加實(shí)例數(shù)量可以增加處理量。
可以看到各個(gè)組件的可用性、拓展性都有相應(yīng)的策略達(dá)到保障,我們認(rèn)為Istio是具有可實(shí)施性的。
Istio流量控制背后 Pilot Discovery: Istio的交通大腦Pilot Discovery負(fù)責(zé)Istio服務(wù)發(fā)現(xiàn),支持在Kubernetes里部署,它讀取K8S資源配置,并生成Proxy可用的路由表。以下面的Service A服務(wù)為例,介紹Istio如何進(jìn)行精細(xì)路由。
Discovery與對(duì)應(yīng)K8S集群的API server相連,拉取全量資源信息,并使用Watch方法對(duì)增量變更進(jìn)行同步。
根據(jù)Service A的配置,生成對(duì)應(yīng)Service A的路由配置,通過(guò)gRPC形式的ADS接口提供給Proxy。
Proxy同步到最新配置,熱更新后配置生效。
要知道如果在Istio訪問(wèn)一個(gè)服務(wù),必須得聲明K8S Service。
Istio通過(guò)K8S CRD拓展K8S已有的服務(wù)訪問(wèn)能力,我們列舉網(wǎng)絡(luò)相關(guān)常用的配置:
Gateway
控制Istio Ingress的路由轉(zhuǎn)發(fā)及TLS證書綁定。
VirtualService
服務(wù)流量控制,實(shí)現(xiàn)如A/B測(cè)試、錯(cuò)誤注入、服務(wù)保護(hù)等。
DestinationRule
用于目標(biāo)服務(wù)的版本管理,根據(jù)Pod的Label區(qū)分目標(biāo)服務(wù)的版本,聯(lián)合VirtualService進(jìn)行流量控制。
以下舉個(gè)例子介紹如何利用它們配置同樣大小流量到服務(wù)的不同版本,
# serviceA.yaml kind: Service apiVersion: v1 metadata: name: serviceA labels: app: serviceA spec: ports: - name: http-8080 protocol: TCP port: 8080 targetPort: 8080 selector: app: serviceA type: ClusterIP # virtualServiceA.yaml apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: serviceA spec: hosts: - serviceA http: - route: - destination: host: serviceA subset: v1 - route: - destination: host: serviceA subset: v2 --- # destinationRule apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: serviceA spec: host: serviceA subsets: - labels: version: v1 name: v1 - labels: version: v2 name: v2
以上實(shí)現(xiàn)了Istio服務(wù)調(diào)用serviceA時(shí),會(huì)隨機(jī)地50%概率到serviceA的v1版本,50%概率到serviceA的v2版本。
可以看到,VirtualService通過(guò)hosts關(guān)聯(lián)serviceA,在http區(qū)域有兩個(gè)route,分別是subset v1, subset v2,v1,v2依賴DestinationRule來(lái)定義,同樣用host來(lái)標(biāo)注該DestinationRule控制哪個(gè)host的訪問(wèn),以及通過(guò)pod label中version來(lái)劃分不同版本。
流量控制方面,Istio有相當(dāng)豐富的功能支持,同時(shí)也帶來(lái)了相當(dāng)?shù)膹?fù)雜度,建議用戶根據(jù)日常的使用頻率在后臺(tái)實(shí)現(xiàn)相應(yīng)的前端控制臺(tái),利用自動(dòng)化來(lái)完成流量控制。
Proxy工作機(jī)制自動(dòng)注入
在K8S 1.9之后的版本,Istio利用K8S提供的MutatingAdmissionWebhook在K8S創(chuàng)建Pod前回調(diào)Istio提供的istio-sidecar-injector動(dòng)態(tài)修改Pod配置,添加以Sidecar形式運(yùn)行的Proxy。這里開(kāi)啟自動(dòng)注入有兩個(gè)維度,一是namespace,namespace需要添加istio-injection : enabled標(biāo)簽,這樣實(shí)現(xiàn)該namespace下的所有Pod自動(dòng)注入Proxy;二是deployment可以設(shè)置annotation關(guān)閉自動(dòng)注入。
如果K8S版本不夠,可以利用命令行工具修改Deployment的配置。
接管Pod流量
Service A所在Pod至少運(yùn)行Service A應(yīng)用容器以及用于代理的Envoy容器,創(chuàng)建Pod時(shí)proxy-init命令負(fù)責(zé)獲取Pod監(jiān)聽(tīng)的端口和具體協(xié)議,以此初始化網(wǎng)絡(luò),利用iptables將容器網(wǎng)絡(luò)出入流量都轉(zhuǎn)發(fā)到Proxy監(jiān)聽(tīng)的localhost端口。
若Service A的Pod聲明servicePort為8080:HTTP,最終Proxy將會(huì)接收8080端口的Pod入流量和全部的Pod出流量。
服務(wù)發(fā)現(xiàn)
Proxy基于Envoy,與Pilot Discovery連接,動(dòng)態(tài)同步Kubernetes集群中所有的服務(wù)信息:服務(wù)與Pod IP、端口之間的映射表,通過(guò)路由信息實(shí)現(xiàn)智能路由,從而使服務(wù)發(fā)現(xiàn)從業(yè)務(wù)代碼中剝離。
鏈路追蹤
Proxy支持設(shè)置Zipkin URL,異步上報(bào)鏈路追蹤數(shù)據(jù)。
服務(wù)質(zhì)量監(jiān)控
Proxy將屬性包上報(bào)給Telemetry服務(wù),Telemetry根據(jù)用戶的配置生成指標(biāo)數(shù)據(jù)并由Prometheus收集。
適配Istio我們目前的服務(wù)部署在騰訊云托管Kubernetes,節(jié)點(diǎn)使用16核32G的網(wǎng)絡(luò)增強(qiáng)型機(jī)器,所有的后端服務(wù)都以Docker部署,K8S集群外部署高可用ETCD支持集群內(nèi)服務(wù)發(fā)現(xiàn),數(shù)據(jù)庫(kù)以MySQL、Cassandra、MongoDB為主,消息隊(duì)列采用Kafka、NSQ。在應(yīng)用Istio的過(guò)程中,我們對(duì)基礎(chǔ)庫(kù)進(jìn)行了修改,刪減了Istio已提供的功能并完成了對(duì)Istio的適配。
前情提要見(jiàn)聞舊后端服務(wù)架構(gòu),所有Golang服務(wù)以打包成Docker鏡像,以"gRPC"協(xié)議通信。
見(jiàn)聞Golang后端使用go-micro框架,一個(gè)支持多插件的Golang微服務(wù)框架,作者將組件分成transport,server,client,registry,codec等,通過(guò)組合不同類型的組件非常靈活地配置微服務(wù)技術(shù)棧。對(duì)于有定制需求的微服務(wù)架構(gòu),是值得推薦的選擇。
通信協(xié)議作為服務(wù)互通的基石,Istio對(duì)gRPC和HTTP非常友好,根據(jù)協(xié)議Istio能解析HTTP頭中的信息,支持提取指標(biāo)以供分析。go-micro只是利用HTTP和gRPC作為通信協(xié)議,但是協(xié)議的解析邏輯是協(xié)議無(wú)關(guān)的,所以可以說(shuō)它只是用了這些通信協(xié)議的外殼,傳輸?shù)膱?bào)文內(nèi)容是"micro方言",這就導(dǎo)致了Golang暴露的服務(wù)無(wú)法被其它語(yǔ)言其它框架調(diào)用。為了將協(xié)議能在多語(yǔ)言中完全統(tǒng)一,也為了更好地使用Istio的監(jiān)控統(tǒng)計(jì)功能,這個(gè)時(shí)候我們開(kāi)始對(duì)go-micro的存留有一些新的思考,我們是否還需要go-micro?經(jīng)過(guò)近2年的生產(chǎn)實(shí)踐,我們是不是可以更精簡(jiǎn)我們的框架?
經(jīng)過(guò)這些思考過(guò)后,我們的決定是去go-micro框架,擁抱更輕量級(jí)的基礎(chǔ)框架,這個(gè)框架只要支持:
gRPC
純?cè)纯?/p>
Istio
支持Istio的基礎(chǔ)功能,譬如一些HTTP header轉(zhuǎn)發(fā)等
改動(dòng)盡量小
我們已經(jīng)存在上百個(gè)Golang項(xiàng)目,避免改動(dòng)Golang項(xiàng)目代碼,將改動(dòng)放到基礎(chǔ)庫(kù)為佳
go-micro通過(guò)定義自制protobuf插件的方式在stub代碼中集成框架功能,經(jīng)過(guò)對(duì)邏輯的梳理,我們決定復(fù)寫protobuf插件,生成兼容micro的stub代碼,通過(guò)對(duì)micro接口的向后兼容,開(kāi)發(fā)人員不需要修改代碼,只需要在CI階段運(yùn)行protoc即時(shí)生成新版代碼。
詳情可見(jiàn)再見(jiàn),micro
運(yùn)維流程右半圖描述運(yùn)維人員如何利用運(yùn)維后臺(tái)運(yùn)維Kubernetes集群,Istio的運(yùn)維必須有自動(dòng)化的工具來(lái)減少人工配置帶來(lái)的錯(cuò)誤,見(jiàn)聞的舊運(yùn)維后臺(tái)基于騰訊云容器平臺(tái)暴露的開(kāi)放API,在引入Istio后,功能依賴于更細(xì)節(jié)的label以及CRD(Custom Resource Definition),于是得依托更細(xì)粒度的Kubernetes API,新的后臺(tái)需要能完成基本的Kubernetes運(yùn)維,而且結(jié)合Istio的實(shí)際進(jìn)行日常更新,經(jīng)過(guò)選型,見(jiàn)聞基于Kubernetes Dashboard二次開(kāi)發(fā)了Istio部分的一些功能(APP部署、更新,Istio配置更新等),利用Istio Dashboard實(shí)現(xiàn)APP創(chuàng)建、部署接口,并由此重構(gòu)原有的運(yùn)維后臺(tái)。
最終,SRE提供兩個(gè)后臺(tái),精細(xì)控制的Istio Dashboard;提供給開(kāi)發(fā)人員日常更新使用的簡(jiǎn)化版后臺(tái)。
服務(wù)發(fā)布日常最重要、最高頻的功能,服務(wù)版本變更。
服務(wù)創(chuàng)建服務(wù)創(chuàng)建包括對(duì)老服務(wù)的改造,一個(gè)K8S服務(wù)要經(jīng)過(guò)一些配置上的更新才能成為Istio APP。一個(gè)Kubernetes服務(wù)需要滿足以下要求來(lái)獲得Istio的功能支持:
Service資源聲明服務(wù)監(jiān)聽(tīng)的端口號(hào)以及協(xié)議
這里的服務(wù)端口聲明中name字段值需要以協(xié)議名為起始值,譬如grpc、http、tcp、udp等,istio識(shí)別前綴,用于初始化Proxy,譬如grpc-svc,http-svc,不正確的端口命名會(huì)引起Proxy的異常行為,以及監(jiān)控服務(wù)無(wú)法捕獲該協(xié)議下的指標(biāo)。
服務(wù)探活接口
每個(gè)后端服務(wù)提供一個(gè)HTTP探活接口,這樣服務(wù)啟動(dòng)時(shí),不至于讓其它服務(wù)訪問(wèn)到未就緒的狀態(tài)。
對(duì)于HTTP探活接口的定義包括Proxy以及APP是否初始化完成,見(jiàn)聞的實(shí)踐是在基礎(chǔ)鏡像中打入一個(gè)探活程序:
檢測(cè)Proxy是否初始化
通過(guò)Proxy的配置同步時(shí)間與Pilot Discovery的配置更新時(shí)間對(duì)比,相同時(shí)認(rèn)為其就緒。
APP自定義接口
APP可以在指定端口提供就緒API。
# serviceA.yaml kind: Service apiVersion: v1 metadata: name: serviceA namespace: default labels: app: serviceA spec: ports: - name: grpc protocol: TCP port: 10088 targetPort: 10088 selector: app: serviceA type: ClusterIP
Deployment資源要求
有必要的兩個(gè)label:app和version,明確定義流量控制中的目標(biāo)服務(wù)。
可以看例子中deployment的app為serviceA,version為v1。
聲明對(duì)外服務(wù)的端口,要求Proxy對(duì)指定端口入流量的接管。
例子中ports聲明了10088端口。
# deploymentA.yaml kind: Deployment apiVersion: extensions/v1beta1 metadata: name: serviceA-v1 labels: app: serviceA version: v1 spec: replicas: 1 selector: matchLabels: app: serviceA version: v1 template: metadata: labels: app: serviceA version: v1 spec: containers: - name: serviceA image: "some-image" ports: - containerPort: 10088 protocol: TCP resources: requests: cpu: 1000m livenessProbe: httpGet: path: /health port: 54321 scheme: HTTP initialDelaySeconds: 1 timeoutSeconds: 2 periodSeconds: 5 successThreshold: 1 failureThreshold: 3 terminationMessagePath: /dev/termination-log terminationMessagePolicy: File imagePullPolicy: Always securityContext: privileged: false restartPolicy: Always terminationGracePeriodSeconds: 30 dnsPolicy: ClusterFirst
符合以上要求,服務(wù)能正確接入Istio系統(tǒng)并獲得服務(wù)發(fā)現(xiàn)和監(jiān)控的能力。
服務(wù)更新Istio提供流量控制,給運(yùn)維帶來(lái)方便的A/B測(cè)試,用于根據(jù)指定規(guī)則遷移流量。
見(jiàn)聞的服務(wù)更新依靠Istio流量遷移功能,發(fā)布服務(wù)的新版本,并將流量通過(guò)Istio規(guī)則遷移到新版本,實(shí)際細(xì)節(jié)如下:
更新流量控制將流量指向已有版本
以下實(shí)例利用VirtualService將ServiceA的服務(wù)流量全部指向已存在的v1版本
# virtualService apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: serviceA spec: hosts:
http: - route: - destination: host: serviceA subset: v1 --- # destinationRule apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: serviceA spec: host: serviceA subsets: - labels: version: v1 name: v1 ```
部署新版本的Deployment
查找符合app label的deployment,運(yùn)維人員基于該deployment創(chuàng)建v2版本的deployment,并向destinationRule中增加v2版本。
# destinationRule apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: serviceA spec: host: serviceA subsets: - labels: version: v1 name: v1 - labels: version: v2 name: v2
更新流量控制將流量指向新版本
以下實(shí)例利用VirtualService將ServiceA的服務(wù)流量全部指向v2版本
# virtualService apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: serviceA spec: hosts: - serviceA http: - route: - destination: host: serviceA subset: v2
下線v1版本的deployment,刪除DestinationRule中的v1
使用Istio Dashboard來(lái)實(shí)現(xiàn)上述流程
為什么使用Istio Ingress作為新的Ingress方案?
過(guò)去我們使用騰訊云托管的Kubernetes Ingress,為了對(duì)Ingress流量控制而引入Istio Ingress。我們之前提到Istio Ingress是基于Envoy,它讀取Istio控制的配置進(jìn)行路由,與其它內(nèi)部服務(wù)一樣方便地接入Istio所有功能。
除了VirtualService和DestinationRule,Istio定義了Gateway來(lái)控制實(shí)例支持的Host和證書。具體的流程是:
創(chuàng)建Istio Ingress提供的Deployment和Service
創(chuàng)建Deployment ingressgateway時(shí),以ConfigMap的形式掛載Ingress需要的證書。
配置Gateway
配置Ingress接收具體域名(如wallstreetcn.com)的流量,以及對(duì)應(yīng)的TLS證書位置,這里的證書路徑已經(jīng)掛在到Ingress的Deployment上。以下是一個(gè)典型的Gateway配置。
apiVersion: networking.istio.io/v1alpha3 kind: Gateway metadata: name: wallstreetcn-com namespace: istio-system spec: selector: istio: ingressgateway servers: - hosts: - wallstreetcn.com port: name: http number: 80 protocol: HTTP - hosts: - wallstreetcn.com port: name: https number: 443 protocol: HTTPS tls: mode: SIMPLE privateKey: /etc/istio/ingressgateway-certs/tls.key serverCertificate: /etc/istio/ingressgateway-certs/tls.crt
配置完成后,再配合VirtualService的路由控制,控制Ingress的反向代理到default命名空間下的gateway服務(wù)80端口,如下所示:
apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: wallstreetcn-com namespace: istio-system spec: gateways: - wallstreetcn-com hosts: - wallstreetcn.com http: - route: - destination: host: gateway.default.svc.cluster.local port: number: 80監(jiān)控指標(biāo)
Istio支持Prometheus拉取集群指標(biāo),并提供Grafana看板展示。這里建議初期使用Istio自帶的Grafana看板配置,并且注意Kubernetes主機(jī)的類型劃分,Prometheus服務(wù)適合放在內(nèi)存型機(jī)器。可以與Dashboard集成,在發(fā)布服務(wù)過(guò)程中即時(shí)查看指標(biāo)。
服務(wù)質(zhì)量Istio自帶一些默認(rèn)的Grafana面板,統(tǒng)計(jì)所有可以被訪問(wèn)的HTTP/gRPC服務(wù)的返回碼以及延時(shí)情況。
對(duì)于返回碼,認(rèn)為5xx為錯(cuò)誤,并在面板上使用label_join((sum(rate(istio_requests_total{reporter="destination", response_code!~"5.*"}[1m])) by (destination_workload, destination_workload_namespace) / sum(rate(istio_requests_total{reporter="destination"}[1m])) by (destination_workload, destination_workload_namespace)), "destination_workload_var", ".", "destination_workload", "destination_workload_namespace")計(jì)算服務(wù)錯(cuò)誤率。
對(duì)于延時(shí)情況采用histogram_quantile獲取多維度p50、p90、p95、p99的延時(shí)分布。
鏈路追蹤之前提到Proxy由Envoy實(shí)現(xiàn),Envoy支持設(shè)置Zipkin上報(bào)API,Proxy在收發(fā)請(qǐng)求時(shí)將鏈路指標(biāo)上報(bào)到Zipkin,為了實(shí)現(xiàn)鏈路追蹤,Proxy在流量轉(zhuǎn)發(fā)中解析協(xié)議中的HTTP或gRPC請(qǐng)求頭,找出其中的追蹤頭,組裝成指標(biāo)。
所以應(yīng)用端需要在收到調(diào)用方請(qǐng)求時(shí)解析出請(qǐng)求頭,并持續(xù)攜帶該請(qǐng)求頭向后傳遞。
由于見(jiàn)聞在Ingress之后映射一個(gè)HTTP gateway,請(qǐng)求從Ingress轉(zhuǎn)發(fā)到HTTP gateway,再發(fā)送到后續(xù)的gRPC服務(wù),所以HTTP gateway有段代碼生成gRPC請(qǐng)求頭。
import ( "github.com/labstack/echo" gmeta "google.golang.org/grpc/metadata" ) // Create a gRPC context from Echo. func NewContextFromEcho(ec echo.Context) context.Context { md := gmeta.MD{} for _, header := range []string{ "x-request-id", "x-b3-traceid", "x-b3-spanid", "x-b3-parentspanid", "x-b3-sampled", "x-b3-flags", "x-ot-span-context", } { md.Set(header, ec.Request().Header.Get(header)) } md.Set("x-b3-parentspanid", ec.Request().Header.Get("x-b3-spanid")) return gmeta.NewOutgoingContext(context.Background(), md) }
在后續(xù)的gRPC服務(wù)調(diào)用中使用該Context,至于gRPC服務(wù)之間的調(diào)用,我們發(fā)現(xiàn)會(huì)自動(dòng)將context傳遞到下一個(gè)服務(wù),所以沒(méi)有做類似處理。
這里追蹤的數(shù)據(jù)如果全量捕獲將會(huì)是非常大的,并且對(duì)于監(jiān)控來(lái)說(shuō)也不必要,所以可以設(shè)置抽樣率,Istio提供ConfigMap中設(shè)置抽樣率,一般來(lái)說(shuō)設(shè)置成1%即可。
實(shí)踐中的寶貴經(jīng)驗(yàn)在Istio實(shí)踐過(guò)程中,有哪些需要注意的問(wèn)題。
API server的強(qiáng)依賴,單點(diǎn)故障
Istio對(duì)Kubernetes的API有很強(qiáng)的依賴,諸如流量控制(Kubernetes資源)、集群監(jiān)控(Prometheues通過(guò)Kubernetes服務(wù)發(fā)現(xiàn)查找Pod)、服務(wù)權(quán)限控制(Mixer Policy)。所以需要保障API server的高可用,我們?cè)龅絇olicy組件瘋狂請(qǐng)求Kubernetes API server使API server無(wú)法服務(wù),從而導(dǎo)致服務(wù)發(fā)現(xiàn)等服務(wù)無(wú)法更新配置。
* 為避免這種請(qǐng)求,建議使用者了解與API server直接通信組件的原理,并盡量減少直接通信的組件數(shù)量,增加必要的Rate limit。 * 盡量將與API server通信的服務(wù)置于可以隨時(shí)關(guān)閉的環(huán)境,這是考慮如果部署在同一Kubernetes集群,如果API server掛掉,無(wú)法關(guān)閉這些有問(wèn)題的服務(wù),導(dǎo)致死鎖(又想恢復(fù)API server,又要依靠API server關(guān)閉服務(wù))
服務(wù)配置的自動(dòng)化
服務(wù)配置是Istio部署后的重頭戲,避免使用手動(dòng)方式更改配置,使用代碼更新配置,將常用的幾個(gè)配置更新操作做到運(yùn)維后臺(tái),相信手動(dòng)一定會(huì)犯錯(cuò)的事實(shí)。
關(guān)于Pilot Discovery
Pilot Discovery 1.0.0版本有很大的性能問(wèn)題,1.0.4有很大的性能提升,但引入了一個(gè)新bug,所以請(qǐng)使用1.0.5及以上的版本,該版本在見(jiàn)聞的平均CPU負(fù)載從10核降到了0.5核,大大降低了Proxy同步配置的延時(shí)。
關(guān)于Mixer Policy 1.0.0
這個(gè)組件曾導(dǎo)致API server負(fù)載過(guò)高(很高的list pods請(qǐng)求),所以我們暫時(shí)束之高閣,慎用。
性能調(diào)優(yōu)
在使用Proxy、Telemetry時(shí),默認(rèn)它們會(huì)打印訪問(wèn)日志,我們選擇在生產(chǎn)上關(guān)閉該日志。
時(shí)刻觀察Istio社區(qū)的最新版本,查看新版本各個(gè)組件的性能優(yōu)化以及bug修復(fù)情況,將Istio當(dāng)做高度模塊化的系統(tǒng),多帶帶升級(jí)某些組件。上面就提到我們?cè)贗stio1.0的基礎(chǔ)上使用了1.0.5版本的Policy、Telemetry、Pilot Discovery等組件。
服務(wù)平滑更新和關(guān)閉
Istio依靠Proxy來(lái)幫助APP進(jìn)行路由,考慮幾種情況會(huì)出現(xiàn)意外的狀態(tài):
* APP啟動(dòng)先于Proxy,并開(kāi)始調(diào)用其它服務(wù),這時(shí)Proxy尚未初始化完畢,APP調(diào)用失敗。 * Service B關(guān)閉時(shí),調(diào)用者Service A的Proxy尚未同步更新Service A關(guān)閉的狀態(tài),向Service B發(fā)送請(qǐng)求,調(diào)用失敗。
第一種情況要求APP有重試機(jī)制,能適當(dāng)重試請(qǐng)求,避免啟動(dòng)時(shí)的Proxy初始化與APP初始化的時(shí)差。
第二種情況,一種是服務(wù)更新時(shí),我們使用新建新服務(wù),再切流量;一種是服務(wù)異常退出,這種情況是在客戶端重試機(jī)制。希望使用Istio的開(kāi)發(fā)人員有更好的解決方案。
見(jiàn)聞Istio化已于去年10月份完成并上線,我們的線上集群中Istio和非Istio的APP混合部署,上千的Pod數(shù)量曾對(duì)不夠健壯的服務(wù)發(fā)現(xiàn)組件造成巨大的壓力,在這期間曾遇到Istio的一些驚喜,并不斷總結(jié)經(jīng)驗(yàn),希望給之后使用Istio的同學(xué)一些借鑒。之后的過(guò)程中,SRE的目標(biāo)依然是保障線上服務(wù)的健壯性。
Istio Dashboard
優(yōu)化APP部署流程,考慮自動(dòng)部署的功能,通過(guò)服務(wù)指標(biāo)自動(dòng)完成灰度發(fā)布和流量遷移。
Prometheus
Prometheus的高可用、可拓展方案的探索。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/32927.html
摘要:以下內(nèi)容根據(jù)魏巍分享整編,希望對(duì)大家了解有所幫助。數(shù)據(jù)平面由一組智能代理組成,代理部署為,其控制微服務(wù)之間所有的網(wǎng)絡(luò)通信。 7月7日,時(shí)速云企業(yè)級(jí)容器 PaaS 技術(shù)沙龍第 10 期在上海成功舉辦,時(shí)速云容器架構(gòu)負(fù)責(zé)人魏巍為大家詳細(xì)講解了 Service Mesh 中代表性的實(shí)踐方案、并以 Istio 為例詳細(xì)講解了 Service Mesh 中的技術(shù)關(guān)鍵點(diǎn),包括 Istio 控制平面...
摘要:以下內(nèi)容根據(jù)魏巍分享整編,希望對(duì)大家了解有所幫助。數(shù)據(jù)平面由一組智能代理組成,代理部署為,其控制微服務(wù)之間所有的網(wǎng)絡(luò)通信。 7月7日,時(shí)速云企業(yè)級(jí)容器 PaaS 技術(shù)沙龍第 10 期在上海成功舉辦,時(shí)速云容器架構(gòu)負(fù)責(zé)人魏巍為大家詳細(xì)講解了 Service Mesh 中代表性的實(shí)踐方案、并以 Istio 為例詳細(xì)講解了 Service Mesh 中的技術(shù)關(guān)鍵點(diǎn),包括 Istio 控制平面...
摘要:敖小劍萬(wàn)字解讀服務(wù)網(wǎng)格新生代添加很多新的功能以及改建,下面來(lái)談一談,讓人激動(dòng)的大改進(jìn)對(duì)于自定義資源和初始化器的支持,要求或更新,如果集群中啟用了特性,建議安裝初始化器,它為所有想要的管理的微服務(wù)部署注入了自動(dòng)的。 關(guān)于Service Mesh,數(shù)人云之前給大家分享了敖小劍老師的《Qcon2017實(shí)錄|Service Mesh:下一代微服務(wù)》那么它對(duì)于容器相比傳統(tǒng)模式都有哪方面的優(yōu)勢(shì)呢?...
摘要:宋體宋體是在監(jiān)聽(tīng)器配置完成之后執(zhí)行的,用于向中插入用戶自定義的。宋體宋體截止目前為止,平臺(tái)上共有個(gè)應(yīng)用通過(guò)提供服務(wù),除了,同時(shí)針對(duì)其他網(wǎng)絡(luò)資源也做了嚴(yán)格的隔離,以此來(lái)保證不同用戶的服務(wù)的穩(wěn)定性。KUN(中文名鯤)是 UCloud 面向內(nèi)部的基于 Kubernetes 的資源交付平臺(tái),提供監(jiān)控告警、CI/CD、網(wǎng)絡(luò)雙棧、Service Mesh 等能力。在踐行 Service Mesh 理念的...
摘要:優(yōu)化網(wǎng)絡(luò)在今年早些時(shí)候,我們公布了許多關(guān)于的新的網(wǎng)絡(luò)功能,包括原生集群,共享,原生容器負(fù)載均衡以及原生容器的網(wǎng)絡(luò)服務(wù),它們服務(wù)于上的應(yīng)用程序以及在谷歌云上的。 showImg(https://segmentfault.com/img/bVbnY8w);許多企業(yè)機(jī)構(gòu)正在把全部或部分 IT 業(yè)務(wù)遷移到云端,幫助企業(yè)更好的運(yùn)營(yíng)。不過(guò)這樣的大規(guī)模遷移,在企業(yè)的實(shí)際操作中也有一定難度。不少企業(yè)保...
閱讀 1350·2021-11-23 09:51
閱讀 2728·2021-09-03 10:47
閱讀 2312·2019-08-30 15:53
閱讀 2518·2019-08-30 15:44
閱讀 1439·2019-08-30 15:44
閱讀 1270·2019-08-30 10:57
閱讀 2008·2019-08-29 12:25
閱讀 1150·2019-08-26 11:57