Kubernetes 在網易雲中的落地優化實踐

本文來自網易雲社區前端


今天我跟你們講的是 Kubernetes 在網易的一些實踐,目的是拋磚引玉,看看你們在這個方向有沒有更好的實踐方法。簡單介紹一下網易雲。網易雲是從最先 Kubernetes 1.0 開始作起,後面 1.3 版本一直用了很長的時間。最近,對內部業務提供了 1.9 的版本。
後端


容器雲平臺架構安全


20180823102354808cfa62-0afe-45a4-9497-b33b3f6043cd.jpg


這是網易公有云的一個容器平臺架構,能夠簡單的分爲幾個部分。最底下的是基礎設施層。這個是由 laaS 來負責,在 laaS 以上,是容器和 Kubernetes 的調度層。由於 laaS 會去作其它的公共系統(好比認證、計費)。NCE(Netease Container Engine,容器引擎)這層服務,是容器和 Kubernetes 調度上面的一個抽象層,它上面是爲用戶提供前端的 Web 和 API 服務。
性能優化


咱們也是 Kubernetes 用戶,在爲用戶提供 Kubernetes 服務的同時,也在解決咱們的問題。在容器服務上,2016 年就已有幾十個業界知名的服務微服務的工具,一個是 Spring Cloud,一個是 Kubernetes。在咱們開發團隊中,也會去想用什麼樣的技術更適合咱們。Spring Cloud 和 Kubernetes 都是一個利器。它們面向的用戶和解決思路是不同的。Spring Cloud 更多的是面向開發者們,尤爲是 Java 開發者,他們是從代碼級別去考慮微服務是怎麼去設計的。開發者們須要去處理,好比註冊、環境配置怎麼拿到?對於他們來講,除了作業務開發,他還要關心一些業務以外的東西。網絡


Kubernetes 更可能是面向 DevOps,它是但願經過提供一個平臺,一個通用性的方案把微服務中間須要處理的細節放在平臺上解決。不用去關注服務發現和 DNS 這些東西,就好比說在 Spring Cloud 裏面的服務發現。你須要代碼去拿這些信息。
架構


可是在 Kubernetes 裏,你只須要去建立一個服務,而後訪問這個 Kubernetes 服務,你不用去關心後臺策略是怎麼作、服務是怎麼發現、請求是怎麼傳到後面的 Pod。因此它是從不一樣的層面去解決這個問題的。由於 Spring Cloud 和 Kubernetes,不是一個徹底對應的產品。做爲微服務的一些基礎要點,它們是有本身不一樣的解決方案。這裏是作了一個相對的比較。你會發現不管是 Spring Cloud,仍是 Kubernetes,其實都有他本身的方式去解決問題。
併發


Spring Cloud or Kubernetes?負載均衡


2018082310241637edab88-1027-448e-8cca-e103790a599f.jpg


咱們開發團隊作了一些調研,Kubernetes 加 Docker,咱們能夠比較好的解決部分問題。有一些問題 Kubernetes 本身能夠解決,但用起來不是很方便。還有一些只能用第三方工具,或者本身的方式來解決。好比說像監控,咱們就是用第三方工具。好比說 ELK 是用 Grafana 去作監控。分步式追蹤,咱們作了一個 APM 分佈步式追蹤。
運維


20180823102423c0976d71-7e15-4fbd-8913-c5bf378da30a.jpg


比較來看,若是作微服務,並非說我只選 Kubernetes,或是 Spring Cloud,而是把它們結合起來用,更能發揮他們各自的優點。再好比服務發現、負載均衡、高可用、調度、部署這部分,咱們是用 Kubernetes。好比故障隔離,咱們用 Hystrix 去作進程內隔離,可是作進程間隔離,是經過 Kubernetes 的資源配額去作。好比像配置問題,Docker 能解決應用和運行環境等問題。微服務


通常狀況,咱們會分爲開發環境、測試環境、預發佈和線上環境。不一樣的環境,它的配置是不同的。若是是用 Kubernetes ConfigMap,它不能實時生效,因此咱們用的 Disconf 配置中心。要把微服務作好,你要根據本身的實際狀況,去選擇適合的產品和技術,還要作一些基於第三方的開源工具和開發。


除了微服務這塊,在咱們本身的生產測試環境中,咱們也用到了親和性和反親和性的特性,好比說一個很常見的需求,當我有些關鍵的應用模塊須要去作儲備部署,我須要去測試。當主模塊壞掉後,咱們經過它的親和性去作,好比咱們用 Node 和 Pod 的親和性和反親和性去作,中間會給你一些表達式去匹配規則。


這裏面有兩種模式,一種是 Hard 模式,一種是 Soft 模式。Hard 模式是你必須知足個人要求,它還有一個特性,在調度期間,我必需要知足它的要求。若是我已經調度成功了,後面的標籤我沒有改動,仍是要讓 Pod 正常運行。Soft 模式,我若是知足你表達式匹配的資源,那我就優先知足你。若是沒有,那你按照調度器的分配繼續進行下去。


