Стадия жизненного цикла модуля: General Availability
У модуля есть требования для установки

Toolbox

Включенные в Toolbox инструменты используются для обслуживания и выполнения административных задач над продуктом Code

Toolbox содержит множество полезных gitlab-инструментов, таких как rails-console, rake-tasks, backup-utillity и т.д. Они позволяют посмотреть совершать такие задачи, как просмотр статуса миграции в БД, профилирование rails-приложений, запуск rake-tasks в административых целях, взаимодействовать с rails-console или выполнять процедуру восстановления из бекапов

Важно: компонент toolbox теперь опциональный (по умолчанию включён). Если pod toolbox отсутствует, убедитесь, что он включён в CodeInstance:

spec:
  features:
    toolbox:
      enabled: true # значение по умолчанию

Отключить его можно, установив spec.features.toolbox.enabled: false.


# Launch a shell inside the pod
kubectl -n d8-code exec -it -c toolbox deploy/toolbox -- bash

# open Rails console
gitlab-rails console -e production

# execute a Rake task
gitlab-rake gitlab:env:info

Советы по Rails-консоли

Rails-console является одним из компонентов Toolbox.

Через Rails-консоль можно выполнить множество полезных и иногда экстренных задач. Доступ к консоли предоставляет административные права по умолчанию, поэтому настоятельно рекомендуется использовать её с осторожностью и только в случае крайней необходимости.


Как отключить пайплайны для всех проектов

Project.all.find_each { |project| project.update!(builds_enabled: false) }

Как включить стандартную аутентификацию по паролю

Gitlab::CurrentSettings.update!(password_authentication_enabled_for_web: true)

Registry V1

Очистка неиспользуемых данных

Чтобы запустить очистку, сначала нужно перевести registry в режим чтения. Добавьте следующее в CodeInstance:

...
spec:
  features:
    registry:
      maintenance:
        readOnly: true
...

Теперь registry работает в режиме только для чтения (r/o), теперь получим имя одного из Pod’ов registry:

kubectl get pods -n d8-code -l app.kubernetes.io/component=registry,app.kubernetes.io/name=code -o jsonpath='{.items[0].metadata.name}'

Запустите сам процесс очистки. Ознакомьтесь с документацией registry, если хотите точно понять необходимость параметра -m.

kubectl exec -n d8-code <registry-pod> -- /bin/registry garbage-collect -m /etc/docker/registry/config.yml

Registry V2

Миграция с V1

Внимание! Эта операция не может быть отменена после запуска. Внимательно прочтите документацию.

  1. Включите режим обслуживания для container registry, установив значение spec.features.registry.maintenance.readOnly в true:

    kubectl patch codeinstance code --type=json -p="[{\"op\": \"replace\", \"path\": \"/spec/features/registry/maintenance/readOnly/enabled\", \"value\": true}]"
  2. Добавьте аннотацию registry-migration-in-progress=true к ресурсу CodeInstance:

    kubectl annotate codeinstance/code registry-migration-in-progress=true
  3. (Точка невозврата) Укажите настройки базы данных в разделе spec.features.registry.database:

    spec:
      features:
        registry:
          postgres:
            mode: External
            external:
              database: registry-database # имя базы данных для метаданных registry
              host: postgres.postgres.svc # IP-адрес или DNS-имя сервера PostgreSQL
              password: postgres # пароль для подключения к базе данных PostgreSQL
              port: 5432 # TCP-порт для подключения к базе данных PostgreSQL
              username: postgres # имя пользователя для подключения к базе данных PostgreSQL

    Поля host, password, port и username можно не указывать — в этом случае они будут взяты из spec.storages.postgres.external. Обязательно требуется только поле database.

  4. Дождитесь завершения reconcile. Убедитесь, что все поды в d8-code namespace находятся в готовом состоянии:

    kubectl -n d8-code get pods
  5. Зайдите в registry контейнер:

    kubectl -n d8-code exec -it -c registry deploy/registry -- bash
  6. Перейти в директорию /tmp

    cd /tmp
  7. Выполните приведённую ниже команду и дождитесь её завершения(внутри registry контейнера):

    registry database migrate up /etc/docker/registry/config.yml
  8. (Точка невозврата) После успешного завершения миграции запустите импорт(внутри registry контейнера):

    registry database import /etc/docker/registry/config.yml
  9. Вы можете выйти из registry контейнера.

  10. Удалите аннотацию и отключите режим обслуживания:

    kubectl annotate codeinstance/code registry-migration-in-progress-
    kubectl patch codeinstance code --type=json -p="[{\"op\": \"replace\", \"path\": \"/spec/features/registry/maintenance/readOnly/enabled\", \"value\": false}]"
  11. Уберите аннотацию registry-migration-in-progress у ресурса CodeInstance

    kubectl annotate codeinstance/code registry-migration-in-progress-

