新聞中心
使用Kubernetes三年,我們從中學(xué)到了什么?
作者:讀芯術(shù) 2020-10-13 18:10:46
云計(jì)算 雖然kubernetes使我們的生活更輕松了,但過程會(huì)蠻艱辛,要經(jīng)過范式的改變。不僅要完全更迭我們的技能和工具,還有設(shè)計(jì)和思想。我們必須掌握許多新的科技,大幅擴(kuò)充提升團(tuán)隊(duì)和基礎(chǔ)設(shè)施。

讓客戶滿意是我們工作的目標(biāo),不斷超越客戶的期望值來(lái)自于我們對(duì)這個(gè)行業(yè)的熱愛。我們立志把好的技術(shù)通過有效、簡(jiǎn)單的方式提供給客戶,將通過不懈努力成為客戶在信息化領(lǐng)域值得信任、有價(jià)值的長(zhǎng)期合作伙伴,公司提供的服務(wù)項(xiàng)目有:域名注冊(cè)、雅安服務(wù)器托管、營(yíng)銷軟件、網(wǎng)站建設(shè)、賀州網(wǎng)站維護(hù)、網(wǎng)站推廣。
2017年.我們構(gòu)建了第一個(gè)kubernetes集群,版本是1.9.4。有兩個(gè)集群,一個(gè)用裸機(jī)RHEL VMs運(yùn)行,另一個(gè)用的是AWS EC2。時(shí)至今日,我們的Kubernetes基礎(chǔ)架構(gòu)團(tuán)隊(duì)有超過400個(gè)虛擬機(jī),遍布多個(gè)數(shù)據(jù)中心。這個(gè)平臺(tái)有高度可用且關(guān)鍵的軟件應(yīng)用和系統(tǒng),能管理運(yùn)行近四百萬(wàn)個(gè)活躍機(jī)器的大型實(shí)時(shí)網(wǎng)絡(luò)。
雖然kubernetes使我們的生活更輕松了,但過程會(huì)蠻艱辛,要經(jīng)過范式的改變。不僅要完全更迭我們的技能和工具,還有設(shè)計(jì)和思想。我們必須掌握許多新的科技,大幅擴(kuò)充提升團(tuán)隊(duì)和基礎(chǔ)設(shè)施。
回首用kubernetes產(chǎn)出的這三年,我們得出以下關(guān)鍵經(jīng)驗(yàn)。
1. 應(yīng)用的奇怪案例
涉及到微服務(wù)和容器化,工程師們傾向于不使用Java,主要是因?yàn)樗愀獾膬?nèi)存管理。然而Java已不同往日,它的容器適配性在幾年里已有提高。畢竟大多數(shù)系統(tǒng)都用Java運(yùn)行,如Apache Kafka和Elasticsearch。
在2017-2018年,只有一些應(yīng)用在Java8運(yùn)行。這些應(yīng)用通常很難適應(yīng)Docker內(nèi)存系統(tǒng),并且很容易因?yàn)槎褍?nèi)存問題和異常的垃圾收集趨勢(shì)而崩潰。這是由于Java虛擬機(jī)不能遵守Linux cgroup和namespace造成的,而他們是容器化技術(shù)的核心。
然而甲骨文公司在這之后不斷提升Java容器化的適配性。Java8的后續(xù)補(bǔ)丁也引入了實(shí)驗(yàn)性的Java虛擬機(jī)flag標(biāo)示來(lái)解決這些問題:
- XX:+UnlockExperimentalVMOptions
- XX:+UseCGroupMemoryLimitForHeap
但Java仍名聲不佳,對(duì)比同行的python和Go,Java占用內(nèi)存且啟動(dòng)速度慢。主要是由Java虛擬機(jī)的內(nèi)存管理及類加載器造成的。
現(xiàn)在如果必須選擇Java,我們會(huì)確保版本為11及以上,并且我們的Kubernetes內(nèi)存設(shè)定為Java虛擬機(jī)最大堆內(nèi)存( -Xmx )之上的1GB,以提供余量。也就是說,如果JVM使用8GB的堆內(nèi)存,則該應(yīng)用的Kubernetes資源限制就是9GB。有了它生活會(huì)更好。
圖源:unsplash
2. Kubernetes的生命周期升級(jí)
Kubernetes的生命周期管理很繁雜,比如它的升級(jí)和加強(qiáng),特別體現(xiàn)在用裸機(jī)或者VM搭建的集群。在升級(jí)時(shí),我們發(fā)現(xiàn)搭建新集群最簡(jiǎn)單的方式就是用最新的版本并將工作負(fù)載從舊版本轉(zhuǎn)移到新版本。努力和計(jì)劃在模型內(nèi)進(jìn)行升級(jí)是不值得的。
Kubernetes有多個(gè)運(yùn)行插件,需要與升級(jí)同步。Docker、Calico或Flannel之類的CNI插件都需要仔細(xì)地將它們組合在一起才能正常工作。雖然一些項(xiàng)目可以使它變得更容易運(yùn)行,如Kubespray、Kubeone、Kops和Kubeaws,但它們都有缺點(diǎn)。
我們?cè)赗HEL VM上使用Kubespray搭建了集群。Kubespray有關(guān)于搭建、添加、刪除新節(jié)點(diǎn)、版本升級(jí)的指導(dǎo)手冊(cè),基本覆蓋了我們使用Kubernetes產(chǎn)出需要的所有內(nèi)容。但升級(jí)手冊(cè)包含了免責(zé)聲明,提醒我們即使變更很小也不要忽略任何版本,也就是說要更新所有中間版本才能使用目標(biāo)版本。
訣竅就是,當(dāng)你計(jì)劃使用或已經(jīng)使用了Kubernetes,想想生命周期活動(dòng)以及你的方案如何這些問題。相對(duì)來(lái)說用它來(lái)搭建和運(yùn)行集群是比較簡(jiǎn)單的,但生命周期的維護(hù)仍是有著諸多活動(dòng)部件的全新領(lǐng)域。
3. 構(gòu)建和部署
圖源:unsplash
要做好重新設(shè)計(jì)整個(gè)搭建和部署管道的準(zhǔn)備。我們的搭建過程和部署必須經(jīng)歷Kubernetes的完全轉(zhuǎn)型,不僅對(duì)Jenkins管道進(jìn)行了大量的重組,還使用了Helm等新工具,策劃了新的git流程和構(gòu)建,標(biāo)記了docker鏡像,并對(duì)helm部署圖表進(jìn)行了版本控制。
不僅需要維護(hù)代碼,還需要策略來(lái)維護(hù)Kubernetes部署文件、Docker文件、Docker鏡像和Helm圖表,并設(shè)計(jì)一種將它們鏈接起來(lái)的方法。
在幾次迭代后我們有了如下設(shè)計(jì):放置應(yīng)用程序代碼及其Helm圖表于單獨(dú)的git存儲(chǔ)庫(kù)中,這使我們可以分別對(duì)它們進(jìn)行版本控制。(語(yǔ)義版本號(hào))
然后,我們將圖表版本的地圖與應(yīng)用程序版本一起保存,并使用它來(lái)跟蹤發(fā)布。例如,將app-1.2.0與charts-1.1.0一起部署。如果僅更改Helm值文件,則僅更改圖表的補(bǔ)丁程序版本(例如,從1.1.0到1.1.1)。所有這些版本均由每個(gè)存儲(chǔ)庫(kù)RELEASE.txt發(fā)行說明。
Apache Kafka或Redis的代碼之類的系統(tǒng)應(yīng)用程序的工作方式有所不同,我們未構(gòu)建或修改其代碼。也就是說,由于Docker標(biāo)簽只是Helm chart版本控制的一部分,我們沒有兩個(gè)git存儲(chǔ)庫(kù)。如果我們?cè)?jīng)更改了docker標(biāo)簽進(jìn)行升級(jí),我們將在圖表標(biāo)簽中增加主要版本。
4. 存活和就緒探針(雙刃劍)
Kubernetes的存活和就緒探針是能自動(dòng)解決系統(tǒng)問題的出色功能點(diǎn)。可以在發(fā)生故障時(shí)重新啟動(dòng)容器,并將流量從異常事故中轉(zhuǎn)移。但在某些故障情況下,探針可能是雙刃劍,并影響應(yīng)用程序的啟動(dòng)和恢復(fù),尤其是有狀態(tài)應(yīng)用程序,例如消息平臺(tái)或數(shù)據(jù)庫(kù)。
Kafka系統(tǒng)就是受害者。我們運(yùn)行了一個(gè)有replicationFactor of 3 和minInSyncReplica of 2的 3 Broker 3 Zookeeper狀態(tài)集,當(dāng)系統(tǒng)意外故障或崩潰導(dǎo)致Kafka啟動(dòng)時(shí)會(huì)發(fā)生此問題。這導(dǎo)致它在啟動(dòng)期間運(yùn)行其他腳本來(lái)修復(fù)損壞的索引,根據(jù)嚴(yán)重程度不同,該過程可能需要10到30分鐘。
由于時(shí)間耗費(fèi)增加,存活探針將不斷失敗,從而向Kafka發(fā)出終止信號(hào)以重新啟動(dòng),這一并阻止了Kafka系統(tǒng)修改索引和完全啟動(dòng)。
唯一的解決方案是在存活探針設(shè)置中設(shè)置 initialDelaySeconds,從而在容器啟動(dòng)后延遲探針評(píng)估。但是問題在于當(dāng)然很難給出具體時(shí)間,有些恢復(fù)甚至需要一個(gè)小時(shí),因此我們需要留足空間來(lái)計(jì)算時(shí)間。但是initialDelaySeconds增加的時(shí)間越多,速度就越慢,因?yàn)閱?dòng)失敗時(shí)Kubernetes需要更長(zhǎng)的時(shí)間來(lái)重新啟動(dòng)容器。
最新的幾個(gè)版本中,Kubernetes引入了第三種探針“啟動(dòng)探針”來(lái)解決這個(gè)問題。在alpha from 1.16 和 beta from 1.18 中都可用。啟動(dòng)探針可以使存活和就緒探針在容器啟動(dòng)前停止運(yùn)行,保證應(yīng)用程序的啟動(dòng)不受干擾。
5. 公開外部IP
圖源:unsplash
我們了解到,使用靜態(tài)外部IP公開服務(wù)會(huì)極大損害內(nèi)核的連接跟蹤機(jī)制。除非詳細(xì)計(jì)劃,否則它只會(huì)大規(guī)模崩潰。
集群在Calico for CNI和BGP運(yùn)行,作為Kubernetes內(nèi)部路由協(xié)議,并與邊緣路由器搭配。而Kubeproxy,我們使用IP Tables模式。我們?cè)贙ubernetes有著龐大的服務(wù),該服務(wù)通過外部IP公開,每天處理數(shù)百萬(wàn)個(gè)連接。
所有的源網(wǎng)絡(luò)地址轉(zhuǎn)換(NAT)和偽裝來(lái)自軟件定義網(wǎng)絡(luò),Kubernetes需要一個(gè)機(jī)制來(lái)跟蹤所有邏輯流。為此,它使用內(nèi)核的Conntrack and netfilter工具來(lái)管理與靜態(tài)IP的外部連接,接著將其轉(zhuǎn)換為內(nèi)部服務(wù)IP,再轉(zhuǎn)為pod IP。這些都通過conntrack表和IP表完成。
但這個(gè)conntrack表有限制。當(dāng)達(dá)到極限時(shí),Kubernetes集群(下有OS內(nèi)核)將不能接受新連接。在RHEL上,可以通過這種方式進(jìn)行檢查:
- $ sysctlnet.netfilter.nf_conntrack_countnet.netfilter.nf_conntrack_maxnet.netfilter.nf_conntrack_count = 167012
- net.netfilter.nf_conntrack_max = 262144
解決該問題的方法是匹配帶有邊緣路由器的多個(gè)節(jié)點(diǎn),使你的靜態(tài)IP的傳入連接遍及整個(gè)群集。因此,如果集群中有大量虛擬機(jī),累積起來(lái)就可以擁有一個(gè)大的conntrack表來(lái)處理大量的傳入連接。
在2017年剛開始使用的時(shí)候,這個(gè)問題完全難住了我們。但2019年Calico發(fā)布了一份相關(guān)的詳盡研究,題目就是《為什么conntrack不再友好》。
我們是否一定需要Kubernetes?
圖源:debian
三年來(lái),我們?nèi)栽诿刻炖^續(xù)探索和學(xué)習(xí)新東西。這個(gè)復(fù)雜的平臺(tái)中存在著一系列挑戰(zhàn),尤其是構(gòu)建和維護(hù)環(huán)境的開銷很大。這會(huì)改變你設(shè)計(jì)、思考、構(gòu)建的方式,并且會(huì)需要團(tuán)隊(duì)不斷提升擴(kuò)充來(lái)契合轉(zhuǎn)變。
然而,如果你在云端并且使用Kubernetes作為“服務(wù)”,那么大部分平臺(tái)維護(hù)的開銷都可以下降,例如“如何擴(kuò)展內(nèi)部網(wǎng)絡(luò)CIDR?”或“如何升級(jí)我的Kubernetes版本?”
應(yīng)該問的第一個(gè)問題是:“是否一定需要Kubernetes?”這可以幫助你評(píng)估問題,判斷用Kubernetes來(lái)解決它們是否必要。Kubernetes的升級(jí)轉(zhuǎn)換等并不便宜。你的用例一定要真正配得上這筆支出并且值得使用這個(gè)平臺(tái)。如果值得,那么Kubernetes可以極大地提高生產(chǎn)力。
記住,為了使用科技而使用是沒有意義的。
本文轉(zhuǎn)載自微信公眾號(hào)「讀芯術(shù)」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系讀芯術(shù)公眾號(hào)。
當(dāng)前標(biāo)題:使用Kubernetes三年,我們從中學(xué)到了什么?
標(biāo)題網(wǎng)址:http://m.fisionsoft.com.cn/article/coicphh.html


咨詢
建站咨詢
