k8s中流量分离以及资源隔离实战
源寶導讀:明源云客的終端用戶越來越多,也涌現出線上流量活動的場景,大量的訪問和接口請求導致服務器出現較高負載。本文將介紹云客團隊為了緩解服務器壓力,通過K8S進行分流與資源隔離的實踐過程。
一、背景
? ? PaaS和B2C的主要客戶云客的終端用戶越來越多,也開始有流量活動的需求。
? ? 近期云客需要開始一個流量活動,B2C配合對特定接口做了壓測并且對系統容量進行了調整。當時的壓測結果是200并發300ms完成基本符合云客的要求。可是活動開始后事情跟我們預想的是不一樣的,壓測只測試了注冊接口,但是實際登陸接口也會有巨大的請求量。由于登陸接口有比較多的調用第三方所以在請求量大的是對服務器的CPU帶來較高的負載。在這個情況下我們不斷的對服務進行擴容。可是擴到190個核心服務服務依然是沒法正常。
? ? 由于當時部署的是整個服務組統一給所有用戶提供服務,如下圖:
? ? 按照這個情況只要一個租戶的流量特別大給集群帶來壓力就會導致整個服務異常,所有人都無法正常訪問。出于將影響范圍縮小的考慮,我們需要將活動的流量分流并保障即便活動的客戶出現問題也只是影響活動租戶不會影響到其他租戶。
二、分流
? ??在思考如何分流時,第一個想到的是之前已經在云鏈和云空間落地的利用openresty識別url參數,header,cookie中的特征信息然后進行路由這個方案。但是由于paas和B2C部署是基于k8s這個方案就變的不那么好了。
? ? 使用openresty就需要在集群之外架設將流量分配到兩個集群,那么會遇到這些問題:
分流集群通常不是常駐有需要的時候才會部署,這樣每次需要分流前都要去維護分流策略。
為了保障openresty的可用性,可能需要在集群外部部署多個openresty服務。那么流量的路徑會變的很復雜且冗長,這會讓排查問題變的困難,同時會影響訪問速度。
需要時間完成分流策略的代碼,并且要進行一定的壓力測試才能夠正式上線接管流量。會需要很比較多的時間。
? ? 由于這些問題,考慮從k8s的ingress來進行分流。有了下圖的設想:
? ? ingress-controller的選擇
? ? 我們使用的ingress-controller是nginx-ingress,nginx-ingress自帶一個分流功能,定義上也十分符合k8s和helm的的管理方式。查閱官方文檔后發現,目前nginx-ingress只支持header,cookie進行分流,可是現狀是現有項目分流的特征信息在url的query才有。只能再去尋找其他ingress-controller。
? ? 查找并對比了traefik,ambassador,haproxy,alibaba-ingress這幾個ingress-controller。
traefik在功能上是滿足的且有很多新的功能十分值得嘗試,并且解決了nginx令人詬病的靜態配置問題。但是不支持tcp協議路由,需要k8s版本高于1.14。由于一個網絡插件升級的問題我們的k8s集群一直還在1.12版本,所以這次用不上了。
ambassador。如果嚴格遵循k8s的定義,ambassador其實不算一個ingress-controller。它并不是通過ingress去定義路由規則,而是直接在service上加上注解定義路由規則(更像一個api網關)。這樣的話我們需要改動的點就比較多了。
haproxy的優勢在負載均衡算法,在七層協議的路由能力不能滿足需求。pass
alibaba-ingress,阿里云基于nginx-ingress進行了一些定制開發和優化的ingress-controller。基本是與我們現在用的nginx-ingress一致,在分流的規則定義上有一些差異。nginx的分流是分別在兩個namespace定義兩條ingress規則(注解有差異,通過注解匹配請求),alibaba的則是在同一個ingress規則定義2個后端服務再通過注解匹配請求。alibaba-ingress的分流規則支持基于query的匹配是符合我們需求的,但是兩年沒有更新版本并且官方不提供helm部署方式。
? ? 基于符合需求且影響點最小化的思路,選用了alibaba-ingress來作為這次分流的ingress-controller。
三、部署
? ? 在選定了分流的方案之后,如何高效穩定的部署兩組服務成為第二個需要解決的問題。
? ? 目前我們的部署方式:將一組服務打包成一個產品進行部署。
? ? 如何部署分流的服務組,有兩個方案:
將分流的服務一個個加入產品里面進行部署。
將現有產品在其他namespace再部署一份。
方案1:所有服務都在一個namespace中ingress規則很好配(ingress規則不能路由到不同namespace的service),但是會讓服務管理變的十分復雜,并且需要修改應用配置。放棄。
方案2:兩組服務分別 部署在兩個namespace需要解決跨namespace配置ingress規則的問題,但是管理上簡單,也不需要對應用做任何改動。
? ? 改變部署存在的影響點太多,時間緊迫必須選擇影響點最少的辦法。所以方案2是首選。
? ? 如何讓ingress規則跨namespace
? ? 既然ingress的規則不能跨namespace路由,那就想辦法把其他namespace的service弄到當前namespace。在k8s中有一種ExternalName類型的service,提供了映射外部服務的能力(其實就是一個類似cname解析的功能)。
? ? 部署示意:
? ? 分兩個命名空間部署兩組一模一樣的服務,在常駐服務的命名空間中用ExternalName類型的service將分流服務命名空間內的服務映射過來。ingress在同一個命名空間下進行流量分配。
四、資源隔離
? ? 在分流和部署的方案都確定以后,需要考慮最后一個問題。如何保障正常用戶不被活動的用戶影響。根據我們的現狀,之所以正常用戶會被影響的主要原因就是資源被活動用戶消耗殆盡導致整個系統的崩潰,基于這個情況為了保護正常用戶的訪問只需要將正常用戶和活動用戶使用的資源進行隔離即可。
? ? K8S提供了幾種管理容器調度到節點的功能:
節點選擇器(nodeSelector),非常簡單的方法來將 pod 約束到具有特定標簽的節點上
節點親和(nodeAffinity),節點親和分為硬和軟兩種,“硬”類似節點選擇器只是可以用更復雜的約束規則,“軟”則是盡可能運行到符合條件的節點上。
節點瑕疵和容忍度(Taint和Toleration),為特定節點打上瑕疵標簽,只有能夠容忍該瑕疵的pod才能運行到這類節點上。
? ? 實現隔離
? ? 利用1和3的功能,就能夠實現我們期望的效果。
為活動的租戶新增一批節點,給這些節點打上瑕疵標簽。保持正常業務的容器無法被調度到這些節點。
按照之前部署中介紹的方案,為活動租戶新部署一套服務。
新增的一組服務,配置節點選擇器約束到特定節點,配置節點容忍新增節點的瑕疵標簽。
? ? 經過上述步驟就能夠將兩組服務的資源很好的隔離開。
五、快速配置
? ? 完成了功能性的訴求,最后就是需要在使用上變得便利。因為之前選擇方案都會考慮配置和部署的便利性,所以最終只需要對現有的chart(部署模版)進行一些小小的調整就能實現快速配置分流以及隔離。
? ? 新增節點
? ? 通過阿里云新增節點,之后通過下面命令對節點打標簽和瑕疵
kubectl label node cn-hangzhou.i-bp1faickzmmuat2f09dr b2c=canary kubectl taint node cn-hangzhou.i-bp1faickzmmuat2f09dr b2c=canary:NoSchedule? ? 部署分流服務
? ? 我們使用helm部署,只需要復制常駐服務的values文件新增幾個字段并關閉ingress配置然后用helm部署到新的namespace即可。
? ? 以一個服務的values舉例,復制內容如下:
修改后內容如下:
b2c-nginx-proxy:replicaCount: 5image:tag: "20190920"env:enabled: true ingress:enabled: falseannotations: kubernetes.io/ingress.class: nginxhosts:- example.mypaas.com.cntls: - secretName: example.com.cnhosts:- example.mypaas.com.cntolerations:- key: b2coperator: "Equal"value: "canary"effect: "NoSchedule" nodeSelector:b2c: canary? ? 常駐服務開啟分流配置
? ? 常駐服務的values文件新增幾行即可實現分流以一個服務的values舉例:
b2c-nginx-proxy:replicaCount: 3image:tag: "20190920"env:enabled: true ingress:enabled: truecanary:enable: true #開啟分流annotations: kubernetes.io/ingress.class: nginxnginx.ingress.kubernetes.io/service-match: | #分流規則配置b2c-nginx-proxy-canary: query("tenant_code", /.*zhaosadmin.*/) hosts:- example.mypaas.com.cntls: - secretName: example.com.cnhosts:- example.mypaas.com.cn? ? 簡單的三步即可完成租戶分流并且隔離。
六、應用
? ? 當所有驗證ok后,立馬將這套方案在生產上線,將當時活動的租戶分流并隔離。同時開始縮減集群規模把為正常租戶提供服務的服務組節點數量恢復成常駐節點數量,保留四個節點繼續為活動租戶提供服務。
? ? 到目前為止正常租戶的服務沒有受到過影響。
七、云擎的灰度策略
? ? 灰度發布的技術本質跟這個分流并沒有太大的區別。只是使用場景上的差異,所以這套方案可以放到云擎直接實現灰度發布。簡單介紹一下,將來各團隊接入使用時也能提前準備。
? ? 支持的路由規則
? ? 云擎支持的ingress-controller只會是nginx-ingress,因為alibaba-ingress幾年沒有更新,不敢在生產環節長期使用。
所以云擎只能支持根據header和cookie進行路由。如果各團隊希望能夠灰度發布需要在請求頭中加入特定標識。
? ? 數據庫的灰度
沒有租戶庫的團隊,需要保持灰度的兩個版本在數據結構上是兼容的
有租戶庫的團隊,選擇租戶的范圍進行數據升級
? ? 產品內部的服務調用
? ? 需要使用灰度發布必須保持各個服務間的調用都要走內網調用。不能通過公網域名調用,這樣會導致調用關系混亂。
? ? 支持的特性
? ? 由于是利用nginx-ingress實現的,所以還是會遵循一些nginx本身的限制。
只能創建一條灰度規則
一條規則內可以同時定義header,cookie,權重。優先級關系:header -> cookie -> 權重。
header支持自定義值并且值可以用正則匹配,cookie只支持固定值:always或never
分流規則所有配置遵循原有的所有配置,如:最大傳輸大小,是否強制https,超時時間等
八、未來
? ? 現階段利用nginx-ingress云擎能夠以極低的成本提供灰度發布的能力,但是nginx-ingress整體來看功能還是有欠缺。不過在這次事件中為了找方案,了解了其他優秀的ingress-controller。后續應該會把所有的ingress-controller替換成traefik來實現更多功能。
------ END ------
作者簡介
尹同學:?運維負責人,目前在云技術創新中心負責技術運維工作。
也許您還想看
天眼系統對應用頁面首次有效渲染的數據采集
云客大數據管理保障體系
淺談Readiness和Liveness在云客的應用
基于Go的微服務運行情況監控實踐
總結
以上是生活随笔為你收集整理的k8s中流量分离以及资源隔离实战的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: EFCore.Sharding(EFCo
- 下一篇: 怎样实现WPF Prism Module