잡 스펙의 `resources` 블록

잡 스펙의 resources 블록

resources 블록은 태스크가 실행하는 데 필요한 요구 사항을 설명해요. 리소스 요구 사항에는 메모리, CPU 등이 포함돼요.

출처: 문서

본문

배치 job -> group -> task -> **resources**
job "docs" {
  group "example" {
    task "server" {
      resources {
        cpu    = 100
        memory = 256

        device "nvidia/gpu" {
          count = 2
        }
      }
    }
  }
}

매개변수 (Parameters)

  • cpu (int: 100) - 이 태스크를 실행하는 데 필요한 CPU(MHz).

  • cores (int: <optional>) - 태스크를 위해 구체적으로 예약할 CPU 코어 수. cpu와 함께 사용할 수 없어요. cores 설정의 동작은 각 태스크 드라이버(docker, exec 등)마다 다르다는 점에 유의하세요.

  • memory (int: 300) - 필요한 메모리(MB).

  • memory_max (int: <optional>) - 선택적으로, 클라이언트에 여분의 메모리 용량이 있을 때 태스크가 사용할 수 있는 최대 메모리(MB). 자세한 내용은 Memory Oversubscription을 참고하세요.

  • numa ([Numa]: <optional>) - 태스크의 NUMA 스케줄링 선호도를 지정. cores 사용이 필요해요.

  • device ([Device]: <optional>) - 장치 요구 사항. 여러 장치 타입을 요청하기 위해 반복할 수 있어요.

  • secrets (int: <optional>) - 디렉터리가 tmpfs인 플랫폼에서 secrets/ 디렉터리의 크기(MB). 설정되면 스케줄러가 클라이언트에 리소스를 할당할 때 memory 값에 secrets 값을 더하고, 이 값은 nomad alloc status와 nomad node status 명령이 보여주는 할당된 리소스에 포함돼요. 설정하지 않으면 클라이언트가 1MB의 tmpfs 공간을 할당하고 그것은 스케줄링 목적이나 할당된 리소스에 포함되지 않아요. 워크로드가 tmpfs를 지원하지 않는 플랫폼에 배치될 경우 이 값을 설정하지 마세요. 스케줄링 목적으로 여전히 계산되기 때문이에요.

예시 (Examples)

다음 예시는 resources 블록만 보여줘요. resources 블록은 위에 나열된 배치에서만 유효하다는 점을 기억하세요.

코어 (Cores)

이 예시는 태스크가 예약된 코어 2개를 요구함을 지정해요. 이 블록을 사용하면 Nomad는 태스크를 위해 코어 2개를 독점적으로 예약할 충분한 여유 용량이 있는 클라이언트를 찾아요. cpu 필드와 달리 이 태스크는 클라이언트에서 Nomad가 관리하는 다른 태스크와 CPU 시간을 공유하지 않아요.

resources {
  cores = 2
}

같은 리소스 블록에서 cores와 cpu가 모두 정의되면 잡 검증이 실패해요.

Nomad의 CPU 리소스 예약에 대한 자세한 내용은 How Nomad Uses CPU를 참고하세요.

메모리 (Memory)

이 예시는 태스크가 동작하는 데 2GB의 RAM을 요구함을 지정해요. 2GB는 2048MB와 같아요:

resources {
  memory = 2048
}

장치 (Devices)

이 예시는 device 블록에 지정된 장치 제약 조건을 보여주며, nvidia GPU 두 개를 사용할 수 있게 요구해요:

resources {
  device "nvidia/gpu" {
    count = 2
  }
}

메모리 오버서브스크립션 (Memory oversubscription)

