Рубрики
Uncategorized

Kubernetes: Бег миграции SQL с работой Kubernetes и Helm крюк

У нас есть проект, работающий в Kubernetes, которые необходимо запустить миграции SQL во время развертывания. Чтобы бежать … с меткой kubernetes, учебник, sql, devops.

У нас есть проект, работающий в Kubernetes, которые необходимо запустить миграции SQL во время развертывания.

Чтобы запустить миграцию надо клонировать репозиторий GitHub и запустить на самом деле миграции, хранящиеся в нем.

В настоящее время это делается с Kubernetes initContainers и есть два из них — первый с Гит клонирует репозиторий с файлами миграций в Кубернаны объем , а потом еще один с SQL-мигрировать Запускает эти миграции из этого общего объема.

Тем не менее, есть несколько вопросов с этим подходом:

  1. Каждый раз, когда мы запускаем новый POD, он управляет своими инициаторами и миграциями
  2. Если развертывание раскрутит пару стручков — каждый запускает миграции
  3. Если миграции будут работать на w whume и не будут отвечать на готовность Kubernetes — он может быть убит без отделки миграций

Чтобы избежать все вышеперечисленного, давайте перенастроить процесс, используя Kubernetes Работа Чтобы запустить только один POD и добавив Хелм крючки Чтобы вызвать миграцию во время развертывания.

Примечание: KK вот псевдоним для kubectl.

Подготовка

Docker Image

Сначала давайте создадим наш собственный докерный образ с Blackjack и Git и https://github.com/rubenv/sql-migrate Отказ

Создать DockerFile:

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

Построить и толкать его:

$ docker build -t projectname/sql-migrate-git .
$ docker push projectname/sql-migrate-git

Аутентификация Git.

Второе вещью — аутентификация GitHub.

На данный момент наш Git-Container аутентифицируется через ключ RSA, который проводится в секретах Kubernetes, то он проходит в POD через переменную среды, откуда она принимается скриптом Bash /opt/git/git.sh который используется для создания ключевого файла /root/.ssh/id_rsa Внутри контейнера, и этот ключ, наконец, используется для аутентификации.

initcontainers В нашем развертывании в настоящее время выглядит следующим:

...
      initContainers:
      - name: git-clone
        image: projectname/git-cloner
        env:
        - name: SSH_PRIVATE_KEY
          valueFrom:
            secretKeyRef:
              name: git-ssh-key
              key: id_rsa
        - name: REPOSITORY_URL
          value: {{ .Values.git.repo }}
        - name: GIT_BRANCH
          value: {{ .Values.git.branch }}
        command: ['sh', '-c', '/opt/git/git.sh']
        volumeMounts:
          - name: git-volume
            mountPath: "/git"
            readOnly: false
      - name: init-migration
        image: fufuhu/sql-migrate:latest
        command: ['sh', '-c', 'while [! -d /git/db/migrations]; do sleep 2; done && sleep 2; /bin/sql-migrate up -config=/config/config.yaml -env=main']
        volumeMounts:
          - name: migration-config
            mountPath: "/config/"
            readOnly: true
          - name: git-volume
            mountPath: "/git"
            readOnly: false
...

Много шагов, много объектов, сложный процесс.

Вместо этого будем использовать логин и Github токен который будет передан в наш контейнер из переменных среды, а затем мы можем клонировать репозиторий через HTTPS.

Давайте проверим это:

