HAProxy로 로드 밸런싱

HAProxy로 로드 밸런싱 (Load balancing with HAProxy)

HAProxy를 사용해 Nomad에서 HTTP(S) 및 TCP 요청을 로드 밸런싱하는 방법을 알아봐요.

출처: 문서

본문

HAProxy는 인터넷에서 들어오는 HTTP(S) 및 TCP 요청을 처리할 수 있는 프런트엔드 서비스로 분산해요.

HAProxy에는 HAProxy의 로드 밸런싱 풀을 채울 placeholder 백엔드 서버를 지정할 수 있는 [server-template] 지시문이 포함돼요. 이러한 백엔드 서버 중 하나로 Consul을 사용해 Consul DNS에서 SRV 레코드를 요청할 수 있어요.

다음 단계에 따라 HAProxy를 로드 밸런서로 사용해요.

  1. 애플리케이션을 배포해요.
  2. HAProxy를 구성하고 배포해요.

이 가이드는 데모 웹 애플리케이션의 로드 밸런서로 HAProxy를 배포하는 방법을 보여줘요.

사전 요구 사항

Nomad 설치가 Consul을 사용하도록 구성되어야 해요. 자세한 내용은 Consul 통합 콘텐츠를 참고해요.

데모 웹 애플리케이션 배포

데모 웹 애플리케이션에 대한 작업 명세를 만들고 파일 이름을 webapp.nomad.hcl로 지어요. 이 작업 명세는 HAProxy 구성에서 대상으로 삼을 데모 웹 애플리케이션의 인스턴스 세 개를 만들어요.

webapp.nomad.hcl

job "demo-webapp" {
  datacenters = ["dc1"]

  group "demo" {
    count = 3

    network {
      port "http" { }
    }

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

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

    task "server" {
      env {
        PORT    = "${NOMAD_PORT_http}"
        NODE_IP = "${NOMAD_IP_http}"
      }

      driver = "docker"

      config {
        image = "hashicorp/demo-webapp-lb-guide"
        ports = ["http"]
      }
    }
  }
}

nomad run 명령으로 웹 애플리케이션 작업을 배포해요.

$ nomad run webapp.nomad.hcl
==> Monitoring evaluation "8f3af425"
    Evaluation triggered by job "demo-webapp"
    Evaluation within deployment: "dc4c1925"
    Allocation "bf9f850f" created: node "d16a11fb", group "demo"
    Allocation "25e0496a" created: node "b78e27be", group "demo"
    Allocation "a97e7d39" created: node "01d3eb32", group "demo"
    Evaluation status changed: "pending" -> "complete"
==> Evaluation "8f3af425" finished with status "complete"

HAProxy 작업 만들고 실행하기

HAProxy에 대한 작업을 만들고 이름을 haproxy.nomad.hcl로 지어요. 이 HAProxy 인스턴스는 배포된 웹 애플리케이션 인스턴스 전반에 요청을 분산해요.

이 작업 명세는 HAProxy 로드 밸런서에 8080의 정적 포트를 사용해요. 이 덕분에 클러스터 안 어디에서든 haproxy.service.consul:8080을 조회해 데모 웹 애플리케이션에 도달할 수 있어요.

haproxy.nomad.hcl

job "haproxy" {
  region      = "global"
  datacenters = ["dc1"]
  type        = "service"

  group "haproxy" {
    count = 1

    network {
      port "http" {
        static = 8080
      }

      port "haproxy_ui" {
        static = 1936
      }
    }

    service {
      name = "haproxy"

      check {
        name     = "alive"
        type     = "tcp"
        port     = "http"
        interval = "10s"
        timeout  = "2s"
      }
    }

    task "haproxy" {
      driver = "docker"

      config {
        image        = "haproxy:3.3.1"
        network_mode = "host"

        volumes = [
          "local/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg",
        ]
      }

      template {
        data = <<EOF
defaults
   mode http

frontend stats
   bind *:1936
   stats uri /
   stats show-legends
   no log

frontend http_front
   bind *:8080
   default_backend http_back

backend http_back
    balance roundrobin
    server-template mywebapp 10 _demo-webapp._tcp.service.consul resolvers consul resolve-opts allow-dup-ip resolve-prefer ipv4 check

resolvers consul
    nameserver consul 127.0.0.1:8600
    accepted_payload_size 8192
    hold valid 5s
EOF

        destination = "local/haproxy.cfg"
      }

      resources {
        cpu    = 200
        memory = 128
      }
    }
  }
}

