ようへいの日々精進XP

よかろうもん

Elasticsearch のノードで "too many open files" が出てしまったので対処したメモ

f:id:inokara:20140308084423p:plain

このロゴの色が好きです。

経緯

きっかけ

  • 試験運用開始後ヒープサイズ以外のトラブルに見舞われたことがなかった Elasticsearch ノードについにその日が来たのでメモ
  • 「すんません、kibana 落ちてます?」というお問い合わせ
  • 「こちらこそすんません、すぐに調べます」って調べたら...
  • kibana のダッシュボードにはアクセス出来るけど Elasticsearch に繋がっていない模様

エラーログ

以下のようなログが出て Elasticsearch が止まっていた。

[2014-03-07 09:40:09,761][WARN ][netty.channel.socket.nio.AbstractNioSelector] Failed to accept a connection.
java.io.IOException: Too many open files
        at sun.nio.ch.ServerSocketChannelImpl.accept0(Native Method)
        at sun.nio.ch.ServerSocketChannelImpl.accept(ServerSocketChannelImpl.java:165)
        at org.elasticsearch.common.netty.channel.socket.nio.NioServerBoss.process(NioServerBoss.java:100)
        at org.elasticsearch.common.netty.channel.socket.nio.AbstractNioSelector.run(AbstractNioSelector.java:312)
        at org.elasticsearch.common.netty.channel.socket.nio.NioServerBoss.run(NioServerBoss.java:42)
        at org.elasticsearch.common.netty.util.ThreadRenamingRunnable.run(ThreadRenamingRunnable.java:108)
        at org.elasticsearch.common.netty.util.internal.DeadLockProofWorker$1.run(DeadLockProofWorker.java:42)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1146)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:679)

参考


対処

緊急対応

とりあえずは Elasticsearch の再起動で対応。

sudo /etc/init.d/elasticsearch restart

これで一先ず復旧。

ファイルディスクリプタの上限値

ファイルディスクリプタの上限値を確認すると...

cat /proc/${elasticsearch_PID}/limits

以下のようになっている。

Limit                     Soft Limit           Hard Limit           Units
Max cpu time              unlimited            unlimited            seconds
Max file size             unlimited            unlimited            bytes
Max data size             unlimited            unlimited            bytes
Max stack size            8388608              unlimited            bytes
Max core file size        0                    unlimited            bytes
Max resident set          unlimited            unlimited            bytes
Max processes             unlimited            unlimited            processes
Max open files            65535                65535                files
Max locked memory         65536                65536                bytes
Max address space         unlimited            unlimited            bytes
Max file locks            unlimited            unlimited            locks
Max pending signals       16382                16382                signals
Max msgqueue size         819200               819200               bytes
Max nice priority         0                    0
Max realtime priority     0                    0
Max realtime timeout      unlimited            unlimited            us

現状のファイルディスクリプタ数(開いているファイル数)

そして、ヒープ以外の設定はほぼデフォルトの状態で動かしてきた Elasticsearch ノード。現在、プロセスが開いているファイル数を確認すると...。

ls -l /proc/${elasticsearch_PID}/fd/ | wc -l

以下のようになっていた。

64466

ガビーン、ほぼ上限。ちなみに、Elasticsearch で以下のように実行することで同様にファイルディスクプリタの数を確認することが出来る。

curl -s http://${ES_HOST}:9200/_nodes/stats/process?pretty

対応

起動スクリプト/etc/init.d/elasticsearchMAX_OPEN_FILES の指定が出来るので以下のように修正。

--- /home/kawahara/elasticsearch        2014-03-07 10:15:57.172040915 +0900
+++ elasticsearch       2014-03-07 10:16:27.032040421 +0900
@@ -72,7 +72,7 @@
 #ES_JAVA_OPTS=

 # Maximum number of open files
-MAX_OPEN_FILES=65535
+MAX_OPEN_FILES=80000

 # Maximum amount of locked memory
 #MAX_LOCKED_MEMORY=

Elasticsearch で確認

curl http://localhost:9200/_nodes/process?pretty

とりあえず "max_file_descriptors" : 80000 となっていることを確認。

{
  "ok" : true,
  "cluster_name" : "elasticsearch",
  "nodes" : {
    "xxxxxxxxxxxxxxxxxxxxxx" : {
      "name" : "hogehoge",
      "transport_address" : "inet[/xxx.xxx.xxx.xxx:9300]",
      "hostname" : "hostname",
      "version" : "0.90.x",
      "http_address" : "inet[/xxx.xxx.xxx.xxx:9200]",
      "process" : {
        "refresh_interval" : 1000,
        "id" : 20904,
        "max_file_descriptors" : 80000
      }
    }
  }
}

とりあえずの対策(監視)

以下のようなシェルスクリプトを作って Jenkins で監視させることにした。

#!/bin/bash

ES_HOST=xxx.xxx.xxx.xxx
FD_THRESHHOLD=70000
FD_COUNT=`curl -s http://${ES_HOST}:9200/_nodes/stats/process?pretty | /${JENKINS_HOME}/bin/jq '.nodes[] |.process.open_file_descriptors'`

notification(){
  mail -s "Elasticsearch Filedescriptor Limit Alert." xxx@xxx.com
}

if [ ${FD_COUNT} -gt ${FD_THRESHHOLD} ];then
  echo ""
  echo "Filedescriptor is ${FD_COUNT}" | notification
  echo "Filedescriptor is ${FD_COUNT}"
  exit 1
else
  echo ""
  echo "${FD_COUNT}"
  echo "Filedescriptor is normally"
fi

今後の対策とメモ

対策

  • クラスタのノード数を増やして一台のノードで受け持つシャードの数を減らす
  • インデックスあたりのシャードの数を減らす

メモ

  • 初歩的なトラブルだと思うが勉強になった
  • ざっくり計算でインデックス数 x 5(シャード数)= 開いているファイル数 になっていない