Nomad 모니터링

Nomad 모니터링 (Monitor Nomad)

Nomad 클라이언트와 서버 에이전트가 수집하는 런타임 메트릭을 통해 클러스터의 상태와 성능을 모니터링하는 방법을 알아봐요.

출처: 문서

본문

Nomad 클라이언트와 서버 에이전트는 다양한 런타임 메트릭을 수집해요. 이 메트릭들은 Nomad 클러스터의 상태와 성능을 모니터링하는 데 유용해요. 세심한 모니터링은 문제가 발생하기 전에 추세를 발견하고, 문제가 생겨도 디버깅하는 데 도움을 줘요.

모든 Nomad 에이전트(서버, 클라이언트 모두)는 기본적인 시스템 및 Go 런타임 메트릭을 보고해요.

Nomad 서버는 많은 메트릭을 보고하지만, 일부 메트릭은 리더 서버에만 특화되어 있어요. 리더십은 언제든 바뀔 수 있으므로 이러한 메트릭은 모든 서버에서 모니터링해야 해요. 비리더에서 누락(또는 0)된 메트릭은 안전하게 무시해도 돼요.

Nomad 클라이언트는 실행 중인 호스트에 대한 메트릭과 각 할당(allocation)에 대한 메트릭을 별도로 가져요. 이 두 메트릭 모두 명시적으로 활성화해야 해요.

기본적으로 Nomad 에이전트는 1초 간격으로 텔레메트리 데이터를 수집해요. Nomad는 게이지(gauge), 카운터(counter), 타이머(timer)를 지원한다는 점을 참고해요.

Nomad에서 메트릭을 얻는 방법은 세 가지가 있어요.

  • /v1/metrics API 엔드포인트를 조회해 현재 Nomad 프로세스의 메트릭을 반환받아요. 이 엔드포인트는 Prometheus 형식의 메트릭도 지원해요.
  • Nomad 프로세스에 USR1 신호를 보내요. 그러면 현재 텔레메트리 정보가 (Linux에서) STDERR로 덤프돼요.
  • Nomad가 DataDog, Prometheus, statsd, Circonus 같은 타사 제공자에게 메트릭을 자동으로 전달하도록 설정해요.

알림(Alerting)

알림의 권장 사례는 모니터링 제공자의 알림 기능을 활용하는 것이에요. Nomad의 의도는 기본적으로 알림을 지원하는 것이 아니라, 사용자가 기존 모니터링 시스템을 발판으로 필요한 알림을 구성할 수 있도록 메트릭을 노출하는 것이에요. 몇 가지 일반적인 패턴을 소개할게요.

  • StatsD exporter를 사용해 Nomad에서 Prometheus로 메트릭을 내보내고, Prometheus에서 알림 규칙을 정의한 뒤 Alertmanager를 사용해 요약 및 라우팅/알림(PagerDuty, Slack 등)을 처리해요. Datadog에서도 비슷한 워크플로우를 지원해요.
  • 주기적으로 테스트 작업(job)을 Nomad에 제출해 애플리케이션 배포 파이프라인이 엔드투엔드로 동작하는지 확인해요. 이 패턴은 배치 처리 워크로드에 잘 맞아요.
  • Nomad 위에 Nagios를 배포해요. Nomad 작업 파일을 중앙에서 관리하고, 새 Nomad 작업이 추가되면 Nagios 모니터를 추가해요. 작업이 제거되면 Nagios 모니터도 제거해요. Consul 알림을 Nagios 모니터에 매핑해요. 이렇게 하면 작업별 알림 시스템을 제공해요.
  • 각 배치 작업의 이력을 살펴 작업이 비정상 상태인지 판단하고 모니터링 시스템을 적절히 갱신하는 스크립트를 작성해요. 대부분의 경우 특정 배치 작업이 가끔 실패해도 통과 상태로 되돌아가기만 하면 괜찮아요.

핵심 성과 지표(Key performance indicators)

Nomad 서버의 메모리·CPU·디스크·네트워크 사용량은 모두 클러스터 규모와 스케줄링 처리량에 비례해 선형적으로 증가해요. Nomad가 정상 동작하는지 보장하는 가장 중요한 부분은 이러한 시스템 리소스를 모니터링해 서버가 리소스 제약에 부딪히지 않게 하는 것이에요.

