Под SonarQube Pod не запускается из-за проблем с Elasticsearch index
Содержание
Описание проблемыКорневая причинаДиагностикаШаг 1 — Различите «медленное восстановление» и «поврежденный index»Шаг 2 — Проверьте лог Pod на failing componentРешениеВариант A — Дайте восстановлению больше времени (медленное восстановление)Вариант B — Сбросьте index Elasticsearch (поврежденный index)B.1 — Изнутри запущенного Pod (PVC или ephemeral storage)B.2 — При использованииlocalpath storageШаг 3 — Проверьте восстановлениеПримечанияОписание проблемы
SonarQube Pod не переходит в состояние Ready и постоянно перезапускается. Типичные симптомы:
-
Pod находится в состоянии
CrashLoopBackOff, а количество перезапусков увеличивается каждые несколько минут. -
В логе Pod при запуске возникает
NullPointerException, выброшенный изorg.sonar.server.es.IndexCreator. -
В логе Pod видно, что запуск зависает на восстановлении данных Elasticsearch, например:
после чего Pod в итоге завершается по причине liveness или readiness probe.
В этих случаях PostgreSQL исправен: его Pod находится в состоянии Running и не перезапускается; проблема наблюдается только у SonarQube Pod.
Корневая причина
SonarQube встраивает экземпляр Elasticsearch в /opt/sonarqube/data/es8 (каталог соответствует major-версии встроенного Elasticsearch; в более старых версиях SonarQube использовался es7). Запуск может быть заблокирован двумя связанными условиями:
- Поврежденный index Elasticsearch. Файлы index находятся в несогласованном состоянии — обычно после некорректного завершения работы, сбоя хранилища или нехватки места на диске. SonarQube не может открыть index, и web-процесс аварийно завершает работу. В новой установке это проявляется как
NullPointerExceptionвIndexCreator; в существующей установке — как цикл перезапуска при запуске. - Медленное восстановление, прерываемое probe. Elasticsearch способен восстановить index, но на это требуется больше времени, чем допускает liveness или readiness probe, поэтому Pod завершается в процессе восстановления, и цикл повторяется.
Данные Elasticsearch в SonarQube — это производное состояние. Они автоматически перестраиваются из PostgreSQL при следующем запуске, поэтому удаление index не приводит к потере пользовательских данных — это лишь откладывает первый запуск до завершения повторного создания index.
Диагностика
Шаг 1 — Различите «медленное восстановление» и «поврежденный index»
Проверьте недавнюю историю перезапусков и причину каждого перезапуска:
- Если вы видите
Last State: TerminatedсReason: Errorсразу после сбоя probe (например,Liveness probe failed), а в логе последним отображался процесс восстановления, значит Pod завершается в процессе восстановления. Рассматривайте это как медленное восстановление. - Если лог завершается stack trace (например,
NullPointerExceptionизIndexCreatorилиIndexNotFoundException), а Pod перезапускается без события сбоя probe, рассматривайте это как поврежденный index.
Шаг 2 — Проверьте лог Pod на failing component
Убедитесь, что сбой исходит именно из процесса SonarQube, а не PostgreSQL. В соответствующих строках упоминаются IndexCreator, ElasticSearch или пути es7/es8.
Решение
Выберите вариант, соответствующий результату Шага 1.
Вариант A — Дайте восстановлению больше времени (медленное восстановление)
Если Pod завершается в процессе восстановления, временно ослабьте или отключите liveness и readiness probe, чтобы Pod не перезапускался во время длительного первого восстановления. Отредактируйте Deployment SonarQube (может потребоваться установить аннотацию skip-sync: "true" для Deployment, чтобы operator не откатил ваши изменения):
Удалите или значительно увеличьте initialDelaySeconds / failureThreshold у livenessProbe и readinessProbe, затем дождитесь, пока Pod завершит восстановление и перейдет в состояние Ready. После стабилизации удалите аннотацию skip-sync, чтобы исходная конфигурация probe была восстановлена при следующем reconcile.
Вариант B — Сбросьте index Elasticsearch (поврежденный index)
Удалите index на диске, чтобы SonarQube пересоздал его при следующем запуске. Точная процедура зависит от того, как предоставлен data volume:
B.1 — Изнутри запущенного Pod (PVC или ephemeral storage)
Если Pod не удается удержать в рабочем состоянии достаточно долго, чтобы выполнить exec, масштабируйте Deployment до нуля, смонтируйте PVC в debug Pod (kubectl debug или небольшой манифест Pod, который монтирует тот же PVC), выполните переименование там, а затем снова увеличьте масштаб исходного Deployment.
B.2 — При использовании localpath storage
Войдите на node, на которой работает SonarQube Pod, найдите каталог данных SonarQube в корне localpath на node и переименуйте или удалите каталог es*:
Затем инициируйте перезапуск Pod:
Шаг 3 — Проверьте восстановление
Дождитесь, пока Pod перейдет в состояние Ready, затем убедитесь в пользовательском интерфейсе SonarQube, что проекты, issues и rules отображаются корректно. Первый scan после повторного индексирования может занять больше времени, чем обычно, поскольку index заполняется заново.
Если index сброшен, а Pod по-прежнему не запускается, значит проблема не в Elasticsearch — перед повторной попыткой еще раз проверьте лог Pod на предмет основной ошибки.
Примечания
- Место на storage. Оба сценария сбоя часто вызываются тем, что data volume заканчивается по дисковому пространству. Прежде чем считать index поврежденным, проверьте
df -h /opt/sonarqube/dataвнутри Pod (или эквивалентный путь на node) и увеличьте размер volume, если он заполнен. - Резервные копии. Каталог
es8.bak, созданный в Варианте B, можно удалить после того, как SonarQube снова станет стабильным. До этого момента сохраняйте его на случай, если потребуется rollback. - Официальная рекомендация. Документированная SonarQube процедура принудительного повторного индексирования Elasticsearch является upstream reference для этого сценария: см. Reindexing.