728x90

Cluster lever shard allocation

샤드 할당은 initial recovery, replica 할당(증설), 재할당 그리고 노드가 추가/삭제 될때 발생 하는 것에 대한 설정들은 다음과 같습니다. 

  • All
  • Primaries
  • New_primaries
  • None

이 Setting은 노드 재시작시 local Primary shard 복수 시에는 해당하지 않습니다.

Local primaries 란 remote cluster의 primaries가 아닌 것을 말합니다. ( remote cluster)

 

예시) Primary 샤드를 갖고 있는 노드가 재시작하면 재시작된 노드의 primary shard allocation id와 active인 allocation id를 비교해서 같다면 바로 primary로 즉시 복구 합니다. 

cluster.routing.allocation.node_concurrent_incoming_recoveries
cluster.routing.allocation.node_concurrent_outcoming_recoveries

 

동시에 샤드 복구를 허용하는 개수, 두 설정 모두 default가 2

incoming 은 샤드 rebalance 가 아니라면 대부분 replica 샤드이고 outgoing은 샤드 rebalance가 아니라면 대부분 primary 샤드 입니다. 

Cluster.routing.rebalance.enable – 재분배가 가능한 샤드의 종류 (all, primaries, replicas, none) Cluster.routing.allocation.allow_rebalance – 샤드 재분배를 허용하는 경우,
Always
Indices_primaries_active: 모든 primary 샤드가 클러스터에 할당된 경우
Indices_all_active(default): 모든 샤드가 할당된 경우
Cluster.routing.allocation.cluster_concurrent_rebalance : 동시에 재분배할 샤드 갯수

 

 


Shard balancing heuristics

아래 설정 값은 각 샤드를 할당할 노드를 선택할 때 위에 소개한 설정과 함께 사용됩니다. 

3개의  rebalancing setting값에서 (rebalance 문자가 있는 설정값) 허용된

 rebalance 작업이 더 이상 balance.threshold 값보다 높일 수 없다고 판단되면 해당 클러스터는 균형을 이루었다고 판단하고

재분배가 안 일어날 수도 있습니다.

Cluster.routing.allocation.balance.shard

전체 샤드 개수 중 해당 노드에 할당된 샤드 개수의 weight factor

Default는0.45f 값을 높일수록 노드당 갖고 있는 샤드 개수가 비슷해집니다.

Cluster.routing.allocation.balance.index

특정 노드에 할당된 인덱스 당 샤드 개수의 weight factor

Default는0.55f 값을 높일수록 노드당 갖고 있는 인덱스 개수가 비슷해집니다.

Cluster.routing.allocation.balance.threshold

재분배 일어날 최솟값

 

Default1.0f 값을 높일수록 재분배에 덜 민감하게 동작합니다.

노드마다 가중치 계산하고 threshold

 

Balancing algorithm에 의해 재분배를 하려고 해도 forced awareness, allocation filtering에 의해 재분배가 일어나지

않을 수도.

 

 

문제점 : 

 

 

인덱스의 데이터값이 들어올때 primary shard의 할당이 한 노드에 쏠리는 현상을 어떤식으로 방지하거나 혹은 할당된 프라이머리샤드를 재분배를 할 수 있는지.

 

Disk-based shard allocation 

 

노드에 사용 가능한 디스크를 고려해서 샤드를 할당할 수도 있습니다.

Cluster.routing.allocation.disk.watermark.low

샤드 할당 시 고려할 disk low watermark, default 85%

 

) 85%로 설정하면 디스크 사용율이 85%노드에는 샤드 할당을 하지 않습니다.

이 설정은 새로 생기는 인덱스의 primary 샤드엔 적용되지 않습니다.

값을 비율로 할 수도 있고 (ex 85%) 절댓값으로도 (500mb) 할 수 있습니다.

비율로 할 때는 사용량을 의미하고, 절대값으로 할 때는 남는 공간을 의미합니다.

