노마드 설치 요구사항

노마드 설치 요구사항

이 페이지는 노마드가 필요로 하는 하드웨어와 네트워킹 리소스의 개요를 담고 있어요. RAM, CPU, 네트워크 토폴로지와 포트, 사용자 권한, Linux 기능(capabilities)을 검토해요.

출처: 문서

본문

리소스

노마드 서버는 대형 머신 인스턴스에서 실행해야 할 수 있어요. 4-8+ 코어, 16-32 GB+ 메모리, 40-80 GB+의 빠른 디스크, 그리고 상당한 네트워크 대역폭을 권장해요. 코어 수와 네트워크 권장사항은 높은 처리량을 보장하기 위한 것이에요. 노마드는 네트워크 통신에 크게 의존하며, 서버가 리전의 모든 노드를 관리하고 스케줄링을 수행하기 때문이에요. 메모리와 디스크 요구사항은 노마드가 모든 상태를 메모리에 저장하고 이 데이터의 스냅샷 두 개를 디스크에 저장하기 때문이에요. 이는 쓰기가 많은 바쁜 클러스터에서 높은 IO를 발생시켜요. 따라서 높은 로드 클러스터를 배포할 때 디스크는 서버의 가용 메모리보다 최소 2배 이상이어야 해요. AWS에서 실행할 때는 data dir에 NVME 또는 Provisioned IOPS SSD 스토리지를 선호해요.

이 권장사항은 가이드라인이므로, 운영자는 항상 노마드의 리소스 사용량을 모니터링해 머신이 과소 또는 과대 크기인지 판단해야 해요.

노마드 클라이언트는 노마드가 사용하지 않아야 하는 노드의 리소스 예약을 지원해요. 이는 노드별 특정 리소스 사용률을 목표로 하고, Consul 및 운영 체제 자체처럼 노마드의 관리 밖에서 실행되는 애플리케이션을 위한 리소스를 예약하는 데 사용해야 해요.

자세한 내용은 예약(reservation) 구성 문서를 참고해 주세요.

네트워크 토폴로지

노마드 서버는 활성 상태와 높은 처리량 스케줄링을 보장하기 위해 서로 간 10밀리초 미만의 네트워크 지연 시간을 가져야 해요. 고가용성을 달성하기 위해 노마드 서버는 서로 낮은 지연 연결이 있는 여러 데이터센터에 분산될 수 있어요.

예를 들어 AWS에서는 각 리전이 여러 존으로 구성되며 존 간에는 매우 낮은 지연 링크가 있어요. 따라서 각 존을 노마드 데이터센터로 모델링할 수 있고, 각 존은 쿼럼과 리전을 형성하기 위해 연결될 수 있는 단일 노마드 서버를 가질 수 있어요.

노마드 서버는 상태 복제에 Raft를 사용하며, 고도의 일관성을 요구하는 Raft는 기능하기 위해 쿼럼의 서버가 필요해요. 따라서 리전에서 홀수 개의 노마드 서버를 실행할 것을 권장해요. 보통 리전에서 3-5개의 서버를 실행하는 것이 권장돼요. 클러스터는 3개 서버 클러스터에서 서버 하나의 장애를, 5개 서버 클러스터에서 두 개의 장애를 견딜 수 있어요. 쿼럼에 서버를 더 추가하면 상태 복제에 더 많은 시간이 걸려 처리량이 감소하므로, 리전에서 7개를 넘는 서버를 실행하는 것은 권장하지 않아요.

노마드 클라이언트는 Raft에 참여하지 않으므로 서버와 같은 지연 시간 요구사항이 없어요. 따라서 클라이언트는 서버까지 100+ 밀리초 지연 시간을 가질 수 있어요. 이는 단일 "global" 리전과 많은 데이터센터가 있는 경우, 대륙이나 전 세계에 지리적으로 분산된 클라이언트를 서비스하는 노마드 서버 집합을 가질 수 있게 해요.

