點集群部署與排錯實戰(zhàn):從單機到高可用架構(gòu))
Elasticsearch 6.5.4這個版本在很多人眼里已經(jīng)算“老家伙”了但直到今天它仍然活躍在一大堆公司的生產(chǎn)環(huán)境里日志平臺、訂單檢索、商品搜索甚至一些跑了好幾年沒敢動的業(yè)務(wù)系統(tǒng)。前段時間我把內(nèi)網(wǎng)一套ES從單節(jié)點擴成3節(jié)點集群中間踩了不少坑也把常見的報錯挨個處理了一遍。這篇文章就把整個 elasticsearch-6.5.4 集群部署過程完整記錄下來從環(huán)境初始化、配置文件解讀到三節(jié)點聯(lián)調(diào)最后把部署和運行時最常見的錯誤全部貼出來附上報錯現(xiàn)場、原因分析和解決辦法。不管你是剛從單機ES遷移到集群的運維還是第一次在測試環(huán)境搭ES集群的開發(fā)這篇都能直接照著抄。1. 項目概述與集群設(shè)計思路1.1 為什么從單節(jié)點升級到三節(jié)點集群很多人一開始接觸ES都是單節(jié)點跑著玩裝好、啟動、建索引、寫數(shù)據(jù)看起來一切正常??梢坏?shù)據(jù)量上來單節(jié)點的問題就藏不住了JVM堆內(nèi)存漲上去之后GC越來越卡機器宕機數(shù)據(jù)直接不可用想給索引配副本都配不了——因為副本分片不能和主分片放在同一個節(jié)點上這不只是ES的限制而是分布式系統(tǒng)的基礎(chǔ)邏輯。ES集群的核心就是把一個索引拆成多個分片shard散到不同節(jié)點上每個分片還能配副本replica。這樣單點掛了其他節(jié)點上的副本還能繼續(xù)服務(wù)查詢也可以并行打到多個分片吞吐量比單機高出一截。生產(chǎn)環(huán)境里最常見的起步配置就是三節(jié)點原因很簡單三節(jié)點可以同時容忍一個節(jié)點宕機還能正常選出主節(jié)點。兩個節(jié)點看著省錢實際上很容易出現(xiàn)集群腦裂或主節(jié)點選舉僵局維護成本反而高。這次部署的硬件環(huán)境是三臺CentOS 7.6虛擬機配置都是4核16G內(nèi)存、100G數(shù)據(jù)盤。ES版本固定為6.5.4主要考慮是這套環(huán)境和現(xiàn)有的日志采集鏈路已經(jīng)跑通升級大版本會牽扯到數(shù)據(jù)遷移、插件兼容、客戶端版本等一系列改動代價不小。如果是全新項目我會建議直接上更新的版本但存量系統(tǒng)里6.5.4穩(wěn)定跑著別亂動就是最好的方案。1.2 節(jié)點角色和硬件規(guī)劃ES 6.5.4里節(jié)點角色主要通過兩個參數(shù)控制node.master和node.data。簡單理解node.master: true表示這個節(jié)點有資格參與主節(jié)點選舉負(fù)責(zé)集群級別的元數(shù)據(jù)管理、索引創(chuàng)建刪除、分片分配等操作node.data: true表示這個節(jié)點負(fù)責(zé)存儲數(shù)據(jù)、執(zhí)行搜索和寫入請求。規(guī)劃節(jié)點角色時不要想得太復(fù)雜。小集群3到5個節(jié)點最省事的做法是每個節(jié)點都同時承擔(dān) master 候選和 data 角色也就是“混合節(jié)點”。只有當(dāng)集群規(guī)模到了幾十個節(jié)點、主節(jié)點負(fù)載明顯偏高時才需要拆出專門的 master 節(jié)點避免數(shù)據(jù)節(jié)點頻繁執(zhí)行大查詢把主節(jié)點拖垮。這次三臺機器的角色規(guī)劃如下節(jié)點名IP角色內(nèi)存數(shù)據(jù)盤node-1192.168.80.101master候選 data16G100Gnode-2192.168.80.102master候選 data16G100Gnode-3192.168.80.103master候選 data16G100G三節(jié)點全部設(shè)為 master 候選是因為minimum_master_nodes這個防腦裂配置在奇數(shù)節(jié)點下最好算候選節(jié)點數(shù)除以2加1三節(jié)點就是2。如果只有兩個節(jié)點是 master 候選公式是2/212也能運行但一旦其中一個掛了剩下的節(jié)點湊不夠法定票數(shù)整個集群就會停止服務(wù)沒有意義。1.3 大數(shù)據(jù)集群部署的基本策略做集群部署最忌諱的是“裝完再說”。ES集群雖然是軟件層面的事情但真正決定它穩(wěn)不穩(wěn)定的往往是裝之前的規(guī)劃。我的習(xí)慣是先走一遍下面的清單再動手指安裝網(wǎng)絡(luò)規(guī)劃三臺機器內(nèi)網(wǎng)互通防火墻放行9200和9300端口/etc/hosts里寫好三臺機器的解析記錄。這一步?jīng)]做好后面會出現(xiàn)各種詭異的節(jié)點連接失敗。系統(tǒng)參數(shù)JDK版本、vm.max_map_count、文件句柄數(shù)、內(nèi)存鎖定限制這些必須在啟動ES之前調(diào)整完否則會撞上一連串bootstrap check錯誤。目錄規(guī)劃數(shù)據(jù)目錄、日志目錄單獨劃分磁盤不要和系統(tǒng)盤擠在一起。ES的寫入放大效應(yīng)很明顯數(shù)據(jù)盤滿了會直接導(dǎo)致集群只讀。部署順序先單節(jié)點啟動確認(rèn)沒報錯再逐臺加入最后統(tǒng)一驗證集群狀態(tài)。這套思路不光是ES適用搭其他大數(shù)據(jù)組件比如Kafka、HDFS也是同一個套路先設(shè)計再實施啟動失敗時通過日志定位而不是反復(fù)重啟碰運氣。2. 環(huán)境準(zhǔn)備與基礎(chǔ)配置2.1 JDK 1.8 安裝與版本確認(rèn)ES 6.5.4官方要求JDK 1.8及以上這里我直接用的是系統(tǒng)安裝的OpenJDK 1.8。如果不想在服務(wù)器上裝額外的東西發(fā)行包里也帶了自檢邏輯但生產(chǎn)環(huán)境我建議還是手動裝一個明確的JDK版本方便后續(xù)排查問題。# 查看是否已安裝JDK java -version # CentOS 7下用yum安裝OpenJDK 1.8 yum install -y java-1.8.0-openjdk-devel # 確認(rèn)JAVA_HOME echo $JAVA_HOME # 如果沒有輸出在/etc/profile里加一行并source # export JAVA_HOME/usr/lib/jvm/java-1.8.0-openjdk這里有一個容易忽略的坑如果服務(wù)器上同時存在多個JDK版本JAVA_HOME指到了JDK 11甚至更高版本ES 6.5.4在啟動時可能會報版本不兼容或者一些奇怪的類加載錯誤。所以在啟動ES之前先單獨執(zhí)行一次java -version確認(rèn)是1.8再往下走。2.2 系統(tǒng)參數(shù)調(diào)優(yōu)內(nèi)核、文件句柄、內(nèi)存鎖定ES官方文檔里特別強調(diào)的Linux系統(tǒng)參數(shù)有三個少一個都會導(dǎo)致啟動失敗或運行期性能問題。第一個是vm.max_map_count默認(rèn)值是65530ES要求至少262144。這個參數(shù)控制的是進(jìn)程最多能擁有的內(nèi)存映射區(qū)域數(shù)量ES用mmap加載索引段文件數(shù)據(jù)量大以后很容易觸到上限。啟動時如果沒調(diào)錯誤信息長這樣[1] bootstrap checks failed [1]: max virtual memory areas vm.max_map_count [65530] likely too low, increase to at least [262144]解決辦法就是改內(nèi)核參數(shù)并持久化sysctl -w vm.max_map_count262144 echo vm.max_map_count 262144 /etc/sysctl.conf sysctl -p第二個是文件句柄數(shù)。ES進(jìn)程需要打開大量文件每個分片、每個索引段、日志文件都要占用fd默認(rèn)的4096根本不夠。修改方式是在/etc/security/limits.conf里給ES用戶加上限制cat /etc/security/limits.conf EOF esuser soft nofile 65536 esuser hard nofile 65536 esuser soft nproc 4096 esuser hard nproc 4096 esuser soft memlock unlimited esuser hard memlock unlimited EOF第三是內(nèi)存鎖定。如果你打算在elasticsearch.yml里設(shè)置bootstrap.memory_lock: true就必須給用戶配置memlock unlimited否則啟動會報“memory locking requested for elasticsearch process but memory is not locked”。所以limits.conf里那兩行memlock不要漏掉。2.3 創(chuàng)建用戶與目錄規(guī)劃ES出于安全考慮不允許用root直接啟動報錯信息很直接“can not run elasticsearch as root”。所以需要單獨建一個系統(tǒng)用戶。groupadd esgroup useradd -m -s /bin/bash -g esgroup esuser mkdir -p /data/es-data /data/es-logs chown -R esuser:esgroup /data/es-data /data/es-logs數(shù)據(jù)目錄和日志目錄分開放這個細(xì)節(jié)看著不起眼實際很有用。ES運行一段時間后數(shù)據(jù)目錄體積會漲得很快日志如果也寫在里面排錯時想清理日志就很不方便數(shù)據(jù)盤和日志盤混在一起還容易相互影響。下載和安裝直接解壓就行cd /usr/local wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.5.4.tar.gz tar -zxvf elasticsearch-6.5.4.tar.gz mv elasticsearch-6.5.4 /usr/local/elasticsearch chown -R esuser:esgroup /usr/local/elasticsearchES的安裝包是免編譯的解壓就能用這也是它部署起來相對快的原因。但解壓之后一定要記得改屬主否則以esuser用戶啟動時會遇到權(quán)限問題的報錯很容易被誤判成別的問題。3. 集群核心配置詳解3.1 集群名稱、節(jié)點名稱與角色劃分ES的配置文件在/usr/local/elasticsearch/config/elasticsearch.yml。第一個要改的是cluster.name這是集群的“身份證”只有相同cluster.name的節(jié)點才會加入同一個集群。默認(rèn)值是“elasticsearch”生產(chǎn)環(huán)境一定要改成自己的名字否則內(nèi)網(wǎng)里如果有別的ES實例可能發(fā)生節(jié)點串集群的尷尬事故。node.name是節(jié)點在集群里的名字必須唯一。建議和機器名保持一致這樣在監(jiān)控面板里一眼就能看出是哪臺機器出了問題。我在node-1上配置如下cluster.name: es-cluster-prod node.name: node-1 node.master: true node.data: truenode.master和node.data都設(shè)為true在自定義ES的時候要特別注意如果一個節(jié)點node.master和node.data都是false那這個節(jié)點就是個客戶端節(jié)點只轉(zhuǎn)發(fā)請求不存儲數(shù)據(jù)。小集群里一般不需要這樣的節(jié)點白白浪費一臺機器。3.2 網(wǎng)絡(luò)綁定、端口與跨域設(shè)置網(wǎng)絡(luò)配置是初學(xué)者最容易懵的地方。network.host決定ES監(jiān)聽在哪個IP上。默認(rèn)是127.0.0.1也就是只能本機訪問。要讓集群節(jié)點間互相通信必須綁到內(nèi)網(wǎng)IP最簡單的寫法是network.host: 192.168.80.101 http.port: 9200 transport.tcp.port: 9300http.port是供REST API調(diào)用的端口Kibana、head插件、業(yè)務(wù)代碼都走這個端口。transport.tcp.port是節(jié)點間內(nèi)部通信的端口集群的發(fā)現(xiàn)和數(shù)據(jù)復(fù)制都走9300。生產(chǎn)環(huán)境里防火墻一般要同時放行這兩個端口很多人只放9200結(jié)果節(jié)點死活加入不了集群排查到最后才發(fā)現(xiàn)是9300被擋了。還有一個跨域配置如果你打算用elasticsearch-head這個瀏覽器插件來管理集群必須在yml里開啟CORShttp.cors.enabled: true http.cors.allow-origin: *不加這兩行head插件會一直報連接失敗因為瀏覽器的跨域策略直接攔截了請求。這個錯誤我在后面會專門列出來。3.3 節(jié)點發(fā)現(xiàn)與腦裂防護ES 6.5.4用的是ZenDiscovery機制節(jié)點通過discovery.zen.ping.unicast.hosts指定的地址列表來互相發(fā)現(xiàn)。配置方法是把集群里所有節(jié)點的IP和transport端口都寫進(jìn)去discovery.zen.ping.unicast.hosts: - 192.168.80.101:9300 - 192.168.80.102:9300 - 192.168.80.103:9300這里有個細(xì)節(jié)要注意列表里的IP要寫全每個節(jié)點都寫同樣的列表而不是只寫自己。這樣任何一個節(jié)點啟動后都能通過列表里的其他節(jié)點找到整個集群。防腦裂的配置是discovery.zen.minimum_master_nodes這也是6.x版本里最重要的一個參數(shù)。腦裂指的是集群被分成兩個“小集群”各自以為自己是主數(shù)據(jù)寫入互相沖突。防止辦法就是要求選舉主節(jié)點時必須湊夠法定票數(shù)三節(jié)點集群計算公式為3 / 2 1 2discovery.zen.minimum_master_nodes: 2有些人圖省事不配這個參數(shù)默認(rèn)值是1這在三節(jié)點集群里是致命的。一旦網(wǎng)絡(luò)抖動兩個從節(jié)點可能各自都認(rèn)為自己是主節(jié)點整個集群的寫入就亂了。3.4 JVM堆內(nèi)存怎么設(shè)置最合理ES的JVM堆內(nèi)存配置在/usr/local/elasticsearch/config/jvm.options。6.5.4默認(rèn)是1G生產(chǎn)環(huán)境肯定不夠。我的經(jīng)驗是設(shè)置成物理內(nèi)存的一半但最好不要超過30G。-Xms8g -Xmx8g為什么是30G這個數(shù)字因為JVM的CompressedOops壓縮指針技術(shù)只對堆內(nèi)存小于32G的情況有效超過32G后指針會變寬同樣的數(shù)據(jù)占用更多內(nèi)存GC性能反而下降。所以即使機器有128G內(nèi)存ES堆內(nèi)存也建議控制在31G以內(nèi)剩下的內(nèi)存留給操作系統(tǒng)做文件緩存這對ES的讀取性能幫助很大。-Xms和-Xmx要設(shè)成一樣大避免JVM運行中動態(tài)擴容導(dǎo)致GC抖動。還有一個原則是不要隨便改GC策略6.5.4默認(rèn)的GC在絕大多數(shù)場景下已經(jīng)夠用強行換成別的GC調(diào)優(yōu)沒有壓測數(shù)據(jù)支撐基本是給自己挖坑。4. 三節(jié)點集群部署實操全流程4.1 節(jié)點一node-1完整部署所有系統(tǒng)參數(shù)和用戶準(zhǔn)備完后開始配node-1。先編輯elasticsearch.yml把完整配置寫出來cluster.name: es-cluster-prod node.name: node-1 node.master: true node.data: true path.data: /data/es-data path.logs: /data/es-logs bootstrap.memory_lock: true network.host: 192.168.80.101 http.port: 9200 transport.tcp.port: 9300 http.cors.enabled: true http.cors.allow-origin: * discovery.zen.ping.unicast.hosts: - 192.168.80.101:9300 - 192.168.80.102:9300 - 192.168.80.103:9300 discovery.zen.minimum_master_nodes: 2我建議用systemd來管理ES進(jìn)程比bin/elasticsearch -d直接后臺跑更規(guī)范開機自啟和異常重啟都方便。寫一個systemd服務(wù)文件/etc/systemd/system/elasticsearch.service[Unit] DescriptionElasticsearch Afternetwork.target [Service] Typesimple Useresuser Groupesgroup LimitNOFILE65536 LimitNPROC4096 LimitMEMLOCKinfinity ExecStart/usr/local/elasticsearch/bin/elasticsearch Restartalways [Install] WantedBymulti-user.target注意systemd里也要設(shè)置LimitNOFILE和LimitMEMLOCK即使已經(jīng)在limits.conf里配置過了systemd服務(wù)默認(rèn)還是會用自己的一套限制這兩個地方必須同時改。配置完成后重載并啟動服務(wù)systemctl daemon-reload systemctl enable elasticsearch systemctl start elasticsearch啟動后先不要急著操作觀察日志。ES啟動比較慢第一次啟動可能要等十幾秒看日志文件tail -f /data/es-logs/es-cluster-prod.log看到類似下面的輸出說明啟動成功[INFO ][o.e.n.Node] [node-1] initialized [INFO ][o.e.n.Node] [node-1] started [INFO ][o.e.n.Node] [node-1] adding [node-1] to [es-cluster-prod]...然后驗證HTTP接口curl -s http://192.168.80.101:9200/?pretty正常會返回集群名、節(jié)點名和版本號信息。這時候集群里只有node-1一個節(jié)點狀態(tài)是yellow這很正常因為分片的副本還沒地方放。4.2 節(jié)點二、節(jié)點三加入集群node-2和node-3的配置和node-1幾乎一樣只有兩個地方不同node.name改成自己的機器名network.host改成自己的IP。其他配置保持一致尤其是discovery.zen.ping.unicast.hosts列表里要寫三個節(jié)點這一點不能漏。node-2的/etc/systemd/system/elasticsearch.service和node-1相同elasticsearch.yml只需要改兩行node.name: node-2 network.host: 192.168.80.102node-3同理改成node-3和192.168.80.103。我一般會把node-1的整個配置目錄用scp復(fù)制過去再改這兩個字段這樣不容易打錯字scp -r /usr/local/elasticsearch/config esuser192.168.80.102:/usr/local/elasticsearch/復(fù)制完記得改屬主。然后分別啟動node-2和node-3再回到node-1上看集群狀態(tài)curl -s http://192.168.80.101:9200/_cluster/health?pretty如果看到status: green、number_of_nodes: 3、unassigned_shards: 0就說明集群已經(jīng)構(gòu)建成功。我部署時第一次沒看到green而是卡在yellow后來發(fā)現(xiàn)是之前測試留下的索引副本還沒分配完等幾十秒讓ES自動重新分配就好了。如果等了幾分鐘還是黃色就要用下面第5部分的方法排查了。4.3 集群健康檢查與功能驗證集群狀態(tài)green只代表分片分配沒問題業(yè)務(wù)功能還得實際測一下。我習(xí)慣在部署完成后創(chuàng)建一個測試索引寫入幾條數(shù)據(jù)再搜一遍curl -s -XPUT http://192.168.80.101:9200/test-index -H Content-Type: application/json -d { settings: { number_of_shards: 3, number_of_replicas: 1 } }然后寫入一條文檔curl -s -XPUT http://192.168.80.101:9200/test-index/_doc/1 -H Content-Type: application/json -d { title: cluster test, content: this is a test doc }再執(zhí)行搜索curl -s http://192.168.80.101:9200/test-index/_search?qtitle:clusterpretty能看到正常返回結(jié)果說明集群的寫入、分片、副本和查詢鏈路都通了。如果還需要Kibana只需在Kibana的kibana.yml里配好一個節(jié)點的地址比如elasticsearch.hosts: [http://192.168.80.101:9200]Kibana會自動感知集群里的其他節(jié)點。5. 常見錯誤與排查技巧實錄5.1 啟動失敗類錯誤這部分是部署ES時遇到最多的問題幾乎每個新手都會在這里卡一輪。我把最常見的幾個啟動失敗錯誤列出來都是真實報錯信息。錯誤一max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536]這個錯誤在初次部署時出現(xiàn)頻率極高。原因是ES進(jìn)程的文件句柄上限不夠。在limits.conf里配了65536之后重開SSH會話或者重啟服務(wù)才會生效。如果你用的是systemd還要檢查服務(wù)文件里的LimitNOFILE是否也設(shè)置了。# 確認(rèn)當(dāng)前進(jìn)程的limit cat /proc/es_pid/limits | grep open files錯誤二max virtual memory areas vm.max_map_count [65530] likely too low這個在前面已經(jīng)提過直接執(zhí)行sysctl -w vm.max_map_count262144臨時生效再寫進(jìn)/etc/sysctl.conf持久化。有時候你明明執(zhí)行了sysctl命令但ES還是報同樣的錯誤可能是你改了宿主機的參數(shù)但ES跑在容器里或者systemd開啟了不同的命名空間需要確認(rèn)修改作用于ES所在的隔離環(huán)境。錯誤三memory locking requested for elasticsearch process but memory is not locked如果你啟用了bootstrap.memory_lock: true這個錯誤說明鎖定內(nèi)存失敗。檢查limits.conf里的memlock是否為unlimitedsystemd服務(wù)里是否加了LimitMEMLOCKinfinity。如果想要省事可以把bootstrap.memory_lock設(shè)為false但生產(chǎn)環(huán)境建議還是開啟避免ES堆內(nèi)存被交換到磁盤導(dǎo)致性能驟降。錯誤四can not run elasticsearch as rootES出于安全考慮禁止root啟動用之前創(chuàng)建的esuser用戶來啟動就好。檢查當(dāng)前用戶whoami如果是root切換到esusersu - esuser -c /usr/local/elasticsearch/bin/elasticsearch5.2 節(jié)點無法加入集群類錯誤三臺機器都配好啟動后節(jié)點之間能不能正常組集群這是繞不開的一個坎。經(jīng)典報錯是日志里反復(fù)出現(xiàn)[INFO ][o.e.d.z.ZenDiscovery] [node-2] master not discovered yet, waiting for [30s]看到這個別慌這不是立刻失敗是節(jié)點在等主節(jié)點。如果等了很久還是這個日志就要往這幾個方向排查先看discovery.zen.ping.unicast.hosts配置是否完整三臺機器的IP和9300端口都要寫進(jìn)去。再看防火墻是否放行了9300端口# 在node-1上測試到node-2的9300端口是否連通 telnet 192.168.80.102 9300telnet能通說明網(wǎng)絡(luò)沒問題不通就去查防火墻。很多云環(huán)境的安全組規(guī)則也要檢查服務(wù)器本地防火墻可能關(guān)了但安全組把你的9300端口擋在外面了。再看cluster.name是否一致。三個節(jié)點集群名必須一模一樣這玩意不匹配節(jié)點互相看不到對方會一直重復(fù)“waiting for master”的循環(huán)。我在測試環(huán)境里犯過一次這個錯誤node-1寫的是es-cluster-prodnode-2的配置是從別的環(huán)境復(fù)制來的集群名還是es-cluster-test結(jié)果node-2永遠(yuǎn)進(jìn)不了集群日志里也不報明顯的錯誤排查了半小時才發(fā)現(xiàn)是這種低級問題。如果日志里有類似failed to send join request to master重點檢查transport端口和節(jié)點間網(wǎng)絡(luò)。這類問題排查思路跟“點擊一個按鈕沒反應(yīng)時先看頁面報了什么錯”是一樣的不要猜先看節(jié)點日志日志指向哪個方向就順藤摸瓜。5.3 集群運行期錯誤分片未分配、磁盤水位、索引只讀集群啟動成功不代表萬事大吉運行期的問題才是真正考驗排錯能力的地方。分片未分配unassigned shards集群狀態(tài)yellow或者red最直接的表現(xiàn)就是_cluster/health里的unassigned_shards不為0。先看哪些分片沒分配curl -s http://192.168.80.101:9200/_cat/shards?v curl -s http://192.168.80.101:9200/_cluster/allocation/explain?prettyallocation/explain接口會直接告訴你為什么分片分配不了是磁盤空間不足、還是副本數(shù)大于可用節(jié)點數(shù)、還是節(jié)點沒起來。我用這個接口的時候有一次是因為索引副本數(shù)配成了2但集群只有3個節(jié)點主分片占掉一個節(jié)點后兩個副本至少要4個節(jié)點才能放下自然分配不了。把副本數(shù)改成1問題立即解決。如果節(jié)點宕機后重啟分片暫時顯示UNASSIGNED是正常的ES會自動重新分配。但如果等了很久還沒恢復(fù)可以嘗試觸發(fā)一次重新分配curl -s -XPOST http://192.168.80.101:9200/_cluster/reroute?retry_failedtrue這個命令只是重新觸發(fā)分配流程不會幫你解決根本問題最終還是要看explain接口指出的原因。磁盤高水位high disk watermark [90%] exceededES默認(rèn)在磁盤使用率達(dá)到85%時停止分配新分片到90%時會嘗試把分片遷移到其他節(jié)點防止磁盤寫滿。數(shù)據(jù)量大的業(yè)務(wù)索引和分片漲得飛快磁盤說滿就滿。日志里會出現(xiàn)[WARN ][o.e.c.r.a.DiskThresholdMonitor] [node-2] high disk watermark [90%] exceeded on [node-2], all copies of the shards are allocated to other nodes這時的解決辦法不是改配置而是先清理磁盤。刪掉過期索引或者擴磁盤才是正路。臨時降低水位線雖然能讓ES繼續(xù)寫但會帶來很大的數(shù)據(jù)風(fēng)險比如磁盤真的寫滿導(dǎo)致節(jié)點崩潰我一般只在應(yīng)急的時候才用用完之后立刻恢復(fù)默認(rèn)值cluster.routing.allocation.disk.watermark.low: 85% cluster.routing.allocation.disk.watermark.high: 90%索引變成只讀磁盤水位出問題時ES在某些版本里會自動把索引置為只讀來保護數(shù)據(jù)表現(xiàn)就是業(yè)務(wù)方寫入報錯。清理完磁盤后記得手動解除索引的只讀狀態(tài)curl -s -XPUT http://192.168.80.101:9200/your-index/_settings -H Content-Type: application/json -d { index.blocks.read_only_allow_delete: null }5.4 常見錯誤速查表下面這些是我在實際部署和運維里遇到過的錯誤匯總整理成速查表方便大家直接對號入座錯誤現(xiàn)象根本原因快速解決辦法can not run elasticsearch as root用root啟動了ES創(chuàng)建esuser并切換用戶max file descriptors [4096] too low文件句柄限制不夠limits.conf systemd LimitNOFILEvm.max_map_count [65530] too low內(nèi)存映射區(qū)域太少sysctl -w vm.max_map_count262144memory locking not availablememlock未放開limits.conf systemd LimitMEMLOCK bootstrap.memory_lockmaster not discovered yet節(jié)點發(fā)現(xiàn)失敗檢查unicast.hosts、防火墻9300、cluster.namefailed to send join requesttransport通信失敗檢查9300端口連通性node.id重復(fù) / node.name沖突多個節(jié)點配了同一個名字修改node.name保持唯一high disk watermark exceeded磁盤空間接近上限清理磁盤擴容數(shù)據(jù)盤unassigned_shards不為0分片無法分配allocation/explain接口定位原因head插件連不上ES跨域未開啟http.cors.enabled: truesystem call filters failed容器環(huán)境不支持seccomp物理機別管容器里按需調(diào)整bootstrap配置Permission denied目錄屬主不對chown -R esuser:esgroupheap size mismatchXms和Xmx不一致兩個參數(shù)設(shè)置相同值5.5 排查思路像調(diào)試點擊事件一樣定位集群問題很多人遇到ES報錯就慌了到處翻博客、試命令最后問題沒解決反而把集群狀態(tài)搞得更差。我自己的排錯思路非常固定和調(diào)試前端頁面上的一個點擊事件幾乎一樣先看事件有沒有觸發(fā)再順著調(diào)用鏈一層層看哪里斷了。ES的“事件觸發(fā)信息”就是它的日志和健康接口。打開節(jié)點日志看啟動時有沒有ERROR看運行中有沒有WARN打開_cluster/health看status是green、yellow還是red打開_cat/nodes看所有節(jié)點是否都正確加入了集群。這一套下來大部分問題的范圍能縮小到“配置問題、網(wǎng)絡(luò)問題、資源問題”三類。接著就是順著鏈路逐級排查。比如head插件點了連接沒反應(yīng)第一步看瀏覽器開發(fā)工具的網(wǎng)絡(luò)請求請求是否到達(dá)了9200端口如果到達(dá)了看ES返回的是什么狀態(tài)碼如果ES返回CORS相關(guān)的錯誤就去檢查yml里的跨域配置如果請求根本沒到去看Kibana或者其他前端代理是否正常工作。每個節(jié)點上排查都遵循“日志為主、猜測為輔”的原則不要憑感覺改配置每次只改一個參數(shù)改完看日志驗證改錯了就回滾。6. 集群上線后的日常運維建議6.1 每天/每周該看哪些指標(biāo)集群部署完不是終點日常運維才是長期要做的事。我建議每天固定看一次_cluster/health確認(rèn)status是green同時看節(jié)點的CPU、內(nèi)存、磁盤使用率。每周再花幾分鐘看看JVM堆內(nèi)存的使用趨勢、分片數(shù)量是否異常膨脹、查詢的響應(yīng)延遲有沒有明顯上升。# 快速查看集群健康 curl -s http://192.168.80.101:9200/_cluster/health?pretty # 查看節(jié)點狀態(tài) curl -s http://192.168.80.101:9200/_cat/nodes?v # 查看索引大小和分片分布 curl -s http://192.168.80.101:9200/_cat/indices?v如果發(fā)現(xiàn)某個節(jié)點堆內(nèi)存長期維持在85%以上就要考慮擴容或者清理數(shù)據(jù)了。ES集群的容量規(guī)劃要留出余量磁盤用到70%左右就該準(zhǔn)備清理或擴容等到90%報警再處理基本就處于很被動的狀態(tài)了。6.2 數(shù)據(jù)備份與安全創(chuàng)建分片副本只是提供了高可用不是備份。如果業(yè)務(wù)數(shù)據(jù)很重要一定要配置ES的快照功能把索引備份到獨立的存儲上。# 注冊快照倉庫 curl -s -XPUT http://192.168.80.101:9200/_snapshot/my_backup -H Content-Type: application/json -d { type: fs, settings: { location: /data/es-backup } }注意location目錄要提前創(chuàng)建好并且確保ES進(jìn)程有權(quán)限寫入。生產(chǎn)環(huán)境里最好把快照倉庫掛載到獨立的共享存儲或者對象存儲別跟數(shù)據(jù)盤放一起否則整臺機器掛了數(shù)據(jù)盤和備份盤都沒了等于沒備份。6.3 關(guān)于6.5.4版本和未來升級的實話6.5.4這個版本在ES的版本歷史里不算新官方也早已停止了維護。如果你的系統(tǒng)是新建的我建議直接用7.x甚至8.x的版本如果你是存量系統(tǒng)短時間內(nèi)動不了那至少要做到兩點一是不要輕易跨大版本升級ES的升級路徑有嚴(yán)格限制5.x到6.x、6.x到7.x的遷移規(guī)則都不一樣二是所有插件都要嚴(yán)格匹配版本比如IK分詞器有專門的6.5.4版本裝錯版本會導(dǎo)致es啟動后插件加載失敗。我個人的體會是ES集群的坑大多數(shù)集中在部署初期真正跑起來之后反而相對穩(wěn)定。把環(huán)境參數(shù)調(diào)好、把角色規(guī)劃清楚、把常見錯誤準(zhǔn)備好排查套路這套集群就能安安靜靜地為你服務(wù)很長一段時間。