Nomad vs. Kubernetes: 왜 우리는 SaaS를 HashiCorp Nomad로 전환했는가

발행: (2026년 3월 19일 AM 06:17 GMT+9)
7 분 소요
원문: Dev.to

Source: Dev.to

번역을 진행하려면 번역하고자 하는 전체 텍스트를 제공해 주세요. 현재는 링크만 포함되어 있어 번역할 내용이 없습니다. 텍스트를 복사해서 알려주시면 그대로 한국어로 번역해 드리겠습니다.

Source:

복잡성 세금: 왜 쿠버네티스가 항상 정답은 아닌가

현대 DevOps 환경에서 쿠버네티스(K8s)는 컨테이너 오케스트레이션의 기본 선택으로 여겨집니다. 강력하고 검증된 솔루션이며 방대한 생태계를 가지고 있습니다. 하지만 많은 중소 규모 SaaS 팀에게는 쿠버네티스가 상당한 복잡성 세금을 부과합니다.

우리는 2년 동안 프로덕션 K8s 클러스터를 운영했습니다. 확장 문제는 해결했지만, **엔지니어링 시간의 약 30 %**를 오케스트레이터 자체를 유지보수하는 데 사용했습니다—CNI 플러그인 디버깅, 복잡한 RBAC 관리, 그리고 박사 학위가 필요할 정도로 느껴지는 Helm 차트와 씨름하는 등.

그때 우리는 HashiCorp Nomad를 살펴보게 되었습니다.

Nomad는 컨테이너화된 애플리케이션과 비컨테이너화된 애플리케이션 모두를 관리할 수 있는 가볍고 유연한 오케스트레이터입니다. 유닉스 철학을 따릅니다: 한 가지 일을 잘 수행한다. 이 글에서는 우리가 전환한 이유, 아키텍처 차이점, 그리고 프로덕션 수준의 Nomad 워크플로우를 구현하는 방법을 살펴보겠습니다.

기본 Nomad 에이전트 설정

data_dir = "/opt/nomad/data"
bind_addr = "0.0.0.0"

server {
  enabled          = true
  bootstrap_expect = 3
}

client {
  enabled = true
}

이 간결함은 개발자 경험에도 그대로 이어집니다. Nomad Job은 HCL(HashiCorp Configuration Language)로 정의되며, 쿠버네티스에서 요구되는 장황한 YAML보다 훨씬 읽기 쉽습니다.

Next.js 프론트엔드를 위한 프로덕션‑레디 Nomad 잡

job "webapp" {
  datacenters = ["dc1"]
  type        = "service"

  group "frontend" {
    count = 3

    network {
      port "http" {
        to = 3000
      }
    }

    service {
      name = "webapp-frontend"
      port = "http"

      check {
        type     = "http"
        path     = "/api/health"
        interval = "10s"
        timeout  = "2s"
      }
    }

    task "nextjs" {
      driver = "docker"

      config {
        image = "my-registry/webapp:latest"
        ports = ["http"]
      }

      resources {
        cpu    = 500   # MHz
        memory = 256   # MB
      }

      env {
        NODE_ENV = "production"
      }
    }
  }
}

Nomad에서 계층 구조는 Job → Group → Task입니다. 하나의 Job은 여러 그룹을 포함할 수 있고, 그룹은 같은 노드에 함께 배치되는 태스크들을 포함합니다(쿠버네티스의 Pod와 유사).

서비스 디스커버리와 로드 밸런싱

쿠버네티스에서 “함정” 중 하나는 Ingress 컨트롤러의 복잡성입니다. Nomad 생태계에서는 Consul을 사용합니다. Nomad 태스크가 시작되면 자동으로 Consul에 등록됩니다. 이후 Fabio 혹은 Traefik을 로드 밸런서로 사용하면 Consul 서비스 카탈로그를 기반으로 동적으로 설정이 업데이트됩니다.

비밀 관리를 위한 Vault 통합

K8s Secrets(단순히 base64‑인코딩된 문자열) 대신 Nomad는 Vault와 네이티브하게 통합됩니다. 비밀을 환경 변수나 파일 형태로 직접 주입할 수 있습니다:

template {
  data = <<EOH
    DATABASE_URL="{{with secret \"database/creds/readonly\"}}{{.Data.url}}{{end}}"
  EOH
  destination = "secrets/file.env"
  env         = true
}

네트워킹 및 스토리지 고려사항

  • 네트워크 스택 – 기본적으로 Nomad는 호스트의 네트워크 스택을 사용합니다. 이는 거의 네이티브에 가까운 성능을 제공하지만 포트 충돌을 직접 관리해야 합니다.
    해결책: 격리된 컨테이너 네트워크를 위해 CNI 플러그인을 이용한 Nomad의 브리지 네트워킹 모드를 사용합니다(쿠버네티스와 유사).

  • 스토리지 – Nomad의 CSI(Container Storage Interface) 지원은 견고하지만 쿠버네티스만큼 “자동화”되지는 않습니다.
    해결책: SaaS 데이터베이스는 관리형 서비스(예: RDS, Supabase)를 사용하거나, 최대 IOPS를 위해 Nomad의 host_volume을 이용해 전용 노드에 배치하는 것을 권장합니다.

기능 비교

기능KubernetesHashiCorp Nomad
복잡성높음 (학습 곡선 가파름)낮음 (단일 바이너리)
유연성컨테이너만 (대부분)컨테이너, 바이너리, Java, VM
생태계방대함집중형 (HashiStack)
자원 사용량높은 오버헤드매우 낮은 오버헤드

주요 내용

  • Nomad는 운영 및 유지 관리가 훨씬 쉽습니다.
  • HashiStack(Nomad, Consul, Vault)은 모듈식이며 최고의 조합 방식을 제공합니다.
  • HCL은 인프라스트럭처‑코드에 적합한 우수한 구성 언어입니다.

오케스트레이션에 대한 여러분의 접근 방식은 무엇인가요? “Kubernetes 피로감”을 느끼셨나요, 아니면 복잡성을 감수하고도 생태계의 이점이 더 크다고 생각하시나요? 의견을 댓글에 남겨 주세요.

0 조회
Back to Blog

관련 글

더 보기 »