Теперь у вас установлен Реестр V2.


Бэкапы


Автоматическое создание бэкапов перед обновлениями модуля

При получении новой версии модуля Code происходит обновление только контроллера, а все остальные компоненты остаются нетронутыми и продолжают работать до момента создания бэкапа. Обновленный оператор ожидает успешного завершения задания по созданию бэкапа.

  • Если во время запуска задания по созданию бэкапа или в самом процессе создания бэкапа возникает ошибка, оператор будет периодически проверять статус существующих заданий. В случае обнаружения успешно завершенного задания, оператор начнет разворачивать остальные компоненты.

Обновление на уровне модуля завершится с ошибкой, если оно запущено в период, когда предыдущее обновление с опцией backup.backupBeforeUpdate завершилось неудачно, а версия оператора и его компонентов различаются

Для корректной работы данного функционала требуется версия Deckhouse Kubernetes Platform не ниже 1.69

Включение автоматического создания бэкапов

Для включения автоматического создания бэкапов необходимо в спецификации CodeInstance установить значения параметров backup.enabled и backup.backupBeforeUpdate в true. Пример конфигурации:

backup:
  backupBeforeUpdate: true
  backupStorageGb: 3
  cronSchedule: 0 0 1 * *
  enabled: true

Логика работы автоматического создания бэкапов перед обновлением

  • Оператор хранит свою версию в переменной окружения pod/deployment — GITLAB_VERSION.
  • Версия компонентов GitLab проверяется вызовом API.
  1. Проверяются значения параметров backup.enabled и backup.backupBeforeUpdate. Если хотя бы одно из них не равно true, оператор пропустит создание бэкапа и начнет обновление всех своих компонентов.
  2. Получается текущая версия оператора и компонентов GitLab. Если версии не различаются, создание бэкапа пропускается.
  3. Выполняется поиск Kubernetes Job по созданию бэкапа за последний час:
    • Если ни одна задача (job) не найдена, оператор создаст новую задачу и будет следить за её статусом, ожидая успешного завершения.
    • Если в течение последнего часа найдена хотя бы одна задача со статусом Failure, оператор не будет обновлять компоненты. В Prometheus будет отправлен алерт, сигнализирующий об ошибке обновления. Алерт будет активен до тех пор, пока не будет выключена опция backup.backupBeforeUpdate или не будет найдена задача со статусом Success.
    • Если найдена задача со статусом Success, оператор перейдет к обновлению остальных компонентов.

