- Kamal Proxy는 웹 애플리케이션 앞에서 동작하는 작은 HTTP 프록시로, 진행 중인 트래픽을 끊지 않고 새 인스턴스로 배포를 전환하도록 설계됨
- 새 인스턴스는
kamal-proxy deploy로 등록되며, 프록시가 HTTP 헬스 체크를 통과한 뒤에만 새 트래픽을 해당 인스턴스로 라우팅함 - 배포 명령은 이전 인스턴스의 트래픽이 모두 빠질 때까지 기다리므로, 성공적으로 반환된 뒤에는 진행 중 요청 중단 없이 이전 인스턴스를 제거할 수 있음
- 단일 프록시에서 여러 애플리케이션을 운영할 수 있도록 호스트 기반 라우팅, 경로 기반 라우팅, 자동 TLS와 수동 TLS 인증서 지정 기능을 제공함
- Kamal Proxy는 Kamal 배포 도구의 일부로 설계됐지만, 단독 실행이나 다른 배포 도구의 구성 요소로도 사용할 수 있음
Kamal Proxy가 하는 일
- Kamal Proxy는 제로 다운타임 배포 조율을 쉽게 하기 위한 작은 HTTP 프록시임
- 웹 애플리케이션을 Kamal Proxy 뒤에서 실행하면, 진행 중인 트래픽을 중단하지 않고 변경 사항을 배포할 수 있음
- 이 동작을 위해 애플리케이션 쪽의 특별한 협력은 필요하지 않음
- Kamal Proxy는 컨테이너 패키징과 프로비저닝을 포함하는 Kamal의 일부로 동작하도록 설계됨
- 단독으로 사용하거나 다른 배포 도구의 일부로 사용할 수도 있음
실행과 배포 흐름
- 프록시 인스턴스는
kamal-proxy run명령으로 실행함 - 설정 파일은 없으며, 기본값이 애플리케이션에 맞지 않을 때 옵션을 지정할 수 있음
- 기본 HTTP 포트는
80 - 다른 포트로 실행하려면
kamal-proxy run --http-port 8080사용 - 전체 옵션은
kamal-proxy help run에서 확인 가능
- 기본 HTTP 포트는
- 트래픽을 웹 애플리케이션으로 보내려면 애플리케이션 인스턴스를 프록시에 deploy함
- 배포 대상 인스턴스는
hostname:port형식으로 지정함- 예:
kamal-proxy deploy service1 --target web-1:3000 - 이 명령은
web-1:3000을service1서비스 이름으로 등록함
- 예:
제로 다운타임 전환 방식
- 새 인스턴스가 등록되면 Kamal Proxy는 즉시 HTTP 헬스 체크를 실행해 접근 가능성과 동작 여부를 확인함
- 헬스 체크가 성공하면 새 트래픽을 새 인스턴스로 라우팅하기 시작함
- 새 인스턴스가 적절한 시간 안에 healthy 상태가 되지 못하면
deploy명령은 배포를 중단하고 0이 아닌 종료 코드를 반환함 - 각 배포는 이전에 배포된 인스턴스의 모든 트래픽을 새 인스턴스로 넘김
deploy명령은 이전 인스턴스에서 트래픽이 모두 빠질 때까지 기다린 뒤 반환함- 성공적으로 반환된 뒤에는 이전 인스턴스를 제거해도 진행 중 요청을 끊지 않음
- 새 인스턴스가 healthy 상태일 때만 트래픽을 받고, 이전 인스턴스는 완전히 drain된 뒤 제거되므로 배포가 제로 다운타임으로 진행됨
헬스 체크 설정
- 기본 헬스 체크는 각 서비스에 대해 초당 1회
/up으로GET요청을 보냄 200응답을 healthy 상태로 간주함- 애플리케이션에 맞게 헬스 체크를 바꾸려면
deploy플래그를 사용함--health-check-path--health-check-port--health-check-timeout--health-check-interval
- 헬스 체크 경로 변경 예시:
kamal-proxy deploy service1 --target web-1:3000 --health-check-path web/index.html
- 메인 서비스와 다른 포트에서 헬스 엔드포인트를 노출하는 경우:
kamal-proxy deploy service1 --target web-1:3000 --health-check-port 8080
라우팅 기능
-
호스트 기반 라우팅
- 호스트 기반 라우팅을 사용하면 하나의 Kamal Proxy 인스턴스로 같은 서버의 여러 애플리케이션에 트래픽을 라우팅할 수 있음
- 배포 시 특정 호스트를 지정할 수 있음
kamal-proxy deploy service1 --target web-1:3000 --host app1.example.com- 이 방식으로 배포된 인스턴스는 지정된 호스트의 트래픽만 받음
- 각 애플리케이션에 별도 호스트를 지정하면 포트 충돌 없이 같은 서버에서 여러 애플리케이션을 실행할 수 있음
- 특정 호스트는 한 번에 하나의 서비스만 라우팅할 수 있음
- 이미
service1이app1.example.com을 사용 중이면service2가 같은 호스트로 배포될 때 오류가 반환됨 service1을 제거한 뒤에는service2를 같은 호스트에 배포할 수 있음
-
경로 기반 라우팅
- 경로 기반 라우팅은 요청 경로에 따라 트래픽을 다른 서비스로 나누는 애플리케이션에 사용함
- 서비스는 서로 다른 경로 접두사 아래에 마운트될 수 있음
/api로 시작하는 요청을web-1로 보내는 예:kamal-proxy deploy service1 --target web-1:3000 --path-prefix=/api- 나머지를
web-2로 보내는 예:kamal-proxy deploy service2 --target web-2:3000 - 기본적으로 경로 접두사는 upstream으로 전달되기 전에 제거됨
/api/users/123요청은web-1에/users/123으로 전달됨- 원래 경로를 그대로 전달하려면
--strip-path-prefix=false를 지정함
TLS 지원
- Kamal Proxy는 애플리케이션용 TLS 인증서를 자동으로 획득하고 갱신할 수 있음
- 자동 TLS는 배포 시
--tls플래그를 추가해 활성화함kamal-proxy deploy service1 --target web-1:3000 --host app1.example.com --tls
- 자동 TLS에는 호스트 지정이 필요함
- 임의 호스트명에 대해 악의적으로 인증서를 요청하지 못하게 하기 위한 조건임
- 경로 기반 라우팅에서 TLS 옵션은 루트 경로에 설정해야 함
- 같은 호스트의 다른 경로에 배포된 서비스는 루트 경로에 지정된 TLS 설정을 사용함
- 수동으로 획득한 TLS 인증서, 자체 인증 기관, Cloudflare origin certificate을 설치해야 하는 경우 인증서 파일과 개인 키 경로를 직접 지정할 수 있음
--tls-certificate-path cert.pem--tls-private-key-path key.pem
환경 변수와 빌드
- Docker 컨테이너 실행 같은 환경에서는
run옵션을 환경 변수로 지정할 수 있음 kamal-proxy run은 설정된 환경 변수가 있으면 각 옵션 값을 환경 변수에서 읽음kamal-proxy run --http-port 8080HTTP_PORT=8080 kamal-proxy run
- 환경 변수 이름이 기존 환경과 충돌하면
KAMAL_PROXY_접두사를 붙여 구분할 수 있음KAMAL_PROXY_HTTP_PORT=8080 kamal-proxy run
- 로컬 빌드는 동작하는 Go 환경에서
make로 수행함 - Docker 컨테이너로 빌드하려면
make docker를 사용함 - 프록시 명령을 시험해볼 수 있는 Docker Compose 설정은
example폴더에 있음