Skip to content

Latest commit

 

History

History
668 lines (611 loc) · 75.3 KB

File metadata and controls

668 lines (611 loc) · 75.3 KB

Архитектура

Структура проекта

osctl/
├── cmd/
│   └── main.go                    # Точка входа приложения
├── commands/                      # Команды CLI
│   ├── root.go                   # Общие флаги и список команд
│   ├── snapshots.go               # Создание снапшотов
│   ├── snapshot-manual.go        # Ручное создание снапшотов
│   ├── snapshotsdelete.go         # Удаление снапшотов согласно конфигурации
│   ├── indicesdelete.go          # Удаление индексов согласно конфигурации
│   ├── retention.go              # Удаление индексов при превышении порога диска
│   ├── dereplicator.go           # Уменьшение реплик до 0
│   ├── coldstorage.go            # Миграция в cold storage
│   ├── snapshotschecker.go        # Проверка наличия снапшотов
│   ├── snapshotsbackfill.go       # Создание снапшотов для индексов без них
│   ├── danglingchecker.go        # Проверка dangling индексов
│   ├── extracteddelete.go        # Удаление extracted индексов
│   ├── sharding.go               # Автоматическое шардирование
│   ├── indexpatterns.go         # Управление Kibana index patterns
│   └── datasource.go             # Создание Kibana data sources
├── pkg/
│   ├── config/                   # Конфигурация
│   │   ├── config.go            # Основная конфигурация
│   │   ├── osctlindicesconfig.go # Конфигурация индексов
│   │   └── tenantsconfig.go     # Конфигурация тенантов
│   ├── opensearch/              # OpenSearch API клиент
│   │   ├── client.go            # HTTP-клиент
│   │   ├── cluster.go           # allocation, aliases, nodes
│   │   ├── indices.go           # Операции с индексами и их настройками
│   │   ├── snapshots.go         # Работа со снапшотами
│   │   ├── templates.go         # Работа с index templates
│   │   └── tasks.go             # Работа с _tasks API
│   ├── kibana/                  # Kibana API клиент
│   │   ├── client.go            # HTTP-клиент
│   │   └── service.go           # saved objects, data-source
│   ├── alerts/                  # Madison алерты
│   │   └── to_madison.go
│   ├── logging/                 # Логирование
│   │   └── logger.go
│   └── utils/                   # Утилиты
│       ├── date.go              # Действия с датами
│       ├── indices.go           # Работа с индексами
│       ├── snapshots.go         # Работа со снапшотами
│       ├── cluster.go           # Работа с кластером (утилизация, проверка нод)
│       ├── templates.go         # Работа с шаблонами
│       └── helpers.go           # Вспомогательные функции
├── config-example/                # Примеры конфигураций, job и деплойментов
├── Dockerfile
├── go.mod
├── go.sum
├── config.yaml                      # Единый конфиг
└── README.md

Алгоритмы для каждого флага

1. snapshots - Создание снапшотов индексов