在咱們的環境裏,對 Node 打標籤。好比說有兩臺,一臺是 ci1,一臺是 ci2,在文件中進行配置。好比一個節點,它能夠是 ci1 或者 ci2,它把 Pod 調度到 Node 上,可是這兩個應用跟儲備又不能在一塊兒,它們必需要分開。咱們在應用名字設置了一個 Pod 反親和性。若是發現這個 Pod 已經在一臺上,那它只能被調動到另外一臺上。咱們能夠用一樣的一個配置去部署這樣一個應用,不須要去分兩個配置。並且咱們不須要去管底層的 Node 資源是怎麼樣的,或者說咱們要靠其它的一些靈活方式去作反親和性配置。


網易雲有一個現存的監控系統。它對於數據的要求,有一些規範。咱們專門作了一個 Agent。這個 Agent,就是爲了它從 cAdvisor 上挖數據,上報給監控系統。一方面,社區對模塊是有更新的,咱們不想對它有新動做。若是你作了本身的邏輯在裏面,而社區更新了,在此以後就很難處理這件事。咱們想把社區和咱們制定一些東西,或者說咱們跟內部其它系統去作的相關適配,能夠去解耦。


經過 cAdvisor,作一個 DaemonSet。咱們在每個節點上,都會部署一個 Agent,它會去拉 cAdvisor 的數據。若是 Agent 在後面社區版本里進行了數據更新。咱們只須要作一些相對應的適配,從新更新與部署。對咱們來講,維護會很是簡單。另一個,咱們的外部客戶可能會有些非社區原生的需求。


好比說他要在界面上作保存鏡像的操做。這些非原生的需求,咱們會在 Node 端有一個容器服務的 Agent,它去監控這些命令。若是是這些非原生的需求,是由 Agent 來處理。咱們就能夠看到,DaemonSet 能夠簡化一些部署的難度。在特定的場景下,它能夠在個人集羣裏,對全部的 Node,或是部分的 Node 部署一個 Agent。


若是你更新且把鏡像從新作好,從新拉一個鏡像就能夠。因此說很是適合這種相似於獲取日誌,長期在 Node 上作工做的事情。並且,它能夠把一些定製化需求和社區原生需求解耦,這樣既能跟上社區更新,又能夠根據本身的系統和業務產品,去作一些特別的適配。


由於網易雲自己提供有關 Node/PV 的服務,因此在這一塊又和私有云有點不同。由於像社區原生的 Kubernetes,它更多的是面向私有云市場。像不少公有云廠商,提供的 Kubernetes 服務,也是用戶申請後,它給你一套完整的 Kubernetes 集羣。這個集羣是由用戶本身來維護的。


可是網易雲目前所提供的 Kubernetes 服務,有點像 AWS 的 Fargate 的模式,全部租戶都在這整個公有云中,都是在同一個 Kubernetes 集羣下管理。租戶是對 Kubernetes 沒有訪問權限的,他只能訪問平臺暴露出來的,好比 Deployment、Service、Ingress、Statefulset、Endpoint 等對象,用戶只能使用這些資源。


K8S 公有云實踐


2018082310243249b4550e-df68-4fd8-a328-ad907a4ba941.jpg


公有云和私有云的場景存在不一樣。私有云沒有足夠的概念。在企業內部,只是不一樣部門或者不一樣項目,可是資源多是全局可見的。但在公有云上就不同。由於公有云是有租戶的,我匹配的這些資源不是全局共享的,由於你不用關心這種安全性問題。可是在公有云上,用戶不少,租戶不少,租戶之間不須要去作隔離。


2018082310244002028288-e7aa-4534-9146-d8f123dfd1e5.jpg


咱們的容器平臺和底層的 laaS 層是作耦合。它不是原生的 Kubernetes 形態,像主機,咱們是由 laaS 提供一個虛擬型或尾機給容器作一個 Node。硬盤,咱們是由 laaS 層存儲一個後端硬盤,網絡是經過 VPC 網絡,因此說租戶與租戶之間是隔離的。


咱們之前的版本是一對一的,到了新的版本後每一個租戶能夠去建立多個 Namespace。像認證、受權、也是在租戶這邊安排。還有一個像 Kubernetes ,它的 Node 資源,是預分配的,你在建立集羣時,就要提早把這些 Node 資源準備好,它才能夠調度。可是這個場景在公有云就不合適。由於你沒法預估用戶須要多少資源,沒辦法根據這個去部署。


若是你部署多了會浪費。你部署少了,資源可能就不夠。咱們想的一種辦法就是用相似於半實時的預備資源方式。它不徹底是你申請時纔給你建立的一個 Node。若是是這樣,對用戶來講,體驗會很差。因此咱們的辦法就是提早準備一個資源池,把臨時的 Node 建立出來後不給它聯網。它在臨時資源池裏,咱們會維持一個水平。


