실패 허용도를 높이기 위해 분산(spread) 사용하기
실패 허용도를 높이기 위해 분산(spread) 사용하기 (Use spread to increase failure tolerance)
Nomad 스케줄러는 노드에 작업을 배치할 때 리소스 사용률과 애플리케이션 밀도를 최적화하기 위해 빈 패킹(bin-packing) 알고리즘을 사용해요. 빈 패킹은 최적의 리소스 사용률을 보장하지만, 특정 작업의 할당 대부분을 일부 노드가 감당하게 만들 수 있어요. 이는 단일 노드나 단일 데이터센터의 장애가 애플리케이션 비가용성으로 이어질 수 있는 연쇄 장애를 일으킬 수 있어요.
spread 스탠자는 운영자가 속성 및/또는 클라이언트 메타데이터에 기반해 워크로드를 사용자 지정 방식으로 분산할 수 있게 해 이 문제를 해결해요. 작업 명세에서 spread 기준을 사용함으로써 Nomad 작업 운영자는 데이터센터나 랙 같은 도메인에 걸친 장애가 애플리케이션 가용성에 영향을 주지 않도록 보장할 수 있어요.
리전 내의 여러 데이터센터에 배포해야 하는 Nomad 애플리케이션을 생각해 보세요. 데이터센터 dc1에는 노드 4개가 있고 dc2에는 노드 1개가 있어요. 이 애플리케이션은 인스턴스 10개를 가지며, 사용자 트래픽을 더 많이 받아 요청을 처리할 충분한 실행 인스턴스가 없어 다운타임이 발생하지 않도록 해야 하므로 그중 7개를 dc1에 배포해야 해요. 나머지 3개 할당은 dc2에 배포할 수 있어요.
Nomad 작업 명세에서 spread 스탠자를 사용해 워크로드의 70%가 데이터센터 dc1에, 30%가 dc2에 배치되도록 해요. Nomad 운영자는 target과 함께 percent 옵션을 사용해 분산을 사용자 지정할 수 있어요.
출처: 문서
본문
전제 조건 (Prerequisites)
이 가이드에 설명된 작업을 수행하려면 Consul이 설치된 Nomad 환경이 필요해요. 이 저장소를 사용해 샌드박스 환경을 프로비저닝할 수 있어요. 이 가이드는 서버 노드 1개와 클라이언트 노드 5개가 있는 클러스터를 가정해요.
Tip: 이 가이드는 데모 목적이며 단일 서버 노드만 사용해요. 프로덕션 클러스터에서는 서버 노드 3개 또는 5개를 권장해요.
클라이언트 노드 중 하나를 다른 데이터센터에 배치하기 (Place one of the client nodes in a different datacenter)
이 가이드에서 노드가 위치한 데이터센터 사이의 작업 배치에 대한 분산을 사용자 지정할 거예요. 클라이언트 노드 중 하나를 선택하고 /etc/nomad.d/nomad.hcl을 편집해 그 위치를 dc2로 변경해요. 필요한 변경이 포함된 예제 구성 파일의 스니펫은 아래와 같아요.
data_dir = "/opt/nomad/data"
bind_addr = "0.0.0.0"
datacenter = "dc2"
# Enable the client
client {
enabled = true
# ...
}
선택한 클라이언트 노드에서 변경 후 Nomad 서비스를 재시작해요.
$ sudo systemctl restart nomad
모든 것이 올바르게 구성되었다면 nomad node status 명령을 실행하고 노드 중 하나가 이제 데이터센터 dc2에 있는지 확인할 수 있어야 해요.
$ nomad node status
ID DC Name Class Drain Eligibility Status
5d16d949 dc2 ip-172-31-62-240 <none> false eligible ready
7b381152 dc1 ip-172-31-59-115 <none> false eligible ready
10cc48cc dc1 ip-172-31-58-46 <none> false eligible ready
93f1e628 dc1 ip-172-31-58-113 <none> false eligible ready
12894b80 dc1 ip-172-31-62-90 <none> false eligible ready
spread 스탠자가 있는 작업 만들기 (Create a job with the spread stanza)
redis.nomad.hcl이라는 이름의 파일을 만들고 다음 내용을 넣어요:
job "redis" {
datacenters = ["dc1", "dc2"]
type = "service"
spread {
attribute = "${node.datacenter}"
weight = 100
target "dc1" {
percent = 70
}
target "dc2" {
percent = 30
}
}
group "cache1" {
count = 10
network {
port "db" {
to = 6379
}
}
task "redis" {
driver = "docker"
config {
image = "redis:latest"
ports = ["db"]
}
service {
name = "redis-cache"
port = "db"
check {
name = "alive"
type = "tcp"
interval = "10s"
timeout = "2s"
}
}
}
}
}
작업이 spread 스탠자를 지정하고 datacenter 속성을 지정하면서 percent 옵션으로 dc1과 dc2를 대상으로 한다는 점에 유의하세요. 이는 Nomad 스케줄러가 워크로드의 70%를 dc1에, 30%를 dc2에 분산하려 시도하도록 알려줘요.
redis.nomad.hcl 작업 등록하기 (Register the redis.nomad.hcl job)
다음 명령으로 Nomad 작업을 실행해요:
$ nomad run redis.nomad.hcl
==> Monitoring evaluation "c3dc5ebd"
Evaluation triggered by job "redis"
Allocation "7a374183" created: node "5d16d949", group "cache1"
Allocation "f4361df1" created: node "7b381152", group "cache1"
Allocation "f7af42dc" created: node "5d16d949", group "cache1"
Allocation "0638edf2" created: node "10cc48cc", group "cache1"
Allocation "49bc6038" created: node "12894b80", group "cache1"
Allocation "c7e5679a" created: node "5d16d949", group "cache1"
Allocation "cf91bf65" created: node "7b381152", group "cache1"
Allocation "d16b606c" created: node "12894b80", group "cache1"
Allocation "27866df0" created: node "93f1e628", group "cache1"
Allocation "8531a6fc" created: node "7b381152", group "cache1"
Evaluation status changed: "pending" -> "complete"
10개 할당 중 3개가 노드 5d16d949에 배치된 것을 주목하세요. 이것은 데이터센터 dc2에 있도록 구성된 노드예요. Nomad 스케줄러는 spread 스탠자에 지정된 대로 워크로드의 30%를 dc2에 분산했어요.
Nomad 스케줄러는 배치를 할 때 노드의 전체 점수에 다른 구성 요소도 반영하므로, constraint처럼 spread 스탠자가 분산 선호도를 엄격하게 구현할 것이라고 기대하지 말아야 한다는 점을 명심하세요. 이제 다음 몇 단계에서 점수화를 자세히 살펴볼 거예요.
작업 상태 확인하기 (Check the status of the job)
작업 상태를 확인하고 할당이 어디에 배치되었는지 검증해요. 다음 명령을 실행해요:
$ nomad status redis
출력의 Summary 섹션에 실행 중인 작업 인스턴스 10개가 나열되어야 해요:
...
Summary
Task Group Queued Starting Running Failed Complete Lost
cache1 0 0 10 0 0 0
Allocations
ID Node ID Task Group Version Desired Status Created Modified
0638edf2 10cc48cc cache1 0 run running 2m20s ago 2m ago
27866df0 93f1e628 cache1 0 run running 2m20s ago 1m57s ago
49bc6038 12894b80 cache1 0 run running 2m20s ago 1m58s ago
7a374183 5d16d949 cache1 0 run running 2m20s ago 2m1s ago
8531a6fc 7b381152 cache1 0 run running 2m20s ago 2m2s ago
c7e5679a 5d16d949 cache1 0 run running 2m20s ago 1m55s ago
cf91bf65 7b381152 cache1 0 run running 2m20s ago 1m57s ago
d16b606c 12894b80 cache1 0 run running 2m20s ago 2m1s ago
f4361df1 7b381152 cache1 0 run running 2m20s ago 2m3s ago
f7af42dc 5d16d949 cache1 0 run running 2m20s ago 1m54s ago
이 출력을 nomad node status 명령의 결과와 교차 확인해 워크로드의 30%가 dc2의 노드(이 경우 노드 5d16d949)에 배치되었는지 검증할 수 있어요.
작업 배치에 대한 상세 점수화 정보 얻기 (Obtain detailed scoring information on job placement)
Nomad 스케줄러는 리소스가 사용 가능하더라도 spread 스탠자에 지정한 방식으로 항상 워크로드를 분산하지는 않아요. spread 점수화가 스케줄링 결정을 내리기 전에 다른 메트릭과도 함께 반영되기 때문이에요. 이 단계에서 그러한 다른 요소 중 일부를 살펴볼 거예요.
이전 단계의 출력을 사용해 노드에 배치된 할당을 하나 고르고, nomad alloc status 명령을 verbose 옵션과 함께 사용해 상세 점수화 정보를 얻어요. 이 예제에서 가이드는 할당 ID 0638edf2를 참조해요 — 할당 ID는 다를 거예요.
$ nomad alloc status -verbose 0638edf2
결과 출력은 맨 아래에 Placement Metrics 섹션을 보여줘요.
...
Placement Metrics
Node node-affinity allocation-spread binpack job-anti-affinity node-reschedule-penalty final score
10cc48cc-2913-af54-74d5-d7559f373ff2 0 0.429 0.33 0 0 0.379
93f1e628-e509-b1ab-05b7-0944056f781d 0 0.429 0.515 -0.2 0 0.248
12894b80-4943-4d5c-5716-c626c6b99be3 0 0.429 0.515 -0.2 0 0.248
7b381152-3802-258b-4155-6d7dfb344dd4 0 0.429 0.515 -0.2 0 0.248
5d16d949-85aa-3fd3-b5f4-51094cbeb77a 0 0.333 0.515 -0.2 0 0.216
allocation-spread, binpack, job-anti-affinity, node-reschedule-penalty, node-affinity 열의 결과가 결합되어 각 노드에 대한 final score 열의 숫자가 나온다는 점에 주목하세요. Nomad 스케줄러는 각 노드의 최종 점수를 사용해 배치 위치를 결정해요.
다음 단계 (Next steps)
spread 스탠자에서 target의 percent 옵션 값을 변경하고 배치 동작과 각 노드에 주어진 최종 점수가 어떻게 변하는지 관찰해요(이전 단계에서와 같이 nomad alloc status 명령 사용).