본문 바로가기
WIKI 기술 지식 베이스

Traefik HTTP Services 문서

원문 보기 위키 갱신

출처: Traefik HTTP Services 문서 (HTTP Services Documentation)

본문

Service

Traefik 서비스는 들어오는 트래픽을 백엔드 서버들에 어떻게 분산할지를 정의해요. 이 페이지는 두 가지 주요 개념을 다뤄요:

  • Service Load Balancer: 다양한 로드 밸런싱 전략으로 백엔드 서버에 트래픽을 라우팅해요

  • 고급 서비스 유형: 가중치 분산, 미러링 또는 페일오버를 위해 여러 서비스를 함께 조합해요

Service Load Balancer

loadBalancer 서비스 유형은 들어오는 요청을 백엔드 서버 목록으로 라우팅해요. 각 서비스는 트래픽을 전달할 서버가 하나뿐이라 해도 로드 밸런서를 갖고 있어요.

로드 밸런서는 서버 간 트래픽을 분산하는 여러 전략을 지원해요:

  • wrr (Weighted Round Robin) - 기본 전략. 요청을 서버들에 순환하며 고르게 분산해요

  • p2c (Power of Two Choices) - 무작위 서버 두 개를 선택해 활성 연결이 더 적은 쪽으로 라우팅해요

  • hrw (Highest Random Weight) - 세션 어피니티를 위해 클라이언트 IP 기반의 일관된 해싱을 사용해요

  • leasttime - 응답 시간이 가장 낮고 활성 연결이 가장 적은 서버로 라우팅해요

설정 예시

구조화 (YAML)

http:
  services:
    my-service:
      loadBalancer:
        strategy: "wrr"
        servers:
          - url: "http://private-ip-server-1/"
            weight: 2
            preservePath: true
        sticky:
          cookie:
            name: "sticky-cookie"
        healthcheck:
          path: "/health"
          interval: "10s"
          timeout: "3s"
        passiveHealthCheck:
          failureWindow: "3s"
          maxFailedAttempts: 3
        passHostHeader: true
        serversTransport: "customTransport@file"
        responseForwarding:
          flushInterval: "150ms"

구조화 (TOML)

[http.services]
  [http.services.my-service.loadBalancer]
    strategy = "wrr"
    [[http.services.my-service.loadBalancer.servers]]
      url = "http://private-ip-server-1/"

    [http.services.my-service.loadBalancer.sticky.cookie]
      name = "sticky-cookie"

    [http.services.my-service.loadBalancer.healthcheck]
      path = "/health"
      interval = "10s"
      timeout = "3s"

    [http.services.my-service.loadBalancer.passiveHealthCheck]
      failureWindow = "3s"
      maxFailedAttempts = 3

    passHostHeader = true
    serversTransport = "customTransport@file"

    [http.services.my-service.loadBalancer.responseForwarding]
      flushInterval = "150ms"

Labels

labels:
  - "traefik.http.services.my-service.loadBalancer.strategy=wrr"
  - "traefik.http.services.my-service.loadBalancer.servers[0].url=http://private-ip-server-1/"
  - "traefik.http.services.my-service.loadBalancer.servers[0].weight=2"
  - "traefik.http.services.my-service.loadBalancer.servers[0].preservePath=true"
  - "traefik.http.services.my-service.loadBalancer.sticky.cookie.name=sticky-cookie"
  - "traefik.http.services.my-service.loadBalancer.healthcheck.path=/health"
  - "traefik.http.services.my-service.loadBalancer.healthcheck.interval=10s"
  - "traefik.http.services.my-service.loadBalancer.healthcheck.timeout=3s"
  - "traefik.http.services.my-service.loadBalancer.passiveHealthCheck.failureWindow=3s"
  - "traefik.http.services.my-service.loadBalancer.passiveHealthCheck.maxFailedAttempts=3"
  - "traefik.http.services.my-service.loadBalancer.passHostHeader=true"
  - "traefik.http.services.my-service.loadBalancer.serversTransport=customTransport@file"
  - "traefik.http.services.my-service.loadBalancer.responseForwarding.flushInterval=150ms"

Tags

{
  "Tags": [
    "traefik.http.services.my-service.loadBalancer.strategy=wrr",
    "traefik.http.services.my-service.loadBalancer.servers[0].url=http://private-ip-server-1/",
    "traefik.http.services.my-service.loadBalancer.servers[0].weight=2",
    "traefik.http.services.my-service.loadBalancer.servers[0].preservePath=true",
    "traefik.http.services.my-service.loadBalancer.sticky.cookie.name=sticky-cookie",
    "traefik.http.services.my-service.loadBalancer.healthcheck.path=/health",
    "traefik.http.services.my-service.loadBalancer.healthcheck.interval=10s",
    "traefik.http.services.my-service.loadBalancer.healthcheck.timeout=3s",
    "traefik.http.services.my-service.loadBalancer.passiveHealthCheck.failureWindow=3s",
    "traefik.http.services.my-service.loadBalancer.passiveHealthCheck.maxFailedAttempts=3",
    "traefik.http.services.my-service.loadBalancer.passHostHeader=true",
    "traefik.http.services.my-service.loadBalancer.serversTransport=customTransport@file",
    "traefik.http.services.my-service.loadBalancer.responseForwarding.flushInterval=150ms"
  ]
}

설정 옵션

