K8S部署Springboot專案

適合ingress-nginx接入外部負載均衡的部署 一文主要介紹瞭如何透過ingress-nginx對外暴露服務,以及與外部負載均衡的結合,下面我們透過將SpringBoot專案遷入K8S中,來完整了解下從一個Java專案的整體流程。

環境準備

1.名稱空間

K8S透過namespace劃分叢集資源。因此我們透過prod、test、develop來劃分生產環境、測試環境、開發環境。

在此我們主要以test進行演示。

2. 映象倉庫

我們透過harbor倉庫來儲存springboot專案的映象,可參考Docker部署spring boot體驗來了解helloworld專案從打包到上傳harbor倉庫的過程。

部署

1.建立名稱空間

kubectl create ns test

2.新增harbor認證

透過secret 可以實現類似docker login登入harbor倉庫認證過程。

#在對應的namespace下建立secretkubectl create secret docker-registry harbor ——namespace test ——docker-server=harbor。test。cn ——docker-username=admin ——docker-password=admin ——docker-email=test@test。cn

注意:

一定要在對應的namespace下建立secret,否則會導致從harbor倉庫pull映象認證不透過。

3.定義Deployment

通常Deployment、service、ingress 寫在一份yaml檔案中,為方便演示我們都進行單獨分解。

# 1。vim deployment。yamlapiVersion: apps/v1kind: Deploymentmetadata: name: helloworld namespace: testspec: replicas: 1 selector: matchLabels: app: helloworld template: metadata: name: helloworld labels: app: helloworld spec: hostAliases: - ip: “10。11。10。11” hostnames: - “api1。test。cn” - “api2。test。cn” - ip: “10。11。10。12” hostnames: - “api3。test。cn” containers: - name: helloworld env: - name: JAVA_OPTS value: “-Xmx128m -Xms128m -Dspring。profiles。active=test” image: harbor。test。cn/helloworld/helloworld:1311c4520122dfa67bb60e0103c9519fcb370e50 imagePullPolicy: IfNotPresent livenessProbe: httpGet: path: / port: 8080 initialDelaySeconds: 200 timeoutSeconds: 5 readinessProbe: httpGet: path: / port: 8080 initialDelaySeconds: 180 timeoutSeconds: 5 ports: - containerPort: 8080 resources: limits: cpu: “0。5” memory: “500Mi” requests: cpu: “0。5” memory: “500Mi” volumeMounts: - name: logdir mountPath: /logs - name: localtime mountPath: /etc/localtime - name: timezone mountPath: /etc/timezone imagePullSecrets: - name: harbor volumes: - name: logdir emptyDir: {} - name: localtime hostPath: path: /etc/localtime - name: timezone hostPath: path: /etc/timezone# 2。應用配置檔案kubectl apply -f deployment。yaml# 3。檢視# kubectl get pod -n testNAME READY STATUS RESTARTS AGEhelloworld-6f78bd8668-j6hmp 1/1 Running 0 3d18h

要點:

hostAliases:

用於指定適用於該專案的hosts解析,可根據實際情況進行新增。

env:

jvm啟動引數透過環境變數env傳遞,而args只適用於dockder build階段,因此不能使用。

resources:

容器預設會無限制佔用宿主機資源,因此需要進行限制。對於java 專案 xms xmx只是堆記憶體,實際程序所佔記憶體比這還大,例如某專案預設Xms Xmx都是128M,但是pod的資源限制為200M、300M都會導致OOM,

因此調整的資源需要比Xmx還要大

hostPath:

將宿主機節點檔案系統中的檔案或目錄掛載到叢集中,

由於基於宿主機的目錄,多副本跨節點必須保證目錄存在,否則可能導致失敗

emptyDir:

當pod被分配給節點時,首先建立emptyDir卷,並且只要該pod在該節點上執行,該卷就會存在。正如卷的名字所述,它最初是空的。pod中的容器可以讀取和寫入emptyDir卷中的相同檔案。儘管該卷可以掛在到每個容器中的相同或不同路徑上。當出於任何原因從節點中刪除pod時,emptyDir中的資料將被永久刪除。