Raft 합의 프로토콜

Nomad는 리더 선출과 상태 복제에 Raft 합의 프로토콜을 사용해요. 잘못된 리더 선출은 서버 간 네트워킹 문제, 불충분한 CPU 리소스, 불충분한 디스크 IOPS에 의해 발생할 수 있어요. 클라우드 환경의 사용자는 리더 선출을 안정화하기 위해 서버를 네트워킹과 CPU가 개선된 다음 인스턴스 클래스로 올리거나 고성능 디스크로 전환하곤 해요.

nomad.raft.leader.lastContact 메트릭은 Raft 지연 시간의 일반적인 지표로, Raft 타이밍이 어떻게 동작하는지 관찰하고 인프라 프로비저닝을 안내하는 데 사용할 수 있어요. 이 값이 상승 추세라면 CPU, 디스크 IOPS, 네트워크 지연 시간을 살펴봐요. nomad.raft.leader.lastContact는 리더 임대 타임아웃인 500ms에 너무 가까워지면 안 돼요.

nomad.raft.replication.appendEntries 메트릭은 Raft 트랜잭션이 팔로워 쿼럼에 복제되는 데 걸리는 시간을 나타내요. 이 값이 상승 추세라면 팔로워의 디스크 I/O와 리더-팔로워 간 네트워크 지연 시간을 확인해요.

CPU, IO 연산, 네트워킹을 검사하는 방법은 플랫폼과 환경에 따라 달라요. Linux에서는 sysstat 패키지에 유용한 도구가 여럿 들어 있어요. 고려할 예시를 들어볼게요.

  • CPU - vmstat 1, 클라우드 제공자의 "CPU %" 메트릭
  • IO - iostat, sar -d, 클라우드 제공자의 "volume write/read ops" 및 "burst balance" 메트릭
  • Network - sar -n, netstat -s, 클라우드 제공자의 인터페이스 "allowance" 메트릭

nomad.raft.fsm.apply 메트릭은 서버가 Raft 항목을 내부 상태 머신에 적용하는 데 걸리는 시간을 나타내요. 이 값이 상승 추세라면 nomad.nomad.fsm.* 메트릭을 살펴 특정 Raft 항목의 지연 시간이 증가하는지 확인해요. 이를 Nomad 서버의 attempting to apply large raft entry 경고 수준 로그와 비교할 수 있어요. 특정 유형의 메시지가 여기에 나타난다면, Raft 메시지를 적용하는 시간을 늘리는 큰 작업 명세 또는 디스패치 페이로드가 있는 작업이 있을 수 있어요. 서로 다른 태스크 그룹을 별도 작업으로 나누거나, 템플릿을 임베딩 대신 다운로드하거나, 태스크 그룹의 count를 줄여 작업 크기를 축소해 보세요.

스케줄링

Scheduling 문서는 평가(evaluation)가 스케줄링 계획이 되고 할당이 배치되는 워크플로우를 설명해요.

진행 상황(Progress)

Nomad에는 스케줄링 파이프라인의 두 구성 요소, 즉 워커와 리더의 계획 적용기(plan applier)가 계획의 유효성에 대해 의견이 갈리는 버그 클래스가 존재할 수 있어요. 병리적 경우에는 워커가 동일한 계획을 만들고 계획 적용기가 반복적으로 거부해서 작업이 스케줄링을 끝내지 못할 수 있어요.

이런 버그 클래스는 매우 드물지만, Nomad 서버의 plan for node rejected 로그 줄이 반복해서 나타나면 감지할 수 있어요.

nomad: plan for node rejected: node_id=0fa84370-c713-b914-d329-f6485951cddc reason="reserved port collision" eval_id=098a5

이 로그 줄은 정상적인 클러스터 상태로 인해 드물게 나타날 수 있지만, 반복적으로 나타나면서 작업이 결국 실행되지 못하게 해서는 안 돼요(로그에 남은 평가 ID를 찾아 작업을 확인해 보세요).

계획 거부 추적기(Plan rejection tracker)

