• Русский
  • Под SonarQube Pod не запускается из-за проблем с Elasticsearch index

    Описание проблемы

    SonarQube Pod не переходит в состояние Ready и постоянно перезапускается. Типичные симптомы:

    • Pod находится в состоянии CrashLoopBackOff, а количество перезапусков увеличивается каждые несколько минут.

    • В логе Pod при запуске возникает NullPointerException, выброшенный из org.sonar.server.es.IndexCreator.

    • В логе Pod видно, что запуск зависает на восстановлении данных Elasticsearch, например:

      Elasticsearch is launching, waiting for recovery to complete

      после чего 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»

    Проверьте недавнюю историю перезапусков и причину каждого перезапуска:

    kubectl -n <NAMESPACE> describe pod <RELEASE>-sonarqube-xxxxx
    • Если вы видите Last State: Terminated с Reason: Error сразу после сбоя probe (например, Liveness probe failed), а в логе последним отображался процесс восстановления, значит Pod завершается в процессе восстановления. Рассматривайте это как медленное восстановление.
    • Если лог завершается stack trace (например, NullPointerException из IndexCreator или IndexNotFoundException), а Pod перезапускается без события сбоя probe, рассматривайте это как поврежденный index.

    Шаг 2 — Проверьте лог Pod на failing component

    kubectl -n <NAMESPACE> logs <RELEASE>-sonarqube-xxxxx --previous

    Убедитесь, что сбой исходит именно из процесса SonarQube, а не PostgreSQL. В соответствующих строках упоминаются IndexCreator, ElasticSearch или пути es7/es8.

    Решение

    Выберите вариант, соответствующий результату Шага 1.

    Вариант A — Дайте восстановлению больше времени (медленное восстановление)

    Если Pod завершается в процессе восстановления, временно ослабьте или отключите liveness и readiness probe, чтобы Pod не перезапускался во время длительного первого восстановления. Отредактируйте Deployment SonarQube (может потребоваться установить аннотацию skip-sync: "true" для Deployment, чтобы operator не откатил ваши изменения):

    kubectl -n <NAMESPACE> annotate deployment <RELEASE>-sonarqube skip-sync=true --overwrite
    kubectl -n <NAMESPACE> edit deployment <RELEASE>-sonarqube

    Удалите или значительно увеличьте initialDelaySeconds / failureThreshold у livenessProbe и readinessProbe, затем дождитесь, пока Pod завершит восстановление и перейдет в состояние Ready. После стабилизации удалите аннотацию skip-sync, чтобы исходная конфигурация probe была восстановлена при следующем reconcile.

    Вариант B — Сбросьте index Elasticsearch (поврежденный index)

    Удалите index на диске, чтобы SonarQube пересоздал его при следующем запуске. Точная процедура зависит от того, как предоставлен data volume:

    B.1 — Изнутри запущенного Pod (PVC или ephemeral storage)

    kubectl -n <NAMESPACE> exec -it <RELEASE>-sonarqube-xxxxx -- bash
    
    # Inside the Pod
    cd /opt/sonarqube/data
    ls       # confirm the directory name (typically es8 on SonarQube 9+)
    mv es8 es8.bak
    exit
    
    # Restart the Pod so SonarQube rebuilds the index
    kubectl -n <NAMESPACE> delete pod <RELEASE>-sonarqube-xxxxx

    Если Pod не удается удержать в рабочем состоянии достаточно долго, чтобы выполнить exec, масштабируйте Deployment до нуля, смонтируйте PVC в debug Pod (kubectl debug или небольшой манифест Pod, который монтирует тот же PVC), выполните переименование там, а затем снова увеличьте масштаб исходного Deployment.

    B.2 — При использовании localpath storage

    Войдите на node, на которой работает SonarQube Pod, найдите каталог данных SonarQube в корне localpath на node и переименуйте или удалите каталог es*:

    # On the node hosting the Pod
    ls /<LOCALPATH_ROOT>/<NAMESPACE>/<PVC_NAME>/
    mv /<LOCALPATH_ROOT>/<NAMESPACE>/<PVC_NAME>/es8 /<LOCALPATH_ROOT>/<NAMESPACE>/<PVC_NAME>/es8.bak

    Затем инициируйте перезапуск Pod:

    kubectl -n <NAMESPACE> delete pod <RELEASE>-sonarqube-xxxxx

    Шаг 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.