| 필드 | 설명 | 필수 | | servers | 서비스의 개별 백엔드 인스턴스를 나타내요 | 예 | | strategy | 서버 간 트래픽 분산을 위한 로드 밸런싱 전략이에요. 유효한 값: wrr (기본), p2c, hrw, leasttime. | 아니요 | | sticky | 초기 응답에 Set-Cookie 헤더를 설정해 어떤 서버가 첫 응답을 처리했는지 클라이언트에게 알려줘요. | 아니요 | | healthcheck | 건강하지 않은 서버를 로드 밸런싱 순환에서 제거하도록 헬스 체크를 구성해요. | 아니요 | | passiveHealthCheck | 건강하지 않은 서버를 로드 밸런싱 순환에서 제거하도록 수동 헬스 체크를 구성해요. | 아니요 | | passHostHeader | 클라이언트 Host 헤더를 서버로 전달할 수 있게 해요. 기본적으로 passHostHeader는 true예요. | 아니요 | | serversTransport | Traefik과 서버 사이의 통신을 위한 HTTP ServersTransport 구성을 참조할 수 있게 해요. serversTransport가 지정되지 않으면 default@internal이 사용돼요. | 아니요 | | responseForwarding | Traefik이 백엔드 서버의 응답을 클라이언트로 전달하는 방식을 구성해요. | 아니요 | | responseForwarding.flushInterval | 응답 본문을 복사하는 동안 클라이언트로의 flush 사이 간격을 지정해요. 밀리초 단위의 기간이며 기본값은 100ms예요. 음수 값은 클라이언트로의 각 쓰기 직후 flush한다는 뜻이에요. FlushInterval은 ReverseProxy가 응답을 스트리밍 응답으로 인식하면 무시돼요. 그런 응답의 경우 쓰기가 클라이언트로 즉시 flush돼요. | 아니요 |

Servers

Servers는 서비스의 개별 백엔드 인스턴스를 나타내요. 서비스 loadBalancer의 servers 옵션을 사용하면 들어오는 요청을 처리할 인스턴스 목록을 구성할 수 있어요.

설정 옵션 | 필드 | 설명 | 필수 | | url | 특정 인스턴스를 가리켜요. | File 프로바이더는 예, Docker 프로바이더는 아니요 | | weight | 서버에서 가중 로드 밸런싱을 할 수 있게 해요. | 아니요 | | preservePath | URL 경로를 보존할 수 있게 해요. | 아니요 |

로드 밸런싱 전략

로드 밸런서의 strategy 옵션은 백엔드 서버 간 트래픽이 어떻게 분산되는지 결정해요.

Weighted Round Robin (wrr)

기본 전략이에요. 서버 가중치를 존중하며 모든 서버에 걸쳐 요청을 순환하며 고르게 분산해요. 이 전략은 Earliest Deadline First (EDF) 스케줄링을 사용해 가중 라운드로빈 동작을 제공해요.

WRR 로드 밸런싱 -- File 프로바이더 사용

구조화 (YAML)

## 라우팅 구성
http:
  services:
    my-service:
      loadBalancer:
        strategy: "wrr"
        servers:
        - url: "http://private-ip-server-1/"
          weight: 3
        - url: "http://private-ip-server-2/"
          weight: 1

구조화 (TOML)

## 라우팅 구성
[http.services]
  [http.services.my-service.loadBalancer]
    strategy = "wrr"
    [[http.services.my-service.loadBalancer.servers]]
      url = "http://private-ip-server-1/"
      weight = 3
    [[http.services.my-service.loadBalancer.servers]]
      url = "http://private-ip-server-2/"
      weight = 1

Power of Two Choices (p2c)

무작위로 서버 두 개를 선택해 활성 연결이 가장 적은 쪽으로 요청을 라우팅해요. 이 알고리즘은 서버들의 응답 시간이 각기 다를 때 더 나은 부하 분산을 제공해요.

P2C 로드 밸런싱 -- File 프로바이더 사용

구조화 (YAML)

## 라우팅 구성
http:
  services:
    my-service:
      loadBalancer:
        strategy: "p2c"
        servers:
        - url: "http://private-ip-server-1/"
        - url: "http://private-ip-server-2/"
        - url: "http://private-ip-server-3/"

구조화 (TOML)

## 라우팅 구성
[http.services]
  [http.services.my-service.loadBalancer]
    strategy = "p2c"
    [[http.services.my-service.loadBalancer.servers]]
      url = "http://private-ip-server-1/"
    [[http.services.my-service.loadBalancer.servers]]
      url = "http://private-ip-server-2/"       
    [[http.services.my-service.loadBalancer.servers]]
      url = "http://private-ip-server-3/"

Highest Random Weight (hrw)

클라이언트의 IP 주소를 기반으로 일관된 해싱(Rendezvous Hashing)을 사용해 같은 클라이언트의 요청이 일관되게 같은 서버로 라우팅되도록 보장해요. 이 방식은 sticky 쿠키 없이도 세션 어피니티를 제공해요.

이 알고리즘은 클라이언트 소스 IP의 해시와 백엔드 식별자를 결합해 각 사용 가능한 백엔드의 점수를 계산하고, 가장 높은 점수의 백엔드에 클라이언트를 배정해요.

HRW 로드 밸런싱 -- File 프로바이더 사용

구조화 (YAML)

## 라우팅 구성
http:
  services:
    my-service:
      loadBalancer:
        strategy: "hrw"
        servers:
        - url: "http://private-ip-server-1/"
        - url: "http://private-ip-server-2/"
        - url: "http://private-ip-server-3/"

구조화 (TOML)

