擁抱雲原生,如何將開源項目用k8s部署?

微信搜索【阿丸筆記】,關注Java/MySQL/中間件各系列原創實戰筆記,乾貨滿滿。java

k8s以及雲原生相關概念近年來一直比較火熱,阿丸最近搞了個相關項目,小結一下。node

擁抱雲原生,如何將開源項目用k8s部署?

 

本文將重點分享阿里開源項目otter適配k8s部署的改造過程,其中的改造過程和技巧應該適用於將大多數開源項目改造到k8s進行部署。mysql

1.背景

otter是阿里開源的分佈式數據庫同步系統,基於數據庫增量日誌解析,並準實時同步到本機房或異地機房的mysql/oracle數據庫(相關內容能夠參考https://github.com/alibaba/otter,本文不作過多贅述)。git

爲了充分利用物理資源、快速擴容同步節點、擁抱雲原生,決定使用k8s部署otter。github

otter的項目總體上自成一體,出於改形成本考慮,儘可能在項目已有基礎上,作一些適配,不改動源代碼。web

本文將重點分享對於otter適配k8s部署的改造過程,有不當之處,還請多多指教。面試

涉及到幾個核心內容:sql

  • otter基本架構
  • dockerfile編寫
  • deployment編寫
  • 啓動腳本改造
  • K8s中固定ip/port訪問

2.otter的基本架構

擁抱雲原生,如何將開源項目用k8s部署?

 

典型管理系統架構,manager(web管理)+node(工做節點)docker

  • manager運行時推送同步配置到node節點
  • node節點將同步狀態反饋到manager上
  • 基於zookeeper,解決分佈式狀態調度的,容許多node節點之間協同工做
  • 基於Canal開源產品,獲取數據庫增量日誌數據。固然,otter採用了canal的嵌入式模式,不是獨立的canal節點。

基於以上部署架構,咱們只須要將otter-manager和otter-node部署到k8s上。數據庫

尤爲是otter-node,須要利用k8s實現節點快速水平擴展、計算性能彈性擴縮容。

2.Dockerfile編寫

2.1 otter-manager的Dockerfile

otter-manager比較簡單,包括幾個步驟:

  • 使用一個centos的基礎鏡像
  • 設置時區
  • 建立目錄
  • 拷貝下載好的manager.deployer-4.2.18到指定目錄
  • 使用啓動startup-new.sh腳本啓動(這裏對本來的啓動腳本作了一些改造,後文進行詳述)

具體以下所示:

擁抱雲原生,如何將開源項目用k8s部署?

 

2.2 otter-node的Dockerfile

otter-node稍微有所不一樣,根據官方文檔說明,須要安裝aria2來作文件傳輸。

 

注意注意,因爲aria2安裝很是慢,所以,咱們須要先安裝aria2做爲一個新的基礎鏡像,而後在新的基礎鏡像上構建otter-node鏡像,能大大提升後續鏡像構建速度。

 

新的基礎鏡像以下,命名爲 registry.xxx.com/xxx/otter-node-base:1.0。

擁抱雲原生,如何將開源項目用k8s部署?

 

而後在此基礎上構建新的otter-node鏡像。

擁抱雲原生,如何將開源項目用k8s部署?

 

注意,otter-node的配置方式比較特殊,須要先在otter-admin上獲取一個nid,而後才能運行一個otter-node。

因此,咱們在dockerfile中以ARG 聲明一個nid,而後在後續構建鏡像的時候,經過 --docker-arg 傳入nid具體的值。

固然,若是把nid看做一個配置文件的話,也能夠用下文提到的configmap的形式在Deployment中掛載進去

3.Deployment編寫

什麼是Deployment?

k8s的一個Deployment控制器爲 Pods 和 ReplicaSets 提供聲明式的更新能力。咱們經過編寫Deployment描述指望的目標狀態,而後 Deployment 控制器更改Pods或者ReplicaSets的實際狀態, 使其變爲指望狀態。

具體關於Deployment的知識不展開說明,能夠參考k8s官方文檔。

咱們須要部署測試環境與生產環境兩套集羣,而不管是otter-manager仍是otter-node,都依賴於讀取 conf/otter.properties 做爲配置。

所以,咱們須要根據環境,修改不一樣的otter.properties。

 

那麼,對於k8s部署來講,能夠採用同一份鏡像,而後在不一樣環境(k8s的不一樣namespace)中將otter.properties做爲configmap寫入,最後經過volume的形式掛載到pod的指定路徑上。

 

這裏對幾個名詞作簡單介紹,詳細內容能夠參考k8s官方文檔。

  • Configmap:一種 API 對象,用來將非機密性的數據保存到健值對中。使用時,Pods能夠將其用做環境變量、命令行參數或者存儲卷中的配置文件。(若是想存儲的數據是機密的,可使用 Secret,而不是configmap)
  • Volume:卷的核心是包含一些數據的一個目錄,Pod 中的容器能夠訪問該目錄。 所採用的特定的卷類型將決定該目錄如何造成的、使用何種介質保存數據以及目錄中存放 的內容。使用卷時, 在 .spec.volumes 字段中設置爲 Pod 提供的卷,並在 .spec.containers[*].volumeMounts 字段中聲明卷在容器中的掛載位置。

因此,首先在指定環境(namespace中)建立configmap,以otter.properties做爲key,以文件內容做爲value。

具體命令以下

kubectl create configmap otter-manager-dev-config --from-file=otter.properties=conf/otter-dev.properties -n otter-system

  • 在namespace爲otter-system中建立一個名字爲otter-manager-dev-config的configmap,其中,以otter.properties做爲key,以文件內容做爲value。

產生的configmap以下圖所示

擁抱雲原生,如何將開源項目用k8s部署?

 

而後,將這個configmap在Deployment中用volume進行引用,而後經過volumeMounts掛載到指定目錄,Deployment具體以下所示。

擁抱雲原生,如何將開源項目用k8s部署?

 

這裏須要特別注意volumeMounts的路徑覆蓋問題,須要在volumeMounts中配置subPath爲具體文件名。

4.啓動腳本改造

Otter包括兩個部分,管理控制檯manager和工做運行節點node,正常狀況下都是用各自的啓動腳本startup.sh啓動的。

爲了適配k8s,咱們須要對啓動腳本作改造,本文以otter-manager的啓動腳本爲例,otter-node也是相似。

將啓動腳本startup.sh改造爲 startup-moon.sh,重點解決兩個問題

  • 前臺進程保持運行
  • jvm參數自定義改造

4.1 前臺進程保持運行

因爲容器中用entrypoint啓動的進程爲1號進程,一旦1號進程執行結束,容器就會退出了。

而本來的startup.sh中,用java啓動後,使用 「&」 將java進程轉換爲後臺進程,因此startup.sh做爲1號進程會很快執行結束,容器就會自動退出了。

因此咱們須要將1號進程保持住,不要退出。

這裏考慮了兩個方案:

  • Startup.sh腳本中增長一個前臺進程進行保持,好比 tail -f /dev/null 命令
  • 將「&」去掉,讓java啓動後就做爲前臺進程一直保持

後來考慮了一下,仍是選擇了方案二。主要緣由是爲了利用pod自動重啓的特性。

若是Java進程意外退出了,那麼方案二就能使得1號進程也結束,而後pod就能自動重啓了。而方案一的話,因爲startup.sh腳本仍然在執行tail,因此即便java進程退出,1號進程也不會結束。

具體修改以下:

擁抱雲原生,如何將開源項目用k8s部署?

 

最終pod中的進程如圖所示

擁抱雲原生,如何將開源項目用k8s部署?

 

  • 1號進程是啓動腳本
  • 1號進程的子進程是otter的java應用進程(前臺進程)

4.2 虛擬機大小自定義配置

因爲otter項目中,將jvm的啓動參數配置在了start.sh中,不方便進行手動配置。

所以,將start.sh的配置jvm參數的邏輯註釋掉,採用本身配置的環境變量JAVA_OPTIONS進行注入。

擁抱雲原生,如何將開源項目用k8s部署?

 

這個環境變量的注入方式也比較簡單,就是在上面的Deployment中的env配置的(藍色框部分),方便之後手動修改jvm參數大小而不用修改鏡像。

擁抱雲原生,如何將開源項目用k8s部署?

 

5.k8s上固定IP/Port訪問

otter-node的部署中,有個比較特殊的地方。

不一樣於普通的微服務的無狀態擴展,otter-node的部署必須指定nid、ip、port,這種設計聽說是爲解決單機部署多實例而設計的,容許單機多node指定不一樣的端口(具體能夠參考官方wiki,https://github.com/alibaba/otter/wiki/Node_Quickstart,這裏不展開說明)。

 

仍是直接看看如何在k8s上進行適配吧。

這裏採用了k8s的NodePort進行處理。

NodePort 服務是引導外部流量到你的服務的最原始方式。NodePort,正如這個名字所示,在全部節點(虛擬機)上開放一個特定端口,任何發送到該端口的流量都被轉發到對應服務。以下圖所示。

擁抱雲原生,如何將開源項目用k8s部署?

 

在上面的配置中,可使用IP1:3000 或者 IP2:3000 或者 IP3:3000 訪問service。

固然,爲了保證不綁定特定KVM的IP,咱們在前面掛一個SLB服務,經過訪問SLB的 虛擬IP:PORT 的形式訪問。

對於otter部署來講,otter-manager須要兩組 IP:PORT、每一個node須要三組 IP:PORT。

注意,因爲otter部署中,每一個node須要暴露的port都是不一樣的,因此每次新增一個otter-node,都須要新增三組 IP:PORT。

咱們以otter-node爲例,來看下NodePort類型的Service的yml文件吧。

擁抱雲原生,如何將開源項目用k8s部署?

 

  • kind爲service
  • type爲NodePort
  • 配置了三組端口。port/targetport都是應用暴露端口,而nodePort是對外訪問端口。

6.總結

通過這樣的改造,咱們就能用k8s的部署otter-manager和otter-node了,而且可以快速擴容節點、彈性使用機器資源。

咱們回顧一下其中的關鍵問題和技巧:

  • Dockerfile編寫中,能夠把環境相關依賴打成一個新的基礎鏡像,提升後續應用鏡像的構建速度。
  • Dockerfile中,能夠經過ARG定義一些構建過程當中的變量,進行替換。
  • 對於不一樣環境的配置文件,能夠在不一樣環境(k8s的namespace)下配置不一樣的configmap,而後在Deployment文件中經過volumeMounts的方式掛載進去。
  • 對於後臺進程,須要改造爲前臺進程使得pod可以保持
  • 對於一些特定的環境變量,能夠在Deployment中經過env進行傳入。

其餘開源項目若是有須要上k8s的,這些技巧應該都能用上。

若是你有更好的一些方式和技巧分享,歡迎留言交流~~~

 

都看到最後了,原創不易,點個關注,點個贊吧~
文章持續更新,能夠微信搜索「阿丸筆記 」第一時間閱讀,回覆【筆記】獲取Canal、MySQL、HBase、JAVA實戰筆記,回覆【資料】獲取一線大廠面試資料。
知識碎片從新梳理,構建Java知識圖譜: github.com/saigu/JavaK…(歷史文章查閱很是方便)
相關文章
相關標籤/搜索