Решение проблем при ошибке создания бэкапов

  1. Необходимо прочитать логи задачи, завершившейся со статусом Failure, чтобы найти ошибку. (Примеры возможных проблем: недостаточно места в S3-бакете для хранения бэкапов, проблемы с сетью.). Пример команды для чтения логов:

    kubectl -n d8-code logs backup-before-update-1745879676-zdzz7

    Эта команда позволяет просмотреть логи поды, которая была создана для выполнения задачи.

  2. Поскольку оператор создает задачу для создания бэкапов только один раз, после устранения проблем с созданием бэкапов необходимо вручную пересоздать задачу, чтобы восстановить корректную работу оператора. Оператор автоматически найдет успешно завершенную задачу и продолжит работу. Пример команды:

    kubectl -n d8-code create job --from=cronjob/full-backup backup-before-update-manual-created

    Где:

    • backup-before-update-manual-created — имя новой задачи, которая будет запущена.

Бекапы и восстановление

Важно: Rails secrets, TLS/SSL-сертификаты и SSH host keys не включаются в архив бэкапа и должны быть сохранены отдельно. В модуле Code Rails secrets хранятся в Kubernetes Secret rails-secret-v1, SSH host keys — в Kubernetes Secret shell-host-keys. Также, при использовании registry v2, бекап базы данных registry не происходит в рамках описанного общего процесса бекапа. Процесс бекапа этой БД остается в зоне ответственности администратора системы.

Скрипт резервного копирования создает архивный файл для сохранения ваших данных.

Для создания архивного файла скрипт резервного копирования выполняет следующие действия:

  • Извлекает предыдущий архивный файл резервной копии, если вы выполняете инкрементное резервное копирование.
  • Обновляет или создает новый архивный файл резервной копии.
  • Выполняет все подзадачи резервного копирования:
    • Создает резервную копию базы данных.
    • Создает резервную копию Git-репозиториев.
    • Создает резервную копию файлов (включая S3-хранилища).
  • Архивирует подготовленную область резервного копирования в tar-файл.
  • Загружает новый архив резервной копии в объектное хранилище.
  • Очищает файлы подготовленной области резервного копирования, которые были заархивированы.

Бекапы по расписанию

В случае отсутствия поля backup.cronSchedule автоматические бекапы не будут работать. Поля является обязательным для работы автоматизированного создания бекапов

Убедитесь, что функционал бекапов включен в спецификации CodeInstance. Пример конфигурации секции описан в разделе «Настройка бекапов»

Бекапы реализованы с помощью kubernetes cronJobs (расписание cron-а также может быть настроена). Используется нативный инструмент Gitlab-а backup-utlity, а сам процесс подробно описан в официальной документации. Стоит отметить, что снятие бекапов производится с использованием ключа --repositories-server-side. что обеспечивает асинхронный бекап репозиториев непосредственно с реплик Gitaly, подробнее можно почитать в этом разделе официальной документации.

Важно: бэкапы, создаваемые по расписанию через CronJob, запускаются с флагом --repositories-server-side. Убедитесь, что объекты бэкапа репозиториев в S3 доступны для Gitaly во время восстановления.

Особенности конфигурации диска

Размер диска вычисляется по формуле Gitaly node size + sum of all buckets size + database size. Такой размер закладывается намеренно: настройка persistentVolumeClaim является общей для CronJob и Toolbox. Бэкапы по расписанию запускаются с флагом --repositories-server-side и не записывают репозитории на диск, однако при ручном бэкапе из Toolbox репозитории скачиваются локально и занимают место на диске. Формула гарантирует, что выделенного диска хватит в обоих сценариях.

При запуске CronJob бэкапа будет запрошен PVC того же размера, что задан в backup.backupStorageGb. Таким образом, в момент старта джобы бэкапа в кластере должно быть доступно 2X от значения по формуле: один PVC уже занят Toolbox, второй запрашивается CronJob.

  • Убедитесь, что выделенного размера диска достаточно для хранения файла бекапа
  • Альтернативным вариантом будет отключение persistenceVolume для бекапов (backup.persistentVolumeClaim.enabled: false). В таком случае, следует убедиться, что на kubernetes Node, где будут запущены backup-cronjob и toolbox (для восстановления из бекапа) достаточно места на дисках

Для включения регулярных бекапов добавьте следующую секцию в CodeInstance:

