作者:趙凱
Elasticsearch 在 6.7 版本正式加入索引生命週期管理,旨在管理 Elasticsearch 中的索引。
通常我們使用 elasticsearch 的時候,index 命名都是 xxx-YYYY.MM.dd 類似這樣的格式,每天創建一個index,這需要我們自己創建 index,或者通過自動創建。
- 每天創建一個 index,但是每天的數據量又非常少,這對集群來說是不利的。
- 如果是自動創建的話,集群 index 和 shard 數過多,那麼在每天的 00:00 時,大量的 index 同時創建,這時我們就會發現集群的寫入速度會變慢,可能會發生 index 寫入拒絕的情況。
- 集群需要對冷熱數據進行分離,性能好的機器放最近頻繁查詢的數據,隨著時間推移,數據查詢不在頻繁,需要將數據遷移到性能較差的機器上。
以上這些我們可以使用 Elasticsearch 提供的索引生命週期管理功能能很好的解決,接下來我們瞭解一下 索引生命週期管理。
索引生命週期的四個階段
- Hot:
index 正在查詢和更新,一般性能好的機器會設置為 Hot 節點來進行數據的讀寫。
- Warm:
index不再更新,但是仍然需要查詢,節點性能一般可以設置為 Warm 節點。
- Cold:
index不再被更新,且很少被查詢,數據仍然可以搜索,但是能接受較慢的查詢,節點性能較差,但有大量的磁盤空間。
- Delete:
數據不需要了,可以刪除。
節點的類型可以通過一下兩種方式設置,推薦第二種,第一種後續可能會棄用。
第一種:
# elasticsearch.yml
# node.attr.xxx: xxx
node.attr.data: warm
第二種(推薦):
# elasticsearch.yml
# data_content, data_hot, data_warm, data_cold
# 配置該節點既屬於內容層又屬於熱層
node.roles: ["data_hot", "data_content"]
這四個階段按照 Hot,Warm,Cold,Delete 順序執行,上一個階段沒有執行完成是不會執行下一個階段的,對於不存在的階段,會跳過該階段進入到下一個階段。
生命週期默認每 10 分鐘檢測一次,可以通過集群的配置動態修改,如下
PUT _cluster/settings
{
"transient": {
"indices.lifecycle.poll_interval": "10m"
}
}
生命週期管理 API
每個階段支持的行為會在下一章節進行介紹,此章節僅僅為了介紹 API。
- 創建生命週期管理策略
min_age 參數指定從 index 創建後多長時間進入到該階段。
以下示例是指從當 index 創建時間超過 10 天后,進入到 warm 階段,將 segment 數量 merge 為 1,warm 階段完成後,進入 delete 階段,index 創建時間超過 30 天后,將 index 刪除。
PUT _ilm/policy/my_policy
{
"policy": {
"phases": {
"warm": {
"min_age": "10d",
"actions": {
"forcemerge": {
"max_num_segments": 1
}
}
},
"delete": {
"min_age": "30d",
"actions": {
"delete": {}
}
}
}
}
}
- 查看生命週期管理策略
# 查看所有的生命週期管理策略
GET _ilm/policy
# 查看特定的生命週期管理策略
# GET _ilm/policy/<policy_id>
- 刪除生命週期管理策略
DELETE _ilm/policy/<policy_id>
- 觸發生命週期策略中特定步驟的執行
current_step
- phase 當前階段的名稱
- action 當前行為的名稱
- name 當前步驟的名稱
next_step
- phase 想要執行階段的名稱
- action 想要執行行為的名稱
- name 想要執行步驟的名稱
POST _ilm/move/my-index-000001
{
"current_step": {
"phase": "new",
"action": "complete",
"name": "complete"
},
"next_step": {
"phase": "warm",
"action": "forcemerge",
"name": "forcemerge"
}
}
- 移除生命週期管理策略
# POST <target>/_ilm/remove
POST my-index-000001/_ilm/remove
- 生命週期重試
# POST <index>/_ilm/retry
POST my-index-000001/_ilm/retry
- 查看當前索引生命週期管理狀態
GET /_ilm/status
- 查看一個或多個索引的當前生命週期狀態
# GET <target>/_ilm/explain
GET my-index-000001/_ilm/explain
- 啟動索引生命週期管理插件
POST _ilm/start
- 停止索引生命週期管理插件
POST /_ilm/stop
四個階段支持的行為
索引生命週期每個階段支持的行為如下:
-
Hot
- Set Priority
- Unfollow
- Force Merge
- Rollover
-
Warm
- Set Priority
- Unfollow
- Read only
- Allocate
- Shrink
- Force Merge
- Migrate
-
Cold
- Set Priority
- Unfollow
- Allocate
- Migrate
- Freeze
- Searchable Snapshot
-
Delete
- Wait For Snapshot
- Delete
行為
Set Priority
設置索引的優先級,一旦進入到某階段,就設置索引的優先級,節點重新啟動後,優先級較高的索引將會優先恢復。
參數:
- priority: 正整數。
例如:設置 warm 階段 index 的優先級為 50
PUT _ilm/policy/my_policy
{
"policy": {
"phases": {
"warm": {
"actions": {
"set_priority" : {
"priority": 50
}
}
}
}
}
}
Rollover
當 index 滿足三個條件中的任何一個時,會將別名指向新生成的索引。
參數:
- max_age
達到索引創建的最大時間
- max_docs
達到指定的文檔數後
- max_size
index 達到指定的大小時,主分片的大小,不包含副本。
以上三個參數至少應該存在一個
例如:當前 index 主分片大小達到 100GB 或文檔數超過 100000000 或者 index 創建超過 7天 生產新的 index
PUT _ilm/policy/my_policy
{
"policy": {
"phases": {
"hot": {
"actions": {
"rollover" : {
"max_size": "100GB",
"max_docs": 100000000,
"max_age": "7d"
}
}
}
}
}
}
Unfollow
將 follow 索引轉換為正常索引。
例如:
PUT _ilm/policy/my_policy
{
"policy": {
"phases": {
"hot": {
"actions": {
"unfollow" : {}
}
}
}
}
}
Allocate
指定 index 的副本數,遷移 index 到某些節點,冷熱節點數據遷移依賴此步驟。
參數:
- number_of_replicas
指定 index 的副本數
- include
將 index 遷移到具有指定屬性之一的節點
- exclude
將 index 遷移到不包含指定屬性的節點
- require
將 index 遷移到具有所有指定屬性的節點
Note: include 滿足其中一個就可以, require 必須全部滿足。
例如:到達 warm 階段將 index 的備份數設置為 2,並且將 index 遷移至屬性 box_type 包含 hot, warm 且不包含 cold 的節點。
PUT _ilm/policy/my_policy
{
"policy": {
"phases": {
"warm": {
"actions": {
"allocate" : {
"number_of_replicas" : 2,
"include" : {
"box_type": "hot"
},
"exclude" : {
"box_type": "cold"
},
"require" : {
"box_type": "hot,warm"
}
}
}
}
}
}
}
Force Merge
指定 index 合併後 segment 數量,在 hot 階段使用時,必須包含 rollover ,merge 時會將 index 設置為只讀。
參數:
- max_num_segments
segment 最大數量
- index_codec
壓縮文件存儲, default: LZ4
例如:warm 階段將 index 的 segments 合併為 1。
PUT _ilm/policy/my_policy
{
"policy": {
"phases": {
"warm": {
"actions": {
"forcemerge" : {
"max_num_segments": 1
}
}
}
}
}
}
Read only
將 index 設置為只讀。
例如:
PUT _ilm/policy/my_policy
{
"policy": {
"phases": {
"warm": {
"actions": {
"readonly" : { }
}
}
}
}
}
Shrink
index 設置為只讀,然後將 index 縮小為具有更少的的 shard, 縮小後的 index 名稱為 shrink-
參數:
- number_of_shards
合併後的主分片數
例如:warm 階段將 index 的 shard 數合併為 1 個。
PUT _ilm/policy/my_policy
{
"policy": {
"phases": {
"warm": {
"actions": {
"shrink" : {
"number_of_shards": 1
}
}
}
}
}
}
Freeze
最大程度減少 index 的內存佔用。
例如:cold 階段將 index freeze,釋放內存。
PUT _ilm/policy/my_policy
{
"policy": {
"phases": {
"cold": {
"actions": {
"freeze" : { }
}
}
}
}
}
Migrate
通過更新 index.routing.allocation.include._tier_preference 設置,將 index 移動到對應的數據層,如果指定了 allocate,會在遷移前先將副本數減少。如果在熱階段和冷階段沒有指定 allocate 分配選項,ILM 會自動注入遷移操作,如果要禁用可以將 enabled 設置為 false。
參數:
- enabled
default: true, 控制 ILM 在此階段是否自動遷移索引
例如:warm 階段禁用遷移操作, 主動將 index 備份數設置為 1,並且將 index 遷移至屬性 rack_id 為 one 或者 two 的節點。
PUT _ilm/policy/my_policy
{
"policy": {
"phases": {
"warm": {
"actions": {
"migrate" : {
"enabled": false
},
"allocate": {
"number_of_replicas": 1,
"include" : {
"rack_id": "one,two"
}
}
}
}
}
}
}
Searchable Snapshot
生成可搜索快照,在 7.10 版本還處於 beta,在新版可能會有所更改。
在 delete action 步驟中默認會刪除快照,如果需要保留,在 delete action 中將 delete_searchable_snapshot 設置 false
參數:
- snapshot_repository
Required,指定存儲快照的位置
- force_merge_index
Boolean,default: true, 如果索引在先前的操作中已經使用了 force merge, 則可搜索快照操作不會執行強制合併。
例如:在 cold 階段生成快照。
PUT _ilm/policy/my_policy
{
"policy": {
"phases": {
"cold": {
"actions": {
"searchable_snapshot" : {
"snapshot_repository" : "backing_repo"
}
}
}
}
}
}
Wait For Snapshot
等待制定的 SLM 策略執行,然後在刪除索引,為了確保刪除的索引快照是可用的。
參數:
- policy
required, SML 策略的名字
例如:delete 階段等待 SLM 策略執行,然後刪除索引。
PUT _ilm/policy/my_policy
{
"policy": {
"phases": {
"delete": {
"actions": {
"wait_for_snapshot" : {
"policy": "slm-policy-name"
}
}
}
}
}
}
Delete
刪除 index
參數:
- delete_searchable_snapshot
boolean, default: true, 是否刪除 cold 階段創建的 searchable snapshot。
例如:index 創建 90 天后,刪除 index
PUT _ilm/policy/my_policy
{
"policy": {
"phases": {
"delete": {
"min_age" : "90d",
"actions": {
"delete" : { }
}
}
}
}
}
通過 alias 使用 ILM
- 創建生命週期策略
warm 階段將 index 分配給節點屬性 data 為 warm 的節點, cold 階段將 index 分配給節點屬性 data 為 cold 的節點。
節點屬性可以通過 elasticsearch.yml 進行配置或環境變量設置。
# 啟動命令
bin/elasticsearch -Enode.attr.data=warm
# elasticsearch.yml
# node.attr.xxx: xxx
# 建議使用 node.roles 進行配置, 可以參考 通過 data tiers 使用 ILM 這一章節
# node.attr 後續版本可能不在使用
node.attr.data: warm
創建生命週期策略,
在 index 創建 1 天后進入 hot 階段,設置優先級為 100, 當 index 主分片大小超過 50gb 或者 index 文檔數超過 500000000 或者 index 創建超過 2 天生成新的 index
warm 階段將 index 遷移至屬性 data 為 warm 的節點
cold 階段將 index 副本數設置為 1 並將 index 遷移至屬性 data 為 cold 的節點
當 hot ,warm,cold 階段的動作都完成並且 index 創建達到 7 天,刪除 index。
PUT _ilm/policy/logx_policy
{
"policy": {
"phases": {
"hot": {
"min_age": "1d",
"actions": {
"set_priority": {
"priority": 100
},
"rollover": {
"max_age": "2d",
"max_docs": 500000000,
"max_size": "50gb"
}
}
},
"warm": {
"min_age": "1d",
"actions": {
"set_priority": {
"priority": 50
},
"allocate": {
"include": {
"data" : "warm"
}
}
}
},
"cold": {
"min_age": "1d",
"actions": {
"set_priority": {
"priority": 0
},
"allocate": {
"number_of_replicas": 1,
"include" : {
"data": "cold"
}
}
}
},
"delete": {
"min_age": "7d",
"actions": {
"delete": {}
}
}
}
}
}
- 創建索引模板,將生命週期應用到 index
設置 shard 數為 2, 備份數 為 1, 生命週期策略為 logx_policy,滾動別名為 logx
PUT _index_template/logx-template
{
"index_patterns" : ["logx-*"],
"priority" : 1,
"template": {
"settings" : {
"index" : {
"number_of_shards" : "2",
"number_of_replicas" : "1",
"lifecycle.name": "logx_policy",
"lifecycle.rollover_alias": "logx"
}
}
}
}
- 創建第一個 index,以下兩種形式任選一種即可, index 格式必須滿足該正則 ^.-\d+$* , example:logs-000001
PUT logx-000001
{
"aliases": {
"logx": {
"is_write_index": true
}
}
}
# OR 帶創建日期的 index
# PUT /<logx-{now/d}-1> with URI encoding:
PUT /%3Clogx-%7Bnow%2Fd%7D-1%3E
{
"aliases": {
"logx": {
"is_write_index": true
}
}
}
後續的數據讀寫均使用固定別名 logx
通過 Data stream 使用 ILM
- 創建生命週期策略
創建生命週期策略,在 index 創建 1 天后進入 hot 階段,設置優先級為 100, 當 index 主分片大小超過 50gb 或者 index 文檔數超過 500000000 或者 index 創建超過 2 天生成新的 index,warm 階段將 index 遷移至屬性 data 為 warm 的節點,cold 階段將 index 副本數設置為 1 並將 index 遷移至屬性 data 為 cold 的節點,當 hot ,warm,cold 階段的動作都完成並且 index 創建達到 7 天,刪除 index。
PUT _ilm/policy/logx_policy
{
"policy": {
"phases": {
"hot": {
"min_age": "1d",
"actions": {
"set_priority": {
"priority": 100
},
"rollover": {
"max_age": "2d",
"max_docs": 500000000,
"max_size": "50gb"
}
}
},
"warm": {
"min_age": "1d",
"actions": {
"set_priority": {
"priority": 50
},
"allocate": {
"include": {
"data" : "warm"
}
}
}
},
"cold": {
"min_age": "1d",
"actions": {
"set_priority": {
"priority": 0
},
"allocate": {
"number_of_replicas": 1,
"include" : {
"data": "cold"
}
}
}
},
"delete": {
"min_age": "7d",
"actions": {
"delete": {}
}
}
}
}
}
- 創建索引模板,將生命週期應用到 index
與通過 alias 的形式區別: 模板不需要指定 index.rollover_alias,也不需要手動創建第一個index,直接將數據寫入符合模板的 index 即可,至於這個 index 在 Elasticsearch 中對應幾個index,我們無需關注。
PUT _index_template/logx-template
{
"index_patterns" : ["logx-*"],
"priority" : 1,
"data_stream": { },
"template": {
"settings" : {
"index" : {
"number_of_shards" : "2",
"number_of_replicas" : "1",
"lifecycle.name": "logx_policy"
}
}
}
}
- 創建 data stream
POST /logx-business/_doc/
{
"@timestamp":"2021-04-13T11:04:05.000Z",
"message":"Loginattemptfailed"
}
# OR
PUT /_data_stream/logx-business
後續的數據讀寫均使用固定 index: logx-business
通過 Data tiers 使用 ILM
data tiers ( 數據層 )是具有相同數據角色的節點的集合
- Content tier ( 內容層 )節點處理諸如產品目錄之類的內容的索引和查詢負載。
- Hot tier ( 熱層 ) 節點處理諸如日誌或指標之類的時間序列數據的索引負載,並保存你最近,最常訪問的數據。
- Warm tier ( 溫層 )節點保存的時間序列數據訪問頻率較低,並且很少需要更新。
- Cold tier ( 冷層 )節點保存時間序列數據,這些數據偶爾會被訪問,並且通常不會更新。
推薦冷熱分離採用 data tiers 這種方式,節點可以通過如下配置方式配置:
# elasticsearch.yml
# data_content, data_hot, data_warm, data_cold
# 配置該節點既屬於內容層又屬於熱層
node.roles: ["data_hot", "data_content"]
- 創建生命週期策略
warm 階段將 index 遷移至 warm 節點,cold 階段禁用 migrate,將 index 分配給 rack_id 為 one 或 two 的節點。
創建生命週期策略,在 index 創建 1 天后進入 hot 階段,設置優先級為 100, 當 index 主分片大小超過 50gb 或者 index 文檔數超過 500000000 或者 index 創建超過 2 天生成新的 index,warm 階段將 index 遷移至 warm 節點,cold 階段將 index 副本數設置為 1,禁用 migrate, 並將 index 遷移至屬性 data 為 cold 的節點,當 hot ,warm,cold 階段的動作都完成並且 index 創建達到 7 天,刪除 index。
PUT _ilm/policy/logx_policy
{
"policy": {
"phases": {
"hot": {
"min_age": "1d",
"actions": {
"set_priority": {
"priority": 100
},
"rollover": {
"max_age": "2d",
"max_docs": 500000000,
"max_size": "50gb"
}
}
},
"warm": {
"min_age": "1d",
"actions": {
"set_priority": {
"priority": 50
},
"migrate" : {
}
}
},
"cold": {
"min_age": "1d",
"actions": {
"set_priority": {
"priority": 0
},
"allocate": {
"number_of_replicas": 1,
"include" : {
"data": "cold"
}
},
"migrate" : {
"enabled": false
}
}
},
"delete": {
"min_age": "7d",
"actions": {
"delete": {}
}
}
}
}
}
- 創建索引模板,將生命週期應用到 index
設置 shard 數為 2, 備份數 為 1, 生命週期策略為 logx_policy
PUT _index_template/logx-template
{
"index_patterns" : ["logx-*"],
"priority" : 1,
"data_stream": { },
"template": {
"settings" : {
"index" : {
"number_of_shards" : "2",
"number_of_replicas" : "1",
"lifecycle.name": "logx_policy"
}
}
}
}
- 創建 data stream
POST /logx-business/_doc/
{
"@timestamp":"2021-04-13T11:04:05.000Z",
"message":"Loginattemptfailed"
}
# OR
PUT /_data_stream/logx-business
後續的數據讀寫均使用固定 index: logx-business