Kong Gateway 의 Advanced Load Balancing을 통해 Canary 배포 구현
Kong Gateway 를 활용하여 Canary 배포를 구현하는 것은 현대적인 애플리케이션의 DevOps 방법론과 CI/CD 배포 환경에서 중요한 주제입니다.
이 블로그 포스트에서는 Kong Gateway의 Advanced Load Balancing 기능을 통해 Canary 배포를 구현하는 방법을 상세히 설명합니다.
목차
1. Kong Gateway 와 Canary 배포란?
1-1. Kong Gateway 를 통한 Canary 배포의 장점
2. Kong Manager 를 통한 Canary 배포 구현
2-1. Kong Gateway Upstream 생성
2-2. Kong Gateway Gateway Services 및 Route 설정
2-3. Postman을 통한 Canary 배포 확인
3. Kong Admin API를 통한 Canary 배포 구현
1. Kong Gateway 와 Canary 배포란?
Kong Gateway는 API 관리를 위한 오픈소스 플랫폼입니다. 이는 API 트래픽을 관리하고 보호하는 데 필요한 다양한 기능을 제공하며, 마이크로서비스 아키텍처에서 API를 효율적으로 관리할 수 있게 해줍니다. Kong Gateway는 빠르고, 확장 가능하며, 플러그인을 통해 기능을 확장할 수 있습니다. 또한, 다양한 배포 환경에서 동작하며 API 요청을 라우팅, 인증, 트래픽 제어 및 로깅 등의 작업을 수행할 수 있습니다.
Kong의 커뮤니티용 Gateway OSS 버전을 설치하려면 NGINX STORE의 Kong Gateway, Kong Manager 설치 및 구성하기 포스트를 참고하세요.
Canary 배포는 새로운 소프트웨어 버전을 점진적으로 릴리스하여 전체 시스템에 미치는 영향을 최소화하는 배포 전략입니다. 초기에는 소수의 사용자에게만 새로운 버전을 배포하고, 문제가 없으면 점차 더 많은 사용자에게 배포를 확장해 나가는 방식입니다.
이는 새로운 기능이나 수정 사항이 실사용 환경에서 예상치 못한 문제를 일으킬 수 있는 위험을 줄이는 데 매우 효과적입니다.
1-1. Kong Gateway 를 통한 Canary 배포의 장점
Canary 배포의 주요 장점은 리스크 관리와 피드백 수집입니다. 새로운 버전이 소수의 사용자에게만 배포되기 때문에, 버그나 문제를 조기에 발견하고 수정할 수 있습니다. 또한, 실제 사용자 환경에서의 피드백을 통해 개선점을 신속히 반영할 수 있습니다. 이는 시스템 안정성을 유지하면서 새로운 기능을 지속적으로 제공할 수 있게 해줍니다.
Kong Gateway의 고급 로드 밸런싱 기능을 활용하면 Canary 배포를 더욱 효율적으로 관리할 수 있습니다. 이는 특정 트래픽을 선택적으로 라우팅할 수 있는 기능을 제공하여, 새로운 버전의 애플리케이션을 점진적으로 배포하는 데 이상적입니다. Kong Gateway는 다양한 조건에 따라 트래픽을 분배할 수 있어 Canary 배포를 정교하게 제어할 수 있습니다.
2. Kong Manager 를 통한 Canary 배포 구현
Kong Manager 대시보드를 통해서 Canary 배포를 손쉽게 구현할 수 있습니다. Kong의 커뮤니티용 Gateway OSS의 Advanced Load Balancing 기능은 트래픽을 다양한 방식으로 분배할 수 있는 기능을 제공합니다. 이를 통해 트래픽을 새로운 버전과 기존 버전 간에 효율적으로 분배할 수 있으며, Canary 배포 시 예상치 못한 문제 발생 시 신속하게 대응할 수 있습니다. 이러한 기능은 안정적인 Canary 배포를 지원하는 데 매우 유용합니다.
Kong Manager 를 통한 Canary 배포를 시작하기 위해서 Kong Manager 관리자 대시보드의 Upstreams 탭으로 접근하세요.
2-1. Kong Gateway Upstreams 생성
Upstreams은 Kong의 커뮤니티용 Gateway가 요청을 전달하는 API, 애플리케이션 또는 마이크로서비스를 의미합니다. Kong Gateway에서 Upstream 개체는 가상 호스트 이름을 나타내며 여러 서비스를 통해 들어오는 요청에 대해 Health Checks, 회로 차단, Load Balancing하는 데 사용할 수 있습니다.

