可以看到,開(kāi)發(fā)人員所維護(hù)的 Dockerfile 可以說(shuō)相當(dāng)簡(jiǎn)單了,這大大的降低了開(kāi)發(fā)人員維護(hù)的難度。

另外,因?yàn)闃?gòu)建產(chǎn)物的大小,很大程度上決定了部署時(shí)間的長(zhǎng)短,所以我們使用了號(hào)稱最小的鏡像——alpine,alpine 有很多的優(yōu)點(diǎn):

  ? 體積小

  ? 有包管理器、有豐富的依賴

  ? 大廠的支持,包含 Docker 公司在內(nèi)的多家大廠官方使用

但是他有一個(gè)缺點(diǎn),alpine 上并沒(méi)有 glibc 庫(kù),他所使用的是一個(gè) musl libc 的小體積替代版,但是 Java 是必須依賴的 glibc 的,不過(guò)早就有大神了解了這點(diǎn),在 GitHub 上已經(jīng)提供了預(yù)編譯的 glibc 庫(kù),名字為alpine-pkg-glibc,裝上這個(gè)庫(kù)就可以完美支持 Java,同時(shí)還能夠保持體積很小。

Rancher 的高可用性

安裝 Rancher 的方式有兩種:?jiǎn)喂?jié)點(diǎn)安裝和高可用集群安裝。一般單節(jié)點(diǎn)安裝僅適用于測(cè)試或者 demo 環(huán)境,所以要正式投入使用的話,還是推薦高可用集群的安裝方式。

我們一開(kāi)始測(cè)試環(huán)境就使用了單節(jié)點(diǎn)安裝的方式,后來(lái)因?yàn)?Rancher Server 那臺(tái)機(jī)器出現(xiàn)過(guò)一次重啟,就導(dǎo)致了測(cè)試環(huán)境故障,雖然備份了,但是還是丟失了少量數(shù)據(jù),最后我們測(cè)試環(huán)境也采用了 HA 高可用部署,整個(gè)架構(gòu)如下圖所示。

Rancher Server 我是采用的 RKE 安裝,并且為了防止阿里云出現(xiàn)區(qū)域性的故障,我們將 Rancher Server 的三臺(tái)機(jī)器,部署在了兩個(gè)可用區(qū),Rancher Server-001、003 在北京的 H 區(qū)、Rancher Server-002 在北京的 G 區(qū)。

負(fù)載均衡,我們采用的是阿里云的 SLB,也是采購(gòu)的主備型實(shí)例,防止單點(diǎn)故障,因?yàn)?Rancher 必須使用 SSL 證書(shū),我們也有自己的域名證書(shū),為了方便在 SLB 上進(jìn)行 SSL 證書(shū)的維護(hù),我們使用的是 7 層協(xié)議,在 SLB 上做的 SSL 終止,Rancher Server 的架構(gòu)圖可以參考下圖:

圖片

  下游集群,也就是用來(lái)承載業(yè)務(wù)的 K8s 集群,我們也是一半一半,在阿里云的兩個(gè)可用區(qū)進(jìn)行部署的,需要注意的是,為了保證兩個(gè)區(qū)的網(wǎng)絡(luò)時(shí)延 <= 15 ms,這就完成了一個(gè)高可用的災(zāi)備架構(gòu)。

  備份方面,我們也使用了阿里云 ECS 快照 + ETCD S3 協(xié)議備份到了阿里云的 OSS 對(duì)象存儲(chǔ)兩種方案,確保出現(xiàn)故障后,能夠及時(shí)恢復(fù)服務(wù)。

  部署的詳細(xì)教程可以參考Rancher 官方文檔。

容器的運(yùn)維

  容器的運(yùn)維,這里主要指容器的日志收集和容器監(jiān)控,容器監(jiān)控方面呢,Rancher 自帶了 Prometheus 和 Grafana,而且和 Rancher 的 UI 有一些整合,就非常的方便,所以監(jiān)控方面我就不展開(kāi)講了,我主要說(shuō)一說(shuō)日志收集。

  在 K8s 里,日志的收集相比傳統(tǒng)的物理機(jī)、虛機(jī)等方式要復(fù)雜一些,因?yàn)?K8s 所提供的是動(dòng)態(tài)的環(huán)境,像綁定 hostpath 這種方式是不適用的,我們可以通過(guò)以下這個(gè)表格直觀的對(duì)比一下:

