Home > OS >  DB Migration with helm
DB Migration with helm

Time:09-23

I am trying to migrate our cassandra tables to use liquibase. Basically the idea is trivial, have a pre-install and pre-upgrade job that will run some liquibase scripts and will manage our database upgrade.

For that purpose I have created a custom docker image that will have the actual liquibase cli and then I can invoke it from the job. For example:

apiVersion: batch/v1
kind: Job
metadata:
  name: "{{ .Release.Name }}-update-job"
  namespace: spring-k8s
  labels:
    app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
    app.kubernetes.io/instance: {{ .Release.Name | quote }}
    app.kubernetes.io/version: {{ .Chart.AppVersion }}
    helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
  annotations:
    # This is what defines this resource as a hook. Without this line, the
    # job is considered part of the release.
    "helm.sh/hook": pre-install, pre-upgrade
    "helm.sh/hook-weight": "5"
    "helm.sh/hook-delete-policy": before-hook-creation
spec:
  template:
    metadata:
      name: "{{ .Release.Name }}-cassandra-update-job"
      namespace: spring-k8s
      labels:
        app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
        app.kubernetes.io/instance: {{ .Release.Name | quote }}
        helm.sh/chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
    spec:
      restartPolicy: Never
      containers:
        - name: pre-install-upgrade-job
          image: "lq/liquibase-cassandra:1.0.0"
          command: ["/bin/bash"]
          args:
            - "-c"
            - "./liquibase-cassandra.sh --username {{ .Values.liquibase.username }} --password {{ .Values.liquibase.username }} --url {{ .Values.liquibase.url | squote }} --file {{ .Values.liquibase.file }}"

Where .Values.liquibase.file == databaseChangelog.json.

So this image lq/liquibase-cassandra:1.0.0 basically has a script liquibase-cassandra.sh that when passed some arguments can do its magic and update the DB schema (not going to go into the details).

The problem is that last argument: --file {{ .Values.liquibase.file }}. This file resides not in the image, obviously, but in each micro-services repository.

I need a way to "copy" that file to the image, so that I could invoke it. One way would be to build this lq/liquibase-cassandra all the time (with the same lifecycle of the project itself) and copy the file into it, but that will take time and seems like at least cumbersome. What am I missing?

CodePudding user response:

It turns out that helm hooks can be used for other things, not only jobs. As such, I can mount this file into a ConfigMap before the Job even starts (the file I care about resides in resources/databaseChangelog.json):

apiVersion: v1
kind: ConfigMap
metadata:
  name: "liquibase-changelog-config-map"
  namespace: spring-k8s
  annotations:
    helm.sh/hook: pre-install, pre-upgrade
    helm.sh/hook-delete-policy: hook-succeeded
    helm.sh/hook-weight: "1"
data:
{{ (.Files.Glob "resources/*").AsConfig | indent 2 }}

And then just reference it inside the job:

  .....
  spec:
  restartPolicy: Never
  volumes:
    - name: liquibase-changelog-config-map
      configMap:
        name: liquibase-changelog-config-map
        defaultMode: 0755
  containers:
    - name: pre-install-upgrade-job
      volumeMounts:
        - name: liquibase-changelog-config-map
          mountPath: /liquibase-changelog-file
      image: "lq/liquibase-cassandra:1.0.0"
      command: ["/bin/bash"]
      args:
        - "-c"
        - "./liquibase-cassandra.sh --username {{ .Values.liquibase.username }} --password {{ .Values.liquibase.username }} --url {{ .Values.liquibase.url | squote }} --file {{ printf "/liquibase-changelog-file/%s" .Values.liquibase.file }}"
  • Related