Skip to content

필사 모드: Traefik 완전 가이드 — IngressRoute, 미들웨어, 동적 설정

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

들어가며

쿠버네티스 클러스터를 운영하다 보면 외부 트래픽을 내부 서비스로 라우팅하는 진입점(ingress)이 반드시 필요합니다. 표준 Ingress 리소스만으로는 경로 재작성, 인증, rate limit 같은 요구사항을 표현하기 어렵고, 컨트롤러마다 어노테이션 문법이 제각각이라 이식성이 떨어집니다.

Traefik은 이런 한계를 동적 설정(dynamic configuration)과 미들웨어(middleware)라는 개념으로 풀어낸 클라우드 네이티브 엣지 라우터입니다. Go로 작성된 단일 바이너리이며, 쿠버네티스 CRD, 표준 Ingress, Docker, Consul 등 여러 프로바이더(provider)를 동시에 감시하면서 라우팅 규칙을 실시간으로 재구성합니다. 설정 파일을 다시 로드하거나 프로세스를 재시작할 필요가 없습니다.

이 글에서는 Traefik의 핵심 개념을 차근차근 짚은 뒤, IngressRoute CRD와 미들웨어 체이닝, Let's Encrypt 자동 TLS, 대시보드, 그리고 2026년 현재 표준으로 자리잡은 Gateway API와의 관계까지 실전 예제와 함께 살펴봅니다. 마지막에는 Helm 배포와 흔히 마주치는 함정도 정리합니다.

이 글은 다음 독자를 대상으로 합니다.

- 쿠버네티스에서 ingress-nginx 대신 Traefik 도입을 검토 중인 분

- 표준 Ingress의 어노테이션 지옥에서 벗어나고 싶은 분

- 자동 TLS와 미들웨어 체이닝을 선언적으로 관리하고 싶은 분

- Ingress에서 Gateway API로의 마이그레이션 경로를 고민하는 분

Traefik 아키텍처 한눈에 보기

Traefik의 라우팅 모델은 네 가지 핵심 객체로 구성됩니다. 요청이 들어와서 백엔드 파드에 도달하기까지의 흐름을 이해하면 나머지 설정이 훨씬 쉬워집니다.

인터넷 / 외부 클라이언트

|

v

+-------------------------------------------------+

| EntryPoint |

| (:80 web / :443 websecure 포트 수신) |

+-------------------------------------------------+

|

v

+-------------------------------------------------+

| Router |

| 규칙 매칭: Host(`app.example.com`) && Path |

| 매칭되면 Middleware 체인으로 전달 |

+-------------------------------------------------+

|

v

+-------------------------------------------------+

| Middleware 체인 (순서대로) |

| auth -> redirect -> ratelimit -> stripprefix |

+-------------------------------------------------+

|

v

+-------------------------------------------------+

| Service |

| 로드밸런싱 대상 (쿠버네티스 Service / 파드) |

+-------------------------------------------------+

|

v

백엔드 파드(Pod)

EntryPoint

EntryPoint는 Traefik이 트래픽을 수신하는 네트워크 진입점입니다. 보통 정적 설정(static configuration)에서 정의하며, 포트와 프로토콜을 지정합니다. 관례적으로 80번 포트를 web, 443번 포트를 websecure로 부릅니다.

traefik.yml (정적 설정)

entryPoints:

web:

address: ":80"

http:

redirections:

entryPoint:

to: websecure

scheme: https

permanent: true

websecure:

address: ":443"

http:

tls: {}

metrics:

address: ":9100"

위 예시에서 web으로 들어온 모든 HTTP 요청은 websecure(HTTPS)로 영구 리다이렉트됩니다. EntryPoint 단위에서 전역 리다이렉트를 거는 것은 매우 흔한 패턴입니다.

Router

Router는 들어온 요청을 어떤 규칙으로 매칭할지 정의합니다. Host, Path, Header, Method 등 다양한 매처(matcher)를 논리 연산자로 조합할 수 있습니다.

동적 설정 예시

http:

routers:

my-app:

rule: "Host(`app.example.com`) && PathPrefix(`/api`)"

entryPoints:

- websecure

middlewares:

- strip-api-prefix