다음 HAProxy backend 구성을 주목해요.

  • balance는 roundrobin이므로 HAProxy는 사용 가능한 서비스 전반에 순서대로 로드 밸런싱해요.
  • server-template 옵션은 Consul 서비스 등록이 HAProxy의 백엔드 서버 풀을 구성할 수 있게 해요. 이 때문에 백엔드 서버의 IP 주소를 명시적으로 추가할 필요가 없어요.
  • 서버 템플릿 이름은 mywebapp이에요. 이 템플릿 이름은 Consul에 등록된 서비스 이름과 연결되지 않아요.
  • _demo-webapp._tcp.service.consul 파라미터는 HAProxy가 백엔드 서비스 demo-webapp.service.consul의 DNS SRV 레코드를 사용해 사용 가능한 인스턴스를 발견하도록 해요.

작업 명세에 HAProxy 구성용 인라인 템플릿이 포함되어 있지만, task.artifact 스탠자와 함께 task.template 스탠자를 사용해 S3 버킷 같은 원격 소스에서 입력 템플릿을 다운로드할 수도 있어요. 자세한 내용은 template 예시를 참고해요.

nomad run 명령으로 HAProxy 작업을 배포해요.

$ nomad run haproxy.nomad.hcl
==> Monitoring evaluation "937b1a2d"
    Evaluation triggered by job "haproxy"
    Evaluation within deployment: "e8214434"
    Allocation "53145b8b" created: node "d16a11fb", group "haproxy"
    Evaluation status changed: "pending" -> "complete"
==> Evaluation "937b1a2d" finished with status "complete"

HAProxy 통계 페이지 확인

http://<your-haproxy-address>:1936에서 HAProxy의 통계 및 모니터링 페이지를 방문할 수 있어요. 이 페이지로 설정을 확인하고 기본 모니터링을 수행해요.

서비스에 대해 사전 프로비저닝된 로드 밸런서 백엔드 슬롯이 열 개 있지만 그 중 세 개만 사용 중이에요. 이는 현재 작업의 세 할당과 일치해요.

로드 밸런서를 통한 요청

HAProxy 로드 밸런서에 접근하면 다음 예시와 유사한 응답을 볼 수 있어야 해요. 클러스터 안의 노드에서 curl 명령을 실행해요.

$ curl haproxy.service.consul:8080
Welcome! You are on node 172.31.54.242:20124

HAProxy가 세 개의 Nomad 클라이언트에 걸쳐 있는 데모 웹 애플리케이션의 배포 인스턴스 중 하나로 요청을 전달한 것을 주목해요. 출력은 데모 웹 애플리케이션 호스트의 IP 주소를 보여줘요. 요청을 반복하면 어떤 백엔드 웹 서버 인스턴스가 요청을 받았는지에 따라 IP 주소가 바뀌어요.

클러스터 외부에서 HAProxy에 접근

클러스터 외부에서 HAProxy에 접근하려면 클라우드 환경에서 클라이언트의 활성 포트 8080에 매핑되는 로드 밸런서를 설정할 수 있어요. 그러면 요청을 외부 로드 밸런서로 직접 보낼 수 있어요.

Nomad 클라이언트 노드는 시간이 지나며 바뀔 수 있으므로 최종 사용자에게 서비스 접근을 위한 단일 엔드포인트를 제공하는 것이 중요해요. AWS Elastic Load Balancing (ELB), Azure Load Balancer, Google Cloud Load Balancing 같은 클라우드 제공자의 로드 밸런서 뒤에 Nomad 클라이언트 노드를 배치해 이를 수행할 수 있어요.

기본 단계는 로드 밸런서를 만들고, 클라이언트 노드를 등록하고, 리스너를 만들고, 건강 검사를 구성하는 것을 포함해요. 이 가이드를 따랐다면 HAProxy에 대한 인그레스 경로를 만들어야 해요.

클라우드 제공자의 로드 밸런서를 구성한 후에는 클라우드 로드 밸런서 DNS 이름에 접근할 수 있어야 해요.

  • 포트 8080에서 데모 웹 애플리케이션 관찰
  • 포트 1936에서 HAProxy 웹 UI 접근

더 알아보기 (Learn more)