Disk-based shard allocation 이란?
disk-based shard allocation 이란 elasticsearch 서버 내부의 디스크를 파악하고
효율적인 데이터 분산처리를 위한 자동화 옵션이다.
elasticsearch는 새로운 샤드를 어디에 할당할지 결정하기 전에
disk-based shard allocator 를 통해서 노드의 사용 가능한 디스크 공간을 고려한다.
disk-based shard allocator 의 옵션은 elasticsearch.yml 파일을 통해 수정하고 재시작하거나
cluster-update-setting API를 통해 운영 상태의 클러스터에서도 변경할 수 있다.
기본적으로 disk-based shard allocator 는
1) low watermark
2) high watermark
3) flood stage
세개의 임계값을 기반으로 샤드를 재할당하거나
인덱스 생성을 허용/금지 또는 인덱스 내의 쓰기의 허용/금지 여부를 결정한다.
disk-based shard allocator의 주요 목표는
노드가 사용자가 지정한 워터마크 값을 초과하지 않도록 하거나,
초과가 일시적인 현상인지를 확인하는 것이다.
disk-based shard allocator는
low watermark 임계치를 초과하는 노드에
더 많은 샤드를 할당하는 것을 금지하여
노드가 high watermark 값에
근접해지는 것을 최대한 막으려고 한다.
모든 노드가 low watermark 임계치를 초과한 경우 primary 샤드를 제외한
replica shard 에는 새로운 샤드를 할당할 수 없으며,
Elasticsearch는 디스크 사용량을 high watermark 값 미만으로 유지하기 위해
노드 간에 샤드를 이동할 수 없도록 한다.
그러므로 클러스터에 총 디스크 공간이 충분하고
항상 클러스터 내의 모든 노드가 low watermark 값 아래에 있는지 확인하는 작업이 중요하다.
클러스터 내에 모든 노드가 low watermark 임계치를 초과했고
특정 노드가 high watermark 임계치를 초과하게되면
Elasticsearch는 자동적으로 일부 샤드를 같은 클러스터 내의
다른 노드로 이동하여 이 문제를 해결한다.
disk-based shard allocator에 제어되는 제어규칙은
사용자가 제공하는 서비스에 맞게 유연하게 적용해야 한다.
이러한 규칙이 너무 엄격하면
노드의 디스크 사용량을 제어하는 데 필요한 샤드 이동을 방지할 수도 있다.
노드가 Elasticsearch가 샤드를 다른 곳으로 이동할 수 있는 것보다
빠르게 디스크를 채우면 디스크가 완전히 채워질 위험이 있다.
이렇게 되면 심각한 서비스의 중단이 발생할 수 있으니 주의해야 한다.
위와 같이 클러스터 내의 디스크가 100% 채워지는 노드가 발생하는 것을 방지하기 위해
최후의 수단으로 디스크 사용량이 "lood_stage 임계치에 도달하면
Elasticsearch는 영향을 받는 노드에서 샤드가 있는 인덱스에 대한 쓰기를 차단한다.(읽기는 허용한다.)
또한 같은 클러스터의 내의 다른 노드로 샤드를 계속 이동시킨다.
영향을 받는 노드의 디스크 사용량이 상위 워터마크 아래로 떨어지면
Elasticsearch가 자동으로 쓰기 블록을 제거한다.
Disk-based shard allocation 단계
disk-based shard allocator 가 어떤식으로 작동하는지 테스트를 해보자.
테스트는 아래와 같이 3대의 node를 구성하여 한 클러스터로 묶어놓은 상태이다.
elasticsearch에서 disk-based allocation default setting 은 아래와 같다.
GET /_cluster/settings?include_defaults=true&flat_settings=true
여기서 가장 중요한 3가지의 옵션의 설명은 아래와 같다.
1. cluster.routing.allocation.disk.watermark.low
디스크 사용량에 대한 로우 워터마크를 제어한다. 기본값은 85%,
Elasticsearch가 85% 이상의 디스크를 사용하는 노드에 샤드를 할당하지 않음을 의미한다.
(정확하게는 replica shard 를 할당하지 않음)
비율 값으로 설정할 수 도 있다.
2. cluster.routing.allocation.disk.watermark.high
상위 워터마크를 제어한다.
기본값은 90%, Elasticsearch가 디스크 사용량이 90%를 초과하는 노드에서
샤드를 재배치하려고 시도함을 의미.
해당 옵션도 비율 값으로 설정할 수 있다.
이 설정은 이전에 할당되었는지 여부에 관계없이 모든 샤드의 할당에 영향을 준다.
3. cluster.routing.allocation.disk.watermark.flood_stage
홍수 단계 워터마크를 제어하며 기본값은 95%이다.
index.blocks.read_only_allow_deleteElasticsearch는
노드에 할당된 하나 이상의 샤드가 있고
플러드 단계를 초과하는 디스크가 하나 이상 있는
모든 인덱스에 읽기 전용 인덱스 블록(index block)을 적용한다. (쓰기가 불가능)
이 설정은 노드의 디스크 공간 부족을 방지하기 위한 최후의 수단이다.
디스크 사용률이 상위 워터마크 아래로 떨어지면 인덱스 블록이 자동으로 해제된다.
로우 및 하이 워터마크 값과 유사하게 비율 값, 예를 들어 0.95,
또는 절대 바이트 값으로 설정될 수 있다.
Scenario 1 - cluster 내의 하나의 node 가 low watermark 임계치를 초과한 경우
일단 위의 시나리오 환경을 맞춰주려면 우분투에서
아래의 명령어를 실행하여 강제적으로 디스크 사용률을 높여주면 된다.
node 1에 대한 디스크 사용률을 85 프로 이상으로 올려주자.
아래의 os 환경은 ubuntu에서 진행하였다.
fallocate -l <원하는 용량> <생성할 파일이름>
위 코드를 양식에 맞추어서 명령어를 실행시켜 주면
아래와 같이 node 1의 free disk 가 12% 정도로 현재 low watermark 임계치를 초과한 상태이다.
kibana dev-tool에서 아래와 같은 인덱스를 만들어주자 (예시로 5개 정도 만들어주자)
각 인덱스들은 1개의 primary shard와 2개의 replica shard를 가지게 된다.
PUT /my_index_testing_1
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 2
},
"mappings": {
"properties": {
"name": {
"type": "text"
},
"age": {
"type": "integer"
},
"in_date": {
"type": "date",
"format" : "yyyy-MM-dd HH:mm:ss.SSS"
}
}
}
}
생성한 인덱스 정보에 들어가게 되면 아래와 같이 node 1 에만 primary shard 가 할당 되고
replica shard는 모두 node2 node3에 할당된 것을 볼 수 있다.
다른 테스트 인덱스를 만들어봐도 Node 1 에만 Primary shard 가 만들어질 것이다.
이는 node1 이 low watermark 임계치를 초과함으로써
disk-based shard allocator의 영향으로 node1에서는 replica shard를 생성하지 못하게 막은 것이다.
즉, 현재 클러스터 내의 노드 상태는 아래와 같다고 볼 수 있다.
node 1의 disk 사용률이 85% 미만으로 떨어지게 되면
index를 생성해도 node1에만 primary shard 가 몰리는 것을 방지할 수 있다.
아래와 같이 node1의 디스크 사용률을 낮춰주었다.
그리고 새로운 테스트 인덱스를 생성해 주니 아래와 같은 인덱스의 정보를 얻을 수 있다.
disk-based shard allocator 가 node1의 디스크 사용률을 체크하고
low watermark 임계치 아래로 내려갔다고 판단한 후에
해당 노드에서 이제는 replica shard를 생성할 수 있도록 구성한 것이다.
그래서 새로운 인덱스를 생성하게 되면 아래와 같이
node 3에 primary shard 가 생성되고
나머지 node에 replica shard가 생성되는 것을 볼 수 있다.
Scenario 2 - cluster 내의 모든 node 가 low watermark 임계치를 초과한 경우
아래와 같이 Cluster로 묶여있는
세 개의 노드 전부 disk 사용률이 85프로가 넘어간다고 가정해 보자.
현재 클러스터 상태를 도식화해보면 아래와 같다.
위의 클러스터 상태에서 테스트 인덱스 하나를 생성해 보자.
해당 인덱스는 하나의 primary shard와 두 개의 replica shard를 갖는 인덱스이다.
인덱스를 생성하였는데 health 상태가 yellow로 표시된다.
이유는 shard legend 탭을 보면 알겠지만,
primary shard는 할당되어 있지만, replica shard 가 할당되어 있지 않다.
이럴 경우에 새로운 인덱스를 더 만들게 되면 아래와 같은 클러스터 상태가 된다.
새로 생성된 인덱스에 할당된 a6샤드를 보게 되면
primary shard만 존재하게 되고 replica shard 는 존재하지 않는 모습을 볼 수 있다.
이런 경우에는 특정 node가 존재하는 서버에 장애가 발생한다면
a6 가 아닌 샤드들은 replica 가 다른 노드에 존재하므로 상관이 없지만,
a6와 같이 replica shard가 부재한 샤드의 정보는 잃게 되는 불상사가 초래될 수 있다.
가장 먼저 3대 서버 모두 디스크 사용률을 낮춰서
disk-based shard allocator 가 각 node에 low watermark를 풀도록 하는 것이 우선이다.
하지만, 그럴 여유가 없다면 아래와 같이 cluster 내의
low watermark의 임계치를 높이는 것도 하나의 방법이다.
kibana dev-tool에서 아래와 같은 쿼리를 날려주면
low watermark의 임계치를 높일 수 있다.
아래는 low watermark 임계치를 89.9프로로 올리는 쿼리이다.
PUT _cluster/settings
{
"transient": {
"cluster.routing.allocation.disk.watermark.low" : "89.9%"
}
}
위와 같이 임계치를 변경하게 되면,
replica shard를 생성하지 못한 index 가
다른 노드에 replica node를 생성할 수 있게 된다.
물론 이 방법은 권장되는 방법이 아니고
어떤 식으로든 먼저 디스크 사용량을 확보하는 게 우선이다.
Scenario 3 - cluster 내의 하나의 node 가 high watermark 임계치를 초과한 경우
아래 양식대로 3개의 인덱스를 각각 생성해 준다.
my_index_water_1
my_index_water_2
my_index_water_3
PUT /my_index_water_1
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 1
},
"mappings": {
"properties": {
"name": {
"type": "text"
},
"age": {
"type": "integer"
},
"in_date": {
"type": "date",
"format" : "yyyy-MM-dd HH:mm:ss.SSS"
}
}
}
}
기존 샤드는 그림에 표시하지 않는다고 가정해 보자.
클러스터 내부는 아래와 같이 표시된다.
이번 예제에서는 하나의 index에
primary shard 1개, replica shard 1개로 구성했다.
my_index_water_1 인덱스의 샤드 : a1
my_index_water_2 인덱스의 샤드 : a2
my_index_water_3 인덱스의 샤드 : a3
여기서 node 1의 디스크 사용률을 90프로 이상으로 올려보자.
그럼 자동적으로 disk-based shard allocator는
node1에 high watermark 상태를 부여할 것이다.
그럼 elasticsearch 내의 disk-based shard allocator는
node1에 있는 shard를 resharding 하는 작업을 수행한다.
아래의 그림은 resharding 하는 과정을 나타낸 것이다.
각 인덱스의 shard의 변화를 보면 아래와 같다.
위와 같이 node1의 디스크 용량을 확보하기 위해
샤드들을 다른 노드로 재배치하는 것을 볼 수 있다.
실제 테스트로 확인한 결과 대부분의 node1에 있는 샤드들은
다른 노드로 재배치되었고,
primary : 1 / replica : 2 옵션을 가진 인덱스는 replica를 옮길 수 없으므로
보존되어 있는 모습을 보였다.
node1 이 high watermark 임계치를 초과할 경우에는
low watermark rule 때와 마찬가지로 node1에는
replica shard 가 생성되지 않는다.
그리고 해당 노드의 임계치가 high watermark 값을
초과한 경우에는 더 이상 primary shard 도 생성되지 않는다.
만약에 강제적으로 primary shard를 node의 숫자보다 많게 지정해도
node 1 에는 어떠한 샤드도 추가되지 않는다.
그저 node2, node3에서 primary shard를 나눠서 저장할 뿐이다.
새로운 인덱스를 생성하여,
해당 인덱스의 primary shard를 10개로 구성하는
명령어를 아래와 같이 실행하였다.
PUT /my_index_water_10
{
"settings": {
"number_of_shards": 10,
"number_of_replicas": 0
},
"mappings": {
"properties": {
"name": {
"type": "text"
},
"age": {
"type": "integer"
},
"in_date": {
"type": "date",
"format" : "yyyy-MM-dd HH:mm:ss.SSS"
}
}
}
}
위와 같이 high watermark 임계치를 초과한 node-1
에는 어떤 샤드도 할당되지 않는 모습을 볼 수 있다.
Scenario 4 - cluster 내 모든 node 가 high watermark 임계치를 초과한 경우
node 1, node 2, node 3 세 개의 노드 모두
디스크 사용량이 90% 이상이라고 가정해 보자.
특정 노드가 high watermark 임계치를 초과할 때에는
해당 노드에서는 primary shard , replica shard 모두 만들 수 없으므로
인덱스 생성 자체가 불가능해진다.
하나의 노드만 high watermark 임계치를 초과한 경우에는
다른 노드로 건너가서 인덱스를 생성하면 그만이지만
현재 상태는 모든 노드가 high watermark 상태이기 때문에
그마저도 불가능하다. 즉 "인덱스 생성 불능 상태"에 빠지게 된다.
위와 같이 새로운 인덱스를 생성할 수 없지만
아래와 같이 기존 인덱스에 데이터를 쓰는 데에는 문제가 없다.
POST my_index_water_2/_doc
{
"name" : "인누리",
"age" : 44,
"in_date" : "2016-07-12 18:25:13.002"
}
또한 인덱스 내의 데이터를 읽는 것도 아무런 문제가 되지 않는다.
GET my_index_water_2/_doc/UfuJeIMBokeudZV4L5FW
즉 Cluster 내의 모든 node가 high watermark 임계치를
초과한 경우라면, 새로운 인덱스는 생성이 불가능하고
기존 인덱스에 데이터를 쓰거나 읽는 데에는
전혀 문제없음을 알 수 있다.
Scenario 5 - cluster 내 모든 node 가 high watermark 임계치를 초과하였고 그중 한 노드는 Flood 단계일 경우
cluster 상태를 보면 Flood stage에 놓인 node2 내에는
my_index_water_2 인덱스의 primary shard 가 존재한다.
해당 인덱스에 데이터를 아래와 같이 넣어보면 error 가 발생한다.
POST my_index_water_2/_doc
{
"name" : "인누리",
"age" : 44,
"in_date" : "2016-07-12 18:25:13.002"
}
{
"error" : {
"root_cause" : [
{
"type" : "cluster_block_exception",
"reason" : "index [my_index_water_2] blocked by: [TOO_MANY_REQUESTS/12/disk usage exceeded flood-stage watermark, index has read-only-allow-delete block];"
}
],
"type" : "cluster_block_exception",
"reason" : "index [my_index_water_2] blocked by: [TOO_MANY_REQUESTS/12/disk usage exceeded flood-stage watermark, index has read-only-allow-delete block];"
},
"status" : 429
}
Flood 상태가 되면 해당 노드에 존재하는 인덱스 샤드에
데이터를 쓰려고 했을 경우 해당 명령이 거부된다.
그러므로 해당 인덱스에는 더 이상 데이터가 들어갈 수 없는 상황이 발생한다.
하지만 아래와 같이 데이터를 읽는 것은 문제없다.
GET my_index_water_2/_doc/UfuJeIMBokeudZV4L5FW
node 가 flood stage 단계에 진입했다는 뜻은
현재 서버의 디스크 상태가 매우 심각하다는 의미이기도 하다.
해당 노드의 디스크가 flood 상태라도 데이터의 유실 자체가 문제가 되는 경우라면
flood stage의 임계값을 상향 조정해 줄 수 있다.
하지만 이것도 임시방편일 뿐이다.
결국 디스크가 100프로 차게 되면 서비스의 중단은 물론
서버자체에도 접속하지 못하게 되는 아찔한 상황이 발생하게 된다.
그러므로 disk 상태를 항상 모니터링하는 것이 중요하다.
즉 마지막으로 disk-based shard allocator를
단계별로 정리하면 아래와 같다.
disk-based shard allocator step |
watermark 대상이 되는 노드 | 해당 임계치를 넘었을 경우 동작방식 |
watermark.low | 특정 노드만 대상이 되는 경우 | 해당 node 에는 replica shard 생성 불가 |
watermark.low | 모든 노드가 대상이 되는 경우 | 새로운 인덱스를 생성할 경우에 replica shard 를 생성할 수 없으므로 Cluster 상태가 yellow 로 유지됨 |
watermark.high | 특정 노드만 대상이되는 경우 | 해당 node 에는 primary / replica shard 생성 불가 기존 샤드가 다른 노드로 re-allocation 됨. |
watermark.high | 모든 노드가 대상이 되는 경우 | 새로운 인덱스의 생성 불가 기존 인덱스 내부의 데이터를 읽고 쓰기는 가능 |
watermark.flood_stage | 특정 노드만 대상이되는 경우 | 기존 인덱스라도 해당 인덱스의 primary 샤드가 flood_stage 에 할당되어 있다면, 새로운 데이터를 쓰는것은 금지됨. 데이터를 읽는것은 허용됨 |
'Elasticsearch' 카테고리의 다른 글
[Elasticsearch] 검색성능 비교 (0) | 2023.05.15 |
---|---|
[Elasticsearch] Nori 분석기 적용 (0) | 2023.05.14 |
[Elasticsearch] text, keyword 타입 (0) | 2023.03.02 |
[Elasticsearch] 검색(Search) (0) | 2023.02.28 |
[Elasticsearch] 색인 (Indexing) (0) | 2023.02.27 |