Алгоритм:

  1. Загрузка конфигурации: Получаем osctl-indices-config через --osctl-indices-config
  2. Разделение конфигураций: Разделяем конфигурации на системные (system: true) и обычные (system: false)
  3. Получение индексов:
    • Системные индексы: GET /_cat/indices/.*?h=index,ss&bytes=b&s=ss:desc для всех индексов, начинающихся с точки (только если есть конфигурации с system: true)
    • Обычные индексы: GET /_cat/indices/*{yesterday}*?h=index,ss&bytes=b&s=ss:desc для индексов за вчера (только если есть конфигурации с system: false)
  4. Группировка индексов:
    • Для каждого индекса находим соответствующий конфиг через FindMatchingIndexConfig
    • Пропускаем индексы с флагом manual_snapshot: true
    • Группируем индексы по паттернам через AddIndexToSnapshotGroups, учитывая переопределение репозитория (Repository в конфиге)
    • Создаем группы по репозиториям: для каждой группы создается один снапшот
  5. Dry run режим:
    • Получаем существующие снапшоты за сегодня из целевого репозитория
    • Для каждой группы проверяем наличие снапшота со статусом SUCCESS:
      • Если снапшот существует и содержит все индексы - пропускаем
      • Если снапшот существует, но некоторые индексы отсутствуют - показываем план создания дополнительного снапшота с именем {baseName}-{randomSuffix}-{date} только для отсутствующих индексов
    • Для снапшотов со статусом IN_PROGRESS показываем явное сообщение
    • Показываем план создания снапшотов с указанием репозитория для каждой группы
  6. Создание снапшотов (параллельно, с ограничением слотов):
    • Для всех групп формируем список задач SnapshotTask с полями: имя снапшота, список индексов, репозиторий, дата и расчетный размер (Size), который используется для приоритизации.
    • Задачи сортируются по размеру по убыванию (большие снапшоты первыми).
    • Для всех задач запускается worker‑pool через CreateSnapshotsInParallel:
      • Количество одновременно работающих горутин ограничено конфигом max-concurrent-snapshots (по умолчанию 3).
      • Каждая горутина (worker) последовательно берет задачи из общего канала и вызывает CreateSnapshotWithRetry, передавая свой workerID для логов.
    • Проверка существующих снапшотов перед постановкой задачи в очередь:
      • Для каждой группы проверяем существующие снапшоты через GET /_snapshot/{repo}/*{today}* с обработкой 404 через GetSnapshotsIgnore404.
      • Проверяем состояние снапшота через CheckSnapshotStateInRepo:
        • Если снапшот уже в состоянии SUCCESS и содержит все индексы группы — задача не создается (группа пропускается).
        • Если снапшот SUCCESS, но часть индексов отсутствует — создаем задачу на отдельный снапшот {baseName}-{randomSuffix}-{date} только для отсутствующих индексов.
        • Если снапшот в состоянии IN_PROGRESS — задача для этой группы не создается (пропускаем до следующего запуска).
      • Если снапшота нет или он не в состоянии SUCCESS:
        • Для группы вызываем CheckAndCleanSnapshot для удаления ошибочного снапшота (PARTIAL/FAILED).
        • Формируем задачу SnapshotTask на создание нового снапшота.
    • Лимит слотов и ожидание внутри CreateSnapshotWithRetry:
      • Перед каждой попыткой создания снапшота вызывается WaitForSnapshotSlot, которая смотрит _snapshot/_status, считает активные снапшоты и ждет, пока их число станет < max-concurrent-snapshots.
      • Логи WaitForSnapshotSlot показывают, сколько сейчас активных снапшотов, какой workerID и какой снапшот ждут свободный слот.
    • Проверка существующего снапшота прямо перед созданием:
      • После ожидания слота, но до вызова CreateSnapshot, CreateSnapshotWithRetry еще раз вызывает CheckSnapshotStateInRepo для конкретного снапшота:
        • Если снапшот уже в состоянии SUCCESS — создание пропускается, задача считается выполненной.
        • Если снапшот уже есть в другом состоянии (IN_PROGRESS/FAILED/PARTIAL и т.п.) — вызов CreateSnapshot пропускается, дальше запускается только мониторинг этого существующего снапшота (иначе возникает рейс кондишен).
    • Проверка статуса:
      • После старта CreateSnapshotWithRetry опрашивает статус через GET /_snapshot/{repo}/*{today}* (через GetSnapshots) с таймаутом видимости 15 минут.
      • Если состояние IN_PROGRESS, дополнительно вызывается GetSnapshotStatusDetail (GET /_snapshot/{repo}/{snapshot}/_status).
      • Если в детальном статусе shards_stats.failed > 0:
        • Снапшот сразу считается невалидным, удаляется через DeleteSnapshotsWithRetry.
        • При наличии оставшихся попыток делается пауза 15 минут и выполняется очередной retry.
    • Retry логика в CreateSnapshotWithRetry:
      • Максимум 7 попыток для каждого снапшота.
      • Таймаут ожидания появления снапшота в списке — 15 минут с момента старта попытки.
      • Любые ошибки при polling (включая 404 до истечения таймаута) считаются временными: ждем до таймаута, затем либо retry (если попытки остались), либо ошибка.
      • Для статусов PARTIAL/FAILED снапшот удаляется, затем ждем 15 минут и делаем retry (если попытки остались).
      • Для неизвестных состояний выполняется retry после короткой паузы.
      • Все переходы к следующей попытке реализованы через метку retryLoop.
    • Алертинг: При неудаче после всех попыток отправляется алерт в Madison через SendMadisonSnapshotCreationFailedAlert.
    • Обработка ошибок: Ошибки по одной задаче не прерывают выполнение остальных задач в пуле.
    • Repo-specific группы: Для снапшотов в кастомных репозиториях применяется та же параллельная логика с ограничением слотов.
  7. Unknown индексы: Если включено unknown.snapshot в конфиге и manual_snapshot: false, создаем снапшот "unknown-{date}" в основном репозитории (также через SnapshotTask и общий пул с limit по max-concurrent-snapshots)

Конфигурация:

  • Использует --osctl-indices-config для централизованной конфигурации
  • Поддерживает prefix и regex паттерны
  • Разделяет обработку системных и обычных индексов
  • Пропускает индексы с флагом manual_snapshot: true
  • manual_snapshot используется для ручного исключения из общего потока создания снапов - например для особо огромных идексов - чтобы для них сделать отдельную джобу snapshot-manual
  • Поддерживает переопределение репозитория через Repository в конфиге индекса
  • Использует общий лимит параллельных снапшотов max-concurrent-snapshots (CLI/конфиг), по умолчанию 3

2. snapshot-manual - Ручное создание снапшотов

Алгоритм:

  1. Загрузка параметров: Получаем параметры индекса через CLI флаги (--snapshot-manual-kind, --snapshot-manual-value, --snapshot-manual-name, --snapshot-manual-system, --snapshot-manual-repo)
  2. Валидация: Проверяем обязательные параметры (value, name для regex)
  3. Получение индексов:
    • Системные индексы (--snapshot-manual-system): GET /_cat/indices/.*?h=index,ss&bytes=b&s=ss:desc для всех индексов, начинающихся с точки
    • Обычные индексы (без --snapshot-manual-system): GET /_cat/indices/*{yesterday}*?h=index,ss&bytes=b&s=ss:desc для индексов за вчера
  4. Поиск соответствующих индексов: Находим индексы соответствующие паттерну через MatchesIndex с учетом флага system
  5. Dry run режим:
    • Определяем целевой репозиторий: snapshot-manual-repo или snap-repo
    • Проверяем существующие снапшоты в целевом репозитории
    • Если снапшот со статусом SUCCESS уже существует - завершаем без плана
    • Если снапшот со статусом IN_PROGRESS - показываем явное сообщение
    • Показываем план создания снапшота с указанием репозитория
  6. Создание снапшота (с учетом слотов и детального статуса):
    • Перед фактическим созданием снапшота CreateSnapshotWithRetry вызывает WaitForSnapshotSlot, которая читает _snapshot/_status и ждет, пока число активных снапшотов станет < max-concurrent-snapshots.
    • После вызова OpenSearch на создание снапшота запускается polling‑цикл:
      • Список снапшотов читается через GetSnapshots (GET /_snapshot/{repo}/*{today}*) с таймаутом видимости 15 минут.
      • Если состояние IN_PROGRESS, дополнительно запрашивается детальный статус через GetSnapshotStatusDetail (GET /_snapshot/{repo}/{snapshot}/_status).
      • Если в детальном статусе shards_stats.failed > 0, снапшот немедленно удаляется через DeleteSnapshotsWithRetry; при наличии оставшихся попыток — пауза 15 минут и retry.
      • Для состояний PARTIAL/FAILED без детального статуса действует та же логика: удаление + пауза 15 минут перед retry.
    • Максимум 7 попыток; по исчерпании попыток создается алерт в Madison аналогично команде snapshots.

Конфигурация:

  • Использует CLI флаги для параметров одного паттерна индексов
  • Поддерживает prefix и regex паттерны
  • Учитывает флаг --snapshot-manual-system для системных индексов
  • Поддерживает переопределение репозитория через --snapshot-manual-repo
  • Не обрабатывает unknown индексы
  • Не использует --osctl-indices-config
  • Разделяет слоты с остальными снапшот‑командами через общий max-concurrent-snapshots

3. snapshotsdelete - Удаление снапшотов

Алгоритм:

  1. Загрузка конфигурации: Получаем osctl-indices-config и S3 конфигурацию (unit_count.all, unit_count.unknown)
  2. Получение снапшотов из основного репозитория: GET /_snapshot/{repo}/* для всех снапшотов из основного репозитория
  3. Фильтрация снапшотов основного репозитория:
    • Для каждого снапшота находим соответствующий конфиг через FindMatchingSnapshotConfig
    • Если снапшот имеет переопределенный репозиторий (Repository в конфиге) - пропускаем его (такие снапшоты обрабатываются отдельно в кастомных репозиториях)
    • Если конфиг найден и snapshot: true:
      • Используем snapshot_count_s3 из конфига или unit_count.all из S3 конфига как количество дней
      • Проверяем возраст через IsOlderThanCutoff
    • Если конфиг не найден:
      • Если снапшот имеет дату в названии - добавляем в unknownSnapshots
      • Если снапшота нет даты в названии - добавляем в danglingSnapshots (логируем, но не удаляем)
  4. Unknown снапшоты: Если включено unknown.snapshot, применяем unit_count.unknown для снапшотов без конфига, но с датой в названии
  5. Обработка переопределенных репозиториев:
    • Собираем все уникальные репозитории из конфигов, где Repository != "" и snapshot: true
    • Для каждого кастомного репозитория:
      • Получаем все снапшоты через GET /_snapshot/{repo}/*
      • Для каждого снапшота находим соответствующий конфиг через FindMatchingSnapshotConfig
      • Проверяем, что снапшот точно соответствует паттерну или регексу в конфиге:
        • Конфиг должен быть найден (ic != nil)
        • Репозиторий в конфиге должен совпадать с текущим репозиторием (ic.Repository == repo)
        • В конфиге должно быть snapshot: true
      • Если снапшот не соответствует - логируем как "dangling" и пропускаем
      • Если снапшот соответствует, но не имеет даты в названии - пропускаем с логированием
      • Если снапшот соответствует и имеет дату - проверяем возраст:
        • Используем snapshot_count_s3 из конфига или unit_count.all из S3 конфига
        • Если снапшот старше - добавляем в список для удаления из этого репозитория
  6. Dry run режим: Показываем список снапшотов для удаления, группируя по репозиториям
  7. Удаление: Через DeleteSnapshotsBatch с группировкой по репозиториям (основной и кастомные)

Примечания:

  • Никогда не трогаем снапшоты без даты в нужном формате старше чем Unknown политика, но выводим их в лог
  • Снапшоты в переопределенных репозиториях обрабатываются только если они точно соответствуют паттерну или регексу в конфиге и находятся в правильном репозитории
  • Снапшоты из основного репозитория, у которых в конфиге указан переопределенный репозиторий, не обрабатываются (они должны обрабатываться в своем кастомном репозитории)

4. indicesdelete - Удаление индексов

Алгоритм:

  1. Загрузка конфигурации: Получаем osctl-indices-config, unknown.days_count, S3 конфигурацию (unit_count.all, unit_count.unknown) и indicesdelete_check_snapshots
  2. Валидация конфигурации (при загрузке):
    • Если есть секции indices или unknown: проверяем что s3_snapshots.unit_count.all >= 1 (иначе ошибка)
    • Для каждого индекса: проверяем что days_count >= 1 и snapshot_count_s3 >= 0 (иначе ошибка)
    • Для unknown: проверяем что days_count >= 1 или 0 (не задан) (иначе ошибка)
    • Если snapshot_count_s3 == 0 и snapshot: true, устанавливаем snapshot_count_s3 = unit_count.all
    • Если unit_count.unknown == 0 и unit_count.all > 0, устанавливаем unit_count.unknown = unit_count.all
  3. Получение индексов: GET /_cat/indices/*?h=index,cd&bytes=b&s=index:asc для всех индексов
  4. Фильтрация индексов:
    • Пропускаем системные индексы (начинающиеся с .)
    • Пропускаем extracted индексы (начинающиеся с extracted_)
    • Для каждого индекса находим соответствующий конфиг через FindMatchingIndexConfig
    • Если конфиг найден:
      • Если индекс имеет дату в названии:
        • Индексы старше retention period (days_count): Проверяем возраст через IsOlderThanCutoff с days_count из конфига - если старше, добавляем в список indicesOlderThanRetentionPeriod
        • Индексы, требующие проверки снапшотов: Если snapshot: true в конфиге:
          • Определяем cutoff дату для снапшотов: используем snapshot_count_s3 из конфига (если не задан, используется s3_snapshots.unit_count.all)
          • Если индекс старше days_count, но НЕ старше snapshot_count_s3 - добавляем в список indicesRequiringSnapshotCheck
          • Если индекс старше snapshot_count_s3 - снапшот уже ротирован, проверка не требуется, индекс удаляется без проверки (через indicesOlderThanRetentionPeriod)
      • Если у индекса нет даты в названии - просто логируем (не проверяем возраст, не удаляем)
    • Если конфиг не найден:
      • Если индекс имеет дату в названии - добавляем в unknownIndices для дальнейшей обработки
      • Если у индекса нет даты в названии - просто логируем (не проверяем возраст, не добавляем в unknown, не удаляем)
  5. Фильтрация unknown индексов: Применяем FilterUnknownIndices для исключения известных паттернов (только для индексов с датой в названии)
  6. Обработка unknown индексов: Для каждого отфильтрованного unknown индекса (только с датой в названии):
    • Индексы старше retention period: Если unknown.days_count > 0 и индекс старше cutoff - добавляем в список indicesOlderThanRetentionPeriod
    • Индексы, требующие проверки снапшотов: Если unknown.snapshot: true и unknown.manual_snapshot: false:
      • Определяем cutoff дату для снапшотов: используем s3_snapshots.unit_count.unknown из S3 конфига
      • Если индекс старше unknown.days_count, но НЕ старше unit_count.unknown - добавляем в список indicesRequiringSnapshotCheck
      • Если индекс старше unit_count.unknown - снапшот уже ротирован, проверка не требуется, индекс удаляется без проверки (через indicesOlderThanRetentionPeriod)
  7. Логирование списков: Логируем оба списка с указанием количества и полного списка индексов
  8. Проверка снапшотов (если есть индексы, требующие проверки):
    • Если indicesdelete_check_snapshots=true:
      • Проверяем наличие snap-repo - если не настроен, джоба завершается с ошибкой
      • Получаем все снапшоты один раз через GET /_snapshot/{snap_repo}/* с обработкой 404 через GetSnapshotsIgnore404 (для избежания зависаний)
      • Если произошла ошибка при получении снапшотов - джоба завершается с ошибкой
      • Для каждого индекса из списка indicesRequiringSnapshotCheck проверяем наличие валидного снапшота через HasValidSnapshot
      • Если снапшот найден - логируем и добавляем индекс в финальный список для удаления
      • Если снапшота нет - логируем предупреждение и НЕ добавляем индекс в финальный список (но сохраняем для summary)
      • Добавляем все индексы из indicesOlderThanRetentionPeriod, которые не в indicesRequiringSnapshotCheck (для них проверка не требуется) в финальный список для удаления
    • Если indicesdelete_check_snapshots=false:
      • Пропускаем проверку снапшотов, используем только indicesOlderThanRetentionPeriod (все индексы старше days_count удаляются без проверки)
  9. Dry run режим: Показываем финальный список индексов для удаления
  10. Удаление: Через BatchDeleteIndices с dry run поддержкой
  11. Summary: В конце выводится summary с успешно удаленными индексами, неудачными удалениями и индексами, пропущенными из-за отсутствия валидного снапшота

Примечания:

  • Никогда не удаляем системные индексы (начинающиеся с .)
  • Никогда не трогаем индексы без даты в нужном формате старше чем Unknown политика, но выводим их в лог
  • Если indicesdelete_check_snapshots=true и не удалось получить информацию о снапшотах или snap-repo не настроен - джоба завершается с ошибкой
  • Индексы из списка indicesRequiringSnapshotCheck (старше days_count, но не старше snapshot_count_s3) удаляются только если у них есть валидный снапшот (при indicesdelete_check_snapshots=true)
  • Индексы старше snapshot_count_s3 удаляются без проверки снапшота (снапшот уже ротирован)
  • Индексы из списка indicesOlderThanRetentionPeriod, которые не в indicesRequiringSnapshotCheck (если snapshot: false или старше snapshot_count_s3), удаляются без проверки снапшотов
  • Если для группы индексов snapshot: false, то индексы не попадают в indicesRequiringSnapshotCheck и удаляются по правилам indicesOlderThanRetentionPeriod
  • Если для unknown индексов unknown.snapshot: false, то они не попадают в indicesRequiringSnapshotCheck
  • Снапшоты получаются один раз для всех индексов (как в snapshotschecker и snapshotsbackfill)

Конфигурация:

  • Использует --osctl-indices-config для централизованной конфигурации
  • Использует --indicesdelete-check-snapshots для включения/выключения проверки снапшотов перед удалением (по умолчанию true)
  • Использует --snap-repo для проверки снапшотов (обязателен если indicesdelete-check-snapshots=true)
  • Учитывает days_count и snapshot_count_s3 из конфига индексов
  • Учитывает s3_snapshots.unit_count.all и s3_snapshots.unit_count.unknown из S3 конфига
  • Валидация конфига: all >= 1, days_count >= 1, snapshot_count_s3 >= 0

5. retention - Удаление индексов по утилизации диска

Алгоритм:

  1. Расчёт утилизации: Получаем GET /_cat/nodes?h=name,node.role,diskUsedPercent&format=json, фильтруем только data ноды (роль содержит d), считаем среднюю утилизацию по data нодам. При первом запуске (showDetails=true) логируем JSON список всех data нод с их именами, ролями и утилизацией.
  2. Если утилизация <= порога: Завершаем выполнение
  3. Проверка нод (опционально):
    • Если retention_check_nodes_down=true (по умолчанию):
      • Вызываем utils.CheckNodesDown с showDetails=true для первого запуска
      • Функция получает список нод из кластера, проверяет что все ноды имеют числовой суффикс (формат name-number), извлекает уникальные префиксы нод, получает количество реплик из Kubernetes StatefulSets для каждого префикса, суммирует реплики и сравнивает с количеством нод в кластере
      • При первом запуске логирует детальную информацию о нодах, StatefulSets и разнице
      • Если хотя бы одна нода не имеет числового суффикса - команда завершается с ошибкой (логирует проблемные имена нод)
      • Если разница между суммой реплик в StatefulSets и количеством нод в кластере != 0 - команда завершается с логом (не ошибкой) о невозможности запустить retention
    • Если retention_check_nodes_down=false: Проверка выполняется, но при ошибках только логируется предупреждение, команда продолжает работу
  4. Валидация параметров: Проверяется, что retention_days_count >= 2. Если значение меньше 2, команда завершается с ошибкой.
  5. Вычисление cutoff date: На основе параметра retention_days_count (минимум 2 дня) вычисляется дата отсечки. Индексы новее этой даты не будут удаляться.
  6. Получение кандидатов:
    • Получаем все индексы через GET /_cat/indices/*?h=index,ss&bytes=b&s=ss:desc
    • Фильтруем индексы используя utils.ShouldSkipIndexRetention (исключаем только системные индексы, начинающиеся с ., в отличие от ShouldSkipIndex не исключаем extracted_ индексы)
    • Проверяем наличие даты в имени индекса через HasDateInName
    • Исключаем индексы с будущими датами
    • Фильтрация по cutoff date: Используется функция IsOlderThanCutoff для проверки каждого индекса. Удаляются только индексы старше cutoff date.
    • Проверка утилизации в цикле: Если утилизация уже <= порога во время фильтрации - прекращаем обработку
  7. Проверка снапшотов (опционально):
    • Если retention_check_snapshots=true (по умолчанию):
      • Получаем все снапшоты через GET /_snapshot/{snap_repo}/* с обработкой 404 через GetSnapshotsIgnore404
      • Для каждого отфильтрованного индекса проверяем наличие валидного снапшота через HasValidSnapshot
      • Если снапшота нет - пропускаем индекс с предупреждением (не добавляем в список для удаления)
      • Если валидный снапшот найден - логируем факт проверки и добавляем индекс в список для удаления
    • Если retention_check_snapshots=false: Пропускаем проверку снапшотов, все отфильтрованные индексы добавляются в список для удаления
  8. Dry run режим: Показываем первые 5 индексов для удаления с их размерами
  9. Удаление индексов:
    • Для каждого индекса из списка для удаления:
      • Если утилизация уже <= порога - прекращаем удаление
      • Удаляем индекс через DELETE /{index}
      • После каждого удаления делаем паузу 15 секунд
      • Пересчитываем утилизацию через utils.GetAverageUtilization с showDetails=false (детали не логируются)
      • Проверка нод после удаления: Вызываем utils.CheckNodesDown с showDetails=false (детали не логируются). Если retention_check_nodes_down=true и разница != 0 - прекращаем удаление с логом. Если произошла ошибка и retention_check_nodes_down=true - прекращаем удаление с ошибкой. Если retention_check_nodes_down=false и произошла ошибка - только логируем предупреждение и продолжаем.
      • Останавливаем удаление, если утилизация стала меньше или равна порогу
  10. Summary: В конце выводится summary с финальной утилизацией, списком успешно удаленных индексов и списком неудачных удалений

Конфигурация:

  • Требует --snap-repo для проверки снапшотов
  • Использует --retention-threshold для порога утилизации (по умолчанию 75%)
  • Использует --retention-days-count для определения минимального возраста индексов для удаления (минимум 2 дня, по умолчанию 2 дня). Если значение меньше 2, команда завершается с ошибкой. Индексы новее cutoff date не удаляются.
  • Использует --retention-check-snapshots для включения/выключения проверки снапшотов перед удалением (по умолчанию true). Если false, индексы удаляются без проверки наличия снапшотов.
  • Использует --retention-check-nodes-down для включения/выключения проверки выбывших нод (по умолчанию true). Если true и обнаружены выбывшие ноды или ноды без числового суффикса - retention не запускается или останавливается.
  • Использует --kube-namespace для namespace Kubernetes при проверке StatefulSets (по умолчанию "infra-elklogs")
  • Индексы фильтруются функцией utils.ShouldSkipIndexRetention для исключения только системных индексов (начинающихся с .). В отличие от ShouldSkipIndex, не исключает extracted_ индексы, так как они могут быть удалены при превышении порога утилизации.
  • Индексы проверяются функцией IsOlderThanCutoff для определения соответствия cutoff date, как и в других командах программы.
  • Использует GetSnapshotsIgnore404 для получения снапшотов с корректной обработкой отсутствующих репозиториев.
  • Использует utils.GetAverageUtilization для расчета средней утилизации по data нодам (логирует детали только при первом запуске).
  • Использует utils.CheckNodesDown для проверки выбывших нод через сравнение с Kubernetes StatefulSets (логирует детали только при первом запуске).

6. dereplicator - Уменьшение реплик старых индексов

Алгоритм:

  1. Получение индексов: GET /_cat/indices/*?h=index,rep для всех индексов
  2. Фильтрация по возрасту: Для каждого индекса проверяем:
    • Индекс не системный (не начинается с .)
    • Индекс имеет реплики > 0
    • Индекс старше --dereplicator-days-count дней через IsOlderThanCutoff
  3. Проверка snapshots (если --dereplicator-use-snapshot):
    • Требуется --snap-repo
    • Получаем все snapshots через GET /_snapshot/{snap_repo}/* с обработкой 404 через GetSnapshotsIgnore404
    • Для каждого отфильтрованного индекса проверяем наличие валидного снапшота через HasValidSnapshot
    • Если снапшота нет - пропускаем индекс с предупреждением (не добавляем в список для обработки)
  4. Dry run режим: Показываем список индексов, для которых будут установлены реплики 0
  5. Установка 0 реплик:
    • Для каждого индекса из списка:
      • В dry run режиме: логируем план установки реплик
      • В обычном режиме: устанавливаем реплики через PUT /{index}/_settings с body {"index":{"number_of_replicas":0}}
      • При ошибке - логируем и добавляем в список проблемных индексов
  6. Summary: В конце выводится summary с успешно обработанными индексами, проблемными индексами и пропущенными индексами (без валидного снапшота)

Конфигурация:

  • Использует --dereplicator-days-count для количества дней (по умолчанию 2)
  • Опционально использует --dereplicator-use-snapshot для проверки снапшотов перед уменьшением реплик
  • Использует GetSnapshotsIgnore404 для получения снапшотов с корректной обработкой отсутствующих репозиториев

7. coldstorage - Миграция в cold storage

Алгоритм:

  1. Получение индексов: GET /_cat/indices/*?h=index для всех индексов
  2. Фильтрация по возрасту: Индексы старше --hot-count дней через IsOlderThanCutoff
  3. Проверка текущего состояния:
    • Для каждого кандидата получаем текущий routing.allocation.require.temp через GET /{index}/_settings
    • Если индекс уже имеет требуемый атрибут - пропускаем с логированием
  4. Dry run режим: Показываем список индексов для миграции
  5. Перемещение в cold: Через PUT /{index}/_settings с allocation settings:
    {
      "index": {
        "routing.allocation.require.temp": "{cold-attribute}",
        "number_of_replicas": 0
      }
    }

Конфигурация:

  • Использует --hot-count для количества дней в hot (по умолчанию 4)
  • Использует --cold-attribute для атрибута cold нод (по умолчанию "cold")

8. snapshotschecker - Проверка наличия снапшотов

Алгоритм:

  1. Загрузка конфигурации: Получаем osctl-indices-config, unknown.snapshot и S3 конфигурацию (unit_count.all, unit_count.unknown)
  2. Получение всех индексов: GET /_cat/indices/*?h=index для всех индексов
  3. Фильтрация индексов:
    • Пропускаем системные индексы (начинающиеся с .) и extracted индексы через ShouldSkipIndex
    • Пропускаем индексы без даты в названии
    • Исключаем индексы за сегодня и вчера
    • Остальные индексы (за позавчерашний день и старше) добавляем в список для обработки
  4. Проверка снапшотов: Получаем все снапшоты через GET /_snapshot/{repo}/*
  5. Определение индексов без снапшотов с учетом cutoff даты:
    • Для каждого индекса находим соответствующий конфиг через FindMatchingIndexConfig
    • Если конфиг найден:
      • Проверяем snapshot: true и manual_snapshot: false
      • Определяем cutoff дату: используем наименьшую (ближайшую к настоящему) из days_count и snapshot_count_s3/s3_snapshots.unit_count.all через GetLaterCutoffDate
      • Если индекс старше cutoff - пропускаем с логированием
      • Если индекс не старше cutoff - проверяем наличие валидного снапшота через HasValidSnapshot
      • Если снапшота нет - добавляем в список проблемных индексов
    • Если конфиг не найден:
      • Если включен unknown.snapshot и manual_snapshot: false:
        • Определяем cutoff дату для unknown: используем наименьшую из unknown.days_count и s3_snapshots.unit_count.unknown через GetLaterCutoffDate
        • Если индекс старше cutoff - пропускаем с логированием
        • Если индекс не старше cutoff - проверяем наличие валидного снапшота
        • Если снапшота нет - добавляем в список проблемных индексов
  6. Dry run режим: Только логирование отсутствующих снапшотов, алерты не отправляются
  7. Алерт в Madison: Если найдены отсутствующие снапшоты и не dry run - отправляем через madisonClient.SendMadisonSnapshotMissingAlert со списком всех проблемных индексов (логируется попытка отправки и результат)

Конфигурация:

  • Требует --osctl-indices-config
  • Использует --snap-repo для проверки снапшотов
  • Использует unknown.snapshot для включения unknown индексов
  • Учитывает days_count и snapshot_count_s3 из конфига индексов
  • Учитывает s3_snapshots.unit_count.all и s3_snapshots.unit_count.unknown из S3 конфига
  • Использует cutoff дату (наименьшую из days_count и S3 дней) для определения, какие индексы должны иметь снапшоты

9. snapshotsbackfill - Создание снапшотов для индексов без снапшотов

Алгоритм:

Режим 1: С параметром --indices-list

  1. Загрузка конфигурации: Получаем osctl-indices-config, unknown.snapshot и S3 конфигурацию
  2. Получение списка индексов: Парсим --indices-list (список через запятую)
  3. Фильтрация индексов:
    • Для каждого индекса проверяем наличие даты в названии через HasDateInName
    • Если даты нет - пропускаем с логированием предупреждения
    • Если дата есть - добавляем в список для обработки
  4. Проверка снапшотов: Получаем все снапшоты через GET /_snapshot/{repo}/*
  5. Определение индексов без снапшотов: Для каждого индекса проверяем наличие валидного снапшота через HasValidSnapshot
  6. Группировка по датам: Группируем индексы без снапшотов по датам через GroupIndicesByDate
  7. Сортировка дат: Сортируем даты по возрастанию (от старых к новым) через sort.Strings
  8. Сортировка индексов по размеру: Для каждой даты получаем индексы с размерами через GetIndicesWithFields с сортировкой ss:asc (от маленьких к большим) и переупорядочиваем список индексов для даты
  9. Создание снапшотов: Для каждой даты собираем задачи SnapshotTask (одна задача на группу/репозиторий) и передаем их в общий пул CreateSnapshotsInParallel (см. ниже) с сортировкой по размеру по возрастанию (сначала маленькие индексы).

Режим 2: Без параметра --indices-list

  1. Загрузка конфигурации: Получаем osctl-indices-config, unknown.snapshot и S3 конфигурацию
  2. Получение всех индексов: GET /_cat/indices/*?h=index для всех индексов
  3. Фильтрация по датам:
    • Включаем индексы за позавчерашний день и все более старые
    • Пропускаем индексы без даты в названии
  4. Проверка снапшотов: Получаем все снапшоты через GET /_snapshot/{repo}/*
  5. Определение индексов без снапшотов: Для каждого индекса проверяем наличие валидного снапшота через HasValidSnapshot
  6. Группировка по датам: Группируем индексы без снапшотов по датам через GroupIndicesByDate
  7. Сортировка дат: Сортируем даты по возрастанию (от старых к новым) через sort.Strings
  8. Сортировка индексов по размеру: Для каждой даты получаем индексы с размерами через GetIndicesWithFields с сортировкой ss:asc (от маленьких к большим) и переупорядочиваем список индексов для даты
  9. Создание снапшотов: Для каждой даты собираем задачи SnapshotTask и передаем их в общий пул CreateSnapshotsInParallel с сортировкой по размеру по возрастанию.

Алгоритм создания снапшотов для группы по дате (параллельный):

  1. Разделение конфигураций: Разделяем конфигурации на системные и обычные
  2. Обработка индексов:
    • Для каждого индекса находим соответствующий конфиг через FindMatchingIndexConfig
    • Если конфиг найден:
      • Проверяем snapshot: true и manual_snapshot: false
      • Определяем cutoff дату: используем snapshot_count_s3 из конфига, если есть, иначе s3_snapshots.unit_count.all из S3 конфига, иначе days_count из конфига, но если snapshot_count_s3 или s3_snapshots.unit_count.all более ранние - берем их
      • Если индекс старше cutoff - пропускаем с логированием
      • Добавляем индекс в группы через AddIndexToSnapshotGroups (учитывая переопределение репозитория)
    • Если конфиг не найден - добавляем в unknownIndices
  3. Фильтрация unknown индексов: Применяем FilterUnknownIndices и проверяем cutoff для unknown (используем наиболее ранний из s3_snapshots.unit_count.unknown или unknown.days_count)
  4. Группировка для снапшотов: Группируем индексы через GroupIndicesForSnapshots и на их основе формируем задачи SnapshotTask (по одной задаче на группу/репозиторий с полями: имя снапшота, индексы, репозиторий, namespace, дата, размер и интервал опроса 10 минут).
  5. Dry run режим:
    • Получаем существующие снапшоты за дату из целевого репозитория
    • Для каждой группы проверяем наличие снапшота со статусом SUCCESS:
      • Если снапшот существует и содержит все индексы - пропускаем
      • Если снапшот существует, но некоторые индексы отсутствуют - показываем план создания дополнительного снапшота с именем {baseName}-{randomSuffix}-{date} только для отсутствующих индексов
    • Фильтруем снапшоты со статусом IN_PROGRESS
    • Показываем план создания снапшотов с указанием репозитория для каждой группы
  6. Создание снапшотов (через общий пул и слоты):
    • Для каждой группы/репозитория:
      • Проверяем существующие снапшоты через GET /_snapshot/{repo}/*{date}* с обработкой 404 через GetSnapshotsIgnore404.
      • Проверяем состояние снапшота через CheckSnapshotStateInRepo:
        • Если снапшот уже SUCCESS и содержит все индексы — задачу SnapshotTask не создаем.
        • Если снапшот SUCCESS, но часть индексов отсутствует — создаем отдельную задачу SnapshotTask для {baseName}-{randomSuffix}-{date} только для отсутствующих индексов.
        • Если снапшот IN_PROGRESS — задачу не создаем, группа пропускается до следующего запуска.
      • Если снапшота нет или он не SUCCESS:
        • Проверяем/удаляем ошибочный снапшот через CheckAndCleanSnapshot.
        • Создаем задачу SnapshotTask на новый снапшот.
    • Все задачи по дате передаются в CreateSnapshotsInParallel, который:
      • Сортирует задачи по размеру по возрастанию (сначала маленькие индексы, потом большие).
      • Запускает worker‑pool с максимум max-concurrent-snapshots одновременно активными горутинами.
      • Для каждой задачи вызывает CreateSnapshotWithRetry с интервалом polling 10 минут, используя общий лимит слотов через WaitForSnapshotSlot и детальный статус _snapshot/{repo}/{snapshot}/_status для преждевременного отлова failed‑шардов.
    • Retry логика в CreateSnapshotWithRetry:
      • Аналогична команде snapshots: до 7 попыток, 15‑минутный таймаут видимости, удаление PARTIAL/FAILED снапшотов, 15‑минутная пауза перед retry, специальная обработка failed‑шардов через детальный статус.
    • Приоритет: За счет меньшего интервала ожидания свободного слота для snapshots (минуты) по сравнению с snapshotsbackfill (10 минут) обычные ежедневные снапшоты получают приоритет по занятию слотов.
    • Алертинг и ошибки: При неудаче после всех попыток отправляется алерт в Madison, ошибки по одной задаче не прерывают остальные.

Конфигурация:

  • Использует --osctl-indices-config для централизованной конфигурации
  • Поддерживает prefix и regex паттерны
  • Пропускает индексы с флагом manual_snapshot: true
  • Поддерживает переопределение репозитория через Repository в конфиге индекса
  • Учитывает days_count и snapshot_count_s3 из конфига индексов
  • Учитывает s3_snapshots.unit_count.all и s3_snapshots.unit_count.unknown из S3 конфига
  • Использует unknown.snapshot для включения unknown индексов
  • Использует общий лимит параллельных снапшотов max-concurrent-snapshots и разделяет слоты с командами snapshots и snapshot-manual

10. danglingchecker - Проверка dangling индексов

Алгоритм:

  1. Запрос dangling: GET /_dangling?pretty для получения списка dangling индексов
  2. Если найдены:
    • Извлекаем имена индексов из ответа
    • Логируем найденные dangling индексы
  3. Dry run режим: Только логирование найденных индексов, алерты не отправляются
  4. Алерт в Madison: Если найдены dangling индексы и не dry run - отправляем через SendMadisonDanglingIndicesAlert

Конфигурация:

  • Требует --madison-key, --osd-url и --madison-url для отправки алертов

11. extracteddelete - Удаление extracted индексов

Алгоритм:

  1. Подключение к Recoverer: Используется --os-recoverer-url для подключения к OpenSearch Recoverer (не к основному кластеру)
  2. Получение индексов: GET /_cat/indices/{extracted_pattern}*?h=index для всех extracted индексов (по умолчанию extracted_)
  3. Фильтрация по возрасту: Индексы старше --days дней через IsOlderThanCutoff с использованием --recoverer-date-format (по умолчанию %d-%m-%Y)
  4. Dry run режим: Показываем список extracted индексов для удаления
  5. Удаление: Через DELETE /{index} для каждого подходящего индекса

Конфигурация:

  • Использует --os-recoverer-url для подключения к Recoverer (по умолчанию https://opendistro-recoverer:9200)
  • Использует --extracted-pattern для префикса extracted индексов (по умолчанию extracted_)
  • Использует --days для количества дней хранения (по умолчанию 7)
  • Использует --recoverer-date-format для формата даты в названиях extracted индексов (по умолчанию %d-%m-%Y)

12. sharding - Автоматическое шардирование

Алгоритм:

  1. Получение всех индексов: GET /_cat/indices/*?h=index,pri.store.size&bytes=b - получаем все индексы с primary store size (без учета реплик) для вычисления максимального размера паттерна
  2. Получение индексов за сегодня: GET /_cat/indices/*-{today}*,-.*?h=index,pri.store.size&bytes=b&s=pri.store.size:desc - получаем индексы за сегодня, отсортированные по размеру
  3. Группировка по паттернам:
    • Для каждого индекса за сегодня определяем базовый паттерн: удаляем дату и все что после нее (включая суффиксы типа -00, -01)
    • Группируем индексы по базовому паттерну: {base}-*
    • Для каждого паттерна находим максимальный размер среди всех индексов с этим паттерном
  4. Вычисление максимального размера паттерна:
    • Для каждого паттерна ищем все индексы с префиксом {base}-
    • Игнорируем все что после даты в названии индекса
    • Находим максимальный primary store size среди всех индексов паттерна
    • Используем размер сегодняшнего индекса как начальное значение
  5. Получение количества data нод: GET /_cat/nodes?h=node.role&s=name - считаем ноды с ролью data (не master, не cold)
  6. Расчёт количества шардов:
    • shards_needed = max_size / target_size_gib + 1
    • Если shards_needed > dataNodes - ограничиваем shards_needed = dataNodes
    • Минимум 1 шард
  7. Расчёт реплик:
    • Если dataNodes <= 1 - устанавливаем replicas = 0
    • Иначе - устанавливаем replicas = 1
  8. Вычисление приоритета: priority = количество_дефисов_в_паттерне * 1000
  9. Проверка существующего шаблона:
    • Нормализуем паттерн (удаляем * и trailing -)
    • Ищем существующий шаблон через FindIndexTemplateByPattern
  10. Проверка default_template: Проверяем существование шаблона default_template через utils.TemplateExists (используется для добавления composed_of при создании новых шаблонов)
  11. Dry run режим:
    • Если шаблон существует: показываем изменение number_of_shards (если отличается)
    • Если шаблона нет: показываем создание нового шаблона
    • Выводим summary со всеми изменениями
  12. Обновление существующего шаблона:
    • Получаем существующий шаблон через GET /_index_template/{name}
    • Сохраняем шаблон "как есть", изменяем только:
      • template.settings.index.number_of_shards на рассчитанное значение
      • template.settings.index.query.default_field на ["message","text","log","original_message"]
    • Если установлен --sharding-routing-allocation-temp - обновляем template.settings.index.routing.allocation.require.temp
    • Отправляем обновленный шаблон через PUT /_index_template/{name}
  13. Создание нового шаблона:
    • Имя шаблона: {base}-sharding
    • Настройки индекса:
      • number_of_shards: рассчитанное количество
      • number_of_replicas: рассчитанное количество (0 или 1)
      • mapping.total_fields.limit: 2000
      • query.default_field: ["message","text","log","original_message"]
      • Если установлен --sharding-routing-allocation-temp - добавляем routing.allocation.require.temp
    • Если default_template существует (проверено через utils.TemplateExists) - добавляем composed_of: ["default_template"]
    • Приоритет: рассчитанное значение
    • Отправляем через PUT /_index_template/{name}

Конфигурация:

  • Использует --sharding-target-size-gib для целевого размера шарда (по умолчанию 25, максимум 50 GiB)
  • Использует --exclude-sharding для regex исключения паттернов
  • Использует --sharding-routing-allocation-temp для установки routing.allocation.require.temp (например, "hot")
  • Игнорирует системные индексы (начинающиеся с .)
  • При создании нового шаблона всегда добавляет composed_of: ["default_template"] если default_template существует (проверяется через utils.TemplateExists)
  • При обновлении существующего шаблона изменяет только number_of_shards и query.default_field, не трогая composed_of и другие поля

13. indexpatterns - Управление Kibana index patterns

Обновление паттернов (общая логика) Выполняется до создания паттернов.

  1. Получаем список существующих index patterns - ID и title (паттерн, например logs-*).
  2. Для каждого паттерна:
    • Через OpenSearch GetIndicesWithFields(title, "index") проверяем, есть ли в кластере индексы, совпадающие с этим паттерном.
    • Если индексов нет — логируем Info и пропускаем refresh для этого паттерна.
  3. Если индексы есть:
    • Через Kibana API CheckIndexPatternExists(tenant, id) проверяем, существует ли saved object index-pattern/{id}:
      • Если 404 (Saved object ... not found) — логируем Info и пропускаем refresh (без error-спама).
      • Если другая ошибка — логируем Warn, но пробуем выполнить refresh.
    • При refresh:
      • Получаем актуальный маппинг через GET /api/index_patterns/_fields_for_wildcard?pattern={title}&... с учетом тенанта.
      • Обновляем паттерн по его ID PUT /api/saved_objects/index-pattern/{ID}:
        • Поле version задается на верхнем уровне JSON рядом с attributes, как ожидает Kibana.

Алгоритм (multitenancy):

  1. Загрузка конфигурации тенантов: Получаем --indexpatterns-kibana-tenants-config (по умолчанию osctltenants.yaml)
  2. Для каждого тенанта:
    • Нормализуем имя тенанта: удаляем дефисы через NormalizeTenantName.
    • Ищем индекс тенанта через GET /_cat/aliases/.kibana*_{normalized_tenant}; если индекс не найден — пропускаем тенант.
    • Получаем существующие index patterns через GET /{tenant_index}/_search?q=type:index-pattern, извлекаем title и ID.
    • При всех вызовах Kibana API для этого тенанта используем заголовок securitytenant: {tenant}.
  3. Определение паттернов для создания:
    • Загружаем паттерны из конфига тенанта (indices в YAML)
    • Удаляем дубликаты через seen map
    • Для каждого паттерна проверяем существование в текущих patterns
    • Если паттерна нет - добавляем в список для создания
  4. Dry run режим: Показываем список паттернов для создания в каждом тенанте
  5. Создание patterns:
    • Для каждого паттерна создаем документ типа index-pattern через POST /{tenant_index}/_doc/index-pattern:{uuid}
    • Устанавливаем title в паттерн и timeFieldName в @timestamp

Алгоритм (без multitenancy):

  1. Загрузка regex: Получаем --kibana-index-regex (обязательно в single-tenant режиме)
  2. Получение индексов за сегодня: GET /_cat/indices/*-{today}*,-.*?h=index&s=i для индексов за сегодня
  3. Построение паттернов:
    • Применяем regex к каждому индексу
    • Извлекаем базовый паттерн через первую группу захвата regex
    • Формируем паттерн: {base}-*
    • Удаляем дубликаты
  4. Получение существующих patterns: GET /{tenant_index}/_search?q=type:index-pattern из .kibana.
  5. Создание недостающих patterns: Для каждого отсутствующего паттерна создаем через POST /{tenant_index}/_doc/index-pattern:{uuid}
  6. Создание extracted_ pattern* (если --indexpatterns-recoverer-enabled):
    • Создаем паттерн extracted_* с ссылкой на data-source через references

Конфигурация:

  • Использует --indexpatterns-kibana-multitenancy для переключения режима
  • Использует --indexpatterns-kibana-tenants-config для пути к конфигу тенантов
  • Использует --kibana-index-regex для построения паттернов в single-tenant режиме
  • Использует --indexpatterns-recoverer-enabled для создания extracted_* pattern (только в single-tenant режиме)
  • Использует --indexpatterns-refresh-enabled для обновления существующих index patterns
  • extracted_* по соображениям безопасности не создается в режиме multitenancy

14. datasource - Создание Kibana data sources

Алгоритм:

  1. Валидация параметров: Проверяем --datasource-name, --datasource-endpoint и --osd-url (обязательны)
  2. Нормализация URL: Добавляем схему https:// к osd-url если отсутствует через NormalizeURL
  3. Определение списка тенантов:
    • Если --datasource-kibana-multitenancy - загружаем тенанты из --kibana-tenants-config (общий флаг, не datasource-kibana-tenants-config)
    • Всегда добавляем "global" тенант
  4. Для каждого тенанта:
    • Получаем существующие data sources через GET /api/saved_objects/_find?type=data-source&securitytenant={tenant} (используем оригинальное имя тенанта с дефисами)
    • Проверяем наличие data source с нужным названием
    • Если не существует - создаем через POST /api/saved_objects/data-source с basic auth, используя --datasource-endpoint как endpoint для OpenSearch
  5. Multidomain режим (если --datasource-kibana-multidomain-enabled):
    • Декодируем --datasource-remote-crt (base64 строки, разделенные |)
    • Получаем ca.crt из Kubernetes секрета recoverer-certs в namespace --kube-namespace
    • Конкатенируем все сертификаты
    • Проверяем существование секрета multi-certs в Kubernetes
    • Если секрет существует - сравниваем содержимое multi.crt
    • Если содержимое отличается или секрета нет - обновляем/создаем секрет
    • Если секрет был обновлен - перезапускаем Kibana deployment (требуется доступ к Kubernetes API)
  6. Dry run режим: Показываем план создания/обновления data sources и секретов без выполнения

Конфигурация:

  • Использует --datasource-name для названия data source (по умолчанию "recoverer")
  • Использует --datasource-endpoint для OpenSearch endpoint URL при создании data source (по умолчанию "https://opendistro-recoverer:9200")
  • Использует --kibana-user и --kibana-pass для basic auth
  • Использует --kube-namespace для namespace Kubernetes секретов (по умолчанию "infra-elklogs")
  • Использует --datasource-kibana-multitenancy для включения multitenancy
  • Использует --datasource-kibana-multidomain-enabled для управления multidomain сертификатами
  • Использует --datasource-remote-crt для удаленных сертификатов (base64, разделенные |)
  • Использует общий флаг --kibana-tenants-config для загрузки тенантов (не datasource-kibana-tenants-config)

Приоритет конфигурации

  1. CLI флаги (высший приоритет)
  2. Переменные окружения
  3. Файлы конфигурации (config.yaml)
  4. Файл конфигурации индексов (osctlindicesconfig.yaml) - для команд snapshots, indicesdelete, snapshotsdelete, snapshotschecker
  5. Значения по умолчанию (низший приоритет)