노마드 클라이언트는 RPC 포트의 서버에 연결한 뒤 지속적인 TCP 연결을 유지해요. 서버와 클라이언트는 이 TCP 연결을 양방향 통신에 사용해요. 그 결과, 서버에서 지리적으로 분산된 클라이언트는 서버와 통신하기 위해 공개 라우팅 가능한 IP 주소가 필요하지 않아요(클라이언트에서 실행되는 워크로드에는 공개 IP가 필요할 수 있지만). 노마드 서버 간, 그리고 클라이언트와 서버 간의 모든 연결은 mTLS로 보호해야 해요.

노마드 클라이언트는 일반적으로 서로 도달 가능할 필요가 없어요. 워크로드가 서로 통신해야 하는 경우가 아니라면 말이에요. 선택적 디스크 마이그레이션(ephemeral disk migration) 필드는 한 가지 예외로, 클라이언트가 서로의 HTTP 포트에 도달할 수 있어야 해요.

사용 포트

노마드는 서버에서 제대로 동작하려면 3개의 다른 포트가, 클라이언트에서는 2개가 필요해요. 일부는 TCP, 일부는 UDP, 일부는 두 프로토콜 모두예요. 아래는 각 포트의 요구사항을 정리한 것이에요. 어떤 유형의 방화벽을 사용하든 다음 트래픽을 허용하도록 구성되어 있는지 확인해야 해요.

  • HTTP API (기본 4646) — 클라이언트와 서버가 HTTP API를 서비스하는 데 사용해요. TCP 전용이에요.
  • RPC (기본 4647) — 클라이언트 에이전트와 서버 사이의 내부 RPC 통신, 그리고 서버 간 트래픽에 사용돼요. TCP 전용이에요.
  • Serf WAN (기본 4648) — 서버가 다른 서버로 LAN과 WAN 양쪽에서 gossip하는 데 사용해요. 노마드 클라이언트가 이 주소에 도달할 수 있어야 하는 것은 아니에요. TCP와 UDP.

작업이 동적 포트를 요청하면 20,000에서 32,000 사이의 포트 범위에서 할당돼요. 이는 IANA가 제안하는 임시(ephemeral) 포트 범위보다 훨씬 아래예요. 운영 체제의 기본 임시 포트 범위가 노마드의 동적 포트 범위와 겹치면, 이 겹침을 피하도록 OS를 조정해야 해요.

Linux에서는 다음과 같이 확인하고 설정할 수 있어요:

$ cat /proc/sys/net/ipv4/ip_local_port_range
32768   60999
$ echo "49152 65535" > /proc/sys/net/ipv4/ip_local_port_range

브리지 네트워킹과 iptables

노마드의 태스크 그룹 네트워크는 브리지 네트워킹과 iptables를 사용해 컨테이너 간 트래픽을 보내면서 Consul의 서비스 메시와 통합돼요.

⚠️ Ubuntu 24.04 같은 새로운 Linux 버전은 기본적으로 브리지 네트워킹을 활성화하지 않을 수 있어요. 브리지 모듈이 없으면 sudo modprobe bridge를 사용해 로드해 주세요.

Linux 커널 브리지 모듈에는 iptables가 브리지를 통과하는 트래픽을 처리하는지 제어하는 세 가지 튜너블 파라미터가 있어요. RedHat, CentOS, Fedora 같은 일부 운영 체제는 이 튜너블 파라미터가 VM 워크로드에 최적화되어 있어 게스트 트래픽용 iptables 규칙이 올바르게 구성되지 않을 수 있어요.

Linux 배포판이 브리지 네트워크를 통해 컨테이너 트래픽을 iptables로 라우팅하도록 구성되어 있는지 확인해 주세요. 브리지 네트워크에서 iptables 처리를 허용하도록 튜너블 파라미터를 설정하려면 다음 명령을 실행해요.

$ echo 1 > /proc/sys/net/bridge/bridge-nf-call-arptables
$ echo 1 > /proc/sys/net/bridge/bridge-nf-call-ip6tables
$ echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables

클라이언트 노드 시작 시 이 설정을 유지하려면 /etc/sysctl.d/에 파일을 추가하거나, Linux 배포판이 그 디렉터리에 넣어둔 파일을 제거해 주세요. 다음 예시는 클라이언트 노드의 튜너블 파라미터를 구성해요.

