샤드 배치는 대부분 ElasticSearch가 알아서 해줍니다.
하지만 unassinged 샤드가 발생해서 5회 이상 재할당이 실패한 경우 더 이상 자동으로 할당이 되지 않습니다. 또 다른 상황으로 마이그레이션을 할 때 샤드를 다른 노드로 배치해야 하는 경우도 있습니다. 이런 상황에서 샤드 배치 방식을 수동으로 변경해야 하는데, 그 방법에 대해 알아보겠습니다.
샤드 배치 명령어
샤드를 배치하는 방법은 4가지가 있습니다.
- `reroute`: 샤드 하나를 특정 노드에 배치
- `allocation`: 샤드 배치 방식을 클러스터 전체에 적용
- `rebalance`: 샤드 재분배 방식을 클러스터 전체에 적용
- `filtering`: 특정 조건에 해당하는 샤드들을 특정 노드에 배치
이 중에서 샤드 하나를 특정 노드에 배치하는 `reroute`를 먼저 알아보겠습니다.
reroute: 샤드 하나를 특정 노드로 이동 (사실은 교환)
POST 요청을 보낼 때 JSON에 담겨야 할 기본 내용입니다.
- 특정 인덱스에서(index)
- 특정 샤드를(shard)
- 어느 노드에서(from_node)
- 어느 노드로(to_node)
curl -X POST "localhost:9200/_cluster/reroute?pretty" -H 'Content-Type: application/json' -d'
{
"commandㄴ": [
{
"move": { # 이동 명령
"index": "user", # 인덱스 이름
"shard": 1, # 이동시킬 샤드 번호
"from_node": "es-1.com", # 이동할 샤드의 출발 노드 이름
"to_node": "es-2.com" # 이동할 샤드의 도착 노드 이름
}
}
]
}
'
위의 예시에서 4가지가 JSON 형태로 되어 있는 것을 확인할 수 있는데요, 샤드의 이동이 시작되면 입력한 노드들은 "RELOCATING" 상태가 됨을 응답으로 받습니다.
샤드를 다른 노드로 이동시킬 때 주의해야 할 부분이 있는데요,
위의 예시대로 user 인덱스에서 1번 샤드를 `es-1` 노드에서 `es-2` 노드로 이동시키면 노드마다 균등한 샤드를 배치해야 하기 때문에 자동으로 `es-2` 노드에서 다른 샤드 하나를 `es-1` 노드로 이동시킨다는 것입니다.
즉, 단순히 `es-1` 노드와 `es-2` 노드가 샤드를 교환하는 것으로 이해할 수 있습니다.
참고로 `es-2` 노드에서 교환 대상이 되는 샤드는 디스크 사용량을 기준으로 선정이 됩니다.
샤드 이동 취소
만약 샤드 이동을 취소해야 한다면 아래 명령어를 입력하면 됩니다.
curl -X POST "localhost:9200/_cluster/reroute?pretty -H 'Content-Type: applicaton/json' -d'
{
"commands": [
{
"cancel": { # 취소 명령
"index": "user", # 이동 취소할 인덱스 이름
"shard": 1, # 이동 취소할 샤드 번호
"node": "es-1.com" # 이동 취소할 노드 이름
}
}
]
}
'
배치되지 않은(unassinged) 레플리카 샤드 다시 배치하기
노드들의 디스크 사용량이 높아지면 샤드 배치가 실패하게 됩니다.
샤드 배치에 실패한 샤드는 unassinged 상태로 남아있게 되는데요, 이런 경우 데이터 노드를 늘리거나 기존 인덱스를 삭제해 디스크 공간을 먼저 확보해야 합니다.
샤드 배치 실패의 원인을 잡고 난 다음에 아래 명령어를 입력합니다.
curl -X POST "localhost:9200/_cluster/reroute?pretty" -H 'Content-Type: application/json' -d'
{
"commands": [
{
"allocate_replica": { # 레플리카 샤드 할당 명령
"index": "user", # 배치할 인덱스
"shard": 1, # 배치할 레플리카 샤드 번호
"node": "es-1.com" # 배치할 노드
}
}
]
}
'
만약 특정 노드에 배치하지 않고 한 번에 여러 개의 unassinged 샤드들을 배치하려면 아래 명령어를 입력합니다.
curl -X POST "localhost:9200/_cluster/reroute?retry_failed"
allocation: 클러스터의 전체 샤드 배치를 활성화/비활성화
allocation 명령은 클러스터 내에 배치된 모든 샤드들에 대한 설정을 일괄적으로 할 수 있는 기능입니다.
세부적으로 5가지 옵션을 줄 수 있습니다.
- all: 프라이머리 샤드, 레플리카 샤드 모두 배치 활성화 (기본값)
- null: 기존 allocation 설정을 제거하고 기본값(all)로 변경
- primaries: 프라이머리 샤드만 배치 활성화
- new_primaries: 새로 생성되는 인덱스에 대해 프라이머리 샤드만 배치 활성화
- none: 프라이머리 샤드, 레플리카 샤드 모두 배치 비활성화
만약 노드들의 버전 업그레이드로 인해 Rolling Restart 작업이 필요하다면, 우선 클러스터 내에 샤드 배치를 모두 비활성화해야 합니다.
아래 명령어는 이 작업을 위해 allocation 명령에서 `none`을 사용한 예시입니다.
curl -X POST "localhost:9200/_cluster/settings?pretty" -H 'Content-Type: application/json' -d'
{
"persistent": {
"cluster.routing.allocation.enable": "none" # 모든 샤드 배치 비활성화
}
}
'
모든 노드의 버전 업그레이드를 마치고 다시 기본값(all)로 돌리려면 따옴표를 붙이지 않고 null을 주면 됩니다.
curl -X POST "localhost:9200/_cluster/settings?pretty" -H 'Content-Type: application/json' -d'
{
"persistent": {
"cluster.routing.allocation.enable": null # 기존 allocation 설정 삭제하고 기본값(all) 설정
}
}
'
장애 상황에서 샤드 복구 시 노드 당 복구할 샤드 개수 설정
allocation 명령어 옵션 중 장애 상황에서 노드 당 복구할 샤드의 개수를 설정할 수도 있습니다.
curl -X POST "localhost:9200/_cluster/settings?pretty" -H 'Content-Type: application/json' -d'
{
"persistent": {
"cluster.routing.allocation.node_concurrent_recoveries": 2 # 기본값
}
}
'
rabalance: 클러스터의 샤드들을 고르게 재배치하는 설정
rebalance 명령어는 클러스터 내에 샤드가 재배치되는 방법을 설정할 수 있는 기능입니다.
적용할 수 있는 옵션으로 5가지가 있습니다.
- all: 프라이머리 샤드와 레플리카 샤드 모두 재배치 활성화
- null: 기존 rebalance 설정값을 제거하고 기본값(all)로 변경
- primaries: 프라이머리 샤드만 재배치 활성화
- replicas: 레플리카 샤드만 재배치 활성화
- none: 프라이머리 샤드와 레플리카 샤드 모두 재배치 비활성화
예를 들어, 프라이머리 샤드만 재배치를 활성화하려면 아래 명령어를 입력합니다.
curl -X POST "localhost:9200/_cluster/settings?pretty" -H 'Content-Type: application/json' -d'
{
"persistent": {
"cluster.routing.rebalance.enable": "primaries"
}
}
'
재배치가 발생하는 임계치 관련 설정
재배치는 아무때나 일어나지 않고, 한 대 이상의 노드의 디스크 사용량이 임계값에 도달했을 때 재배치가 동작합니다.
(`cluster.routing.allocation.disk.threshold_enabled: true`가 기본 설정입니다.)
아래 그림처럼 디스크 사용량의 신호등이라고 볼 수 있습니다.
재배치가 발생하는 임계치 기준은 4가지가 있으며, 이 부분도 변경이 가능합니다.
- cluster.routing.allocation.disk.watermark.low: 해당 디스크 사용량을 넘어선 노드에는 샤드 배치 비활성화. 새로 생성된 인덱스만 할당하기 시작. 기본값은 85%
- cluster.routing.allocation.disk.watermark.high: 해당 디스크 사용량을 넘어선 노드를 대상으로 즉시 샤드 재배치 진행. 새로 생성된 인덱스도 적용. 기본값은 90%
- cluster.routing.allocation.disk.watermark.flood_stage: 모든 노드의 디스크 사용량이 해당 값을 넘었을 때 자동으로 인덱스를 read_only로 변경. 기본값은 95%
- cluster.info.update.interval: 임계치에 도달했는지 체크하는 주기. 기본값은 30s
만약 디스크 사용량이 95%가 넘으면 인덱스들이 `read_only`로 변경되어 모든 노드에서 더 이상 인덱싱을 할 수 없는 장애 상황이 됩니다.
ElasticSearch 7.x 버전부터는 디스크를 확보하거나 데이터 노드를 추가해 노드들의 디스크 사용량이 해당 `flood_stage` 값 아래로 내려가면 `read_only` 모드가 해제됩니다.
filtering: 필터링 조건에 해당하는 노드에만 샤드를 배치
마지막으로 알아볼 filtering 명령어는 특정 조건에 해당하는 노드에 샤드들을 배치하는 명령어입니다.
노드의 이름(`_name`), IP(`_ip`), 호스트명(`_host`) 등 세 가지 속성(attribute)을 이용해 필터링할 수 있습니다.
필터링 옵션에는 세 가지가 있으며 적절한 옵션을 선택해 설정을 적용합니다.
- cluster.routing.allocation.include.{노드의 attribute}: 해당 속성이 포함된 노드에만 샤드 할당
- cluster.routing.allocation.require.{노드의 attribute}: 해당 속성이 있는 노드에만 샤드 할당
- cluster.routing.allocation.exclude.{노드의 attribute}: 해당 조건에 맞는 노드는 샤드 할당에서 제외
아래 명령어는 es-1.com, es-2.com 이름의 노드에만 샤드를 할당하는 설정을 적용한 예시입니다.
아래 예시처럼 `,`를 기준으로 속성을 여러 개 입력할 수 있습니다.
curl -X POST "localhost:9200/_cluster/settings?pretty" -H 'Content-Type: application/json' -d'
{
"persistent": {
"cluster.routing.allocation.include._name": "es-1.com, es-2.com" # es-1.com, es-2.com 이름의 노드에만 샤드 할당
}
}
'
만약 exclude 옵션으로 모든 노드에 샤드를 할당하지 않도록하는 명령어는 어떻게 될까요?
ElasticSearch는 클러스터의 안정성을 유지하기 위해 최소한의 룰에 위배되는 명령은 무시합니다. 노드가 2개가 있고, 1개의 노드에만 배치하려고 하면 장애가 발생했을 때 클러스터 전체가 장애 상태가 되므로 노드 2개 모두에 샤드가 배치됩니다.
참고
- 기초부터 다지는 ElasticSearch 운영 노하우
'ElasticSearch' 카테고리의 다른 글
ElasticSearch 클러스터 설정 톺아보기 (0) | 2024.12.30 |
---|---|
ElasticSearch 기본 개념 (0) | 2024.12.29 |
bulk API 수행 시 'Malformed content, found extra data after parsing: START_OBJECT' 에러 해결하는 방법 (1) | 2024.12.26 |