~ # export GIT_AUTHUSER=backend-user
~ # export GIT_AUTHKEY=cdc***0fe
~ # git clone
[https://$GIT_AUTHUSER:$GIT_AUTHKEY@github.com/projectname-dev/backend-services.git](https://%24GIT_AUTHUSER:%24GIT_AUTHKEY@github.com/projectname-dev/backend-services.git)
Cloning into 'backend-services'…
…
Receiving objects: 100% (5115/5115), 846.55 KiB | 1.30 MiB/s, done.
Resolving deltas: 100% (2826/2826), done.

Хорошо, «это работает» ©

Миграция SQL в Куберане

Теперь мы можем начать писать файл манифеста Шаблоны/appname-api-mygrations.yaml Для описания нашей работы Kubernetes, которая позже будет вызвать рулем крюка.

Работа Kubernetes

Гит клон

Во-первых, чтобы убедиться, что работа работает — давайте напишем его без переменных и значений HELM, все переменные среды POD будут установлены в виде открытых значений, а действие здесь будет Гит клон теперь:

apiVersion: batch/v1
kind: Job
metadata:
  name: "migration-job"
  labels:
  annotations:
spec: 
  backoffLimit: 0
  template:
    metadata:
      name: "migration-job-pod"
    spec:
      restartPolicy: Never
      containers:
      - name: db-migrations
        image: projectname/sql-migrate-git:latest
        command: ["/bin/sh", "-c"]
        args:
          - git clone --single-branch --branch develop [https://backend-user:cdc***0fe@github.com/projectname/backend-services.git](https://backend-user:cdc***0fe@github.com/projectname/backend-services.git) &&
            ls -l backend-services/db/migrations

Здесь, в RestArtPolicy Мы установили не перезапустить контейнер, если он не удается, так как мы хотели бы видеть, что миграции были выполнены неудачными, и то же самое в Backofflimit = 0 — Чтобы не повторно создать стручок, если он не удастся и просто оставьте работу с Не удалось статус.

В Гит клон Филиал будет установлен из задания Jenkins, пользователь и URL-адрес будут установлены в Значения.yaml и токен аутентификации будет храниться с Секреты Helm Позже переместит его в переменную среды.

Создайте работу:

$ kk -n eks-dev-1-appname-api-ns apply -f appname-api-jobs.yaml
job.batch/migration-job created

Проверьте свои журналы:

$ kk -n eks-dev-1-appname-api-ns logs job/migration-job
Cloning into 'backend-services'…
total 20
-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

Репозиторий был клонирован, теперь доступны миграционные фильмы.

Проверьте статус POD:

$ kk -n eks-dev-1-appname-api-ns get pod
NAME READY STATUS RESTARTS AGE
migration-job-f72vs 0/1 Completed 0 9s

И статус работы:

$ kk -n eks-dev-1-appname-api-ns get job
NAME COMPLETIONS DURATION AGE
migration-job 1/1 2s 5s

Теперь может продолжаться с точным процессом миграции.

Секретарь

Чтобы запустить миграции, нам нужно создать файл конфигурации, который будет храниться в Kubernetes Configmap , но в этом файле пароль базы данных должен быть установлен.

Не очень хорошая идея хранить его в открытом тексте в конфигурации и файле, но SQL-мигрировать Позволяет использовать переменную среды в файле, проверять свою документацию — https://github.com/rubenv/sql-migrate#as-a-standalone-tool

Итак, мы создадим переменную для POD под названием $ Db_password , и сохранит фактический пароль в секретах Кубератеса, а затем в Хелме, мы будем использовать Секреты Helm Хранить его зашифровано в значениях графика.

Также в этом секретах мы будем хранить значение для $ Git_token Переменная среды для использования в Гит клон команда.

Еще в Шаблоны/appname-api-mygrations.yaml Добавить секрет:

...
---
apiVersion: v1
kind: Secret
metadata:
  name: backend-db-password
type: Opaque
stringData:
  db_password: password
  git_token: cdc***0fe

В spec.containers.env Из вакансии добавляют переменные и обновите Гит клон использовать $ Git_token переменная:

...
      containers:
      - name: db-migrations
        image: projectname/sql-migrate-git:latest
        command: ["/bin/sh", "-c"]
        args:
          - git clone --single-branch --branch develop [https://backend-user:$GIT_TOKEN@github.com/projectnamev/backend-services.git](https://backend-user:%24GIT_TOKEN@github.com/projectnamev/backend-services.git) &&
            ls -l backend-services/db/migrations;
            cat /config/config.yaml
        env:
        - name: GIT_TOKEN
          valueFrom:
            secretKeyRef:
              name: backend-db-password
              key: git_token
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: backend-db-password
              key: db_password
...

Configmap.

Далее создайте конфигурацию, чтобы сохранить /config/config.yaml Содержание для SQL-мигрировать и использовать $ Db_password Переменная в нем:

...
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: migration-config
data:
  config.yaml: |
    main:
      dialect: mysql
      datasource: backend-user:${DB_PASSWORD}@tcp(stage.backend-db3-master.example.com:3306)/dbname?parseTime=true
      dir: backend-services/db/migrations
      table: backend_services_migrations

В шаблоне POD работой добавляют объемы, а в SPEC.Containers через Облумерены Установите громкость с помощью конфигурации как /config/config.yaml файл.

Полный манифест работы сейчас следующий:

apiVersion: batch/v1
kind: Job
metadata:
  name: "migration-job"
  labels:
  annotations:
spec: 
  backoffLimit: 0
  template: 
    metadata:
      name: "migration-job-pod"
    spec:
      restartPolicy: Never
      containers:
      - name: db-migrations
        image: projectname/sql-migrate-git:latest
        command: ["/bin/sh", "-c"]
        args:
          - git clone --single-branch --branch develop [https://backend-user:$GIT_TOKEN@github.com/projectname/backend-services.git](https://backend-user:%24GIT_TOKEN@github.com/projectname/backend-services.git) &&
            ls -l backend-services/db/migrations;
            cat /config/config.yaml
        env:
        - name: GIT_TOKEN
          valueFrom:
            secretKeyRef:
              name: backend-db-password
              key: git_token
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: backend-db-password
              key: db_password
        volumeMounts:
        - name: migration-config
          mountPath: "/config/config.yaml"
          subPath: "config.yaml"
          readOnly: true
      volumes:
        - name: migration-config
          configMap: 
            name: migration-config
            items:
            - key: "config.yaml"
              path: "config.yaml"
...

Запустить его:

$ kk -n eks-dev-1-appname-api-ns apply -f appname-api-jobs.yaml
job.batch/migration-job created
secret/backend-db-password created
configmap/migration-config created

Проверять:

$ kk -n eks-dev-1-appname-api-ns logs job/migration-job
Cloning into 'backend-services'…
total 20
-rw-r — r — 1 root root 538 Oct 24 13:41 BS_1_init_schema.up.sql
-rw-r — r — 1 root root 180 Oct 24 13:41 BS_2_add_brand_field.up.sql
-rw-r — r — 1 root root 225 Oct 24 13:41 BS_3_alter_table.up.sql
-rw-r — r — 1 root root 194 Oct 24 13:41 BS_4_add_created_at_field.sql
-rw-r — r — 1 root root 272 Oct 24 13:41 BS_5_alter_table_nourishment_diet.up.sql
main:
dialect: mysql
datasource: backend-user:${DB_PASSWORD}@tcp(stage.backend-db3-master.example.com:3306)/dbname?parseTime=true
dir: backend-services/db/migrations
table: backend_services_migrations

Хорошо — репозиторий был клонирован, создан конфигурационный файл.

Бег миграции

И теперь мы можем описать процесс миграции, пока -Дрирун Опция, а со второй командой — проверьте его статус:

...
        args:
          - git clone --single-branch --branch develop [https://backend-user:$GIT_TOKEN@github.com/projectname/backend-services.git](https://backend-user:%24GIT_TOKEN@github.com/projectname/backend-services.git) &&
            ls -l backend-services/db/migrations &&
            cat /config/config.yaml &&
            /bin/sql-migrate up -config=/config/config.yaml -env=main -dryrun &&
            /bin/sql-migrate status -config=/config/config.yaml -env=main
...

Беги и проверьте свои журналы:

$ kk -n eks-dev-1-appname-test-migrations-ns logs job/migration-job
Cloning into 'backend-services'…
total 20
-rw-r — r — 1 root root 538 Oct 24 14:02 BS_1_init_schema.up.sql
-rw-r — r — 1 root root 180 Oct 24 14:02 BS_2_add_brand_field.up.sql
-rw-r — r — 1 root root 225 Oct 24 14:02 BS_3_alter_table.up.sql
-rw-r — r — 1 root root 194 Oct 24 14:02 BS_4_add_created_at_field.sql
-rw-r — r — 1 root root 272 Oct 24 14:02 BS_5_alter_table_nourishment_diet.up.sql
main:
dialect: mysql
datasource: backnd-user:${DB_PASSWORD}@tcp(stage.backend-db3-master.example.com:3306)/dbname?parseTime=true
dir: backend-services/db/migrations
table: backend_services_migrations
+ — — — — — — — — — — — — — — — — — — — — — + — — — — — — — — — — — — — — — -+
| MIGRATION | APPLIED |
+ — — — — — — — — — — — — — — — — — — — — — + — — — — — — — — — — — — — — — -+
| BS_1_init_schema.up.sql | 2020–05–07 12:21:25 +0000 UTC |
| BS_2_add_brand_field.up.sql | 2020–05–12 14:31:17 +0000 UTC |
| BS_3_alter_table.up.sql | 2020–05–13 06:17:25 +0000 UTC |
| BS_4_add_created_at_field.sql | 2020–07–21 09:55:49 +0000 UTC |
| BS_5_alter_table_nourishment_diet.up.sql | 2020–07–21 09:55:49 +0000 UTC |
+ — — — — — — — — — — — — — — — — — — — — — + — — — — — — — — — — — — — — — -+

Теперь можно перейти к хелме.

Шаблон хелма

Что нам нужно сделать в старом графике?

  1. Удалить initcontainers
  2. Удалить старые секреты
  3. Переместить значения для наших новых переменных в Values.yaml.
  4. Переместите пароль токена и базы данных в Secrets.yaml.

И основная часть здесь состоит в том, чтобы добавить аннотации, чтобы вызвать процесс миграции во время Helm развертывать

Добавьте Аннотации на работу:

apiVersion: batch/v1
kind: Job
metadata:
  name: {{ .Chart.Name }}-migration-job
  labels:
  annotations:
    "helm.sh/hook": pre-install,pre-upgrade
    "helm.sh/hook-weight": "-1"
    "helm.sh/hook-delete-policy": before-hook-creation
spec: 
  backoffLimit: 0
...

Здесь:

  • "helm.sh/hook": предварительная установка, предварительное обновление : запустить работу до helm установить или Обновление (В нашем трубопроводе Дженкинса он начался с Secrets Helm Uppreade --install )
  • "helm.sh/hook very": "-1" : Приоритет создания ресурсов, как сначала нам нужно создать конфигурацию и секрет, который будет использоваться нашей работой, поэтому установить вес меньше, чем для работы
  • "helm.sh/hook-delete-policy" : значение по умолчанию — раньше крюк-творчество (Проверьте документацию ), установите, если для тестирования, а затем его можно изменить на Крюк-успех (Но в этом случае вы не сможете проверить журналы, если миграция потерпит неудачу)

Добавьте Аннотации Блок на конфигурацию и секреты с Крюк-вес меньше, чем на работе.

Манифест Configmap теперь полный контент:

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: migration-config
  annotations:
    "helm.sh/hook": pre-install,pre-upgrade
    "helm.sh/hook-weight": "-5"
    "helm.sh/hook-delete-policy": before-hook-creation
data:         
  config.yaml: |
    main:
      dialect: {{ .Values.backendConfig.db.driver }}
      datasource: {{ .Values.backendConfig.db.user }}:${DB_PASSWORD}@tcp({{ .Values.backendConfig.db.host }}:{{ .Values.backendConfig.db.port }})/{{ .Values.backendConfig.db.database }}?parseTime=true
      dir: backend-services/db/migrations
      table: {{ .Values.backendConfig.db.migrationsTable }}

Секретный:

---     
apiVersion: v1
kind: Secret
metadata:
  name: {{ .Chart.Name }}-migration-secrets
  annotations: 
    "helm.sh/hook": pre-install,pre-upgrade
    "helm.sh/hook-weight": "-10"
    "helm.sh/hook-delete-policy": before-hook-creation
type: Opaque
stringData:
  backend-db-password: {{ .Values.backendConfig.db.password }}
  git_token: {{ .Values.git.token }}

И работа:

apiVersion: batch/v1
kind: Job
metadata:
  name: {{ .Chart.Name }}-migration-job
  labels:
  annotations:
    "helm.sh/hook": pre-install,pre-upgrade
    "helm.sh/hook-weight": "-1"
    "helm.sh/hook-delete-policy": before-hook-creation
spec:
  backoffLimit: 0
  template:
    metadata:
      name: {{ .Chart.Name }}-migration-job-pod
    spec:
      restartPolicy: Never
      containers:
      - name: {{ .Chart.Name }}-db-migrations
        image: projectname/sql-migrate-git:latest
        command: ["/bin/sh", "-c"]
        args: 
          - git clone --single-branch --branch {{ .Values.git.branch }} [https://{{](https://%7B%7B) .Values.git.user }}:$GIT_TOKEN@{{ .Values.git.repo }} &&
            ls -l backend-services/db/migrations &&
            cat /config/config.yaml &&
            /bin/sql-migrate up -config=/config/config.yaml -env=main || exit 1;
            /bin/sql-migrate status -config=/config/config.yaml -env=main
        env:
        - name: GIT_TOKEN
          valueFrom:
            secretKeyRef:
              name: {{ .Chart.Name }}-migration-secrets
              key: git_token
        - name: DB_PASSWORD
          valueFrom:
            secretKeyRef:
              name: {{ .Chart.Name }}-migration-secrets
              key: backend-db-password
        volumeMounts:
        - name: migration-config
          mountPath: "/config/config.yaml"
          subPath: "config.yaml"
          readOnly: true
      volumes:
        - name: migration-config
          configMap: 
            name: migration-config
            items:
            - key: "config.yaml"
              path: "config.yaml"

Здесь я добавил Выход 1 к /bin/sql-migrate u Так что работа будет Потерпеть неудачу В случае ошибок во время миграции и, следовательно, не запускают процесс развертывания.

Беги в Дженкинс:

В Крючки Мы видим, что сначала секрет был создан, как у него есть Вес крючка ":" -10 " , затем configmap, и работа наконец.

И процесс развертывания выглядит сейчас, как следующий:

Сначала удаляется секрет, конфигурация и ресурсы рабочих мест (в соответствии с точкой «HELM.SH/Hook-delete-policy»: перед тем, как создано для создания крюка ), а затем созданы.

Проверьте статус работы:

$ kk -n eks-stage-1-appname-api-ns get job
NAME COMPLETIONS DURATION AGE
appname-api-migration-job 1/1 3s 6m21s

Его журналы:

$ kk -n eks-stage-1-appname-api-ns logs job/appname-api-migration-job
Cloning into 'backend-services'…
total 20
-rw-r — r — 1 root root 538 Oct 26 11:32 BS_1_init_schema.up.sql
-rw-r — r — 1 root root 180 Oct 26 11:32 BS_2_add_brand_field.up.sql
-rw-r — r — 1 root root 225 Oct 26 11:32 BS_3_alter_table.up.sql
-rw-r — r — 1 root root 194 Oct 26 11:32 BS_4_add_created_at_field.sql
-rw-r — r — 1 root root 272 Oct 26 11:32 BS_5_alter_table_nourishment_diet.up.sql
main:
dialect: mysql
datasource: backend-user:${DB_PASSWORD}@tcp(stage.backend-db3-master.example.com:3306)/dbname?parseTime=true
dir: backend-services/db/migrations
table: backend_services_migrations
Applied 0 migrations
+ — — — — — — — — — — — — — — — — — — — — — + — — — — — — — — — — — — — — — -+
| MIGRATION | APPLIED |
+ — — — — — — — — — — — — — — — — — — — — — + — — — — — — — — — — — — — — — -+
| BS_1_init_schema.up.sql | 2020–05–07 12:21:25 +0000 UTC |
| BS_2_add_brand_field.up.sql | 2020–05–12 14:31:17 +0000 UTC |
| BS_3_alter_table.up.sql | 2020–05–13 06:17:25 +0000 UTC |
| BS_4_add_created_at_field.sql | 2020–07–21 09:55:49 +0000 UTC |
| BS_5_alter_table_nourishment_diet.up.sql | 2020–07–21 09:55:49 +0000 UTC |
+ — — — — — — — — — — — — — — — — — — — — — + — — — — — — — — — — — — — — — -+

Наносится 0 миграции , поскольку в файлах миграций нет изменений после последнего Применяется Отказ

Все сделано.

Первоначально опубликовано в RTFM: Linux, DevOps и системное управление Отказ

Оригинал: «https://dev.to/setevoy/kubernetes-running-sql-migrations-with-kubernetes-job-and-helm-hook-503j»