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