• Русский
  • SonarQube Pod зависает при запуске, когда том данных размещён на NFS

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

    Экземпляр SonarQube, у которого том данных размещён на NFS export, не переходит в состояние Ready. Симптомы:

    • Pod PostgreSQL исправен и не перезапускается.
    • Pod SonarQube находится в состоянии Running или застревает в цикле запуска, но так и не сообщает состояние Ready.
    • Журнал Pod продолжает обновляться во время инициализации, а затем зависает на шаге, который читает или записывает файлы в /opt/sonarqube/data. Исключения не возникает — процесс просто перестаёт выводить сообщения на длительное время.
    • Режим файла и права владения внутри Pod могут выглядеть иначе, чем в среде без NFS, но их изменение не помогает.

    Сам NFS export настроен с ожидаемыми параметрами (например, rw,async,no_root_squash,no_all_squash) и доступен из кластера.

    Причина

    SonarQube и встроенный Elasticsearch требуют блокировки файлов для координации доступа к данным на диске. По умолчанию монтирования NFSv3 согласуют блокировки через rpc.lockd / rpc.statd. Если daemons блокировок недоступны с клиента (обычно потому, что они не доступны через network policy, либо на NFS-сервере они не запущены), операции файловой блокировки, выполняемые SonarQube, блокируются бесконечно. Pod остаётся активным, но не может продолжить выполнение, что проявляется как «зависание при запуске».

    Параметр монтирования, который указывает клиенту обрабатывать блокировки локально вместо обращения к серверу, — это nolock. При включённом nolock файловые блокировки становятся локальными для процесса — этого достаточно для одноподового SonarQube — и запуск продолжается нормально.

    Диагностика

    Шаг 1 — Убедитесь, что Pod зависает на операции файловой системы

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

    Журнал, который обрывается посреди шага (чаще всего во время инициализации Elasticsearch или первоначального создания индексов в /opt/sonarqube/data) и не выдаёт новых сообщений в течение нескольких минут, — типичный признак этой проблемы.

    Шаг 2 — Проверьте параметры монтирования на узле

    Определите узел, на котором работает Pod SonarQube, и проверьте параметры монтирования NFS export, который используется для PVC данных SonarQube:

    kubectl -n <NAMESPACE> get pod <RELEASE>-sonarqube-xxxxx -o wide
    
    # On the listed node
    mount | grep nfs

    Если в параметрах монтирования нет nolock, то, вероятно, речь идёт именно об этой проблеме. Наличие параметров вроде local_lock=none или отсутствие записи lock вообще соответствует этому режиму отказа.

    Шаг 3 — Сначала исключите неверную настройку на стороне export

    Если в export отсутствуют rw, no_root_squash или no_all_squash, сначала исправьте это — это другие режимы отказа, и nolock их не устранит. Переходите к решению ниже только после того, как убедитесь, что параметры export корректны и Pod может читать и записывать файлы (но не может их блокировать).

    Решение

    Добавьте nolock в параметры монтирования NFS PV, используемого SonarQube, затем перезапустите Pod SonarQube, чтобы он перемонтировал том с новыми параметрами.

    При использовании NFS PV, созданного вручную

    Отредактируйте PersistentVolume и добавьте nolock в spec.mountOptions:

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: <PV_NAME>
    spec:
      mountOptions:
        - nolock
        # other existing options (e.g. nfsvers=4.1, rw, ...)
      nfs:
        server: <NFS_SERVER>
        path: <EXPORT_PATH>
      # ...

    При использовании динамического NFS StorageClass

    Отредактируйте StorageClass и добавьте nolock в mountOptions, затем пересоздайте PVC (и Pod), чтобы новые параметры вступили в силу на только что созданном PV:

    apiVersion: storage.k8s.io/v1
    kind: StorageClass
    metadata:
      name: <STORAGE_CLASS_NAME>
    mountOptions:
      - nolock
    provisioner: <NFS_PROVISIONER>
    # ...

    Примените изменение

    После обновления PV или StorageClass пересоздайте Pod SonarQube, чтобы том был перемонтирован:

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

    Убедитесь, что на узле используются новые параметры монтирования, затем дождитесь запуска Pod:

    # On the node now hosting the new Pod
    mount | grep nfs    # expect to see nolock
    
    kubectl -n <NAMESPACE> get pods -w

    Примечания

    • nolock безопасен для одноподового SonarQube. SonarQube работает как один Pod, использующий свой том данных, поэтому локальных для процесса блокировок достаточно. Не используйте nolock для рабочих нагрузок, которым действительно требуется межузловая координация через NFS locks.
    • NFSv4. В NFSv4 файловая блокировка является частью самого протокола и не требует rpc.lockd / rpc.statd. Если export доступен как NFSv4 (vers=4 / vers=4.1), но блокировка по-прежнему зависает, сначала ищите другую причину, прежде чем применять nolock.
    • Справка. В документации Red Hat по параметрам монтирования NFS описан nolock и остальные параметры: Mounting NFS shares.