## 라우팅 구성
[http.services]
  [http.services.my-service.loadBalancer]
    strategy = "hrw"
    [[http.services.my-service.loadBalancer.servers]]
      url = "http://private-ip-server-1/"
    [[http.services.my-service.loadBalancer.servers]]
      url = "http://private-ip-server-2/"       
    [[http.services.my-service.loadBalancer.servers]]
      url = "http://private-ip-server-3/"

Least-Time

평균 응답 시간(Time To First Byte - TTFB)이 가장 낮고, 활성 연결이 가장 적으며, 서버 용량으로 가중치가 적용된 서버를 선택해요. 이 전략은 서버들의 성능 특성, 하드웨어 성능 또는 네트워크 지연 시간이 각기 다른 이기종(heterogeneous) 백엔드 환경에 이상적이에요.

이 알고리즘은 각 백엔드의 응답 시간을 지속적으로 측정하고 활성 연결 수를 추적해요. 요청을 라우팅할 때 각 건강한 서버의 점수를 공식 (avg_response_time × (1 + active_connections)) / weight으로 계산해요. 가장 낮은 점수의 서버가 요청을 받아요. 여러 서버의 점수가 동일하면 tie-breaker로 Earliest Deadline First (EDF) 스케줄링을 사용한 Weighted Round Robin (WRR)이 사용돼요.

Least-Time 로드 밸런싱 -- File 프로바이더 사용

구조화 (YAML)

## 라우팅 구성
http:
  services:
    my-service:
      loadBalancer:
        strategy: "leasttime"
        servers:
        - url: "http://private-ip-server-1/"
        - url: "http://private-ip-server-2/"
        - url: "http://private-ip-server-3/"

구조화 (TOML)

## 라우팅 구성
[http.services]
  [http.services.my-service.loadBalancer]
    strategy = "leasttime"
    [[http.services.my-service.loadBalancer.servers]]
      url = "http://private-ip-server-1/"
    [[http.services.my-service.loadBalancer.servers]]
      url = "http://private-ip-server-2/"
    [[http.services.my-service.loadBalancer.servers]]
      url = "http://private-ip-server-3/"

헬스 체크 (Health Check)

healthcheck 옵션은 건강하지 않은 서버를 로드 밸런싱 순환에서 제거하도록 헬스 체크를 구성해요. Traefik은 HTTP(s) 서버가 (매 interval마다 수행되는) 헬스 체크 요청에 2XX에서 3XX 사이의 상태 코드, 또는 구성된 상태와 일치하는 상태 코드를 반환하는 한 건강한 것으로 간주해요. gRPC 서버의 경우 gRPC 헬스 체크 v1 요청에 SERVING을 반환하는 한 건강한 것으로 간주해요.

상태 변경(예: 이 서비스의 모든 서버가 다운됨)을 위로 전파하려면 이 서비스의 부모에도 HealthCheck가 활성화되어 있어야 해요.

헬스 체크 메커니즘에 사용 가능한 옵션은 아래와 같아요:

| 필드 | 설명 | 기본값 | 필수 | | path | 헬스 체크 엔드포인트의 서버 URL 경로를 정의해요. 구성된 경로는 상대 URL이어야 해요. | "" | 예 | | scheme | 헬스 체크 엔드포인트의 서버 URL 스킴을 대체해요. | | 아니요 | | mode | grpc로 정의하면 gRPC 헬스 체크 프로토콜을 사용해 서버를 검사해요. | http | 아니요 | | hostname | 헬스 체크 요청의 Host 헤더에 있는 hostname 값을 정의해요. | "" | 아니요 | | port | 헬스 체크 엔드포인트의 서버 URL 포트를 대체해요. | | 아니요 | | interval | 건강한 대상에 대한 헬스 체크 호출 빈도를 정의해요. | 30s | 아니요 | | unhealthyInterval | 건강하지 않은 대상에 대한 헬스 체크 호출 빈도를 정의해요. 정의되지 않으면 interval 값으로 기본 설정돼요. | - | 아니요 | | timeout | Traefik이 서버를 건강하지 않은 것으로 간주하기 전에 헬스 체크 요청을 기다리는 최대 시간을 정의해요. | 5s | 아니요 | | headers | 헬스 체크 엔드포인트로 보낼 커스텀 헤더를 정의해요. | | 아니요 | | followRedirects | 헬스 체크 호출 중 리다이렉트를 따를지 여부를 정의해요. | true | 아니요 | | method | 엔드포인트에 연결하는 동안 사용될 HTTP 메서드를 정의해요. | GET | 아니요 | | status | 헬스 체크 요청에 대한 응답의 예상 HTTP 상태 코드를 정의해요. | | 아니요 |

Sticky 세션

Sticky 세션이 활성화되면 초기 응답에 Set-Cookie 헤더가 설정되어 클라이언트가 어떤 서버가 첫 응답을 처리했는지 알게 해요. 이후 요청에서 같은 서버와 세션을 유지하려면 클라이언트는 설정된 값을 담은 쿠키를 보내야 해요.

여러 수준에서의 Stickiness

로드 밸런서를 체인하거나 혼합할 때(예: 서버들의 로드 밸런서가 서비스들의 로드 밸런서의 "자식" 중 하나인 경우), stickiness가 끝까지 작동하려면 모든 필요한 수준에서 옵션을 지정해야 해요. 즉 클라이언트는 sticky 수준 수만큼의 key/value 쌍을 담은 쿠키를 보내야 해요.

Stickiness와 건강하지 않은 서버

쿠키에 지정된 서버가 건강하지 않게 되면 요청은 새 서버로 전달돼요 (그리고 쿠키는 새 서버를 추적해요).