service: my-app-service

tls:

certResolver: letsencrypt

규칙(rule)은 백틱으로 감싼 값으로 표현합니다. 우선순위(priority)는 기본적으로 규칙 길이를 기준으로 자동 계산되지만, priority 필드로 직접 지정할 수도 있습니다.

Middleware

Middleware는 Router와 Service 사이에서 요청 또는 응답을 가공하는 단계입니다. 인증, 헤더 추가, 경로 재작성, rate limit, 압축 등 수십 가지 내장 미들웨어가 제공되며, 여러 개를 체인으로 연결할 수 있습니다. 체인의 순서가 동작에 직접 영향을 주므로 순서 설계가 중요합니다.

Service

Service는 실제 백엔드를 가리키며, 로드밸런싱 전략(weighted round robin), 헬스체크, sticky session 같은 옵션을 정의합니다. 쿠버네티스에서는 보통 클러스터의 Service 리소스로 매핑됩니다.

Provider

Provider는 Traefik이 설정을 읽어오는 소스입니다. 핵심은 Traefik이 여러 프로바이더를 동시에 감시한다는 점입니다. 쿠버네티스 환경에서는 주로 두 가지를 씁니다.

| 프로바이더 | 설명 | 사용 리소스 |

| --- | --- | --- |

| kubernetesCRD | Traefik 전용 CRD 기반 | IngressRoute, Middleware 등 |

| kubernetesIngress | 표준 Ingress 리소스 처리 | Ingress, IngressClass |

| kubernetesGateway | Gateway API 표준 처리 | Gateway, HTTPRoute |

정적 설정에서 프로바이더 활성화

providers:

kubernetesCRD:

allowCrossNamespace: false

kubernetesIngress:

ingressClass: traefik

kubernetesGateway: {}

Ingress vs IngressRoute CRD 차이

이 부분이 Traefik 입문자가 가장 헷갈려 하는 지점입니다. 두 방식 모두 트래픽을 라우팅하지만 표현력과 이식성에서 큰 차이가 있습니다.

표준 Ingress의 한계

표준 Ingress는 쿠버네티스 공식 리소스라 이식성이 좋지만, 명세 자체가 host와 path 기반 라우팅 정도만 표준화되어 있습니다. 그 외의 모든 고급 기능(재작성, 인증, rate limit 등)은 컨트롤러별 어노테이션에 의존합니다.

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

name: my-app

annotations:

traefik.ingress.kubernetes.io/router.middlewares: default-auth@kubernetescrd

traefik.ingress.kubernetes.io/router.entrypoints: websecure

spec:

ingressClassName: traefik

rules:

- host: app.example.com

http:

paths:

- path: /

pathType: Prefix

backend:

service:

name: my-app-service

port:

number: 80

보다시피 미들웨어를 붙이려면 어노테이션 문자열에 의존해야 하고, 이 문법은 다른 컨트롤러로 그대로 옮길 수 없습니다. 2026년 현재 표준 Ingress API는 동결(frozen) 상태입니다. 즉 더 이상 새로운 기능이 추가되지 않으며, 커뮤니티의 발전 방향은 Gateway API로 옮겨갔습니다.

IngressRoute CRD

IngressRoute는 Traefik이 정의한 CRD로, 라우팅 규칙과 미들웨어, TLS 설정을 어노테이션 없이 명시적인 YAML 필드로 표현합니다.

apiVersion: traefik.io/v1alpha1

kind: IngressRoute

metadata:

name: my-app

namespace: default

spec:

entryPoints:

- websecure

routes:

- match: Host(`app.example.com`) && PathPrefix(`/api`)

kind: Rule

priority: 10

middlewares:

- name: api-auth

- name: strip-api-prefix

services:

- name: my-app-service

port: 80

tls:

certResolver: letsencrypt

다음 표로 두 방식을 비교해 보겠습니다.

| 항목 | 표준 Ingress | IngressRoute CRD |

| --- | --- | --- |

| 이식성 | 높음 (k8s 표준) | 낮음 (Traefik 전용) |

| 미들웨어 표현 | 어노테이션 문자열 | 네이티브 필드 |

| 매칭 규칙 | host / path 위주 | Host, Header, Method 등 풍부 |

