[Elasticsearch] 샤드 할당 옵션 및 과정

ehwnghks·2022년 9월 18일
1

elasticsearch

목록 보기
5/9

1. 오류 발견

  1. elasticsearch 3개의 노드로 구성된 시스템에서 logstash 파일 추출 시
    데이터 개수가 맞지 않거나 원하는 결과가 추출되지 않는 상황발생.
  2. 키바나로 현재 클러스터와 인덱스들을 확인하다보니 모든 인덱스의 status 가 yellow로 바뀐것을 확인했다.
  3. 모든 인덱스가 레플리카 샤드없이(unassigned) status가 green으로 변하지 않는 것을 확인하고 원인을 확인하니 노드가 있는 서버의 disk가 85%를 다 넘는 상황이였다.

2. 학습

클러스터의 디스크 기반 샤드 할당 설정

  • cluster.routing.allocation.disk.threshold_enabled: 디스크 공간 고려 여부를 설정합니다. 기본 값은 true
  • cluster.routing.allocation.disk.watermark.low: 디스크 사용량의 하위 임계치를 설정합니다. 설정한 값보다 디스크 용량을 더 많이 사용하고 있는 경우 해당 노드에 샤드를 할당하지 않습니다. 이 설정은 이전에 할당된 적이 없는 새로 생성된 인덱스의 프라이머리 샤드에는 영향을 미치지 않습니다. 기본 값은 85%
  • cluster.routing.allocation.disk.watermark.high: 디스크 사용량의 상위 임계치를 설정합니다. 설정한 값보다 디스크 용량을 더 많이 사용하고 있는 경우 해당 노드에 샤드를 재배치하지 않습니다. 이 설정은 이전에 할당되었는지 여부에 관계없이 모든 샤드가 영향을 미칩니다. 기본 값은 90%
  • cluster.routing.allocation.disk.watermark.flood_stage: 디스크 사용량의 플러드 단계 임계치를 설정합니다. 설정한 값보다 디스크 용량을 더 많이 사용하고 있는 경우 노드의 모든 인덱스에- index.blocks.read_only_allow_delete(삭제가 가능한 읽기 전용)를 적용합니다. 이 설정은 노드의 디스크 공간 부족을 방지하기 위한 최후의 수단입니다. 디스크 사용률이 상위 임계치 아래로 떨어지면 수동으로 해제해야 합니다. 기본 값은 95%
  • cluster.info.update.interval: 클러스터의 각 노드에 대한 디스크 사용량을 확인하는 주기를 설정합니다. 기본 값은 30초
  • cluster.routing.allocation.disk.include_relocations: 디스크 사용량을 계산할 때, 현재 노드로 재배치되고 있는 샤드의 고려 여부를 설정합니다. 기본 값은 true

샤드 할당 과정

어떠한 이유로 unassigned 샤드가 생기면 ShardAllocator가 unassigned 샤드를 클러스터 내 어떤 노드에 할당할지 결정합니다.
아래 같은 상황이 발생하면 ShardAllocator가 동작합니다.

  • 인덱스 생성 시 - 인덱스가 생성되거나 snapshot으로부터 색인을 복구할 때 ShardAllocator는 샤드를 어디에 할당할지 결정합니다.
    사용자가 replica 개수를 늘릴 때에도 동작을 합니다.
  • 노드 장애 시 - 노드 장애로 클러스터에서 노드가 빠지면 ShardAllocator가 동작합니다.실패한 노드에 있었던 샤드들을 어디에 위치시킬지 결정합니다.
    클러스터 노드 개수 변경 시 - 클러스터에 노드를 추가/제거하면 ShardAllocator가 동작합니다.
  • 디스크 high water mark 달성 시 - 디스크 사용량이 high water mark(default 90%)에 도달하면ShardAllocator가 high water mark에 도달한 노드에 존재하는 샤드들을 다른 곳으로 옮기기 위해 동작합니다.
  • 수동 리발란스 - 사용자가 클러스터의 균형을 위해 reroute API를 사용하면 ShardAllocator가 동작을 합니다. https://www.elastic.co/guide/en/elasticsearch/reference/current/cluster-reroute.html
  • 클러스터/인덱스 설정에 따른 이동 - 샤드 이동과 관련된 클러스터 혹은 인덱스의 설정 값이 변경되면 동작합니다.https://www.elastic.co/guide/en/elasticsearch/reference/7.2/allocation-awareness.html, https://www.elastic.co/guide/en/elasticsearch/reference/7.2/allocation-filtering.html

