雲原生 容器 Kubernetes K8S Cloud Native

搞定K8s開發測試環境 Loft、DevSpace、Telepresence相助

善用三款容器輔助工具 加速雲原生軟體開發

2021-04-01
容器技術已是雲原生時代下重要的軟體技能,而Google推出Kubernetes容器管理平台後,K8s逐漸成為目前雲端技術的主流。為此,本文將介紹三款雲原生時代加速軟體開發的容器工具,包括Loft、DevSpace、Telepresence,分別加以介紹,並且示範如何安裝以及設定操作。

 

自從2015年Google推出Kubernetes容器管理平台後,圍繞在K8s(因Kubernetes由十個字母所組成,故常簡稱為K8s)的軟體生態圈——Cloud Native Computing Foundation(CNCF,Linux基金會底下的非營利組織)逐漸成為目前雲端技術的業界標準,而CNCF的雲原生定義如下:「雲原生技術有利於各組織在公有雲、私有雲和混合雲等新型動態環境中,構建和運行可彈性擴展的應用系統。雲原生的代表技術包括容器、服務網格、微服務、不可變基礎架構和聲明式API。」

因此,容器技術已是這雲原生時代下必備的軟體技能,且在2015年Docker公司將容器執行環境規格和容器映像檔規格捐給Linux基金會下的Open Container Initiative(OCI)後,容器成為雲端環境的基礎設施即代碼(Infrastructure as Code)和不可變基礎架構(Immutable Infrastructure)的樂高積木,而載運這些容器貨櫃的輪船,就是Kubernetes,其具備以下優缺點。

其優點包括:

1. 利用Kubernetes及CNCF龐大生態系統可提高生產力。

2. Kubernetes是面向雲端現代化的解決方案。

3. Kubernetes讓容器化應用系統運作更穩定。

4. Kubernetes的資源利用率比虛擬化方案更好。

而缺點則是:

1.在簡單的應用系統下,Kubernetes過於龐雜。

2. Kubernetes複雜的學習曲線會降低開發效率。

3.舊系統無法輕易就轉換到Kubernetes平台上。

4.在地端運行的成本可能比虛擬化方案更高。

礙於篇幅,上述優缺點分析,非本文重點,日後再詳述。經常有朋友詢問:「程式開發人員是否也要學習Kubernetes?」個人看法是「容器以內屬於開發人員,容器以外屬於Infra維運人員負責,而容器與容器間的系統架構則是架構師負責。」基本上,開發人員專注容器內的程式邏輯和實作,理解Kubernetes基本知識和熟悉容器部署操作即可,由於容器生態圈仍持續發展,必有省時省力的工具解決類似問題,正如本文介紹的三套工具一樣。

雲原生軟體開發的難題

而微服務架構適合中大型企業採用,單一大系統分成多組開發團隊維護,筆者過去在momo服務時,網購EC系統開發就有四組,加上又與手機App共用後端程式,常常會有共用程式版本須對齊的協作問題,除非系統已經複雜到這樣類似情況,否則無須隨風起舞。

微服務架構從無到有的開發流程如下,微服務設計與拆分是業務流程分析師(Business Analyst)或系統分析師(System Analyst),使用領域驅動設計(Domain Driven Design,DDD)方法論,定義出整體系統的核心域(Core Domain)和上下文對應(Context Map),而系統設計師(System Designer)與架構師協同,依照Clean Architecture定義(圖1)來設計微服務專案結構,程式設計師依照SA文件設計程式後,由DevOps工程師負責寫CI/CD自動化流程上版到容器儲存庫,而SRE工程師和雲端架構師建置雲端基礎架構,讓此微服務系統可以順利運行,因此雲原生軟體開發涵蓋多種技術專業領域,足以證明現代化雲原生開發比原本軟體開發還要龐雜。國泰金控就是依照上述微服務開發步驟,協助國泰產險發展微服務中台架構打造保險碎片化產品BeSafe,而此篇介紹的雲原生開發工具,可快速解決開發難題和節省雲端成本。

