es集群狀態red排查流程


es集群狀態red

問題描述

公司有一套kibana日志收集系統,組合方式為filebeat+elasticsearch+kibana,elasticsearch使用三台服務器組合成集群。近期公司的zabbix服務器持續告警某台服務器cpu使用率在80%以上,
登錄服務器首先查看是哪個服務器對cpu占用過多,查看是因為es導致。

排查思路

  1. 針對es集群占用cpu使用率過高問題
# 因es集群僅作為kibana日志收集使用,所以使用es-head首先查看集群狀態

  1. 針對es集群red狀態問題
# es集群的幾種狀態
	green:所有主分片和副本都可用
	yellow:所有主分片都可用,但不是所有副本分片都可用
	red:不是所有主分片都可用,這意味着缺少數據:搜索只能返回部分數據,而分配到這個分片上的寫入請求會返回一個異常。
	
# 查看es集群當前狀態(當前集群都在線,沒有問題)
	[root@VM-30-28-centos logs]# curl -s 172.31.30.28:9200/_cat/nodes
	172.31.30.28 63 96 4 0.02 0.16 0.36 dilm - VM-30-28-centos
	172.31.30.88 20 98 9 0.32 0.50 0.56 dilm * VM-30-88-centos
	172.31.30.48 60 97 9 0.91 0.73 0.83 dilm - VM-30-48-centos

疑問:雖然處於red狀態,但是集群狀態沒有問題

# 1.查看系統最大打開文件描述符數是否夠用
[root@VM-30-28-centos logs]# df -i      # 使用都在百分之一左右,絲毫不影響
Filesystem       Inodes  IUsed    IFree IUse% Mounted on
devtmpfs        2030545    346  2030199    1% /dev
tmpfs           2033272      7  2033265    1% /dev/shm
tmpfs           2033272    469  2032803    1% /run
tmpfs           2033272     16  2033256    1% /sys/fs/cgroup
/dev/vda1       3276800  65778  3211022    3% /
tmpfs           2033272      1  2033271    1% /run/user/0
/dev/vdb1      32768000 161045 32606955    1% /opt

查看當前健康狀態,發現未分配分片數居然達到了三千多,並且集群中所有活躍的分片數和主分片數達成了一致,也就是未分配的都是副本分片,主分片處於活躍狀態,
由於災備原則,主分片和其對應副本不能同時在一個節點上,es無法找到其他節點來存放第三個副本的分片,所以導致了集群處於red狀態

但是為什么會出現es無法找到其他節點來存放第三個副本分片呢?

原因如下:

① 副本太多,節點太少,es無法完成分片

​ 解決方式:1. 減少副本數 2. 增加節點數

② 分片被鎖住了

​ 解決方式: 嘗試分配,或者手動分配, 可以指定"accept_data_loss" : true。但這樣會導致數據完全丟失。

③ 有節點短暫離開集群,然后重新加入,並且有線程對某個分片做bulk或者scroll等長時間寫入操作,等節點重新加入集群,由於分片 lock滅有釋放,master無法分配這個分片,
通常/_cluster/reroute?retry_failed=true可以解決問題,如果依然無法解決,可能還有其他原因導致鎖住該shard的線程長時間操作該shard無法釋放鎖(長時間GC?)。 所以有可能是索引過大導致。

# 查看所有索引的狀態,大小等
curl -XGET 'http://172.31.30.28:9200/_cat/indices?v'

這里的截圖並不完整,當時有red狀態的索引和yellow狀態的索引,這里的解決辦法直接將red狀態索引刪除處理

刪除red狀態索引方式,但我這里僅作為日志索引,所以影響不大,刪除需要結合實際情況考慮

curl -XGET 'http://172.31.30.28:9200/_cat/indices?v'|grep 'red' |awk '{print $3}'|xargs -i curl  -XDELETE  "http://172.31.30.88:9200/{}"

后續查看es-head狀態,es集群狀態從red轉為yellow,刪除red索引后個別索引從yellow狀態變為green狀態

總結:

遇到集群Red時,我們可以從如下方法排查 :

  • 集群層面:curl -s 172.31.30.28:9200/_cat/nodes 或者 GET _cluster/health
  • 索引層面:GET _cluster/health?pretty&level=indices
  • 分片層面:GET _cluster/health?pretty&level=shards
  • 恢復情況:GET _recovery?pretty

有unassigned分片的排查思路 :

  • 先診斷:GET _cluster/allocation/explain
  • 重新分配: /_cluster/reroute

實在無法分配:

  • 索引重建:

    ① 新建備份索引:

    curl -XPUT ‘http://xxxx:9200/a_index_copy/‘ -d ‘{
    “settings”:{
    		“index”:{
    				“number_of_shards”:3,
    				“number_of_replicas”:2
    			}
    	}
    }
    

    ② 通過reindex api將a_index數據copy到a_index_copy:

    POST _reindex
    {
    "source": {
    			"index": "a_index"
    			},
    			"dest": {
    			"index": "a_index_copy",
    			"op_type": "create"
    	}
    }
    

    ③ 刪除a_index索引,這個必須要先做,否則別名無法添加

    curl -XDELETE 'http://xxxx:9200/a_index'
    

    ④ 給a_index_copy添加別名a_index

    curl -XPOST 'http://xxxx:9200/_aliases' -d '
    {
    		"actions": [
    			{"add": {"index": "a_index_copy", "alias": "a_index"}}
    	]
    }'
    

    translog總結

    • translog在節點有問題時,能夠幫助阻止數據的丟失

      設計目的:

      1、幫助節點從失敗從快速恢復。

      2、輔助flush。避免在flush過程中數據丟失。

    插播一下,translog的知識

    • 我們把數據寫到磁盤后,還要調用fsync才能把數據刷到磁盤中,如果不這樣做在系統掉電的時候就會導致數據丟失,這個原理相信大家都清楚,elasticsearch為了高可靠性必須把所有的修改持久化到磁盤中。
    • 我們的數據先寫入到buffer里面,在buffer里面的數據時搜索不到的,同時將數據寫入到translog日志文件之中。如果buffer快滿了,或是一段時間之后,就會將buffer數據refresh到一個新的OS cache之中。
    • translog的作用:在執行commit之前,所有的而數據都是停留在buffer或OS cache之中,無論buffer或OS cache都是內存,
      一旦這台機器死了,內存的數據就會丟失,所以需要將數據對應的操作寫入一個專門的日志文件之中。
    • 一旦機器出現宕機,再次重啟的時候,es會主動的讀取translog之中的日志文件數據,恢復到內存buffer和OS cache之中。
      整個commit過程就叫做一個flush操作
    • 其實translog的數據也是先寫入到OS cache之中的,默認每隔5秒之中將數據刷新到硬盤中去,也就是說,
      可能有5秒的數據僅僅停留在buffer或者translog文件的OS cache中,如果此時機器掛了,
      會丟失5秒的數據,但是這樣的性能比較好,我們也可以將每次的操作都必須是直接fsync到磁盤,但是性能會比較差。

附:

查看es狀態

# 附,命令方式查看es:
  curl -uelastic:pwd  -XGET "http://172.31.30.28:9200/_cluster/health?pretty"
	{
  "cluster_name" : "es-for-joyuai-log",				# es集群名稱
  "status" : "green",							   # es集群狀態
  "timed_out" : false,							   # 是否出現超時
  "number_of_nodes" : 3,						   # es節點數
  "number_of_data_nodes" : 3,					    # es數據節點數
  "active_primary_shards" : 1167,					# 集群中所有活躍的主分片數
  "active_shards" : 2334,						   # 集群中所有活躍的分片數
  "relocating_shards" : 0,						    # 當前節點遷往其他節點的分片數量,通常為0,當有節點加入或者退出時該值會增加
  "initializing_shards" : 0,						# 正在初始化的分片
  "unassigned_shards" : 0,							# 未分配的分片數,通常為0,當有節點加入或者退出時該值會增加。
  "delayed_unassigned_shards" : 0,					 # 延遲未分配的分片數
  "number_of_pending_tasks" : 0,					 # 是指主節點創建索引並分配shards等任務,如果該指標數值一直未減小代表集群存在不穩定因素
  "number_of_in_flight_fetch" : 0,						
  "task_max_waiting_in_queue_millis" : 0,
  "active_shards_percent_as_number" : 100.0			 # 集群分片的可用性百分比,如果為0則表示不可用
}

腳本刪除30天前的日志索引

#!/bin/bash
#刪除ELK30天前的日志
DATE=`date -d "30 days ago" +%Y.%m.%d`

curl -s  -XGET http://172.31.30.88:9200/_cat/indices?v| grep $DATE | awk -F '[ ]+' '{print $3}' >/tmp/elk.log
for elk in `cat /tmp/elk.log`
do
        curl  -XDELETE  "http://172.31.30.88:9200/$elk"
done


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM