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
Алгоритм:
- Загрузка конфигурации: Получаем
osctl-indices-configчерез--osctl-indices-config - Разделение конфигураций: Разделяем конфигурации на системные (
system: true) и обычные (system: false) - Получение индексов:
- Системные индексы:
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)
- Системные индексы:
- Группировка индексов:
- Для каждого индекса находим соответствующий конфиг через
FindMatchingIndexConfig - Пропускаем индексы с флагом
manual_snapshot: true - Группируем индексы по паттернам через
AddIndexToSnapshotGroups, учитывая переопределение репозитория (Repositoryв конфиге) - Создаем группы по репозиториям: для каждой группы создается один снапшот
- Для каждого индекса находим соответствующий конфиг через
- Dry run режим:
- Получаем существующие снапшоты за сегодня из целевого репозитория
- Для каждой группы проверяем наличие снапшота со статусом
SUCCESS:- Если снапшот существует и содержит все индексы - пропускаем
- Если снапшот существует, но некоторые индексы отсутствуют - показываем план создания дополнительного снапшота с именем
{baseName}-{randomSuffix}-{date}только для отсутствующих индексов
- Для снапшотов со статусом
IN_PROGRESSпоказываем явное сообщение - Показываем план создания снапшотов с указанием репозитория для каждой группы
- Создание снапшотов (параллельно, с ограничением слотов):
- Для всех групп формируем список задач
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 группы: Для снапшотов в кастомных репозиториях применяется та же параллельная логика с ограничением слотов.
- Для всех групп формируем список задач
- 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
Алгоритм:
- Загрузка параметров: Получаем параметры индекса через CLI флаги (
--snapshot-manual-kind,--snapshot-manual-value,--snapshot-manual-name,--snapshot-manual-system,--snapshot-manual-repo) - Валидация: Проверяем обязательные параметры (value, name для regex)
- Получение индексов:
- Системные индексы (
--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для индексов за вчера
- Системные индексы (
- Поиск соответствующих индексов: Находим индексы соответствующие паттерну через
MatchesIndexс учетом флагаsystem - Dry run режим:
- Определяем целевой репозиторий:
snapshot-manual-repoилиsnap-repo - Проверяем существующие снапшоты в целевом репозитории
- Если снапшот со статусом
SUCCESSуже существует - завершаем без плана - Если снапшот со статусом
IN_PROGRESS- показываем явное сообщение - Показываем план создания снапшота с указанием репозитория
- Определяем целевой репозиторий:
- Создание снапшота (с учетом слотов и детального статуса):
- Перед фактическим созданием снапшота
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
Алгоритм:
- Загрузка конфигурации: Получаем
osctl-indices-configи S3 конфигурацию (unit_count.all,unit_count.unknown) - Получение снапшотов из основного репозитория:
GET /_snapshot/{repo}/*для всех снапшотов из основного репозитория - Фильтрация снапшотов основного репозитория:
- Для каждого снапшота находим соответствующий конфиг через
FindMatchingSnapshotConfig - Если снапшот имеет переопределенный репозиторий (
Repositoryв конфиге) - пропускаем его (такие снапшоты обрабатываются отдельно в кастомных репозиториях) - Если конфиг найден и
snapshot: true:- Используем
snapshot_count_s3из конфига илиunit_count.allиз S3 конфига как количество дней - Проверяем возраст через
IsOlderThanCutoff
- Используем
- Если конфиг не найден:
- Если снапшот имеет дату в названии - добавляем в
unknownSnapshots - Если снапшота нет даты в названии - добавляем в
danglingSnapshots(логируем, но не удаляем)
- Если снапшот имеет дату в названии - добавляем в
- Для каждого снапшота находим соответствующий конфиг через
- Unknown снапшоты: Если включено
unknown.snapshot, применяемunit_count.unknownдля снапшотов без конфига, но с датой в названии - Обработка переопределенных репозиториев:
- Собираем все уникальные репозитории из конфигов, где
Repository != ""иsnapshot: true - Для каждого кастомного репозитория:
- Получаем все снапшоты через
GET /_snapshot/{repo}/* - Для каждого снапшота находим соответствующий конфиг через
FindMatchingSnapshotConfig - Проверяем, что снапшот точно соответствует паттерну или регексу в конфиге:
- Конфиг должен быть найден (
ic != nil) - Репозиторий в конфиге должен совпадать с текущим репозиторием (
ic.Repository == repo) - В конфиге должно быть
snapshot: true
- Конфиг должен быть найден (
- Если снапшот не соответствует - логируем как "dangling" и пропускаем
- Если снапшот соответствует, но не имеет даты в названии - пропускаем с логированием
- Если снапшот соответствует и имеет дату - проверяем возраст:
- Используем
snapshot_count_s3из конфига илиunit_count.allиз S3 конфига - Если снапшот старше - добавляем в список для удаления из этого репозитория
- Используем
- Получаем все снапшоты через
- Собираем все уникальные репозитории из конфигов, где
- Dry run режим: Показываем список снапшотов для удаления, группируя по репозиториям
- Удаление: Через
DeleteSnapshotsBatchс группировкой по репозиториям (основной и кастомные)
Примечания:
- Никогда не трогаем снапшоты без даты в нужном формате старше чем Unknown политика, но выводим их в лог
- Снапшоты в переопределенных репозиториях обрабатываются только если они точно соответствуют паттерну или регексу в конфиге и находятся в правильном репозитории
- Снапшоты из основного репозитория, у которых в конфиге указан переопределенный репозиторий, не обрабатываются (они должны обрабатываться в своем кастомном репозитории)
Алгоритм:
- Загрузка конфигурации: Получаем
osctl-indices-config,unknown.days_count, S3 конфигурацию (unit_count.all,unit_count.unknown) иindicesdelete_check_snapshots - Валидация конфигурации (при загрузке):
- Если есть секции
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
- Если есть секции
- Получение индексов:
GET /_cat/indices/*?h=index,cd&bytes=b&s=index:ascдля всех индексов - Фильтрация индексов:
- Пропускаем системные индексы (начинающиеся с
.) - Пропускаем 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)
- Определяем cutoff дату для снапшотов: используем
- Индексы старше retention period (days_count): Проверяем возраст через
- Если у индекса нет даты в названии - просто логируем (не проверяем возраст, не удаляем)
- Если индекс имеет дату в названии:
- Если конфиг не найден:
- Если индекс имеет дату в названии - добавляем в
unknownIndicesдля дальнейшей обработки - Если у индекса нет даты в названии - просто логируем (не проверяем возраст, не добавляем в unknown, не удаляем)
- Если индекс имеет дату в названии - добавляем в
- Пропускаем системные индексы (начинающиеся с
- Фильтрация unknown индексов: Применяем
FilterUnknownIndicesдля исключения известных паттернов (только для индексов с датой в названии) - Обработка 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)
- Определяем cutoff дату для снапшотов: используем
- Индексы старше retention period: Если
- Логирование списков: Логируем оба списка с указанием количества и полного списка индексов
- Проверка снапшотов (если есть индексы, требующие проверки):
- Если
indicesdelete_check_snapshots=true:- Проверяем наличие
snap-repo- если не настроен, джоба завершается с ошибкой - Получаем все снапшоты один раз через
GET /_snapshot/{snap_repo}/*с обработкой 404 черезGetSnapshotsIgnore404(для избежания зависаний) - Если произошла ошибка при получении снапшотов - джоба завершается с ошибкой
- Для каждого индекса из списка
indicesRequiringSnapshotCheckпроверяем наличие валидного снапшота черезHasValidSnapshot - Если снапшот найден - логируем и добавляем индекс в финальный список для удаления
- Если снапшота нет - логируем предупреждение и НЕ добавляем индекс в финальный список (но сохраняем для summary)
- Добавляем все индексы из
indicesOlderThanRetentionPeriod, которые не вindicesRequiringSnapshotCheck(для них проверка не требуется) в финальный список для удаления
- Проверяем наличие
- Если
indicesdelete_check_snapshots=false:- Пропускаем проверку снапшотов, используем только
indicesOlderThanRetentionPeriod(все индексы старшеdays_countудаляются без проверки)
- Пропускаем проверку снапшотов, используем только
- Если
- Dry run режим: Показываем финальный список индексов для удаления
- Удаление: Через
BatchDeleteIndicesс dry run поддержкой - 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
Алгоритм:
- Расчёт утилизации: Получаем
GET /_cat/nodes?h=name,node.role,diskUsedPercent&format=json, фильтруем только data ноды (роль содержитd), считаем среднюю утилизацию по data нодам. При первом запуске (showDetails=true) логируем JSON список всех data нод с их именами, ролями и утилизацией. - Если утилизация <= порога: Завершаем выполнение
- Проверка нод (опционально):
- Если
retention_check_nodes_down=true(по умолчанию):- Вызываем
utils.CheckNodesDownсshowDetails=trueдля первого запуска - Функция получает список нод из кластера, проверяет что все ноды имеют числовой суффикс (формат
name-number), извлекает уникальные префиксы нод, получает количество реплик из Kubernetes StatefulSets для каждого префикса, суммирует реплики и сравнивает с количеством нод в кластере - При первом запуске логирует детальную информацию о нодах, StatefulSets и разнице
- Если хотя бы одна нода не имеет числового суффикса - команда завершается с ошибкой (логирует проблемные имена нод)
- Если разница между суммой реплик в StatefulSets и количеством нод в кластере != 0 - команда завершается с логом (не ошибкой) о невозможности запустить retention
- Вызываем
- Если
retention_check_nodes_down=false: Проверка выполняется, но при ошибках только логируется предупреждение, команда продолжает работу
- Если
- Валидация параметров: Проверяется, что
retention_days_count >= 2. Если значение меньше 2, команда завершается с ошибкой. - Вычисление cutoff date: На основе параметра
retention_days_count(минимум 2 дня) вычисляется дата отсечки. Индексы новее этой даты не будут удаляться. - Получение кандидатов:
- Получаем все индексы через
GET /_cat/indices/*?h=index,ss&bytes=b&s=ss:desc - Фильтруем индексы используя
utils.ShouldSkipIndexRetention(исключаем только системные индексы, начинающиеся с., в отличие отShouldSkipIndexне исключаемextracted_индексы) - Проверяем наличие даты в имени индекса через
HasDateInName - Исключаем индексы с будущими датами
- Фильтрация по cutoff date: Используется функция
IsOlderThanCutoffдля проверки каждого индекса. Удаляются только индексы старше cutoff date. - Проверка утилизации в цикле: Если утилизация уже <= порога во время фильтрации - прекращаем обработку
- Получаем все индексы через
- Проверка снапшотов (опционально):
- Если
retention_check_snapshots=true(по умолчанию):- Получаем все снапшоты через
GET /_snapshot/{snap_repo}/*с обработкой 404 черезGetSnapshotsIgnore404 - Для каждого отфильтрованного индекса проверяем наличие валидного снапшота через
HasValidSnapshot - Если снапшота нет - пропускаем индекс с предупреждением (не добавляем в список для удаления)
- Если валидный снапшот найден - логируем факт проверки и добавляем индекс в список для удаления
- Получаем все снапшоты через
- Если
retention_check_snapshots=false: Пропускаем проверку снапшотов, все отфильтрованные индексы добавляются в список для удаления
- Если
- Dry run режим: Показываем первые 5 индексов для удаления с их размерами
- Удаление индексов:
- Для каждого индекса из списка для удаления:
- Если утилизация уже <= порога - прекращаем удаление
- Удаляем индекс через
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и произошла ошибка - только логируем предупреждение и продолжаем. - Останавливаем удаление, если утилизация стала меньше или равна порогу
- Для каждого индекса из списка для удаления:
- 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 (логирует детали только при первом запуске).
Алгоритм:
- Получение индексов:
GET /_cat/indices/*?h=index,repдля всех индексов - Фильтрация по возрасту: Для каждого индекса проверяем:
- Индекс не системный (не начинается с
.) - Индекс имеет реплики > 0
- Индекс старше
--dereplicator-days-countдней черезIsOlderThanCutoff
- Индекс не системный (не начинается с
- Проверка snapshots (если
--dereplicator-use-snapshot):- Требуется
--snap-repo - Получаем все snapshots через
GET /_snapshot/{snap_repo}/*с обработкой 404 черезGetSnapshotsIgnore404 - Для каждого отфильтрованного индекса проверяем наличие валидного снапшота через
HasValidSnapshot - Если снапшота нет - пропускаем индекс с предупреждением (не добавляем в список для обработки)
- Требуется
- Dry run режим: Показываем список индексов, для которых будут установлены реплики 0
- Установка 0 реплик:
- Для каждого индекса из списка:
- В dry run режиме: логируем план установки реплик
- В обычном режиме: устанавливаем реплики через
PUT /{index}/_settingsс body{"index":{"number_of_replicas":0}} - При ошибке - логируем и добавляем в список проблемных индексов
- Для каждого индекса из списка:
- Summary: В конце выводится summary с успешно обработанными индексами, проблемными индексами и пропущенными индексами (без валидного снапшота)
Конфигурация:
- Использует
--dereplicator-days-countдля количества дней (по умолчанию 2) - Опционально использует
--dereplicator-use-snapshotдля проверки снапшотов перед уменьшением реплик - Использует
GetSnapshotsIgnore404для получения снапшотов с корректной обработкой отсутствующих репозиториев
Алгоритм:
- Получение индексов:
GET /_cat/indices/*?h=indexдля всех индексов - Фильтрация по возрасту: Индексы старше
--hot-countдней черезIsOlderThanCutoff - Проверка текущего состояния:
- Для каждого кандидата получаем текущий
routing.allocation.require.tempчерезGET /{index}/_settings - Если индекс уже имеет требуемый атрибут - пропускаем с логированием
- Для каждого кандидата получаем текущий
- Dry run режим: Показываем список индексов для миграции
- Перемещение в 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")
Алгоритм:
- Загрузка конфигурации: Получаем
osctl-indices-config,unknown.snapshotи S3 конфигурацию (unit_count.all,unit_count.unknown) - Получение всех индексов:
GET /_cat/indices/*?h=indexдля всех индексов - Фильтрация индексов:
- Пропускаем системные индексы (начинающиеся с
.) и extracted индексы черезShouldSkipIndex - Пропускаем индексы без даты в названии
- Исключаем индексы за сегодня и вчера
- Остальные индексы (за позавчерашний день и старше) добавляем в список для обработки
- Пропускаем системные индексы (начинающиеся с
- Проверка снапшотов: Получаем все снапшоты через
GET /_snapshot/{repo}/* - Определение индексов без снапшотов с учетом 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 - проверяем наличие валидного снапшота
- Если снапшота нет - добавляем в список проблемных индексов
- Определяем cutoff дату для unknown: используем наименьшую из
- Если включен
- Для каждого индекса находим соответствующий конфиг через
- Dry run режим: Только логирование отсутствующих снапшотов, алерты не отправляются
- Алерт в 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 дней) для определения, какие индексы должны иметь снапшоты
Алгоритм:
Режим 1: С параметром --indices-list
- Загрузка конфигурации: Получаем
osctl-indices-config,unknown.snapshotи S3 конфигурацию - Получение списка индексов: Парсим
--indices-list(список через запятую) - Фильтрация индексов:
- Для каждого индекса проверяем наличие даты в названии через
HasDateInName - Если даты нет - пропускаем с логированием предупреждения
- Если дата есть - добавляем в список для обработки
- Для каждого индекса проверяем наличие даты в названии через
- Проверка снапшотов: Получаем все снапшоты через
GET /_snapshot/{repo}/* - Определение индексов без снапшотов: Для каждого индекса проверяем наличие валидного снапшота через
HasValidSnapshot - Группировка по датам: Группируем индексы без снапшотов по датам через
GroupIndicesByDate - Сортировка дат: Сортируем даты по возрастанию (от старых к новым) через
sort.Strings - Сортировка индексов по размеру: Для каждой даты получаем индексы с размерами через
GetIndicesWithFieldsс сортировкойss:asc(от маленьких к большим) и переупорядочиваем список индексов для даты - Создание снапшотов: Для каждой даты собираем задачи
SnapshotTask(одна задача на группу/репозиторий) и передаем их в общий пулCreateSnapshotsInParallel(см. ниже) с сортировкой по размеру по возрастанию (сначала маленькие индексы).
Режим 2: Без параметра --indices-list
- Загрузка конфигурации: Получаем
osctl-indices-config,unknown.snapshotи S3 конфигурацию - Получение всех индексов:
GET /_cat/indices/*?h=indexдля всех индексов - Фильтрация по датам:
- Включаем индексы за позавчерашний день и все более старые
- Пропускаем индексы без даты в названии
- Проверка снапшотов: Получаем все снапшоты через
GET /_snapshot/{repo}/* - Определение индексов без снапшотов: Для каждого индекса проверяем наличие валидного снапшота через
HasValidSnapshot - Группировка по датам: Группируем индексы без снапшотов по датам через
GroupIndicesByDate - Сортировка дат: Сортируем даты по возрастанию (от старых к новым) через
sort.Strings - Сортировка индексов по размеру: Для каждой даты получаем индексы с размерами через
GetIndicesWithFieldsс сортировкойss:asc(от маленьких к большим) и переупорядочиваем список индексов для даты - Создание снапшотов: Для каждой даты собираем задачи
SnapshotTaskи передаем их в общий пулCreateSnapshotsInParallelс сортировкой по размеру по возрастанию.
Алгоритм создания снапшотов для группы по дате (параллельный):
- Разделение конфигураций: Разделяем конфигурации на системные и обычные
- Обработка индексов:
- Для каждого индекса находим соответствующий конфиг через
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
- Для каждого индекса находим соответствующий конфиг через
- Фильтрация unknown индексов: Применяем
FilterUnknownIndicesи проверяем cutoff для unknown (используем наиболее ранний изs3_snapshots.unit_count.unknownилиunknown.days_count) - Группировка для снапшотов: Группируем индексы через
GroupIndicesForSnapshotsи на их основе формируем задачиSnapshotTask(по одной задаче на группу/репозиторий с полями: имя снапшота, индексы, репозиторий, namespace, дата, размер и интервал опроса 10 минут). - Dry run режим:
- Получаем существующие снапшоты за дату из целевого репозитория
- Для каждой группы проверяем наличие снапшота со статусом
SUCCESS:- Если снапшот существует и содержит все индексы - пропускаем
- Если снапшот существует, но некоторые индексы отсутствуют - показываем план создания дополнительного снапшота с именем
{baseName}-{randomSuffix}-{date}только для отсутствующих индексов
- Фильтруем снапшоты со статусом
IN_PROGRESS - Показываем план создания снапшотов с указанием репозитория для каждой группы
- Создание снапшотов (через общий пул и слоты):
- Для каждой группы/репозитория:
- Проверяем существующие снапшоты через
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
Алгоритм:
- Запрос dangling:
GET /_dangling?prettyдля получения списка dangling индексов - Если найдены:
- Извлекаем имена индексов из ответа
- Логируем найденные dangling индексы
- Dry run режим: Только логирование найденных индексов, алерты не отправляются
- Алерт в Madison: Если найдены dangling индексы и не dry run - отправляем через
SendMadisonDanglingIndicesAlert
Конфигурация:
- Требует
--madison-key,--osd-urlи--madison-urlдля отправки алертов
Алгоритм:
- Подключение к Recoverer: Используется
--os-recoverer-urlдля подключения к OpenSearch Recoverer (не к основному кластеру) - Получение индексов:
GET /_cat/indices/{extracted_pattern}*?h=indexдля всех extracted индексов (по умолчаниюextracted_) - Фильтрация по возрасту: Индексы старше
--daysдней черезIsOlderThanCutoffс использованием--recoverer-date-format(по умолчанию%d-%m-%Y) - Dry run режим: Показываем список extracted индексов для удаления
- Удаление: Через
DELETE /{index}для каждого подходящего индекса
Конфигурация:
- Использует
--os-recoverer-urlдля подключения к Recoverer (по умолчаниюhttps://opendistro-recoverer:9200) - Использует
--extracted-patternдля префикса extracted индексов (по умолчаниюextracted_) - Использует
--daysдля количества дней хранения (по умолчанию 7) - Использует
--recoverer-date-formatдля формата даты в названиях extracted индексов (по умолчанию%d-%m-%Y)
Алгоритм:
- Получение всех индексов:
GET /_cat/indices/*?h=index,pri.store.size&bytes=b- получаем все индексы с primary store size (без учета реплик) для вычисления максимального размера паттерна - Получение индексов за сегодня:
GET /_cat/indices/*-{today}*,-.*?h=index,pri.store.size&bytes=b&s=pri.store.size:desc- получаем индексы за сегодня, отсортированные по размеру - Группировка по паттернам:
- Для каждого индекса за сегодня определяем базовый паттерн: удаляем дату и все что после нее (включая суффиксы типа
-00,-01) - Группируем индексы по базовому паттерну:
{base}-* - Для каждого паттерна находим максимальный размер среди всех индексов с этим паттерном
- Для каждого индекса за сегодня определяем базовый паттерн: удаляем дату и все что после нее (включая суффиксы типа
- Вычисление максимального размера паттерна:
- Для каждого паттерна ищем все индексы с префиксом
{base}- - Игнорируем все что после даты в названии индекса
- Находим максимальный primary store size среди всех индексов паттерна
- Используем размер сегодняшнего индекса как начальное значение
- Для каждого паттерна ищем все индексы с префиксом
- Получение количества data нод:
GET /_cat/nodes?h=node.role&s=name- считаем ноды с рольюdata(не master, не cold) - Расчёт количества шардов:
shards_needed = max_size / target_size_gib + 1- Если
shards_needed > dataNodes- ограничиваемshards_needed = dataNodes - Минимум 1 шард
- Расчёт реплик:
- Если
dataNodes <= 1- устанавливаемreplicas = 0 - Иначе - устанавливаем
replicas = 1
- Если
- Вычисление приоритета:
priority = количество_дефисов_в_паттерне * 1000 - Проверка существующего шаблона:
- Нормализуем паттерн (удаляем
*и trailing-) - Ищем существующий шаблон через
FindIndexTemplateByPattern
- Нормализуем паттерн (удаляем
- Проверка default_template: Проверяем существование шаблона
default_templateчерезutils.TemplateExists(используется для добавленияcomposed_ofпри создании новых шаблонов) - Dry run режим:
- Если шаблон существует: показываем изменение
number_of_shards(если отличается) - Если шаблона нет: показываем создание нового шаблона
- Выводим summary со всеми изменениями
- Если шаблон существует: показываем изменение
- Обновление существующего шаблона:
- Получаем существующий шаблон через
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}
- Получаем существующий шаблон через
- Создание нового шаблона:
- Имя шаблона:
{base}-sharding - Настройки индекса:
number_of_shards: рассчитанное количествоnumber_of_replicas: рассчитанное количество (0 или 1)mapping.total_fields.limit: 2000query.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и другие поля
Обновление паттернов (общая логика) Выполняется до создания паттернов.
- Получаем список существующих index patterns - ID и
title(паттерн, напримерlogs-*). - Для каждого паттерна:
- Через OpenSearch
GetIndicesWithFields(title, "index")проверяем, есть ли в кластере индексы, совпадающие с этим паттерном. - Если индексов нет — логируем Info и пропускаем refresh для этого паттерна.
- Через OpenSearch
- Если индексы есть:
- Через Kibana API
CheckIndexPatternExists(tenant, id)проверяем, существует ли saved objectindex-pattern/{id}:- Если 404 (
Saved object ... not found) — логируем Info и пропускаем refresh (без error-спама). - Если другая ошибка — логируем Warn, но пробуем выполнить refresh.
- Если 404 (
- При refresh:
- Получаем актуальный маппинг через
GET /api/index_patterns/_fields_for_wildcard?pattern={title}&...с учетом тенанта. - Обновляем паттерн по его ID
PUT /api/saved_objects/index-pattern/{ID}:- Поле
versionзадается на верхнем уровне JSON рядом сattributes, как ожидает Kibana.
- Поле
- Получаем актуальный маппинг через
- Через Kibana API
Алгоритм (multitenancy):
- Загрузка конфигурации тенантов: Получаем
--indexpatterns-kibana-tenants-config(по умолчаниюosctltenants.yaml) - Для каждого тенанта:
- Нормализуем имя тенанта: удаляем дефисы через
NormalizeTenantName. - Ищем индекс тенанта через
GET /_cat/aliases/.kibana*_{normalized_tenant}; если индекс не найден — пропускаем тенант. - Получаем существующие index patterns через
GET /{tenant_index}/_search?q=type:index-pattern, извлекаемtitleи ID. - При всех вызовах Kibana API для этого тенанта используем заголовок
securitytenant: {tenant}.
- Нормализуем имя тенанта: удаляем дефисы через
- Определение паттернов для создания:
- Загружаем паттерны из конфига тенанта (
indicesв YAML) - Удаляем дубликаты через
seenmap - Для каждого паттерна проверяем существование в текущих patterns
- Если паттерна нет - добавляем в список для создания
- Загружаем паттерны из конфига тенанта (
- Dry run режим: Показываем список паттернов для создания в каждом тенанте
- Создание patterns:
- Для каждого паттерна создаем документ типа
index-patternчерезPOST /{tenant_index}/_doc/index-pattern:{uuid} - Устанавливаем
titleв паттерн иtimeFieldNameв@timestamp
- Для каждого паттерна создаем документ типа
Алгоритм (без multitenancy):
- Загрузка regex: Получаем
--kibana-index-regex(обязательно в single-tenant режиме) - Получение индексов за сегодня:
GET /_cat/indices/*-{today}*,-.*?h=index&s=iдля индексов за сегодня - Построение паттернов:
- Применяем regex к каждому индексу
- Извлекаем базовый паттерн через первую группу захвата regex
- Формируем паттерн:
{base}-* - Удаляем дубликаты
- Получение существующих patterns:
GET /{tenant_index}/_search?q=type:index-patternиз.kibana. - Создание недостающих patterns: Для каждого отсутствующего паттерна создаем через
POST /{tenant_index}/_doc/index-pattern:{uuid} - Создание 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
Алгоритм:
- Валидация параметров: Проверяем
--datasource-name,--datasource-endpointи--osd-url(обязательны) - Нормализация URL: Добавляем схему
https://кosd-urlесли отсутствует черезNormalizeURL - Определение списка тенантов:
- Если
--datasource-kibana-multitenancy- загружаем тенанты из--kibana-tenants-config(общий флаг, неdatasource-kibana-tenants-config) - Всегда добавляем "global" тенант
- Если
- Для каждого тенанта:
- Получаем существующие 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
- Получаем существующие data sources через
- 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)
- Декодируем
- 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)
- CLI флаги (высший приоритет)
- Переменные окружения
- Файлы конфигурации (
config.yaml) - Файл конфигурации индексов (
osctlindicesconfig.yaml) - для командsnapshots,indicesdelete,snapshotsdelete,snapshotschecker - Значения по умолчанию (низший приоритет)