容器時區:

掛在宿主機的localtime和timezone,保證專案日誌時間正常。

livenessProbe:

透過探針livenessProbe進行檢測,httpGet獲取的狀態碼等於200或小於400則正常。檢測失敗後,將根據使用restartPolicy策略。restartPolicy預設為always。

readinessProbe:

透過探針readinessProbe進行檢測,httpGet獲取的狀態碼等於200或小於400則正常。指示容器是否準備好服務請求。如果就緒探針失敗,則端點控制器將從與Pod匹配的所有服務的端點中刪除Pod的IP地址。預設每10秒檢測一次,連續失敗數為3,連續成功數為1。

initialDelaySeconds:

如果啟動時間超過initialDelaySeconds會導致livenessProbe、readinessProbe檢測不成功。readinessProbe 失敗導致無法接受請求,livenessProbe失敗導致容器不斷重啟。

因此initialDelaySeconds要大於實際啟動時間

注意:

對於SpringBoot專案的日誌檔案,我們並沒有進行持久化儲存,而是透過emptyDir臨時儲存,然後透過寫入ELK做長期儲存。

對於SpringBoot專案的資料檔案,無論透過hostPath還是emptyDir都不合適,需透過PVC進行持久化儲存。

4.定義service

# 1。vim service。yamlapiVersion: v1kind: Servicemetadata: name: helloworld namespace: testspec: type: NodePort selector: app: helloworld ports: - port: 8080 targetPort: 8080# 2。應用配置檔案kubectl apply -f service。yaml# 3。檢視狀態# kubectl get svc -n testNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEhelloworld NodePort 10。1。139。205 8080:30949/TCP 6d# 4。訪問# curl 10。1。138。205:8080Hello,world

對於NodePort型別的service,透過叢集所有節點的IP都可以訪問服務。

# curl 192。168。3。218:30949 Hello,world!# curl 192。168。3。219:30949 Hello,world!# curl 192。168。3。217:30949 Hello,world!# 原因:# 所有節點lvs資訊都有對service 30949埠的轉發,因此叢集內所有節點都可透過service訪問服務ipvsadm -l -n |grep -A 2 -B 2 30949TCP 192。168。3。217:30949 rr -> 10。244。2。100:8080

5.定義ingress-ingress

此部分細節可參考適合ingress-nginx接入外部負載均衡的部署 選擇適合自己的部署方式,本文我們使用預設的Deployment+NodePort進行部署。

# 1。vim ingress。yaml apiVersion: extensions/v1beta1kind: Ingressmetadata: name: helloworld namespace: testspec: rules: - host: hello。test。cn http: paths: - path: / backend: serviceName: helloworld servicePort: 8080# 2。應用kubectl apply -f ingress。yaml# 3。檢視# kubectl get ing -n testNAME CLASS HOSTS ADDRESS PORTS AGEhelloworld hello。test。cn 10。1。217。16 80 4d18h# kubectl get svc -n ingress-nginxNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEingress-nginx NodePort 10。1。217。16 80:30687/TCP,443:31826/TCP 15h# kubectl get svc -n ingress-nginxNAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGEingress-nginx NodePort 10。1。217。16 80:30687/TCP,443:31826/TCP 15h# 4。訪問# curl -x 192。168。3。218:30687 hello。test。cnHello,world!

注意:

預設ingress-nginx部署並不能讓我們從外部透過80埠訪問到服務,只能透過NodePort暴露的埠訪問。

總結

以上是整個SpringBoot專案的部署過程及需要注意的地方,個人認為K8S部署SpringBoot專案最主要的應該是資源限制、健康檢查及儲存這三點。

資源限制保證叢集內容器合理佔用宿主機資源,避免資源無限佔用導致叢集問題;

健康檢查保證叢集內容器正常執行,合理摘除不健康的節點,保證請求的轉發到健康節點;

選擇合適的儲存方式,保證專案的執行時資料、日誌檔案合理儲存;