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

K8S生態(tài)體系落地的選型和踩坑都講全了

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

 [[320104]]

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

監(jiān)控

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

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

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

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

日志

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

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

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

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

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

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

如何正確地添加Sidecar

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

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

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

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

在日志應用場合,我們注冊了Pod對象的Create動作,項目只需要通過annotation傳入幾個簡單配置,就可以自動生成一個自定義的Filebeat Sidecar,非常干凈和方便。

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

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

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

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

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

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

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

這里注意的一點是,我們在實現(xiàn)IP固化功能后,一些微服務團隊也希望使用這個功能。他們想要解決的痛點是容器發(fā)版之后,注冊中心仍然保有舊的PodIP的問題。這里不適合去做IP固化:

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

任務調度

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

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

最后我們選擇使用開源的goCron方案,為項目單獨部署任務專用deployment,通過gRPC的方式進行任務的啟停和日志傳輸。

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

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

集群事件監(jiān)控

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

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

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

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

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

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

針對此問題的解決方案有三個:

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

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

關于LXCFS,這里只提供一個關鍵詞,大家可以去搜索相關信息。

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

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

關于容器內時間的模擬,我們使用了libfaketime,進程啟動時添加LD_PRELOAD和FAKETIME環(huán)境變量。

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

我平時會使用Auger這個開源項目,通過管道的形式將etcd中的內容還原成yaml文本。

我認知中的Kubernetes,它是一個容器編排體系,是一套云原生的微服務架構。

>>>>

Q&A

Q1:落地過程必然涉及到之前開發(fā)、測試和運維流程的變更,組織和相關人員都會面臨調整,這部分工作貴公司是如何推進的,踩了哪些坑,如何解決的?

A:這個一言難盡啊,人的問題是最難解決的,能用技術解決的都不是問題,要是說回答的話,初期打通公司各個關節(jié),讓大boss認可這件事,行政命令強推,很重要。不然做出來也沒人用,就是白忙活,在用戶中找小白鼠迭代,而不是自己弄個自以為完美的推出去。

Q2:Java容器瞬間拉起的過程,整個集群都會被CPU用盡,如何解決Java CPU啟動時候CPU資源互爭的情況?

A:這個問題我們也遇到過,后來把內核升級到4.19后就不再發(fā)生了,很多內存耗盡,CPU爆炸的問題我們都通過內核升級解決了。

Q3:日志平臺怎么解決沒法像grep -C查找上下文,日志平臺怎么標準化日志格式?

A:這個得看日志平臺具體開發(fā)是怎么實現(xiàn)的了,一般來說這不是問題

日志格式的標準化,得和業(yè)務合作。事實上日志平臺一般是中臺部門的單獨的系統(tǒng),它要單獨開發(fā)。

Q4:容器化落地怎么協(xié)調開發(fā)的需求?比如開發(fā)學習成本,比如本地調試和現(xiàn)場保留復現(xiàn)問題,排查問題的方法方式對開發(fā)友好。

A:這還是人的問題,很多業(yè)務開發(fā)不愿意學習,不接受新事物,一葉障目否定容器,這真的沒辦法。還是從人身上尋求妥協(xié)吧。每個人的精力都是有限的,這種事情陷進去很難拔出來;公開培訓,講座,駐場支持,培養(yǎng)業(yè)務部門懂的人。

Q5:線上Kubernetes集群采用什么方式部署,二進制還是kubeadm等,部署架構是怎么樣的?

A:如果了解證書制作和Kubernetes各個組件的作用,建議從二進制文件入手,企業(yè)環(huán)境可以自己寫Ansible等腳本。kubeadm維護一般不適用于線上環(huán)境。

Q6:我是一名Java工程師,有7年經(jīng)驗,想轉行到容器相關領域,請問成為容器開發(fā)工程師需要哪些條件?

A:對Linux要非常了解,脫離JVM看一些系統(tǒng)方面的知識。此外容器的語言基本上都是Go,微服務那套和Java沒啥區(qū)別,熟悉Protobuf。

Q7:如何保證日志Sidecar的存活與否不會影響到業(yè)務容器?

A:Sidecar和業(yè)務容器本來就是互相隔離的,現(xiàn)在1.10+的Kubernetes在Pod內只會共享網(wǎng)絡,不會默認共享pid了,應該不會有啥影響。

Q8:Sidecar方式收集日志會出現(xiàn)延時,特別是丟失問題,這個如何解決?

A:減少Filebeat的采集時間,這個我感覺無解?;蛘咴趃racefultime上做文章,讓Filebeat多活一會。

 

責任編輯:武曉燕 來源: DBAplus社群
相關推薦

2020-03-16 13:16:48

Kubernetes選型踩坑

2019-09-28 23:09:28

網(wǎng)絡故障數(shù)據(jù)包網(wǎng)段

2020-09-01 10:40:11

K8SDocker開源

2025-04-15 07:44:28

2024-07-22 13:43:31

Kubernetes容器

2022-04-22 13:32:01

K8s容器引擎架構

2023-11-06 07:16:22

WasmK8s模塊

2023-05-04 15:49:59

KafkaK8sKubernetes

2022-06-30 10:22:26

K8s可觀測Prometheus

2023-07-04 07:30:03

容器Pod組件

2024-04-10 08:39:56

BigDecimal浮點數(shù)二進制

2023-12-20 08:13:54

K8S監(jiān)控管理

2025-01-07 14:36:12

2020-10-16 18:30:41

K8SDockerCRI-O

2022-09-07 09:22:36

SpringBootWeb

2023-09-06 08:12:04

k8s云原生

2022-11-18 07:34:12

Docker項目目錄

2022-06-01 09:38:36

KubernetesPod容器

2024-01-26 14:35:03

鑒權K8sNode

2024-09-26 09:50:07

點贊
收藏

51CTO技術棧公眾號