深度了解微博云原生技術(shù)的思考與實(shí)踐
移動互聯(lián)網(wǎng)高速發(fā)展的早期,企業(yè)更多關(guān)注業(yè)務(wù)擴(kuò)張,用成本投入來換取市場占用率。但如今移動互聯(lián)網(wǎng)經(jīng)歷了近十年的高速發(fā)展,互聯(lián)網(wǎng)人口紅利逐漸消退,幾乎沒有公司能夠再忽視成本。無論是蘋果公司的供應(yīng)鏈、庫存管理,還是特斯拉通過國產(chǎn)化降低成本,又或者是各大云廠商對企業(yè) IT 成本的優(yōu)化,都是這些企業(yè)保持高速發(fā)展的重要因素。
企業(yè)在早期的資源使用上以滿足業(yè)務(wù)需求為第一要務(wù),資源的使用率管理相對粗放。無論是機(jī)器規(guī)劃的多樣化還是容量規(guī)劃問題,或者是在離線資源的整合問題,歸納起來其實(shí)都是額外預(yù)留了不需要的資源,導(dǎo)致成本浪費(fèi)。
近些年隨著云原生的興起和建設(shè),服務(wù)已經(jīng)具備快速遷移能力?;诖耍Y源容量就可以按需申請,最小化閑置資源,業(yè)務(wù)也可以在不同的時(shí)間段在相同的機(jī)器上按需要部署,不同規(guī)格的機(jī)器可以基于超高規(guī)格的機(jī)器(256C/2T)混合部署,化零為整,大幅降低資源成本。微博在云原生改造過程中也嘗試進(jìn)行了各種能力建設(shè),并梳理了以下 6 種有效的成本優(yōu)化手段。
現(xiàn)在越來越多的企業(yè)開始全面擁抱云計(jì)算,開始關(guān)注云原生技術(shù)。從管理物理數(shù)據(jù)中心到使用云主機(jī),我們不用再關(guān)心基礎(chǔ)運(yùn)維。從云主機(jī)到 Kubernetes 容器,我們不用再關(guān)心機(jī)器的管理。云上抽象層級越高,就越少人需要關(guān)心底層問題,企業(yè)就能夠節(jié)省大量的人力成本與資源投入。云原生技術(shù)就是更高一層的抽象,CNCF 對云原生技術(shù)的定義是:
有利于各組織在公有云、私有云和混合云等新型動態(tài)環(huán)境中,構(gòu)建和運(yùn)行可彈性擴(kuò)展應(yīng)用。通過容器、服務(wù)網(wǎng)格、微服務(wù)、不可變基礎(chǔ)設(shè)施和聲明式API等技術(shù),構(gòu)建容錯(cuò)性好、易于管理和便于觀察的松耦合系統(tǒng)。
例如 FaaS 架構(gòu),開發(fā)者可以完全不用考慮服務(wù)器,構(gòu)建并運(yùn)行應(yīng)用程序和服務(wù)。還有面向開源架構(gòu)的的云原生技術(shù),與提供 MySQL,Redis 云服務(wù)類似,提供基于 Spring Cloud、Dubbo、HSF 等開源微服務(wù)架構(gòu)的應(yīng)用管理服務(wù),開發(fā)者無需考慮部署、監(jiān)控、運(yùn)維的問題。
微博也一直在致力于推動基礎(chǔ)設(shè)施云原生化,我們圍繞 Kubernetes 構(gòu)建面向容器的云原生基礎(chǔ)設(shè)施,形成了物理數(shù)據(jù)中心加多個(gè)公有云的混合云 Kubernetes 平臺,提供秒級伸縮能力。構(gòu)建開箱即用的 CI/CD 體系,依托云原生伸縮能力,保證大量的 Job 穩(wěn)定運(yùn)行,讓開發(fā)人員擺脫代碼發(fā)布泥沼。接下介紹這幾方面的實(shí)踐經(jīng)驗(yàn)。
物理數(shù)據(jù)中心 Kubernetes 化
面向單機(jī)器的基礎(chǔ)設(shè)施架構(gòu)已經(jīng)無法發(fā)揮云的最大優(yōu)勢。把容器按照服務(wù)顆粒度進(jìn)行管理,每個(gè)服務(wù)對應(yīng)一組虛擬機(jī),雖然基礎(chǔ)運(yùn)維通過 IaaS 層抽象得到了極大簡化,但是業(yè)務(wù)的運(yùn)維成本依然很高,業(yè)務(wù) SRE 需要維護(hù)復(fù)雜的設(shè)備配置腳本,管理不同服務(wù)設(shè)備配置的差異性,需要 7 * 24 小時(shí)對故障設(shè)備進(jìn)行干預(yù)。而且資源利用率無法最大化,服務(wù)池是按設(shè)備劃分,一個(gè)新設(shè)備添加到服務(wù)池后只能被這個(gè)服務(wù)使用,它的冗余的計(jì)算能力并不能為其他服務(wù)使用。另外不同業(yè)務(wù)容器運(yùn)行在不同的機(jī)器上,容器網(wǎng)絡(luò)架構(gòu)更關(guān)注性能而非隔離性,通常會采用 Host 模式,這也提高了服務(wù)混合部署的運(yùn)維成本。
基礎(chǔ)設(shè)施只有形成集群,才能最大程度發(fā)揮容器的良好隔離、資源分配與編排管理的優(yōu)勢。目前 Kubernetes 已經(jīng)容器編排系統(tǒng)的事實(shí)標(biāo)準(zhǔn),提供面向應(yīng)用的容器集群部署和管理系統(tǒng),消除物理(虛擬)機(jī),網(wǎng)絡(luò)和存儲基礎(chǔ)設(shè)施的負(fù)擔(dān)。同時(shí) CNCF 推出一致性認(rèn)證,推動各公有云廠商提供標(biāo)準(zhǔn)的 Kubernetes 服務(wù),這就確保通過 Kubernetes 部署的應(yīng)用在不同云廠商之間具有可遷移性,避免被廠商鎖定。
之前提到微博的容器會獨(dú)占物理機(jī)的網(wǎng)絡(luò)協(xié)議棧,雖然能夠做到網(wǎng)絡(luò)效率的最大化,但是會導(dǎo)致多容器部署時(shí)出現(xiàn)端口沖突,無法滿足 Kubernetes 動態(tài)編排的需求。為了解決端口沖突問題,我們首先測試了 vxlan 網(wǎng)絡(luò)架構(gòu),因?yàn)槠鋽?shù)據(jù)平面需要進(jìn)行封裝、解封操作,網(wǎng)絡(luò)性能損耗超過5%,并不滿足微博后端服務(wù)對網(wǎng)絡(luò)性能的要求。最后我們評估可行的網(wǎng)絡(luò)方案有兩種 MacVlan 和 Calico BGP。
其中 MacVlan 成熟穩(wěn)定,通過機(jī)房上聯(lián)交換機(jī)改為 Vlan Trunk 模式,在物理機(jī)上創(chuàng)建 MacVlan 網(wǎng)卡子接口,通過 CNI 插件將虛擬網(wǎng)卡插入 Pause 容器中,實(shí)現(xiàn)容器網(wǎng)絡(luò)與物理網(wǎng)絡(luò)打通。容器的網(wǎng)絡(luò)通信直接通過 MacVlan 物理子接口,發(fā)出的報(bào)文在網(wǎng)卡上打 VlanTag,數(shù)據(jù)平面基本沒有性能損耗??刂破矫嬉蛐枰獙λ猩下?lián)交換機(jī)進(jìn)行 Vlan Trunk 改造,工作量較大,所以這個(gè)方案僅針對高配物理機(jī)所在網(wǎng)絡(luò)進(jìn)行了改造。
Calico BGP 是可以同時(shí)實(shí)現(xiàn)數(shù)據(jù)平面 0 損耗與控制平面自動化的容器網(wǎng)絡(luò)解決方案。與 MacVlan 實(shí)現(xiàn)的扁平二層網(wǎng)絡(luò)不同,Calico 在每個(gè)節(jié)點(diǎn)上部署 BGP Client 與 Reflector 實(shí)現(xiàn)了一個(gè)扁平的三層網(wǎng)絡(luò),每個(gè)節(jié)點(diǎn)發(fā)布的路由狀態(tài)由 Felix 維護(hù)。不過由于 Felix 采用 iptables 實(shí)現(xiàn)路由 ACLs 功能,對性能存在一定影響。因?yàn)槲锢頂?shù)據(jù)中心不面向外部用戶開放,所以 ACLs 功能對微博是可以去除的,我們對 Calico 進(jìn)行了優(yōu)化,去除 iptables 依賴。
微博也主動回饋 Kubernetes 社區(qū),也包括為 Kubernetes 代碼庫做貢獻(xiàn),例如修復(fù)多租戶下網(wǎng)絡(luò)隔離 TC 資源泄露問題。
之前的運(yùn)維是面向物理機(jī)的,所以物理機(jī)上存在很多運(yùn)維工具,如日志推送、域名解析、時(shí)鐘同步、定時(shí)任務(wù)等。業(yè)務(wù)通過 Kubernetes 編排后,以上的功能都需要進(jìn)行容器化改造。例如在容器中使用 systemd 會涉及到提權(quán)問題,在實(shí)踐過程中發(fā)現(xiàn)用 systemd 如果權(quán)限控制不當(dāng)會造成容器被 Kill 的情況。所以我們單獨(dú)開發(fā)了兼容 linux crontab 語法的定時(shí)任務(wù)工具 gorun,把這個(gè)工具集成在了運(yùn)維容器里面。
因?yàn)闃I(yè)務(wù)容器會產(chǎn)生大量日志,出于 I/O 性能考慮,同時(shí)為了方便快速定位,日志會存儲于本地 PVC 中,支持配額管理,避免一個(gè)容器把磁盤寫滿。運(yùn)維基礎(chǔ)設(shè)施容器通過監(jiān)聽文件,對老舊日志進(jìn)行壓縮清理,性能 Profile 日志會在本地進(jìn)行統(tǒng)計(jì)計(jì)算后通過 UDP 協(xié)議推送到 Graphite 或 Prometheus。對于關(guān)鍵日志,會通過 Flume 推送到 Kafka 集群,而且支持失敗重傳,保證日志的一致性。
通過對運(yùn)維容器化后,所有業(yè)務(wù) Pod 都具備相同的運(yùn)維能力,形成標(biāo)準(zhǔn)化的監(jiān)控報(bào)警、運(yùn)維決策、流量切換、服務(wù)降級,異常封殺、日志查詢的服務(wù)保障體系,服務(wù)可運(yùn)維性大幅度提升。
容器編排
Kubernetes 的 Deployment 支持 Pod 自我修復(fù),滾動升級和回滾,擴(kuò)容和縮容,這些特性都是云原生基礎(chǔ)設(shè)施必備的。但是 Kubernetes 設(shè)計(jì)原則中對集群的管理尤其是服務(wù)升級過程中保持“無損”升級,對 Deployment 進(jìn)行滾動升級,會創(chuàng)建新 Pod 替換老 Pod,以保證 Deployment 中 Pod 的副本數(shù)量。原有里面的IP地址和滾動升級之前的IP地址是不會相同的。而如果集群夠大,一次滾動發(fā)布就會導(dǎo)致負(fù)載均衡變更 (集群副本數(shù)/滾動發(fā)布步長)次。對于微博服務(wù)來說,頻繁變更會導(dǎo)致這個(gè)負(fù)載均衡轄下,所以后端實(shí)例的接口不穩(wěn)定。
微博實(shí)現(xiàn)了常備 Pod 的 In-place Rolling Updates 功能,根據(jù)業(yè)務(wù)冗余度及業(yè)務(wù)實(shí)際需要來調(diào)整上線的步長,上線過程中保持容器的IP不變,減少在上線過程中業(yè)務(wù)的抖動。因?yàn)闃I(yè)務(wù)的啟動需要一定時(shí)間,不能按照容器啟停來做步長控制,我們利用 Kubernetes 容器生命周期管理的 liveness/readiness probe 實(shí)現(xiàn)容器提供服務(wù)的狀態(tài),避免了上線過程中容器大面積重啟的問題。同時(shí)優(yōu)化了 Kubernetes 的 postStar 的原生實(shí)現(xiàn),因?yàn)樵锩嬷徽{(diào)用一次,不管成功與否都會殺掉容器,改成不成功會按照指定的次數(shù)或時(shí)間進(jìn)行重試。IP 的靜態(tài)分配使用 Calico CNI 實(shí)現(xiàn):
apiVersion: v1 kind: Pod metadata: name: wb_service annotations: "cni.projectcalico.org/ipAddrs": "[\"10.142.0.50\"]"
Kubernetes 的編排策略相對靈活,分為三個(gè)階段,初篩階段用于篩選出符合基本要求的物理機(jī)節(jié)點(diǎn),優(yōu)選階段用于得到在初篩的節(jié)點(diǎn)里面根據(jù)策略來完成選擇最優(yōu)節(jié)點(diǎn)。在優(yōu)選完畢之后,還有一個(gè)綁定過程,用于把 Pod 和物理機(jī)進(jìn)行綁定,鎖定機(jī)器上的資源。這三步完成之后,位于節(jié)點(diǎn)上的 kubelet 才開始創(chuàng)建 Pod。在實(shí)際情況中,把物理機(jī)上的容器遷移到 Kubernetes,需要保持容器的部署結(jié)構(gòu)盡量一致,例如一個(gè)服務(wù)池中每臺物理機(jī)上分配部署了 wb_service_a 和 wb_service_b 兩個(gè)容器,可以通過 podAffinity 來完成服務(wù)混部的編排:
apiVersion: v1 kind: Pod metadata: name: wb_service_b annotations: "cni.projectcalico.org/ipAddrs": "[\"10.142.0.50\"]" labels: service: wb_service_b spec: affinity: podAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: service operator: In values: ["wb_service_a"] topologyKey: "kubernetes.io/hostname"
一些比較復(fù)雜的,運(yùn)維復(fù)雜的集群,通過 Kubernetes Operator 進(jìn)行容器編排。Operator 是由 CoreOS 開發(fā)的,用來擴(kuò)展 Kubernetes API,特定的應(yīng)用程序控制器,它用來創(chuàng)建、配置和管理復(fù)雜的有狀態(tài)應(yīng)用,如數(shù)據(jù)庫、緩存和監(jiān)控系統(tǒng)。Operator 基于 Kubernetes 的資源和控制器概念之上構(gòu)建,但同時(shí)又包含了應(yīng)用程序特定的領(lǐng)域知識。Operator 可以將運(yùn)維人員對軟件操作的知識給代碼化,同時(shí)利用 Kubernetes 強(qiáng)大的抽象來管理大規(guī)模的軟件應(yīng)用。例如 CacheService 的運(yùn)維是比較復(fù)雜的,需要資源編排,數(shù)據(jù)同步,HA 結(jié)構(gòu)編排,備份與恢復(fù),故障恢復(fù)等等。通過實(shí)現(xiàn) CacheService Operator 可以讓開發(fā)一通過聲明式的 Yaml 文件即可創(chuàng)建、配置、管理復(fù)雜的 Cache 集群。CacheService Operator 支持:
創(chuàng)建/銷毀:通過 Yaml 聲明 CacheService 規(guī)格,即可通過 Kubernetes 一鍵部署,刪除
伸縮:可以修改 Yaml 中聲明的副本數(shù)量,Operator 實(shí)現(xiàn)擴(kuò)容,配置主從結(jié)構(gòu),掛載域名等操作
備份:Operator 根據(jù) Yaml 中聲明的備份機(jī)制,實(shí)現(xiàn)自動的備份功能,例如定期備份,錯(cuò)峰備份等
升級:實(shí)現(xiàn)不停機(jī)版本升級,并支持回滾
故障恢復(fù):單機(jī)故障時(shí),自動 HA 切換,同時(shí)恢復(fù)副本數(shù)量,并自動恢復(fù)主從結(jié)構(gòu)
復(fù)雜的應(yīng)用在 Kubernetes 上部署,服務(wù)數(shù)量眾多,服務(wù)間的依賴關(guān)系也比較復(fù)雜,每個(gè)服務(wù)都有自己的資源文件,并且可以獨(dú)立的部署與伸縮,這給采用 Kubernetes 做應(yīng)用編排帶來了諸多挑戰(zhàn):
管理、編輯與更新大量的 Yaml 配置文件
部署一個(gè)含有大量配置文件的復(fù)雜 Kubernetes 應(yīng)用,例如上面提到的 CacheService Operator
參數(shù)化配置模板支持多個(gè)環(huán)境
Helm 可以解決這些問題。Helm 把 Kubernetes 資源(如 Pods,Deployments,Services 等)打包到一個(gè) Chart 中,實(shí)現(xiàn)可配置的發(fā)布是通過模板加配置文件,動態(tài)生成資源清單文件。
彈性伸縮
在云時(shí)代,彈性已經(jīng)成為新常態(tài)。而且微博的社交媒體屬性,不可提前預(yù)期的突發(fā)峰值是家常便飯,所以基礎(chǔ)設(shè)施不但需要具備彈性,而且需要具備在短時(shí)間內(nèi)提供足夠資源的能力。Kubernetes 基于容器技術(shù)在啟動時(shí)間方面比虛擬機(jī)更具優(yōu)勢,省去了虛擬機(jī)創(chuàng)建、環(huán)境初始化、配置管理等諸多環(huán)節(jié),直接拉起業(yè)務(wù) Pod,擴(kuò)容時(shí)間可以從分鐘級縮短到秒級。
而且峰值流量突發(fā)時(shí),運(yùn)維、開發(fā)同學(xué)可能是在吃飯、睡覺、休假,這個(gè)時(shí)候靠人為干預(yù)肯定是來不及的,所以系統(tǒng)需要自動做出擴(kuò)容決策。對于復(fù)雜的分布式系統(tǒng),實(shí)現(xiàn)自動決策需要解決兩個(gè)問題,一個(gè)是容量決策,一個(gè)是依賴關(guān)系。Kubernetes 的 HPA(Horizontal Pod Autoscaling)可以根據(jù) Metric 自動伸縮一個(gè) Deployment 中的 Pod 數(shù)量。HPA 由一個(gè)控制循環(huán)實(shí)現(xiàn),循環(huán)周期由 horizontal-pod-autoscaler-sync-period 標(biāo)志指定(默認(rèn)是 30 秒)。在每個(gè)周期內(nèi),查詢 HPA 中定義的資源利用率。并且在擴(kuò)容前會有一個(gè)冷靜期,一般是 5 分鐘(可通過 horizontal-pod-autoscaler-downscale-stabilization 參數(shù)設(shè)置),然后通過下面的公式進(jìn)行擴(kuò)縮容:
desired = ceil[current * ( currentMetric / desiredMetric )]
但是這種容量決策存在兩個(gè)問題。因?yàn)橥话l(fā)峰值流量上漲迅速,上述擴(kuò)容機(jī)制第一次擴(kuò)容往往擴(kuò)不到位,觸發(fā)連續(xù)多次擴(kuò)容,導(dǎo)致服務(wù)在流量上漲期間一直處于過載狀態(tài),影響服務(wù) SLA。另一個(gè)問題是冷靜期問題,如果冷靜期過長,會導(dǎo)致峰值流量無法得到及時(shí)擴(kuò)容,冷靜期過短會錯(cuò)把抖動當(dāng)做峰值,造成不必要的成本浪費(fèi)。第三個(gè)問題是復(fù)雜的業(yè)務(wù)系統(tǒng)依賴關(guān)系復(fù)雜,每個(gè)服務(wù)根據(jù)各自指標(biāo)進(jìn)行伸縮,由于上面還未伸縮流量被擋在了上游,下游這時(shí)感知不到準(zhǔn)確流量趨勢,從整體應(yīng)用角度看很容易出現(xiàn)上游泄洪下游被淹的問題。
微博整體的彈性伸縮架構(gòu)是基于混合云的架構(gòu),內(nèi)網(wǎng)私有云,公有云虛機(jī),云 Kubernetes 一體化 Kubernetes 彈性集群,實(shí)現(xiàn)快速自動化資源調(diào)度,解決了跨 IDC 調(diào)度、定制的調(diào)度算法與策略、容量評估、服務(wù)間擴(kuò)容依賴關(guān)系等,構(gòu)建了全鏈路,壓測,指標(biāo),報(bào)警,干預(yù)多維度的能力:
全鏈路是構(gòu)建一個(gè)應(yīng)用整體的容量決策體系,各服務(wù)不再獨(dú)自判定容量,而是根據(jù)全鏈路容量指標(biāo)作出一致性擴(kuò)容決策
壓測可以幫助了解目前部署的冗余情況,合理的設(shè)定擴(kuò)容公式,避免多次重復(fù)性擴(kuò)容
指標(biāo)體系是要從成千上萬個(gè) Metric 中抽象出可以作為決策的依據(jù),打通負(fù)載均衡,Web 服務(wù),數(shù)據(jù)庫資源等多維度指標(biāo)
報(bào)警及時(shí)多路徑觸達(dá),避免單點(diǎn)
干預(yù)不但要支持快速伸縮,還應(yīng)支持快速優(yōu)雅降級,為服務(wù)擴(kuò)容爭取時(shí)間
CI/CD
云計(jì)算技術(shù)的普及,研發(fā)流程也隨之變化,越來越多的組織和團(tuán)隊(duì)開始接受 DevOps 理念。持續(xù)集成(CI)和持續(xù)交付(CD)是 DevOps 的基石。但是 CI/CD 在實(shí)際落地過程中存在諸多困難,導(dǎo)致實(shí)際效果不理想。以 CI 為例,開發(fā)同學(xué)應(yīng)該對“順利的話,會有大約100個(gè)失敗的測試”這種情形并不陌生。由于開發(fā)環(huán)境與測試環(huán)境并不一致等諸多因素,CI 經(jīng)常出現(xiàn)不相干的偶發(fā)失敗,長此以往開發(fā)同學(xué)會默認(rèn)選擇忽略 CI 環(huán)節(jié)的報(bào)錯(cuò)警告,最終導(dǎo)致 CI/CD 淪為一句口號。
利用云原生的聲明性基礎(chǔ)架構(gòu),可以將應(yīng)用系統(tǒng)的和應(yīng)用程序存放在 Git 的版本控制庫中,每個(gè)開發(fā)人員都可以提交拉取請求代碼,輕松在 Kubernetes 上部署應(yīng)用程序和運(yùn)維任務(wù),開發(fā)人員可以更高效地將注意力集中在創(chuàng)建新功能而不是運(yùn)維相關(guān)任務(wù)上?;?Git 的持續(xù)交付流水線,有諸多優(yōu)勢和特點(diǎn):
版本控制的聲明性容器編排,Kubermetes作為一個(gè)云原生的工具,可以把它的“聲明性”看作是“代碼”,聲明意味著配置由一組事實(shí)而不是一組指令組成,例如,“有十個(gè)redis服務(wù)器”,而不是“啟動十個(gè)redis服務(wù)器,告訴我它是否有效”
Git 作為事實(shí)的唯一真實(shí)來源,任何能夠被描述的內(nèi)容都必須存儲在Git庫中,包括系統(tǒng)相關(guān)的:策略,代碼,配置,甚至監(jiān)控事件
與其他工具相結(jié)合,例如監(jiān)控系統(tǒng)可以方便地監(jiān)控集群,以及檢查比較實(shí)際環(huán)境的狀態(tài)與代碼庫上的狀態(tài)是否一致
目前大多數(shù) CI/CD 工具都使用基于推送的模型?;谕扑偷牧魉€意味著代碼從CI系統(tǒng)開始,通過一系列構(gòu)建測試等最終生成鏡像,最后手動使用 “kubectl” 將部署到 Kubernetes 集群。程序員是最不喜歡開發(fā)流程被打斷,多個(gè)系統(tǒng)間的切換會極大影響程序員的開發(fā)效率。所以我們通過 CI 和 IDE 結(jié)合,把 CI 流程融入到開發(fā)自測環(huán)節(jié)中,讓程序員可以進(jìn)行面向 CI 的測試驅(qū)動開發(fā),提高對交付代碼質(zhì)量的信心。
CI/CD 流水線是圍繞程序員經(jīng)常使用的 GitLab 構(gòu)建,程序員可以對 Merge Request 的 CI 結(jié)果一目了然,避免了在多個(gè)系統(tǒng)間來回切換。每次代碼提交都要執(zhí)行基于分支的完整 CI 流程,借助云原生的彈性能力和共享存儲,解決了大量并發(fā)的 Job 的計(jì)算資源瓶頸,同時(shí)緩解了 Job 間共享數(shù)據(jù)的帶寬壓力以及網(wǎng)絡(luò)傳輸延時(shí)。
持續(xù)部署要比持續(xù)集成更加復(fù)雜。部署流程中依賴人工的環(huán)節(jié)非常多,例如灰度是由運(yùn)維部署到生產(chǎn)環(huán)境部分機(jī)器,驗(yàn)證需要依靠開發(fā)和運(yùn)維同學(xué)經(jīng)驗(yàn)檢查新版本各項(xiàng)指標(biāo)是否正常,滾動發(fā)布與回滾也需要運(yùn)維同學(xué)全程干預(yù)。金絲雀部署可以有效規(guī)避風(fēng)險(xiǎn),在生產(chǎn)環(huán)境的基礎(chǔ)設(shè)施中小范圍的部署新的應(yīng)用代碼,如果沒有錯(cuò)誤,新版本才逐漸推廣到整個(gè)服務(wù),而不用一次性從老版本切換到新版本。不過如何驗(yàn)證沒有錯(cuò)誤是比較有挑戰(zhàn)的,微服務(wù)依賴復(fù)雜、部署范圍廣、指標(biāo)維度多,是最易出錯(cuò),最耗時(shí)的環(huán)節(jié)。我們針對這個(gè)問題,開發(fā)了智能時(shí)序數(shù)據(jù)異常識別服務(wù),覆蓋操作系統(tǒng),JVM,資源 SLA,業(yè)務(wù) SLA 的上千維度指標(biāo)。它不但可以自動準(zhǔn)確識別異常識別,性能衰減等人工經(jīng)驗(yàn)?zāi)軌虬l(fā)現(xiàn)的問題,也能夠識別如資源不合理訪問等人工很難察覺的問題。現(xiàn)在的 CD 流程包含部署、集成測試、金絲雀驗(yàn)證、滾動發(fā)布、回滾自動化環(huán)節(jié)。
Weibo Mesh
Service Mesh 并不是什么新的技術(shù),它所關(guān)注的高性能、高可用、服務(wù)發(fā)現(xiàn)和治理等有服務(wù)化的一天就已經(jīng)存在,社區(qū)也不乏這方面的最佳實(shí)踐。不過之前主要是兩種方式,一種是微服務(wù) RPC 框架形式,例如 Motan, gRPC, Thrift, Dubbo 等。傳統(tǒng)微服務(wù)框架有諸多弊端:
升級困難,框架、SDK 的與業(yè)務(wù)代碼強(qiáng)綁定
多語言問題,各種語言的服務(wù)治理能力天差地別,服務(wù)質(zhì)量體系難以統(tǒng)一
還有一種是集中式 Proxy 形式,例如 Nginx,Twemproxy,SQL Proxy 等。雖然 Proxy 的形式一定程度上解決了胖客戶端的問題,沒有了升級問題,多語言可以統(tǒng)一接入。但是在性能方面的損耗,對于耗時(shí)較長的請求來說還可以接受,但這在服務(wù)間調(diào)用這種毫秒級請求時(shí),性能是不能容忍的,而且服務(wù)的拆分勢必導(dǎo)致整個(gè)體系內(nèi)耗時(shí)隨著微服務(wù)規(guī)模的擴(kuò)大而劇增,而且 Proxy 本身很容易成為整個(gè)系統(tǒng)中的瓶頸點(diǎn)。所以經(jīng)??梢钥吹胶蠖朔?wù)是同時(shí)使用 Proxy 和 RPC 的情況。
而 Cloud Native 會催生出如此火爆的 Service Mesh,最主要的因素是 Kubernetes 使基礎(chǔ)設(shè)施的標(biāo)準(zhǔn)化,大家發(fā)現(xiàn)之前這些很重的 RPC 框架可以抽離出來,原本需要增加維護(hù)的復(fù)雜性被 Kubernetes 解決掉了,跨語言、服務(wù)治理等收益凸顯出來。而且 Mesh 的 SideCard 形式,相比 Proxy 在請求耗時(shí)方面優(yōu)勢也相當(dāng)明顯。
微博將 Motan RPC 胖客戶端實(shí)現(xiàn)的治理功能下沉到 Agent 上,服務(wù)注冊和發(fā)現(xiàn)依賴微博自研 Vintage 命名和配置服務(wù),對服務(wù)的訂閱和發(fā)現(xiàn)來建立服務(wù)間依賴的邏輯網(wǎng)絡(luò)。業(yè)務(wù)與 的通信協(xié)議保持一致,Agent 支持 HTTP 和 RPC 的調(diào)用,業(yè)務(wù)只需把原有的調(diào)用指向 Agent 即可,不需要改造業(yè)務(wù)代碼。在跨語言通信協(xié)議設(shè)計(jì)方面,Google 的 Protocol Buffers(pb)序列化能夠提供優(yōu)秀的跨語言序列化能力,但是在一是老舊 HTTP 遷移到 pb 協(xié)議的改造成本過高,二是部分語言(例如 PHP) 在做復(fù)雜 pb 對象序列化時(shí)性能比較差,甚至比 json 序列化還要慢 3 倍左右。微博實(shí)現(xiàn)了全新語言無關(guān)的通信協(xié)議 Motan2 和跨語言友好的數(shù)據(jù)序列化協(xié)議 Simple 來應(yīng)對跨語言。
除了代理 Service 的能力外,Mesh 體系提供了緩存、隊(duì)列等服務(wù)化代理,業(yè)務(wù)方可以與依賴緩存、隊(duì)列資源治理解耦的能力??梢源蠓岣吣切┲卫砟芰Ρ容^薄弱的業(yè)務(wù)和語言的架構(gòu)水平。隨著云原生技術(shù)的日趨完善,會有越來越多的基礎(chǔ)設(shè)施從原有的 SDK 中抽象出來。未來數(shù)據(jù)庫訪問會以 Database Mesh 形式提供訪問,封裝數(shù)據(jù)分片、讀寫分離、從庫負(fù)載均衡、熔斷、鏈路采集能力,例如 Google Cloud SQL 提供本地 Proxy,業(yè)務(wù)方無需將 IP 地址列入白名單或配置 SSL,即可安全地訪問 Cloud SQL。
Kubernetes入門與實(shí)戰(zhàn)培訓(xùn)
Kubernetes入門與實(shí)戰(zhàn)培訓(xùn)將于2019年11月22日在北京開課,3天時(shí)間帶你系統(tǒng)掌握Kubernetes,學(xué)習(xí)效果不好可以繼續(xù)學(xué)習(xí)。本次培訓(xùn)包括:Docker基礎(chǔ)、容器技術(shù)、Docker鏡像、數(shù)據(jù)共享與持久化、Docker實(shí)踐、Kubernetes基礎(chǔ)、Pod基礎(chǔ)與進(jìn)階、常用對象操作、服務(wù)發(fā)現(xiàn)、Helm、Kubernetes核心組件原理分析、Kubernetes服務(wù)質(zhì)量保證、調(diào)度詳解與應(yīng)用場景、網(wǎng)絡(luò)、基于Kubernetes的CI/CD、基于Kubernetes的配置管理等等,點(diǎn)擊下方圖片或者閱讀原文鏈接查看詳情。