쿠키 이름

기본 쿠키 이름은 sha1의 약어예요 (예: _1d52e).

MaxAge

기본적으로 어피니티 쿠키는 MaxAge 옵션이 0으로 설정되어 있어 절대 만료되지 않아요.

이 옵션은 쿠키가 만료될 때까지의 시간(초)을 나타내요. 음수로 설정하면 쿠키가 즉시 만료돼요.

Secure, HTTPOnly, SameSite 플래그

기본적으로 어피니티 쿠키는 이러한 플래그 없이 생성돼요. 하지만 구성으로 바꿀 수 있어요.

SameSite는 none, lax, strict 또는 빈 값일 수 있어요. 값은 대소문자를 구분하지 않아요.

Domain

쿠키의 Domain 속성은 쿠키가 유효한 도메인을 지정해요.

Domain 속성을 설정하면 쿠키가 하위 도메인 간에 공유될 수 있어요 (예를 들어 example.com에 설정된 쿠키는 www.example.com, api.example.com 등에서 접근 가능해요). 이는 sticky 세션이 여러 하위 도메인에 걸쳐 있을 때 특히 유용하며, 클라이언트가 인프라의 다른 부분과 상호작용할 때도 세션이 유지되도록 보장해요.

Stickiness 추가하기 -- File 프로바이더 사용

구조화 (YAML)

## 라우팅 구성
http:
  services:
    my-service:
      loadBalancer:
        sticky:
         cookie: {}

구조화 (TOML)

## 라우팅 구성
[http.services]
  [http.services.my-service]
    [http.services.my-service.loadBalancer.sticky.cookie]

커스텀 옵션으로 Stickiness 추가하기 -- File 프로바이더 사용

구조화 (YAML)

## 라우팅 구성
http:
  services:
    my-service:
      loadBalancer:
        sticky:
          cookie:
            name: my_sticky_cookie_name
            secure: true
            domain: mysite.site
            httpOnly: true

구조화 (TOML)

## 라우팅 구성
[http.services]
  [http.services.my-service]
    [http.services.my-service.loadBalancer.sticky.cookie]
      name = "my_sticky_cookie_name"
      secure = true
      httpOnly = true
      domain = "mysite.site"
      sameSite = "none"

필요한 모든 수준에 Stickiness 설정 -- File 프로바이더 사용

구조화 (YAML)

## 라우팅 구성
http:
  services:
    wrr1:
      weighted:
        sticky:
          cookie:
            name: lvl1
        services:
          - name: whoami1
            weight: 1
          - name: whoami2
            weight: 1

    whoami1:
      loadBalancer:
        sticky:
          cookie:
            name: lvl2
        servers:
          - url: http://127.0.0.1:8081
          - url: http://127.0.0.1:8082

    whoami2:
      loadBalancer:
        sticky:
          cookie:
            name: lvl2
        servers:
          - url: http://127.0.0.1:8083
          - url: http://127.0.0.1:8084

구조화 (TOML)

## 라우팅 구성
[http.services]
  [http.services.wrr1]
    [http.services.wrr1.weighted.sticky.cookie]
      name = "lvl1"
    [[http.services.wrr1.weighted.services]]
      name = "whoami1"
      weight = 1
    [[http.services.wrr1.weighted.services]]
      name = "whoami2"
      weight = 1

  [http.services.whoami1]
    [http.services.whoami1.loadBalancer]
      [http.services.whoami1.loadBalancer.sticky.cookie]
        name = "lvl2"
      [[http.services.whoami1.loadBalancer.servers]]
        url = "http://127.0.0.1:8081"
      [[http.services.whoami1.loadBalancer.servers]]
        url = "http://127.0.0.1:8082"

  [http.services.whoami2]
    [http.services.whoami2.loadBalancer]
      [http.services.whoami2.loadBalancer.sticky.cookie]
        name = "lvl2"
      [[http.services.whoami2.loadBalancer.servers]]
        url = "http://127.0.0.1:8083"
      [[http.services.whoami2.loadBalancer.servers]]
        url = "http://127.0.0.1:8084"

같은 서버로 세션을 유지하려면 클라이언트는 각 요청에 대해 쿠키 안에 두 수준을 지정해야 해요. 예를 들어 curl로는:

curl -b "lvl1=whoami1; lvl2=http://127.0.0.1:8081" http://localhost:8000

수동 헬스 체크 (Passive Health Check)

passiveHealthCheck 옵션은 건강하지 않은 서버를 로드 밸런싱 순환에서 제거하도록 수동 헬스 체크를 구성해요.

수동 헬스 체크는 서버 건강을 평가하기 위해 실제 트래픽에 의존해요. Traefik은 평소대로 요청을 전달하고 각 응답이나 타임아웃을 평가하며, 요청이 실패할 때마다 실패 카운터를 증가시켜요. 지정된 시간 창 안에서 연속된 실패 수가 구성된 임계값을 초과하면, Traefik은 해당 서버가 복구될 때까지 그 서버로의 트래픽 라우팅을 자동으로 중단해요. 서버는 구성된 실패 창(failure window)이 지나면 다시 건강한 것으로 간주돼요.

수동 헬스 체크 메커니즘에 사용 가능한 옵션은 아래와 같아요:

| 필드 | 설명 | 기본값 | 필수 | | failureWindow | 서버가 건강하지 않은 것으로 표시되기 위해 실패한 시도가 발생해야 하는 시간 창을 정의해요. 또한 서버가 얼마나 오래 건강하지 않은 것으로 간주될지도 정의해요. | 10s | 아니요 | | maxFailedAttempts | 서버를 건강하지 않은 것으로 표시하기 전에 실패 창 안에서 허용되는 연속 실패 횟수를 정의해요. | 1 | 아니요 |