New Upstream 버튼을 클릭하여 Canary 배포를 진행할 Upstream 서버를 생성합니다.

Name 필드에 생성 할 Upstream의 가상 호스트 이름을 지정합니다. Name 필드는 필수입력칸이며, 그 외는 모두 선택입력칸입니다.
- General Information
- Name: 요청을 전달하는 Upstream 가상 호스트의 이름을 지정합니다.
- Host Header: 요청을 전달하는 가상 호스트 개체의 Header를 지정합니다.
- Client Certificate: 설정하면 업스트림 서버로 TLS Handshaking 하는 동안 클라이언트 인증서로 사용할 인증서를 지정합니다.
- Tags: 그룹화 및 필터링을 위한 Upstream과 연결된 선택적 문자열 집합입니다.
- Load Balancing
- Algorithm: Load Balancing을 진행할 알고리즘을 선택합니다. 대표적으로 Round Robin 방식이 있습니다.
- Slots: 10 – 65536 범위의 정수를 허용하는 Upstream 서버 슬롯입니다.
- Hash Fallback: 기본 해시온이 해시를 반환하지 않는 경우 (예: 헤더가 누락되었거나 소비자가 식별되지 않음) 해시온이 쿠키로 설정된 경우 해시 인업으로 사용할 수 없습니다.
- Health Checks & Circuit Breakers
- Active Health Checks: Active Health Checks는 이름에서 알 수 있듯이 대상의 상태를 능동적으로 조사합니다. Upstream Entity에서 Active Health Check가 활성화되면 Kong은 업스트림의 각 대상에서 구성된 경로로 주기적으로 HTTP 또는 HTTPS 요청을 보냅니다.
- Passive Health Checks: Circuit Breakers라고도 하는 Passive Health Checks는 Kong이 프록시하는 요청(HTTP/HTTPS/TCP)을 기반으로 수행되며, 추가 트래픽이 발생하지 않습니다.
- Healthchecks Threshold: 설정값에 도달할때까지 Health Checks가 정상적으로 이루어지면 업스트림의 상태를 정상으로 간주하고 Health Checks를 중단합니다.


본 포스트에서 생성된 upstreams의 이름은 example-upstream 입니다. 해당 필드를 클릭한 뒤, Targets 탭으로 이동하여 Canary 배포를 진행할 서비스의 IP 혹은 도메인을 입력합니다.



Weight를 수정해 요청 중 90%는 host.example.com:8181로 이동하고, 10%는 host.example.com:8282로 이동 시키도록 구성합니다.

2-2. Kong Gateway Gateway Services 및 Route 설정
Gateway Services를 수정하여 Host를 생성한 Upstream 명으로 변경합니다.
(Gateway Services가 없다면 생성합니다.)

Route를 설정하여 Kong의 커뮤니티용 Gateway의 / (root 경로)로 접속할 시 GW-1 Gateway Services로 접속 되도록 라우팅 규칙을 설정합니다.

2-3. Postman을 통한 Canary 배포 확인
Postman과 같은 API 테스트 도구, 혹은 curl과 같은 HTTP Request 도구를 통해 Kong Gateway 서버로 약 10개의 Request를 전송한 뒤, Upstream Target 서버의 Logs를 통해 확인합니다.

Target 서버의 Logs를 확인해보면, 10개의 Request 중 9개의 Request는 Weight가 90인 Target 서버로 전달되었고, 약 1개의 Request 만이 Weight가 10인 서버로 전달되었습니다.