Nomad는 클라이언트별로 계획 거부 이력을 추적하고, 특정 시간 창 내에서 횟수가 임계값을 초과하면 해당 클라이언트를 부적격(ineligible)으로 표시하는 메커니즘을 제공해요. 이 기능은 plan_rejection_tracker 서버 설정으로 활성화할 수 있어요.

노드가 과도한 계획 거부 때문에 부적격으로 표시되면 다음 노드 이벤트가 등록돼요.

Node marked as ineligible for scheduling due to multiple plan rejections, refer to https://developer.hashicorp.com/nomad/s/port-plan-failure for more information

그리고 로그 줄도 함께 나와요.

[WARN]  nomad.state_store: marking node as ineligible due to multiple plan rejections: node_id=67af2541-5e96-6f54-9095-11089d627626

클라이언트가 반복적인 계획 거부로 인해 부적격으로 표시된다면, 노드를 드레이닝(drain)하고 종료해 보세요. 검증으로 잡히지 않는 잘못된 설정이 노드를 이 상태로 만들 수 있어요: #11830.

plan for node rejected 로그가 같은 node_id를 참조하며 반복적으로 나타나는데 클라이언트가 부적격으로 설정되지 않는다면, 서버의 plan_rejection_tracker 설정을 조정해 볼 수 있어요.

성능(Performance)

다음 메트릭들은 스케줄링 과정의 여러 지점에서 처리량 변화를 관찰할 수 있게 해줘요.

  • nomad.worker.invoke_scheduler. <type> - 주어진 유형의 스케줄러를 실행하는 시간이에요. 각 스케줄러 워커는 한 번에 하나의 평가를 완전히 인메모리로 처리해요. 이 메트릭이 증가하면 스케줄러의 CPU와 메모리 리소스를 살펴봐요.
  • nomad.blocked_evals.total_blocked - 차단된 평가의 수예요. 차단된 평가는 스케줄러가 계획의 일부로 모든 할당을 배치할 수 없을 때 생성돼요. 차단된 평가는 재평가되어 클러스터 리소스의 변화가 차단된 평가의 할당에 사용될 수 있게 돼요. 차단된 평가의 증가는 클러스터의 클라이언트 리소스가 부족하거나, 모든 할당을 배치할 수 없는 작업이 제출되었음을 의미할 수 있어요.
  • nomad.broker.total_unacked - 승인되지 않은 평가의 수예요. 평가가 처리되면 워커는 처리 완료를 평가 브로커에 알리는 승인 RPC를 리더에게 보내요. 미승인 평가는 스케줄러에서 진행 중이며 아직 승인되지 않은 것들이에요. 미승인 평가의 증가는 스케줄러에 처리할 평가 큐가 크다는 것을 의미할 수 있어요. 위의 invoke_scheduler 메트릭(위)을 보고 스케줄러의 CPU와 메모리 리소스를 살펴봐요. Nomad는 각 개별 스케줄러에 대해 유사한 메트릭도 내보내요. 예를 들어 nomad.broker.batch_unacked는 배치 스케줄러의 미승인 평가 수를 보여줘요.
  • nomad.broker.total_pending - 평가 브로커의 보류 중인 평가 수예요. Nomad는 주어진 작업에 대해 한 번에 하나의 평가만 동시에 처리해요. 미승인 평가가 승인되면 Nomad는 해당 작업의 최신 평가를 제외한 나머지를 모두 버려요. 이 메트릭의 증가는 클러스터 상태가 스케줄러가 따라잡을 수 있는 속도보다 빠르게 변하고 있음을 의미할 수 있어요.
  • nomad.plan.evaluate - 워커가 제출한 스케줄러 계획을 평가하는 시간이에요. 이 연산은 모든 스케줄러 워커의 계획을 직렬화하기 위해 리더에서 발생해요. 전적으로 리더의 메모리에서 일어나요. 이 메트릭이 증가하면 리더의 CPU와 메모리 리소스 또는 제출되는 계획의 크기를 살펴봐요.
  • nomad.plan.apply - 플래너가 계획이 Raft에 의해 확인되기를 비동기적으로 기다리는 시간이에요. 이 메트릭이 증가하면 Consensus Protocol (Raft) 섹션을 참고해요.
  • nomad.plan.outstanding_apply - 계획 적용기가 Raft에 디스패치했지만 아직 확인을 받지 못한 계획의 수예요. 이 값은 0에 가까워야 해요.
  • nomad.plan.wait_for_index - 플래너가 계획의 Raft 인덱스가 처리되기를 기다리는 데 필요한 시간이에요. 이 메트릭이 증가하면 위의 Consensus Protocol (Raft) 섹션을 참고해요. 이 메트릭이 5초에 가까워지면 스케줄링 작업이 실패하고 재시도될 수 있어요. 가능하다면 메트릭이 개선될 때까지 스케줄링 부하를 줄여요.
  • nomad.plan.submit - 워커에서 리더로 스케줄러 계획을 제출하는 시간이에요. 이 연산은 Raft에 쓰는 것을 필요로 하며 nomad.plan.evaluate와 nomad.plan.wait_for_index(위)의 시간을 포함해요. 이 메트릭이 증가하면 위의 Consensus Protocol (Raft) 섹션을 참고해요.
  • nomad.plan.queue_depth - 제출된 후 평가를 기다리는 스케줄러 계획의 수예요. 이 메트릭이 증가하면 nomad.plan.evaluate와 nomad.plan.submit 메트릭을 살펴 문제가 일반적인 리더 리소스인지 아니면 Raft 성능인지 판단해요.

위 메트릭 중 어느 것의 상승도 스케줄러 처리량 감소를 나타내요.

용량(Capacity)

리소스 가용성을 모니터링하는 중요성은 워크로드마다 달라요. 배치 처리 워크로드는 종종 클러스터가 용량에 있거나 근접해야 하고, 대기 중인 작업이 적절한 리소스가 생기면 바로 실행되어야 한다고 가정하고 동작해요. 주로 가동 시간 요구 사항이 있는 장기 실행 서비스를 담당하는 클러스터는 20% 이상의 여유(headroom)를 유지하고 싶을 수도 있어요. 다음 메트릭들은 클라이언트별로 클러스터 전반의 용량을 평가하는 데 사용할 수 있어요.

  • nomad.client.allocated.cpu
  • nomad.client.unallocated.cpu
  • nomad.client.allocated.disk
  • nomad.client.unallocated.disk
  • nomad.client.allocated.memory
  • nomad.client.unallocated.memory

태스크 리소스 소비

여기에 나열된 메트릭들을 사용해 태스크별 리소스 소비를 추적할 수 있어요. 사용자 대상 서비스의 경우 태스크에 예약된 리소스 이상으로 CPU가 올라갈 때 알리는 것이 일반적이에요.

작업 및 태스크 상태

Nomad에서 실행 중인 워크로드의 상태와 성능을 모니터링하려면 Job Summary Metrics를 참고해요.

런타임 메트릭

런타임 메트릭은 모든 클라이언트와 서버에 적용돼요. 다음 메트릭들은 부하와 메모리 압박의 일반적인 지표예요.

  • nomad.runtime.num_goroutines
  • nomad.runtime.heap_objects
  • nomad.runtime.alloc_bytes

위 중 어느 것의 상승(특히 서버 메모리 사용량)에 대해 알리는 것이 권장돼요.

Serf 연합 배포

Nomad는 Serf 라이브러리의 멤버십 및 장애 감지 기능을 사용해 연합 배포의 모든 서버에 대해 하나의 전역 gossip 풀을 유지해요. member.flap 및/또는 msg.suspect의 상승은 멤버십이 불안정하다는 신뢰할 수 있는 지표예요.

이 메트릭들이 증가하면 서버의 CPU 부하와 Serf 주소에 대한 네트워크 지연 시간 및 패킷 손실을 살펴봐요.

클라이언트 소개(Client introduction)

client_introduction.enforcement을 warn 또는 strict로 설정해 Nomad를 구성하면, 클라이언트 등록 요청을 처리하는 서버는 소개 토큰(introduction token) 없이 새 등록이 있을 때마다 nomad.client.introduction.enforcement 카운터를 증가시켜요.

이 메트릭을 모니터링하면 소개 토큰 없이 등록하는 클라이언트를 식별하는 데 도움이 돼요. 이는 더 엄격한 시행 수준으로 마이그레이션할 때 중요해요.

더 알아보기 (Learn more)