歡迎光臨
每天分享高質量文章

得到App的容器及Kubernetes實踐

得到App是較早踐行微服務架構設計的技術團隊,眾所周知,微服務帶來最大的挑戰是管理和運維。從2017年初開始調研,經歷VM、Swarm、Kubernetes的兩次變遷,到現在已經有兩年的時間,目前容器平臺運行了約70%的服務,支撐了約80%的流量。本次分享將圍繞降低容器和Kubernetes使用門檻、專案標準化和容器設施的易用性展開,希望我們的經驗對有計劃使用Kubernetes和打算將服務容器化的企業有所幫助。
羅輯思維作為一家創業公司,產品得到App的後端服務目前主要執行在阿裡雲。由於技術選型比較“激進”,並且踐行微服務架構設計,目前的語言棧按照佔比排名有:Golang、Node.js、Python、Java、PHP、C++,之前使用雲主機(ECS)帶來的執行環境管理複雜、釋出過程不統一等問題。所以,將應用容器化以及微服務治理,一直是較為迫切的需求。
從2013年底Docker開源,到現在已經發展了超過5年的時間,大家已經聽說容器技術的優勢和收益並逐漸接受準備擁抱之。但想要落地容器以及容器管理系統Kubernetes這種新一代基礎設施,遠沒有想象中容易,在新技術落地的過程中,阻礙往往不是來自於技術本身,而在於觀唸的更新、生態的豐富以及易用性。

 

容器技術的應用

想要落地容器技術,首先是標的的確立,類似“把大象放進冰箱”分為三步:開啟冰箱,放進大象,關上冰箱。我們將容器技術落地的標的也簡化為三步:程式碼映象化,容器化部署,微服務治理。
其次離不開大量的內部推廣、佈道,以及不厭其煩的各種支援,這對運維團隊的要求很高,需要有人能夠對程式語言棧和容器技術以及運維工具有較深瞭解,才能打通整個流程。在概念層面簡單化,在內部我們統一將容器類比為“行程”,Kubernetes類比為管理行程的“作業系統”,工具平臺簡單易用,使開發人員只關註業務。
最後由運維牽頭,開發協助,制定出一系列規範和流程,階段性總結和周知,收集反饋、改進工具,總而言之,微服務治理,是一個從上到下的系統工程。
目前狀態
目前得到App的主要執行環境是Docker + Kubernetes,包括測試(聯調等)、預釋出、線上幾個環境。少量不適合容器化和歷史專案執行在ECS(雲主機)中。約70%專案和80%流量已經執行在Kubernetes管理的容器中,還有Swarm叢集也在執行服務,即將結束的2019年Q1完成全面落地Kubernetes,到時候下線Swarm叢集。
里程碑
回顧容器在得到App落地的過程,有幾個關鍵的時間節點,希望能對大家評估落地時間有所幫助。
  • 2017年3月,立項

  • 2017年5月,Swarm叢集方案

  • 2017年8月,配套建設,開始小範圍業務遷移

  • 2017年11月,商城業務完成遷移,經歷高併發考驗

  • 2018年3月,調研Kubernetes

  • 2018年5月,Kubernetes設計方案

  • 2018年8月,圍繞Kubernetes配套建設,開始小範圍業務遷移

  • 2018年11月,部分業務遷移,經歷高併發考驗 2019年3月,完成落地

因2015下半年到2016年期間以Docker為首的容器技術火爆,我們在2016下半年進行前期關註,2017年初開始立項,2017年5月份完成基於Swarm的容器管理方案設計,2017年8月份完成叢集及周邊建設、釋出系統初版開發,開始小範圍業務遷移,2017年11月份完成商城業務的遷移,經歷了全鏈路壓測和跨年活動的考驗。2018年3月份開始調研Kubernetes,5月份完成設計方案,8月份完成叢集搭建和新釋出系統初版開發,開始小範圍業務遷移,11月份完成部分業務遷移,經歷全鏈路壓測和跨年活動的考驗,即將結束的2019年Q1將完成全部專案遷移工作。
前置條件
這裡簡單羅列了一下前置的規範制定:
  • 統一各語言執行時版本(建議最多3個),彙總各種模組串列

  • 統一base映象作業系統發行版、版本、彙總預設安裝的常用工具

  • 制定命名規範,使用能夠描述專案用途的名字,域名≈專案名=釋出系統內名字

  • 映象分3層:OS、runtime、code

  • 編寫OS、runtime的base image

  • 編寫Dockerfile和entrypoint模板

  • 框架中提供探活API,Liveness、Readiness、Graceful Shutdown等

  • 統一日誌格式,建議access日誌為單行json,相對Nginx或httpd預設的空格分割欄位方式,欄位較容易擴充套件,反序列化友好,並且能夠支援命令列工具分析。

  • 服務分級,對專案根據重要程度和影響面進行分級,不同級別服務的釋出流程、SLA要求各不相同。

