利用configmap覆蓋tomcat項目數據庫配置文件
一、需求背景及問題引入
這個實驗之前本來是做一個k8s jenkins發布tomcat項目的,想實現k8s的滾動升級:通過改pod 鏡像名來觸發系統完成deployment運行pod的滾動升級操作。(這個問題解決之后,后續會補充一篇結合jenkins發布整個流程的)
大致交代下這篇文章的實驗背景:測試項目來源於公司的一個線上舉報違規項目,我特意在gitlab上克隆了一個專門做測試。數據庫連接配置文件寫的是天翼內網ip,線上項目也是部署在天翼雲的機器上,也就是這個項目是通過內網方式連接數據庫跑起來的。
實驗環境:基於公司個人辦公電腦開的的vmware,開了4台虛擬機做的k8s集群(版本:v1.15.2),其中k8s-1,k8s-2既是工作節點也是master節點。
所以要想把項目在pod上成功跑起來,肯定是不能用這個天翼內網ip去連數據庫的,要把項目運行起來就要通過公網去連線上的數據庫(包括mongo+mysql)
數據庫內網ip:10.0.0.x; 外網ip:14.x.x.235
二、實驗嘗試及報錯
實現環境說明:k8s已經部署好jenkins的pod(用的是blueocean的官方鏡像),maven和jenkins通過nfs網絡存儲做了持久化,節點機器都已經掛載好對應的持久化目錄。
jenkins的持久化目錄為:/data/nfs-volume/jenkins_home
鏡像tomcat1:v8.5.51事先從官方網站下載,上傳到自己搭建的harbor倉庫里(k8s-4),下載下來的tomcat鏡像的工作目錄默認在 /usr/local/tomcat/ 上。jenkins發布,pipeline腳本會把jenkins workspaces下maven編譯好的項目war包(下圖的 ./target/xx.war)復制到tomcat1:v8.5.51的鏡像里面,形成需要跑應用項目的新鏡像:tomcat-deploy:v1。最后通過交付給k8s資源文件把tomcat項目跑起來。
這里我只發個tomcat項目的deployment.yaml的文件(這樣子掛載上去是不認的),test-conf(spec.template.spec.volumes.name)引入的是configmap.yaml的配置文件內容

1 kind: Deployment 2 apiVersion: extensions/v1beta1 3 metadata: 4 name: tomcat 5 namespace: public 6 labels: 7 name: tomcat 8 spec: 9 replicas: 1 10 selector: 11 matchLabels: 12 name: tomcat 13 template: 14 metadata: 15 labels: 16 app: tomcat 17 name: tomcat 18 spec: 19 volumes: 20 - name: test-conf 21 items: 22 - key: application-pro.properties 23 path: application-pro.properties 24 containers: 25 - name: tomcat 26 image: harbor.odljy.com/infra/tomcat-deploy:v1 27 ports: 28 - containerPort: 8080 29 protocol: TCP 30 volumeMounts: 31 - name: test 32 mountPath: /usr/local/tomcat/webapps/ROOT/WEB-INF/classes/config/application-pro.properties 33 subpath: application-pro.properties 34
曾經試過在交付資源清單給k8s之前,用sed去更改這個配置文件的內網數據庫ip。無論是改pod里面配置文件/usr/local/tomcat/.../application-pro.properties(不支持sed命令),還是改外面的 /data/nfs-volume/jenkins_home/tomcat_home/WEB-INF/classes/config/application-pro.properties(說沒有找到該文件,該目錄是nfs給jenkins做的持久化目錄),這個問題后面參考解決的文章有說。
三、實驗最終解決方案
這篇文章給了我解決思路(上面的一些錯誤文章也有說到):https://www.cnblogs.com/xxz-blog/articles/14293312.html
最關鍵的一點是保證pod啟動前,要把配置文件覆蓋過去,新增了一個tomcat的運行腳本負責解壓war包,覆蓋文件及跑起tomat


####### 1、構建發布鏡像和啟動服務腳本
(1)Dockerfile 文件
1 From harbor.odljy.com/public/tomcat:8.5.31 2 RUN /bin/cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone 3 4 #將webapps下的全部清空 5 RUN rm -rf /usr/local/tomcat/webapps/* 6 COPY wdtz-0.0.1-SNAPSHOT.war /usr/local/tomcat/webapps/ROOT.war 7 ADD runtomcat.sh bin/runtomcat.sh 8 CMD ["sh", "bin/runtomcat.sh"]
(2)runtomcat.sh(跟參考文章中復制路徑不同,我直接復制到ROOT的,這樣不需要帶項目名,直接訪問靜態頁面路徑就行)
1 cd /usr/local/tomcat/webapps 2 unzip /usr/local/tomcat/webapps/ROOT.war -d ROOT 3 rm -rf ROOT.war 4 \cp /tmp/application-pro.properties /usr/local/tomcat/webapps/ROOT/WEB-INF/classes/config/application-pro.properties 5 cd /usr/local/tomcat 6 sh /usr/local/tomcat/bin/catalina.sh run
####### 2、 k8s 資源交付部分
apiVersion: v1 kind: ConfigMap metadata: name: tomcat-mysql-conf namespace: public labels: name: tomcat-mysql-conf data: application-pro.properties: | spring.datasource.url=jdbc:mysql://14.xx.xx.235:8xx5/數據庫名?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true spring.datasource.username=yourusername spring.datasource.password=yourpwd 。。。
(2)deployment.yaml
1 kind: Deployment 2 apiVersion: extensions/v1beta1 3 metadata: 4 name: tomcat 5 namespace: public 6 labels: 7 name: tomcat 8 spec: 9 replicas: 1 10 selector: 11 matchLabels: 12 name: tomcat 13 template: 14 metadata: 15 labels: 16 app: tomcat 17 name: tomcat 18 spec: 19 volumes: 20 - name: tomcat-mysql-conf 21 configMap: 22 name: tomcat-mysql-conf 23 containers: 24 - name: tomcat 25 image: tomcat:v2.0 26 ports: 27 - containerPort: 8080 28 protocol: TCP 29 volumeMounts: 30 - name: tomcat-mysql-conf 31 mountPath: /tmp/application-pro.properties 32 subPath: application-pro.properties #這個不太清楚用法,先記下
(3)service.yaml(可要可不要,增加nodePort,為了給svc映射外網訪問)

1 apiVersion: v1 2 kind: Service 3 metadata: 4 name: tomcat 5 namespace: public 6 spec: 7 type: NodePort 8 ports: 9 - protocol: TCP 10 port: 8080 11 targetPort: 8080 12 nodePort: 3009 13 selector: 14 app: tomcat
(4)ingress.yaml(通過域名訪問:tomcat.odljy.com)

1 kind: Ingress 2 apiVersion: extensions/v1beta1 3 metadata: 4 name: tomcat 5 namespace: public 6 spec: 7 rules: 8 - host: tomcat.odljy.com 9 http: 10 paths: 11 - path: / 12 backend: 13 serviceName: tomcat 14 servicePort: 8080
####### 3、交付資源清單給k8s后,及測試項目可用性
[root@k8s-1 tomcat]# kubectl get pods -n public NAME READY STATUS RESTARTS AGE tomcat-5bfc545688-tt2n9 1/1 Running 0 17h
1、進去容器確認讀了新的配置文件,證明數據庫連接信息被覆蓋了

2、 tomcat日志,沒有jdbc連接錯誤
3、項目確實能跑起來了,測試發短信
4、證明項目能跑(不想搞壞數據庫數據,就不提交了表單信息了)