Kubernetes已經成爲企業新一代雲IT架構的重要基礎設施,但是在企業部署和運維Kubernetes集羣的過程中,依然充滿了複雜性和困擾。阿里雲容器服務自從2015年上線後,一路伴隨客戶和社區的成長,目前託管着上萬的K8s集羣來支撐全球各地的客戶。我們對客戶在規劃集羣過程中經常會遇見的問題,進行一些分析解答。試圖緩解大家的“選擇恐懼症”。
如何選擇Worker節點實例規格?
裸金屬還是虛擬機?
在Dimanti 2019年的容器調查報告中,對專有云用戶選擇裸金屬服務器來運行容器的主要原因進行了分析。
- 選擇裸金屬服務器的最主要原因(超過55%)是:傳統虛擬化技術I/O損耗較大;對於I/O密集型應用,裸金屬相比傳統虛擬機有更好的性能表現
- 此外近36%的客戶認爲:裸金屬服務器可以降低成本。大多數企業在初始階段採用將容器運行在虛擬機的方案,但是當大規模生產部署的時候,客戶希望直接運行在裸金屬服務器上來減少虛擬化技術的license成本(這也常被戲稱爲“VMWare稅”)。
- 還有近30%的客戶因爲在物理機上部署有更少的額外資源開銷(如虛擬化管理、虛擬機操作系統等);還有近24%的客戶選擇的原因是:可以有更高的部署密度,從而降低基礎設施成本。
- 超過28%的客戶認爲,在物理機上可以更加靈活地選擇網絡、存儲等設備和軟件應用生態。
在公共雲上,我們應該如何選擇呢?
2017年10月,阿里雲“神龍架構”橫空出世。彈性裸金屬服務器(ECS Bare Metal Instance)是一款同時兼具虛擬機彈性和物理機性能及特性的新型計算類產品,實現超強超穩的計算能力,無任何虛擬化開銷。阿里雲2019年8月重磅發佈了彈性計算第六代企業級實例,基於神龍架構對虛擬化能力進行了全面升級
- 基於阿里自研神龍芯片和全新的輕量化Hypervisor - 極大減少虛擬化性能開銷
- 基於阿里雲智能神龍芯片和全新的輕量化VMM,將大量傳統虛擬化功能卸載到專用硬件上,大大降低了虛擬化的性能開銷,同時用戶幾乎可以獲得所有的宿主機CPU和內存資源,提高整機和大規格實例的各項能力,尤其是I/O性能有了大幅度提升。
- 使用最新第二代英特爾至強可擴展處理器 - E2E性能提升
- 使用最新一代Intel Cascade Lake CPU, 突發主頻提升至3.2GHz, 各場景E2E性能大幅提升,並在深度學習的多種場景有數倍的提升。
- 給企業級場景帶來穩定和可預期的表現 - 全球最高水準SLA
- 針對軟硬件優化以及更加實施更細緻的QoS手段,給企業級客戶的負載提供更穩定可預期的性能。
ECS實例類型 | 第六代裸金屬實例 | 六代虛擬機實例 |
---|---|---|
CPU | 目前包含80/104兩種規格 | 2~104 |
CPU與內存配比 | 1:1.8 ~ 1:7.4 | 1:2 ~ 1:8 |
虛擬化資源開銷 | 沒有 | 極小 |
GPU支持 | 是 (部分型號) | 是 (部分型號) |
支持Intel SGX | 是 (部分型號) | 否 |
支持安全沙箱容器(如KataContainer, 阿里雲安全沙箱容器等) | 是 | 否 |
支持License綁定硬件 | 是 | 是 (DDH支持) |
支持熱遷移 | 否 (支持宕機遷移) | 是 |
一般而言建議:
- 對性能極其敏感的應用,如高性能計算,裸金屬實例是較好的選擇。
- 如果需要Intel SGX,或者安全沙箱等技術,裸金屬實例是不二選擇。
- 六代虛擬機實例基於神龍架構,I/O性能有了顯著提升,同時有更加豐富的規格配置,可以針對自身應用需求靈活選擇,降低資源成本。
- 虛擬機實例支持熱遷移,可以有效降低運維成本。
阿里雲ACK K8s集羣支持多個節點伸縮組(AutoScalingGroup),不同彈性伸縮組支持不同的實例規格。在工作實踐,我們會爲K8s集羣劃分靜態資源池和彈性資源池。通常而言,固定資源池可以根據需要選擇裸金屬或者虛擬機實例。彈性資源池建議根據應用負載使用合適規格的虛擬機實例來優化成本、避免浪費,提升彈性供給保障。
此外由於裸金屬實例一般CPU核數非常多,大規格實例在使用中的挑戰請參見下文。
較少的大規格實例還是較多的小規格實例?
一個引申的問題是,如何選擇實例規格?我們列表對比一下
較少的大規格實例 | 較多的小規格實例 | 備註 | |
---|---|---|---|
節點管理開銷 | 較低 | 較高 | |
操作系統額外開銷 | 較低 | 較高 | |
節點部署密度 | 較高 | 較低 | |
節點調度複雜性(如NUMA) | 較高 | 較低 | 部署密度增加之後,需要更加合理的資源調度來保障應用SLA |
節點穩定性 | 較低 | 較高 | 隨着部署密度增加,節點自身的穩定性也會隨之下降 |
節點失效爆炸半徑 | 較大 | 較小 | 一個大規格實例失效,會影響更多的應用容器。也需要預留更多的資源進行宕機遷移。 |
Master組件壓力 | 較小 | 較大 | Worker節點數量是影響Master節點容量規劃和穩定性的因素之一。K8s 1.13版本引入的NodeLease功能讓節點數量對master組件的壓力降低很多。 |
默認情況下,kubelet 使用 CFS 配額 來執行 pod 的 CPU 約束。當節點上運行了很多 CPU 密集的應用時,工作負載可能會遷移到不同的 CPU 核,工作負載的會受到 CPU 緩存親和性以及調度延遲的影響。當使用大規格實例類型時,節點的CPU數量較多,現有的Java,Golang等應用在多CPU共享的場景,性能會出現明顯下降。所有對於大規格實例,需要對CPU管理策略進行配置,利用CPU set進行資源分配。
此外一個重要的考慮因素就是NUMA支持。在NUMA開啓的裸金屬實例或者大規格實例上,如果處理不當,內存訪問吞吐可能會比優化方式降低了30%。Topology管理器可以開啓NUMA感知 https://kubernetes.io/docs/tasks/administer-cluster/topology-manager/ 。但是目前K8s對NUMA的支持比較簡單,還無法充分發揮NUMA的性能。
阿里雲容器服務提供了 CGroup Controller 可以更加靈活地對NUMA架構進行調度和重調度。
如何容器運行時?
Docker容器還是安全沙箱?
在 Sysdig 發佈的 2019 容器使用報告中,我們可以看到Docker容器佔據市場規模最大的容器運行時 (79%),containerd 是 Docker貢獻給CNCF社區的開源容器運行時,現在也佔據了一席之地,並且得到了廠商的廣泛支持;cri-o 是紅帽公司推出的支持OCI規範的面向K8s的輕量容器運行時,目前還處在初級階段。
很多同學都關心containerd與Docker的關係,以及是否containerd可以取代Docker?Docker Engine底層的容器生命週期管理也是基於containerd實現。但是Docker Engine包含了更多的開發者工具鏈,比如鏡像構建。也包含了Docker自己的日誌、存儲、網絡、Swarm編排等能力。此外,絕大多數容器生態廠商,如安全、監控、日誌、開發等對Docker Engine的支持比較完善,對containerd的支持也在逐漸補齊。所以在Kubernetes運行時環境,對安全和效率和定製化更加關注的用戶可以選擇containerd作爲容器運行時環境。對於大多數開發者,繼續使用Docker Engine作爲容器運行時也是一個不錯的選擇。
此外,傳統的Docker RunC容器與宿主機Linux共享內核,通過CGroup和namespace實現資源隔離。但是由於操作系統內核的攻擊面比較大,一旦惡意容器利用內核漏洞,可以影響整個宿主機上所有的容器。
越來越多企業客戶關注容器的安全性,爲了提升安全隔離,阿里雲和螞蟻金服團隊合作,引入安全沙箱容器技術。19年9月份我們發佈了基於輕量虛擬化技術的RunV安全沙箱。相比於RunC容器,每個RunV容器具有獨立內核,即使容器所屬內核被攻破,也不會影響其他容器,非常適合運行來自第三方不可信應用或者在多租戶場景下進行更好的安全隔離。
阿里雲安全沙箱容器有大量性能優化,可以達到90%的原生RunC性能
- 利用Terway CNI網絡插件,網絡性能無損。
- 利用DeviceMapper構建了⾼速、穩定的容器 Graph Driver
- 優化 FlexVolume 和 CSI Plugin,把 mount bind 的動作下沉到沙箱容器內,從而避開了 9pfs 帶來的性能損耗。
而且,ACK爲安全沙箱容器和和RunC容器提供了完全一致的用戶體驗,包括日誌、監控、彈性等。同時,ACK可以在一臺神龍裸金屬實例上同時混布RunC和RunV容器,用戶可以根據自己的業務特性自主選擇。
同時,我們也要看到安全沙箱容器還有一些侷限性,現有很多日誌、監控、安全等工具對獨立內核的安全沙箱支持不好,需要作爲sidecar部署在安全沙箱內部。
對於用戶而言,如果需要多租戶隔離的場景,可以採用安全沙箱配合network policy來完成,當然也可以讓不同租戶的應用運行在不同的虛擬機或者彈性容器實例上,利用虛擬化技術來進行隔離。
注意:安全沙箱目前只能運行在裸金屬實例上,當容器應用需要資源較少時成本比較高。可以參考下文的Serverless K8s有關內容。
如何規劃容器集羣?
一個大集羣還是一組小集羣?
在生產實踐中,大家經常問到的一個問題是我們公司應該選擇一個還是多個Kubernetes集羣。
Rob Hirschfeld在Twitter上做了一個調查,
- 一個大一統的的平臺,支持多種應用負載、環境和多租戶隔離
- 或者,一組以應用爲中心的小集羣,支持不同應用和環境的生命週期管理。
https://thenewstack.io/the-optimal-kubernetes-cluster-size-lets-look-at-the-data/
大多數的用戶選擇是後者,典型的場景是
- 開發、測試環境使用不同的集羣
- 不同的部門使用不同的集羣進行隔離
- 不同的應用使用不同的集羣
- 不同版本的K8s集羣
在用戶反饋中,採用以多個小集羣的主要原因在於爆炸半徑比較小,可以有效提升系統的可用性。同時通過集羣也可以比較好地進行資源隔離。管理、運維複雜性的增加是採用多個小集羣的一個不足之處,但是在公共雲上利用託管的K8s服務(比如阿里雲的ACK)創建和管理K8s集羣生命週期非常簡單,可以有效解決這個問題。
我們可以比較一下這兩種選擇
單一大集羣 | 多個應用爲中心集羣 | |
---|---|---|
爆炸半徑 | 大 | 小 |
硬多租(安全、資源強隔離) | 複雜 | 簡單 |
混合調度多種類型資源 (GPU等 ) | 複雜 | 簡單 |
集羣管理複雜性 | 較低 | 較高(自建)/較低(採用託管K8s服務) |
集羣生命週期的靈活性 | 困難 | 簡單(不同集羣可以有不同的版本和伸縮策略) |
規模化引入的複雜性 | 複雜 | 簡單 |
源自Google Borg的理念,Kubernetes的願景是成爲Data Center Operating System,而且Kubernetes也提供了RBAC、namespace等管理能力,支持多用戶共享一個集羣,並實現資源限制。 但是這些更多是 “軟多租” 能力,不能實現不同租戶之間的強隔離。在多租最佳實踐中,我們可以有如下的一些建議
- 數據平面:可以通過PSP (PodSecurityPolicy) 或者安全沙箱容器,提升容器的隔離性;利用 Network Policy 提升應用之間網絡隔離性;可以通過將nodes和namespace綁定在一起,來提升namespace之間資源的隔離。
- 控制平面:Kubernetes的控制平面包括master組件API Server, Scheduler, etcd等,系統addon如CoreDNS, Ingress Controller等,以及用戶的擴展,如3方的CRD (Customer Resource Definition) controller。這些組件大多不具備良好的租戶之間的安全、資源和故障隔離能力。一個錯誤的CRD contoller實現有可能打掛一個集羣的API Server。
關於Kubernetes多租戶實踐的具體信息可以參考下文。目前而言,Kubernetes對硬隔離的支持存在很多侷限性,同時社區也在積極探索一些方向,如阿里容器團隊的Virtual Cluster Proposal 可以提升隔離的支持,但是這些技術還未成熟。
另一個需要考慮的方案是Kubernetes自身的可擴展性,我們知道一個Kubernetes集羣的規模在保障穩定性的前提下受限於多個維度,一般而言Kubernetes集羣小於5000節點。當然,運行在阿里雲上還受限於雲產品的quota限制。阿里經濟體在Kubernetes規模化上有豐富的經驗,但是對於絕大多數客戶而言,是無法解決超大集羣的運維和定製化複雜性的。
對於公共雲客戶我們一般建議,針對業務場景建議選擇合適的集羣規模
- 對於跨地域(region)場景,採用多集羣策略,K8s集羣不應跨地域。我們可以利用CEN將不同地域的VPC打通。
- 對於強隔離場景,採用多集羣策略,不同安全域的應用部署在不同的集羣上。
- 對於應用隔離場景,比如SaaS化應用,可以採用單集羣方式支持多租,並加強安全隔離。
- 對於多個大規模應用,可以採用多集羣策略,比如,在線應用、AI訓練、實時計算等可以運行在不同的K8s集羣之上,一方面可以控制集羣規模,一方面可以針對應用負載選擇合適的節點規格和調度策略。
- 由於有VPC中節點、網絡資源的限制,我們可以甚至將不同的K8s集羣分別部署在不同的VPC,利用CEN實現網絡打通,這部分需要對網絡進行前期規劃。
如果需要對多個集羣的應用進行統一管理,有如下幾個考慮
- 利用Kubefed 構建集羣聯邦,ACK對集羣聯邦的支持可以參考 https://help.aliyun.com/document_detail/121653.html
- 利用統一的配置管理中心,比如GitOps方式來管理和運維應用 https://github.com/fluxcd/flux
另外利用託管服務網格服務ASM,可以利用Istio服務網格輕鬆實現對多個K8s集羣的應用的統一路由管理。
如何選擇K8s或者Serverless K8s集羣?
在所有的調查中,K8s的複雜性和缺乏相應的技能是阻礙K8s企業所採用的主要問題,在IDC中運維一個Kubernetes生產集羣還是非常具有挑戰的任務。阿里雲的Kubernetes服務ACK簡化了K8s集羣的生命週期管理,託管了集羣的master節點被,但是用戶依然要維護worker節點,比如進行升級安全補丁等,並根據自己的使用情況進行容量規劃。
針對K8s的運維複雜性挑戰,阿里雲推出了Serverless Kubernetes容器服務 ASK。
完全兼容現有K8s容器應用,但是所有容器基礎設施被阿里雲託管,用戶可以專注於自己的應用。它具備幾個特點
- 首先它按照容器應用實際消耗的資源付費,而不是按照預留的節點資源付費
- 對用戶而言沒有節點的概念,零維護
- 所有資源按需創建,無需任何容量規劃。
在ASK中,應用運行在彈性容器實例 - ECI (Elastic Container Instance)中,ECI基於輕量虛擬機提供的沙箱環境實現應用安全隔離,並且完全兼容Kubernetes Pod語義。在ASK中我們通過對Kubernetes做減法,將複雜性下沉到基礎設施,極大降低了運維管理負擔,提升用戶體驗,讓Kubernetes更簡單,讓開發者更加專注於應用自身。除了無需管理節點和Master外,我們將DNS, Ingress等能力通過阿里雲產品的原生能力來實現,提供了極簡但功能完備的Kubernetes應用運行環境。
Serverless Kubernetes極大降低了管理複雜性,而且其自身設計非常適合突發類應用負載,如CI/CD,批量計算等等。比如一個典型的在線教育客戶,根據教學需要按需部署教學應用,課程結束自動釋放資源,整體計算成本只有使用包月節點的 1/3。
在編排調度層,我們藉助了CNCF社區的Virtual-Kubelet,並對其進行了深度擴展。Virtual-Kubelet提供了一個抽象的控制器模型來模擬一個虛擬Kubernetes節點。當一個Pod被調度到虛擬節點上,控制器會利用ECI服務來創建一個ECI實例來運行Pod。
我們還可以將虛擬節點加入ACK K8s集羣,允許用戶靈活控制應用部署在普通節點上,還是虛擬節點上。
值得注意的是 ASK/ECI 是 nodeless 形態的pod,在K8s中有很多能力和node相關,比如NodePort等概念不支持,此外類似日誌、監控組件經常以DaemonSet的方式在K8s節點上部署,在ASK/ECI中需要將其轉化爲Sidecar。
用戶該如何選擇ACK和ASK呢?ACK主要面向的是基礎設施運維團隊,具備和K8s高度的兼容性和靈活性控制性。而ASK則是面向業務技術團隊或者開發者,用戶完全不需具備K8s的管理運維能力,即可管理和部署K8s應用。而ACK on ECI,則同時支持用戶負載運行在ECS實例或者ECI實例上,可以允許用戶進行靈活控制。
ACK on ECI/ASK則可以將彈性的負載通過ECI的方式運行,有幾個非常典型的場景:
- 應對突發流量:ECI基於面向容器的輕量安全沙箱,可以實現30s 500Pod的彈性伸縮能力,可以輕鬆應對突發的業務流量,在面對不確定的業務流量時,可以簡化彈性配置。
- 批量數據處理:我們可以實現Serverless Spark/Presto這樣的計算任務, 按需爲計算任務分配計算資源。
- 安全隔離:有些業務應用需要運行3方不可信應用,比如一個AI算法模型,ECI本身利用安全沙箱進行隔離,我們可以利用ECI隔離運行相關應用。
ACK on ECI還可以和Knative這樣的Serverless應用框架配合,開發領域相關的Serverless應用。
總結
合理規劃K8s集羣可以有效規避後續運維實踐中的穩定性問題,降低使用成本。期待與大家一起交流阿里雲上使用Kubernetes的實踐經驗。
原文鏈接: