自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

Kubernetes生態(tài)體系落地過程中的選型和踩坑

云計(jì)算
無論大小企業(yè),容器化都被認(rèn)為可以大幅度地提升效率,增加運(yùn)維標(biāo)準(zhǔn)化和資源利用率。但是此類事情一旦做不好很容易造成花了大量成本而效果得不到認(rèn)可的尷尬結(jié)果。本次分享從團(tuán)隊(duì)的實(shí)際經(jīng)驗(yàn)出發(fā),聊一下容器化生態(tài)體系落地中的一些事情。

 開源節(jié)流,是企業(yè)提升利潤(rùn)的兩大方向;中臺(tái)戰(zhàn)略或基礎(chǔ)結(jié)構(gòu)體系常常肩負(fù)了節(jié)流的重任。無論大小企業(yè),容器化都被認(rèn)為可以大幅度地提升效率,增加運(yùn)維標(biāo)準(zhǔn)化和資源利用率。但是此類事情一旦做不好很容易造成花了大量成本而效果得不到認(rèn)可的尷尬結(jié)果。本次分享從團(tuán)隊(duì)的實(shí)際經(jīng)驗(yàn)出發(fā),聊一下容器化生態(tài)體系落地中的一些事情。

[[318786]]

監(jiān)控

 

容器環(huán)境一般是提供一整套解決方案的,監(jiān)控可以分為三種:指標(biāo)監(jiān)控、業(yè)務(wù)監(jiān)控、調(diào)用鏈監(jiān)控。

業(yè)務(wù)監(jiān)控和調(diào)用鏈監(jiān)控更多的取決于業(yè)務(wù)開發(fā)部門的選型,如skywalking等。

容器環(huán)境下,指標(biāo)監(jiān)控非Prometheus莫屬,通過Service Discovery機(jī)制中的Kubernetes plugin獲得scrape路徑,之后的鏈路就比較通暢了。

使用Prometheus過程中一個(gè)繞不開的問題是持久化存儲(chǔ),WAL中保存的數(shù)據(jù)不宜過多,否則內(nèi)存和加載速度都會(huì)產(chǎn)生很大問題,官方支持的remote read/write列表中,我們考查了InfluxDB和TiDB這兩個(gè),實(shí)踐中兩者占用的內(nèi)存都非常大,建議在集群外的物理機(jī)中進(jìn)行部署,如果使用InfluxDB,如果集群中Pod創(chuàng)建頻繁(例如使用了cronjob)可能會(huì)觸發(fā)key數(shù)量限制。

日志

 

日志分為兩種:std系列日志和文件日志,它們的區(qū)別主要在于收集方式不同,一般來說,收集上來的日志都會(huì)并進(jìn)入ELK體系,后面的處理就都差不多了。

std系列日志因其屬于Linux模型,可以統(tǒng)一從Docker數(shù)據(jù)目錄中予以收集,一種部署方式是使用DaemonSet部署Fluentd并掛載hostPath。

文件形態(tài)的日志略顯復(fù)雜,NFS/CephFS等分布式存儲(chǔ)肯定不適合存放日志,我們通過emptyDir形式實(shí)現(xiàn)目錄共享,然后新增filebeat sidecar對(duì)共享目錄中的日志文件進(jìn)行收集,入ELK體系。

如何與持續(xù)交付對(duì)接

 

這里我們關(guān)注持續(xù)交付部署部分的方案,Kubernetes的部署本質(zhì)上就是不同類型的資源對(duì)象以yaml格式應(yīng)用,在自研與使用開源方案之間,我們選用了Helm作為部署階段中,持續(xù)交付與Kubernetes的溝通橋梁。通過Helm我們可以把部署配置變成一個(gè)JSON對(duì)象,輔以標(biāo)準(zhǔn)化的部署模版,實(shí)現(xiàn)部署的標(biāo)準(zhǔn)化,同時(shí)自帶了資源狀態(tài)監(jiān)測(cè),應(yīng)用管理等功能。

作為一個(gè)toB性質(zhì)的服務(wù),我們不應(yīng)該只關(guān)注服務(wù)本身的可用性和性能,更應(yīng)該從最終用戶體驗(yàn)維度進(jìn)行自查改進(jìn)。例如Kubernetes官方的Benchmark工具中提到Pod平均啟動(dòng)時(shí)間,但是對(duì)項(xiàng)目來說更加關(guān)注的是Pod平均ready時(shí)間,而探針的結(jié)果是受到項(xiàng)目依賴,數(shù)據(jù)庫(kù)等因素的影響的。對(duì)于特定項(xiàng)目,很多數(shù)值是穩(wěn)定的,我們可以在報(bào)警系統(tǒng)中進(jìn)行一些統(tǒng)計(jì)學(xué)方面的處理。

如何正確地添加Sidecar

 

剛剛的日志章節(jié),提到了使用Filebeat Sidecar來收集日志,持續(xù)交付對(duì)接過程中提到了使用模版來生成項(xiàng)目的yaml文件。這就意味著,日志Sidecar容器必須在項(xiàng)目部署配置中予以體現(xiàn),與項(xiàng)目進(jìn)行耦合。這帶來了很大的復(fù)雜度,也令日志系統(tǒng)的配置變更流程非常復(fù)雜。畢竟穩(wěn)定的項(xiàng)目一般不會(huì)去更新部署配置,日志系統(tǒng)要一直兼容老版本的規(guī)則文件。因而需要一種手段,把日志配置和項(xiàng)目配置進(jìn)行隔離。

我們找到的辦法是Kubernetes的動(dòng)態(tài)準(zhǔn)入控制(Mutating Admission Webhook)來實(shí)現(xiàn)sidecar injection。通過這一機(jī)制,所有的資源在操作(增刪改)同步到etcd前,都會(huì)請(qǐng)求Webhook,Webhook可以通過或否決(allow/reject),也可以響應(yīng)一個(gè)JSON Patch,修改對(duì)象的部分資源。

事實(shí)上,常常會(huì)發(fā)現(xiàn)我們定義的Pod中會(huì)被默認(rèn)注入default service account,就是Kubernetes中內(nèi)置Admission的作用產(chǎn)物,現(xiàn)在非?;鸬腎stio,其劫持流量的原理為修改每個(gè)Pod的網(wǎng)絡(luò)規(guī)則,也是通過這種機(jī)制注入init-container,從而在Pod中修改iptables來實(shí)現(xiàn)。

通過這一機(jī)制,還可以針對(duì)諸如hostPort,hostPath,探針規(guī)范作出安全審計(jì),可以說提供了相當(dāng)豐富的想象空間。風(fēng)險(xiǎn)點(diǎn)是Webhook必須穩(wěn)定可靠,延時(shí)較長(zhǎng)不是問題,1.14+提供了timeoutSeconds,但如果返回一個(gè)不能被apply的patch,會(huì)導(dǎo)致資源創(chuàng)建失敗。

在日志應(yīng)用場(chǎng)合,我們注冊(cè)了Pod對(duì)象的Create動(dòng)作,項(xiàng)目只需要通過annotation傳入幾個(gè)簡(jiǎn)單配置,就可以自動(dòng)生成一個(gè)自定義的Filebeat Sidecar,非常干凈和方便。

如何實(shí)現(xiàn)自定義PodIP

 

Kubernetes中每次Pod的創(chuàng)建都會(huì)分配一個(gè)新的IP,社區(qū)的目的是希望用戶使用Service+DNS的機(jī)制實(shí)現(xiàn)通信,但實(shí)際上,在一些基礎(chǔ)組件的容器化過程中,由于軟件兼容性,我們會(huì)希望某些業(yè)務(wù)容器的IP固化,不因重啟而變更。

這里以Redis舉例要用到穩(wěn)定的IP的場(chǎng)景:

在Redis集群模式中,“cluster meet”命令只支持IP格式,不支持域名解析配置,社區(qū)中有人提出過這個(gè)issue結(jié)果被拒了。雖說Redis集群中任意一個(gè)節(jié)點(diǎn)的IP變更都可以在Redis集群內(nèi)自動(dòng)識(shí)別(因?yàn)镮nstance ID不變),但是如果因?yàn)橐馔馇闆r導(dǎo)致所有Redis集群節(jié)點(diǎn)同時(shí)發(fā)生重啟,集群內(nèi)節(jié)點(diǎn)兩兩無法發(fā)現(xiàn)彼此,那就只能由運(yùn)維人工介入,重新讓節(jié)點(diǎn)發(fā)現(xiàn)彼此,此外IP的變更也會(huì)導(dǎo)致有緩存的Redis客戶端產(chǎn)生錯(cuò)誤。

在Kubernetes中,Service相關(guān)資源由kube-proxy負(fù)責(zé),主要體現(xiàn)在iptables或IPVS規(guī)則中,而PodIP是由CNI負(fù)責(zé)分配,具體體現(xiàn)在eth-pair和路由表中。我們選用了Calico作為CNI插件,通過cni.projectcalico.org/ipAddrs這個(gè)annotation將預(yù)期的IP傳遞給Calico。

相對(duì)于對(duì)CNI進(jìn)行二次開發(fā)自行實(shí)現(xiàn)IPAM來說,這種方法的開發(fā)成本較小。

在具體實(shí)現(xiàn)上:由于Pod是通過上級(jí)對(duì)象資源的模版創(chuàng)建,無法在模版中為每個(gè)Pod自定義annotation,所以我們同樣通過動(dòng)態(tài)準(zhǔn)入機(jī)制實(shí)現(xiàn),例如在sts資源中自定義一個(gè)annotation并傳遞一組IP,隨后劫持Pod的創(chuàng)建,根據(jù)序號(hào)依次為Pod新增annotation,以激活Calico的指定PodIP功能。

這里注意的一點(diǎn)是,我們?cè)趯?shí)現(xiàn)IP固化功能后,一些微服務(wù)團(tuán)隊(duì)也希望使用這個(gè)功能。他們想要解決的痛點(diǎn)是容器發(fā)版之后,注冊(cè)中心仍然保有舊的PodIP的問題。這里不適合去做IP固化:

  • 原因一:Web項(xiàng)目大都使用deployment發(fā)布,在rs和Pod階段,podName會(huì)添加隨機(jī)字符串,無法甄別排序;事實(shí)上,我們只對(duì)sts資源開放了固化IP的方案;
  • 原因二:微服務(wù)應(yīng)用應(yīng)當(dāng)實(shí)現(xiàn)對(duì)SIGINT,SIGTERM等信號(hào)的監(jiān)聽,在pod terminationGracePeriodSeconds中自行實(shí)現(xiàn)注冊(cè)中心的反注冊(cè)。

任務(wù)調(diào)度

 

我們有一些祖?zhèn)鞯臉I(yè)務(wù)員仍然使用PHP,PHP在進(jìn)程管理上比較欠缺,物理機(jī)環(huán)境下很多調(diào)度工作要借助于cronjob來完成。我們一些PHP項(xiàng)目一開始上容器的時(shí)候,采用的就是Kubernetes提供的cronjob機(jī)制,使用下來有這么幾個(gè)問題:

  • Pod執(zhí)行日志通過ELK體系收集后展示不直觀;
  • 更新代碼后Pod在節(jié)點(diǎn)的首次啟動(dòng)會(huì)因?yàn)閜ull代碼而不準(zhǔn)時(shí);
  • 無法手動(dòng)執(zhí)行啟動(dòng);
  • 間隔時(shí)間較短的cron大幅度提高了集群Pod總數(shù),增加管理節(jié)點(diǎn)的壓力。

最后我們選擇使用開源的goCron方案,為項(xiàng)目單獨(dú)部署任務(wù)專用deployment,通過gRPC的方式進(jìn)行任務(wù)的啟停和日志傳輸。

值得注意的是,在開源goCron方案中,由Server角色向Node角色發(fā)起請(qǐng)求,但是我們不可能為每一個(gè)Node容器都配備Ingress或者NodePort暴露。

在有關(guān)二次開發(fā)中,我們?yōu)間RPC proto參數(shù)中新增了target字段。即Server角色中心化部署,每個(gè)容器編排集群部署一個(gè)Agent角色作為中轉(zhuǎn),最終通過SVC達(dá)到Node角色。

集群事件監(jiān)控

 

我們排查問題的時(shí)候第一件事一般都是describe一下相關(guān)資源,然后查看event,但是事實(shí)上,event默認(rèn)只能存在1小時(shí);kube-apiserver中有一個(gè)參數(shù)定義了事件在etcd中的保留時(shí)間:event-ttl Amount of time to retain events. (default 1h0m0s)。

這個(gè)1h主要是考慮到大規(guī)模集群中etcd的性能瓶頸;但即使是小集群,這個(gè)值也不建議調(diào)整到24h以上。這意味著,如果半夜中集群中發(fā)生事件,到了白天上班只能看到restart計(jì)數(shù)器+1或者對(duì)象存活時(shí)間清零,而找不到任何相關(guān)信息。

所以我們經(jīng)過二次開發(fā),在所有集群內(nèi)部署了一個(gè)事件收集中間件,監(jiān)聽所有ns中的ev,發(fā)送至ES,并進(jìn)行一些簡(jiǎn)單的聚合,以metrics的形式暴露給prom。這一工具深受運(yùn)維團(tuán)隊(duì)好評(píng),并且逐漸成為了集群健康的重要晴雨表。

容器內(nèi)時(shí)間模擬及系統(tǒng)參數(shù)模擬

 

容器化和虛擬化相比,最大的區(qū)別在于容器和物理機(jī)共享了內(nèi)核,內(nèi)核實(shí)現(xiàn)了進(jìn)程調(diào)度、網(wǎng)絡(luò)、io,等等功能,并通過Namespace和CGroup實(shí)現(xiàn)隔離。但是在這些隔離中,時(shí)間、CPU、內(nèi)存等信息不在隔離范圍內(nèi),從而帶來了問題。

首先我們看一下CPU和內(nèi)存,在容器中,如果我們打印/proc/cpuinfo或是/proc/meminfo,取到的是物理機(jī)的核數(shù)和內(nèi)存大小,但實(shí)際上容器必然是會(huì)有資源限制的,這會(huì)誤導(dǎo)容器環(huán)境中的進(jìn)程,使得一些預(yù)期中的優(yōu)化變成了負(fù)優(yōu)化。如線程數(shù)、GC的默認(rèn)設(shè)置。

針對(duì)此問題的解決方案有三個(gè):

  1. Java/Golang/Node啟動(dòng)時(shí)手動(dòng)參數(shù)傳入資源最大限制
  2. Java 8u131+和Java 9+添加-XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap;Java 8u191+和Java 10+默認(rèn)開啟UseContainerSupport,無需操作;但是這些手段無法修正進(jìn)程內(nèi)直接讀取/proc下或者調(diào)用top、free -m、uptime等命令輸出的內(nèi)容
  3. 改寫相關(guān)內(nèi)核參數(shù),對(duì)任意程序都有效果

前兩種方案,侵入性較高,我們選擇使用第三種方案,改寫相關(guān)內(nèi)核參數(shù),使用LXCFS實(shí)現(xiàn),yaml中使用hostPath裝載。

關(guān)于LXCFS,這里只提供一個(gè)關(guān)鍵詞,大家可以去搜索相關(guān)信息。

與CPU/內(nèi)存相類似的還有Uptime、diskStats、Swaps等信息,改寫后容器內(nèi)top、free -m、uptime等命令都會(huì)顯示正確。

值得注意的是CPU的限制,容器中所謂的CPU限制,并不是綁定獨(dú)占核,而是限制使用時(shí)間。舉個(gè)例子:一臺(tái)4核的物理機(jī),能并行4個(gè)線程;而一臺(tái)32核的宿主機(jī)上起一個(gè)限制為4核的容器,它仍然能并行32個(gè)線程,只不過每個(gè)核只能占用1/8的時(shí)間片。

關(guān)于容器內(nèi)時(shí)間的模擬,我們使用了libfaketime,進(jìn)程啟動(dòng)時(shí)添加LD_PRELOAD和FAKETIME環(huán)境變量。

最后聊一下Kubernetes的基礎(chǔ),etcd。當(dāng)api-server不可用的時(shí)候,直接讀取etcd中的數(shù)據(jù)將成為最后的救命稻草。然而etcd中存放的數(shù)據(jù)在某個(gè)版本之后已經(jīng)變成了Protobuf編譯過的二進(jìn)制數(shù)據(jù)。get出來之后肉眼無法識(shí)別。

我平時(shí)會(huì)使用Auger這個(gè)開源項(xiàng)目,通過管道的形式將etcd中的內(nèi)容還原成yaml文本。

我認(rèn)知中的Kubernetes,它是一個(gè)容器編排體系,是一套云原生的微服務(wù)架構(gòu)。

Q&A

 

Q:落地過程必然涉及到之前開發(fā)、測(cè)試和運(yùn)維流程的變更,組織和相關(guān)人員都會(huì)面臨調(diào)整,這部分工作貴公司是如何推進(jìn)的,踩了哪些坑,如何解決的?A:這個(gè)一言難盡啊,人的問題是最難解決的,能用技術(shù)解決的都不是問題,要是說回答的話,初期打通公司各個(gè)關(guān)節(jié),讓大boss認(rèn)可這件事,行政命令強(qiáng)推,很重要。不然做出來也沒人用,就是白忙活,在用戶中找小白鼠迭代,而不是自己弄個(gè)自以為完美的推出去。