| TCP / UDP 라우팅 | 불가 | IngressRouteTCP / UDP 지원 |

| 우선순위 제어 | 제한적 | priority 필드로 명시 |

| 향후 표준 | 동결됨 | Traefik 종속 |

결론적으로 이식성이 최우선이라면 표준 Ingress 또는 Gateway API를, Traefik의 모든 기능을 활용하려면 IngressRoute를 선택합니다. 다만 신규 프로젝트라면 뒤에서 설명할 Gateway API를 우선 검토하는 것이 2026년 기준으로 합리적입니다.

미들웨어 체이닝 실전

미들웨어는 Traefik의 가장 강력한 기능입니다. 각 미들웨어를 독립적인 CRD로 정의하고, IngressRoute에서 순서대로 참조해 체인을 구성합니다. 자주 쓰는 네 가지를 살펴보겠습니다.

1. 기본 인증 (BasicAuth)

먼저 자격증명을 담은 Secret을 만들고, 미들웨어에서 참조합니다.

apiVersion: v1

kind: Secret

metadata:

name: dashboard-auth-secret

namespace: default

type: Opaque

stringData:

users: |

admin:$apr1$abcd1234$encryptedpasswordhash

apiVersion: traefik.io/v1alpha1

kind: Middleware

metadata:

name: api-auth

namespace: default

spec:

basicAuth:

secret: dashboard-auth-secret

removeHeader: true

users 값은 htpasswd로 생성한 해시 형식이어야 합니다. removeHeader를 true로 두면 인증 후 Authorization 헤더를 백엔드로 전달하지 않습니다.

2. 리다이렉트 (RedirectScheme / RedirectRegex)

HTTP를 HTTPS로 강제하거나, 특정 경로 패턴을 다른 위치로 보낼 수 있습니다.

apiVersion: traefik.io/v1alpha1

kind: Middleware

metadata:

name: https-redirect

namespace: default

spec:

redirectScheme:

scheme: https

permanent: true

apiVersion: traefik.io/v1alpha1

kind: Middleware

metadata:

name: legacy-redirect

namespace: default

spec:

redirectRegex:

regex: "^https://old.example.com/(.*)"

replacement: "https://new.example.com/${1}"

permanent: true

3. Rate Limit

분당 또는 초당 요청 수를 제한해 백엔드를 보호합니다. average는 평균 허용 속도, burst는 순간 허용량입니다.

apiVersion: traefik.io/v1alpha1

kind: Middleware

metadata:

name: api-ratelimit

namespace: default

spec:

rateLimit:

average: 100

burst: 50

period: 1s

sourceCriterion:

ipStrategy:

depth: 1

sourceCriterion으로 클라이언트를 식별하는 기준을 정합니다. 프록시 뒤에 있다면 ipStrategy.depth로 X-Forwarded-For 헤더에서 실제 클라이언트 IP를 추출하도록 설정합니다.

4. StripPrefix

백엔드가 루트 경로(/)를 기대하는데 외부에서는 특정 prefix로 접근하는 경우, 경로 앞부분을 제거합니다.

apiVersion: traefik.io/v1alpha1

kind: Middleware

metadata:

name: strip-api-prefix

namespace: default

spec:

stripPrefix:

prefixes:

- /api

forceSlash: false

이 미들웨어가 적용되면 외부의 /api/users 요청은 백엔드에 /users로 전달됩니다.

미들웨어 체인 구성과 순서

여러 미들웨어를 IngressRoute에서 배열로 나열하면 그 순서대로 적용됩니다. 순서를 잘못 잡으면 의도와 다르게 동작하므로 주의해야 합니다.

apiVersion: traefik.io/v1alpha1

kind: IngressRoute

metadata:

name: secure-api

namespace: default

spec:

entryPoints:

- websecure

routes:

- match: Host(`api.example.com`)

kind: Rule

middlewares:

- name: https-redirect

- name: api-auth

- name: api-ratelimit

- name: strip-api-prefix

services:

- name: api-service

port: 8080

tls:

certResolver: letsencrypt

위 체인은 다음 순서로 동작합니다.

요청