有了這些前提條件的加持,後續容器落地效率會有很大提升。

 

技術方案

架構
從2018年起,得到App的技術團隊對於微服務治理和DevOps推進做了大量工作,產出了很多工具,右上角的Tools矩陣,大部分是2018年誕生的,目前看已經有了很大的成績。
Kubernetes在底層基礎設施跟上層微服務治理工具中間,起到了承接作用。
網路
網路元件使用Flannel + alivpc Backend,目前我們的服務全在阿裡雲VPC網路,該方案設計簡潔,比較穩定,透過寫入vRouter路由表方式,來達成容器網路與ECS網路對等,實現了容器IP與ECS IP互通。
服務治理
  • Artemis框架

  • 服務發現

  • APM(tracing)

  • API Gateway

對於服務治理,我們是在2018年初啟動,這方面我們的思路是:用規範和約定來將程式設計框架和基礎設施打通、應用以程式設計框架的形式連線基礎設施。
自研的框架Artemis,集成了服務註冊和配置中心以及tracing功能。
服務發現和配置儲存使用Consul,每個容器中主服務行程啟動前會啟動一個Agent,該Agent會將IP地址及模組資訊註冊到服務發現中心,並跟Consul保持心跳,Agent啟動時會拉取全量資料並快取到本地,同時接受服務發現中心的push。當容器掛掉時,由Consul的監控程式進行剔除,但容器主動退出時,Artemis框架會捕獲SIGNTERM、SIGNKILL、SIGNQUIT訊號,透過Agent進行服務登出。服務間所有呼叫需要經過本地的Agent,使用IP直連的方式,多實體的負載均衡也在本地的Agent中實現。
API Gateway基於服務發現服務發現中心的資料,進行後端實體的註冊。
APM作為鏈路追蹤、問題分析的首要工具,給開發人員提供便捷的排障支援。
配置管理
兩部分:配置中心,配置檔案
對於配置,沒有使用ConfigMap來存放應用配置,因為目前正在推進配置中心,現狀是配置檔案和配置中心共存的方式,應用啟動時預設去配置中心查詢,查詢失敗時會降級使用專案程式碼中的配置檔案。使用配置中心的方式,切換不同環境的配置檔案較為靈活,對於配置檔案方式,不同環境的配置檔案透過entrypoint.sh切換,entrypoint.sh指令碼中接收RUN_ENV變數,啟用(mv、cp)配置檔案。
服務間呼叫
  • DDNS(自研服務發現,容器間直接IP呼叫)

  • Service(LoadBalancer)阿裡雲SLB(作為降級方案)

  • Ingress(未接入DDNS的)

服務間呼叫,目前得到App內部正在落地服務發現,未來較多的是Pod間直接IP:Port呼叫;LoadBalancer型別的Service作為服務發現的降級方案使用;Ingress主要作為節省LoadBalancer資源,以及除錯和測試環境使用。
Ingress
Ingress Controller Backend,對比了Nginx、HAProxy、Traefik等方案,最後選擇了Nginx,原因是:穩定、效能好,支援協議多(TCP、UDP、HTTP、HTTP2),運維人員熟悉。
部署方式是:每個生產叢集配置3臺低配節點(4核8GB),透過nodeSelector或者taint功能,使Nginx獨享節點,跟應用節點資源隔離。
Nginx Ingress Controller缺點是設計較為複雜,分為3層:Golang、Nginx Lua,較難定製和修改。
雖然Traefik相較Nginx Ingress Controller設計簡單不少,並且是Golang開發,易於二次開發,但透過壓力測試結果來看,在資源管理上,跟Nginx差距很大。
Nginx可以使用split_clients模組進行灰度釋出(Canary Deployment)。
監控方案
  • Prometheus

  • AlertManager

  • cAdvisor

  • Node-exporter

  • Kube-state-metrics

  • Geb(自研)