Cluster.routing.allocation.disk.watermark.flood_statge

넘치는 단계로 판단하는 watermark, default 95%

 A  노드의 디스크 사용률이 95%가 넘으면  A노드에 할당된 샤드의 인덱스들은 (한 개의 샤드여도) read-only index block 이 됩니다.

 

인덱싱이 가능한 디스크 공간이 생기면 (수동으로) 수동으로 index block 설정을 수동으로 해제해야 합니다.

read_only, read_only_allow_delete block 설정된 인덱스마다 들어가서 수동으로 해제

3 개의 설정값은 비율과 절댓값을 섞어 쓸 수 없습니다.

(low watermark – 85% / high watermark 500mb를 같이 사용 X)

내부적으로 low < high, high < flood_stage

 

Cluster.info.update.interval 노드의 디스크 사용량 정보 업데이트 간격, default 30

Cluster.routing.allocation.disk.include_relocations
노드의 디스크 사용량을 계산할 때 노드의 재배치 중인 샤드 고려 여부,

default true 재배치 중인 샤드의 크기를 고려한다는 의미는 한 샤드의 재배치가 90% 정도 진행 중일 때
디스크 사용량을 조회하면
이미 재배치가 완료된 것처럼 디스크 사용량이 계산됩니다.

 

https://www.elastic.co/guide/en/elasticsearch/reference/current/modules-cluster.html#shard-allocation-awareness

 

Cluster-level shard allocation and routing settings | Elasticsearch Guide [8.17] | Elastic

You can’t mix the usage of percentage/ratio values and byte values across the cluster.routing.allocation.disk.watermark.low, cluster.routing.allocation.disk.watermark.high, and cluster.routing.allocation.disk.watermark.flood_stage settings. Either all va

www.elastic.co

Shard allocation awareness

 

물리적인 거리를 고려해서 shard 할당할 수 있습니다. ‘rack_id‘zone’ attribute를 이용할 수 있습니다.

https://github.com/elastic/elasticsearch/blob/master/server/src/main/java/org/elasticsearch/cluster/routing/alloc

Attribute 값의 개수만큼 샤드를 복사합니다.

Force awareness

Shard allocation awareness 기능을 이용하여 근거리에 샤드를구성할 수 있습니다.

전 세계에 서비스가 되는데 동일한 데이터 조회가 필요한 경우에 쓰임이 많을것으로 생각됨

Elasticsearch cluster node 들에 primary shard와와 replica shard 할당하는 방법 결정

-물리적 구성 관점에서 장애 요소 최소화해서 할당

Cluster-level shard allocation filtering

특정 노드를 shutdown 시키려고 할 때 해당 기능을 이용하면 좋습니다.

Filtering 할수 있는 attribute는node name, host IP, publish IP , IP(host or public IP), hostname, node id가 있습니다.

 

클러스터 내 특정 노드를 제외 시키기 위한 설정
특정 노드에 문제가 발생해서 신규로 생성되는 인덱스의 샤드가 할당되지 못하도록 함.

 

예시) Node 42_1번의번의 disk 90% 이상 사용 중인 경우

신규 인덱스의 샤드를배치시키게 되면 disk full로 이어질 수 있음.

 

이런 경우 당장 shard rebalancing을 수행하기 어렵고

다른 노드들에 disk usage가 여유가 있을 경우 임시로 제외시키는 설정 가능

 

-> 장애로 이어지기 전에 조치를 취하고 disk 용량을 확보 후 다시 투입

728x90
728x90

추석 연휴 동안 서버 3대중 한대가 죽어서 2대로 테스트 데이터를 받고있었습니다. 

오늘 회사 서버를 살려서 연결 해 보니, 새로 생성된 데이터의 샤드가 제대로 분배가 되지 않는것을 파악했습니다.

 

그 해결책으로 밑에 구문을 보시면 될거같습니다.

 

 