Middlewares

각 HTTP 서비스에 미들웨어 목록을 연결할 수 있어요. 미들웨어는 어떤 라우터가 요청을 전달하든, 서비스가 처리하는 모든 요청에 적용돼요.

미들웨어 실행 순서

라우터와 서비스 양쪽 모두에 미들웨어가 구성되면, 라우터 미들웨어가 먼저 적용되고 그 다음 서비스 미들웨어가 적용돼요. 즉 요청은 서비스 미들웨어에 도달하기 전에 라우터 미들웨어를 통과해요.

지원되는 프로바이더

서비스 수준 미들웨어는 File, Docker, Swarm, Kubernetes IngressRoute, Kubernetes Ingress, Kubernetes Gateway API 프로바이더로 구성할 수 있어요.

서비스에 미들웨어 연결 -- File 프로바이더 사용

구조화 (YAML)

## 동적 구성
http:
  services:
    my-service:
      middlewares:
        - add-header
      loadBalancer:
        servers:
          - url: "http://127.0.0.1:8080"

  middlewares:
    add-header:
      headers:
        customRequestHeaders:
          X-Custom-Header: "service-middleware"

구조화 (TOML)

## 동적 구성
[http.services]
  [http.services.my-service]
    middlewares = ["add-header"]
    [http.services.my-service.loadBalancer]
      [[http.services.my-service.loadBalancer.servers]]
        url = "http://127.0.0.1:8080"

[http.middlewares]
  [http.middlewares.add-header.headers]
    [http.middlewares.add-header.headers.customRequestHeaders]
      X-Custom-Header = "service-middleware"

서비스에 미들웨어 연결 -- Docker Labels 사용

labels:
  # 미들웨어 정의
  - "traefik.http.middlewares.add-header.headers.customRequestHeaders.X-Custom-Header=service-middleware"
  # 서비스에 미들웨어 연결 (loadBalancer 수준이 아닌 서비스 수준에서)
  - "traefik.http.services.my-service.middlewares=add-header"
  # 서비스 구성
  - "traefik.http.services.my-service.loadbalancer.server.port=8080"

고급 서비스 유형

고급 서비스 유형을 사용하면 가중 분산, 일관된 해싱, 미러링 또는 페일오버 시나리오를 위해 여러 서비스를 함께 조합할 수 있어요. 이것들은 로드 밸런싱 전략과는 구별돼요. 서버 수준이 아닌 서비스 수준에서 동작해요.

핵심 차이점

  • 로드 밸런싱 전략 (wrr, p2c, hrw, leasttime): 단일 loadBalancer 서비스 내에서 서버 간 트래픽을 분산해요

  • 고급 서비스 유형 (weighted, highestRandomWeight, mirroring, failover): 여러 서비스 간 트래픽을 분산하거나 관리해요

Weighted Round Robin

weighted 서비스 유형은 가중치를 기반으로 여러 서비스 간에 요청을 로드 밸런싱해요. 이것은 wrr 전략과는 달라요. 서버가 아닌 서비스에 대해 동작해요.

지원되는 프로바이더

이 서비스 유형은 현재 File 프로바이더 또는 IngressRoute로 정의할 수 있어요.

구조화 (YAML)

## 라우팅 구성
http:
  services:
    app:
      weighted:
        services:
        - name: appv1
          weight: 3
        - name: appv2
          weight: 1

    appv1:
      loadBalancer:
        servers:
        - url: "http://private-ip-server-1/"

    appv2:
      loadBalancer:
        servers:
        - url: "http://private-ip-server-2/"

구조화 (TOML)

## 라우팅 구성
[http.services]
  [http.services.app]
    [[http.services.app.weighted.services]]
      name = "appv1"
      weight = 3
    [[http.services.app.weighted.services]]
      name = "appv2"
      weight = 1

  [http.services.appv1]
    [http.services.appv1.loadBalancer]
      [[http.services.appv1.loadBalancer.servers]]
        url = "http://private-ip-server-1/"

  [http.services.appv2]
    [http.services.appv2.loadBalancer]
      [[http.services.appv2.loadBalancer.servers]]
        url = "http://private-ip-server-2/"

헬스 체크 (Health Check)

HealthCheck는 이 서비스에 대한 자동 자가 헬스 체크를 활성화해요. 즉 자식 중 하나가 다운으로 보고되면 이 서비스가 그것을 인지하고, 로드 밸런싱 알고리즘을 실행할 때 이를 고려해요 (즉 다운된 자식을 무시해요). 또한 이 서비스의 부모도 HealthCheck가 활성화되어 있으면, 이 서비스는 부모에게 상태 변경을 보고해요.

동작

주어진 서비스에 HealthCheck가 활성화되어 있는데 그 하위 중 어느 하나라도 활성화되어 있지 않으면, 서비스 생성이 실패해요.

Weighted 서비스의 HealthCheck는 현재 File 프로바이더로만 정의할 수 있어요.

구조화 (YAML)

## 라우팅 구성
http:
  services:
    app:
      weighted:
        healthCheck: {}
        services:
        - name: appv1
          weight: 3
        - name: appv2
          weight: 1

    appv1:
      loadBalancer:
        healthCheck:
          path: /status
          interval: 10s
          timeout: 3s
        servers:
        - url: "http://private-ip-server-1/"

    appv2:
      loadBalancer:
        healthCheck:
          path: /status
          interval: 10s
          timeout: 3s
        servers:
        - url: "http://private-ip-server-2/"