得到App的Prometheus是部署在獨立的伺服器,以執行在Kubernetes叢集外部的方式,透過APIServer獲取資源資訊,然後進行metrics pull。使用了Node-exporter,Kube-state-metrics,以及自研的收集程式Geb,來匯出不同維度的度數。使用Grafana做監控資料展示,展示維度有Pod、Deployment、Node、Cluster、大盤。
當資料量大、查詢較慢時,可使用Prometheus alert中的record陳述句,進行資料預處理,即將查詢產生的結果存入新的metrics,使用新metric繪製圖表和報警的rules檢查,速度會有較大提升。
觸發閾值後發往AlertManager,在AlertManager中根據不同的級別對告警進行路由、沉默和收斂。
通知通道有:郵件、企業微信、簡訊。
Prometheus
目前的監控項有:
  • Ingress中的url探活

  • CPU、記憶體、load

  • TCP連線數

  • 檔案描述符

  • nf_conntrack

部分監控資料收集使用了Prometheus push gateway,此種方式可以將程式中的實時資料發給push gateway,然後由Prometheus進行收集、儲存。圖中的Geb為開發的監控Agent,目前主要收集容器中的網路連線資料。
日誌方案
  • ILogTail

  • 阿裡雲日誌服務

  • Filebeat

  • Kafka

  • ElasticSearch

由於自建的日誌系統需要較多伺服器資源,後續要花費很多精力去最佳化,考慮到投入產出比,使用阿裡雲日誌服務(SLS)比較有優勢,目前我們容器內產生的日誌都是使用ILogTail收集發往SLS,使用阿裡雲監控的日誌關鍵字監控功能監控錯誤日誌中的特定關鍵字。
Filebeat目前只負責收集APM產生的Trace日誌,發往Kafka,由日誌處理程式來進行消費,處理後序列化到ElasticSearch。
日誌收集
  • DaemonSet

  • 持久化stdout日誌

  • Pod更新後刪除原始日誌檔案

  • 日誌收集Agent使用HostPath

Pod使用EmptyDir易失性儲存方式,將日誌寫入磁碟,filebeat和ilogtail透過HostPath掛載形式收集,以DaemonSet方式部署,每個Worker節點上部署一個Agent。
釋出系統演進

  • up(Git)

  • Dozer(Swarm)

  • Chons(Kubernetes)

得到App創立初期,運維同學編寫shell指令碼(rsync等工具)進行釋出。後來引入開源專案walle(瓦力)釋出系統,使得釋出不再需要運維人員參與,並且引入了釋出審核機制,大大提高了釋出效率。進入容器化時代後,圍繞Docker Swarm和阿裡雲資源開發了Dozer系統以及新一代圍繞Kubernetes、支援CI/CD的Chons平臺。
up
  • 開源專案walle 1.x

  • Git SSH

  • Git Hooks

  • 從shell指令碼時代進入工具時代

  • 需要手工管理的節點IP和ssh key

  • 難於除錯、排錯

up釋出系統,基於開源釋出系統walle(瓦力)二次開發,其核心是圍繞Git Hook。每個專案需要運維人員和開發人員協作,須經歷購買伺服器,初始化伺服器環境,專案發版配置,除錯部署過程指令碼幾個步驟,較為繁瑣。並且釋出過程除錯較難。作為第一代發版系統,雖然有一些問題,但一直服役到現在,管理少量使用ECS的服務釋出。
Dozer
  • GitLab

  • Jenkins

  • Docker Swarm

  • Docker Registry

  • 阿裡雲監控

  • 阿裡雲日誌服務

  • 阿裡雲LoadBalancer

  • 阿裡雲OpenAPI(節點管理)

Dozer是基於Docker Swarm叢集API的容器發版系統,其底層是阿裡雲容器服務全家桶,上層根據釋出流程和規範開發了相關功能。
使用的元件有GitLab(程式碼管理),Jenkins(呼叫其API進行docker build,並回呼Dozer),Swarm API(釋出、調整容器數量等核心功能),阿裡雲監控(容器監控)、阿裡雲日誌服務(日誌收集 儲存 分析)、阿裡雲SLB(多容器實體的匯聚和負載均衡)、阿裡雲OpenAPI(新增叢集Worker節點)。
該方案的優點是:簡單,快速,較為穩定,有容器底層技術的支援,可以將精力投在內部的落地上。缺點也是明顯的,即限制較多,強依賴阿裡雲,有時候業務的需求由於阿裡雲暫未開放相關功能,不得不進行取捨。
Dozer介面(服務詳情)
  • 打包、釋出

  • 調整實體數

  • 重啟容器

  • 進入容器

  • 監控連結

  • 日誌連結

  • 系統事件

