當elasticsearch硬碟滿了


不小心把dev場gRPC的debug log打開了,導致每天產生了差不多800萬條event 把本來就剩不了多少的空間直接塞爆了,碰巧prometheus跟logstash在同一個節點上 prometheus不幸地掛掉了導致連訊息也沒收到 過了兩三天才發覺數據沒了才發現出事

最後要搞了兩天才把數據回復 幸運的是開始時就已經設置了一些機制去防錯 因此這次才沒有發展成為災難性的事件 就寫了以下的一些分享


1. log shipper很重要

在一開始使用ELK stack時也有考慮過經TCP直接由logger經TCP直接傳給logstash/es 但考慮到多個因素如網絡/服務器穩定性等就決定用filebeat filebeat的好處是你直接把日誌打到file裡去,然後再加一個logrotate去設定輪替 這點很重要,不然日誌的檔案只會增不會減,儲存空間會變成另一個問題 然後經filebeat上傳到logstash/es

如果你使用network logging的話 只要logstash/es 報錯,那麼你那段時間的log就真的變沒有了(除非你會重寫,但也因此有更多的東西要兼顧) 而用filebeat的話你還有一段時間可以排錯修復(logrotate 一般就7-10日) 這正正給了我時間去把那些沒有上傳的log 重新上載…

2. non-prod的log最好用curator每日清掉

若非要測試,那麼非production場的數據應該要及早刪掉 不然index數量只會越來越多…

3. match timestamp是很重要的

ES本身的設定是你什麼時侯上傳event給他,他就會預設把該event的時間設定為該時間 可以透過logstash把log裡面的時間覆蓋掉本來的timestamp 這個好處是event在es的timestamp變得更有意義(由上傳時間變為發生時間) 更大的好處是如果你高負載/重新上傳時時間資訊就不會丟失

4. ES本身的硬碟防爆機制

詳細可看這裡https://www.elastic.co/guide/en/elasticsearch/reference/6.x/disk-allocator.html 簡單來說就是ES會把硬碟快滿分別三個階段

cluster.routing.allocation.disk.watermark.low

  • 預設85% 當某個節點超過這個限額後ES會停止分配shards到其之上

cluster.routing.allocation.disk.watermark.high

  • 預設90% 當某個節點超過這個限額後ES會嘗試把該節點的shards分配到其他節點上

cluster.routing.allocation.disk.watermark.flood_stage

  • 預設95% 當某個節點超過這個限額後ES會把該節點的所有index都加一個flag index.blocks.read_only_allow_delete

    意味著那些index變成唯讀,防止硬碟真的爆滿


最後回復數據時卡最久就是index.blocks.read_only_allow_delete這個機制 因為當我把兩個data node的硬碟空間都增加了之後 logstash/filebeat都卡住不動,es也沒有看到有新數據進來 搞了很久才發現這個機制

而要解決也很解單的,只需要更新每個index的設定,把這枝flag設成null就可以了 (當然最好就是逐個index去解鎖)

# reset all the read only flag for all indices
PUT /_all/_settings
{
  "index.blocks.read\_only\_allow_delete": null
}