本記事は「Kong Advent Calendar 2025」の2日目のエントリとして、kind: Gatewayを使ったKong Gatewayの構築方法について解説する。
以前「KubernetesのGateway APIとは」という記事でKubernetesのGateway APIを紹介してから1年半、徐々にIngressからGateway APIへの置き換えが進んでいるように見える。
またNGINXについてはIngressの廃止が発表された。
記事によると2026/3まではメンテナンスされるものの、それ移行はセキュリティ脆弱性も修正されなくなるので、早めにGateway APIに移行することが推奨されている。
このように徐々にIngress Controllerが減っていくことが予想されるため、早めにGateway APIに移行した方が良さそうだ。
今回、以前執筆した「EKS上に使えるKong Gatewayを構築する」の記事をベースに、KubernetesのGateway APIを使ってKong Gatewayを構築する方法を紹介する。
前提
前回記事と同じく以下を前提条件とする。
- デプロイ先はEKSでクラスタは構築済み
-
Type: LoadBalancerが利用できる
構築対象は以下とする。
- Kong Gateway Enterprise版
- Helmにより構築
設定内容
以下の内容で設定する。
- デプロイにはHybridモードを採用
- RBACを有効化し、Kong ManagerのログインにBasic認証を利用
- 証明書はLet's Encryptを利用
- DPは冗長化し、Podも分散配置する
- PDBでサービス断しないようにする
- Gateway APIにはTraefikを利用
- スケール観点でHPAを利用
- リソースの使いすぎに備えてrequests, limitsを設定
- Prometheus向けにServiceMonitorを有効化する
今回もあえて設定の汎用性を考慮してGateway APIにはTraefikを利用する。
前回使っていたContourは無償利用が出来なくなったので不採用とした。サヨナラContour。
なおKong Gateway提供元のKongもKong Ingress ControllerというIngress Controllerを提供していてGateway APIも利用できるが、ベンダロックイン色が強くなるのでこちらも不採用とした。
構築手順
1. Traefikの導入
最初にこちらの手順に従ってGateway API用のCRDを導入する。
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.4.0/standard-install.yaml
Traefik用のRBACを導入する。
kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v3.6/docs/content/reference/dynamic-configuration/kubernetes-gateway-rbac.yml
Ingress Controllerを導入する。
helm upgrade -i traefik oci://ghcr.io/traefik/helm/traefik -n traefik --create-namespace --set providers.kubernetesGateway.enabled=true
--set providers.kubernetesGateway.enabled=trueをつけることでkind: Gatewayとkind: GatewayClassがインストールされる。
$ helm template traefik oci://ghcr.io/traefik/helm/traefik --set providers.kubernetesGateway.enabled=true 2> /dev/null| grep Gateway
kind: Gateway
kind: GatewayClass
2. 証明書の作成(Let's Encrypt、CP-DP間)
これらに関しては前回記事と同じ手順なので省略する。
前回記事:
3. Kong GatewayのControl Planeのデプロイ
最初にライセンスファイル、Admin APIの初期パスワード、DBのパスワードをSecretとして作成する。
LICENSE_FILE=~/license.json
kubectl create secret generic kong-enterprise-license \
--from-file=license=$LICENSE_FILE \
-n kong
kubectl create secret generic kong-enterprise-superuser-password \
--from-literal=password=kongpass \
-n kong
kubectl create secret generic kong-database-password \
--from-literal=password=kongpass \
-n kong
次にControl PlaneのYAMLを用意する。
cp.yaml(クリックすると展開)
image:
repository: kong/kong-gateway
tag: "3.10"
secretVolumes:
- kong-cluster-tls-cert
env:
role: control_plane
database: postgres
pg_host: kong-cp-db-rw.kong.svc.cluster.local
pg_database: kong
pg_password:
valueFrom:
secretKeyRef:
name: kong-database-password
key: password
pg_user: kong
cluster_cert: /etc/secrets/kong-cluster-tls-cert/tls.crt
cluster_cert_key: /etc/secrets/kong-cluster-tls-cert/tls.key
enforce_rbac: "on"
admin_gui_url: https://kong.hogehoge.info
admin_gui_api_url: https://admin.hogehoge.info
admin_gui_auth: basic-auth
admin_gui_session_conf: "{\"secret\":\"secret\",\"rolling_timeout\": 36000}"
password:
valueFrom:
secretKeyRef:
name: kong-enterprise-superuser-password
key: password
resources:
limits:
cpu: 2
memory: 4G
requests:
cpu: 1
memory: 2G
admin:
enabled: true
type: ClusterIP
http:
enabled: true
containerPort: 8001
servicePort: 8001
tls:
enabled: false
ingress:
enabled: false
manager:
enabled: true
type: ClusterIP
http:
enabled: true
containerPort: 8002
servicePort: 8002
tls:
enabled: false
ingress:
enabled: false
cluster:
enabled: true
tls:
enabled: true
servicePort: 8005
containerPort: 8005
clustertelemetry:
enabled: true
tls:
enabled: true
containerPort: 8006
servicePort: 8006
proxy:
enabled: false
enterprise:
enabled: true
license_secret: kong-enterprise-license
ingressController:
enabled: false
postgresql:
enabled: false
serviceMonitor:
enabled: true
labels:
release: prometheus-stack
Kong Gatewayのvalues.yamlにはGateway API用の記述がないため、一旦Ingress抜きでデプロイし、その後手動でGateaway API用の設定を追加することにする。
なおハマリどころとして、以下の設定がないとデプロイは出来て接続もできるものの上手くUIが表示されない問題が発生した。
admin_gui_url: https://kong.hogehoge.info
admin_gui_api_url: https://admin.hogehoge.info
あまり理解できていないが、アクセスする経路がIngressからGateway APIに変わったことで、X-Forwarded-Port等のヘッダ情報が変わったことでhttps://kong.hogehoge.info:8443にアクセスしに行くようになり、8443ポートが空いていないためエラーになっていたようだ。
作成したYAMLをデプロイする。
helm upgrade -i kong-aws-cp kong/kong -n kong -f cp.yaml
次にkind: Gatewayを作成する。
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: kong-gateway
namespace: kong
spec:
gatewayClassName: traefik
listeners:
- name: https
protocol: HTTPS
port: 8443
tls:
mode: Terminate
certificateRefs:
- name: kong-tls-cert
allowedRoutes:
namespaces:
from: Same
Gatewayリソースは待受のルールみたいなものを書くもので、Inressのアノテーション辺りでよく記載されていたものになる。
個人的なハマリどころはspec.listeners[].portで、Gateway Classで指定したコントローラのPodが待ち受けているポートを指定する。
これはService経由ではないので、Serviceのポートではないことに注意。
またkind: HTTPRouteも作成する。
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: kong-admin-route
namespace: kong
spec:
parentRefs:
- name: kong-gateway
sectionName: https
hostnames:
- "admin.hogehoge.info"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: kong-aws-cp-kong-admin
port: 8001
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: kong-manager-route
namespace: kong
spec:
parentRefs:
- name: kong-gateway
sectionName: https
hostnames:
- "kong.hogehoge.info"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: kong-aws-cp-kong-manager
port: 8002
spec.parentRefs[].sectionNameで、Gatewayのspec.listeners[].nameで指定した名前を指定する。
作成したYAMLを適用する。
kubectl apply -f kinggw.yaml -f httproute-admin.yaml -f httproute-manager.yaml
4. Kong GatewayのData Planeのデプロイ
Data PlaneのYAMLを用意する。
dp.yaml(クリックすると展開)
image:
repository: kong/kong-gateway
tag: "3.10"
secretVolumes:
- kong-cluster-tls-cert
env:
role: data_plane
database: "off"
cluster_control_plane: kong-aws-cp-kong-cluster.kong.svc:8005
cluster_telemetry_endpoint: kong-aws-cp-kong-clustertelemetry.kong.svc:8006
cluster_cert: /etc/secrets/kong-cluster-tls-cert/tls.crt
cluster_cert_key: /etc/secrets/kong-cluster-tls-cert/tls.key
resources:
limits:
cpu: 2
memory: 4G
requests:
cpu: 1
memory: 2G
podDisruptionBudget:
#enabled: true
enabled: false
maxUnavailable: 1
autoscaling:
#enabled: true
enabled: false
minReplicas: 2
maxReplicas: 3
topologySpreadConstraints:
- maxSkew: 1
topologyKey: kubernetes.io/hostname
whenUnsatisfiable: DoNotSchedule
proxy:
enabled: true
type: ClusterIP
http:
enabled: true
containerPort: 8000
servicePort: 8000
tls:
enabled: false
ingress:
enabled: false
ingressController:
enabled: false
manager:
enabled: false
enterprise:
enabled: true
license_secret: kong-enterprise-license
serviceMonitor:
enabled: true
labels:
release: prometheus-stack
こちらもCPと同様にIngress抜きでデプロイし、その後手動でGateaway API用の設定を追加する。
作成したYAMLでデプロイする。
helm upgrade -i -f dp.yaml kong-aws-dp kong/kong --wait --debug
以下のHTTPRouteも作成する。
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: kong-dp-route
namespace: kong
spec:
parentRefs:
- name: kong-gateway
sectionName: https
hostnames:
- "proxy.hogehoge.click"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: kong-aws-dp-kong-proxy
port: 8000
こちらも適用する。
kubectl apply -f httproute-dp.yaml
動作確認
Kong Managerに設定したドメインでアクセスすると、以下のようにログイン画面が表示され、指定したログイン情報(kong_admin/kongpass)でアクセス出来ることが分かる。
またProxyについても設定したドメインでアクセスできることが分かる。
$ curl https://proxy.hogehoge.info
{
"message":"no Route matched with those values",
"request_id":"3cc326500e00c12fa8072550eddea942"
}
問題なさそうだ。
所感
最初はGateway APIに移行するのはかなり簡単だと思って舐めていたが、思った以上に時間が掛かってしまった。
時間が掛かった要因としては以下があった。
- Kong GatewayのHelm ChartがGateway APIに未対応
- Gateway APIに不慣れなことによる設定のTry&Error
- Gateway APIとIngressでの挙動の違いによるエラー
IngressとGateway APIで概念が変わっている箇所も結構あり、移行を考える際は慎重に検討した方が良さそうだ。