此時若是一個用戶,他申請了資源,咱們就把建立好的 Node 作初始化,放在這個租戶的 VPC 網絡裏。把信息給到他,他就能夠去作第二步。一方面,咱們不須要去預備更強大的資源;另外一方面,咱們在用戶申請時,時間響應會少一些。


當用戶把資源池裏的 Node 請求消費了一部分,咱們會根據消耗水平在後臺補一些新的資源,它通常會維持這麼一個規模。在通常狀況下,沒有特別多的高併發,或者說在不少大規模部署狀況下,咱們是能減小用戶的等待時間又不會佔用太多的底層資源,這是咱們對這塊的一個處理方式。


爲何要作系統優化呢?有這幾個方面的緣由。最核心的是爲了省錢,網易雲鬚要支撐不少內部業務,每一個業務都會有本身的一套資源羣,而作高可用功能會佔用不少資源。因此咱們但願有可以管理全部租戶的資源。面向用戶的產品,也須要這樣的需求。因此說咱們面向多個團體,必需要保證當客戶有具體的資源申請時,性能能夠知足用戶需求。


社區從 1.0 的 100 個 Node 到 1.6 的 5000 個 Node。雖然數量已經增長了不少但可能還不夠。咱們是但願一個集羣能作到 3 萬個 Node,因此咱們在這裏作了不少東西。但在 Kubernetes 的架構裏,它全部的請求都是經過 API Server,而後去作一些查詢、訪問,再到 etcd 作產品。etcd 就是一個瓶頸,並且 etcd 自己比較缺乏水平擴展能力,因此須要作一些優化。


當你規模加大後,在你作一些規則時就會碰到一些基本問題。咱們是在 Controller 端,作一個本身的 Controller。它是和咱們剛纔說的 laaS 服務作一些交互,申請一個 Node,把網絡打造在 Node 上,去建立 Pod。咱們在前面又放了一層 HAProxy,作一些負載均衡。


K8S 性能優化


20180823102451a00b9a18-28a3-48eb-8986-805a1c373279.jpg


舉個例子,若是你是社區原生方式,好比說你有 1 萬個 Node,就能夠建立 1 萬個 Service,由於它是全局的能夠互訪,當你建立的規則是一萬乘一萬時,每一個節點都會有這麼多的規則。可想而知,你的性能就會不好。


對於公有云來講,由於咱們是作租戶隔離,因此說它不須要把全部的規則在每一個 Node 上都去設一遍。由於個人租戶是一個 VPC,須要在這個 VPC 上設用戶本身的規則。我不用去設置別的租戶 Node 上的規則。在每一個租戶裏,他的 Node 規則不多。即便你再次設置規則也沒有關係。


在後端存儲,咱們也是對 etcd 集羣,就像 MySQL 同樣,作相似分庫的部署。咱們會根據不一樣的對象、Node、RS、Pod,不一樣對象去分不一樣的多個 etcd 集羣,減輕單個 etcd 集羣的壓力。其它作了一些調優,好比底層,咱們用了 SSD,去作一些快照。在以前咱們也考慮過是否有其它更好的 KV 存儲方式,後來從 etcd 2 到 3 後,在性能上解決了很多問題,尤爲是 etcd 3,它批量的消息推送效率比之前 2 版本要高了不少。


好比說底層的網絡,咱們的 laaS 層網絡是基於 OVS+vxlan 作的,而沒有用 Calico 等業界的一些方案,網絡上,咱們要提供 VPC 的安全隔離;性能上,咱們測試下來的網絡優化,也比一些開源的方式好一些。因此咱們把這部分放到雲底層去作。咱們的容器平臺,不須要關心底層是什麼樣,它只須要對接這些網絡層,至關於接口。它須要申請資源,申請下來就能夠了。


結語


以上這些是當前網易雲對 Kubernetes 的一些實踐和體會,隨着用戶愈來愈多的瞭解 Kubernetes 和容器技術所帶來的好處,以及這些技術和生態的更新和演進,將來 Kubernetes 和容器也會有愈來愈多的潛力被開發出來。


20180823102500940fcf2f-d999-4ecf-b964-cd0480e9bc29.jpg




張亮 / 網易雲解決方案架構師


從事網易雲基礎服務解決方案工做。多年企業基礎架構、虛擬化項目設計、部署和運維經驗,瞭解企業 IT 面對的問題。目前主要關注如何經過容器、IaaS、PaaS 等技術和解決方案解決實際問題,幫助企業從傳統 IT 架構向雲演進、並更好的利用雲帶來的益處來促進核心業務發展。





網易雲計算基礎服務深度整合了 IaaS、PaaS 及容器技術,提供彈性計算、DevOps 工具鏈及微服務基礎設施等服務,幫助企業解決 IT、架構及運維等問題,使企業更聚焦於業務,是新一代的雲計算平臺。點擊可免費試用

 

網易雲新用戶大禮包:https://www.163yun.com/gift