노드선택

노드의 자격 판단은 가중치 함수로 추상화해서 현재 가장 적합하다고 판단된 노드에 샤드 할당이 됩니다.가중치 함수는 어떤 인자를 전달하면 노드의 샤드 가중치를 리턴하는 수학 함수라고 생각하시면 됩니다.샤드 할당에 가장 적합한 노드는 가중치가 가장 적은 노드입니다.

AllocateUnassigned

reroute가 실행되면 가장 먼저 실행되는 연산은 allocateUnassigned 입니다.
인덱스가 생성되면 샤드는(primary, replica 모두) unassinged입니다. 노드가 클러스터에서 떨어지면 해당 노드에 할당된 샤드는 유실됩니다.primary 샤드가 유실됐다면 replica가 primary로 승격되고 replica 샤드는 unassigned 상태로 됩니다.
allocateUnassigned의 BalancedShardAllocator에서 모든 unassigned 샤드를 순회하면서
샤드 할당에 적합한 후보 노드"들"을 찾은 후(Allocation Deciders) 가장 작은 가중치의 노드를 선택합니다.
unassigned 샤드 할당 시 노드 고를 때 Elasticsearch는 순서가 있습니다. primary 샤드를 먼저 선택하는데다른 인덱스 primary 샤드 할당하기 전 하나의 인덱스의 모든 primary 샤드를 할당합니다.
인덱스 선택할 때는 인덱스 명과 index settings의 우선순위 값을 기반으로 비교합니다. (PriorityComparator 참조)이 방법은 Elasticsearch가 많은 인덱스의 샤드가 부분적으로 assigned 상태로 되기보다는 가능한 많은 인덱스의 primary 샤드가assigned로 되게 합니다.Elasticsearch의 모든 primary 샤드가 assigned로 되면, 각 인덱스의 첫 번째 replica 샤드를 할당하고그다음 각 인덱스의 두 번째 replica 샤드를 할당합니다. and so on...

샤드이동

Elasticsearch cluster를 scale down 하는 경우를 생각해보겠습니다.
미국의 블랙 프라이 데이나 중국의 광군제를 대비해 scale out을 했다가 시즌이 끝나면 다시 평소에 트래픽에 맞는 클러스터로 복귀해야 합니다.
이때 여러분은 primary, replica 샤드를 갖고 있는 노드를 내릴 건데 이때 약간의 데이터 유실이 있을 수도 있습니다.
좀 더 좋은 방법은 노드를 바로 삭제하기보다는 exclude filter를 사용하여 모든 샤드가 해당 노드에서 없어지길 기다렸다가 끝났을 때 노드 삭제하는 것입니다.
특정 노드의 디스크가 꽉 차서 샤드 이동으로 저장 공간을 확보해야할할 경우도 있습니다.

allocateUnassigned()가 완료된 직 후에 moveShards()가 실행되어 처리됩니다.
샤드 이동은 클러스터 내에 있는 모든 샤드를 순회하면서 현재 노드에 남아 있을지 말지(can remain) 체크합니다.
이동이 필요하다고 판단되면 적합한 노드 후보군 중에(Allocation Deciders) 가중치가 가장 노드를 선택합니다.
이 노드를 target node라고 부릅니다. 샤드 할당은 현재 노드에서 target node로 이뤄집니다.
moveShards() 연산은 STARTED 상태인 샤드에만 적용되고 다른 상태인 경우 건너뜁니다.
전체 노드에서 균형 있게 샤드를 이동하기 위해 moveShards() 연산은 nodeInterleavedShardIterator를 사용합니다.
이 iterator는 노드에서 너비 우선 순회로 각 노드에서 한 개의 샤드를 고르고, 다음 샤드를 고르는 걸 반복합니다.
그래서 모든 노드의 모든 샤드는 move 관련해서만 평가됩니다. 다른 평가는 하지 않아요.

샤드 리발란스

클러스터가 한계치에 도달했다면 여러분은 scale out을 결정할 겁니다.
Elasticsearch는 더 나은 분산처리를 위해 자동으로 해당 노드를 발견하고 샤드 재할당을 합니다.
노드 추가/삭제 시 항상 샤드 이동이 필요한 건 아닙니다.
※ 노드가 갖고 있는 샤드의 수가 굉장히 적은데 scaleout 대비용으로 노드를 추가한 경우

