應用上K8S第三步:K8S整合Java應用
需求
當我們對Java應用完成Maven/Gradle打包並將映象推送至遠端倉庫後,剩下的工作就是應用上K8S了,涉及到的工作主要為:
編寫Deployment/Service/Ingress部署應用; 環境變數傳遞Xmx、應用名、環境名等個性化配置; configmap傳遞統一標準規範的jvm引數; 共享目錄統一管理配置檔案;
透過對Java應用執行依賴的JVM引數、執行目錄等內容的分析,需要分別透過K8S內建環境變數、Configmap、PV/PVC等功能進行不同程度的整合。
JVM引數管理
一套統一標準的JVM引數便於運維團隊對Java程式的統一管理,例如統一的記憶體引數、日誌目錄、gc日誌等等。我們將統一的JVM引數定義如下:
-server
-Xms2048m
-Xmx2048m
-XX:MaxPermSize:256m
-Dapp.name=test
-Denv=prod
-Djava.io.tmpdir=/tmp
# gc.log輸出到統一的日誌目錄
-Xloggc:/data/logs/gc.log
-XX:+PrintGC
-XX:+PrintGCDetails
-XX:+PrintGCTimeStamps
-XX:+PrintGCDateStamps
-XX:+PrintHeapAtGC
-XX:+PrintReferenceGC
-Dsun.jnu.encoding=UTF-8
-XX:+HeapDumpOnOutOfMemoryError
# dump檔案輸出到統一的日誌目錄
-XX:HeapDumpPath=/data/logs/HeapDumpOnOutOfMemoryError.dump
其中:
"-Xms2048m -Xmx2048m"從JVM引數拆分,需要K8S環境變數單獨傳遞變數,以便應用記憶體個性化調整; "-Denv=prod"從JVM引數拆分,需要K8S環境變數單獨傳遞變數,以便不同環境應用配置檔案訪問; "-Dapp.name=test"在Dockerfile構建階段就透過程式碼內部的變數進行自動配置; 剩餘的JVM引數因沒有個性化配置,統一透過configmap配置檔案進行統一管理;
1.Dockerfile 引數化傳遞
# vim Dockerfile
FROM harbor.xxx.com/public/centos-jdk8:1.0.0
MAINTAINER yunwei
#VOLUME /tmp
ARG JAR_FILE
ARG APP_NAME
ENV APP_NAME=${APP_NAME}
COPY ${JAR_FILE} ${APP_NAME}.jar
ENTRYPOINT ["/bin/sh","-c","java -Dapp.name=${APP_NAME} -Denv=${PROFILE} ${XM} -Xbootclasspath/a:/data/config/${APP_NAME} $JVM_OPTS -jar /${APP_NAME}.jar"]
其中:
"-Dapp.name"透過gradle打包映象傳遞; "-Denv"和"XM"透過K8S環境變數傳遞; "-Xbootclasspath"為配置檔案共享目錄; "$JVM_OPTS"透過K8S的configmap傳遞;
2.K8S整合變數和配置
我們透過Deployment中的環境變數和configmap來進一步整合環境執行引數:
# vim configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: jvmoptions
namespace: test
data:
JVM_OPTS: "-server -XX:MaxPermSize:256m -Djava.io.tmpdir=/tmp -Xloggc:/data/logs/gc.log -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -XX:+PrintReferenceGC -Dsun.jnu.encoding=UTF-8 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/data/logs/HeapDumpOnOutOfMemoryError.dump"
# vim Deployment.yaml
apiVersion: apps/v1
kind: Deployment
...省略...
spec:
containers:
- name: sysmonitor
env:
- name: PROFILE
value: "test"
- name: XM
value: "-Xms2048m -Xmx2048m"
- name: JVM_OPTS
valueFrom:
configMapKeyRef:
name: jvmoptions
key: JVM_OPTS
...省略...
目錄管理
透過JVM引數可以發現,應用執行依賴的執行目錄主要有:
/data/logs,gc日誌目錄和執行日誌目錄; /data/config/應用名,應用名的配置檔案目錄;
以上目錄我們一定要持久化,以便應用崩潰時能夠進行排查或後續日誌收集,K8S的解決方案是透過PV/PVC的方式實現持久卷的管理。
PV是叢集中的一塊儲存,可以由管理員事先製備( 靜態製備
), 或者使用儲存類(Storage Class)來動態製備
。PVC是使用者對儲存的請求, Pod 透過 PVC 申領 PV 資源,實現對儲存的使用。
雖然靜態製備和動態製備都能實現我們對儲存資源的使用,但是從目前對目錄使用情況的分析,靜態製備是最適合我們的使用方案。而動態製備更適用於多目錄及不同等級儲存資源的需求及動態分配,對我們目前的使用量不太適用。對於儲存的適用,我們統一基於NFS的檔案儲存:
# vim static-pv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-static
labels:
type: pv-static
spec:
storageClassName: nfs
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Recycle
mountOptions:
- vers=3
- async
- rsize=1048576
- wsize=1048576
nfs:
path: /data
server: 10.10.20.250
capacity:
storage: 10Gi
# vim static-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-static
namespace: test
labels:
type: pvc-static
spec:
storageClassName: nfs
accessModes:
- ReadWriteMany
resources:
requests:
storage: 5Gi
# Deployment掛載
# vim deployment.yaml
apiVersion: apps/v1
kind: Deployment
...省略...
template:
spec:
containers:
- name: test
env:
- name: PROFILE
value: "test"
- name: XM
value: "-Xms2048m -Xmx2048m"
- name: JVM_OPTS
valueFrom:
configMapKeyRef:
name: jvmoptions
key: JVM_OPTS
...省略...
ports:
- containerPort: 8090
volumeMounts:
- name: data
mountPath: /data
...省略...
volumes:
- name: data
persistentVolumeClaim:
claimName: pvc-static
我們在Nas上建立一個 data (10G)共享目錄,可方便對配置檔案進行統一管理:
將Nas 共享目錄掛載到K8S 的一個master節點上,可在容器外進行管理; /data/config目錄下的所有應用配置檔案,後續可在容器外手動git pull更新; 透過pv/pvc 將Nas 共享目錄 /data 掛載到應用pod容器內的 /data 目錄,多個pod共享檔案; 其他logs或其他目錄均由應用自動生成;
Deployment/Service/Ingress
完整的一套應用上K8S的部署如下:
# vim helloworld.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: helloworld
namespace: test
spec:
replicas: 1
selector:
matchLabels:
app: helloworld
template:
metadata:
name: helloworld
labels:
app: helloworld
spec:
containers:
- name: helloworld
env:
- name: PROFILE
value: "p2"
- name: XM
value: "-Xms2048m -Xmx2048m"
- name: JVM_OPTS
valueFrom:
configMapKeyRef:
name: jvmoptions
key: JVM_OPTS
image: harbor.xxx.com:8000/helloworld:1.1.21
imagePullPolicy: IfNotPresent
livenessProbe:
httpGet:
path: /app/health
port: 8090
initialDelaySeconds: 60
timeoutSeconds: 5
readinessProbe:
httpGet:
path: /app/health
port: 8090
initialDelaySeconds: 60
timeoutSeconds: 5
ports:
- containerPort: 8090
volumeMounts:
- name: data
mountPath: /data
imagePullSecrets:
- name: harbor-secret
volumes:
- name: data
persistentVolumeClaim:
claimName: pvc-static
---
apiVersion: v1
kind: Service
metadata:
name: helloworld
namespace: test
spec:
type: NodePort
selector:
app: helloworld
ports:
- port: 8090
targetPort: 8090
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: helloworld
namespace: test
spec:
rules:
- host: helloworld.xxx.net
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: sysmonitor
port:
number: 8090
總結
應用上K8S後並不意味著結束,相反我們仍還有其他需要工作要做:
Prometheus監控應用狀態; 流水線實現應用的版本更新、快速交付; 應用根據負載的彈性伸縮; 應用的日誌收集;
其實本文應用的日誌最終寫在NFS共享儲存上,還是將其持久化到叢集node節點上。尤其是在上百已經級別的情況下,畢竟NFS的效能也是我們不得不面對的一個問題。其最終的解決方案,需要我們去從容選擇。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70024420/viewspace-2930590/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 應用上K8S第三步:Maven打包K8SMaven
- 應用上K8S第二步:Gradle 打包K8SGradle
- Helm部署k8s應用K8S
- K8s 部署應用必備K8S
- 玩k8s? ----管理應用程式配置K8S
- 應用上K8S第一步:Dockerfile引數化構建技巧K8SDocker
- k8s中應用GlusterFS型別StorageClassK8S型別
- k8s 通過helm釋出應用K8S
- 使用 k8s 快速部署應用服務K8S
- 應用上K8S第四步:如何選擇合適的持久卷K8S
- K8s 下的應用管理 — 瞭解 HelmK8S
- K8s 下的應用管理 — 瞭解 HelmfileK8S
- K8S釋出應用步驟詳解K8S
- 五分鐘 k8s 實戰-應用探針K8S
- k8s學習筆記一(搭建&部署helloworld應用)K8S筆記
- 五分鐘k8s入門到實戰-應用配置K8S
- 深入玩轉K8S之外網如何訪問業務應用K8S
- K8s技術全景:架構、應用與最佳化K8S架構
- K8s理解初識到應用到理解K8S
- 騰訊遊戲 K8s 應用實踐|更貼近業務場景的 K8s 工作負載:GameDeployment & GameStatefulSet遊戲K8S負載GAM
- 使用Rancher在K8S上部署高效能PHP應用程式K8SPHP
- [譯]單應用跨多k8s叢集的部署與管理K8S
- 雲原生系列2 部署你的第一個k8s應用K8S
- K8s小白?應用部署太難?看這篇就夠了!K8S
- K8s 應用的網路可觀測性: Cilium VS DeepFlowK8S
- 利用 K8S 的反親和性構建高可用應用K8S
- 微服務從程式碼到k8s部署應有盡有大結局(k8s部署)微服務K8S
- 你的K8s 執行時環境安全嗎? KubeXray幫你保護K8s環境及應用K8S
- 普通公司不應該使用K8s - Anurag GoelK8SGo
- K8s 下的應用管理 — 私有 Helm Chart 的建立與維護K8S
- 更新應用時,如何實現 K8s 零中斷滾動更新?K8S
- 使用 k8s 部署你的第一個應用: Pod,Deployment 與 ServiceK8S
- 使用 Tye 輔助開發 k8s 應用竟如此簡單(一)K8S
- 使用 Tye 輔助開發 k8s 應用竟如此簡單(二)K8S
- 使用 Tye 輔助開發 k8s 應用竟如此簡單(六)K8S
- 使用 Tye 輔助開發 k8s 應用竟如此簡單(三)K8S
- 開發階段,將SpringBoot應用快速部署到K8SSpring BootK8S
- 在非k8s 環境下 的應用 使用 Dapr Sidekick for .NETK8SIDE