圖片

  可以看到,K8s 需要采集的日志種類比較多,而容器化的部署方式,在單機(jī)器內(nèi)的應(yīng)用數(shù)是很高的,而且都是動(dòng)態(tài)的,所以傳統(tǒng)的采集方式是不適用于 K8s 的。

  目前 K8s 的采集方式大體可以分為兩種,被動(dòng)采集和主動(dòng)推送。

  主動(dòng)推送一般有DockerEngine和業(yè)務(wù)直寫兩種方式:DockerEngine 是 Docker 的 LogDriver 原生自帶的,一般只能收集 STDOUT、一般不建議使用;而業(yè)務(wù)直寫,則需要在應(yīng)用里集成日志收集的 SDK,通過(guò) SDK 直接發(fā)送到收集端,日志不需要落盤,也不需要部署Agent,但是業(yè)務(wù)會(huì)和 SDK 強(qiáng)綁定,靈活性偏低,建議對(duì)于日志量較大,或者對(duì)日志有定制化要求的場(chǎng)景使用。

  被動(dòng)推送是采用部署日志收集 Agent 進(jìn)行采集的,有兩種方式,一種是 Daemonset 每個(gè)機(jī)器節(jié)點(diǎn)上部署一個(gè) Agent,還有一種 Sidecar,每個(gè) Pod 以 Sidecar 的形式部署一個(gè) Agent。

  Sidecar 部署方式比較消耗資源,相當(dāng)于每個(gè) Pod 都有一個(gè) agent,但是這種方式 靈活性以及隔離性較強(qiáng),適合大型的 K8s 集群或者作為 PaaS 平臺(tái)為業(yè)務(wù)方提供服務(wù)的群使用,Daemonset 部署方式,資源消耗較小,適合功能單一、業(yè)務(wù)不多的集群。

  結(jié)合我們自身的場(chǎng)景,屬于小規(guī)模集群,并且業(yè)務(wù)也不算多,我們選擇了 Daemonset 的部署方式,在測(cè)試環(huán)境,我們經(jīng)過(guò)調(diào)研選擇了阿里開(kāi)源的一個(gè)日志收集組件log-pilotGitHub 地址是:github.com/AliyunContainerService/log-pilot,通過(guò)結(jié)合 Elasticsearch、Kibana 等算是一個(gè)不錯(cuò)的 K8s 日志解決方案。

  因?yàn)槲覀兊姆?wù)器都在阿里云上,我們運(yùn)維人員比較少只有2位,沒(méi)有精力再去維護(hù)一個(gè)大型的分布式存儲(chǔ)集群,所以我們的業(yè)務(wù)日志選擇存儲(chǔ)在了阿里云的日志服務(wù),所以在生產(chǎn)環(huán)境,我們的 K8s 也使用了阿里云日志服務(wù),目前單日日志 6億+ 沒(méi)有任何問(wèn)題。

  使用阿里云收集日志呢,你需要開(kāi)通阿里云的日志服務(wù),然后安裝 Logtail 日志組件alibaba-log-controller Helm,這個(gè)在官方文檔里有安裝腳本,我把文檔鏈接貼在下面,在安裝組件的過(guò)程中會(huì)自動(dòng)創(chuàng)建aliyunlogconfigs CRD,部署alibaba-log-controller的Deployment,最后以 DaemonSet 模式安裝 Logtail。然后你就可以在控制臺(tái),接入你想要收集的日志了。安裝完以后是這樣的:

圖片

  Logtail支持采集容器內(nèi)產(chǎn)生的文本日志,并附加容器的相關(guān)元數(shù)據(jù)信息一起上傳到日志服務(wù)。Kubernetes文件采集具備以下功能特點(diǎn):

  ?只需配置容器內(nèi)的日志路徑,無(wú)需關(guān)心該路徑到宿主機(jī)的映射

  ?支持通過(guò)Label指定采集的容器

  ?支持通過(guò)Label排除特定容器

  ?支持通過(guò)環(huán)境變量指定采集的容器

  ?支持通過(guò)環(huán)境變量指定排除的容器

  ?支持多行日志(例如java stack日志)

  ?支持Docker容器數(shù)據(jù)自動(dòng)打標(biāo)簽

  ?支持Kubernetes容器數(shù)據(jù)自動(dòng)打標(biāo)簽

  如果你想了解更多,可以查看阿里云日志服務(wù)的官方文檔。

