Kubernetes 2026.10.29 6 min read

MetalLB VIP 하나에 Traefik을 연결해 Host별 HTTP 경로를 나눴다

먼저 MetalLB의 LoadBalancer Service를 단독으로 시험하고, 그 주소를 Traefik의 진입점으로 옮기는 순서를 잡았다. 외부 IP가 할당되는 단계와 HTTP Host에 따라 backend가 선택되는 단계를 나눠 확인하기 위해서였다.

Pod와 Service의 내부 통신을 확인한 다음에는 클러스터 밖에서 접속할 경로가 필요했다. 내부의 ClusterIP로만 시험하던 단계에서 벗어나, 관리 서버에서 외부 주소로 요청하고 나중에는 여러 서비스를 같은 진입점에 연결하려 했다.

먼저 MetalLB의 LoadBalancer Service를 단독으로 시험하고, 그 주소를 Traefik의 진입점으로 옮기는 순서를 잡았다. 외부 IP가 할당되는 단계와 HTTP Host에 따라 backend가 선택되는 단계를 나눠 확인하기 위해서였다.

주소 풀과 L2 광고부터 확인했다

MetalLB는 Layer 2 방식으로 구성했다. 관리자가 사용할 주소 범위를 정하고 IPAddressPool과 L2Advertisement를 준비했다. 당시 설치 안내에서 참조한 manifest는 v0.16.1이었다. 이 값은 당시 선택한 자료의 버전이며 현재 환경의 설치 기준으로 일반화하지 않았다.

MetalLB IPAddressPool과 L2Advertisement
MetalLB IPAddressPool과 L2Advertisement.

MetalLB가 DHCP 서버에 새 주소를 요청한다고 이해하지 않도록 구조를 다시 정리했다. 내가 지정한 풀에서 LoadBalancer Service에 주소를 할당하고, 해당 주소를 L2에서 알리는 구성이었다. 따라서 사용할 주소가 기존 네트워크의 다른 장비와 겹치지 않는지 먼저 정할 필요가 있었다.

kubectl get ipaddresspools -n metallb-system
kubectl get l2advertisements -n metallb-system

주소 풀만 등록하고 끝내지 않고 controller와 speaker의 상태도 확인 대상으로 삼았다. 이후 테스트 전용 namespace에서 Nginx를 두 replica로 실행하고 LoadBalancer Service를 만들었다. Service에는 시험에 사용할 VIP를 지정했다. 실제 내부 주소는 이 글에서 생략했다.

클러스터 밖에서 HTTP 응답을 확인했다

테스트의 출발점은 Service에 외부 주소가 보이는지였다. 이어 Kubernetes 노드 밖에 있는 관리 서버에서 그 VIP로 HTTP 요청을 보냈다. 주소 할당 상태와 외부에서 요청이 도달한 결과를 함께 확인하는 흐름이었다.

이 단계의 완료 기준은 MetalLB 구성요소, 풀과 광고 설정, Nginx 배포와 Service 상태, 외부 HTTP 응답이었다. 해당 시험을 마친 뒤 다음 단계로 넘어갔다. 이 결과만으로 노드 장애 시 VIP 전환 시간이나 전체 가용성까지 측정했다고 주장하지는 않았다.

서비스 하나에 외부 주소를 하나씩 쓰는 시험은 진입 경로를 확인하는 데 도움이 됐다. 다음에는 같은 진입점으로 들어온 요청을 서비스별로 나누려 했다. 이 역할을 Traefik에 맡겼다.

시험 Service의 VIP를 Traefik으로 옮겼다

Traefik에도 앞서 시험한 VIP를 사용하려 했다. 그러려면 먼저 그 주소를 점유한 테스트 Service를 정리해야 했다. 시험 전용 namespace의 리소스를 확인하고 제거한 뒤 주소가 다른 Service에 남아 있지 않은지 살펴보는 순서로 진행했다.

MetalLB와 주소 풀 자체는 유지했다. 정리 범위는 앞서 만든 시험용 서비스였다. 한 번 검증한 외부 주소를 다시 사용하면서 주소 할당 계층을 그대로 두고 HTTP 라우팅 계층만 추가하려는 작업이었다.

초기 Traefik 구성은 HTTP 80을 노출하고 LoadBalancer Service를 사용하도록 잡았다. IngressClass를 traefik으로 지정하고 기본 클래스로 사용하지 않는 값으로 준비했다. 테스트에서 사용할 Kubernetes Ingress provider를 켜고 dashboard는 외부에 노출하지 않는 방향이었다.

당시의 Helm values는 이 구성 의도를 보여 주는 자료였다. 실제 적용 결과는 Pod, Service, IngressClass와 Helm release 상태를 확인하는 대상으로 삼았다. values에 적은 키가 있다는 사실만으로 그 키의 모든 효과를 단정하지 않고 결과 리소스의 상태를 함께 보려 했다.

Traefik LoadBalancer Service와 MetalLB Controller·Speaker 상태
Traefik LoadBalancer Service와 MetalLB Controller·Speaker 상태.

같은 VIP에서 APP-OK와 API-OK를 나눴다

HTTP 라우팅 시험은 작은 echo 애플리케이션 두 개로 진행했다. 하나는 APP-OK, 다른 하나는 API-OK를 반환하게 했고 각각 Service를 뒀다. 공개 글에서는 두 Host를 app.demo.internal과 api.demo.internal로 부른다.

Ingress의 구조는 두 Host를 서로 다른 Service에 연결하는 것이었다. 두 경로 모두 루트 경로를 Prefix로 받도록 했다. 같은 외부 주소에 접속하더라도 요청의 Host가 다르면 다른 backend로 가는지 확인하려 했다.

ingressClassName: traefik
# app.demo.internal → app Service
# api.demo.internal → api Service

처음부터 DNS 구성이 끝났다고 가정하지 않고 curl의 resolve 옵션으로 이름과 VIP를 연결해 요청했다. 단순히 VIP에 접속하는 것과 원하는 Host로 요청하는 것은 달랐다. IP 접근이 된다는 결과만으로 Host 기반 규칙까지 동작한다고 볼 수 없었다.

두 응답을 정상 확인하면서 초기 HTTP 경로 검증을 마쳤다. 이후 실제 애플리케이션을 올리는 작업에서도 이 데모가 유지되는지를 확인했다. 새 서비스를 추가하는 작업이 기존 요청 경로에 영향을 주는지도 함께 봐야 했기 때문이다.

HTTPS는 뒤의 애플리케이션 배포에서 별도로 추가했다. 초기 시험부터 인증서와 HTTPS 진입점이 있었다고 합쳐 설명하지 않았다. 이 단계에서 확인한 결과는 MetalLB의 외부 VIP와 Traefik의 Host 기반 HTTP 라우팅이었다. 외부 주소와 애플리케이션 라우팅을 나눠 검증한 덕분에 이후 문제에서도 어느 계층을 먼저 볼지 기준을 세울 수 있었다.

RCA Platform Ingress와 Traefik VIP·Endpoint
RCA Platform Ingress와 Traefik VIP·Endpoint.

후속 HTTPS 검증에서는 사설 CA와 rca.lab.test 이름을 검증하고 /health/ready가 200을 반환하는 것까지 별도로 확인했다. 초기 HTTP 데모와 후속 실제 애플리케이션 HTTPS를 시점별로 구분해 남겼다.

SEARCH JOURNAL

기록 검색

글 제목, 요약, 태그에서 찾습니다.

검색을 준비하고 있어요.

검색어를 입력해 주세요.

    Ctrl/⌘ K 검색 Esc 닫기 ↑ ↓ 결과 이동