1. 程式人生 > >魅族容器雲平臺基於k8s的自動化運維實踐

魅族容器雲平臺基於k8s的自動化運維實踐

作者簡介

曾彬

阿里巴巴 高階技術專家

網際網路老兵,十多年的基礎架構經驗,曾在支付寶、愛立信、魅族等擔任系統架構師,從事過 Linux 核心開發,Java 中介軟體、SOA 應用框架的設計實現、雲平臺設計實現等工作,技術涉獵廣,在非功能性基礎架構與實施,效能調優等方面經驗豐富,曾整體負責魅族雲平臺的架構設計與實現及運維工作。

前言

魅族容器雲平臺主要是基於 k8s 的技術。將從以下六個方面介紹魅族容器雲的實踐過程,分別是基本介紹、k8s 叢集、容器網路、外部訪問4/7層負載均衡、監控/告警/日誌、業務釋出/映象/多機房。

1、基本介紹

魅族雲平臺的定位是私有云平臺,主要是用於支撐線上業務,用以替換傳統的虛擬化方式。目前現狀是2017年完成全國三個資料中心的建設,年內完成90%業務的遷移。

我們是以小團隊緊跟 k8s 社群步伐,快速迭代、低成本試錯的方式來構建我們的平臺的。同時,針對一些我們遇到的問題,做一些區域性創新,在保證系統核心的隨社群穩定升級的前提下,解決好非功能性問題。

魅族

2、k8s 叢集

對於 k8s 叢集構建,將從 k8s 的單一映象、k8s 叢集 master、minion 三個方面分別展開介紹。

2.1 單一映象

k8s 叢集

k8s 叢集的安裝部署是利用單一映象 + docker run 實現一鍵安裝。為此將所有 k8s 相關的描述檔案、指令碼和二進位制全部打包成映象,目的是實現叢集的快速部署和升級。

2.2 Master

Master

為了能夠實現自動載入,k8s 叢集核心元件使用了 Static Pod 方式。在自動修復方面,kubelet probe 可以實現 Pod 的自檢,配置了自動重啟。如果需要對核心元件進行升級,指定統一映象的版本號即可實現核心元件升級更新。

k8s 叢集

controller manager 和 scheduler 服務在三臺物理機實現叢集 master 高可用。API Server 的高可用既可以通過負載均衡方式實現,也能通過 DNS 方式實現。

叢集 controller mananger 重啟可能會出現 Node 狀態不同步的問題,因此對於核心元件狀態,需要配置告警並及時檢查有無異常狀態。

2.3 minion

硬體方面並沒有固定的配置,儘量利用現有的資源。在我們的叢集中,常見 minion 的配置是 24核 CPU(with ht)、128GB 記憶體以及千兆網絡卡。

 minion

k8s 叢集中 minion 作為計算節點,其上主要是各種業務的容器和 Systempods。

對於 minion 節點做了三個方面引數的優化,中斷相關、TCPbacklog 和 swap。

minion

minion 節點作業系統使用的是 centos 7,docker storage 使用的 devicemapper driver,日誌基本寫到外掛的 EmptyDir volume,docker 儲存使用得很少。

我們為 EmptyDir Volume 專門開闢了普通分割槽,沒有使用 lvm,因為日誌量不好預估,遭遇過因為 lvm metadata 的事故。

使用 Device Mapper 還遭遇過 kernel issue,因此需要更新核心。

預設核心是3.10版本,長期維護的核心版本的是我們需要的。而且考慮到要對某些核心模組做 hacking,4.0及以上變化較大,hackingtcp_v4_syn_recv_sock 存在問題,所以我們最終選擇了自行編譯 3.16核心。

考慮到和 CMDB 的結合,minion 節點打上了 Label,例如標記它的功能是什麼,物理位置資訊,機櫃等。這些資訊對於 Pod 排程非常重要。包括 Pod 的 Node 親和性,Pod 親和性和反親和性。

3、容器網路

容器網路

容器網路的方面我們採用的是 calico 的方案。主機通過 BGP 直接和核心路由裝置對接,這裡也可以用 RouteReflector 替代。

控制層面走 BGP,資料層面走三層路由。網路封包會經過主機的 netfilter框架,最後經由主機 forward chain 進入容器,預設都會被 conntrack。部署方面,Calico 通過 k8s 的 Daemonset 方式,部署非常方便

優化

優化主要是針對 conntrack,建議儘量使用 headless service,少產生 iptables rule。同時,對 conntrack 用量進行監控。容錯方面,容器會主動去  ping 交換機,確保網路的連通性。當 calico 出現問題的時候,容器是不會加入服務的,由此來保證服務的可靠性。

對於我們系統,絕大部分流量來自外部 LVS,其可信任度高,預設的方式會產生大量的 conntrack 記錄,所以應當把 LVS 過來的流量直接給 bypass conntrack。

mesh

經過生產實踐效果驗證,no mesh 模式的穩定性要優於 mesh 模式。異常處理主要分為 POD 主動檢測網路和 calico 的整體健康監控告警。

4、外部訪問4/7層負載均衡

我們做的是對外服務,大部分流量都是從外部打進來的,終端使用者都是外部的客戶,所以針對外部的訪問做了4層和7層的負載均衡。我們做的是對外服務,大部分流量都是從外部打進來的,終端使用者都是外部的客戶,所以針對外部的訪問做了4層和7層的負載均衡。

4.1 4層負載均衡

開源