장애 대응으로 한참 샤드 복구와 샤드 할당 작업 등이 수행 중인 바쁜 상황에서 새 인덱스가 생성 될 때를 조심해야 한다. 

엘라스틱서치에 새 샤드가 할당될 때 엘라스틱서치는 해당 노드에 총 몇개의 샤드가 있는지 체크한 뒤 적은 수의 샤드를 들고 있는 노드에 새 샤드를 할당한다. 

 

문제는 장애 복구 작업 중 방금 재시작된 노드는 샤드 복구가 제대로 끝난 상태가 아니라는 것이다. 이 노드는 겉으로 보기에는 적은 샤드를 들고 있는 것으로 판정된다. 이때 새 인덱스가 생성되면 이 인덱스의 모든 샤드를 한 노드가 몰아서 할당받는다. 그렇게 해야 전체적인 샤드 수의 균형이 맞다고 엘라스틱서치가 판단하기 때문이다. 

여기에 데이터까지 들어오면 원래는 수십 대의 노드가 분산해서 색인해야 할 데이터를 한 노드가 전부 받아서 처리하다가 다시 죽는 문제가 발생한다. 

cluster.routing.allocation.balance.shard 설정은 샤드 할당의 균형을 맞추는 경향성을 지정한다. 이 값이 낮을수록 균형을 신경 쓰지 않는다. 기본값은 0.45다. 장애 복구 작업 도중 새 인덱스가 생성될 것으로 예상되면 이 값을 임시로 0으로 낮춘다.

 

# 가중치: 노드마다 샤드 개수 밸런싱 < 인덱스마다 샤드 개수 밸런싱
cluster.routing.allocation.balance.shard: 0
cluster.routing.allocation.balance.index: 1
cluster.routing.allocation.balance.threshold: 1.0

쿼리
PUT _cluster/settings
{
  "transient": {
    "cluster.routing.allocation.balance.shard": 0.0,
    "cluster.routing.allocation.balance.index": 1.0
  }
}

공식 문서 :  https://www.elastic.co/guide/en/elasticsearch/reference/7.2/shards-allocation.html

 

Cluster level shard allocation | Elasticsearch Guide [7.2] | Elastic

Regardless of the result of the balancing algorithm, rebalancing might not be allowed due to forced awareness or allocation filtering.

www.elastic.co

비상 상황 처리가 끝나면 이 값을 다시 원래대로 돌려야한다. 계속 0으로 놓고 운영을 하면 특정 노드에 특정 샤드의 배분이 우선된다. 균형을 고려하지 않고 순서대로 단순하게 샤드를 배정하기 때문에 시간이 지날수록 어떤 노드는 특정한 샤드를 많이 할당받고, 어떤 노드는 샤드를 잘 할당 받지 않는 현상이 심화된다. 

 

당장 큰 문제는 생기지 않겠지만 인덱스당 샤드의 수 대비 노드의 수가 크면 클수록, 인덱스의 수가 많을수록, 인덱스마다 데이터의 성질이 다를수록 쏠림 경항이 심해지며 점점 문제의 소지가 된다.

 

이미 특정 노드에 샤드가 몰린 경우 수동으로 reroute API를 호출해서 다른 노드에 샤드를 옮길 수 있다. 다만 이 reroute 작업이 수행되는 동안은 클러스터 부하가 커지기 때문에 전후 상황을 봐서 수행해야 한다. reroute API 는 다음과 같이 호출한다. commands에  하나 이상의 명령을 지정할 수도 있다. 

POST _cluster/rerout
{
	"commands":[
    {
      "move":{
        "index": "test-index-5",
        "shard" : 0,
        "from_node": "es02",
        "to_node": "es01"
      }
    }
  ]
}

 

직업 REST API를 호출하는 방법 외에도 cerebro 같은 관리 도구를 사용하면 UI상에서 샤드 분포를 눈으로 확인하며 쉽고 편리하게 샤드를 옮길 수 있다.

