[Traefik] 소개 및 기본 사용법
Traefik은 k8s 기반 환경에서 주류로 떠오른 로드밸런서 시스템 중 하나다,
Docker, 쿠버네티스, 온프레미스 환경에서 모두 사용 가능하나, 컨테이너 환경에 더 최적화되어있다.
특징
기존의 리버스 프록시 시스템들과 용도가 크게 다를건 없는데, 컨테이너 환경에 좀 더 친화적이라는게 좀 다른 지점이다.
고전적인 로드밸런서-리버스 프록시 시스템들은 서버는 서버대로 두고, 로드밸런서가 직접 서버를 가리키게끔 수정하는 중앙제어식 구조를 갖고 있다.
반면, traefik은 서버들이 일정 조건을 충족하면, traefik이 자동으로 감지하고 가로채서 연결을 하는 독특한 구조를 갖고 있다.
그래서 관리포인트가 좀 미묘하긴 한데, 꽤 간편한 지점도 있어서 매니아들이 상당수 존재한다.
단점은, 확실히 HAProxy, nginx 같은 고인물들에 비하면 근본적인 기능이 엄청 많이 딸린다는 것이다.
로드밸런싱 알고리즘도 roundrobin 밖에 없고, 무중단 배포를 위한 connection draining 기능도 아예 존재하지 않는다.
나는 전반적인 성숙도가 많이 떨어진다고 느꼈다.
시작해보기
docker compose를 통해서 빠르게 시작해보겠다.
version: '3'
services:
reverse-proxy:
# The official v3 Traefik docker image
image: traefik:v3.4
# Enables the web UI and tells Traefik to listen to docker
command: --api.insecure=true --providers.docker
ports:
# The HTTP port
- "4080:80"
# The Web UI (enabled by --api.insecure=true)
- "8080:8080"
volumes:
# So that Traefik can listen to the Docker events
- /var/run/docker.sock:/var/run/docker.sock
traefik에는 2개의 포트가 필요하다.
실제 로드밸런서 엔드포인트로 사용할 포트와, WebUI 포트다.
traefik은 단일 엔드포인트에 여러개의 도메인을 달아서 여러개의 서버를 연결하는 방식을 취한다.
실행해서 엔드포인트에 꽂아보면
아무것도 없다. 원래 이건 이렇게 깨지는게 맞다.
그리고 WebUI로 들어가면

꽤 볼만한 UI가 제공되는 것을 볼 수 있다.
새로운 서버가 연결되면 이 목록에도 추가가 된다.
서버 추가
자, 그럼 로드밸런서에 서버를 연결해보자.
이미지는 내가 대충 말아둔거다.
server:
# A container that exposes an API to show its IP address
image: myyrakle/node-server-for-test
labels:
- "traefik.enable=true"
- "traefik.http.routers.myserver.rule=Host(`myserver.docker.localhost`)"
- "traefik.http.services.myserver.loadbalancer.server.port=80" # 컨테이너 내부 포트
여기서 중요한건 다른게 아니라 레이블이다.
레이블을 통해서 이 서버가 어떤 형태로 traefik에 붙고싶은지 자기주장을 한다.
가장 중요한건 Host를 지정하는 부분이다. 저 Host를 통해 로드밸런서 엔드포인트로 진입이 가능해지기 때문이다.
그렇게 실행해보면
HTTP 서비스 목록에 추가가 될텐데
그러면 이렇게 방금 지정한 호스트에 로드밸런서 포트 쌍의 엔드포인트로 접근이 가능해지고


실제로 curl로 접근할 때는, 이런 식으로 Host 값을 넘겨주는 형태로 실제 서버에 라우팅할 수 있다.
서버를 외부로 개방해야 한다면 이 조합으로 개방하면 된다.
스케일링
replica를 2개로 늘려보자.
스케일링은 매우 간편한 편에 속한다.
그냥 동일한 옵션으로 컨테이너만 더 띄우면

알아서 붙여주기 때문이다.
단점은, 로드밸런싱 알고리즘의 선택 자유도가 매우 좁다는 것이다.
얼마 전까지만 해도 roundrobin만 제공되다가 Power of two choices라는 이상한게 추가돼서 2가지다.
무중단 교체?
traefik에서 무중단배포/교체를 구현하는건 좀 복잡하고 불편한 편이다. 지저분한 트릭을 사용해야 한다.
그냥 서버 내린다고 되는게 아니고, 서버를 내리더라도 traefik이 미리 알 수 있는 구조가 아니기 때문에 그 순간에 라우팅된 요청에 대해서는 실패가 발생한다.
어째서인지는 모르겠지만, 이에 대해서 모범 답안도 잘 정리되어있지 않고 문서에도 뭐가 없었다.
그리고 애당초 traefik은 connection을 Draining하는 기능이 존재하지 않는다. 서버를 하나 제거해야 한다면 그 서버에 대한 신규 요청을 닫고 기존 요청만 처리하게 해야 안전한 교체가 가능한데, 그게 아예 없다.
개발중이라고는 하는데 소식이 없다.
그래서 중단을 막으려면 어떻게든 종료 대상 서버에 트래픽이 들어가지 않도록 꼼수를 써야한다. 헬스체크를 실패하게 만들어서 요청이 들어오지 않게 하거나, weight을 지정해서 몰리지 않게 하거나 하는 방법이 있다.
사실 이게 왜 주류인지도 잘 모르겠다.
참조
https://doc.traefik.io/traefik/getting-started/quick-start/
https://www.maxcountryman.com/articles/zero-downtime-deployments-with-docker-compose
https://github.com/traefik/traefik/issues/41