Dozer的服務詳情頁面,比較簡陋,基本上是一些連結的入口頁面,但在容器落地的第一個階段支撐了幾乎所有需求,目前隨著Swarm叢集即將下線,它也即將停用。
Chons平臺
  • 內部PaaS

  • 註重易用性

  • 開發人員工作中必用的系統

  • 構建、釋出、監控、日誌

  • 遮蔽Kubernetes中的概念,但又對Manifes有所展現

  • 抽象出Stack和Component概念

Chons專案,設計之初,標的就是一款私有容器雲產品,它的競爭對手是業內容器雲公司的產品。在開發迭代過程中廣泛借鑒了各個產品的優點,避免它們的缺點。
它定位是:開發人員在工作中必須使用的系統,資源申請、開發、問題排查,Chons都是第一入口。
在易用性方面,遮蔽了Kubernetes中的各種概念,簡化為兩個概念Stack和Component。不給使用者造成困擾,開發人員只關註Coding、監控資料和日誌。
同時對Manifests有所展現,給希望瞭解Kubernetes的使用者檢視。
 
Stack
  • 一套環境

  • 一整套獨立的服務棧

  • 每個人可以建立

  • 可以多套共存

  • 基於namespace

  • 版本化管理,可以複製、匯出、匯入

 
Component
  • 一個服務

  • Deployment或StatefulSet

  • Service

  • Ingress

  • 彈性伸縮 HPA(未來)

  • 資源配額

  • 域名

  • 日誌倉庫

  • 監控項

雖然Chons的設計支援一個Pod執行多個容器,但目前大部分服務的執行方式是,一個Pod中只有一個容器,容器內部有兩個行程:服務發現Agent,和業務行程。
容器內無持久化資料。
Chons(Component詳情)
Component詳情頁,為最高頻使用頁面。
參考多個雲商產品,合併Deployment|StatefulSet、Pod、Service、Ingress、日誌、監控、灰度釋出、構建歷史、部署歷史、事件等功能。
 
Web Console
Web Console是把開源專案Kubernetes-dashboard中的Console前後端程式碼引入,原因是:該Web終端功能完善,支援顏色主題,支援bash快捷鍵,滑鼠選取複製、貼上,較為穩定。我們加入了iterm2中的badge功能,提示使用者當前所在容器。不過該終端的後端服務單個實體負載能力有限,我們部署了多個後端服務,使用tengine的session_sticky功能進行負載均衡和排程。該Console在公司內滿意度較高。
 
監控(Component)
監控資料展示使用Grafana,資料來自Prometheus,目前展示兩個層次的資料:Component級別(即多個Pod的彙總),Pod級別。資料維度為CPU、記憶體、IO、TCP連線,開發人員從Chons平臺中點選連結跳轉過來,自助進行查詢、分析。
大盤
監控大盤,主要展示資源水位,整體的狀態,運維人員使用監控大盤,關註資源的分配情況,進行節點的增減。
Dockerfile模板
  • Golang

  • multi-stage構建

  • 產出精簡映象

  • 新增到Git中即可

簡單到只需要將Dockerfile和entrypoint.sh兩個模板檔案新增到專案程式碼中即可,無需要任何修改。
entrypoint模板
Chons系統在建立Component時會預設註入一個RUN_ENV變數,entrypoint.sh指令碼根據該變數值進行配置檔案切換。
CI/CD
CI和CD系統是自研的,目前功能比較簡單,透過接收GitLab的push和merge request hook的通知,觸發CI流程。
CI系統呼叫Chons封裝的構建API,Chons處理後轉發到Jenkins進行構建,產出image,push到Registry儲存,然後Chons回呼CI系統API,CI系統呼叫Chons封裝的部署API,Chons處理後轉發到Kubernetes進行更新,Watch到更新完成的event後回呼CI系統,CI系統繼續出發後續任務節點。
在得到App內部,目前使用較多的是測試和預釋出環境。

 

總結