728x90
728x90

인덱스의 샤드 개수(number_of_shards) 는 한 번 지정하면 reindex 등의 특별한 작업을 수행하지 않는 한 변경할 수 없다.

그런데 샤드 개수를 어떻게 지정하느냐에 따라 엘라스틱서치 클러스터 전체의 성능이 크게 달라진다. 중요한 설정임에도 불구하고 샤드 개수를 정확히 어떤 값으로 지정하면 되는지 딱 정해주는 알기 쉽고 명확한 기준은 알려진 바가 없다. 이 문제는 굉장히 어려운 문제다. 이번 절에서는 샤드 개수를 어떻게 지정할지 그 전략을 알아보도록 하겠습니다. 

 

샤드 크기와 개수 조정

클러스터에 샤드 숫자가 너무 많아지면 클러스터 성능이 눈에 띄게 떨어지게 됩니다. 샤드 하나당 루씬 인덱스가 하나씩 더 뜨며 힙을 차지 한다. 주 샤드를 하나 더 띄울 때마다 복제본 샤드도 늘어나는 것을 고려하면 무작정 number_of_shards를 늘릴 수는 없다. 그렇다고 샤드 숫자를 적게 지정하면 샤드 하나당 크기가 커진다. 

 

샤드 하나의 크기가 너무 커지는것도 심각한 문제이고, 샤드 크기가 지나치게 크면 재기동이나 장애 상황 등에서 샤드 복구, 복제본 샤드 생성에 너무 많은 시간이 소요된다. 이렇게 되면 문제 상황에서 클러스터 안정성이 크게 떨어진다. 장애로 인해 재기동한 노드가 샤드 복구를 하는 과정 자체가 너무 무거워서 복구 도중 다시 죽는 일도 생길 수 있다. 전체 적인 서비스 성능도 쉽게 체감될 정도로 감소한다.

결국 밸런스가 중요합니다.

그렇다면 어떤 기준으로 어떻게 밸런스를 잡아야 할까요?

 

조금 더 중요한 원칙은 샤드 하나의 크기를 일정 기준 이하로 유지해야한다는 것입니다. 

전체 샤드의 수를 체크 하는 것은 그 다음입니다. 

샤드의 크기를 기준 크기 이하로 유지하는 선에서 전체 샤드 개수를 최대한 줄이는 방향으로 접근 해야합니다. 그렇다면 '너무 크다'의 기준은 얼마나 되어야 할까요?? ( 엘라스틱 블로그 참조 : 샤드 당 20GB~ 40GB 크기가 적절하다고 말하고있음), 그러나 실제 운영 경험상으로는 샤드 하나당 크기가 20GB 만 되어도 다양한 상황에서 느리고 무겁다라고 느껴집니다. 

블로그에서 말한 크기의 샤드 또한 버틸 수 있을지 모르지만, 수 GB 내외 수준에서 조정하는 것을 추천드립니다. 

샤드의 크기는 cat shards API 를 이용해서 확인 할 수 있습니다. 

GET _cat/shards?v&s=store:desc

또한 블로그에서 힙 1GB 당 20개 이하의 샤드를 들고있는 것이 적절하다고 설명하고 약 32GB 힙 기준으로 노드당 640 샤드 이하다.

샤드 개수 확인 API

GET _cat/health?v
GET _cat/allocation?v

힙 1GB 당 샤드 20개 기준은 빡빡하기는 하나 이 기준을 지키는 것을 어느 정도 이상적인 목표로 삼으며 밸런스를 조정하면 좋다. 

그러나 이 기준만으로 샤드 개수를 결정할 수는 없다. 샤드 개수 결정에 고려하면 좋은것을 더 알아보도록 하자.

모든 노드가 충분히 일을 하고 있는지...?

ES 의 샤드는 이름 자체가 의미하듯 샤딩, 즉 분산처리를 위해 생긴 개념이다. 

