從零拆解-怎么把Go項目部署到K8s上運行
K8s 基礎
K8s現(xiàn)在在各家公司的普及度已經很高,網上介紹它的資料也有很多,那什么是K8s呢?它的本名叫Kubernetes(單詞太長,后面還是用 K8s 代替 )是一個基于容器技術的分布式架構方案。
它具備完善的集群管理能力,包括多層次的安全防護和準入機制、多租戶應用支撐能力、透明的服務注冊和服務發(fā)現(xiàn)機制、內建負載均衡器、故障發(fā)現(xiàn)和自我修復能力、服務滾動升級和線上擴容、可擴展的資源自動調度機制、多粒度的資源配額管理能力。還提供完善的管理工具,涵蓋開發(fā)、部署測試、運維監(jiān)控等各個環(huán)節(jié)。
總結一句話:是一套結合了容器編排和集群調度管理的大規(guī)模分布式系統(tǒng)解決方案。
在K8s 中會把各種資源抽象成對象--簡而言之就是面向對象,大到集群的節(jié)點(Node)、小到配置項 (ConfigMap) 都是對象,常用的有以下對象。
圖片
Pod是K8s 里的最小調度單元,Pod里面則是容器(一個Pod里可以有多個容器,但只有一個主容器,其他都是輔助它的)。
控制器則是管理 Pod 用的,對于我們來說常用的控制器只有Deployment,它能夠控制Pod的滾動更新。
圖片
Deployment 是一個復合型的控制器,它包裝了一個叫做 ReplicaSet -- 副本集的控制器。ReplicaSet 管理正在運行的Pod數量,Deployment 在其之上實現(xiàn) Pod 滾動更新,對Pod的運行狀況進行健康檢查以及回滾更新的能力。他們三者之間的關系可以用下面這張圖表示。
圖片
另外還有就是K8s的操作都是通過kubectl 把指令提交給集群的,這里匯總了一些比較常用的kubectl命令
- kubectl apply -f xxx.yaml 讓K8s 創(chuàng)建在集群里按配置文件創(chuàng)建/更新資源對象
- kubectl get pod | deploy | svc | ingress 查看集群中的pod、Deployment、Service、Ingress 資源的狀態(tài)
- kubectl describe pod | deploy | svc | ingress {$objectName} 查看具體資源對象當前的詳細信息
- kubectl delete pod | deploy | svc | ingress {$objectName} 刪除指定對象
Go Mall 項目部署到 K8s
接下來我們演示一下怎么把我們專欄的項目部署到K8s上,首先說明一點,因為我們項目依賴的MySQL和Redis都是在本地電腦上安裝的,把項目部署到容器后就沒辦法再用本地電腦上的MySQL和Redis了,所以在演示項目的K8s部署和運行時還需要把MySQL在Redis都部署到K8s上,這樣他們才能在集群內部通信。
所以我們首先把項目中 application.test.yaml 的數據庫和Redis的連接配置做一個更改:
app:
......
database:
master:
type:mysql
#通過k8s service name連接, 在k8s集群內的管理 mysql pod的service名是mysql
dsn:root:superpass@tcp(mysql:3306)/go_mall?charset=utf8&parseTime=True&loc=Asia%2FShanghai
maxopen:100
maxidle:10
maxlifetime:300000000000
redis:
addr:redis:6379#通過k8s service name連接, 在k8s集群內的管理 redis pod的service名是redis
password:123456
pool_size:
這也就意味著我們把項目部署到K8s時,還需要給它指定ENV環(huán)境變量為test,這樣才能應用上這個配置文件。
接下來我們就看一下go-mall項目的 Deployment 文件的定義
apiVersion: apps/v1
kind:Deployment
metadata:
name:go-mall
spec:
replicas:2
selector:
matchLabels:
app:go-mall-app
template:
metadata:
labels:
app:go-mall-app
spec:
containers:
-name:go-mall-container
image:go-mall:v202501111557
env:
-name:ENV
value:test
resources:
limits:
memory:"200Mi"
cpu:"50m"
ports:
-containerPort:8080
volumeMounts:
-name:app-log
mountPath:/home/applog
volumes:
-name:app-log
hostPath:
path:/tmp/applog
type:DirectoryOrCreate
Deployment中template下的配置是關于Pod的定義,其中容器鏡像指定的是 go-mall:v202501111557,我們每次發(fā)版本部署的時候都會給這個鏡像版本,然后再提交給K8s集群讓他們負責滾動更新。
env選項中我們指定了ENV=test的環(huán)境變量,此外我們還把容器中的日志文件目錄/home/applog 掛載到了電腦上的/tmp/applog目錄。
把項目部署到K8s上去后,如果不做任何操作它只能在K8s的集群內部訪問,如果想要在集群外部能訪問就需要用Service把它們暴露出來。
apiVersion: v1
kind:Service
metadata:
name:go-mall-svc
spec:
type:NodePort
selector:
app:go-mall-app
ports:
-name:http
protocol:TCP
nodePort:32080
port:8080
targetPort:8080
這個Service服務管理標簽為 app: go-mall-app 的Pod,并把它們通過端口32080暴露到集群外部。
好了關于項目的K8s配置介紹的差不多了,但是我們現(xiàn)在還不能把它們提交給K8s,需要先把依賴的MySQL和Redis部署上去。這里我給大家準備好了運行整個項目需要的全套K8s配置,點下面的鏈接即可下載:https://github.com/user-attachments/files/18385362/go-mall-k8s.zip
需訂閱專欄后聯(lián)系我開通項目權限才能訪問
下載解壓后,項目的目錄如下:
圖片
部署到K8s后怎么調試
把我們的項目部署到K8s后,因為在容器中運行,想要調試就沒有在本地IDE里那么方便了,這里介紹幾個必要的命令幫助大家調試。
首先是kubctl get pods | grep go-mall 來查看現(xiàn)在正運行著go-mall項目的Pod,上面我們講解過,我們給項目分配了兩個復制集,所以這個命令會顯示出兩個Pod。
如果我們想要要登錄到其中一個Pod中,那么需要我們執(zhí)行以下命令(注意下面的Pod名稱 go-mall- 后面是隨機的,執(zhí)行時記得換成自己當時查看到的Pod名稱)
kubectl exec -it go-mall-6459549b69-cmwsb -- /bin/sh
假如說我們通過kubectl get pods 查看Pod時發(fā)現(xiàn) go-mall-6459549b69-cmwsb 這個Pod 啟動失敗了,大概率是項目啟動時有問題,那么這個時候需要我們查看Pod當時寫到標準輸出中的日志,怎么查看呢?用下面這個命令。
kubectl logs go-mall-6459549b69-cmwsb
執(zhí)行的時候也是記得要換成自己的Pod名哦,不要直接抄過去。