backup:
  cronSchedule: 0 0 */7 * *
  enabled: true
  s3:
    bucketName: d8-code-test-backups
    tmpBucketName: d8-code-test-backups-tmp
    external:
      provider: YCloud
      accessKey: __ACCESS_KEY__
      secretKey: __SECRET_KEY__
    mode: External
  persistentVolumeClaim:
    enabled: true # использовать ли persistentStorage при бекапе и восстановлении из бекапа
    storageClass: localpath

backup.s3.bucketName хранит итоговые архивы бэкапов (<backup_id>_gitlab_backup.tar). backup.s3.tmpBucketName — временный бакет, который используется в процессе backup/restore для промежуточных данных. Рекомендуется использовать отдельный бакет для tmpBucketName и настроить для него короткую lifecycle/retention политику.

После правильной настройки CodeInstance нет необходимости в дополнительных шагах. Просто дождитесь, пока бекап выполнится по расписанию.

Ручные бекапы по требованию

  1. Убедитесь, что секция backup.s3.external задана иначе будут унаследованы значения из секции storages.s3.external в CodeInstance. Обязательно нужно задать поле backup.s3.bucketName
  2. Убедитесь, что значение backup.enabled равняется true
  3. Убедитесь, что необходимый компонент запущен и готов к работе
kubectl -n d8-code get pods -lapp.kubernetes.io/component=toolbox
  1. hostЗапустите утилиту бекапирования
kubectl exec -n d8-code -c toolbox deploy/toolbox -it -- backup-utility

Если бэкап запускается вручную, параметры --skip нужно выбирать самостоятельно в зависимости от вашей схемы хранения и миграции данных. Пример:

kubectl exec -n d8-code -c toolbox deploy/toolbox -it -- backup-utility --skip registry --skip uploads
  1. Бекап будет сохранен в бакете backup.s3.bucketName. Его имя будет соответствовать <timestamp>_gitlab_backup.tar формату.

Хранение бэкапов

Используйте поле backup.keepLast чтобы хранить только N последних архивов с бэкапами в S3 бакете. Backup CronJob автоматически удалит старые бэкапы после успешного выполнения бэкапа.

Пример:

...
spec:
   backup:
   cronSchedule: 0 0 */7 * *
   enabled: true
   keepLast: 10
...

Server-side бэкапы

По умолчанию, автоматические бэкап выполняются с флагом server-side - это значит что гит репозитории бэкапятся напрямую в S3 бакет, без включения в архив бэкапа.
Чтобы отключить данную опцию, задайте backup.serverSide: false, но это сильно увеличит нагрузку на сеть и диск в процессе бэкапа.

Восстановление из бекапов

Предусловия восстановления

  • Исходный бэкап и целевой GitLab должны быть одной и той же версии.
  • toolbox должен быть включен и находиться в состоянии Running.
  • Имя архива должно оставаться в формате <backup_id>_gitlab_backup.tar.
  • При восстановлении по URL pod Toolbox должен иметь доступ к указанному URL.
  • Rails secrets, TLS/SSL-сертификаты и SSH host keys не включаются в архив бэкапа и должны быть сохранены отдельно. В модуле Code Rails secrets хранятся в Kubernetes Secret rails-secret-v1, SSH host keys — в Kubernetes Secret shell-host-keys. Восстановление с другими Rails secrets сделает все зашифрованные данные (токены, 2FA-секреты и т.д.) нечитаемыми.

Матрица команд backup/restore

  • Создание бэкапа: backup-utility (при необходимости с вручную выбранными --skip флагами).
  • Восстановление по ID бэкапа из backup-бакета: backup-utility --restore -t <backup_id>.
  • Восстановление по URL или локальному пути: backup-utility --restore -f <URL|file:///path/to/<backup_id>_gitlab_backup.tar>.
  • Для бэкапов, созданных CronJob с --repositories-server-side, используйте стандартную команду восстановления и обеспечьте доступ к тем же S3-данным бэкапа репозиториев.

