K8S环境中,每次部署服务前更新数据库表

项目需求:K8S环境中,每次部署Spring服务前,更新数据库表。

分析:Spring服务启动时会自动加载类路径中的liquibase文件来更新数据库,但无法读取外部路径中liquibase文件,要想使用,只能将liquibase文件打成jar加入服务启动类路径。项目要求所有的数据库操作(包括schema/table)都是by tenant级别,该逻辑是由公司自有框架实现,短期难以通过直接调用liquibase api实现by tenant级别的数据库操作。

解决方案:新建init container运行新服务,新服务包含两个功能:下载最新liquibase文件+打包jar,将jar加入主服务类路径。

目录

1.新服务部分

2.主服务部分


1.新服务部分

下载最新liquibase文件,该项目中liquibase文件存放在Azure database。

下载后,首先按照gradle目录结构存放,并在根目录添加gradle.build文件。

String changelogDir = "/liquibaseJar/src/main/resources/db/changelog/";

新服务创建run.sh文件,用于执行build命令,app.jar实现下载功能。

#!/bin/bash
#env
echo "==========start download liquibase files=========="
java -jar /opt/eureka/app.jar

echo "==========show files in liquibaseJar=========="
ls liquibaseJar

echo "==========start build liquibase files jar=========="
cd liquibaseJar
gradle build
cd ../
cp /liquibaseJar/build/libs/liquibaseJar.jar targetLiquibaseJar

echo "==========show files in targetLiquibaseJar=========="
ls /targetLiquibaseJar

新服务创建Dockerfile文件,准备打包环境,该文件将在CI pipline执行,将服务打包成镜像。

FROM centos:7
EXPOSE 8080
RUN sed -i -e "s|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g" /etc/yum.repos.d/CentOS-*
RUN yum install wget -y
RUN mkdir -p /usr/local/jdk
RUN mkdir -p /usr/local/gradle
RUN wget https://services.gradle.org/distributions/gradle-5.0-bin.zip
RUN yum install unzip -y
RUN unzip -d /usr/local/gradle gradle-5.0-bin.zip
RUN wget https://download.java.net/java/GA/jdk11/13/GPL/openjdk-11.0.1_linux-x64_bin.tar.gz
RUN tar -zxf  openjdk-11.0.1_linux-x64_bin.tar.gz -C /usr/local/jdk
ENV JAVA_HOME="/usr/local/jdk/jdk-11.0.1"
ENV GRADLE_HOME="/usr/local/gradle/gradle-5.0"
ENV PATH="/usr/local/jdk/jdk-11.0.1/bin:/usr/local/gradle/gradle-5.0/bin:${PATH}"
RUN mkdir -p /liquibaseJar/src/main/resources/db/changelog/
RUN mkdir -p /targetLiquibaseJar
COPY resources/main/liquibaseJar/run.sh /run.sh
RUN yum install dos2unix -y
RUN dos2unix run.sh
COPY resources/main/liquibaseJar/build.gradle /liquibaseJar/build.gradle
COPY libs/dpi-meta-service-support-service.jar /opt/eureka/app.jar
# CMD ["/opt/eureka/app.jar"]

2.主服务部分

修改app.yaml,添加init container,其中dpi-meta-service-support即为新服务。

command中指定执行run.sh,如上所述,完成下载liquibase文件+build jar。

添加mount目录,让主服务可以访问包含liquibase文件的jar包。

    spec:
      initContainers:
        - name: liquibase-jar
          image: eureka-docker-prod.common.repositories.cloud.sap/cornerstone/dpi-meta-service-support:v1.7
          env:
          command:
            - "bash"
            - "/run.sh"
          volumeMounts:
            - name: liquibase
              mountPath: /targetLiquibaseJar

修改配置文件,将jar添加到主服务类路径中。

main_container:
    JAVA_TOOL_OPTIONS: "-Xbootclasspath/a:/liquibase/liquibaseJar.jar"

至此,每次在K8S部署服务,init container将下载最新liquibase文件,并build jar包,container 将jar包加入主服务类路径中,实现每次启动时更新数据库。