구조화 (TOML)

## 라우팅 구성
[http.services]
  [http.services.app]
    [http.services.app.weighted.healthCheck]
    [[http.services.app.weighted.services]]
      name = "appv1"
      weight = 3
    [[http.services.app.weighted.services]]
      name = "appv2"
      weight = 1

  [http.services.appv1]
    [http.services.appv1.loadBalancer]
      [http.services.appv1.loadBalancer.healthCheck]
        path = "/health"
        interval = "10s"
        timeout = "3s"
      [[http.services.appv1.loadBalancer.servers]]
        url = "http://private-ip-server-1/"

  [http.services.appv2]
    [http.services.appv2.loadBalancer]
      [http.services.appv2.loadBalancer.healthCheck]
        path = "/health"
        interval = "10s"
        timeout = "3s"
      [[http.services.appv2.loadBalancer.servers]]
        url = "http://private-ip-server-2/"

Highest Random Weight

highestRandomWeight 서비스 유형은 일관된 해싱(Rendezvous Hashing)을 사용해 여러 서비스 간에 요청을 로드 밸런싱해요. 같은 클라이언트 IP의 요청이 일관되게 같은 서비스로 라우팅되도록 보장해요.

이것은 loadBalancer의 hrw 전략과는 달라요. 서버가 아닌 서비스에 대해 동작해요.

지원되는 프로바이더

이 서비스 유형은 현재 File 프로바이더로만 정의할 수 있어요.

구조화 (YAML)

## 라우팅 구성
http:
  services:
    app:
      highestRandomWeight:
        services:
        - name: appv1
          weight: 1
        - name: appv2
          weight: 1

    appv1:
      loadBalancer:
        servers:
        - url: "http://private-ip-server-1/"

    appv2:
      loadBalancer:
        servers:
        - url: "http://private-ip-server-2/"

구조화 (TOML)

## 라우팅 구성
[http.services]
  [http.services.app]
    [[http.services.app.highestRandomWeight.services]]
      name = "appv1"
      weight = 1
    [[http.services.app.highestRandomWeight.services]]
      name = "appv2"
      weight = 1

  [http.services.appv1]
    [http.services.appv1.loadBalancer]
      [[http.services.appv1.loadBalancer.servers]]
        url = "http://private-ip-server-1/"

  [http.services.appv2]
    [http.services.appv2.loadBalancer]
      [[http.services.appv2.loadBalancer.servers]]
        url = "http://private-ip-server-2/"

헬스 체크 (Health Check)

HealthCheck는 Weighted Round Robin 서비스 유형과 유사하게 이 서비스에 대한 자동 자가 헬스 체크를 활성화해요.

동작

주어진 서비스에 HealthCheck가 활성화되어 있는데 그 하위 중 어느 하나라도 활성화되어 있지 않으면, 서비스 생성이 실패해요.

Highest Random Weight 서비스의 HealthCheck는 현재 File 프로바이더로만 정의할 수 있어요.

구조화 (YAML)

## 라우팅 구성
http:
  services:
    app:
      highestRandomWeight:
        healthCheck: {}
        services:
        - name: appv1
          weight: 1
        - name: appv2
          weight: 1

    appv1:
      loadBalancer:
        healthCheck:
          path: /status
          interval: 10s
          timeout: 3s
        servers:
        - url: "http://private-ip-server-1/"

    appv2:
      loadBalancer:
        healthCheck:
          path: /status
          interval: 10s
          timeout: 3s
        servers:
        - url: "http://private-ip-server-2/"

구조화 (TOML)

## 라우팅 구성
[http.services]
  [http.services.app]
    [http.services.app.highestRandomWeight.healthCheck]
    [[http.services.app.highestRandomWeight.services]]
      name = "appv1"
      weight = 1
    [[http.services.app.highestRandomWeight.services]]
      name = "appv2"
      weight = 1

  [http.services.appv1]
    [http.services.appv1.loadBalancer]
      [http.services.appv1.loadBalancer.healthCheck]
        path = "/health"
        interval = "10s"
        timeout = "3s"
      [[http.services.appv1.loadBalancer.servers]]
        url = "http://private-ip-server-1/"

  [http.services.appv2]
    [http.services.appv2.loadBalancer]
      [http.services.appv2.loadBalancer.healthCheck]
        path = "/health"
        interval = "10s"
        timeout = "3s"
      [[http.services.appv2.loadBalancer.servers]]
        url = "http://private-ip-server-2/"

Mirroring

mirroring 서비스 유형은 서비스로 보내진 요청을 다른 서비스로 미러링해요. 기본적으로 전체 요청이 미러링되는 동안 메모리에 버퍼링된다는 점을 참고하세요. 이 동작을 수정하는 방법은 아래 예시의 maxBodySize 옵션을 참고하세요. mirrorBody 옵션을 false로 설정해 요청 본문을 생략할 수도 있어요.

percent의 기본 동작

mirror 서비스를 구성할 때 percent 필드가 설정되지 않으면 기본값은 0이며, 이는 미러로 어떤 트래픽도 보내지 않는다는 뜻이에요.

지원되는 프로바이더

이 서비스 유형은 현재 File 프로바이더 또는 IngressRoute로 정의할 수 있어요.

구조화 (YAML)