容器的多租戶隔離

  我這里所講的,主要指的是企業(yè)內(nèi)部用戶的多租戶隔離,而不是指的 SaaS、KaaS 服務(wù)模型的多租戶隔離。

  在權(quán)限方面,因?yàn)槲宜緦?duì)于權(quán)限的管控較嚴(yán)格,而 Rancher 恰好提供了非常方便的基于 集群、項(xiàng)目、命名空間等多個(gè)粒度的權(quán)限控制,并且支持我司基于 OpenLDAP 的認(rèn)證協(xié)議,非常便于管理,我可以給不同項(xiàng)目組的開(kāi)發(fā)、測(cè)試人員開(kāi)通相對(duì)應(yīng)的 集群/項(xiàng)目/命名空間的權(quán)限。

  比如下圖,我可以給集群添加用戶、也可以給某個(gè) Project 添加用戶,并且可以指定幾個(gè)不同的角色,甚至可以自定義角色。

圖片

  比如場(chǎng)景1:我可以給 項(xiàng)目組長(zhǎng),分配開(kāi)發(fā)環(huán)境集群->項(xiàng)目1 所有者(Owner)權(quán)限,然后項(xiàng)目組長(zhǎng)可以自由控制給本項(xiàng)目添加他的成員,并分配相應(yīng)權(quán)限。

  場(chǎng)景2:我可以給 測(cè)試經(jīng)理,分配測(cè)試集群的所有者(Owner)權(quán)限,由測(cè)試經(jīng)理來(lái)分配,誰(shuí)來(lái)負(fù)責(zé)哪個(gè)項(xiàng)目的測(cè)試部署,以及開(kāi)發(fā)人員只能查看日志等。

  在資源方面,一定要進(jìn)行容器的資源配額設(shè)置,如果不設(shè)置資源限額,一旦某一個(gè)應(yīng)用出現(xiàn)了性能問(wèn)題,將會(huì)影響整個(gè) node 節(jié)點(diǎn)上的所有應(yīng)用,K8s 會(huì)將出現(xiàn)問(wèn)題的應(yīng)用調(diào)度到其他 node 上,如果你的資源不夠,將會(huì)出現(xiàn)整個(gè)系統(tǒng)的癱瘓,導(dǎo)致雪崩。

圖片

  Java 應(yīng)用的資源配額限制也有一個(gè)坑,因?yàn)槟J(rèn) Java 是通過(guò)/proc/meminfo來(lái)獲取內(nèi)存信息的,默認(rèn) JVM 會(huì)使用系統(tǒng)內(nèi)存的 25% 作為 Max Heap Size,但是容器內(nèi)的/proc/meminfo是宿主機(jī)只讀模式掛載到容器里的,所以采取默認(rèn)值是行不通的,會(huì)導(dǎo)致應(yīng)用超過(guò)容器限制的內(nèi)存配額后被OOM,而健康檢查又將服務(wù)重啟,造成應(yīng)用不斷的重啟。

  那是不是通過(guò)手動(dòng)參數(shù)設(shè)置 JVM 內(nèi)存 = 容器內(nèi)存限額呢?不行!因?yàn)?JVM消耗的內(nèi)存不僅僅是 Heap,因?yàn)?JVM 也是一個(gè)應(yīng)用,它需要額外的空間去完成它的工作,你需要配置的限額應(yīng)該是Metaspace + Threads + heap + JVM進(jìn)程運(yùn)行所需內(nèi)存 + 其他數(shù)據(jù) 關(guān)于這塊,因?yàn)樯婕暗降膬?nèi)容較多,就不進(jìn)行展開(kāi),感興趣的同學(xué)可以自己去 Google 一下。

總 結(jié)

因?yàn)槲覀兊臉I(yè)務(wù)場(chǎng)景并不復(fù)雜,所以我們的容器化之路,其實(shí)走的也相對(duì)來(lái)講蠻順暢的,我們的運(yùn)維人員很少,只有 2 位,所以我們也沒(méi)有太多的時(shí)間精力去維護(hù)太多的自建系統(tǒng),我們使用了很多的阿里云產(chǎn)品,包括 Rancher,他很方便的部署方式,友好的 UI,包括集成好的監(jiān)控等等,在容器化之路上給了我們很大的信心。