Для восстановления из бекапов следуйте нижеприведенной инструкции:

  1. Остановите оператор, чтобы он не вмешивался в процесс восстановления. Подробнее.

  2. Используйте toolbox-под и встроенную в него утиллиту backup-utlity для старта процесса восстановления:

    • по ID бэкапа: kubectl -n d8-code exec -it -c toolbox deploy/toolbox -- backup-utility --restore -t <backup_id>
    • по URL или локальному пути: kubectl -n d8-code exec -it -c toolbox deploy/toolbox -- backup-utility --restore -f <URL|file:///path/to/<backup_id>_gitlab_backup.tar>

    Где:

    • backup_id — идентификатор из имени архива <backup_id>_gitlab_backup.tar.
    • URL — публичный адрес файла или локальный путь в формате file:///path.
  3. Следуйте процессу интерактивного режима восстановления: отвечайте yes на все предложения утиллиты

Дополнительно у Вас есть возможность верифицировать целостьность выгружаемых данных из того же пода Toolbox, следуя официальной документации

  1. Верните оператору управление ресурсами. Подробнее.

Как убедиться, что восстановление завершилось корректно

После восстановления выполните проверки:

kubectl -n d8-code get pods
kubectl -n d8-code exec -it -c toolbox deploy/toolbox -- gitlab-rake gitlab:fe:secret:verify
kubectl -n d8-code exec -it -c toolbox deploy/toolbox -- gitlab-rake db:migrate:status
kubectl -n d8-code exec -it -c toolbox deploy/toolbox -- gitlab-rake gitlab:check SANITIZE=true

Восстановление считается успешным, когда все pods в состоянии Ready, нет ожидающих миграций, и gitlab:check завершается без критичных ошибок.

Устранение неполадок

  • unable to reset refs. Proceeding with a normal restore сообщение в логах при восстановлении из бэкапа. Данное сообщение не является ошибкой. Начиная с версии Gitlab 16.* появилась новая оптимизация восстановления, которая пытается сбросить репозиторий (если он существует) до резервной копии списка refs. В данном случае репозиторий не существовал, поэтому оптимизация была пропущена.
  • При восстановлении бэкапа, созданного в Omnibus, могут появляться ошибки о создании/использовании старой PostgreSQL роли из бэкапа и/или о создании PostgreSQL extension. Обычно это связано с отличиями PostgreSQL-окружения между источником и целевой инсталляцией (например, роли, права, владелец extension). Эти сообщения обычно не являются критичными и не нарушают процесс восстановления и дальнейшую работу после восстановления.

Управление API-токенами

Оператор Code автоматически управляет внутренними API-токенами, используемыми для взаимодействия с GitLab API. Это включает автоматическую ротацию и мониторинг срока действия токенов.

Автоматическая ротация токенов

Оператор автоматически ротирует API-токены ежедневно. Срок действия токенов устанавливается на 37 дней, что гарантирует их обновление задолго до истечения.

Автоматически обновляются следующие токены:

Имя секрета Назначение
code-service-account Используется оператором для операций с GitLab API

В обычных условиях ручное вмешательство для ротации токенов не требуется.

Мониторинг

Оператор экспортирует Prometheus метрику для отслеживания срока действия токенов:

code_operator_api_token_expire_hours{token_name="code-operator-sa"}

Эта метрика показывает оставшееся количество часов до истечения срока действия токена Deckhouse SA.

Устранение неполадок

