Как настроить периодические задания (jobs) в GitLab CI?

«Как настроить периодические задания (jobs) в GitLab CI?» — вопрос из категории CI/CD, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В GitLab CI я настраиваю повторяющиеся задания через pipeline schedules и rules с кроном. Вот как это выглядит в моих проектах:

1. Базовый пример .gitlab-ci.yml с расписанием:

variables:
  SCHEDULED_JOB: "false"

# Ежедневная очистка
cleanup:daily:
  stage: cleanup
  script:
    - echo "Running daily cleanup at $(date)"
    - ./scripts/cleanup-old-data.sh
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule" && $SCHEDULE_NAME == "Daily Cleanup"
      when: always

# Еженедельная сводка по безопасности
security:weekly:
  stage: test
  script:
    - trivy image --exit-code 0 --format table $CI_REGISTRY_IMAGE:latest
    - ./scripts/security-report.sh
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule"
      when: always
  artifacts:
    paths:
      - security-report.html
    expire_in: 1 week

# Каждый час проверка здоровья
health:hourly:
  stage: deploy
  script:
    - kubectl get pods -n $K8S_NAMESPACE | grep -v Running
    - ./scripts/check-endpoints.sh
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule" && $SCHEDULE_NAME =~ /Health Check/

2. Настройка расписания в GitLab UI:

  • Settings → CI/CD → Schedules → New schedule
  • Cron-формат: 0 2 * * * (ежедневно в 2:00)
  • Переменные расписания: можно задать SCHEDULE_NAME="Daily Backup"

3. Расширенный пример с ветвлением:

backup:production:
  stage: deploy
  script:
    - pg_dump $PROD_DB_URL | gzip > backup.sql.gz
    - aws s3 cp backup.sql.gz s3://backups/
  rules:
    - if: $CI_PIPELINE_SOURCE == "schedule" && $SCHEDULE_NAME == "Nightly Backup"
      when: manual  # Требует подтверждения
    - if: $CI_COMMIT_BRANCH == "main"
      when: never   # Не запускать при обычных коммитах
  only:
    refs:
      - schedules
    variables:
      - $DEPLOY_ENV == "production"

4. Мои best practices:

  • Использовать only: schedules для явного ограничения
  • Задавать таймауты для долгих jobs: timeout: 2 hours
  • Хранить секреты в CI/CD Variables, а не в коде
  • Логировать результаты в артефакты
  • Мониторить выполнение через Grafana + Prometheus

Для отладки расписаний:

# Посмотреть запланированные пайплайны
curl --header "PRIVATE-TOKEN: $GITLAB_TOKEN" "https://gitlab.com/api/v4/projects/$PROJECT_ID/pipeline_schedules"

# Запустить вручную
curl --request POST --header "PRIVATE-TOKEN: $GITLAB_TOKEN" "https://gitlab.com/api/v4/projects/$PROJECT_ID/pipeline_schedules/$SCHEDULE_ID/play"