我們使用構(gòu)建兩層鏡像的方式,降低了開(kāi)發(fā)人員的學(xué)習(xí)復(fù)雜度。使用了小體積鏡像 alpine + 預(yù)編譯 glibc 減小了鏡像體積。提高了部署的時(shí)間,在架構(gòu)上,我們采用了阿里云雙區(qū)機(jī)房的災(zāi)備的架構(gòu),以及完備的備份方案。使用 Daemonset 部署的日志收集組件,收集到阿里云日志服務(wù),支撐我們 6億/日的日志系統(tǒng)。Rancher 還提供給了我們深度集成的監(jiān)控系統(tǒng)、多租戶隔離等。還有我們自己踩坑 踩出來(lái)的資源配額設(shè)置。

其實(shí)容器化并不復(fù)雜,如果沒(méi)有 K8s,我們需要自己構(gòu)建健康監(jiān)測(cè)系統(tǒng)、發(fā)版系統(tǒng)、維護(hù)不同的主機(jī)環(huán)境,不能細(xì)粒度的進(jìn)行資源劃分,不能更有效的利用計(jì)算資源,運(yùn)維的工作主要是什么?在我看來(lái)其實(shí)就是 節(jié)約成本、提高效率。虛擬化、自動(dòng)化、智能化、高性能、高可用、高并發(fā) 等等,這些無(wú)一不是圍繞著成本和效率這兩個(gè)詞,而 K8s 其實(shí)已經(jīng)幫我們都做好了,而像 Rancher 這種編排平臺(tái)又幫我們降低了 K8s 的學(xué)習(xí)復(fù)雜度,所以你要做的就是加入 K8s,好了,到這里這次的分享就結(jié)束了。感謝~

