利用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、证明项目能跑(不想搞坏数据库数据,就不提交了表单信息了)