При подозрении на проблемы с токенами:

  1. Проверьте логи оператора на предмет статуса ротации:

    kubectl -n d8-code logs deploy/code-operator | grep -i "token"
  2. Проверьте валидность токена:

    API_URL=$(kubectl -n d8-code get ingress webservice-default -o jsonpath='{.spec.rules[0].host}')
    TOKEN=$(kubectl -n d8-code get secret code-service-account -o jsonpath='{.data.api-token}' | base64 -d)
    curl -s -H "PRIVATE-TOKEN: $TOKEN" "https://$API_URL/api/v4/personal_access_tokens/self" | jq .expires_at
  3. Если токен просрочился, выполните следующие действия для создания нового:

    Откройте Rails-консоль с помощью Toolbox:

    kubectl -n d8-code exec -it deploy/toolbox -- gitlab-rails console -e production

    Создайте новый токен для сервисного аккаунта deckhouse_sa:

    user = User.find_by_username('deckhouse_sa')
    
    personal_access_token = PersonalAccessTokens::CreateService.new(
      current_user: user,
      target_user: user,
      organization_id: Organizations::Organization.default_organization.id,
      params: {
        name: 'Deckhouse service account',
        scopes: [:api, :admin_mode],
        expires_at: Time.now + 3.months
      },
    ).execute
    
    personal_access_token.payload[:personal_access_token].token

    Скопируйте полученный токен и обновите Kubernetes-секрет:

    token="$(echo -n "NEW_TOKEN" | base64 -w0)"
    kubectl -n d8-code patch secret code-service-account --type=json -p="[{\"op\": \"replace\", \"path\": \"/data/api-token\", \"value\": \"$token\"}]"

    Поскольку проверка срока действия токена выполняется раз в сутки, перезапустите оператор для немедленной проверки и сброса Prometheus-алерта:

    kubectl -n d8-code rollout restart deploy/code-operator

    Алерт погаснет примерно через 10 минут после запуска нового пода.

Устранение неполадок с партициями БД

Code использует партиционированные таблицы для хранения определённых данных. Партиции создаются и удаляются автоматически по расписанию (раз в месяц или день). Алерт D8CodeDbPartitionMissing срабатывает, если одна или несколько ожидаемых партиций отсутствуют в базе данных более 60 минут.

Алерт может срабатывать кратковременно в ходе штатного жизненного цикла партиций (создание или удаление). Если алерт гаснет в течение 2–3 дней, никаких действий не требуется.

Если алерт не гаснет более 2–3 дней, выполните следующие шаги.

  1. Проверьте, какие партиции отсутствуют, открыв Rails-консоль через Toolbox:

    kubectl -n d8-code exec -it deploy/toolbox -- gitlab-rails console
    LooseForeignKeys::DeletedRecord.partitioning_strategy.missing_partitions

    Пустой результат (=> []) означает, что отсутствующих партиций нет и алерт должен погаснуть самостоятельно.

  2. Если партиции отсутствуют, запустите их создание вручную:

    kubectl -n d8-code exec -it deploy/toolbox -- gitlab-rake gitlab:db:create_dynamic_partitions

    Подождите несколько минут и проверьте, погас ли алерт.

  3. Если алерт по-прежнему не гаснет после выполнения rake-задачи, требуется более детальное расследование конкретных таблиц. Обратитесь в поддержку и предоставьте вывод из шага 1.


Алерты

В данной таблице приведены алерты в модуле и действия которые необходимо предпринять:

Алерт Severity Действие
D8CodeDbPartitionMissing 3 Следуйте инструкции
D8CodeDbPartitionExtraFound 6 Действия не требуются. Ожидаемо во время ротации партиций
D8CodeOperatorTokenExpireIn14Days 5 Действия не требуются.
D8CodeOperatorTokenExpireIn7Days 3 Действия не требуются.
D8CodeOperatorTokenExpireIn24Hours 2 Следуйте инструкции
D8CodeOperatorPossibleReconcilationError 4 Оператор Code многократно пытается выполнить reconcile ресурсов без успеха, что свидетельствует о возможной внутренней ошибке. Проверьте логи пода code-operator и при сохранении проблемы обратитесь в поддержку.
GitalyCgroupMemoryOOM 6 Следуйте инструкции