Q:Java容器瞬間拉起的過程,整個(gè)集群都會(huì)被CPU用盡,如何解決Java CPU啟動(dòng)時(shí)候CPU資源互爭(zhēng)的情況?A:這個(gè)問題我們也遇到過,后來把內(nèi)核升級(jí)到4.19后就不再發(fā)生了,很多內(nèi)存耗盡,CPU爆炸的問題我們都通過內(nèi)核升級(jí)解決了。

Q:日志平臺(tái)怎么解決沒法像grep -C查找上下文,日志平臺(tái)怎么標(biāo)準(zhǔn)化日志格式?A:這個(gè)得看日志平臺(tái)具體開發(fā)是怎么實(shí)現(xiàn)的了,一般來說這不是問題日志格式的標(biāo)準(zhǔn)化,得和業(yè)務(wù)合作。事實(shí)上日志平臺(tái)一般是中臺(tái)部門的單獨(dú)的系統(tǒng),它要單獨(dú)開發(fā)。

Q:容器化落地怎么協(xié)調(diào)開發(fā)的需求?比如開發(fā)學(xué)習(xí)成本,比如本地調(diào)試和現(xiàn)場(chǎng)保留復(fù)現(xiàn)問題,排查問題的方法方式對(duì)開發(fā)友好。A:這還是人的問題,很多業(yè)務(wù)開發(fā)不愿意學(xué)習(xí),不接受新事物,一葉障目否定容器,這真的沒辦法。還是從人身上尋求妥協(xié)吧。每個(gè)人的精力都是有限的,這種事情陷進(jìn)去很難拔出來;公開培訓(xùn),講座,駐場(chǎng)支持,培養(yǎng)業(yè)務(wù)部門懂的人。

Q:線上Kubernetes集群采用什么方式部署,二進(jìn)制還是kubeadm等,部署架構(gòu)是怎么樣的?A:如果了解證書制作和Kubernetes各個(gè)組件的作用,建議從二進(jìn)制文件入手,企業(yè)環(huán)境可以自己寫Ansible等腳本。kubeadm維護(hù)一般不適用于線上環(huán)境。

Q:我是一名Java工程師,有7年經(jīng)驗(yàn),想轉(zhuǎn)行到容器相關(guān)領(lǐng)域,請(qǐng)問成為容器開發(fā)工程師需要哪些條件?A:對(duì)Linux要非常了解,脫離JVM看一些系統(tǒng)方面的知識(shí)。此外容器的語言基本上都是Go,微服務(wù)那套和Java沒啥區(qū)別,熟悉Protobuf。

Q:如何保證日志Sidecar的存活與否不會(huì)影響到業(yè)務(wù)容器?A:Sidecar和業(yè)務(wù)容器本來就是互相隔離的,現(xiàn)在1.10+的Kubernetes在Pod內(nèi)只會(huì)共享網(wǎng)絡(luò),不會(huì)默認(rèn)共享pid了,應(yīng)該不會(huì)有啥影響。

Q:Sidecar方式收集日志會(huì)出現(xiàn)延時(shí),特別是丟失問題,這個(gè)如何解決?A:減少Filebeat的采集時(shí)間,這個(gè)我感覺無解?;蛘咴趃racefultime上做文章,讓Filebeat多活一會(huì)。

[[318787]]

 

責(zé)任編輯:武曉燕 來源: 分布式實(shí)驗(yàn)室
相關(guān)推薦

2020-03-27 07:56:11

K8S生態(tài)體系運(yùn)維

2020-09-15 08:46:26

Kubernetes探針服務(wù)端

2023-02-28 16:26:46

推薦系統(tǒng)模塊

2024-09-09 08:02:27

2017-11-06 10:00:01

ERP管理數(shù)字化

2021-08-05 15:36:34

NFV網(wǎng)絡(luò)設(shè)備

2018-10-15 09:39:29

Kubernetes日志容器

2016-12-30 11:10:32

Hadoop開發(fā)JVM

2021-01-13 16:11:23

存儲(chǔ)

2019-10-28 14:07:29

研發(fā)管理技術(shù)

2013-11-12 09:23:48

布線錯(cuò)誤損失

2024-10-29 09:20:01

2024-01-31 16:36:53

2010-11-26 16:18:13

MySQL變量定義

2023-02-20 08:11:04

2018-09-11 09:14:52

面試公司缺點(diǎn)

2022-05-13 11:47:42

前端框架實(shí)踐

2018-07-30 16:18:51

容災(zāi)備份

2023-12-14 17:34:22

Kubernetes集群K8s

2011-05-03 10:31:59

噴墨打印機(jī)注墨誤區(qū)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)