## 라우팅 구성
http:
  services:
    mirrored-api:
      mirroring:
        service: appv1
        # mirrorBody는 요청 본문을 미러링할지 여부를 정의해요.
        # 기본값은 true예요.
        mirrorBody: false
        # maxBodySize는 요청 본문에 허용되는 최대 크기예요.
        # 본문이 더 크면 요청은 미러링되지 않아요.
        # 기본값은 -1이며, 크기 제한이 없다는 뜻이에요.
        maxBodySize: 1024
        mirrors:
        - name: appv2
          # Percent는 미러링되어야 하는 요청의 백분율을 정의해요.
          # 기본값은 0이며, 미러로 어떤 트래픽도 보내지 않는다는 뜻이에요.
          percent: 10

    appv1:
      loadBalancer:
        servers:
        - url: "http://private-ip-server-1/"

    appv2:
      loadBalancer:
        servers:
        - url: "http://private-ip-server-2/

구조화 (TOML)

## 라우팅 구성
[http.services]
  [http.services.mirrored-api]
    [http.services.mirrored-api.mirroring]
      service = "appv1"
      # maxBodySize는 요청 본문에 허용되는 최대 크기(바이트)예요.
      # 본문이 더 크면 요청은 미러링되지 않아요.
      # 기본값은 -1이며, 크기 제한이 없다는 뜻이에요.
      maxBodySize = 1024
      # mirrorBody는 요청 본문을 미러링할지 여부를 정의해요.
      # 기본값은 true예요.
      mirrorBody = false
    [[http.services.mirrored-api.mirroring.mirrors]]
      name = "appv2"
      percent = 10

  [http.services.appv1]
    [http.services.appv1.loadBalancer]
      [[http.services.appv1.loadBalancer.servers]]
        url = "http://private-ip-server-1/"

  [http.services.appv2]
    [http.services.appv2.loadBalancer]
      [[http.services.appv2.loadBalancer.servers]]
        url = "http://private-ip-server-2/"

헬스 체크 (Health Check)

HealthCheck는 이 서비스에 대한 자동 자가 헬스 체크를 활성화해요. 즉 서비스의 메인 핸들러에 도달할 수 없게 되면 정보가 부모로 위로 전파돼요.

동작

주어진 서비스에 HealthCheck가 활성화되어 있는데 그 하위 중 어느 하나라도 활성화되어 있지 않으면, 서비스 생성이 실패해요.

Mirroring 서비스의 HealthCheck는 현재 File 프로바이더로만 정의할 수 있어요.

구조화 (YAML)

## 라우팅 구성
http:
  services:
    mirrored-api:
      mirroring:
        healthCheck: {}
        service: appv1
        mirrors:
        - name: appv2
          percent: 10

    appv1:
      loadBalancer:
        healthCheck:
          path: /status
          interval: 10s
          timeout: 3s
        servers:
        - url: "http://private-ip-server-1/"

    appv2:
      loadBalancer:
        servers:
        - url: "http://private-ip-server-2/"

구조화 (TOML)

## 라우팅 구성
[http.services]
  [http.services.mirrored-api]
    [http.services.mirrored-api.mirroring]
      service = "appv1"
      [http.services.mirrored-api.mirroring.healthCheck]
    [[http.services.mirrored-api.mirroring.mirrors]]
      name = "appv2"
      percent = 10

  [http.services.appv1]
    [http.services.appv1.loadBalancer]
      [http.services.appv1.loadBalancer.healthCheck]
        path = "/health"
        interval = "10s"
        timeout = "3s"
      [[http.services.appv1.loadBalancer.servers]]
        url = "http://private-ip-server-1/"

  [http.services.appv2]
    [http.services.appv2.loadBalancer]
      [http.services.appv2.loadBalancer.healthCheck]
        path = "/health"
        interval = "10s"
        timeout = "3s"
      [[http.services.appv2.loadBalancer.servers]]
        url = "http://private-ip-server-2/"

Failover

failover 서비스 유형은 메인 서비스를 사용할 수 없을 때 요청을 폴백 서비스로 전달해요. Failover는 두 가지 방식으로 트리거될 수 있어요:

  • 헬스 체크 기반: 메인 서비스가 헬스 체크를 기반으로 도달 불가능해질 때.

  • 상태 코드 기반: 메인 서비스가 errors 구성에 정의된 특정 HTTP 상태 코드로 응답할 때.

HealthCheck와의 관계

failover 서비스는 메인 서비스가 도달 불가능해졌을 때 통보받기 위해 HealthCheck 시스템에 의존해요. 즉 메인 서비스에 HealthCheck가 활성화되어 있고 작동해야 해요. 하지만 failover 서비스 자체에 HealthCheck가 활성화되어 있어야 작동하는 것은 아니에요. HealthCheck는 failover 자체가 다운될 때(즉 메인과 폴백이 모두 다운될 때) 정보를 위로 전파하기 위해서만 필요해요.

지원되는 프로바이더

이 서비스 유형은 File 및 Kubernetes CRD 프로바이더로 정의할 수 있어요.

HealthCheck

HealthCheck는 이 서비스에 대한 자동 자가 헬스 체크를 활성화해요. 즉 메인과 폴백 서비스가 도달 불가능해지면 정보가 부모로 위로 전파돼요.

동작

주어진 서비스에 HealthCheck가 활성화되어 있는데 그 하위 중 어느 하나라도 활성화되어 있지 않으면, 서비스 생성이 실패해요.

Failover 서비스의 HealthCheck는 현재 File 프로바이더로만 정의할 수 있어요.

구조화 (YAML)