/etc/sysctl.d/bridge.conf

net.bridge.bridge-nf-call-arptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1

cgroup 컨트롤러

Linux에서 노마드는 CPU, 메모리 같은 리소스에 대한 접근을 제어하기 위해 cgroup을 사용해요. 노마드는 cgroups v2와 레거시 cgroups v1을 모두 지원해요. 노마드 클라이언트가 시작되면 사용 가능한 cgroup 컨트롤러를 확인하고 os.cgroups.version 속성을 fingerprint에 포함해요.

노마드는 필요한 컨트롤러가 모두 사용 가능할 때만 cgroup으로 리소스를 제어할 수 있어요. 필요한 cgroup이 하나라도 없으면 노마드는 cgroup이 필요한 리소스 제어를 비활성화해요. 데이터센터 밖에서 쓰는 플랫폼(예: Raspberry Pi 같은 취미용 컴퓨터)에서 컨트롤러가 없는 경우가 가장 흔해요.

cgroups v2에서는 다음 명령으로 필요한 컨트롤러가 모두 있는지 확인할 수 있어요.

$ cat /sys/fs/cgroup/cgroup.controllers
cpuset cpu io memory pids

레거시 cgroups v1에서는 이와 동일한 필수 컨트롤러 목록이 /sys/fs/cgroup 디렉터리의 일련의 하위 디렉터리로 나타나요.

누락된 cgroup을 활성화하려면 적절한 부팅 커널 명령줄 인자를 추가해요. 예를 들어 Raspberry Pi 커널 패치셋에서 cpuset cgroup을 활성화하려면 cgroup_cpuset=1 cgroup_enable=cpuset을 추가해요. 이 인자는 부트로더가 지정하는 위치에 추가하면 돼요.

cgroup에 대한 자세한 내용은 Hardening Nomad를 참고해 주세요.

노마드 하드닝

Security Model 가이드에서 언급했듯이 노마드는 기본적으로 안전하지 않아요(not secure-by-default).

사용자 권한

노마드 서버와 노마드 클라이언트는 권한 요구사항이 달라요.

노마드 서버는 가능한 가장 낮은 권한으로 실행해야 해요. 서버는 자체 데이터 디렉터리에 접근하고 자신의 포트에 바인딩할 수 있는 권한만 필요해요. 최소한의 필수 권한을 가진 nomad 사용자를 만들어야 해요. 공식 Linux 패키지에서 노마드를 설치했다면, systemd 유닛 파일은 노마드를 root로 실행해요. 서버 노드에서는 이를 최소 권한의 nomad 사용자로 바꿔야 해요. 자세한 내용은 프로덕션 배포 가이드를 참고해 주세요.

노마드 클라이언트는 root 권한이 필요한 OS 격리 메커니즘 때문에 root로 실행해야 해요(아래 Linux 기능도 참고). 노마드 클라이언트의 데이터 디렉터리는 root가 소유하고 파일시스템 권한은 0700으로 설정해야 해요.

Linux 기능 (capabilities)

Linux에서 노마드 클라이언트는 작업을 격리하기 위해 권한 있는 기능(privileged capabilities)이 필요해요. 노마드 클라이언트는 시크릿을 만드는 데 사용하는 tmpfs 생성, 작업 디렉터리 바인드 마운트, 볼륨 마운트, 일부 작업 드라이버 플러그인 실행을 위해 CAP_SYS_ADMIN이 필요해요. 노마드 클라이언트는 네트워킹을 설정하는 다양한 작업을 위해 CAP_NET_ADMIN이 필요해요. 노마드 클라이언트는 root로 실행해야 하지만, 노마드가 사용자 네임스페이스에서 실행 중이라면 root로 실행해도 필요한 기능이 부여되지 않아요. 사용자 네임스페이스 안에서 노마드 클라이언트를 실행하는 것은 지원되지 않아요. Linux 기능에 대한 자세한 내용은 capabilities(7) 매뉴얼 페이지를 참고해 주세요.

