작업 우선순위를 위한 선점 사용하기
작업 우선순위를 위한 선점 사용하기 (Use preemption for job priority)
선점(preemption)은 Nomad가 실행 중인 할당을 축출(evict)해 더 높은 우선순위의 할당을 배치할 수 있게 해줘요. 일시적으로 차단된 작업의 할당은 클러스터에 실행할 추가 용량이 생길 때까지 "pending" 상태로 들어가요. 이는 운영자가 클러스터 전반의 리소스 경합 상황에서도 상대적으로 더 높은 우선순위의 태스크를 더 일찍 실행해야 할 때 유용해요.
Nomad v0.9.0은 system 작업에 대한 선점을 추가했어요. Nomad v0.9.3 Enterprise는 service와 batch 작업에 대한 선점을 추가했어요. Nomad v0.12.0은 선점을 세 가지 작업 유형 모두에 대한 오픈 소스 기능으로 만들었어요.
선점은 system 작업에 대해 기본적으로 활성화돼요. service와 batch 작업에 대해서는 적절한 옵션을 지정한 페이로드를 스케줄러 구성 API 엔드포인트로 보내 활성화할 수 있어요.
출처: 문서
본문
전제 조건 (Prerequisites)
이 가이드에 설명된 작업을 수행하려면 Consul이 설치된 Nomad 환경이 필요해요. 이 저장소를 사용해 샌드박스 환경을 프로비저닝할 수 있지만, Nomad v0.12.0 이상 또는 Nomad Enterprise v0.9.3 이상을 사용해야 해요.
서버 노드 1개와 클라이언트 노드 3개가 있는 클러스터가 필요해요. 리소스 경합을 시뮬레이션하려면 이 환경의 노드들은 각각 1GB RAM을 가져야 해요(AWS의 경우 t2.micro 인스턴스 유형을 선택할 수 있어요).
Tip: 이 튜토리얼은 데모 목적이며 단일 서버 노드만 사용해요. 프로덕션 클러스터에는 서버 노드 3개 또는 5개를 권장해요.
낮은 우선순위 작업 만들기 (Create a job with low priority)
상대적으로 낮은 우선순위의 작업을 Nomad 클러스터에 만들어 시작해요. 이 작업의 할당 중 하나는 이후 배포에서 클러스터에 리소스 경합이 있을 때 선점돼요. 다음 작업을 파일에 복사하고 webserver.nomad.hcl이라고 이름을 지어요.
job "webserver" {
datacenters = ["dc1"]
type = "service"
priority = 40
group "webserver" {
count = 3
network {
port "http" {
to = 80
}
}
service {
name = "apache-webserver"
port = "http"
check {
name = "alive"
type = "http"
path = "/"
interval = "10s"
timeout = "2s"
}
}
task "apache" {
driver = "docker"
config {
image = "httpd:latest"
ports = ["http"]
}
resources {
memory = 600
}
}
}
}
count가 3이고 각 할당이 600 MB의 memory를 지정한다는 점에 유의하세요. 각 노드는 1GB RAM만 있다는 것을 기억하세요.
낮은 우선순위 작업 실행하기 (Run the low priority job)
nomad job run 명령을 사용해 webserver.nomad.hcl 작업을 시작해요.
$ nomad job run webserver.nomad.hcl
==> Monitoring evaluation "35159f00"
Evaluation triggered by job "webserver"
Evaluation within deployment: "278b2e10"
Allocation "0850e103" created: node "cf8487e2", group "webserver"
Allocation "551a7283" created: node "ad10ba3b", group "webserver"
Allocation "8a3d7e1e" created: node "18997de9", group "webserver"
Evaluation status changed: "pending" -> "complete"
==> Evaluation "35159f00" finished with status "complete"
이 시점에서 nomad job status 명령을 사용해 webserver 작업의 상태를 확인하고 클러스터의 각 클라이언트 노드에 할당이 하나씩 배치되었는지 검증해요.
$ nomad job status webserver
ID = webserver
Name = webserver
Submit Date = 2021-02-11T19:18:29-05:00
Type = service
Priority = 40
...
Allocations
ID Node ID Task Group Version Desired Status Created Modified
0850e103 cf8487e2 webserver 0 run running 8s ago 2s ago
551a7283 ad10ba3b webserver 0 run running 8s ago 2s ago
8a3d7e1e 18997de9 webserver 0 run running 8s ago 1s ago
높은 우선순위 작업 만들기 (Create a job with high priority)
"webserver" 작업보다 큰 priority를 가진 다른 작업을 만들어요. 다음을 redis.nomad.hcl이라는 파일에 복사해요.
job "redis" {
datacenters = ["dc1"]
type = "service"
priority = 80
group "cache1" {
count = 1
network {
port "db" {
to = 6379
}
}
service {
name = "redis-cache"
port = "db"
check {
name = "alive"
type = "tcp"
interval = "10s"
timeout = "2s"
}
}
task "redis" {
driver = "docker"
config {
image = "redis:latest"
ports = ["db"]
}
resources {
memory = 700
}
}
}
}
이 작업은 우선순위 80(앞서 webserver 작업의 우선순위보다 큼)을 가지며 700 MB의 메모리가 필요하다는 점에 유의하세요. 이 할당은 이미 600 MB 할당이 배치된 각 노드가 1GB의 메모리만 있으므로 클러스터에 리소스 경합을 만들 거예요.
선점 활성화 전후의 실행 관찰하기 (Observe a run before and after enabling preemption)
redis.nomad.hcl 실행 시도하기 (Try to run redis.nomad.hcl)
service와 batch 작업에 대한 선점은 기본적으로 활성화되어 있지 않다는 점을 기억하세요. 이는 redis 작업이 클러스터의 리소스 경합 때문에 대기열에 들어가게 된다는 뜻이에요. 작업을 실제로 등록하기 전에 nomad job plan 명령을 실행해 리소스 경합을 검증할 수 있어요.
$ nomad job plan redis.nomad.hcl
+ Job: "redis"
+ Task Group: "cache1" (1 create)
+ Task: "redis" (forces create)
Scheduler dry-run:
- WARNING: Failed to place all allocations.
Task Group "cache1" (failed to place 1 allocation):
* Resources exhausted on 3 nodes
* Dimension "memory" exhausted on 3 nodes
...
nomad job run 명령으로 redis.nomad.hcl 작업을 실행해요. 할당이 대기열에 들어갔음을 관찰해요.
$ nomad job run redis.nomad.hcl
==> Monitoring evaluation "3c6593b4"
Evaluation triggered by job "redis"
Evaluation within deployment: "ae55a4aa"
Evaluation status changed: "pending" -> "complete"
==> Evaluation "3c6593b4" finished with status "complete" but failed to place all allocations:
Task Group "cache1" (failed to place 1 allocation):
* Resources exhausted on 3 nodes
* Dimension "memory" exhausted on 3 nodes
Evaluation "249fd21b" waiting for additional capacity to place remainder
nomad job status 명령으로 작업의 상태를 가져와 할당이 이제 대기열에 들어갔는지 확인할 수도 있어요.
$ nomad job status redis
ID = redis
Name = redis
Submit Date = 2021-02-11T19:22:55-05:00
Type = service
Priority = 80
...
Placement Failure
Task Group "cache1":
* Resources exhausted on 3 nodes
* Dimension "memory" exhausted on 3 nodes
...
Allocations
No allocations placed
지금은 redis 작업을 중지해요. 다음 단계에서 service 작업 선점을 활성화하고 재배포할 거예요. nomad job stop 명령을 -purge 플래그와 함께 사용해요.
$ nomad job stop -purge redis
==> Monitoring evaluation "a9c9945d"
Evaluation triggered by job "redis"
Evaluation within deployment: "ae55a4aa"
Evaluation status changed: "pending" -> "complete"
==> Evaluation "a9c9945d" finished with status "complete"
service 작업 선점 활성화하기 (Enable service job preemption)
Nomad API를 사용해 현재 스케줄러 구성을 가져와요. 클러스터 주소로 환경 변수를 설정하면 curl 명령을 더 재사용하기 쉽게 만들어요. Nomad 클러스터에 맞는 올바른 주소로 대체해요.
$ export NOMAD_ADDR=http://127.0.0.1:4646
ACL이 활성화된 Nomad 클러스터에서 선점을 활성화한다면 X-Nomad-Token 헤더를 통해 Nomad 토큰으로 API에 인증해야 해요. 이 경우 환경 변수를 사용해 헤더 옵션과 토큰 값을 명령에 추가할 수 있어요. 토큰을 사용하지 않는다면 이 단계를 건너뛰어요. 변수가 설정되지 않으면 curl 명령이 올바르게 실행돼요.
$ export NOMAD_AUTH='--header "X-Nomad-Token: «replace with your token»"'
ACLs, consult the
이제 다음 curl 명령으로 구성을 가져와요.
$ curl --silent ${NOMAD_AUTH} \
${NOMAD_ADDR}/v1/operator/scheduler/configuration?pretty
{
"SchedulerConfig": {
"SchedulerAlgorithm": "binpack",
"PreemptionConfig": {
"SystemSchedulerEnabled": true,
"BatchSchedulerEnabled": false,
"ServiceSchedulerEnabled": false
},
"CreateIndex": 5,
"ModifyIndex": 5
},
"Index": 5,
"LastContact": 0,
"KnownLeader": true
}
BatchSchedulerEnabled와 ServiceSchedulerEnabled가 모두 기본적으로 false로 설정되어 있다는 점에 유의하세요. 이 가이드에서 service 작업을 선점하므로 ServiceSchedulerEnabled를 true로 설정해야 해요. API와 직접 상호작용해 이렇게 해요.
다음 JSON 페이로드를 만들어 scheduler.json이라는 파일에 넣어요:
{
"PreemptionConfig": {
"SystemSchedulerEnabled": true,
"BatchSchedulerEnabled": false,
"ServiceSchedulerEnabled": true
}
}
ServiceSchedulerEnabled가 true로 설정되었음에 유의하세요.
다음 명령을 실행해 스케줄러 구성을 업데이트해요:
$ curl --silent ${NOMAD_AUTH} \
--request POST --data @scheduler.json \
${NOMAD_ADDR}/v1/operator/scheduler/configuration
이제 스케줄러 구성을 다시 검사하고 service 작업에 대해 선점이 활성화되었는지 확인할 수 있어야 해요(아래 출력은 축약됨):
$ curl --silent ${NOMAD_AUTH} \
${NOMAD_ADDR}/v1/operator/scheduler/configuration?pretty
...
"PreemptionConfig": {
"SystemSchedulerEnabled": true,
"BatchSchedulerEnabled": false,
"ServiceSchedulerEnabled": true
},
...
redis 작업 다시 실행 시도하기 (Try running the redis job again)
이제 service 작업에서 선점을 활성화했으므로 redis 작업을 배포하면 낮은 우선순위의 webserver 할당 중 하나를 축출하고 대기열에 넣어야 해요. nomad plan을 실행해 어떤 일이 일어날지 미리 볼 수 있어요:
$ nomad job plan redis.nomad.hcl
+ Job: "redis"
+ Task Group: "cache1" (1 create)
+ Task: "redis" (forces create)
Scheduler dry-run:
- All tasks successfully allocated.
Preemptions:
Alloc ID Job ID Task Group
8a3d7e1e-40ee-f731-5135-247d8b7c2901 webserver webserver
...
앞의 계획 출력은 요청된 redis 인스턴스를 배치하기 위해 webserver 할당 중 하나가 축출될 것임을 보여줘요.
이제 nomad job run 명령을 사용해 redis.nomad.hcl 작업 파일을 실행해요.
$ nomad job run redis.nomad.hcl
==> Monitoring evaluation "fef3654f"
Evaluation triggered by job "redis"
Evaluation within deployment: "37b37a63"
Allocation "6ecc4bbe" created: node "cf8487e2", group "cache1"
Evaluation status changed: "pending" -> "complete"
==> Evaluation "fef3654f" finished with status "complete"
webserver 작업에 nomad job status 명령을 실행해 할당 중 하나가 축출되었는지 확인해요.
$ nomad job status webserver
ID = webserver
Name = webserver
Submit Date = 2021-02-11T19:18:29-05:00
Type = service
Priority = 40
...
Summary
Task Group Queued Starting Running Failed Complete Lost
webserver 1 0 2 0 1 0
Placement Failure
Task Group "webserver":
* Resources exhausted on 3 nodes
* Dimension "memory" exhausted on 3 nodes
...
Allocations
ID Node ID Task Group Version Desired Status Created Modified
0850e103 cf8487e2 webserver 0 evict complete 21m17s ago 18s ago
551a7283 ad10ba3b webserver 0 run running 21m17s ago 20m55s ago
8a3d7e1e 18997de9 webserver 0 run running 21m17s ago 20m57s ago
작업 중지하기 (Stop the job)
redis 작업에 nomad job stop 명령을 사용해요. 이렇게 하면 세 번째 webserver 할당을 차단 해제하는 데 필요한 용량이 제공돼요.
$ nomad job stop redis
==> Monitoring evaluation "df368cb1"
Evaluation triggered by job "redis"
Evaluation within deployment: "37b37a63"
Evaluation status changed: "pending" -> "complete"
==> Evaluation "df368cb1" finished with status "complete"
webserver 작업에 nomad job status 명령을 실행해요. 출력은 이제 선점된 것을 대체하는 새 세 번째 할당이 생성되었음을 나타내야 해요.
$ nomad job status webserver
ID = webserver
Name = webserver
Submit Date = 2021-02-11T19:18:29-05:00
Type = service
Priority = 40
Datacenters = dc1
Namespace = default
Status = running
Periodic = false
Parameterized = false
Summary
Task Group Queued Starting Running Failed Complete Lost
webserver 0 0 3 0 1 0
Latest Deployment
ID = 278b2e10
Status = successful
Description = Deployment completed successfully
Deployed
Task Group Desired Placed Healthy Unhealthy Progress Deadline
webserver 3 3 3 0 2021-02-12T00:28:51Z
Allocations
ID Node ID Task Group Version Desired Status Created Modified
4e212aec cf8487e2 webserver 0 run running 21s ago 3s ago
0850e103 cf8487e2 webserver 0 evict complete 22m48s ago 1m49s ago
551a7283 ad10ba3b webserver 0 run running 22m48s ago 22m26s ago
8a3d7e1e 18997de9 webserver 0 run running 22m48s ago 22m28s ago
다음 단계 (Next steps)
이 튜토리얼에서 배운 과정은 batch 작업에도 적용할 수 있어요. 선점에 대한 자세한 내용은 Nomad 문서에서 읽어보세요.