## 라우팅 구성
http:
  services:
    app:
      failover:
        healthCheck: {}
        service: main
        fallback: backup

    main:
      loadBalancer:
        healthCheck:
          path: /status
          interval: 10s
          timeout: 3s
        servers:
        - url: "http://private-ip-server-1/"

    backup:
      loadBalancer:
        healthCheck:
          path: /status
          interval: 10s
          timeout: 3s
        servers:
        - url: "http://private-ip-server-2/"

구조화 (TOML)

## 라우팅 구성
[http.services]
  [http.services.app]
    [http.services.app.failover]
      service = "main"
      fallback = "backup"
      [http.services.app.failover.healthCheck]

  [http.services.main]
    [http.services.main.loadBalancer]
      [http.services.main.loadBalancer.healthCheck]
        path = "/status"
        interval = "10s"
        timeout = "3s"
      [[http.services.main.loadBalancer.servers]]
        url = "http://private-ip-server-1/"

  [http.services.backup]
    [http.services.backup.loadBalancer]
      [http.services.backup.loadBalancer.healthCheck]
        path = "/status"
        interval = "10s"
        timeout = "3s"
      [[http.services.backup.loadBalancer.servers]]
        url = "http://private-ip-server-2/"

Errors

errors 옵션은 상태 코드 기반 페일오버를 활성화해요. 메인 서비스가 구성된 범위 중 하나와 일치하는 HTTP 상태 코드로 응답하면, Traefik은 자동으로 폴백 서비스에서 요청을 재시도해요.

요청 재생(replay)을 지원하기 위해 요청 본문은 maxRequestBodyBytes까지 버퍼링돼요. 이 제한보다 큰 본문을 가진 요청은 413 Request Entity Too Large 응답을 받아요.

다음은 errors 옵션에 사용 가능한 옵션 목록과 failover 서비스에 구성하는 예시예요:

| 필드 | 설명 | 기본값 | | status | 페일오버를 트리거하는 HTTP 상태 코드 범위 목록이에요. 단일 코드("500")와 범위("500-504")를 지원해요. | None | | maxRequestBodyBytes | 폴백 서비스로 재생을 위해 버퍼링할 최대 요청 본문 크기(바이트)예요. 제한 없음은 -1로 설정해요. | -1 |

구조화 (YAML)

## 라우팅 구성
http:
  services:
    app:
      failover:
        service: main
        fallback: backup
        errors:
          status:
            - "500-504"
          maxRequestBodyBytes: 1048576

    main:
      loadBalancer:
        servers:
          - url: "http://private-ip-server-1/"

    backup:
      loadBalancer:
        servers:
          - url: "http://private-ip-server-2/"

구조화 (TOML)

## 라우팅 구성
[http.services]
  [http.services.app]
    [http.services.app.failover]
      service = "main"
      fallback = "backup"
      [http.services.app.failover.errors]
        status = ["500-504"]
        maxRequestBodyBytes = 1048576

  [http.services.main]
    [http.services.main.loadBalancer]
      [[http.services.main.loadBalancer.servers]]
        url = "http://private-ip-server-1/"

  [http.services.backup]
    [http.services.backup.loadBalancer]
      [[http.services.backup.loadBalancer.servers]]
        url = "http://private-ip-server-2/"

Failover 서비스 체인하기

Failover 서비스는 다단계 이중화를 위해 함께 체인할 수 있어요. 다음 예시에서, 기본 서비스가 실패하면 트래픽은 보조(secondary) 서비스로 갑니다. 기본과 보조가 모두 실패하면 트래픽은 3차(tertiary) 서비스로 가요.

구조화 (YAML)

## 라우팅 구성
http:
  services:
    app:
      failover:
        healthCheck: {}
        service: primary-failover
        fallback: tertiary

    primary-failover:
      failover:
        healthCheck: {}
        service: primary
        fallback: secondary

    primary:
      loadBalancer:
        healthCheck:
          path: /health
          interval: 10s
          timeout: 3s
        servers:
          - url: "http://primary-server/"

    secondary:
      loadBalancer:
        healthCheck:
          path: /health
          interval: 10s
          timeout: 3s
        servers:
          - url: "http://secondary-server/"

    tertiary:
      loadBalancer:
        healthCheck:
          path: /health
          interval: 10s
          timeout: 3s
        servers:
          - url: "http://tertiary-server/"

구조화 (TOML)

## 라우팅 구성
[http.services]
  [http.services.app]
    [http.services.app.failover]
      service = "primary-failover"
      fallback = "tertiary"
      [http.services.app.failover.healthCheck]

  [http.services.primary-failover]
    [http.services.primary-failover.failover]
      service = "primary"
      fallback = "secondary"
      [http.services.primary-failover.failover.healthCheck]

  [http.services.primary]
    [http.services.primary.loadBalancer]
      [http.services.primary.loadBalancer.healthCheck]
        path = "/health"
        interval = "10s"
        timeout = "3s"
      [[http.services.primary.loadBalancer.servers]]
        url = "http://primary-server/"

  [http.services.secondary]
    [http.services.secondary.loadBalancer]
      [http.services.secondary.loadBalancer.healthCheck]
        path = "/health"
        interval = "10s"
        timeout = "3s"
      [[http.services.secondary.loadBalancer.servers]]
        url = "http://secondary-server/"

  [http.services.tertiary]
    [http.services.tertiary.loadBalancer]
      [http.services.tertiary.loadBalancer.healthCheck]
        path = "/health"
        interval = "10s"
        timeout = "3s"
      [[http.services.tertiary.loadBalancer.servers]]
        url = "http://tertiary-server/"

더 알아보기 (Learn more)