У нас есть проект, работающий в Kubernetes, которые необходимо запустить миграции SQL во время развертывания.
Чтобы запустить миграцию надо клонировать репозиторий GitHub и запустить на самом деле миграции, хранящиеся в нем.
В настоящее время это делается с Kubernetes initContainers и есть два из них — первый с Гит
клонирует репозиторий с файлами миграций в Кубернаны объем , а потом еще один с SQL-мигрировать
Запускает эти миграции из этого общего объема.
Тем не менее, есть несколько вопросов с этим подходом:
- Каждый раз, когда мы запускаем новый POD, он управляет своими инициаторами и миграциями
- Если развертывание раскрутит пару стручков — каждый запускает миграции
- Если миграции будут работать на 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 | + — — — — — — — — — — — — — — — — — — — — — + — — — — — — — — — — — — — — — -+
Теперь можно перейти к хелме.
Шаблон хелма
Что нам нужно сделать в старом графике?
- Удалить
initcontainers
- Удалить старые секреты
- Переместить значения для наших новых переменных в
Values.yaml.
- Переместите пароль токена и базы данных в
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»