들어가며
Traefik을 단순한 리버스 프록시로만 쓰다가, 어느 순간 "인증을 모든 라우트에 공통으로 걸고 싶다", "특정 클라이언트만 mTLS로 받고 싶다", "신규 버전을 트래픽 5퍼센트만 흘려보고 싶다" 같은 요구가 쏟아지기 시작하면 기본 설정만으로는 한계에 부딪힙니다. 이 글은 그 다음 단계, 즉 Traefik을 프로덕션에서 본격적으로 운영할 때 필요한 고급 기능을 다룹니다.
실무에서 마주치는 전형적인 상황은 이렇습니다. 마이크로서비스가 수십 개로 늘어나면서 각 서비스마다 인증 로직을 중복 구현하는 것이 비효율적이라는 판단이 섭니다. 동시에 보안팀은 외부 파트너 연동 구간에 상호 TLS 인증을 요구하고, 플랫폼팀은 무중단 배포를 위해 카나리와 블루그린을 표준화하고 싶어 합니다. 이 모든 요구가 Traefik의 미들웨어, TLSOption, 서비스 고급 기능, 멀티 프로바이더 조합으로 해결됩니다.
2026년 현재 Kubernetes의 Ingress API는 사실상 동결 상태입니다. 새로운 기능은 더 이상 Ingress에 추가되지 않고, 후속 표준인 Gateway API로 무게 중심이 옮겨가고 있습니다. Traefik은 IngressRoute라는 자체 CRD와 더불어 Gateway API 프로바이더를 모두 지원하므로, 이 글에서 다루는 고급 패턴이 Gateway API의 필터 및 정책 리소스와 어떻게 대응되는지도 함께 짚어보겠습니다.
이 글의 목표는 단순한 기능 나열이 아니라, 각 기능을 언제 어떻게 조합해야 하는지에 대한 설계 감각을 전달하는 것입니다. 따라서 개념 설명 뒤에는 실제로 적용 가능한 CRD YAML과 명령어를 충분히 담았습니다.
미들웨어의 기본 개념
미들웨어는 요청이 백엔드 서비스에 도달하기 전, 또는 응답이 클라이언트로 돌아가기 전에 끼어들어 동작을 변형하는 처리 단위입니다. 헤더 추가, 인증, 속도 제한, 경로 재작성, 압축 등 횡단 관심사를 라우트 정의에서 분리해 재사용할 수 있게 해줍니다.
Traefik에서 미들웨어는 Kubernetes CRD인 Middleware로 선언하고, IngressRoute의 라우트 규칙에서 참조합니다. 핵심은 미들웨어가 순서대로 적용되는 체인이라는 점입니다. 체인의 앞쪽 미들웨어가 요청을 거부하면 뒤쪽 미들웨어와 백엔드는 호출되지 않습니다.
요청 흐름
Client
|
v
[EntryPoint :websecure]
|
v
[Router 매칭] --- Host(api.example.com) && PathPrefix(/v1)
|
v
[Middleware 체인]
1. rate-limit (속도 제한)
2. forward-auth (SSO 인증)
3. strip-prefix (경로 재작성)
4. secure-headers (보안 헤더)
|
v
[Service] --- weighted / mirroring / sticky
|
v
Pod (백엔드)
미들웨어를 설계할 때 가장 중요한 원칙은 순서입니다. 인증보다 속도 제한을 먼저 두면 인증 실패 트래픽도 속도 제한 카운트에 포함되어 공격 표면을 줄이는 데 도움이 됩니다. 반대로 경로 재작성은 인증 이후에 두어야 백엔드가 기대하는 경로로 전달됩니다.
미들웨어 체인 설계 패턴
여러 미들웨어를 매번 라우트마다 나열하는 것은 실수와 중복을 부릅니다. Traefik은 chain 타입 미들웨어를 제공하여 자주 쓰는 조합을 하나의 이름으로 묶을 수 있게 합니다.
먼저 개별 미들웨어를 정의합니다.
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: rate-limit
namespace: edge
spec:
rateLimit:
average: 100
burst: 50
period: 1s
sourceCriterion:
ipStrategy:
depth: 1
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: secure-headers
namespace: edge
spec:
headers:
browserXssFilter: true
contentTypeNosniff: true
frameDeny: true
stsSeconds: 31536000
stsIncludeSubdomains: true
stsPreload: true
customResponseHeaders:
X-Robots-Tag: "noindex, nofollow"
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: strip-api-prefix
namespace: edge
spec:
stripPrefix:
prefixes:
- /v1
이제 이들을 chain으로 묶습니다.
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: api-edge-chain
namespace: edge
spec:
chain:
middlewares:
- name: rate-limit
- name: forward-auth-sso
- name: strip-api-prefix
- name: secure-headers
라우트에서는 chain 하나만 참조하면 됩니다.
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: api-route
namespace: edge
spec:
entryPoints:
- websecure
routes:
- match: Host(`api.example.com`) && PathPrefix(`/v1`)
kind: Rule
middlewares:
- name: api-edge-chain
services:
- name: api-backend
port: 8080
tls:
secretName: api-example-com-tls
이 구조의 장점은 명확합니다. 공통 정책을 한 곳에서 관리하므로 보안 헤더 정책을 바꿀 때 모든 라우트에 즉시 반영됩니다. 또한 라우트 정의가 간결해져 가독성과 리뷰 효율이 올라갑니다.
forwardAuth로 SSO 구현하기
중앙 인증 서버에 인증 판단을 위임하는 패턴이 forwardAuth입니다. Traefik은 요청을 백엔드로 보내기 전에 지정된 인증 서버로 사본을 보내고, 인증 서버가 2xx를 반환하면 통과시키고 그 외에는 인증 서버의 응답을 그대로 클라이언트에 돌려줍니다.
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: forward-auth-sso
namespace: edge
spec:
forwardAuth:
address: http://auth-service.auth.svc.cluster.local:4180/oauth2/auth
trustForwardHeader: true
authResponseHeaders:
- X-Auth-Request-User
- X-Auth-Request-Email
- X-Auth-Request-Groups
authRequestHeaders:
- Cookie
- Authorization
여기서 authResponseHeaders가 핵심입니다. 인증 서버가 검증 결과로 사용자 정보를 헤더에 담아 돌려주면, Traefik이 그 헤더만 추출해 백엔드로 전달합니다. 백엔드는 토큰 검증을 직접 하지 않고도 신뢰할 수 있는 사용자 식별 정보를 받게 됩니다.
oauth2-proxy 같은 인증 게이트웨이와 결합하면 OIDC 기반 SSO가 완성됩니다. 인증되지 않은 요청은 oauth2-proxy가 로그인 페이지로 리다이렉트하도록 별도의 sign_in 경로를 라우팅해 주어야 합니다.
forwardAuth 동작 순서
Client --(1) 요청--> Traefik
Traefik --(2) /oauth2/auth 검증--> auth-service
auth-service --(3a) 200 OK + 사용자 헤더--> Traefik --(4) 백엔드 호출--> Backend
auth-service --(3b) 401/302--> Traefik --(5) 동일 응답 반환--> Client
trustForwardHeader를 true로 두면 X-Forwarded-* 헤더를 신뢰하는데, 이는 Traefik 앞단을 신뢰할 수 있는 경우에만 켜야 합니다. 외부에 직접 노출된 엔트리포인트라면 클라이언트가 위조한 헤더를 그대로 믿게 되므로 주의가 필요합니다.
TLSOption으로 TLS 정교하게 제어하기
기본 TLS 설정만으로는 부족한 경우가 많습니다. 특정 라우트는 TLS 1.3만 허용하고, 다른 라우트는 레거시 클라이언트를 위해 더 넓은 cipher suite를 열어야 할 수 있습니다. TLSOption CRD가 이 세밀한 제어를 담당합니다.
apiVersion: traefik.io/v1alpha1
kind: TLSOption
metadata:
name: modern-tls
namespace: edge
spec:
minVersion: VersionTLS13
sniStrict: true
alpnProtocols:
- h2
- http/1.1
apiVersion: traefik.io/v1alpha1
kind: TLSOption
metadata:
name: intermediate-tls
namespace: edge
spec:
minVersion: VersionTLS12
cipherSuites:
- TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
curvePreferences:
- CurveP521
- CurveP384
minVersion으로 최소 TLS 버전을 강제하고, sniStrict를 true로 두면 SNI가 없는 연결을 거부합니다. 주의할 점은 TLS 1.3에서는 cipherSuites 설정이 무시된다는 것입니다. cipher suite 제어는 TLS 1.2 구간에서만 의미가 있으므로, 최신 보안 정책을 적용하려면 minVersion을 VersionTLS13으로 올리는 편이 단순하고 안전합니다.
라우트에서 TLSOption을 참조하는 방법은 다음과 같습니다.
apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
name: secure-route
namespace: edge
spec:
entryPoints:
- websecure
routes:
- match: Host(`secure.example.com`)
kind: Rule
services:
- name: secure-backend
port: 8443
tls:
secretName: secure-example-com-tls
options:
name: modern-tls
namespace: edge
mTLS와 TLSStore
상호 TLS 인증은 서버뿐 아니라 클라이언트도 인증서를 제시하도록 요구합니다. 외부 파트너 연동, 서비스 간 보안 통신, 제로 트러스트 환경에서 흔히 쓰입니다. TLSOption의 clientAuth 섹션에서 설정합니다.
apiVersion: traefik.io/v1alpha1
kind: TLSOption
metadata:
name: mtls-required
namespace: edge
spec:
minVersion: VersionTLS13
clientAuth:
secretNames:
- partner-ca-bundle
clientAuthType: RequireAndVerifyClientCert
clientAuthType의 값에 따라 동작이 크게 달라집니다. 아래 표로 정리합니다.
| clientAuthType | 클라이언트 인증서 요구 | 검증 수행 | 인증서 없을 때 |
| --- | --- | --- | --- |
| NoClientCert | 안 함 | 안 함 | 통과 |
| RequestClientCert | 요청만 함 | 안 함 | 통과 |
| RequireAnyClientCert | 강제 | 안 함 | 거부 |
| VerifyClientCertIfGiven | 선택 | 제시되면 검증 | 통과 |
| RequireAndVerifyClientCert | 강제 | 항상 검증 | 거부 |
프로덕션에서 진정한 mTLS를 원한다면 RequireAndVerifyClientCert를 선택해야 합니다. RequestClientCert는 검증을 하지 않으므로 단순히 인증서를 수집하는 용도로만 적합합니다.
TLSStore는 기본 인증서를 정의하는 리소스입니다. SNI에 매칭되는 인증서가 없을 때 사용할 폴백 인증서를 지정합니다. 클러스터 전체의 기본값은 이름이 default인 TLSStore로 설정합니다.
apiVersion: traefik.io/v1alpha1
kind: TLSStore
metadata:
name: default
namespace: edge
spec:
defaultCertificate:
secretName: wildcard-example-com-tls
이 설정이 없으면 매칭되지 않는 SNI 요청에 Traefik이 자체 서명한 기본 인증서를 제시하여 브라우저 경고를 유발할 수 있습니다.
서비스 고급 기능
Traefik의 서비스는 단순한 백엔드 지정 이상을 표현할 수 있습니다. 가중치 기반 라운드로빈, 미러링, 스티키 세션이 대표적입니다.
가중치 기반 라우팅 (weighted)
여러 백엔드에 비율을 정해 트래픽을 분배합니다. 카나리 배포의 기반이 됩니다.
apiVersion: traefik.io/v1alpha1
kind: TraefikService
metadata:
name: api-weighted
namespace: edge
spec:
weighted:
services:
- name: api-stable
port: 8080
weight: 90
- name: api-canary
port: 8080
weight: 10
stable에 90, canary에 10의 가중치를 주면 대략 10퍼센트의 트래픽이 신규 버전으로 흐릅니다. IngressRoute에서는 이 TraefikService를 일반 서비스처럼 참조합니다.
미러링 (mirroring)
실제 트래픽의 사본을 별도 백엔드로 복제해 보냅니다. 응답은 무시되므로 클라이언트에 영향을 주지 않고 신규 버전을 실 트래픽으로 테스트할 수 있습니다.
apiVersion: traefik.io/v1alpha1
kind: TraefikService
metadata:
name: api-mirrored
namespace: edge
spec:
mirroring:
name: api-stable
port: 8080
mirrors:
- name: api-shadow
port: 8080
percent: 20
위 설정은 트래픽의 20퍼센트를 api-shadow로 복제합니다. 섀도우 트래픽 테스트는 신규 버전이 실제 부하 패턴에서 어떻게 동작하는지 안전하게 검증하는 강력한 도구입니다.
스티키 세션 (sticky)
같은 클라이언트를 같은 백엔드로 고정합니다. 세션 상태를 메모리에 두는 레거시 애플리케이션에 필요합니다.
apiVersion: traefik.io/v1alpha1
kind: TraefikService
metadata:
name: api-sticky
namespace: edge
spec:
weighted:
services:
- name: api-stable
port: 8080
weight: 1
sticky:
cookie:
name: traefik_backend
secure: true
httpOnly: true
sameSite: strict
가능하다면 애플리케이션을 무상태로 설계해 스티키 세션 의존을 없애는 편이 확장성과 복원력 면에서 유리합니다.
멀티 프로바이더 조합
Traefik은 여러 설정 소스를 동시에 읽어들이는 멀티 프로바이더 아키텍처를 가집니다. Kubernetes CRD, Kubernetes Ingress, 파일, Consul, Gateway API 등을 함께 활성화할 수 있습니다.
providers:
kubernetesCRD:
allowCrossNamespace: false
allowExternalNameServices: false
kubernetesGateway: {}
file:
directory: /etc/traefik/dynamic
watch: true
각 프로바이더는 고유한 네임스페이스 접두사를 가진 라우터와 서비스를 생성합니다. 한 클러스터에서 CRD 기반 라우팅을 주로 쓰면서, 클러스터 외부의 레거시 서비스는 파일 프로바이더로 정적 정의하고, 신규 표준 도입을 위해 Gateway API를 점진적으로 병행하는 식의 전략이 가능합니다.
| 프로바이더 | 주 용도 | 동적 갱신 | 비고 |
| --- | --- | --- | --- |
| kubernetesCRD | IngressRoute 등 Traefik 네이티브 | 예 | 가장 기능 풍부 |
| kubernetesGateway | Gateway API 표준 | 예 | 미래 표준, 이식성 높음 |
| kubernetesIngress | 표준 Ingress 호환 | 예 | API 동결, 신규 기능 없음 |
| file | 클러스터 외부 정적 정의 | 예 (watch) | 레거시 연동에 유용 |
멀티 프로바이더를 쓸 때 주의할 점은 라우터 우선순위입니다. 서로 다른 프로바이더가 겹치는 호스트를 정의하면 우선순위 규칙에 따라 충돌이 발생할 수 있으므로, 호스트와 경로 네임스페이스를 프로바이더별로 명확히 분리하는 것이 좋습니다.
Gateway API와의 대응 관계
2026년의 방향성을 고려하면 Gateway API로의 이전 경로를 알아두는 것이 중요합니다. Traefik의 고급 미들웨어 기능 상당수가 Gateway API의 필터와 정책 리소스로 대응됩니다.
| Traefik 기능 | Gateway API 대응 |
| --- | --- |
| Middleware (헤더 조작) | HTTPRoute의 RequestHeaderModifier 필터 |
| Middleware (경로 재작성) | HTTPRoute의 URLRewrite 필터 |
| Middleware (리다이렉트) | HTTPRoute의 RequestRedirect 필터 |
| weighted TraefikService | HTTPRoute backendRefs의 weight |
| TLSOption | Gateway listener의 TLS 설정 및 정책 |
| forwardAuth | ExtAuth 관련 확장 (구현체별 상이) |
주의할 것은 Gateway API의 코어 사양이 아직 forwardAuth나 rate limit 같은 모든 고급 미들웨어를 표준으로 포괄하지는 못한다는 점입니다. 이런 기능은 구현체별 확장이나 ExtensionRef 필터로 처리되며, Traefik도 일부를 ExtensionRef로 자사 Middleware를 연결하는 방식으로 지원합니다. 따라서 완전한 이식성을 원한다면 코어 필터로 표현 가능한 기능만 사용하고, 고급 기능은 구현체 종속성을 감수하는 절충이 필요합니다.
Yaegi 플러그인
Traefik은 Yaegi라는 Go 인터프리터를 내장하여, 컴파일 없이 Go로 작성한 미들웨어 플러그인을 동적으로 로드할 수 있습니다. 사내 정책을 코드로 구현해야 할 때 유용합니다.
정적 설정에서 플러그인을 선언합니다.
experimental:
plugins:
customHeader:
moduleName: github.com/example/traefik-custom-header
version: v0.2.0
플러그인의 핵심 골격은 다음과 같은 Go 코드입니다.
package customheader
"context"
"net/http"
)
type Config struct {
HeaderName string `json:"headerName,omitempty"`
HeaderValue string `json:"headerValue,omitempty"`
}
func CreateConfig() *Config {
return &Config{}
}
type CustomHeader struct {
next http.Handler
name string
headerName string
headerValue string
}
func New(ctx context.Context, next http.Handler, config *Config, name string) (http.Handler, error) {
return &CustomHeader{
next: next,
name: name,
headerName: config.HeaderName,
headerValue: config.HeaderValue,
}, nil
}
func (c *CustomHeader) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
req.Header.Set(c.headerName, c.headerValue)
c.next.ServeHTTP(rw, req)
}
선언한 플러그인은 Middleware CRD에서 plugin 타입으로 참조합니다.
apiVersion: traefik.io/v1alpha1
kind: Middleware
metadata:
name: add-custom-header
namespace: edge
spec:
plugin:
customHeader:
headerName: X-Internal-Trace
headerValue: edge-gateway
Yaegi는 인터프리터이므로 컴파일된 Go보다 실행 속도가 느립니다. 핫 패스에서 무거운 연산을 수행하는 플러그인은 지연 시간에 영향을 줄 수 있으므로, 성능이 중요한 로직은 별도 사이드카나 정식 빌드 미들웨어로 분리하는 것을 권장합니다.
카나리와 블루그린 배포
앞서 본 weighted 서비스를 활용하면 카나리 배포를 손쉽게 구현할 수 있습니다. 핵심은 가중치를 점진적으로 조정하는 것입니다.
1단계: 카나리에 5퍼센트만 분배
kubectl patch traefikservice api-weighted -n edge --type merge \
-p '{"spec":{"weighted":{"services":[{"name":"api-stable","port":8080,"weight":95},{"name":"api-canary","port":8080,"weight":5}]}}}'
메트릭 관찰 후 문제 없으면 25퍼센트로 증가
kubectl patch traefikservice api-weighted -n edge --type merge \
-p '{"spec":{"weighted":{"services":[{"name":"api-stable","port":8080,"weight":75},{"name":"api-canary","port":8080,"weight":25}]}}}'
최종 전환: 100퍼센트
kubectl patch traefikservice api-weighted -n edge --type merge \
-p '{"spec":{"weighted":{"services":[{"name":"api-stable","port":8080,"weight":0},{"name":"api-canary","port":8080,"weight":100}]}}}'
블루그린은 두 환경을 미리 띄워두고 라우터의 서비스 참조를 한 번에 전환하는 방식입니다. 가중치 0과 100을 즉시 교체하거나, 라우트의 서비스명을 blue에서 green으로 바꾸면 됩니다.
카나리 진행 곡선
트래픽 비율
100% | ____ green/canary
| ___/
50% | ______/
| _____/
5% | _____/
0% |_/_______________________________ 시간
T0 T1 T2 T3 T4 T5
각 단계마다 메트릭/에러율 게이트 통과 확인
각 단계 사이에 반드시 메트릭 게이트를 두어야 합니다. 에러율, 지연 시간, 포화도 같은 지표가 임계치를 넘으면 자동 또는 수동으로 롤백하는 절차를 정해두는 것이 안전한 운영의 기본입니다.
관측: 메트릭과 트레이싱
고급 라우팅을 운영하려면 무엇이 어디로 흐르는지 보이게 만들어야 합니다. Traefik은 Prometheus 메트릭과 OpenTelemetry 트레이싱을 기본 지원합니다.
metrics:
prometheus:
addEntryPointsLabels: true
addRoutersLabels: true
addServicesLabels: true
buckets:
- 0.1
- 0.3
- 1.2
- 5.0
tracing:
otlp:
http:
endpoint: http://otel-collector.observability.svc.cluster.local:4318/v1/traces
addServicesLabels를 켜면 서비스별로 요청 수와 지연 시간을 분리해 볼 수 있어, 카나리 배포 시 stable과 canary의 성능을 직접 비교할 수 있습니다. 다만 라벨 카디널리티가 높아지면 Prometheus 부하가 커지므로, 라우터가 매우 많은 환경에서는 addRoutersLabels를 신중하게 켜야 합니다.
트레이싱은 forwardAuth 같은 외부 호출이 끼어든 요청 경로에서 병목을 찾는 데 특히 유용합니다. 인증 서버 응답이 느린지, 백엔드가 느린지를 스팬 단위로 구분해 볼 수 있습니다.
프로덕션 함정
실제 운영에서 자주 마주치는 함정을 정리합니다.
첫째, 미들웨어 네임스페이스 참조 누락입니다. 미들웨어를 다른 네임스페이스에서 참조할 때는 이름만으로는 찾지 못합니다. provider 접두사 형식인 이름at네임스페이스at프로바이더 규칙을 따르거나 같은 네임스페이스에 두어야 합니다. 크로스 네임스페이스 참조는 allowCrossNamespace 설정에도 의존합니다.
둘째, TLS 1.3에서 cipherSuites가 무시되는 문제입니다. 보안 스캐너가 특정 cipher를 지적해 cipherSuites를 조정했는데도 변화가 없다면, 십중팔구 연결이 TLS 1.3으로 협상되고 있기 때문입니다.
셋째, forwardAuth의 헤더 위조 위험입니다. trustForwardHeader를 켠 채 엔트리포인트를 외부에 직접 노출하면 클라이언트가 X-Forwarded-User 같은 헤더를 위조할 수 있습니다. 신뢰 경계 밖에서는 인증 관련 헤더를 반드시 제거하는 미들웨어를 앞단에 두어야 합니다.
넷째, 스티키 세션과 무중단 배포의 충돌입니다. 스티키 쿠키가 특정 파드에 고정되어 있으면, 그 파드가 롤링 업데이트로 종료될 때 세션이 끊깁니다. 세션 드레이닝과 graceful shutdown을 함께 설계해야 합니다.
다섯째, 미러링의 부작용입니다. 미러링 대상이 쓰기 작업을 수행하는 백엔드라면 데이터가 이중으로 변경될 수 있습니다. 미러는 반드시 읽기 전용이거나 격리된 환경이어야 합니다.
트러블슈팅
문제가 생겼을 때 확인 순서를 정해두면 진단이 빨라집니다.
라우터, 미들웨어, 서비스가 정상 등록되었는지 API로 확인
kubectl port-forward -n edge deploy/traefik 8080:8080
curl -s http://localhost:8080/api/http/routers | jq '.[] | {name, status, rule}'
curl -s http://localhost:8080/api/http/middlewares | jq '.[] | {name, status}'
CRD 적용 상태와 이벤트 확인
kubectl describe ingressroute api-route -n edge
kubectl get events -n edge --sort-by=.lastTimestamp
TLS 핸드셰이크 및 인증서 확인
openssl s_client -connect secure.example.com:443 -servername secure.example.com </dev/null 2>/dev/null | openssl x509 -noout -dates -subject
mTLS 클라이언트 인증서로 호출 테스트
curl -v --cert client.crt --key client.key https://secure.example.com/health
대시보드 API의 status 필드가 enabled가 아니라면 설정 오류가 있다는 뜻입니다. 미들웨어가 warning 상태라면 참조 대상이 없거나 네임스페이스가 맞지 않는 경우가 대부분입니다.
로그 레벨을 일시적으로 DEBUG로 올리면 라우터 매칭과 미들웨어 적용 과정을 상세히 추적할 수 있습니다. 다만 프로덕션에서는 로그량이 폭증하므로 진단 후 반드시 원래대로 되돌려야 합니다.
마치며: 프로덕션 체크리스트
Traefik의 고급 기능은 강력하지만, 잘못 조합하면 디버깅이 어려운 장애로 이어집니다. 아래 체크리스트로 배포 전 점검을 권장합니다.
- 미들웨어 체인의 순서가 의도대로인가 (속도 제한 → 인증 → 재작성 → 보안 헤더)
- forwardAuth의 trustForwardHeader가 신뢰 경계 안에서만 켜져 있는가
- 외부 노출 엔트리포인트에서 인증 관련 헤더를 정리하는 미들웨어가 앞단에 있는가
- TLSOption의 minVersion이 보안 정책에 맞게 설정되었는가 (TLS 1.3 권장)
- mTLS 구간은 RequireAndVerifyClientCert로 검증까지 수행하는가
- TLSStore에 default 인증서가 지정되어 매칭 실패 시 경고를 방지하는가
- 카나리 단계마다 메트릭 게이트와 롤백 절차가 정의되어 있는가
- 미러링 대상이 읽기 전용이거나 격리되어 데이터 이중 변경이 없는가
- 스티키 세션 사용 시 graceful shutdown과 세션 드레이닝이 설계되었는가
- Prometheus 라벨 카디널리티가 관리 가능한 수준인가
- Yaegi 플러그인이 핫 패스의 지연을 유발하지 않는가
- 멀티 프로바이더 간 호스트/경로 충돌이 없는가
- Gateway API 이전 시 코어 필터로 대체 가능한 기능과 종속 기능을 구분했는가
이 항목들을 습관처럼 점검하면, Traefik을 단순한 프록시에서 신뢰할 수 있는 프로덕션 게이트웨이로 끌어올릴 수 있습니다. 다음 단계로는 cert-manager와의 자동 인증서 발급 연동, 그리고 Gateway API 기반 라우팅으로의 점진적 이전을 검토해 보시기를 권합니다.
참고 자료
- [Traefik 공식 문서](https://doc.traefik.io/traefik/)
- [Traefik Middleware 개요](https://doc.traefik.io/traefik/middlewares/overview/)
- [Traefik forwardAuth 미들웨어](https://doc.traefik.io/traefik/middlewares/http/forwardauth/)
- [Traefik TLS 설정](https://doc.traefik.io/traefik/https/tls/)
- [Traefik Kubernetes CRD 프로바이더](https://doc.traefik.io/traefik/providers/kubernetes-crd/)
- [Traefik 플러그인 개발 가이드](https://plugins.traefik.io/create)
- [Kubernetes Ingress 개념](https://kubernetes.io/docs/concepts/services-networking/ingress/)
- [Gateway API 공식 문서](https://gateway-api.sigs.k8s.io/)
- [cert-manager 공식 문서](https://cert-manager.io/docs/)
- [Helm 공식 문서](https://helm.sh/docs/)
현재 단락 (1/408)
Traefik을 단순한 리버스 프록시로만 쓰다가, 어느 순간 "인증을 모든 라우트에 공통으로 걸고 싶다", "특정 클라이언트만 mTLS로 받고 싶다", "신규 버전을 트래픽 5퍼센...