【導(dǎo)讀】:Netflix架構(gòu)師在使用Kubernetes一年后,回顧了團(tuán)隊(duì)遷移到Kubernetes的好與壞,取與舍。
2015年時(shí),我們的團(tuán)隊(duì)在亞馬遜EC2部署服務(wù)已經(jīng)有幾年了。這時(shí)我所在的團(tuán)隊(duì)接到一項(xiàng)任務(wù),要?jiǎng)?chuàng)建所有研發(fā)團(tuán)隊(duì)都可以使用的全新部署平臺(tái)。這些年以來基于AWS的平臺(tái)的新版本發(fā)布雖然已經(jīng)足夠流暢,但如果要用定制化腳本或工具做自動(dòng)化部署,對(duì)于非運(yùn)維團(tuán)隊(duì)人員來說就不那么易用了。對(duì)于沒資源學(xué)習(xí)所有定制化工具和腳本細(xì)節(jié)的小團(tuán)隊(duì)尤其困難。主要問題是,AWS沒有模塊化部署,而沒有模塊化部署研發(fā)和運(yùn)維之間就存在一定隔閡。容器化正是要解決這個(gè)隔閡的,而且容器化是趨勢(shì)。
如果你們還沒在生產(chǎn)中使用Docker和kubernetes,看看我們團(tuán)隊(duì)是怎么吃螃蟹的。我們已經(jīng)在生產(chǎn)環(huán)境使用kubernetes有一年多了。
首先從容器和容器編排工具入手
我認(rèn)為,容器是未來的部署格式。使用容器,非常方便用服務(wù)所需的基礎(chǔ)層進(jìn)行打包。Docker這類工具雖然提供了容器,我們也需要管理副本和做故障轉(zhuǎn)移的工具和API,有了這些才能自動(dòng)化部署多臺(tái)機(jī)器。
Kubernetes和docker swarm這類工具在2015年還很不成熟,只有一些早期的可用于生產(chǎn)環(huán)境的版本。我們還是決定從docker swarm開始用起。
一開始我們用docker swarmd來管理網(wǎng)絡(luò)。我們用“大使模式"和一堆腳本,達(dá)到部署自動(dòng)化的目的。這有多困難呢?這是我們趟的第一個(gè)坑:容器集群、網(wǎng)絡(luò)、部署自動(dòng)化是非常難處理的
我們很快意識(shí)到了這點(diǎn),這時(shí)決定嘗試另一個(gè)工具,kubernetes。kubernetes看起來是最好的選擇,因?yàn)樗衼碜詆oogle、紅帽、Core OS等確切了解大規(guī)模部署的組織的技術(shù)支撐。
kubernetes做負(fù)載均衡
譯注:翻譯本文時(shí)ingress已經(jīng)可用了, 負(fù)載均衡相關(guān)的內(nèi)容可以直接跳過。關(guān)于ingress、負(fù)載均衡、clusterIP和NodePort之間的區(qū)別參考下文中《Ingress vs. ClusterIP vs. NodePort vs. LoadBalancer 》部分 https://www.ibm.com/cloud/blog/kubernetes-ingress
用kubernetes工作,就要非常熟悉它的概念,比如pod、service、replication controller等。如果你還沒對(duì)這些概念非常了解,可以讀讀kubernetes文檔。kubernetes官網(wǎng)為初學(xué)者提供了很多文檔。
http://kubernetes.io/docs/whatisk8s/
只要有一個(gè)在運(yùn)行的kubernetes集群,就可以用kubectl部署一個(gè)服務(wù)了。kubectl是kuberntes的命令行接口。但很快就遇到了自動(dòng)化部署的瓶頸。但在自動(dòng)化部署前還要解決不能通過網(wǎng)絡(luò)請(qǐng)求部署服務(wù)的問題。
部署接口是有一個(gè)服務(wù),但是這個(gè)服務(wù)的IP地址在集群內(nèi)部。也就是部署應(yīng)用的服務(wù)根本不暴露給網(wǎng)絡(luò)請(qǐng)求!在Google Cloud Engine上可以通過配置一個(gè)負(fù)載均衡來訪問kubernetes服務(wù)。但如果不是在GCE用kubernetes,就需要額外做一些事情讓kubecctl可以通過網(wǎng)絡(luò)訪問。
通過kubernetes宿主機(jī)網(wǎng)絡(luò)和端口直接暴露服務(wù)接口,這個(gè)解決辦法比較容易,很多人都是這么做的。但如果我們的服務(wù)依賴著宿主機(jī)的端口,部署多個(gè)應(yīng)用時(shí)就會(huì)產(chǎn)生端口沖突。這也讓擴(kuò)展集群或替換掉宿主機(jī)變得很麻煩。
兩步搭建負(fù)載均衡
在kubernetes集群前端配置如HAProxy和NGINX這類負(fù)載均衡服務(wù)是比較方便的解決方案。我們?cè)贏WS上用VPN訪問kubernetes集群,用AWS的Elastic Load Balancer把外部流量接入集群內(nèi)的HAProxy。HAProxy給每個(gè)Kubernetes服務(wù)都配置了一個(gè)接口,這個(gè)接口把流量分發(fā)給每個(gè)pod。
這個(gè)兩步搭建負(fù)載均衡是為了繞過AWS ELB的限制做的。ELB不能處理多個(gè)虛機(jī),這也是我們用HAProxy的原因。只使用HAProxy不用ELB也可以,但這樣就要想辦法在DNS層繞過動(dòng)態(tài)AWS IP地址。
圖1:兩步負(fù)載均衡的工作原理
當(dāng)前kubernetes正在開發(fā)ingress的功能。這個(gè)功能會(huì)允許直接從kubernetes內(nèi)部定義外部負(fù)載均衡。當(dāng)前這個(gè)功能還沒實(shí)現(xiàn)完,去年我們是用api和一些開源工具做的可配置的負(fù)載均衡。https://kubernetes.io/docs/concepts/services-networking/ingress/
配置負(fù)載均衡
首先我們需要一個(gè)存儲(chǔ)負(fù)載均衡配置的地方。這個(gè)配置可以放在任何地方,但既然已經(jīng)有etcd了,我們就決定把數(shù)據(jù)存到etcd。我們用confd這個(gè)工具監(jiān)聽etcd中配置的變化,基于模板生成新HAProxy配置文件。新服務(wù)添加到Kubernetes中時(shí),在etcd中增加一個(gè)配置,這就會(huì)觸發(fā)新HAProxy文件的生成。
Kubernetes越來越成熟
Kubernetes依然存在很多未解決問題,就像負(fù)載均衡那樣問題多多。很多問題會(huì)被社區(qū)識(shí)別后寫出設(shè)計(jì)文檔,文檔中討論可以解決問題的新功能。但是產(chǎn)出通用的解決方案需要消耗大量時(shí)間,也就是說這些文檔里討論的功能可能需要很久才能發(fā)布到新版本里。這是件好事,長(zhǎng)期來看設(shè)計(jì)新功能時(shí)省事有害無益。
雖然發(fā)布新功能耗時(shí)不短,Kubernetes并沒有被限制住。使用kubernetes API幾乎可以做到任何你想做的事。一旦社區(qū)發(fā)布了解決方案,我們就用標(biāo)準(zhǔn)方案替換我們定制化開發(fā)的方案。
定制化開發(fā)了負(fù)載均衡結(jié)局方案,下一個(gè)挑戰(zhàn)是實(shí)現(xiàn)一個(gè)特別重要的部署能力:藍(lán)綠發(fā)布。
Kubernetes內(nèi)做藍(lán)綠發(fā)布
藍(lán)綠發(fā)布的服務(wù)是在發(fā)布過程中沒有任何服務(wù)不可用時(shí)段的。和滾動(dòng)發(fā)布相比,藍(lán)綠發(fā)布是通過創(chuàng)建一個(gè)新集群副本,上面跑著新版本的服務(wù),老版本的服務(wù)依然存在、而且在接收事實(shí)流量。只有新副本完全部署好、已經(jīng)運(yùn)行起來,這時(shí)負(fù)載均衡會(huì)把流量切給新版本的服務(wù)。
這種發(fā)布方式的好處是同一時(shí)刻,只有一個(gè)版本的服務(wù)在工作,不需要考慮版本兼容的問題。藍(lán)綠發(fā)布對(duì)于實(shí)例數(shù)量少的副本更友好。
圖2:藍(lán)綠發(fā)布的工作原理
圖2里有一個(gè)組件叫Deployer,它負(fù)責(zé)調(diào)度整個(gè)發(fā)布流程。你的團(tuán)隊(duì)可以創(chuàng)建這個(gè)組件,我們已經(jīng)把我們的實(shí)現(xiàn)作為Amdatu項(xiàng)目的一部分、使用Apache協(xié)議開源了。這個(gè)組件還有可以配置部署的web界面。
https://bitbucket.org/amdatulabs/amdatu-kubernetes-deployer
https://bitbucket.org/account/user/amdatulabs/projects/INFRA
重新配置負(fù)載均衡前,需要對(duì)每個(gè)pod做健康檢查,這個(gè)機(jī)制在藍(lán)綠發(fā)布里非常重要。我們希望每個(gè)我們部署的組件都提供一個(gè)監(jiān)控檢查功能。我們通常會(huì)給每個(gè)程序添加一個(gè)HTTP健康檢查服務(wù)。
自動(dòng)化部署
有了Deployer,就能把部署綁定到某個(gè)pipeline上了。打鏡像成功后,構(gòu)建服務(wù)器就會(huì)把新的docker鏡像推到鏡像服務(wù)器上。比如推給Docker Hub。然后構(gòu)建服務(wù)器觸發(fā)Deployer,自動(dòng)部署新版本到test環(huán)境。同樣一個(gè)鏡像可以被推到生產(chǎn)環(huán)境,只需觸發(fā)生產(chǎn)環(huán)境的Deployer即可進(jìn)行部署。
圖3:自動(dòng)化容器部署流水線
了解資源限制
用Kubernetes就必須了解資源限制機(jī)制。可以配置每個(gè)pod的請(qǐng)求數(shù)和CPU、內(nèi)存的限制,也可以控制給定資源數(shù)和突發(fā)資源數(shù)的限制。
https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/
這些配置對(duì)同時(shí)、高效運(yùn)行多個(gè)容器很重要,如果沒有正確地配置,容器可能會(huì)因?yàn)闆]有被分配足夠內(nèi)存而經(jīng)常崩潰。
早早開始配置并測(cè)試容器的資源限制,沒有資源限制的集群依然會(huì)運(yùn)行,不過一旦給某些容器真正的流量,就會(huì)出大問題。
怎么給k8s做監(jiān)控
基本部署好k8s之后,我們很快意識(shí)到監(jiān)控和日志對(duì)這種動(dòng)態(tài)環(huán)境來說非常重要。如果你面對(duì)著數(shù)量眾多的副本和節(jié)點(diǎn),登陸一臺(tái)服務(wù)器看日志文件這件事就不再可行。一旦開始用kubernetes,就需要規(guī)劃集中式的日志和監(jiān)控了。
日志
日志有數(shù)量眾多的開源工具可供選擇。日志管理工具Graylog,從容器中采集和消費(fèi)數(shù)據(jù)用Kafka消息隊(duì)列。容器發(fā)送日志到kafka,kafka把日志交給graylog建索引。我們讓容器自己發(fā)日志到Kafka,這樣處理日志就很容易。還有其他一些方案可以從外部取容器內(nèi)的日志、把日志發(fā)到日志管理系統(tǒng)的方案的做法,參考:https://www.loggly.com/blog/top-5-docker-logging-methods-to-fit-your-container-deployment-strategy/
監(jiān)控
kubernetes在容器掛掉后恢復(fù)做的非常好。當(dāng)容器由于某種原因崩潰,kubernetes會(huì)做容器重啟。如果Kubernetes里運(yùn)行著一個(gè)副本,終端用戶可能無法注意到程序重啟了。Kubernetes的恢復(fù)做的太好,以至于我們遇到過一組容器由于內(nèi)存泄露,一天重啟了好多次但沒人知道重啟動(dòng)這種情況。
盡管從kubernetes的角度看沒問題,但我們開發(fā)和維護(hù)人員還是需要知道是否程序存在問題的。我們用一個(gè)定制化的健康檢查大盤,監(jiān)控所有kubernetes節(jié)點(diǎn)、每個(gè)pod和其他如數(shù)據(jù)存儲(chǔ)之類的服務(wù)。每個(gè)pod的健康檢查是使用了對(duì)當(dāng)前某個(gè)服務(wù)的檢查。要實(shí)現(xiàn)這樣一個(gè)大盤,kubernetes api又一次變得十分重要。
度量負(fù)載、吞吐量、程序錯(cuò)誤等數(shù)據(jù)也很重要,這時(shí)候就要使用開源工具了。我們的應(yīng)用組件把數(shù)據(jù)發(fā)送到InfluxDB這個(gè)時(shí)序數(shù)據(jù)庫里。存儲(chǔ)在InfluxDB內(nèi)的數(shù)據(jù)可以通過Grafana做可視化,Grafana是開源數(shù)據(jù)大盤管理系統(tǒng)。除了influxdb + grafana之外還有很多其他可選項(xiàng),任意解決方案都可以提升系統(tǒng)問題的可觀測(cè)性。
kubernetes和數(shù)據(jù)存儲(chǔ)
很多新k8s用戶問,“我該怎么用kubernetes處理數(shù)據(jù)存儲(chǔ)呢?”
用MongoDB和MySQL這類數(shù)據(jù)存儲(chǔ),一般都要把數(shù)據(jù)持久化地存儲(chǔ)起來。容器重啟時(shí)會(huì)丟失上次的數(shù)據(jù),這對(duì)無狀態(tài)的組件沒什么問題,但是對(duì)于持久化數(shù)據(jù)存儲(chǔ),這樣非常不好。kubernetes對(duì)持久化數(shù)據(jù)有volumn這個(gè)概念。
一個(gè)volume可以有多種底層實(shí)現(xiàn),包括存儲(chǔ)在宿主機(jī)的文件、AWS EBS、NFS等。雖然volume算是個(gè)好解決方案,但是對(duì)我們運(yùn)行著的數(shù)據(jù)存儲(chǔ)來說不是一個(gè)好方案。
副本問題
多數(shù)deployment中,數(shù)據(jù)存儲(chǔ)都會(huì)以復(fù)制的方式運(yùn)行。典型就是Mongodb里的replica set、mysql以主副節(jié)點(diǎn)模式運(yùn)行。這引入了一些新問題,首先是每個(gè)節(jié)點(diǎn)的數(shù)據(jù)存儲(chǔ)集群都可能是不同的系統(tǒng)。寫入同一個(gè)卷可能導(dǎo)致數(shù)據(jù)不可用。另一個(gè)問題是多數(shù)數(shù)據(jù)存儲(chǔ)都需要準(zhǔn)確的用來啟動(dòng)集群的配置參數(shù),自動(dòng)發(fā)現(xiàn)、自動(dòng)配置節(jié)點(diǎn)并不常見常用。
一臺(tái)運(yùn)行著數(shù)據(jù)存儲(chǔ)的機(jī)器要為負(fù)載做特殊的配置,比如配置更高IOPS。這樣一來,對(duì)于數(shù)據(jù)存儲(chǔ),使用k8s做增加刪除節(jié)點(diǎn)的成本會(huì)大大增加。這些特性與k8s部署的動(dòng)態(tài)特性適配性不好。
不在生產(chǎn)環(huán)境中使用Kubernetes存儲(chǔ)數(shù)據(jù)
我們認(rèn)為在Kubernetes中做數(shù)據(jù)存儲(chǔ)收益有限。在K8S中啟動(dòng)數(shù)據(jù)存儲(chǔ)比大多數(shù)kubernetes deployment都復(fù)雜。
鑒于此,我們決定把生產(chǎn)數(shù)據(jù)存儲(chǔ)到kubernetes節(jié)點(diǎn)中。我們?cè)谄渌麢C(jī)器上手動(dòng)部署集群,使用必要的手段優(yōu)化特定數(shù)據(jù)存儲(chǔ)。運(yùn)行在Kubernetes中的服務(wù)和訪問其他服務(wù)一樣連接并訪問存儲(chǔ)節(jié)點(diǎn)。不是有Kubernetes了就一定要把所有東西都部署上去。除了數(shù)據(jù)存儲(chǔ)和HAProxy服務(wù)器,其他在kubernetes內(nèi)運(yùn)行,包括日志和監(jiān)控。
為什么我們對(duì)明年kubernets的表現(xiàn)非常期待
看看我們部署的系統(tǒng),kubernetes已經(jīng)非常強(qiáng)大了。kubernetes API是做自動(dòng)化和部署pipeline的極好的工具。deployment又快又可靠,我們也不再跟虛擬機(jī)打交道了。我們的構(gòu)建和部署因?yàn)闇y(cè)試、維護(hù)容器更容易也變得更可靠了。
可見,采取這種部署方式對(duì)于想跟上業(yè)界其他頻繁部署應(yīng)用、而且要降低部署開銷的團(tuán)隊(duì)的步伐也是非常必要的。
計(jì)算成本
看下成本。跑kubernetes需要一個(gè)etcd集群和一個(gè)master節(jié)點(diǎn),運(yùn)行這些花費(fèi)不高,但是對(duì)于部署規(guī)模不大的集群來說可能成本占比會(huì)更高。對(duì)于部署規(guī)模小的部署,使用Google的容器化服務(wù)解決方案可能是更好的選擇。
對(duì)于大規(guī)模部署來說,這可以節(jié)省很多在服務(wù)方面的開銷。這時(shí)運(yùn)行etcd和一個(gè)master節(jié)點(diǎn)不會(huì)是顯著的消耗了。kubernetes可以在同一臺(tái)機(jī)器上要運(yùn)行很多容器、并最大限度地使用資源。這減少了所需的服務(wù)器數(shù)量,進(jìn)而更省錢。盡管使用K8s聽起來很好,但是對(duì)于運(yùn)維這種大集群來說就不那么好做了,有許多托管服務(wù)需要考慮,包括我的團(tuán)隊(duì)正在研究的云RTI。
Kubernetes的光明未來
用預(yù)發(fā)布版本的kubernetes非常有挑戰(zhàn),跟進(jìn)新版本更新有時(shí)候幾乎是不可能的。近一年來,kubernetes的開發(fā)一直以來都在飛快地進(jìn)行,社區(qū)已經(jīng)變成了開發(fā)人才們的發(fā)電站。社區(qū)一年時(shí)間的進(jìn)展可能是難以估算的。
責(zé)任編輯:lq
-
自動(dòng)化
+關(guān)注
關(guān)注
29文章
5654瀏覽量
79771 -
模塊化
+關(guān)注
關(guān)注
0文章
334瀏覽量
21469
原文標(biāo)題:在生產(chǎn)環(huán)境用了一年 k8s 的經(jīng)驗(yàn)教訓(xùn)
文章出處:【微信號(hào):LinuxHub,微信公眾號(hào):Linux愛好者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
自建K8S集群認(rèn)證過期
k8s和docker區(qū)別對(duì)比,哪個(gè)更強(qiáng)?
k8s微服務(wù)架構(gòu)就是云原生嗎??jī)烧呤鞘裁搓P(guān)系
混合云部署k8s集群方法有哪些?
k8s可以部署私有云嗎?私有云部署全攻略
k8s云原生開發(fā)要求
![<b class='flag-5'>k8s</b>云原生開發(fā)要求](https://file1.elecfans.com/web2/M00/0B/06/wKgaomcZ5XOAO7bVAAGe1drYtZc769.png)
k8s容器啟動(dòng)失敗的常見原因及解決辦法
云服務(wù)器部署k8s需要什么配置?
納尼?自建K8s集群日志收集還能通過JMQ保存到JES
常用的k8s容器網(wǎng)絡(luò)模式有哪些?
K8S集群中使用JDOS KMS服務(wù)對(duì)敏感數(shù)據(jù)安全加密
![<b class='flag-5'>K8S</b>集群中使用JDOS KMS服務(wù)對(duì)敏感數(shù)據(jù)安全加密](https://file1.elecfans.com//web2/M00/01/83/wKgZoma1zJ6AcEuaAAD6dfqMV2U987.png)
K8S學(xué)習(xí)教程三:在PetaExpress KubeSphere 容器部署 Wiki 系統(tǒng) wiki.js 并啟用中文全文檢索
![<b class='flag-5'>K8S</b>學(xué)習(xí)教程三:在PetaExpress KubeSphere 容器部署 Wiki 系統(tǒng) wiki.js 并啟用中文全文檢索](https://file1.elecfans.com/web2/M00/F7/94/wKgZomaE_LWAIzZtAACo5pTAtaY093.png)
K8S學(xué)習(xí)教程(二):在 PetaExpress KubeSphere容器平臺(tái)部署高可用 Redis 集群
![<b class='flag-5'>K8S</b>學(xué)習(xí)教程(二):在 PetaExpress KubeSphere容器平臺(tái)部署高可用 Redis 集群](https://file1.elecfans.com/web2/M00/F7/94/wKgZomaE_LWAIzZtAACo5pTAtaY093.png)
評(píng)論