3. Kong Admin API를 통한 Canary 배포 구현
Kong Admin API를 통해 Upstream과 Target 서버를 생성하고, Weight를 실시간으로 수정하여 무중단 Canary 배포를 구현할 수 있습니다.
cURL 도구를 통해 API Request를 보내거나, Postman과 같은 API Request 테스트 도구를 통해 Kong API Gateway의 Upstream을 생성할 수 있습니다.
다음은 cURL 도구를 통해 Kong API Gateway Upstream을 생성하는 API입니다.
curl -v --request POST \
--url http://localhost:8001/upstreams \
--header 'Content-Type: application/json' \
--header 'accept: application/json' \
--data '{"name":"example-upstream","tags":[],"algorithm":"round-robin"}'
...
> Content-Type: application/json
> accept: application/json
> Content-Length: 64
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 201 Created
생성된 Upstream의 ID를 Kong API Gateway의 REST API를 통해 확인할 수 있습니다.
curl -v http://localhost:8001/upstreams/example-upstream
...
< HTTP/1.1 200 OK
< Date: Wed, 17 Jul 2024 00:24:21 GMT
< Content-Type: application/json; charset=utf-8
< Connection: keep-alive
...
{"client_certificate":null,"tags":null,"hash_on":"none","id":"7973a709-42e0-4b3a-80a8-3ba9a8136750","algorithm":"round-robin"
...
REST API를 통해 출력된 Upstream ID에 Target 생성 API를 통해 Upstream Target을 생성합니다. Target을 생성할 때, 가중치 값을 포함하여 POST 요청을 보냅니다.
curl -v --request POST \
--url http://localhost:8001/upstreams/example-upstream/targets \
--header 'Content-Type: application/json' \
--header 'accept: application/json' \
--data '{"target":"your-target-server-ip:port","upstream":{"id":"7973a709-42e0-4b3a-80a8-3ba9a8136750"},"weight":80,"tags":[]}'
...
> Content-Type: application/json
> accept: application/json
> Content-Length: 113
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 201 Created
...
{"created_at":1721178330.875,"updated_at":1721178330.875,"tags":[],"weight":100,"id":"dd618258-e209-43fc-8522-850a52d902e5","target":"your-target-server-ip:port","upstream":{"id":"7973a709-42e0-4b3a-80a8-3ba9a8136750"}}
GUI 대시보드를 확인해보면 Target 서버가 정상적으로 생성되었음을 확인할 수 있습니다,

동일한 API를 사용해 weight가 20인 Target 서버를 하나 더 생성합니다.
curl -v --request POST \
--url http://localhost:8001/upstreams/example-upstream/targets \
--header 'Content-Type: application/json' \
--header 'accept: application/json' \
--data '{"target":"your-target-server-ip:port","upstream":{"id":"7973a709-42e0-4b3a-80a8-3ba9a8136750"},"weight":20,"tags":[]}'

PATCH 메소드 API를 사용해 생성한 Target 서버들의 ID를 기반으로 Weiget 값을 수정합니다.
http://localhost:8001/upstreams/example-upstream/targets
...
"target": "bar.example.com:8000",
"id": "216de396-a64e-43ab-951e-9260a7699eaf",
"weight": 20,
"tags": []
},
...
"target": "foo.example.com:8000",
"id": "9daac0aa-724c-4a26-9ec0-3d978d3e5b2e",
"weight": 80,
...
PATCH 메소드 REST API를 통해 Upstream Target 서버의 Weight를 각각 70, 30으로 변경합니다.
foo.example.com Weight Patch
curl -v --request PATCH \
--url http://localhost:8001/upstreams/example-upstream/targets/9daac0aa-724c-4a26-9ec0-3d978d3e5b2e \
--header 'Content-Type: application/json' \
--header 'accept: application/json' \
--data '{"weight":70,"tags":[]}' # foo.example.com:8000 Target
...
< HTTP/1.1 200 OK
...
{"upstream":{"id":"7973a709-42e0-4b3a-80a8-3ba9a8136750"},"created_at":1721178665.333,"updated_at":1721352897.528,"target":"foo.example.com:8000","id":"9daac0aa-724c-4a26-9ec0-3d978d3e5b2e","weight":70,"tags":[]} # foo.example.com:8000 Target

bar.example.com Weight Patch
curl -v --request PATCH \
--url http://localhost:8001/upstreams/example-upstream/targets/216de396-a64e-43ab-951e-9260a7699eaf \
--header 'Content-Type: application/json' \
--header 'accept: application/json' \
--data '{"weight":30,"tags":[]}' # bar.example.com:8000 Target
...
< HTTP/1.1 200 OK
...
{"upstream":{"id":"7973a709-42e0-4b3a-80a8-3ba9a8136750"},"created_at":1721178665.333,"updated_at":1721352897.528,"target":"bar.example.com:8000","id":"216de396-a64e-43ab-951e-9260a7699eaf","weight":30,"tags":[]}

변경 후 Kong API Gateway를 통해 10개의 Request를 전송하면 2-3. Postman을 통한 Canary 배포 확인 목차와는 다르게 10개의 요청 중 70%는 foo.example.com 서버로, 30%는 bar.example.com 서버로 트래픽이 전달되는 것을 확인할 수 있습니다.

이러한 Kong Gateway의 Upstream Weight 설정을 통해 손쉽게 Canary 배포를 구현할 수 있습니다.
댓글을 달려면 로그인해야 합니다.