k8s通过configmap替换tomcat项目代码应用配置文件
场景描述
k8s部署tomcat服务,有时候需要根据环境的不同,替换掉项目里的数据库应用配置文件.
环境准备
当前kubernetes版本: v1.15.12
tomcat基础镜像: tomcat:8.5.31
war工程名: test
原war包数据库应用配置文件(mysqldb.properties)信息,这里为了测试将192.168.1.20数据库关闭,让tomcat服务无法访问
mysql.driver=com.mysql.jdbc.Driver
mysql.url=jdbc:mysql://192.168.1.20:3306/test?useUnicode=true&allowMultiQueries=true&characterEncoding=UTF-8
mysql.username=root
mysql.paw=123123
需要替换的数据库应用配置文件(mysqldb.properties)信息, 只有IP地址进行改动
mysql.driver=com.mysql.jdbc.Driver
mysql.url=jdbc:mysql://192.168.1.10:3306/test?useUnicode=true&allowMultiQueries=true&characterEncoding=UTF-8
mysql.username=root
mysql.paw=123123
需求解决
通过configmap直接挂载至目录中
Dockerfile
FROM tomcat:8.5.31
RUN rm -fr /usr/local/tomcat/webapps/*
ADD test.war /usr/local/tomcat/webapps/
制作tomcat:v1.0镜像
docker build -t tomcat:v1.0 .
configmap.yaml (数据库应用配置文件有所省略)
apiVersion: v1
kind: ConfigMap
metadata:
name: tomcat-mysql-conf
namespace: default
labels:
name: tomcat-mysql-conf
data:
mysqldb.properties: |
mysql.driver=com.mysql.jdbc.Driver
mysql.url=jdbc:mysql://192.168.1.10:3306/test?useUnicode=true&allowMultiQueries=true&characterEncoding=UTF-8
mysql.username=root
mysql.paw=123123
deployment.yaml
使用subpath参数挂载文件
kind: Deployment
apiVersion: extensions/v1beta1
metadata:
name: tomcat
namespace: default
labels:
name: tomcat
spec:
replicas: 1
selector:
matchLabels:
name: tomcat
template:
metadata:
labels:
app: tomcat
name: tomcat
spec:
volumes:
- name: tomcat-mysql-conf
configMap:
name: tomcat-mysql-conf
containers:
- name: tomcat
image: tomcat:v1.0
ports:
- containerPort: 8080
protocol: TCP
volumeMounts:
- name: tomcat-mysql-conf
mountPath: /usr/local/tomcat/webapps/test/WEB-INF/classes/mysqldb.properties
subpath: mysqldb.properties
交付资源至k8s
kubectl apply -f configmap.yaml
kubectl apply -f deployment.yaml
# 等待pod启动完成,进入pod容器查看是否有覆盖.
kubectl exec -it tomcat-685f6c5f69-nvc46 /bin/bash
root@tomcat-685f6c5f69-nvc46:/usr/local/tomcat# ls webapps/test/WEB-INF/classes/
mysqldb.properties
2.2. 问题出现:
为什么war包中只有configmap的挂载文件,文件也确实是这个,但是其他文件去哪里了?
2.3. 问题思考:
-
configmap文件挂载是否在pod的容器启动前?
是.
-
configmap文件挂载是否当路径不存在的时候自动创建目录路径?
经测试,当目录路径不存在的时候, 会自动创建目录.
-
tomcat服务何时解压war包,又有什么特性?
当tomcat服务执行启动脚本的时候会解压war包,生成一个同名工程, 但webapps下已存在与war包同名的工程目录,tomcat不会解压war包.
2.4. 问题解决
由上述可得,configmap挂载后在webapps下创建了test目录,导致在tomcat服务启动后,无法正常解压war包
办法一: 制作镜像的时候同时解压war包,其余不变. (镜像会非常大,不推荐)
办法二: 制作镜像的时候添加新的启动脚本,将configmap的文件放置在/tmp目录中(脚本中可以用环境变量来替换相应参数)
脚本会做出以下操作:
1. 进入webapps目录解压war包
2. 复制/tmp/mysqldb.properties至对应的目录中
3. 执行catalina.sh run 命令启动tomcat服务
此处使用方法二
runtomcat.sh
- 可使用环境变量,此处需要给脚本添加可执行权限 chmod +x runtomcat.sh
- /tmp/mysqldb.properties跟下面k8s deployment资源挂载路径相关
cd /usr/local/tomcat/webapps
unzip test.war -d test
\cp /tmp/mysqldb.properties /usr/local/tomcat/webapps/test/WEB-INF/classes/mysqldb.properties
cd /usr/local/tomcat
sh /usr/local/tomcat/bin/catalina.sh run
Dockerfile修改
FROM tomcat:8.5.31
RUN rm -fr /usr/local/tomcat/webapps/*
ADD test.war /usr/local/tomcat/webapps/
ADD runtomcat.sh bin/runtomcat.sh
CMD ["sh", "bin/runtomcat.sh"]
制作tomcat:v2.0镜像
docker build -t tomcat:v2.0 .
更改yaml文件
- 更改镜像版本 tomcat:v1.0 --> tomcat:2.0
- 更改mysqldb.properties文件挂载路径 /tmp/mysqldb.properties
...
...
containers:
- name: tomcat
# 镜像版本tomcat:v1.0 --> tomcat:2.0
image: tomcat:v2.0
ports:
- containerPort: 8080
protocol: TCP
volumeMounts:
- name: tomcat-mysql-conf
# 更改文件挂载路径
mountPath: /tmp/mysqldb.properties
subPath: mysqldb.properties
重新交付资源至k8s,可以发现原war包文件正常解压,并且数据库应用配置文件正常替换. 可在k8s中创建service资源测试下项目页面是否正常访问
下图摘自tomcat日志其中一段,证明可访问数据库192.168.1.10, 可通过kuberctl logs tomcat-xxx-xx 查看详细日志
测试:
对数据库应用配置文件的IP替换(192.168.1.10-->192.168.1.20),重新交付资源,查看tomcat日志会连接拒绝.
由此可得configmap挂载的配置文件被替换且tomcat服务正常连接数据库使用.
至此, k8s通过configmap替换tomcat项目代码应用配置文件已完成
如有疑问,可留下评论.