把 SpringBoot 部署到 K8s,竟然翻車(chē)了!
今天這篇我們?cè)俑乱粋€(gè)怎么把 SpringBoot 應(yīng)用部署到 K8s 上,本來(lái)我是想偷偷懶、照貓畫(huà)虎把上節(jié)課的改改鏡像名不就行了,沒(méi)想到,居然翻車(chē)咧,真的是想偷點(diǎn)懶都不行啊。具體怎么翻車(chē),咱們先往后看,在總結(jié)里再說(shuō)說(shuō),我對(duì) Go 相比于 Java 在云原生里的優(yōu)勢(shì)。
好了,咱們還是先假裝自己都是是小白哈,讓我?guī)Т蠹以俅螐牧汩_(kāi)始把一個(gè) SpringBoot 應(yīng)用部署到 K8s 上運(yùn)行。
SpringBoot 應(yīng)用,在 K8s 上運(yùn)行
怎么把一個(gè) SpringBoot 開(kāi)發(fā)的 Web 應(yīng)用部署到 K8s 集群上運(yùn)行,有哪幾個(gè)步驟要完成的呢,這里我們先歸納一下,后面依次對(duì)每一步進(jìn)行演示。
這里會(huì)把我們上面理論部分的知識(shí)點(diǎn)再串一遍,主要有這么幾個(gè)步驟:
- 完成應(yīng)用代碼的編寫(xiě)
- 把程序打包成容器鏡像
- 使用上一步打包的鏡像,創(chuàng)建應(yīng)用的Pod
- 用 Deployment 調(diào)度應(yīng)用
- 使用 Service 暴露應(yīng)用
- 通過(guò) Ingress 代理應(yīng)用
好了,這六步大家一定要記住,下面我們逐一展開(kāi),詳細(xì)說(shuō)說(shuō)。
完成應(yīng)用代碼的編寫(xiě)
這一步咱們?yōu)榱搜菔荆秃?jiǎn)單來(lái)搞一個(gè) HelloWorld 級(jí)別的代碼就行了,沒(méi)必要搞太復(fù)雜,再?gòu)?fù)雜的項(xiàng)目后面幾步的操作也是一樣。
首先,咱們建一個(gè) Maven 管理的項(xiàng)目,POM 文件里引入這幾個(gè)依賴
POM 文件里的依賴
POM里的依賴很簡(jiǎn)單,首先是 Spring Boot 程序都要先引入的spring-boot-starter-parent,其次我們演示的是 Web 應(yīng)用,所以在項(xiàng)目依賴?yán)镌僖?Spring MVC 的starter 即可。
至于應(yīng)用的代碼,也非常簡(jiǎn)單
應(yīng)用代碼
可以看到,僅就 HelloWorld 級(jí)別的代碼來(lái)說(shuō),并沒(méi)有比咱們演示的 Go 程序代碼多多少,主要原因是很多工作 SpringBoot 都已經(jīng)幫我們做好了。
代碼寫(xiě)好了,接下來(lái)我們把這個(gè) SpringBoot 應(yīng)用打成 Docker 鏡像。
把程序打包成容器鏡像
首先咱們準(zhǔn)備一下打包鏡像的 Dockerfile
FROM openjdk:8-jre
ADD target/*.jar /application.jar
ENTRYPOINT ["java", "-jar","/application.jar"]
把這個(gè)放在項(xiàng)目的根目錄里,具體 Dockerfile 里的命令咱們就不講了,就三個(gè)命令,可以在網(wǎng)管叨bi叨公眾號(hào)里回復(fù)docker,拿到一個(gè) docker 命令的手冊(cè),里面常用 Docker 命令的解釋都有。
下面把應(yīng)用打包成鏡像:
docker build -t registry.cn-hangzhou.aliyuncs.com/docker-study-lab/simple-app-java:v0.1
把鏡像上傳到遠(yuǎn)程倉(cāng)庫(kù):
docker push registry.cn-hangzhou.aliyuncs.com/docker-study-lab/simple-app-java:v0.1
這次,咱們還是把鏡像傳到,某位老好人創(chuàng)建的鏡像倉(cāng)庫(kù)里,大家練習(xí)的時(shí)候也可以往里傳,不過(guò)首先要在阿里云申請(qǐng)個(gè)免費(fèi)的鏡像云賬號(hào),然后用docker login 命令配置一下你的客戶端就行啦,阿里云的頁(yè)面上都有指示,實(shí)在不行了也可以在公眾號(hào)里問(wèn)我。
創(chuàng)建應(yīng)用的Deployment
還記得我在之前的文章 -- K8s 面向?qū)ο罄镎f(shuō)過(guò)
Deployment 是一個(gè)復(fù)合型的控制器,它包裝了一個(gè)叫做 ReplicaSet -- 副本集的控制器。ReplicaSet 管理正在運(yùn)行的Pod數(shù)量,Deployment 在其之上實(shí)現(xiàn) Pod 滾動(dòng)更新,對(duì)Pod的運(yùn)行狀況進(jìn)行健康檢查以及回滾更新的能力
所以,這里我們直接把步驟2、3合起來(lái)一起說(shuō)。其實(shí)也沒(méi)啥好說(shuō)的,畢竟 Go 實(shí)踐那篇文章里我們已經(jīng)講過(guò)一次了,直接上這次用的 YAML 配置
Deployment YAML
誒,我就是在這翻車(chē)的,一開(kāi)始我完全拷貝的 Go 實(shí)踐篇里的 Deployment 配置,部署后,服務(wù)不停的重啟,排查了一下,是在不停的OOM。
翻車(chē)截圖
因?yàn)樵蹅冎唤o Go 的那個(gè)應(yīng)用容器分配了 50M 內(nèi)存,這次用 SpringBoot 雖然也只是個(gè) HelloWorld 程序,但是卻跑不起來(lái),一請(qǐng)求容器就掛。這里就凸顯出 Go 在云原生下的第一個(gè)好處啦:占內(nèi)存小。
排查 K8s 問(wèn)題的方法,可參考之前的文章:想在研發(fā)群里裝?先學(xué)會(huì)這幾個(gè)排查K8s問(wèn)題的辦法
上面我直接把容器可用的內(nèi)存調(diào)成了 500M,不是說(shuō) Java 應(yīng)用占的內(nèi)存是Go應(yīng)用的 10倍,是我懶得一點(diǎn)點(diǎn)去試,直接設(shè)置成了 500M,反正 100 M,試過(guò)是不行的,哭!
用 Service 暴露服務(wù)
創(chuàng)建好上面這幾個(gè)對(duì)象后,我們的應(yīng)用只能在 K8s 集群的內(nèi)部使用,想能從外部訪問(wèn)就得把應(yīng)用暴露出來(lái),這個(gè)時(shí)候就需要 Service 這個(gè)對(duì)象了。Service 對(duì)象具體的概念解釋?zhuān)蹅冞€是看上一篇文章,這里不再贅述了。
下面是一個(gè)默認(rèn)的 Cluster IP 型的 Service,為啥只在集群內(nèi)暴露呢?因?yàn)橄旅嫖覀冞€會(huì)給 Service 加一層 Ingress,所以就不必再用 NodePort 型的 Service 單獨(dú)在節(jié)點(diǎn)上開(kāi)端口再向外暴露服務(wù)啦。
Service YAML
用 Ingress 代理Service
使用 Ingress 前咱們應(yīng)該干什么呢?對(duì),需要先安裝 Ingress Controller ,這里我們使用開(kāi)源的 Ingress-Nginx ,它本質(zhì)上就是個(gè) Nginx,也好理解,Ingress 是代理 Service 對(duì)象的,要想代理先得有個(gè)基礎(chǔ)設(shè)施的支持,只不過(guò) K8s 里任何東西都是面向?qū)ο蠓绞焦芾淼模跃陀辛?Ingress Controller,它支持不同類(lèi)型的 Ingress Controller,咱們用的這個(gè)是免費(fèi)的。
安裝參考下面這個(gè)鏈接,非常簡(jiǎn)單,上次發(fā)文章后,不安裝就跑過(guò)來(lái)問(wèn)我為啥運(yùn)行不了的,自己去面壁會(huì)兒。
https://kubernetes.github.io/ingress-nginx/deploy/
接下來(lái)就是聲明代理我們的 Web 應(yīng)用的 Ingress 對(duì)象
Ingress YAML
通過(guò) kubctl apply -f 命令把它提交給 K8s 集群,創(chuàng)建 Ingress 對(duì)象。
Ingress 對(duì)象創(chuàng)建好后,我們就能通過(guò) java-app.example.com 訪問(wèn)咱們的服務(wù)啦,當(dāng)然前提是在電腦上配置一下咱們的 hosts 文件,添加一下這個(gè)域名到127.0.0.1 的綁定。
看一下咱們的訪問(wèn)效果
K8s 運(yùn)行應(yīng)用的效果
常用命令
最近這兩天的實(shí)踐篇,我一直在給你們講 K8s 的各種資源對(duì)象怎么聲明、怎么配合著使用,操作時(shí)執(zhí)行的命令就提了一嘴,沒(méi)有展開(kāi)說(shuō)。主要的原因還是它的命令非常簡(jiǎn)單,自始至終我就用了一個(gè) kubectl apply 命令,下面我把 K8s 常用的命令組合放這里,供大家操作的時(shí)候參考。
- kubectl apply -f xxx.yaml 讓K8s 創(chuàng)建在集群里按配置文件創(chuàng)建/更新資源對(duì)象
- kubectl get pod | deploy | svc | ingress 查看集群中的pod、Deployment、Service、Ingress 資源的狀態(tài)
- kubectl describe pod | deploy | svc | ingress {$objectName} 查看具體資源對(duì)象當(dāng)前的詳細(xì)信息
- kubectl delete pod | deploy | svc | ingress {$objectName} 刪除指定對(duì)象
總結(jié)
講完這篇 SpringBoot 應(yīng)用上 K8s 的過(guò)程,咱們快速入門(mén)和實(shí)踐這個(gè)短系列就算完結(jié)了。
這里總結(jié)了一下 K8s 常用的入門(mén)知識(shí)以及相關(guān)的實(shí)踐操作,只能算是一個(gè)非常初級(jí)的入門(mén),還有其他很多非常高級(jí)的特性能讓我們控制 K8s 對(duì)應(yīng)用的各種調(diào)度動(dòng)作。