전체 샤드 개수를 줄이는 것만 생각하다 보면 분산처리의 강점을 충분히 살리지 못할 수도 있다. 특정인덱스의 주 샤드와 복제본 샤드가 모든 노드에 고르게 퍼지도록 설정하는 것도 중요한 요소다. 노드 대수가 n대라면 number_of_shards를 n의 배수로 지정해 모든 노드가 작업을 고르게 분산받도록 설정하는 방법 등의 사용된다. 특히 서비스 중요도가 높은 인덱스나 성능을 타이트하게 조정해야 하는 인덱스라면 이 부분을 신경 써야 한다. 

 

서비스상 빈번하게 호출되지 않느 ㄴ인덱스나 크기가 너무 작은 인덱스의 샤드를 모든 노드에 배치 시킬 필요는 없다. 

n의 배수에도 크게 집착하지 않아도 된다. 어차피 추후 선형적 확장을 위해 추가 서버가 투입되면 이 숫자가 달라지게 된다. 또한 한 엘라스틱서치 클러스터에서 활발하게 작업 중이 ㄴ인덱스의 수가 이미 충분히 많다면 단일 인덱스에 대해 모든 노드가 일을 하고 있는지를 과도하게 신경 쓸 필요가 없을 수도 있다. 한 인덱스의 작업에 참혀하지 않는 노드이더라도 다른 인덱스의 작업에 리소스를 사용할 것이기 때문이다. 서비스 중요도와 함께 샤드의 크기, 개수 등의 요소를 함께 적절히 고려한 중용이 필요하다. 

 

미래에 데이터가 커질 것을 고려

지금은 데이터가 초당 n개 씩 들어오지만 한두 달 사이에 초당 10n 개의 데이터가 인입될 수 도 있다. 서비스 요건상 데이터의 성질이 변경되어 새로운 필드가 많이 추가되거나 데이터 크기 자체가 커질 수 있다. 이런 운영상의 이슈로 인해 미래에 커질 수 있는 데이터 사이즈를 어느 정도 고려해서 설정해야 한다. 

 

인덱스 이름에 시간값을 넣어 정기적으로 신규 인덱스를 생성하는 성질의 데이터는 템플릿에 설정된 number_of_shards 값을 봐 가면서 변경하면 이런 문제를 어느 정도 유연하게 대처할 수 있다. 

그러나 단일 인덱스에 서비스 데이터를 담고 있다면 그렇게 하기는 어렵다. 이런 경우라면 미레에 커질 데이터 사이즈를 넉넉히 예상해서 설정해 두는 것이 좋다. 그렇더라도 버틸 수 없는 상태 까지 오면 결국 reindex를 할 수 밖에 없다. reindex를 위해서 미리 alias 를 설정해 두는 것을 잊지 않아야한다. 

 

테스트 수행

앞선 요소들은 단순하게 일률적으로 적용될 만한 것은 아미녀 서비스 환경마다 상황이 다르다. 즉 엘라스틱 블로그에 실힌 힙 1gb당 샤드 2-개라는 가이드 또한 데이터 특성을 전혀 고려하지 않는 숫자입니다. 실제로는 인덱스에 어떤 성격의 데이터가 얼마나 있는지에 따라 양상이 매우 다릅니다. 여러 통제된 조건에서 테스트를 해 보고 결정하는 것이 좋습니다. 

특히 성능에 민감한 인덱스라면 테스트가 더더욱 중요합니다. 

가능하다면 실제 서비스 조건과 유사한 조건으로 테스트를 수행해 보고 그 결과를 참고해 개수를 지정하도록 하자.

물론 문제를 많이 일으키는 인덱스는 데이터 양과 특성이 자주 바뀌는 인덱스인 경우가 많다. 

다양한 요소를 잘 고려해서 종합적으로 결정해야 합니다. 

 

728x90

+ Recent posts