新聞中心
擁抱云原生,如何將開源項目用K8S部署?
作者: 阿丸筆記 2020-12-22 07:42:05
開發(fā)
前端
云原生 本文將重點(diǎn)分享阿里開源項目otter適配k8s部署的改造過程,其中的改造過程和技巧應(yīng)該適用于將大多數(shù)開源項目改造到k8s進(jìn)行部署。

專注于為中小企業(yè)提供成都網(wǎng)站設(shè)計、成都網(wǎng)站制作、外貿(mào)網(wǎng)站建設(shè)服務(wù),電腦端+手機(jī)端+微信端的三站合一,更高效的管理,為中小企業(yè)威遠(yuǎn)免費(fèi)做網(wǎng)站提供優(yōu)質(zhì)的服務(wù)。我們立足成都,凝聚了一批互聯(lián)網(wǎng)行業(yè)人才,有力地推動了成百上千企業(yè)的穩(wěn)健成長,幫助中小企業(yè)通過網(wǎng)站建設(shè)實現(xiàn)規(guī)模擴(kuò)充和轉(zhuǎn)變。
k8s以及云原生相關(guān)概念近年來一直比較火熱,阿丸最近搞了個相關(guān)項目,小結(jié)一下。
本文將重點(diǎn)分享阿里開源項目otter適配k8s部署的改造過程,其中的改造過程和技巧應(yīng)該適用于將大多數(shù)開源項目改造到k8s進(jìn)行部署。
1.背景
otter是阿里開源的分布式數(shù)據(jù)庫同步系統(tǒng),基于數(shù)據(jù)庫增量日志解析,并準(zhǔn)實時同步到本機(jī)房或異地機(jī)房的mysql/oracle數(shù)據(jù)庫(相關(guān)內(nèi)容可以參考https://github.com/alibaba/otter,本文不做過多贅述)。
為了充分利用物理資源、快速擴(kuò)容同步節(jié)點(diǎn)、擁抱云原生,決定使用k8s部署otter。
otter的項目整體上自成一體,出于改造成本考慮,盡量在項目已有基礎(chǔ)上,做一些適配,不改動源代碼。
本文將重點(diǎn)分享對于otter適配k8s部署的改造過程,有不當(dāng)之處,還請多多指教。
涉及到幾個核心內(nèi)容:
- otter基本架構(gòu)
- dockerfile編寫
- deployment編寫
- 啟動腳本改造
- K8s中固定ip/port訪問
2.otter的基本架構(gòu)
典型管理系統(tǒng)架構(gòu),manager(web管理)+node(工作節(jié)點(diǎn))
- manager運(yùn)行時推送同步配置到node節(jié)點(diǎn)
- node節(jié)點(diǎn)將同步狀態(tài)反饋到manager上
- 基于zookeeper,解決分布式狀態(tài)調(diào)度的,允許多node節(jié)點(diǎn)之間協(xié)同工作
- 基于Canal開源產(chǎn)品,獲取數(shù)據(jù)庫增量日志數(shù)據(jù)。當(dāng)然,otter采用了canal的嵌入式模式,不是獨(dú)立的canal節(jié)點(diǎn)。
基于以上部署架構(gòu),我們只需要將otter-manager和otter-node部署到k8s上。
尤其是otter-node,需要利用k8s實現(xiàn)節(jié)點(diǎn)快速水平擴(kuò)展、計算性能彈性擴(kuò)縮容。
2.Dockerfile編寫
2.1 otter-manager的Dockerfile
otter-manager比較簡單,包括幾個步驟:
- 使用一個centos的基礎(chǔ)鏡像
- 設(shè)置時區(qū)
- 創(chuàng)建目錄
- 拷貝下載好的manager.deployer-4.2.18到指定目錄
- 使用啟動startup-new.sh腳本啟動(這里對原本的啟動腳本做了一些改造,后文進(jìn)行詳述)
具體如下所示:
2.2 otter-node的Dockerfile
otter-node稍微有所不同,根據(jù)官方文檔說明,需要安裝aria2來做文件傳輸。
注意注意,由于aria2安裝非常慢,因此,我們需要先安裝aria2作為一個新的基礎(chǔ)鏡像,然后在新的基礎(chǔ)鏡像上構(gòu)建otter-node鏡像,能大大提高后續(xù)鏡像構(gòu)建速度。
新的基礎(chǔ)鏡像如下,命名為 registry.xxx.com/xxx/otter-node-base:1.0。
然后在此基礎(chǔ)上構(gòu)建新的otter-node鏡像。
注意,otter-node的配置方式比較特殊,需要先在otter-admin上獲取一個nid,然后才能運(yùn)行一個otter-node。
所以,我們在dockerfile中以ARG 聲明一個nid,然后在后續(xù)構(gòu)建鏡像的時候,通過 --docker-arg 傳入nid具體的值。
當(dāng)然,如果把nid看作一個配置文件的話,也可以用下文提到的ConfigMap的形式在Deployment中掛載進(jìn)去
3.Deployment編寫
什么是Deployment?
- k8s的一個Deployment控制器為 Pods 和 ReplicaSets 提供聲明式的更新能力。我們通過編寫Deployment描述期望的目標(biāo)狀態(tài),然后 Deployment 控制器更改Pods或者ReplicaSets的實際狀態(tài), 使其變?yōu)槠谕麪顟B(tài)。
具體關(guān)于Deployment的知識不展開說明,可以參考k8s官方文檔。
我們需要部署測試環(huán)境與生產(chǎn)環(huán)境兩套集群,而無論是otter-manager還是otter-node,都依賴于讀取 conf/otter.properties 作為配置。
因此,我們需要根據(jù)環(huán)境,修改不同的otter.properties。
那么,對于k8s部署來說,可以采用同一份鏡像,然后在不同環(huán)境(k8s的不同namespace)中將otter.properties作為ConfigMap寫入,最后通過volume的形式掛載到pod的指定路徑上。
這里對幾個名詞做簡單介紹,詳細(xì)內(nèi)容可以參考k8s官方文檔。
- ConfigMap:一種 API 對象,用來將非機(jī)密性的數(shù)據(jù)保存到鍵值對中。使用時,Pods可以將其用作環(huán)境變量、命令行參數(shù)或者存儲卷中的配置文件。(如果想存儲的數(shù)據(jù)是機(jī)密的,可以使用 Secret,而不是ConfigMap)
- Volume:卷的核心是包含一些數(shù)據(jù)的一個目錄,Pod 中的容器可以訪問該目錄。所采用的特定的卷類型將決定該目錄如何形成的、使用何種介質(zhì)保存數(shù)據(jù)以及目錄中存放 的內(nèi)容。使用卷時, 在 .spec.volumes 字段中設(shè)置為 Pod 提供的卷,并在 .spec.containers[*].volumeMounts 字段中聲明卷在容器中的掛載位置。
所以,首先在指定環(huán)境(namespace中)創(chuàng)建configmap,以otter.properties作為key,以文件內(nèi)容作為value。
具體命令如下
kubectl create configmap otter-manager-dev-config --from-file=otter.properties=conf/otter-dev.properties -n otter-system
- 在namespace為otter-system中創(chuàng)建一個名字為otter-manager-dev-config的ConfigMap,其中,以otter.properties作為key,以文件內(nèi)容作為value。
產(chǎn)生的ConfigMap如下圖所示
最后,將這個ConfigMap在Deployment中用volume進(jìn)行引用,然后通過volumeMounts掛載到指定目錄,Deployment具體如下所示。
這里需要特別注意volumeMounts的路徑覆蓋問題,需要在volumeMounts中配置subPath為具體文件名。
4.啟動腳本改造
Otter包括兩個部分,管理控制臺manager和工作運(yùn)行節(jié)點(diǎn)node,正常情況下都是用各自的啟動腳本startup.sh啟動的。
為了適配k8s,我們需要對啟動腳本做改造,本文以otter-manager的啟動腳本為例,otter-node也是類似。
將啟動腳本startup.sh改造為 startup-moon.sh,重點(diǎn)解決兩個問題
- 前臺進(jìn)程保持運(yùn)行
- jvm參數(shù)自定義改造
4.1 前臺進(jìn)程保持運(yùn)行
由于容器中用entrypoint啟動的進(jìn)程為1號進(jìn)程,一旦1號進(jìn)程執(zhí)行結(jié)束,容器就會退出了。
而原本的startup.sh中,用java啟動后,使用 “&” 將java進(jìn)程轉(zhuǎn)換為后臺進(jìn)程,所以startup.sh作為1號進(jìn)程會很快執(zhí)行結(jié)束,容器就會自動退出了。
所以我們需要將1號進(jìn)程保持住,不要退出。
這里考慮了兩個方案:
- Startup.sh腳本中增加一個前臺進(jìn)程進(jìn)行保持,比如 tail -f /dev/null 命令
- 將“&”去掉,讓java啟動后就作為前臺進(jìn)程一直保持
后來考慮了一下,還是選擇了方案二。主要原因是為了利用pod自動重啟的特性。
如果Java進(jìn)程意外退出了,那么方案二就能使得1號進(jìn)程也結(jié)束,然后pod就能自動重啟了。而方案一的話,由于startup.sh腳本仍然在執(zhí)行tail,所以即使java進(jìn)程退出,1號進(jìn)程也不會結(jié)束。
具體修改如下:
最終pod中的進(jìn)程如圖所示
- 1號進(jìn)程是啟動腳本
- 1號進(jìn)程的子進(jìn)程是otter的java應(yīng)用進(jìn)程(前臺進(jìn)程)
4.2 虛擬機(jī)大小自定義配置
由于otter項目中,將jvm的啟動參數(shù)配置在了start.sh中,不方便進(jìn)行手動配置。
因此,將start.sh的配置jvm參數(shù)的邏輯注釋掉,采用自己配置的環(huán)境變量JAVA_OPTIONS進(jìn)行注入。
這個環(huán)境變量的注入方式也比較簡單,就是在Deployment中的env配置的(藍(lán)色框部分),方便以后手動修改jvm參數(shù)大小而不用修改鏡像。
5.k8s上固定IP/Port訪問
otter-node的部署中,有個比較特殊的地方。
不同于普通的微服務(wù)的無狀態(tài)擴(kuò)展,otter-node的部署必須指定nid、ip、port,這種設(shè)計據(jù)說是為解決單機(jī)部署多實例而設(shè)計的,允許單機(jī)多node指定不同的端口(具體可以參考官方wiki,https://github.com/alibaba/otter/wiki/Node_Quickstart,這里不展開說明)。
還是直接看看如何在k8s上進(jìn)行適配吧。
這里采用了k8s的NodePort進(jìn)行處理。
NodePort 服務(wù)是引導(dǎo)外部流量到你的服務(wù)的最原始方式。NodePort,正如這個名字所示,在所有節(jié)點(diǎn)(虛擬機(jī))上開放一個特定端口,任何發(fā)送到該端口的流量都被轉(zhuǎn)發(fā)到對應(yīng)服務(wù)。如下圖所示。
在上面的配置中,可以使用IP1:3000 或者 IP2:3000 或者 IP3:3000 訪問service。
當(dāng)然,為了保證不綁定特定KVM的IP,我們在前面掛一個SLB服務(wù),通過訪問SLB的 虛擬IP:PORT 的形式訪問。
對于otter部署來說,otter-manager需要兩組 IP:PORT、每個node需要三組 IP:PORT。
注意,由于otter部署中,每個node需要暴露的port都是不同的,所以每次新增一個otter-node,都需要新增三組 IP:PORT。
我們以otter-node為例,來看下NodePort類型的Service的yml文件吧。
- kind為service
- type為NodePort
- 配置了三組端口。port/targetport都是應(yīng)用暴露端口,而nodePort是對外訪問端口。
6.總結(jié)
經(jīng)過這樣的改造,我們就能用k8s的部署otter-manager和otter-node了,并且能夠快速擴(kuò)容節(jié)點(diǎn)、彈性使用機(jī)器資源。
我們回顧一下其中的關(guān)鍵問題和技巧:
- Dockerfile編寫中,可以把環(huán)境相關(guān)依賴打成一個新的基礎(chǔ)鏡像,提高后續(xù)應(yīng)用鏡像的構(gòu)建速度。
- Dockerfile中,可以通過ARG定義一些構(gòu)建過程中的變量,進(jìn)行替換。
- 對于不同環(huán)境的配置文件,可以在不同環(huán)境(k8s的namespace)下配置不同的ConfigMap,然后在Deployment文件中通過volumeMounts的方式掛載進(jìn)去。
- 對于后臺進(jìn)程,需要改造為前臺進(jìn)程使得pod能夠保持
- 對于一些特定的環(huán)境變量,可以在Deployment中通過env進(jìn)行傳入。
其他開源項目如果有需要上k8s的,這些技巧應(yīng)該都能用上。
本文題目:擁抱云原生,如何將開源項目用k8s部署?
當(dāng)前路徑:http://m.fisionsoft.com.cn/article/dphgidp.html


咨詢
建站咨詢
