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