在4層接入上採用了是阿里開源的 Fullnat LVS 方案,看中了它運維方便、水平擴充套件性好。工作在4層的 LVS 服務既可以支援 TCP 同時也支援  UDP,流量從client 端經過 LVS 做 Fullnat 後到達 minion,應答直接路由回對應的LVS。

配置

對於4層負載均衡的配置,是通過自動化方式來實現的,無需人工配置,可以自動在路由裝置宣告 vip,並生成對應的 ECMP 路由。LVS 的 VirtualServer 配置也是自動生成的,VirtualServer 到 EndPoint ip 的自動對映。

流量採集

我們對 LVS 控制程式做了改造,暴露了一些指標,包括網路和應用服務相關的資料,並以此實現了 Grafana 視覺化和監控告警。

監控告警

一方面是對 LVS 整體流量異常告警,另一方面 realserver (Pod) 做高延遲異常檢測告警。

4.2 7層負載均衡

Jetty

七層負載均衡採用的是 POD 裡面跑 nginx+ingress controller,它的定位是業務專屬的反向代理,能夠實現自動擴縮容,面向的 upstream 主要是  Jetty 業務容器。

由於四層負載均衡採用的是 FullnatLVS,真正的終端 ip 地址已經被隱藏起來了,需要從 TCPoption 中獲取。realserver 預設取到的是 LVS 的 local ip 地址,需要使用 TOA 模組來獲取終端 ip。

開源版本的 TOA 一直沒有升級,為此我們將其移植到 3.16,對於大多數業務來說,客戶端 ip 地址是不可或缺的。

 nginx

在把 nginx 容器化之後,踩了一些坑,其中一個是延遲過高。從 access.log 看,upstream 的 RT 時間長達幾秒,而直接訪問 upstream Pod 服務又是很快的,說明是 nginx 的問題。經分析後發現配置不合理,nginx 容器化之後缺少對 worker 數量和親和性的優化。

按照預設配置,一臺24核 CPU 的機器上,對於一個業務的 nginx,自動配置為 24個 worker 程序,而 cpu limit 往往只設置成 5、6個核,worker 沒有 cpu 資源導致高延遲。同時,調整 worker 程序的親和性,防止壓力堆積在前幾個核上。

Nginx 動態縮容

Nginx 動態縮容需考慮柔性,比如某業務原來有3個 Nginx 容器,現在要縮成2個,被停掉這個 Nginx 容器需要做一些優雅退出的準備工作,否則可能導致服務整體響應延遲陡增。

這個 POD 一開始就從 LB 上被摘掉了,我們利用 Pod 的 prestop hook,等待並優雅退出。

擴容時,需要考慮啟動時間和熱身問題。有的業務可能需要幾秒或幾十秒,要有充足的初始化時間,否則,請求過去就會失敗。

如果 Probe Timeout 設定得比較小,會導致 Pod 被強制重啟或者摘除,導致整體服務的雪崩。在實際執行過程中,應根據監控情況對 CPU request 和 Hpa 配置持續優化。

5、監控/告警/日誌

監控

監控採用的是 prometheus,開箱即用的整體方案。部署方面是在 k8s 上部署成 Daemonsets 或者 Deployment,針對其特點會排程到特定的機型,通過型別拆分成幾種 map 來方便管理。

監控指標包括兩個方面,一個是硬指標,例如,從 nginx 獲取當前業務的qps、http code 分佈、當前整個業務的資源消耗情況以及後端的 jetty 消耗情況。

logger

另一方面是業務的軟指標,指的是內部指標,主要包括 jvm 的指標,內部的logger 相關,如 error 計數器。

日誌

日誌的處理是收集到 elasticsearch 處理的。ES 的部署和 prometheus 類似也是 POD 的方式。部署 ES 的 datanode、master 和 client 需要關注執行緒資料和 CPU limit 的匹配問題。

日誌收集

日誌收集容器試過使用 fluentd 進行收集,與業務容器共享一個儲存,發現有日誌滯後和資源消耗高的問題。用 filebeat 容器替代 fluentd 之後,資源佔用率很小,消耗不到0.1核、記憶體不到 100M 就可以實現比較好的日誌傳輸效果。

6、業務釋出/映象/多機房

業務釋出

業務釋出考慮到效率和互動性,需要給使用者提供一個互動介面,能夠生成 k8s的資源描述檔案,並能執行具體的 Action,如建立/更新/刪除。

業務部署

實現上是通過 json schema 的方式來描述所有引數,預設值+結合使用者輸入最終生成 k8s 的資源描述檔案。

自動化部署

利用 ansible 呼叫 kubectl 來實現自動化部署。實現了部署進度,釋出歷史管理,模板化部署。對於多叢集管理,ansible 通過切換不同 k8s 叢集的 context,釋出業務到不同機房。

映象

對於映象的選擇我們的原則就是夠小、夠用,為了保證相容性我們加入 glibc 支援。Docker 其實推薦只跑一個程序,但很多業務都是需要多個程序配合的,S6 用於應對這種場景,作為程序和服務的管理器來實現一些比較複雜的功能。

總的來說,這是一套低成本的私有云實現方案,核心部分持續享受到 k8s 的紅利,可以集中力量解決 4/7 層負載均衡及一些非功能性問題。同時,利用k8s核心系統的能力,快速構建外部支撐系統,如監控、告警、日誌、釋出系統等,在很大程度上提高了效率和可維護性。

文章來自微信公眾號:高效運維