FROM golang:alpine AS builder
RUN apk add --no-cache git gcc g++
RUN go get -v github.com/rubenv/sql-migrate/sql-migrate
RUN mv /go/bin/sql-migrate /bin/sql-migrate
Build and push it:
docker build -t projectname/sql-migrate-git .
docker push projectname/sql-migrate-git
The second thing is the Github authentification.
At this moment our git-container authenticates via an RSA key which is held in a Kubernetes Secrets, then it passes to a pod via an environment variable from where it’s taken by a bash script /opt/git/git.sh which is used to create a key-file /root/.ssh/id_rsa inside of the container, and this key finally is used to authenticate.
The initContainers in our Deployment currently looks like the next:
Now, we can start writing a manifest file templates/appname-api-migrations.yaml to describe our Kubernetes Job which later will be triggered by a Helm hook.
First, to make sure the Job is working – let’s write it without Helm variables and values, all pod’s environment variables will be set as plaintext values, and the action here will be git clone for now:
Here in the restartPolicy we’ve set to not to restart a container if it fails, as we’d like to see that migrations were failed, and the same in the backoffLimit=0 – to not to re-create a pod if it fails and just leave the job with the Failed status.
In the git clone a branch will be set from a Jenkins job, user and URL will be set in a values.yaml, and the authentication token will be kept with Helm secrets, later will move it to an environment variable.
Create the Job:
kk -n eks-dev-1-appname-api-ns apply -f appname-api-jobs.yaml
Check its logs:
kk -n eks-dev-1-appname-api-ns logs job/migration-job
Cloning into 'backend-services'...
-rw-r--r-- 1 root root 538 Oct 24 12:20 BS_1_init_schema.up.sql
-rw-r--r-- 1 root root 180 Oct 24 12:20 BS_2_add_brand_field.up.sql
-rw-r--r-- 1 root root 225 Oct 24 12:20 BS_3_alter_table.up.sql
-rw-r--r-- 1 root root 194 Oct 24 12:20 BS_4_add_created_at_field.sql
-rw-r--r-- 1 root root 272 Oct 24 12:20 BS_5_alter_table_nourishment_diet.up.sql
The repository was cloned, migration fils now are accessible.
Check the pod’s status:
kk -n eks-dev-1-appname-api-ns get pod
NAME READY STATUS RESTARTS AGE
migration-job-f72vs 0/1 Completed 0 9s
And the Job’s status:
kk -n eks-dev-1-appname-api-ns get job
NAME COMPLETIONS DURATION AGE
migration-job 1/1 2s 5s
Now can proceed with the exact migrations process.
To run migrations we need to create a config file that will be stored in a Kubernetes ConfigMap, but in this file, a database’s password must be set.
So, we will create a variable for the pod called $DB_PASSWORD, and will keep the actual password in a Kubernetes Secrets, and later in Helm, we will use the Helm secrets to store it encrypted in a chart’s values.
Also in this Secrets, we will store a value for a $GIT_TOKEN environment variable to be used in the git clone command.
Still one the templates/appname-api-migrations.yaml add a Secret:
"helm.sh/hook": pre-install,pre-upgrade: run the Job before helm install or upgrade (in our Jenkins pipeline it’s started with the helm secrets upgrade --install)
"helm.sh/hook-weight": "-1": priority of the creation of the resources, as first we need to create the ConfigMap and Secret that will be used by our Job, so set their weight less than for the Job
"helm.sh/hook-delete-policy": the default value is the before-hook-creation (check the documentation), set if for testing purpose, and then it can be changed to the hook-succeeded (but in that case you’ll not be able to check the logs if the migration will fail)
Add the annotations block to the ConfigMap and Secrets with the hook-weight less than in the Job.