-> https-redirect (HTTP면 HTTPS로 리다이렉트)

-> api-auth (인증 통과 검사)

-> api-ratelimit (요청 속도 제한)

-> strip-api-prefix (경로 prefix 제거)

-> api-service (백엔드 전달)

원칙적으로 비용이 싸고 거부 가능성이 높은 미들웨어(리다이렉트, 인증, rate limit)를 앞쪽에 두어 불필요한 처리를 조기에 차단하는 것이 좋습니다. 경로 가공 같은 변환은 뒤쪽에 둡니다.

자동 TLS — Let's Encrypt ACME

Traefik의 매력적인 기능 중 하나는 Let's Encrypt를 통한 인증서 자동 발급과 갱신입니다. ACME 프로토콜을 내장하고 있어 별도의 cert-manager 없이도 동작합니다.

ACME 챌린지 방식

ACME는 도메인 소유권을 증명하는 세 가지 챌린지를 지원합니다.

| 챌린지 | 동작 방식 | 와일드카드 인증서 |

| --- | --- | --- |

| HTTP-01 | 80번 포트로 검증 토큰 응답 | 불가 |

| TLS-ALPN-01 | 443번 포트에서 TLS 핸드셰이크 | 불가 |

| DNS-01 | DNS TXT 레코드로 검증 | 가능 |

정적 설정 — HTTP-01 챌린지

certificatesResolvers:

letsencrypt:

acme:

email: ops@example.com

storage: /data/acme.json

httpChallenge:

entryPoint: web

와일드카드 인증서가 필요하면 DNS-01 챌린지를 써야 합니다. DNS 프로바이더(예: Cloudflare, Route53)의 API 토큰을 환경 변수로 주입합니다.

certificatesResolvers:

letsencrypt-dns:

acme:

email: ops@example.com

storage: /data/acme.json

dnsChallenge:

provider: cloudflare

resolvers:

- "1.1.1.1:53"

acme.json 파일은 발급된 인증서와 개인키를 저장하므로 권한을 600으로 제한하고 영속 볼륨(PVC)에 저장해야 합니다. 파드가 여러 개로 스케일되면 같은 파일을 동시에 쓰면서 충돌이 날 수 있으니, 다중 레플리카 환경에서는 cert-manager를 별도로 쓰거나 인증서 발급을 단일 인스턴스로 제한하는 편이 안전합니다.

대시보드

Traefik은 현재 라우터, 서비스, 미들웨어 상태를 시각적으로 보여주는 웹 대시보드를 제공합니다. 운영 중인 라우팅 구성을 빠르게 확인하는 데 유용합니다.

정적 설정에서 대시보드와 API 활성화

api:

dashboard: true

insecure: false

insecure를 true로 두면 인증 없이 노출되므로 운영 환경에서는 절대 사용하면 안 됩니다. 대신 IngressRoute로 대시보드를 노출하고 BasicAuth 미들웨어를 걸어 보호합니다.

apiVersion: traefik.io/v1alpha1

kind: IngressRoute

metadata:

name: traefik-dashboard

namespace: traefik

spec:

entryPoints:

- websecure

routes:

- match: Host(`traefik.example.com`)

kind: Rule

middlewares:

- name: dashboard-auth

services:

- name: api@internal

kind: TraefikService

tls:

certResolver: letsencrypt

서비스로 api@internal이라는 내부 TraefikService를 지정하는 점에 주목하세요. 이는 Traefik 내부 API 핸들러를 가리키는 특수 참조입니다.

Gateway API 지원

2026년 기준으로 가장 중요한 흐름은 Gateway API입니다. 앞서 언급했듯 표준 Ingress는 동결되었고, 쿠버네티스 네트워킹의 차세대 표준은 Gateway API로 정해졌습니다. Gateway API는 역할 분리(인프라 운영자는 Gateway, 앱 개발자는 HTTPRoute)와 풍부한 라우팅 표현력을 표준 CRD로 제공합니다.

Traefik은 Gateway API 구현체로서 인증을 받았으며, kubernetesGateway 프로바이더를 통해 표준 리소스를 처리합니다. 즉 IngressRoute의 표현력을 벤더 종속 없이 표준으로 얻을 수 있습니다.

apiVersion: gateway.networking.k8s.io/v1

kind: GatewayClass

metadata:

name: traefik

spec:

controllerName: traefik.io/gateway-controller

apiVersion: gateway.networking.k8s.io/v1

kind: Gateway

metadata:

name: traefik-gateway

namespace: traefik

spec:

gatewayClassName: traefik

listeners:

- name: web

protocol: HTTP

port: 80

- name: websecure

protocol: HTTPS

port: 443

tls:

mode: Terminate

certificateRefs:

- name: example-tls

apiVersion: gateway.networking.k8s.io/v1

kind: HTTPRoute

metadata:

name: my-app-route

namespace: default

spec:

parentRefs:

- name: traefik-gateway

namespace: traefik

hostnames:

- "app.example.com"

rules:

- matches:

- path:

type: PathPrefix

value: /api

backendRefs:

- name: my-app-service

port: 80

다음 표는 세 가지 방식의 위치를 정리한 것입니다.

| 방식 | 표준 여부 | 표현력 | 권장 상황 |

| --- | --- | --- | --- |

| 표준 Ingress | k8s 표준(동결) | 낮음 | 단순 라우팅, 레거시 |

| IngressRoute | Traefik 전용 | 높음 | Traefik 고급 기능 필요 |

| Gateway API | k8s 표준(발전 중) | 높음 | 신규 프로젝트 권장 |

당장은 Gateway API의 미들웨어 표현이 IngressRoute만큼 풍부하지 않을 수 있어, 두 방식을 혼용하는 과도기적 운영도 흔합니다. 장기적으로는 Gateway API로 수렴하는 방향을 권장합니다.

배포 실습 — Helm values

운영 환경에서는 공식 Helm 차트로 Traefik을 배포하는 것이 일반적입니다. 다음은 실전에서 자주 쓰는 values 예시입니다.

저장소 추가 및 설치

helm repo add traefik https://traefik.github.io/charts

helm repo update

helm install traefik traefik/traefik \

--namespace traefik --create-namespace \

--values values.yaml

values.yaml

deployment:

replicas: 2

ingressClass:

enabled: true

isDefaultClass: true

providers:

kubernetesCRD:

enabled: true

allowCrossNamespace: false

kubernetesIngress:

enabled: true

kubernetesGateway:

enabled: true

ports:

web:

redirectTo:

port: websecure

websecure:

tls:

enabled: true

certificatesResolvers:

letsencrypt:

acme:

email: ops@example.com

storage: /data/acme.json

httpChallenge:

entryPoint: web

persistence:

enabled: true

size: 128Mi

path: /data

dashboard:

enabled: true

resources:

requests:

cpu: 100m

memory: 128Mi

limits:

cpu: 500m

memory: 256Mi

logs:

general:

level: INFO

access:

enabled: true

설치 후 다음 명령으로 상태를 확인합니다.

kubectl get pods -n traefik

kubectl get svc -n traefik

kubectl logs -n traefik deploy/traefik --tail=100

운영과 튜닝

접근 로그와 메트릭

운영 환경에서는 접근 로그를 JSON 형식으로 남기고, Prometheus 메트릭을 활성화해 관측성을 확보합니다.

metrics:

prometheus:

entryPoint: metrics

addEntryPointsLabels: true

addServicesLabels: true

accessLog:

format: json

filters:

statusCodes:

- "400-499"

- "500-599"

statusCodes 필터를 쓰면 4xx, 5xx 응답만 로깅해 로그량을 줄일 수 있습니다.

헬스체크와 프로브

Traefik 자체의 readiness, liveness 프로브는 ping EntryPoint를 통해 구성합니다.

ping:

entryPoint: web

타임아웃 튜닝

장시간 연결이나 대용량 업로드를 다룬다면 EntryPoint의 트랜스포트 타임아웃을 조정합니다.

entryPoints:

websecure:

address: ":443"

transport:

respondingTimeouts:

readTimeout: 60s

writeTimeout: 60s

idleTimeout: 180s

함정과 트러블슈팅

운영하면서 자주 마주치는 문제들을 정리했습니다.

1. 404 또는 라우터가 매칭되지 않음

