Kong Gateway는 마이크로서비스 아키텍처에서 API 트래픽을 관리하고 보호하기 위한 오픈소스 API Gateway입니다.
로드 밸런싱, 인증, 라우팅, 속도 제한, 로깅, 플러그인 기반 확장성 등을 제공하며, 클라우드 네이티브 환경에 적합한 유연하고 확장 가능한 구조를 갖추고 있습니다.
이번 글에서는 Kubernetes 환경에서 GitOps 방식으로 Kong Gateway를 배포하고, 서비스 등록과 라우팅 구성, 그리고 OIDC 플러그인을 활용한 API 접근 제어까지 단계별로 살펴보겠습니다.
다음과 같은 순서로 Kong Gateway 설치부터 인증 및 라우팅 기능 구성까지의 과정을 소개하겠습니다.
- 설치 환경
- Kong Gateway 설치
- Kong Manager와 Admin API 소개
- 서비스(Service) 및 라우트(Route) 등록
- Key Authentication 플러그인 설정
- OIDC 플러그인 설정(Keycloak 연동)
- 마무리
1. 설치 환경
Kong Gateway 설치를 위해 사전에 준비되어 있어야 하는 환경 구성 정보입니다.
- Kubernetes v1.30
- Keycloak 25.0.4
- Kustomize v1.30.0
- Helm v3.17.1
※ 모든 구성 요소는 arm64(aarch64) Linux 아키텍처를 기준으로 합니다.
이 설치 환경 구성에 대한 자세한 방법은 아래 블로그를 참고하세요.
2. Kong Gateway 설치
이 글에서는 Kong Helm Chart를 Kustomize로 배포할 수 있도록 구성된 GitOps 리소스를 사용해 Kong Gateway를 설치합니다.
- Kong Helm Chart 26.4.0
- Kong Gateway 3.9
Kubernetes 환경에 Kong Gateway를 배포하기 위해, GitHub의 gitops-demo 저장소를 클론합니다.
git clone https://github.com/cnapcloud/gitops-demo.git
cd gitops-demo/kong
Kong OIDC 플러그인과 Keycloak을 연동하여 인증하기 위해 Dev Overlay의 patches/add-host-alias.yaml 파일에 Keycloak 도메인과 해당 호스트의 IP를 추가해야 합니다. 이 설정은 Kong Gateway Pod의 /etc/hosts 파일에 해당 도메인을 수동으로 매핑하기 위해 사용됩니다.
- op: add
path: /spec/template/spec/hostAliases
value:
- ip: "192.168.64.2"
hostnames:
- "keycloak.cnap.dev"
gateway 네임스페이스 생성하고 Kong Gateway를 배포합니다.
make namespace
make apply
kubectl 명령어로 Kong Gateway와 관련 리소스가 정상적으로 배포되었는지 확인하고
/etc/hosts 파일에 인그레스 도메인을 등록합니다.
# 설치 확인
kubectl -n gateway get deploy,pod,ingress
# /etc/hosts
127.0.0.1 kong-proxy.cnap.dev kong-manager.cnap.dev kong-admin.cnap.dev
127.0.0.1 kong-httpbin.cnap.dev
Kong Proxy, Admin API, Manager에 대해 외부 도메인을 통해 접근할 수 있도록 구성했으며, dev 도메인은 SSL 통신이 필수이기 때문에 인그레스에 자체 서명된 인증서를 적용하여 보안을 설정했습니다.
이 글은 Helm과 Kustomize를 이용한 GitOps 배포 전략 블로그에서 배포한 HttpBin 애플리케이션을 사용하여 Kong Gateway를 설정하는 방법을 설명하기 위해 kong-httpbin.cnap.dev 도메인을 가지고 새로운 인그레스를 추가했습니다.
3. Kong Manager와 Admin API 소개
Kong Manager는 Kong Gateway의 관리 UI입니다. 브라우저에서 https://kong-manager.cnap.dev에 접속하면 클러스터의 서비스, 라우트, 플러그인 등을 시각적으로 관리할 수 있습니다.
Kong Admin API는 Kong의 모든 설정을 RESTful API로 관리할 수 있도록 제공하는 인터페이스입니다. 보통 https://kong-admin.cnap.dev를 통해 접근하며, CI/CD나 자동화 스크립트에서 활용됩니다. 이 글에서는 기본적인 설정 작업을 Kong Admin API를 통해 직접 수행합니다.
Kong 설정 변경이나 삭제에 대한 API 사용법은 다루지 않기 때문에 https://kong-manager.cnap.dev를 사용해야 합니다. Kong Manager는 등록된 서비스, 라우트, 플러그인 등의 설정 현황을 시각적으로 확인하는 용도로 활용하시면 좋습니다.
※ 주의 사항
이 설치에는 Kong Manager와 Admin API에 대한 인증 설정이 포함되어 있지 않습니다.
따라서 https://kong-manager.cnap.dev 또는 https://kong-admin.cnap.dev에 접속할 경우, 별도의 인증 없이 누구나 접근할 수 있는 상태입니다.
운영 환경에서는 이러한 관리자 인터페이스에 대한 접근을 보호하기 위해 인증 설정이 필요합니다.
인증 설정은 Kong의 Key Athentication, OIDC, 또는 ACL 플러그인 등을 활용하여 상황에 맞는 인증 및 접근 제어를 구성할 수 있습니다.
4. Gateway 서비스 및 라우트 구성
Kong Gateway를 통해 외부에서 백엔드의 HttpBin 애플리케이션에 접근하려면, 먼저 Service와 Route를 등록해야 합니다.
# 서비스 등록
curl -sk -X POST https://kong-admin.cnap.dev/services \
--data "name=httpbin" \
--data "url=http://httpbin.httpbin.svc"
# 라우트 등록
curl -sk -X POST https://kong-admin.cnap.dev/services/httpbin/routes \
--data "name=httpbin" \
--data "paths[]=/" \
--data "hosts[]=kong-httpbin.cnap.dev"
서비스와 라우트를 등록하면, Kong Proxy를 통해 외부에서 HttpBin 애플리케이션에 접근할 수 있습니다. 인그레스는 kong-httpbin.cnap.dev 도메인을 사용하며, Kong Gateway 설치 시 함께 구성되므로 별도 설정은 필요하지 않습니다.
# httpbin 인그레스 설정
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
labels:
app.kubernetes.io/instance: httpbin
app.kubernetes.io/name: httpbin
name: httpbin
spec:
ingressClassName: nginx
rules:
- host: kong-httpbin.cnap.dev
http:
paths:
- backend:
service:
name: kong-proxy
port:
number: 80
path: /
pathType: Prefix
tls:
- hosts:
- kong-httpbin.cnap.dev
secretName: kong-tls
curl이나 브라우저를 사용하여 Kong Gateway를 통해 HttpBin 애플리케이션에 접근할 수 있습니다.
curl https://kong-httpbin.cnap.dev
5. Key Authentication 플러그인 설정
Key Authentication 플러그인은 Kong에서 가장 간단한 인증 방식으로, API 키를 통해 요청자의 접근을 제어합니다. 백엔드 서비스 접근시에 사전에 등록된 API 키를 Header에 포함해 요청해야 하며, Kong은 이 키를 기반으로 인증을 수행합니다. 간단한 보호가 필요한 서비스나 테스트 환경에서 빠르게 적용할 수 있는 인증 방법입니다.
다음과 같이 httpbin API 요청에 Key 기반 인증을 적용하기 위해 Key Authentication 플러그인을 활성화하고, Consumer를 등록한 후 고유 키를 생성합니다.
# Key Authentication 플러그인 활성화
curl -sk -X POST https://kong-admin.cnap.dev/services/httpbin/plugins --data "name=key-auth"
# Consumer 등록
curl -i -k -X POST https://kong-admin.cnap.dev/consumers/ --data "username=demo"
# API 키 생성
curl -sk -X POST https://kong-admin.cnap.dev/consumers/demo/key-auth --data "key=1234"
이렇게 설정을 하고 나서, HttpBin 애플리케이션에 접근하려면 apikey Header를 통해 키를 함께 전달해야 합니다
curl -sk -H "apikey: 1234" \
-H "accept: application/json" \
-X GET "https://kong-httpbin.cnap.dev/ip"
이 플러그인은 Header의 apikey 값을 가지고 Consumer의 Credential과 비교하여 인증하며, 유효한 Key가 있으면 해당 Consumer로 라우팅됩니다. 단, 기본값이 apikey로 설정된 Header의 Key Name이 다른 플러그인이 여러개가 활성화되는 경우 각각의 Key Name마다 별도 Consumer가 필요합니다.
※ Consumer에 대하여
Key Authentication과 같이 Consumer를 기반으로 사용하는 플러그인은 Kong 내부에서 API 요청 주체를 구분하고 관리하기 위해 사용합니다.
Kong에서 말하는 Consumer는 외부 사용자가 아니라, Kong 내에서 API 호출 주체를 식별하고 권한, 인증, 정책을 적용하기 위한 내부 개념입니다.
따라서 Consumer를 등록하고 고유한 키를 발급한 뒤, 이를 통해 각 요청이 어떤 Consumer로부터 왔는지 구분하여 인증을 수행합니다.
6. OIDC 플러그인 연동 (Keycloak)
Kong의 OIDC(OpenID Connect) 플러그인은 외부 인증 서버를 통해 OAuth 2.0/ OpenID Connect 기반의 인증 및 권한 부여를 처리할 수 있도록 도와주는 강력한 인증 플러그인입니다. 이 플러그인을 활용하면 API Gateway 레벨에서 인증을 수행할 수 있어, 마이크로서비스 각각에서 인증 로직을 구현할 필요가 없습니다.
백엔드 서비스에서 사용자 정보나 권한이 필요한 경우를 위해 OIDC 플러그인은 인증 과정에서 획득한 Access Token과 사용자 정보를 HTTP Header를 통해 업스트림으로 전달해줍니다. 이를 통해 백엔드는 인증 상태를 신뢰하고 사용자 식별 및 권한 처리에 활용할 수 있습니다.
Kong OSS OIDC 플러그인
Kong의 오픈소스 버전은 기본적으로 OIDC 플러그인을 제공하지 않습니다.
이에 Kong Gateway 3.9를 베이스 이미지로 하여, lua-resty-openidc 라이브러리(~> 1.8.0)를 활용해 OIDC 기능을 직접 구현한 커스텀 플러그인을 사용합니다.
OIDC 플러그인이 포함된 Docker 이미지는 Docker Hub에 다음과 같이 등록되어 있습니다.
docker.io/cnapcloud/kong-oidc:3.9.1
Kong의 OIDC 플러그인을 활용해 인증 기능을 구성하기 위해, 이전 블로그에서 설정한 Keycloak 환경을 기반으로 그대로 사용합니다.
6-1. Keycloak 클라이언트 생성
Kong Gateway가 Keycloak과 OIDC 프로토콜을 통해 인증을 수행하려면, Keycloak 클라이언트가 요구됩니다. 이 클라이언트는 사용자 인증 후 리디렉션 받을 URL과 클라이언트 타입 등의 설정을 포함합니다.
다음과 같이 Keycloak Admin API를 사용해 httpbin 클라이언트를 생성하겠습니다.
- 토큰 발급: 관리자 계정으로 로그인하여 Admin API 사용을 위한 Access Token을 발급받습니다.
POST /realms/{realm}/protocol/openid-connect/token - 클라이언트 등록: Kong에 해당하는 OIDC 클라이언트를 생성합니다.
→ POST /admin/realms/{realm}/clients - 클라이언트 UUID 및 Secret 조회: 등록된 클라이언트의 내부 ID(UUID)와 비공개 클라이언트인 경우 사용할 Secret을 조회합니다.
→ GET /admin/realms/{realm}/clients?clientId=…
→ GET /admin/realms/{realm}/clients/{id}/client-secret
이미 httpbin 클라이언트가 존재할 경우 등록을 생략하고 Keycloak Admin API로 Access Token을 발급받아 클라이언트 싯크릿을 바로 조회합니다. 또는 Keycloak Admin Console을 통해 직접 확인할 수도 있습니다.
“keyclock-client.sh”
#!/bin/sh
# 환경 변수 설정
export KEYCLOAK_URL="https://keycloak-admin.cnap.dev"
export REALM="cnap"
export USER="admin"
export PASSWORD="password"
export CLIENT_ID="httpbin"
# 토큰 요청
ACCESS_TOKEN=$(curl -sk \
-d "client_id=admin-cli" \
-d "username=${USER}" \
-d "password=${PASSWORD}" \
-d "grant_type=password" \
"${KEYCLOAK_URL}/realms/master/protocol/openid-connect/token" | jq -r '.access_token')
echo "ACCESS_TOKEN=${ACCESS_TOKEN}"
# 클라이언트 등록
curl -sk -X POST "${KEYCLOAK_URL}/admin/realms/${REALM}/clients" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
-d '{
"clientId": "'"${CLIENT_ID}"'",
"enabled": true,
"protocol": "openid-connect",
"redirectUris": ["*"],
"baseUrl": "https://kong-httpbin.cnap.dev",
"webOrigins": ["https://kong-httpbin.cnap.dev"],
"attributes": {
"post.logout.redirect.uris": "+"
},
"bearerOnly": false,
"consentRequired": false,
"standardFlowEnabled": true,
"directAccessGrantsEnabled": true,
"publicClient": false,
"clientAuthenticatorType": "client-secret"
}' || true
# 클라이언트 UUID 조회
CLIENT_UUID=$(curl -sk -H "Authorization: Bearer ${ACCESS_TOKEN}" \
"${KEYCLOAK_URL}/admin/realms/${REALM}/clients?clientId=${CLIENT_ID}" \
| jq -r '.[0].id')
echo "\nCLIENT_UUID=${CLIENT_UUID}"
# 클라이언트 시크릿 조회
CLIENT_SECRET=$(curl -sk -H "Authorization: Bearer ${ACCESS_TOKEN}" \
"${KEYCLOAK_URL}/admin/realms/${REALM}/clients/${CLIENT_UUID}/client-secret" \
| jq -r '.value')
echo "CLIENT_SECRET=${CLIENT_SECRET}"
6-2. Kong에 OIDC 플러그인 적용
Keycloak에서 httpbin 클라이언트 ID와 시크릿을 생성했다면, 이제 Kong에 OIDC 플러그인을 적용하여 인증 흐름을 연결할 차례입니다. 아래와 같이 curl 명령을 사용하여 Kong Admin API를 통해 httpbin 서비스에 OIDC 플러그인을 등록합니다. 주요 설정 항목은 다음과 같습니다:
- name=oidc: 플러그인 이름 (OpenID Connect)
- config.client_id, config.client_secret: Keycloak에 등록한 클라이언트 정보
- config.discovery: Keycloak이 제공하는 OIDC 메타데이터 URL (issuer, endpoints, public key 등 자동 구성)
- config.bearer_only: 브라우저 리디렉션 없이 Access Token으로만 인증할 경우 사용
- config.introspection_endpoint: Access Token 토근을 가지고 유효성을 검사
- config.redirect_after_logout_uri: 로그아웃 후에 리다이렉트되어야 하는 URI
- config.logout_path: 로그아웃 경로
브라우저 기반 인증 (Keycloak 로그인 화면)
curl -sk -X POST https://kong-admin.cnap.dev/services/httpbin/plugins \
-d name=oidc \
-d config.client_id=httpbin \
-d config.client_secret=${CLIENT_SECRET} \
-d config.discovery=https://keycloak.cnap.dev/realms/cnap/.well-known/openid-configuration \
-d config.redirect_after_logout_uri=https://kong-httpbin.cnap.dev \
-d config.logout_path=/logout \
| jq
브라우저 기반의 인증에서 로그 아웃은 OIDC 플러그인에 설정된 로그아웃 패스에 요청을 한다. 로그아웃 요청이 되면 OIDC 플러그인이 설정된 서비스의 세션을 삭제하고, IDP에 Refresh Token 무효화와 SSO 로그아웃을 요청한다. IDP는 로그아웃 처리가 성공적으로 완료가 되면 현재 접속 페이지를 리다이렉트 URI로 이동한다.
여러 개의 서비스에 OIDC 플러그인이 설정된 경우, 로그 아웃을 요청한 서비스외 다른 서비스의 세션은 그대로 유지된다. OIDC 플러그인은 서비스 단위로 설정된 세션에 대해 주기적으로 세션 Idle Time, Renew, Life Time에 설정된 시간에 도달하면, 다시 IDP에 인증 정보를 검사하여 인증 정보가 존재하지 않으면 로그인 페이지로 이동한다.
API 전용 인증 (Bearer Only 모드)
Kong Manager애서 위에서 등록한 브라우저 기반 인증을 위한 OIDC 플러그인을 삭제하고 다시 API 전용 인증을 다음과 같이 등록합니다.
curl -sk -X POST https://kong-admin.cnap.dev/services/httpbin/plugins \
-d name=oidc \
-d config.client_id=httpbin \
-d config.client_secret=${CLIENT_SECRET} \
-d config.discovery=https://keycloak.cnap.dev/realms/cnap/.well-known/openid-configuration \
-d config.bearer_only=yes \
-d config.introspection_endpoint=https://keycloak.cnap.dev/realms/cnap/protocol/openid-connect/token/introspect \
| jq
하나의 서비스에는 동일한 유형의 플러그인을 중복해서 등록할 수 없습니다. 따라서 OIDC 플러그인을 브라우저 요청과 Bearer Only 요청을 모두 처리하도록 이중으로 적용하는 것은 지원되지 않습니다.
6-3. 테스트 및 검증
이 테스트를 진행하기전에 먼저 이전에 설정한 Key Authentication 플러그인이 여전히 활성화되어 있다면, 먼저 해당 플러그인을 비활성화해야 OIDC 플러그인이 정상 작동합니다.
Key Authentication 비활성화
Kong Manager에서 접속하여 “Gateway Services > httpbin > 플러그인"에서 Key Authentication를 비활성화합니다. 또는 아래와 같이 Kong Admin API를 이용하여 비활성화할 수도 있습니다.
# Key Authentication 플러그인 ID 조회
PLUGIN_ID=$(curl -sk -X GET https://kong-admin.cnap.dev/services/httpbin/plugins \
| jq -r '.data[] | select(.name=="key-auth") | .id')
echo "Key Authentication Plugin ID: $PLUGIN_ID"
# 플러그인 비활성화 (PATCH 요청으로 enabled=false 설정)
curl -sk -X PATCH https://kong-admin.cnap.dev/plugins/$PLUGIN_ID \
-d enabled=false
브라우저 기반 인증 테스트
브라우저에서 HttpBin 애플리케이션에 접근하면, Kong Gateway는 OIDC 인증을 위해 Keycloak 로그인 페이지로 리디렉션하고, 인증 완료 후 원래 요청 URL로 다시 리디렉션하여 HttpBin 서비스에 접근이 가능합니다.
https://kong-httpbin.cnap.dev
API 기반 인증 테스트 (Bearer Only)
아래와 같이 curl 명령을 사용하여 HttpBin API에 Access Token을 포함한 요청을 보내면 됩니다.
# 토큰 발급
export KEYCLOAK_URL=https://keycloak.cnap.dev
export REALM=cnap
export CLIENT=httpbin
export CLIENT_SECRET=${CLIENT_SECRET}
export USER=admin
export PASSWORD=password
export ACCESS_TOKEN=$(curl -sk -X POST "${KEYCLOAK_URL}/realms/${REALM}/protocol/openid-connect/token" \
-d grant_type=password \
-d client_id=${CLIENT} \
-d client_secret=${CLIENT_SECRET} \
-d request_token_type=urn:ietf:params:oauth:token_type:access_token \
-d username=${USER} \
-d password=${PASSWORD} \
-d scope='openid profile email' \
| jq -r .access_token)
echo "ACCESS_TOKEN: ${ACCESS_TOKEN}"
# httpbin 서비스 조회
curl -sk -H "Authorization: Bearer ${ACCESS_TOKEN}" \
-H "accept: application/json" \
-X GET "https://kong-httpbin.cnap.dev/ip"
- 인증 성공 시: 백엔드 서비스 응답 반환
- 인증 실패 시: HTTP 401 Unauthorized 응답 반환 (리디렉션 없음)
Bearer Only 모드는 브라우저가 없는 환경이나 서버 간 통신, CLI 기반 접근 등에 적합합니다.
7. 마무리
이번 글에서는 Kong Gateway를 활용한 API 인증 구조에 대해 실질적인 접근 방법을 살펴보았습니다.
- Key Authentication과 OIDC 플러그인을 이용해 Kong Gateway 레벨에서 인증을 처리하는 방법을 익혔고,
- 각 플러그인의 역할과 특징, 적용 시 고려해야 할 사항들을 정리했습니다.
- 특히 Kong OSS에서 OIDC 기능을 직접 구현하여 Enterprise 기능 없이도 인증 체계를 구성하는 방법을 확인했습니다.
이러한 구조는 마이크로서비스 환경에서 API 인증을 게이트웨이에서 일괄 처리하고, 서비스 간 책임 분리를 명확히 하는 데에 효과적입니다.