社區(qū)QA

  Q1:K8S在生產(chǎn)環(huán)境的高可用存儲(chǔ)方案有推薦嗎?

  A1:存儲(chǔ)方案沒(méi)有標(biāo)準(zhǔn)答案,我們主要使用阿里云,所以用的是阿里云的塊存儲(chǔ),比較常見(jiàn)的方案還有 Ceph、GlusterFS、Portworx、OpenEBS 等,他們各有優(yōu)劣,需結(jié)合自己的業(yè)務(wù)需求進(jìn)行選擇

  Q2:灰度發(fā)布,Kubernetes網(wǎng)絡(luò)流量可以通過(guò)服務(wù)網(wǎng)格分流實(shí)現(xiàn)網(wǎng)絡(luò)層面的分發(fā),但是涉及到應(yīng)用大版本的更新時(shí)候,涉及到數(shù)據(jù)庫(kù)結(jié)構(gòu)的變更的時(shí)候,如何實(shí)現(xiàn)灰度發(fā)布?

  A2:沒(méi)有遇到過(guò)這個(gè)場(chǎng)景,不過(guò)提供一個(gè)思路,可以準(zhǔn)備兩套數(shù)據(jù)庫(kù),網(wǎng)絡(luò)分流也可以分流到不通數(shù)據(jù)庫(kù),具體需要你自己驗(yàn)證一下是否可行

  要分清楚這是兩層,一層是邏輯層,一層是數(shù)據(jù)層,不能混為一談

  Q3:Pipeline是用什么做的?Pipeline下,如何處理同一個(gè)分支,需要并行測(cè)試多個(gè)版本的場(chǎng)景?我用Rancher的Pipeline,局限性比較大,就是同一個(gè)分支無(wú)法并行多套進(jìn)行測(cè)試。命名空間在使用,但是同一個(gè)分支下,命名空間是寫在.rancher.yml下的,所以無(wú)法區(qū)分,Rancher的Pipeline不能在外面注入變量進(jìn)行區(qū)分。

  A3:Rancher 的 Pipline 目前還是有一些不夠靈活,我們使用的是自建 Jenkins 做 Pipeline 的,并行測(cè)試,可以用命名空間等隔離策略進(jìn)行隔離,或者準(zhǔn)備多套測(cè)試環(huán)境

  Q4: 你們運(yùn)維的Dockerfile和開(kāi)發(fā)的Dockerfile是怎么合并的?

  A4:開(kāi)發(fā)的 Dockerfile 是 From 運(yùn)維的 Dockerfile

  Q5:你們k8s的漏洞掃描用的什么工具?一般什么級(jí)別的鏡像漏洞需要進(jìn)行修復(fù)?

  A5:暫時(shí)沒(méi)有使用漏掃工具,我們主要根據(jù) Rancher 企業(yè)服務(wù)通知的修復(fù)建議進(jìn)行修復(fù)

  Q6: 就是比如說(shuō)從外網(wǎng),通過(guò)service ip能夠登陸并且管理容器。想實(shí)現(xiàn)這一步必須通過(guò)將service ip暴露出來(lái),然后這個(gè)service ip怎么暴露出來(lái)?麻煩解答一下。

  A6:如果需求是管理容器,其實(shí)可以使用 Rancher 的用戶權(quán)限控制,讓某一用戶擁有某一容器的權(quán)限,暴露 service ip 到公網(wǎng),讓用戶管理容器是無(wú)法實(shí)現(xiàn)的

  Q6 : 好的,謝謝,我還有一點(diǎn)不明白,這個(gè)service ip有什么辦法能讓他暴露出來(lái)呢?你意思是說(shuō)讓不同的用戶通過(guò)rancher平臺(tái)去管理不同的容器嗎?麻煩再給解答一下,謝謝。

  A6:可以使用 NodePort 暴露,通過(guò) Node ip 和 端口進(jìn)行訪問(wèn),或者使用 公有云的負(fù)載均衡產(chǎn)品

  Q6 : 我不是這個(gè)意思,我是想把service ip暴露出來(lái),不只單單想通過(guò)集群內(nèi)部訪問(wèn)。

  A6:service ip 本來(lái)就是 K8s 內(nèi)部的,暴露不了,只能轉(zhuǎn)發(fā)

  Q7: 為何沒(méi)有放在3個(gè)可用區(qū),如果可用區(qū)H掛掉,是否會(huì)導(dǎo)致集群不可訪問(wèn)?

  A7:3個(gè)可用區(qū)當(dāng)然也是可以的,Rancher HA 架構(gòu),只要有一個(gè) Server 可用就沒(méi)有關(guān)系

  Q8:請(qǐng)教下你們多套開(kāi)發(fā)測(cè)試環(huán)境的pipeline是怎么樣的流程呢 (差異化)?有使用helm template嗎,方便講解下更多細(xì)節(jié)么?

  A8:目前是通過(guò) Jenkins 部署參數(shù),部署的時(shí)候可以選擇 命名空間、環(huán)境標(biāo)識(shí)、分支等,通過(guò) sed 修改 template

  Q9:請(qǐng)問(wèn)你們的devops流是怎樣的呢?一個(gè)環(huán)境對(duì)應(yīng)一個(gè)docker鏡像,還是說(shuō)test pre prd共用一個(gè)docker鏡像呢?如果是一個(gè)docker鏡像共用test pre prd的話是怎么做的呢(比如不同環(huán)境的配置以及開(kāi)發(fā)的協(xié)‘同開(kāi)發(fā)流)?

  A9:我們是用的同一個(gè)鏡像,部署時(shí)通過(guò)選擇不通的環(huán)境標(biāo)識(shí)參數(shù),程序會(huì)自動(dòng)注入不同環(huán)境的配置,需要開(kāi)發(fā)進(jìn)行一些相應(yīng)的配置修改

  Q10:不大懂容器的資源限制該如何配置,自己配置了感覺(jué)不起作用

  A10:Rancher 可以在項(xiàng)目、命名空間、Pod 三個(gè)粒度進(jìn)行設(shè)置,優(yōu)先級(jí)相反

About Rancher Labs

Rancher Labs由CloudStack之父梁勝創(chuàng)建。旗艦產(chǎn)品Rancher是一個(gè)開(kāi)源的企業(yè)級(jí)Kubernetes管理平臺(tái),實(shí)現(xiàn)了Kubernetes集群在混合云+本地?cái)?shù)據(jù)中心的集中部署與管理。Rancher一向因操作體驗(yàn)的直觀、極簡(jiǎn)備受用戶青睞,被Forrester評(píng)為“2020年多云容器開(kāi)發(fā)平臺(tái)領(lǐng)導(dǎo)廠商”以及“2018年全球容器管理平臺(tái)領(lǐng)導(dǎo)廠商”,被Gartner評(píng)為“2017年全球最酷的云基礎(chǔ)設(shè)施供應(yīng)商”。

目前Rancher在全球擁有超過(guò)三億的核心鏡像下載量,并擁有包括中國(guó)聯(lián)通、中國(guó)平安、中國(guó)人壽、上汽集團(tuán)、三星、施耐德電氣、西門子、育碧游戲、LINE、WWK保險(xiǎn)集團(tuán)、澳電訊公司、德國(guó)鐵路、廈門航空、新東方等全球著名企業(yè)在內(nèi)的共40000家企業(yè)客戶。

分享到

zhangnn

相關(guān)推薦