SonarQube: Unrecoverable indexation failures и Elasticsearch “Disk watermark exceeded”

Автор: | 29/08/2019
 

Есть SonarQube, запускается из Jenkins-джоб.

См. SonarQube: запуск в Docker и вызов из Jenkins Pipeline.

SonarQube из Jenkins запускается, задачи проходят, но в самом SonarQube возникает ошибка:

java.lang.IllegalStateException: Unrecoverable indexation failures: 1 errors among 1 requests
at org.sonar.server.es.IndexingListener$1.onFinish(IndexingListener.java:39)
at org.sonar.server.es.BulkIndexer.stop(BulkIndexer.java:122)

Логи SonarQube:

Aug 29 12:30:26 jenkins-production docker-compose[12591]: sonarqube_1  | 2019.08.29 09:30:26 ERROR web[][o.s.s.es.BulkIndexer] index [components], type [auth], id [AWzcfdpYaLFDDA6l6km3], message [ClusterBlockException[blocked by: [FORBIDD
EN/12/index read-only / allow delete (api)];]]
Aug 29 12:30:26 jenkins-production docker-compose[12591]: sonarqube_1  | 2019.08.29 09:30:26 ERROR web[][o.s.s.e.RecoveryIndexer] Elasticsearch recovery – too many failures [167/167 documents], waiting for next run
Aug 29 12:30:26 jenkins-production docker-compose[12591]: sonarqube_1  | 2019.08.29 09:30:26 INFO  web[][o.s.s.e.RecoveryIndexer] Elasticsearch recovery – 167 documents processed [167 failures] | time=51ms
Aug 29 12:30:48 jenkins-production docker-compose[12591]: sonarqube_1  | 2019.08.29 09:30:48 INFO  es[][o.e.c.r.a.DiskThresholdMonitor] low disk watermark [85%] exceeded on [mjJvGbfOSZyVqbKWKCGwxw][sonarqube][/opt/sonarqube/data/es6/nodes
/0] free: 11.6gb[11.8%], replicas will not be assigned to this node

Смотрим документацию Disk-based shard allocation – надо обновить cluster.routing.allocation.disk.watermark.low, либо вообще отключить проверку через "cluster.routing.allocation.disk.threshold_enabled" : false.

При том, что на диске свободно 12 гиг из 100, но т.к. ElasticSearch по-умолчанию считает в процентах – ему этого мало.

Т.к. Elasticsearch запускается внутри (аштрисёт!) контейнера с самим SonarQube – ищем, где именно он хранит конфиг:

[simterm]

root@jenkins-production:/opt/jenkins# docker exec -ti jenkins_sonarqube_1 find / -name elasticsearch.yml
find: ‘/proc/tty/driver’: Permission denied
/opt/sonarqube/temp/conf/es/elasticsearch.yml
/opt/sonarqube/elasticsearch/config/elasticsearch.yml

[/simterm]

Ага, вот эти ребята – /opt/sonarqube/elasticsearch/config/elasticsearch.yml.

Sonar запускается из Docker Compose, в который монтируются каталоги:

version: '3.5'

networks:
  sonar:
    external:
      name: jenkins

services:

  sonarqube:
    user: 1004:1004
    image: sonarqube:7.9.1-community
    ports:
      - "9000:9000"
    networks:
      - sonar
    environment:
      - sonar.jdbc.url=jdbc:postgresql://db:5432/sonar
    volumes:
      - /data/sonarqube/conf:/opt/sonarqube/conf
      - /data/sonarqube/logs:/opt/sonarqube/logs
      - /data/sonarqube/temp:/opt/sonarqube/temp
      - /data/sonarqube/data:/opt/sonarqube/data
      - /data/sonarqube/extensions:/opt/sonarqube/extensions
      - /data/sonarqube/bundled_plugins:/opt/sonarqube/lib/bundled-plugins
    logging:
      driver: "journald"
...

Допустимые опции для менеджмента диска (см. Shards):

  • cluster.routing.allocation.disk.threshold_enabled: будет ли Elasticsearch вообще проверять состояние диска
  • cluster.routing.allocation.disk.watermark.low: default 85%, Elasticsearch не будет размещать шарды на этой ноде
  • cluster.routing.allocation.disk.watermark.high: default 90%, Elasticsearch попробует перенести шарды с этой ноды на другие
  • cluster.routing.allocation.disk.watermark.flood_stage: default 95%, запрещает обновление индексов, шарды которых на этой ноде

Создаём на хосте свой конфиг /data/sonarqube/conf/elasticsearch.yml:

cluster.routing.allocation.disk.watermark.flood_stage: 95%
cluster.routing.allocation.disk.watermark.high: 90%

Добавляем маппинг в контейнер SonarQube:

...
    volumes:
      - /data/sonarqube/conf:/opt/sonarqube/conf
      - /data/sonarqube/conf/elasticsearch.yml:/opt/sonarqube/elasticsearch/config/elasticsearch.yml
...

Что бы получить доступ к Elasticsearch – на самом SonarQube надо включить sonar.search.httpPort, см. How to Monitor ElasticSearch.

Включаем коннектор порту 9100:

...
    environment:
      - sonar.jdbc.url=jdbc:postgresql://db:5432/sonar
      - sonar.search.httpPort=9100
...

Перезапускаепм сервис:

[simterm]

root@jenkins-production:/home/admin# systemctl restart sonarqube

[/simterm]

Правда в логах он пишет, что эта опция скоро устареет:

2019.08.29 10:56:15 INFO  app[][o.s.a.es.EsSettings] Elasticsearch listening on /127.0.0.1:9001
2019.08.29 10:56:15 WARN  app[][o.s.a.es.EsSettings] Elasticsearch HTTP connector is enabled on port 9100. MUST NOT BE USED FOR PRODUCTION
2019.08.29 10:55:10 WARN  es[][o.e.d.c.s.Settings] [http.enabled] setting was deprecated in Elasticsearch and will be removed in a future release! See the breaking changes documentation for the next major version.

Проверяем параметры, которые мы задали в файле настроек – подхватил ли их Elasticsearch.

Т.к. Elasticsearch слушает только на localhost внутри конейнера с самим SonarQube (аштрисёт!) – то проверяем curl-ом напрямую из контйнера с SonarQube:

[simterm]

root@jenkins-production:/home/admin# docker exec -ti jenkins_sonarqube_1 curl localhost:9100/_cluster/settings?include_defaults=true | jq '.[].cluster.routing.allocation.disk'
null
null
{
  "threshold_enabled": "true",
  "watermark": {
    "low": "85%",
    "flood_stage": "95%",
    "high": "90%"
  },
  "include_relocations": "true",
  "reroute_interval": "60s"
}

[/simterm]

Применились – можно продолжать билды.

Занятое на ноде место можно проверить так:

[simterm]

root@jenkins-production:/home/admin# docker exec -ti jenkins_sonarqube_1 curl 'http://localhost:9100/_cat/allocation?v&pretty'
shards disk.indices disk.used disk.avail disk.total disk.percent host      ip        node
    24      613.4kb    86.3gb     11.5gb     97.9gb           88 127.0.0.1 127.0.0.1 sonarqube

[/simterm]

Все доступные параметры Elasticsearch – https://nickcanzoneri.com/elasticsearch-settings.

Готово.