遇到的問題
  1. 初期由於我們的伺服器還執行在阿裡雲經典網路(IaaS的早期多租戶網路),在Swarm叢集中我們使用了overlay網路,每個容器建立或刪除時,由於需要叢集內部廣播該容器IP等資訊,隨著容器數量的增加,會有同步失敗情況,造成服務容器間不通問題。

  2. 得到App的服務,大部分是Golang語言開發,由於我們的服務多為HTTP短連線形式,並且如果請求的是域名的話,Golang會直接發起DNS查詢,當查詢量過大時會遇到“lookup failed”相關報錯,需要在容器內部執行nscd服務。

  3. 核心中的TCP引數,尤其是netfilter相關,對於容器網路穩定性影響較大,圖中為目前我們在使用的核心引數。

收益
  • 分鐘級部署

  • 秒級伸縮、恢復

  • 迭代速度成倍增長

  • TCO節省

  • 簡化資源管理

  • 為微服務治理打下基礎

過去,使用ECS擴容,需要人工登入阿裡雲管理介面 (磁碟快照、克隆節點、系統啟動,預計5分鐘擴容完畢)(新買實體、配置發版系統、發版,預計需要10分鐘擴容完畢)。現在,自助點選修改實體數,30秒內擴容完畢。
得益於Kubernetes的優秀設計,現在運維人員不需要關註節點用途,執行環境配置等功能,每個節點都只是資源池的一部分,只需關註叢集資源水位,管理工作只剩下增減節點。
透過容器的落地,簡化了環境管理,統一了釋出流程,遮蔽釋出細節,基礎設施只關註服務執行狀態和埠,開放了運維能力,打通了開發和運維間屏障,是踐行DevOps的基礎,最終使生產效率得到提升。
未來
未來我們將會進行混合雲建設,Kubernetes和容器技術的特性,使得從公有雲遷到線下,以及多公有雲的支援,是必不可少的前提。
後續也會在Chons中強化混合雲和多雲的容器排程、強化CI/CD的功能等。
希望我們的方案對創業公司有所幫助,願大家都能夠落地感受容器的便利,擁抱Kubernetes“雲作業系統”!
Q&A;

Q:業務環境有跨機房麼,還是雲環境,是共用一個叢集還是不同叢集呢?
A:個人傾向多叢集,上層Federation Cluster管理。
Q:程式碼使用釋出是什麼的呢 有使用Helm麼?
A:透過Kubernetes API Server更新Deployment中template的spc裡的container image。
Q:單個應用釋出一次耗時多長時間?主要耗時是在哪個階段呢?
A:1分鐘內,主要耗時在Kubernetes Replication Controller 滾動釋出過程中的Pod狀態同步。
Q:開發流程是什麼樣的,是開發建立映象還是運維自己建立?誰負責釋出到線上環境?
A:建立映象有兩種方式:CI和開發人員手工操作,線上環境開發提交上線單,QA審核。
Q:Kubernetes目前是都在阿裡雲上面嗎? 有沒有跨雲去實現平臺的搭建,如果使用混合雲對你們最大的挑戰?
A:目前還是主要用阿裡雲,未來會建設混合雲,混合雲方案還未確定,個人傾向多叢集,上層Federation Cluster管理,也不排除自研Controller,混個人認為混合雲最大的挑戰在於資料的同步,上層的服務容器中執行並且有Kubernetes來排程大大減輕了管理負擔,我們正在設計多層次的排程:例如流量層排程、服務層排程、資料層排程。
Q:Chon和Dozer是自研的平臺嗎?網上沒有找到相關的介紹。
A:是自研的,可以認為Dozer是容器發版系統,Chons是私有PaaS。
Q:Overlay為何不能用在生產環境?你們現在不算生產環境嗎?Flannel不就是Overlay嗎?
A:Flannel有高效能的HOSTGW,在雲上的話,還有各種公有雲的backend,藉助雲的VPC網路API實現。
Q:為什麼大量短連結需要最佳化DNS?大量短連結會導致什麼問題?
A:Golang預設編譯會關閉Glibc中的dns查詢實現,使用golang的實現,對於DNS服務有較多查詢,會有dns查詢失敗情況。大量短連線一般情況下不會有問題,會增加少量延遲以及伺服器上TCP TIME_WAIT狀態連線數量大。
Q:日誌這塊使用emptydir的話會不會有日誌丟棄的情況?
A:沒有,logtail和filebeat使用的是Watch和tail類似的樣式,我們統計過,延遲最大在5秒。
贊(0)

分享創造快樂