Elasticsearch는 shard allocator의 가중치 함수를 이용해서 리발란스를 결정합니다.
현재 노드에 할당된 샤드 정보가 주어지면 가중치 함수는 해당 노드의 샤드 가중치 점수를 계산해줍니다.
높은 가중치를 가진 노드는 낮은 가중치를 가진 노드보다 샤드 할당에 적합하지 않은 것입니다.
다른 노드 간에 가중치를 비교해서 Elasticsearch는 분산처리 개선을 위해 리발란스를 할지 말지 결정합니다.
리발란스 결정을 위해서 Elasticsearch는  각 노드의 각 인덱스의 가중치를 계산하고, 해당 인덱스의 최소/최대의 차이를 구합니다.
(Elasticsearch 내에서 인덱스의 각 샤드도 동일하게 계산되기 때문에 index level로 계산을 합니다.)※ 아마 샤드로 하면 연산이 늘어나니 비슷한 느낌의 인덱스 레벨로 계산한다~ 뭐 그런 내용인 듯)
그런 다음 불균형이 심한 인덱스부터 리발란스를 시작합니다.

샤드 이동은 무거운 연산입니다.
실제로 샤드 이동을 하기 전에 이동 하기 전과 후의 가중치를 계산해서 샤드 이동이 클러스터 균형에 더 좋아지는 경우에만 샤드 이동이 이뤄집니다.
결국 리발란스는 최적화 문제입니다.임계값을 넘어서 샤드 이동 비용이 가중치 균형의 이점보다 훨씬 중요합니다. (임계값은 차치하더라도 샤드 이동은 보수적으로 해야 한다는 얘기인 듯)
임계값이 고정 값으로 있고 dynamic 설정으로 값을 변경할 수 있습니다.
cluster.routing.allocation.balance.threshold https://www.elastic.co/guide/en/elasticsearch/reference/current/shards-allocation.html#_shard_balancing_heuristics
인덱스의 delta가 임계값보다 작다면 인덱스는 리발란스를 고려합니다.


  • shard allocation 은 왜 발생 하는가?
    - 특정 shard 의 크기가 커졌을 때...
    - 특정 node 의 인덱스 크기가 커졌을 때...
    - node 가 추가 되었거나 삭제 되었을 때.. (신규 서버 투입, 또는 실행중인 노드가 죽었을 때)
  • shard allocation 을 방지 할 수는 없는가?
    - disable allocation 설정을 통해 할 수 있다.
    이 설정은 재시작 시 allocation 을 방지 하는 것이 아니라 rebalancing을 방지 하는 것.
  • unassigned shard 는 왜 발생 하는가?
    - recovery 과정중 문제가 발생 했을 경우 발생을 합니다.
    - shard rebalance 과정중 문제가 발생 했을 경우 발생을 합니다.
    문제란)
    - node 간 데이터를 옮기는 과정이기 때문에 네트워크 구간에서 발생 할 수 있는 여러가지 문제들이 영향을 줄 수 있습니다.
    - 또는 색인 데이터 recovery 가 실패 하고 깨졌을 때도 발생 합니다.
    해결방법)
    아래 두 가지 방법은 기본적으로 primary shard 가 정상이라는 전제 입니다.
    - 강제 reroute
    - 재시작

3. 원인분석 및 이후과정

위의 내용을 토대로 내가 이해한 오류원인은

  1. 데이터가 계속 쌓이면서 인덱스의 크기가 커지며 cluster.routing.allocation.disk.watermark.low 의 default 값 85%로를 넘어 샤드를 다른 노드로 옮기는 작업이 일어 났을 것이다.
  2. 이러한 과정들로 모든 노드들의 disk가 다 85%를 넘어가며 레플리카 샤드를 만들 공간이 없어서 status가 yellow로 변했을 것이다.(서버 모두 하루에 한번씩 elasticsearch를 재구동했음)
  • 다음과 같은 상황을 해결하고자 쓰지않는 인덱스를 제거하고 데이터의 유효기간을 정해 운영하기로 결정.
  • 협의한 기간의 데이터만 리인덱스 및 삭제 배치 적용.

3대의 노드의 disk 공간을 확보한 후 샤드할당 과정 메모

  1. 가장 disk가 적은 노드 아니면 어떠한 계산으로 한 노드에 모든 primary 샤드를 할당한다.
  2. 그 후에 다시 3개의 노드로 골고루 primary 샤드를 분배를 한다.
  3. 그리고 레플리카 샤드를 생성.

참조

profile
반갑습니다.

0개의 댓글