圖1  Clean Architecture定義。

首先,技術團隊需要決定使用何種開發環境?

1. 本機端Kubernetes:已經有Minikube、Docker Desktop、Microk8s等輕量容器平台,在本機電腦上就可直接部署使用,開箱即用,管理成本低,但無法與團隊共用,且大型複雜系統需要較高硬體資源時,或是需要本機以外的相依元件,如內部資料、不同網段的系統服務,便不適用。

2. 地端自建Kubernetes:除了開源K8s方式,還有企業等級的Red Hat OpenShift、VMware PKS和被SUSE收購的Rancher等,適合有機房和Infra維運的企業,撇除軟體授權成本,機房及系統管理成本高,透過VPN或內網連入,適合大型系統和企業內部開發,但部署程式須透過CI/CD排程,無法像本機端可自行部署,開發生產力較低。

3. 雲端付費Kubernetes:目前公有雲服務皆有提供,AWS EKS、微軟Azure AKS和Google GKE等,適合無機房的新創團隊和沒有維運團隊的組織,除了無須專人管理,隨需付費,短期成本,但長期費用高,整體仍比地端自建費用低,適合大型系統短期專案開發,但部署程式仍須透過雲端工具和CI/CD排程,開發生產力低。

此三者的比較,如表1所示。

綜合比較後,國泰金控多項開發專案都是採用雲端K8s,但多套環境,包含Dev開發、UAT測試和Stage準營運,因需要資源隔離避免相互影響,如圖2所示,故無法使用namespace切分,就需要至少三座K8s叢集,再加上至少兩個AZ(Availability Zones),雲端費用相當可觀,是否有類似虛擬化隨選自助的K8s虛擬叢集,可提供每位開發人員獨立的K8s環境,整合各階段開發測試環境,充分利用到雲端付費資源,答案就是K8s Virtual Clusters解決方案之一的Loft(https://loft.sh/)。

圖2  Kubernetes資源共用示意圖。

Loft安裝使用

在軟體開發過程,維運團隊大多只會負責營運環境的正常運行,而程式設計師使用的開發環境和測試環境通常需要自行維護,開發團隊人數眾多或面臨專案期限時,就會有爭搶資源的情況,在開發初期需要使用kubectl指令來部署容器專案,就必須具備可存取K8s叢集的能力和權限。而Loft這套工具具備下列特點:

‧虛擬叢集,比「實體」叢集成本更低,並且可以在數秒內建立或再次刪除,而且功能比簡單的namespace命名空間更強大。

‧在共用叢集環境中提供開發人員自行新增刪除K8s虛擬叢集的自助服務。

‧睡眠模式,在一段時間內不使用後,會將其命名空間和虛擬叢集切換成睡眠狀態,以便節省運算成本。

Loft的架構如圖3所示,使用者可透過kubectl、Loft CLI工具和Loft Web UI來控制,而Loft本身除了運行在K8s平台上,還可以連接其他K8s叢集,並且提供多租戶認證與授權,並以名為Kiosk系統來控管每位使用者或團隊的叢集資源使用限制,使用Rancher所開發的輕量Kubernetes - k3s(https://k3s.io/)作為虛擬叢集的運行環境,見圖4,以syncer元件來同步K8s環境的相關設定和參數,Loft的虛擬K8s叢集解決方案,目前已有Spotify、Datadog等公司採用,虛擬叢集專案網址(https://github.com/loft-sh/virtual-cluster)。

圖3  Loft架構示意圖。
圖4  Loft虛擬叢集架構圖。

安裝步驟

依照官方文件(https://loft.sh/docs/getting-started/setup),先安裝好kubectl工具和Helm v3版本,接著啟動雲端K8s,此文以微軟Azure AKS為例,筆者習慣直接執行「docker run -it -v ${HOME}/.azure:/root/.azure mcr.microsoft.com/azure-cli」,節省安裝時間並避免環境被污染,而Azure CLI詳細建置AKS過程請參閱「快速入門:使用Azure CLI部署Azure Kubernetes Service叢集」(https://docs.microsoft.com/zh-tw/azure/aks/kubernetes-walkthrough)。

啟動完成後取得AKS config使用憑證,執行「az aks get-credentials --resource-group YOUR_RESOURCE_GROUP --name AKS_CLUSTER」,大寫變數請替換成自己的環境設定,放置到「.kube/config」位置,並輸入「kubectl auth can-i create clusterrole -A」確認具備admin權限。

curl -s -L "https://github.com/loft-sh/loft/ releases/latest" | sed -nE 's!.*"([^"]*loft- linux-amd64)".*!https://github.com\1!p' | xargs -n 1 curl -L -o loft && chmod +x loft; sudo mv loft /usr/local/bin;

完成後,就可輸入「loft start」開始在AKS環境上安裝Loft,此時會自動判斷使用雲端K8s。接著會詢問,問題1選擇Yes;問題2「如何來存取Loft」,選擇via ingress,因多人共同使用需要透過網域;問題3「請輸入您的Loft服務的主機名稱」,此選項需要輸入網域,請輸入loft.YOUR_DOMAIN;問題4「管理者的Email信箱」,則輸入自己Email;問題5「是否要安裝nginx-ingress」,選擇Yes,此完整過程請見圖5。

圖5  loft start輸入過程。

接著會出現將問題3的網域,設定AKS的外部IP,請另開終端機,輸入「kubectl get services -n ingress-nginx」。

取得外部IP位置之後,在網域DNS伺服器上新增A Record,設定對應到此IP,工具被自行判斷DNS是否生效,完成之後就會顯示登入資訊和SSL憑證設定連結,如圖6所示。

圖6  完成Loft start設定。

此時開啟畫面上的網址,會出現憑證錯誤訊息而無法使用,故須安裝Cert-Manager,使用Let's Encrypt服務來啟用HTTPS憑證功能,步驟一輸入下方指令:

helm install cert-manager cert-manager  --repo https://charts.jetstack.io \   --set installCRDs=true \   --namespace cert-manager \   --create-namespace \   --wait

步驟二,透過Helm CLI更新Loft服務上的HTTPS憑證:

helm upgrade loft loft --repo https://charts. devspace.sh/ \   --namespace loft \   --reuse-values \   --set certIssuer.create=true \   --set certIssuer.email=youremail@   yourdomain.com

步驟三,檢查Loft憑證更新狀態,執行「kubectl get certificates -n loft -w」,當READY變成True,就表示完成。接下來是最後步驟,讓Loft UI可以透過Helm工具管理cert-manager版本更新:

curl -L "https://raw.githubusercontent. com/loft-sh/loft/master/hack/import- helm-release.sh" | bash -s -- "cert-manager" "https://charts.jetstack.io/"

此時就可重新載入那loft.YOUR_DOMAIN網址,可看到圖7的登入畫面,輸入完成Loft start過程所顯示的使用者admin與密碼,就完成Loft安裝,若忘記那帳密,可重新輸入「loft start」,就會再次顯示。

圖7  Loft服務登入畫面。

設定使用者叢集環境

依照Prepare User Clusters說明(https://loft.sh/docs/getting-started/clusters),免費授權可有兩座共用叢集,此時只用這座AKS即可,在Loft Web UI點選左邊選單Clusters > 選擇中間loft-cluster > 按下Cluster頁籤,中間Cluster Subdomain for Spaces是Loft免費提供的子網域,輸入自己喜歡的名稱,就可使用此子網域來對應Web專案,如圖8所示。

圖8  kubedev.sh的子網域設定。

新增使用者

最後,替開發團隊新增帳號,點選左邊選單Users > 右邊「Add User」,輸入Username、Email Address和Display Name後再按下〔Create〕,就會出現如圖9所示的網站連結,再將此網址提供給開發人員,就可自行登入此Loft UI,建立開發人員自己的虛擬叢集。

圖9  Loft使用者邀請網址畫面。

新增並使用虛擬叢集

開發人員安裝好kubectl和Loft CLI後,點擊邀請網址,便出現已填寫好的Display Name和待輸入的密碼。輸入完成登入後,就進入Loft UI,左邊選單則缺少Admin選項,接著點選單vClusters > 右邊「Create vCluster」,輸入可辨識的Name和Namespace,點開Advanced Options欄位,可看到虛擬叢集是使用rancher/k3s容器映像檔,如圖10所示,按下〔Create〕,中間就會出現此名稱的虛擬叢集。等待狀態為Running後,就可使用kubectl來控制此vCluster,再按下右邊Actions下方的connect圖示,會顯示如何以Loft CLI連接到此虛擬叢集。

圖10  建立vCluster選項畫面。

隨即在開發人員的終端機畫面上輸入「loft login https://loft.YOUR_DOMAIN」,會轉導至Loft Web UI,登入成功後,則顯示「Successfully logged into loft at https://loft.YOUR_DOMAIN」。

接著連接建立好的虛擬叢集,輸入「loft use vcluster YOUR_VCLUSTER --cluster loft-cluster --space YOUR_SPACE」,會將此虛擬叢集的kubernetes config憑證檔下載到.kube/config位置,供kubectl遠端控制。

此時輸入「kubectl get node」和「kubectl cluster-info」,確認可正常使用虛擬叢集後,嘗試部署Nginx服務,執行「kubectl create deployment --image=nginx nginx」,再Port Forward至本機8080 Port,輸入「kubectl port-forward nginx-XXXXXXXX-YYYYY 8080:80」,開啟「http://localhost:8080」,就可看到Nginx歡迎頁面。若想透過loadbalancer方式提供服務到外部,則輸入「kubectl expose deploy/nginx --port 80 --target-port 80 --type LoadBalancer」,在Loft UI的vCluster頁面內的Services頁籤中,同時可看到外部IP對應狀態,如圖11所示。

圖11  vCluster的Services清單。

經過上述操作,開發人員就有自己可獨立操作的Kubernetes開發環境,而此虛擬叢集開發架構,是使用Auzre AKS服務,安裝Loft叢集共用服務,執行獨立的K3s容器虛擬叢集,開發人員或團隊可自行部署容器應用到K3s vCluster,並隨時隨地可自行新增重建,此開發架構如圖12所示。

圖12  Loft vCluster開發架構。

DevSpace操作說明

上述kubectl部署操作,如果是不具備Kubernetes知識的開發人員必定一頭霧水,因此介紹另一套也是由Loft團隊所發展的開發工具DevSpace(https://devspace.sh/)。

DevSpace是針對Kubernetes環境的Client端開源開發工具,具備以下特點:

‧直接在Kubernetes內部建立,測試和除錯應用程式。

‧透過自動載入進行開發:無須重新建立映像或重新啟動容器,便可更新正在運行中的容器。

‧統一團隊內部以及整個開發、測試和營運的部署流程。

‧自動執行重複任務以進行映像構建和部署。

DevSpace是直接在本機端安裝單一CLI工具來運行,雖然多數情況下可直接在IDE終端機直接使用,但仍需要熟悉Docker容器技術,才能排除各式程式框架串接時所遇到的障礙,而DevSpace不需要服務器端組件,因為它是藉由kube-context與kubectl的工具與K8s叢集溝通。

整合Spring Boot專案

首先安裝DevSpace CLI工具,執行如下指令:

curl -s -L "https://github.com/loft-sh/ devspace/releases/latest" | sed -nE 's!.*"([^"]*devspace-linux-amd64)".*!https:// github.com\1!p' | xargs -n 1 curl -L -o devspace && chmod +x devspace; sudo install devspace /usr/local/bin;

下載Spring Boot RESTful範例,官方說明文件在「https://spring.io/guides/gs/rest-service/」,請輸入「git clone https://github.com/spring-guides/gs-rest-service.git」,切換至complete目錄,輸入「devspace init」,啟動DevSpace初始化程序。

然後,會進行詢問。問題1「專案找不到Dockerfile,請問後續處理方式?」,選擇為此專案建立Dockerfile;問題2「此專案是使用何種程式語言開發?」,選擇Java;問題3「使用那一種容器儲存庫(Registry)來存放Docker映像檔?」,選擇hub.docker.com;問題4「容器映像檔的名稱為何?」,輸入YOURNAME/springboot-rest;問題5「所建立的Dockerfile是使用在哪個開發環境?」,選擇build;問題6「要如何部署此專案?」,選擇透過component-chart。透過六個問題,就完成Dockerfile產製和建立devspace.yaml設定檔,上述過程如圖13所示。

圖13  DevSpace初始化過程。

接下來,只須輸入「devspace dev」就可部署到K8s虛擬叢集,但在容器建置過程,指出Dockerfile中的「RUN mvn -T 1C install && rm -rf target」發生Maven build failure,無法完成部署,因此移除此一RUN指令,並將build.sh宣告成可執行,輸入「chmod +x build.sh」,再次執行「devspace dev」就可正常啟動在遠端虛擬叢集,並在localhost上測試,在Loft Web UI中可查看到此Pod和Service。測試完成,輸入「devspace deploy」,完成服務部署,與其他微服務串接,若需要對外開通,則執行「depspace open」,選擇透過domain,再輸入服務網域名稱,可利用早先Loft的Cluster Subdomain免費服務,使用*springboot.philip.kubedev.sh*,開啟此網址就可看到成果,此過程請見圖14,且在Loft UI中的vCluster內,其Ingresses頁籤,可查看網域名稱和外部對應IP,如圖15所示。藉由此操作示範可體認到Loft和DevSpace團隊有意逐步整合這兩套工具。

圖14  DevSpace部署和對外開通過程。
圖15  Loft vCluster中Ingresses對應情況。

Telepresence使用說明

而Telepresence(https://www.telepresence.io/)是另一套與DevSpace類似的輔助工具,比DevSpace更早發展,它可在本地端運行單一服務,同時該服務是連接到遠端Kubernetes叢集,這讓微服務應用開發人員無縫使用,其具備以下特色:

‧即使單一服務相依於叢集中的其他服務,也可在本地端快速開發,馬上更改程式並存檔,可立即看到修改後的新服務。

‧可使用本機所安裝的任何工具來測試、除錯、編輯程式,例如可使用IDE Remote Debugging。

‧讓本地端開發電腦就像是Kubernetes叢集中的一部分,如果本機端的應用程式無法即時部署到遠端叢集時,也是很容易達成。

首先安裝Telepresence工具,指令如下:

curl -s https://packagecloud.io/install/ repositories/datawireio/telepresence/ script.deb.sh | sudo bash sudo apt install --no-install-recommends  telepresence

同樣使用Spring Boot RESTful範例,部署到遠端虛擬叢集,只須輸入「telepresence --new-deployment springboot --run ./mvnw spring-boot:run」,等待遠端容器啟動後,就可看到Spring Boot歡迎畫面,此時Loft UI的vCluster就有一個名為springboot的Pod。

若想取代已經在虛擬叢集執行的服務,如之前devspace deploy部署好的服務,只須輸入「telepresence --swap-deployment YOUR_DEPLOYMENT --run ./mvnw spring-boot:run」,就可將遠端虛擬叢集的服務停止,透過VPN機制轉導至本機端服務,此範例無法突顯此工具在VPN串接K8s叢集的優異功能,接著以Redis示範。

Quarkus讀寫Redis

因Quarkus是新一代雲原生開發框架,所以比Spring Boot更簡單就可在雲端K8s叢集上開發除錯,所以選擇Quarkus來示範讀取Redis內的資料,以便模擬兩個微服務(Quarkus和Redis),分別在各自電腦運行,卻可串接在一起。

首先,在虛擬叢集建立Redis服務,執行「kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook/redis-master-deployment.yaml」建立Redis容器,再輸入「kubectl apply -f https://raw.githubusercontent.com/kubernetes/examples/master/guestbook/redis-master-service.yaml」建立redis-master服務名稱,完成Redis資料庫建立。

再依照Quarkus官網使用Redis Client範例(https://quarkus.io/guides/redis),完成Quarkus Redis Client專案開發後,輸入「telepresence --new-deployment quarkus --run ./mvnw quarkus:dev」啟動本地端服務,存取遠端虛擬叢集上的Redis資料,比照網頁範例,以POST方式呼叫API寫入,「curl -X POST -H "Content-Type: application/json" -d '{"key":"first","value":10}' http://localhost:8080/increments」,再讀取此first的數值,將得到下面結果:

# curl http://localhost:8080/increments/ first {"key":"first","value":10}

再啟動另一個Redis微服務,取代遠端叢集上的redis-master,輸入「telepresence --swap-deployment redis-master --docker-run --rm -p 6379:6379 k8s.gcr.io/redis:e2e」,在本機端使用Docker執行Redis容器,並以VPN方式接到虛擬叢集,輸入「docker ps」,就可看到兩個容器,分別是redis和datawire/telepresence-local。為了驗證Quarkus微服務已經連接到本地端的Redis,再次以POST方式寫入,「curl -X POST -H "Content-Type: application/json" -d '{"key":"cathay","value":168}' http://localhost:8080/increments」,確認寫入結果:

# curl http://localhost:8080/increments/ cathay {"key":"cathay","value":168}

為了證明是寫入本地端Redis,故進入到Redis容器中,卻是否有此key和value,輸入「docker exec -ti YOUR_REDIS bash」,使用redis-cli查詢,確實有成功寫入,如圖16所示。

圖16  查詢本地端容器狀態及Redis內的資料。

雖然DevSpace也可達成上述的兩個微服務互連,但系統架構運作方式不同,兩者架構比較可參考圖17,DevSpace是直接部署到遠端K8s叢集,再Port Forward到本機端,但Telepresence是在遠端叢集啟動Deployment服務以VPN方式連接到本機端,且支援本地端以容器方式替換,這是DevSpace無法做到,但DevSpace提供UI介面支援Kubenetes相關查詢與操作,且涵蓋完整Kubernetes開發階段的各種功能,支援開發、測試、部署和對外開通等kubectl指令,兩者比較如表2所示。

圖17  Telepresence與DevSpace網路架構比較圖。

結語

這三套工具都是CNCF生態圈成員,雲原生體系的相關工具和廠商可在CNCF Landscape網頁(https://landscape.cncf.io/)中查詢,由於Kubernetes虛擬叢集解決方案仍在發展中,正如虛擬化趨勢推升VMware成為主要的虛擬化廠商,未來還會有類似的解決方案逐步浮現,將會有更多的應用案例,如CI/CD和AI/ML等範疇,希望藉由這類工具可以解決目前在雲原生環境開發面臨到的各種問題。

前一期使用VSCode Remote Development來開發Quarkus專案,接下來將說明如何整合DevSpace和Telepresence開發工具,使用容器開發環境,無須再費時安裝開發環境,團隊共同使用可避免環境設定不一致造成的異常問題,下期將有詳細VSCode整合和雲原生開發工具的內容。

<本文作者:鄭淳尹,Docker.Taipei社群共同發起人,國泰金控技術架構師,曾任微軟MVP、momo購物網架構師、臺北榮民總醫院資訊工程師、玉山銀行資訊處專員、宏碁eDC維運工程師,系統維護及開發設計超過16年。開源技術愛好者,曾在多間大學資工系擔任Docker容器技術講師,並翻譯審閱多本容器技術書籍。>

 


追蹤我們Featrue us

本站使用cookie及相關技術分析來改善使用者體驗。瞭解更多

我知道了!