가장 흔한 원인은 EntryPoint 지정 누락입니다. IngressRoute에 entryPoints를 명시하지 않으면 모든 EntryPoint에 노출되거나, 의도한 포트로 들어오지 않을 수 있습니다. 대시보드에서 해당 라우터가 등록되었는지, 규칙이 올바른지 먼저 확인하세요.

라우터 상태를 API로 조회

kubectl port-forward -n traefik deploy/traefik 8080:8080

curl http://localhost:8080/api/http/routers

2. 미들웨어를 찾지 못함

다른 네임스페이스의 미들웨어를 참조하려면 네임스페이스를 명시해야 합니다. IngressRoute의 어노테이션 방식에서는 name-namespace@kubernetescrd 형태를 씁니다. 또한 allowCrossNamespace가 false면 크로스 네임스페이스 참조가 차단됩니다.

3. 인증서가 발급되지 않음

HTTP-01 챌린지는 80번 포트가 외부에서 도달 가능해야 합니다. 방화벽이나 로드밸런서 설정을 확인하세요. acme.json 파일 권한이 600이 아니면 Traefik이 거부합니다. 또한 다중 레플리카에서 같은 acme.json을 공유하면 발급이 꼬일 수 있습니다.

4. StripPrefix 후 백엔드가 깨짐

백엔드 애플리케이션이 절대 경로로 정적 리소스를 참조하면, prefix를 제거한 뒤 링크가 깨질 수 있습니다. 이 경우 애플리케이션에 base path 설정을 하거나, replacePathRegex 미들웨어로 더 정교하게 경로를 다루어야 합니다.

5. 실제 클라이언트 IP가 안 보임

클라우드 로드밸런서 뒤에 있을 때 rate limit이나 로그에 LB의 IP만 찍히는 경우가 있습니다. forwardedHeaders.trustedIPs를 설정하고, rate limit 미들웨어의 ipStrategy.depth를 환경에 맞게 조정해야 합니다.

entryPoints:

websecure:

address: ":443"

forwardedHeaders:

trustedIPs:

- "10.0.0.0/8"

- "172.16.0.0/12"

마치며

Traefik은 동적 설정, 미들웨어, 자동 TLS를 한데 묶어 쿠버네티스 ingress를 선언적으로 운영할 수 있게 해주는 강력한 도구입니다. IngressRoute CRD는 표준 Ingress의 어노테이션 지옥에서 벗어나게 해주지만 벤더 종속이라는 비용이 따릅니다.

2026년 현재 표준 Ingress는 동결되었고 Gateway API가 차세대 표준으로 자리잡았습니다. Traefik은 Gateway API를 정식 지원하므로, 신규 프로젝트라면 Gateway API를 우선 검토하되 Traefik의 미들웨어 생태계가 필요한 부분에서는 IngressRoute를 함께 쓰는 전략이 현실적입니다. 핵심 개념(EntryPoint, Router, Middleware, Service, Provider)을 정확히 이해하면 어떤 방식을 택하든 흔들림 없이 운영할 수 있습니다.

참고 자료

- [Traefik 공식 문서](https://doc.traefik.io/traefik/)

- [Traefik Kubernetes IngressRoute 가이드](https://doc.traefik.io/traefik/routing/providers/kubernetes-crd/)

- [Traefik Helm Charts](https://github.com/traefik/traefik-helm-chart)

- [Kubernetes Ingress 개념](https://kubernetes.io/docs/concepts/services-networking/ingress/)

- [Gateway API 공식 문서](https://gateway-api.sigs.k8s.io/)

- [Let's Encrypt 문서](https://letsencrypt.org/docs/)

- [cert-manager 문서](https://cert-manager.io/docs/)

- [Helm 공식 문서](https://helm.sh/docs/)

- [ingress-nginx 문서](https://kubernetes.github.io/ingress-nginx/)

현재 단락 (1/441)

쿠버네티스 클러스터를 운영하다 보면 외부 트래픽을 내부 서비스로 라우팅하는 진입점(ingress)이 반드시 필요합니다. 표준 Ingress 리소스만으로는 경로 재작성, 인증, ra...

작성 글자: 0원문 글자: 12,364작성 단락: 0/441