작업을 실행하기 위해 노마드 클라이언트는 보통 root 사용자에게 예약된 권한 있는 작업을 수행해요:

  • 작업의 /secrets 디렉터리를 위한 tmpfs 파일시스템 마운트
  • 브리지 네트워킹을 위한 네트워크 브리지 생성
  • 워크로드에 대한 인바운드·아웃바운드 네트워크 트래픽 허용(보통 iptables를 통해)
  • 특정 사용자로 작업 시작
  • 템플릿 출력의 소유자 설정

Linux에서 이 요구사항 집합은 다음으로 확장돼요:

  • cgroups를 통한 리소스 격리 구성
  • 네임스페이스 격리(mount, user, pid, ipc, network 네임스페이스) 구성

볼륨 바인드 마운트를 지원하는 노마드 작업 드라이버도 그렇게 하려면 root로 실행해야 해요. 여기에는 내장 exec와 java 작업 드라이버가 포함돼요. 내장 작업 드라이버는 노마드 클라이언트와 같은 프로세스에서 실행되므로, 노마드 클라이언트 에이전트도 root로 실행해야 한다는 뜻이에요.

루트리스(Rootless) 노마드 클라이언트

노마드 클라이언트 에이전트를 비-root 사용자로 또는 사용자 네임스페이스의 root로 실행하는 것이 가능하지만, 위에서 설명한 권한 있는 작업을 수행하려면 클라이언트 에이전트에 CAP_SYS_ADMIN과 CAP_NET_ADMIN 기능을 부여해야 해요. 이 기능들은 거의 root로 실행하는 것과 기능적으로 동일하며, CAP_SYS_ADMIN으로 실행되는 프로세스는 거의 항상 스스로 "진정한"(네임스페이스 없는) root로 승격할 수 있다는 점을 유의하세요.

일부 작업 드라이버는 권한 있는 작업의 대부분을 dockerd나 podman 같은 외부 프로세스에 위임해요. 브리지 네트워킹이 필요하지 않고 이런 작업 드라이버나 사용자 정의 작업 드라이버를 사용한다면, 다음 추가 구성으로 노마드 클라이언트 에이전트를 비-root 사용자로 실행할 수 있을 수도 있어요:

  • 위임된 cgroups (Delegated cgroups): 권한 없는 사용자로 cgroups를 안전하게 설정하려면 cgroups v2가 필요해요.
  • 사용자 네임스페이스 (User namespaces): 일부 배포판에서는 kernel.unprivileged_userns_clone=1 같은 sysctl 설정이 필요할 수 있어요.
  • 작업 드라이버 엔진: (예: dockerd, podman, containerd 등) 루트리스 동작으로 구성해야 해요. 여기에는 cgroups v2, 사용자 네임스페이스, 그리고 보통 권한 없는 overlay 파일시스템을 허용하는 패치된 커널이나 커널 모듈(예: overlay.ko) 또는 FUSE overlay 파일시스템이 필요해요.

이것은 지원되거나 잘 테스트된 구성이 아니에요. 루트리스 노마드 클라이언트를 실행하려는 경험에 대한 논의와 피드백은 GH-13669를 참고해 주세요.

Docker에서 노마드 실행

시스템을 Docker 컨테이너로 실행하는 것은 일반적인 관행이 되었어요. 컨테이너 안에서 노마드 서버를 실행하는 것은 가능하지만, 노마드 클라이언트는 Rootless Nomad Clients에서 설명했듯이 기본 호스트 머신에 대한 광범위한 접근이 필요해요. Docker 컨테이너는 클라이언트와 작업 드라이버를 제대로 구성하기 어렵게 만드는 상당한 추상화 계층을 도입하므로, Docker 컨테이너에서 노마드 클라이언트를 실행하는 것은 공식적으로 지원되지 않아요.

hashicorp/nomad Docker 이미지는 nomad job plan, nomad fmt 같은 CLI 작업용 자동화 파이프라인에서 사용하도록 의도된 것이에요.

참고: Nomad Docker 이미지는 에이전트로 실행할 때 테스트되지 않았어요.

더 알아보기 (Learn more)