一個ES設定操作引發的「血案」

2022-06-12 12:00:32

背景說明

ES版本 7.1.4
在ES生產環境中增加欄位,一直提示Setting index.mapper.dynamic was removed after version 6.0.0錯誤。但是我只是加一個欄位而已啊。
詳細錯誤

curl --request PUT --url http://ca.yorkbbs.elasticsearch:9200/object006_bbs_post/_mapping --header 'content-type: application/json' --data '{"properties": {"property_inWeChat": {"type": "long"}}}'

{
	"error": {
		"root_cause": [{
			"type": "illegal_argument_exception",
			"reason": "Setting index.mapper.dynamic was removed after version 6.0.0"
		}],
		"type": "illegal_argument_exception",
		"reason": "Setting index.mapper.dynamic was removed after version 6.0.0"
	},
	"status": 400
}

產生原因

直接先說原因吧
錯誤的設定了index.mapper.dynamic屬生,導致此問題。
你也可以理解為是es的一個bug,在設定時並沒有提醒,可以設定成功,但是設定後修改時,啟動時都會判斷。
甚至ES啟動也會失敗,如果ES被更改錯誤後,再次啟動將會失敗,導致無法啟動。
所以,此錯誤是非常可怕的。
而且此錯誤,在當時不一定能發現,可能過了好久,ES出現異常重啟時,發現啟動不了,這個時候可能連備份都已經沒有了。
我發現這個問題時,還算是比較及時的,在錯誤的設定完index.mapper.dynamic後,第二天偶然間需要在index中增加一個欄位。

詳細過程

在某一天,我同事發現我們現在生產用的index的欄位是自動建立的,在早期的時候都是設定為手動建立的,這樣做是為了防止程式出現錯誤時,導致ES欄位爆炸(比如:原來想寫入一個欄位值,結果把一個物件賦值上去了,結果ES就建立了大量的欄位)。所以,我們都會要求把index的欄位改為手動建立,當賦值錯誤時提示錯誤,或者建立失敗。我以前都是用發HTTP請求來完成了,最近一直在用cerebro,瞭解到裡面可以有一個index setting選項,發現裡面有一個dynamic的設定,就直接改成flase了。這個操作正式引爆了核彈。
第二天需要在index中增加一個欄位。才發現增加不了,增加的API語句也是以前用過N次了,而且在測試環境也可以正常增加,只有生產無法增加。回想了一下最近的操作,想想前一天設定過es的設定。當時本意是想把ES設定為欄位不可能自動增加,只能人工增加。
以前呢,我都是用API指令修改,哪天呢,發現公司設定的cerebro叢集管理工具,有UI的修改介面,覺得有UI,就直接修改吧,於是感覺一定與此有關。
我用的cerebro版本是0.9.4

設定介面

後來分析可能是cerebro工具版本比較早,早期確實是用的index.mapper.dynamic,但是es6.0.0以後就不用了,但是這個工具呢,並沒有修改。設定時仍然設定的是index.mapper.dynamic值,剛好呢,es在設定時也沒有校驗。
這裡覺得ES責任最大,你要不支援,你設定時就提示不支援,不讓設定啊。設定時不判斷,設定成功了,修改時又不讓修改。造成的後果無法修復。
同時,以後慎用第三方工具吧,至少在測試環境先多測試測試。

重新建立了一個新的index,就可以新增成功。

curl --request GET --url http://ca.yorkbbs.elasticsearch:9200/object006_bbs_post

出現錯誤的原因就在這裡,設定的時候沒有提示不能設定,設定後再做變更時,提示資料組態檔錯誤,不允許設定,也無法再修復。
此命令一定要謹慎執行,在6.0.0以上版本執行可能會引發此問題
此命令一定要謹慎執行,在6.0.0以上版本執行可能會引發此問題
此命令一定要謹慎執行,在6.0.0以上版本執行可能會引發此問題

### 此命令一定要謹慎執行,在6.0.0以上版本執行可能會引發此問題
PUT http://127.0.0.1:9200/zpf001/_settings
Content-Type: application/json

{
    "index": {
        "mapper": {
            "dynamic": "true"
        }
    }
}

curl --request PUT --url http://127.0.0.1:9200/zpf001/_settings --header 'content-type: application/json' --data '{"index": {"mapper": {"dynamic": "true"}}}'

嘗試過的解決辦法(都失敗了)

由於分析出來原因是因為index setting中錯誤的設定了dynamic屬性,所以解決辦法就是刪除它(也曾想過改個名字,讓ES不認識它),
通過HTTP請求無法把設定刪除,現在只要是修改setting的,都會有這樣提示,檢視了原始碼,在操作前進行了這個判斷。

嘗試修改名字,也無效。修改名稱後,ES連啟動都啟動不了了。

在上面位置,可以找到dynamic欄位,修改為其他名字,重啟無效。ES直接無法啟動了。這個時候發現,其實在設定了dynamic後,你的ES就無法啟動,因為在啟動時,也有上面的版本判斷。
坑爹不!
至此,已經過去幾天了。仍然沒有解決

最後的解決辦法

嘗試好多辦法都無法解決,那就只能重建ES了,還好我們ES的資料可以從DB恢復。

建議

一定要做好備份,比如快照備份,磁碟備份,資料庫備份等等。並且在任何操作前,都要做好可以回退的措施,你真的不知道下一秒會發生什麼?

正式設定ES欄位為手動建立的HTTP請求

### 設定mapping欄位手工同步,不自動建立 true 動態新增新的欄位—預設 false忽略新的欄位 strict 如果遇到新欄位丟擲異常
PUT {{esHost}}/object006/_mapping
Content-Type: application/json

{
    "dynamic": "strict"
}