태스크 메모리 제한을 설정하는 것은 태스크를 중단시킬 위험과 리소스를 낭비할 위험의 균형을 맞춰야 해요. 태스크 메모리 제한이 너무 낮게 설정되면 태스크가 제한을 초과해 중단될 수 있고, 태스크 메모리가 너무 높으면 클러스터가 충분히 활용되지 못해요. Nomad 드라이버는 두 개의 분리된 메모리 제한을 구성해요:

  • 제한(limit) 또는 하드 제한은 태스크가 사용할 수 있는 최대 메모리를 나타내요. 운영체제는 일반적으로 태스크가 이 제한을 초과하면 태스크를 종료해요. Linux에서 대부분의 태스크 드라이버는 memory.max cgroup을 통해 제한을 구현해요.
  • _예약(reservation)_은 태스크의 일반적인 메모리 사용량을 나타내요. 운영체제는 예약에 대해 최선의 메모리 보호를 제공해요. Linux에서 대부분의 태스크 드라이버는 memory.low cgroup을 통해 예약을 구현해요.

클라이언트의 메모리가 경합되거나 낮아지면 운영체제는 실행 중인 태스크에 메모리를 확보하도록 압력을 가해요. 경합이 지속되면 Nomad는 오버서브스크립션된 태스크를 종료하고 다른 클라이언트로 재스케줄링할 수 있어요. 메모리 압력의 정확한 메커니즘은 태스크 드라이버, 운영체제, 애플리케이션 런타임에 따라 달라져요.

예상치 못한 부하 급증에 대한 안전 여유를 허용하면서 클러스터 메모리 활용을 최대화하기 위해, Nomad는 잡 작성자가 앞서 설명한 하드·소프트 제한에 해당하는 두 개의 분리된 리소스 제한을 설정할 수 있게 해요.

  • memory: memory_max가 설정되지 않으면 하드 제한. memory_max가 설정되면 memory는 예약이에요.
  • memory_max: 설정되면 하드 제한. memory_max가 설정되지 않으면 memory가 하드 제한이에요. memory_max가 -1로 설정되고 드라이버에서 지원되면 태스크는 하드 제한이 없어요.

memory_max 제한 속성은 현재 공식 raw_exec, exec2, exec, docker, podman, java 태스크 드라이버에서 지원돼요. 커뮤니티 지원 태스크 드라이버의 메모리 오버서브스크립션 지원은 해당 문서를 참고하세요.

memory_max 설정을 통한 메모리 오버서브스크립션은 옵트인(opt-in)이에요. Nomad 운영자는 스케줄러 구성에서 메모리 오버서브스크립션을 활성화할 수 있어요. 자세한 내용은 MemoryOversubscritionEnabled 매개변수를 참고하세요. Enterprise 고객은 resource quotas를 사용해 메모리 오버서브스크립션을 제한하고 node pool별로 메모리 오버서브스크립션을 활성화·비활성화할 수 있어요.

클러스터 경험 저하를 피하기 위해 리소스 활용도를 검사·모니터링하고 다음 제안을 고려할 것을 권장해요:

  • Nomad가 관리하지 않는 Linux 호스트 서비스에 oom_score_adj를 설정하세요. 예: Docker, 로깅 서비스, 그리고 Nomad 에이전트 자체. Systemd 서비스의 경우 OOMScoreAdj 필드를 사용할 수 있어요.

  • 호스트의 메모리 활용도를 모니터링하고 Out-Of-Memory 오류에 알림을 설정하세요.

  • Nomad가 관리하지 않는 호스트 서비스와 메모리 초과분에 대한 버퍼를 위해 클라이언트 reserved를 충분한 메모리로 설정하세요. 예를 들어 클라이언트 예약 메모리가 1GB라면, 메모리가 경합되고 할당이 종료되기 전에 호스트의 할당이 집계적으로 소프트 메모리 제한을 거의 1GB 초과할 수 있어요.

  • Nomad의 스케줄링은 memory 필드를 사용한다는 점에 유의하세요. Nomad Enterprise의 쿼터 적용에 memory와 memory_max에 대한 별도 필드가 있어요. memory_max를 -1로 설정해 하드 제한을 제거하면 쿼터 사용을 효과적으로 우회해요. 오버서브스크립션과 쿼터를 모두 사용하려면 Sentinel 정책으로 memory_max를 -1로 설정하는 것을 막아야 해요.

더 알아보기 (Learn more)