はじめに
こんにちは。エンタープライズ第三本部 データマネジメントユニット マーケティングIT部の藤澤です。
先日、APIプラットフォームのリーディング企業であるKong株式会社様のパートナー向け認定資格プログラム「Partner Delivery Specialist」に参加し、無事に電通総研第一号の認定を取得することができました。
この資格の認定には、対面で行われた2日間のワークショップへの参加以外にも、事前のオンライン学習、Kong Gateway Associate資格の取得が必要でかなりハードでした。
ワークショップではインフラ周りの知識もかなり必要とされたのですが、普段はアプリケーション開発を中心に行っているため、苦労する場面が多々ありました。
しかし今回のプログラムを通じて、普段の業務であまり触れることがなかったインフラ周りの知識やAPIOpsの思想などについて体系的に学ぶことができ、非常に有意義な経験となりました。
本記事では、Kongの概要に少し触れた後、ワークショップでも取り扱った、Kong GatewayでKubernetesのマイクロサービスをプロキシする方法について共有させていただきます。
なお本記事の内容は、すべて2025年12月時点のものですのでご了承ください。
対象読者
Kongを触ったことがない方、Kubernetesについてクラウドサービスの試験などで名前は知っているが実際に使ったことがない方。
私自身がそうだったので、詰まった点、学びになった点や、実際のニーズに対してどのように活用できるのかについて詳しく書きました。
技術的な内容については、普段KongやKubernetesを使っている方にとっては簡単すぎるかもしれません。
Kongの概要
Kongは、マイクロサービスアーキテクチャにおけるAPIゲートウェイとして広く採用されているプラットフォームです(日本ではデジタル庁から推奨APIゲートウェイに認定されています)。API開発ライフサイクルの管理機能、セキュリティ、認証、レート制限、ロギングなどのAPIゲートウェイ機能を統合的に提供し、複雑なAPI運用を効率化します。
Kongエコシステムの代表的なコンポーネントは以下の3つです。
- Kong Insomnia: APIの設計・開発・テストを効率化するための強力なクライアントツールです。Postmanの競合にあたり、デザインファーストな開発を支援します。
- Kong Gateway: 外部からのリクエストを受け付ける、世界で最も利用されているオープンソースのAPIゲートウェイです。高速な通信処理と豊富なプラグイン拡張が特徴です。
- Kong Mesh: マイクロサービス間の複雑な通信(内部通信)を制御・可視化するためのサービスメッシュです。サービス間の暗号化やトラフィック制御を担います。

出典:Kong Inc. 公式サイト より引用
そして、これらのコンポーネントを統合的に管理・運用できる枠組みをSaaSとして提供しているKong Konnectという製品があります。 Konnectを利用することで、Insomniaで設計したAPIスペックの自動公開(開発者ポータル)、Gateway/Meshの統合監視、チーム間でのコラボレーション機能などが提供され、APIライフサイクル全体の効率化を実現できます。
本ブログでは、上記のうち主にKong GatewayとKong Konnectを使います。
Kong Gatewayのアーキテクチャには、主に以下の3種類があります。
- DB lessモード: Kong Gatewayの設定情報を、各ノードごとにYAML形式の設定ファイルで管理する軽量なモードです。

出典:Kong Inc. 公式サイト より引用 - Traditionalモード: PostgreSQLなどのデータベースを使用して設定を管理するモードで、大規模な環境や複数のノードを運用する際に適しています。

出典:Kong Inc. 公式サイト より引用 - Hybridモード: データベースと接続して設定を管理する専門のコントロールプレーン(CP)と実際にトラフィックをさばく専門のデータプレーン(DP)を分離し、管理を一元化しながらトラフィック処理を分散できる構成です。スケーラビリティとセキュリティの両面で大きなメリットが得られます。

出典:Kong Inc. 公式サイト より引用
本記事では、Hybridアーキテクチャを採用し、CPはKonnectで管理します。
この場合、CPのノード作成、DBとの接続などの手順は不要で、APIの開発者が気にする必要はありません。各APIサーバとの通信が可能な場所にDPのノードを配置し、Konnectとの通信を確立すればOKです。APIゲートウェイのポリシーを変更する際は、Konnectのエンドポイントに対して設定を行えば、自動的に各DPに設定が反映されます。
これにより、オンプレミス・クラウドのハイブリッド構成やマルチクラウド構成を柔軟に構築することが可能となり、ビジネス要件に応じた最適なインフラ設計を実現できます。

出典:Kong Inc. 公式サイト より引用
Kongそのものの説明はここまでにしておきます。詳しくは公式ドキュメントなどを参照してください。
題材
サンプルバックエンドAPIとして、IstioのBookinfoというマイクロサービスを使用します。
Bookinfoは4つのマイクロサービスで構成されており、そのうちproductpageサービスの/api/v1/products以下のエンドポイントはBackend For Frontend(BFF)として実装されています。
今回はKubernetesクラスターにBookinfoとKong Gatewayをデプロイして、BookinfoのBFFに対してプロキシしてみます。
具体的な案件のシナリオとしては、レガシーなモノリシックアプリケーションからマイクロサービスアーキテクチャへ段階的に移行していく際に、まずは4つのマイクロサービスをKubernetesに切り出した、というものが想定されます。
本ブログでは1つのサービスにしかプロキシしませんが、今後他のマイクロサービスへのプロキシ機能も順次追加していくことを考えると、公開する各サービスに認証認可やログ記録などの共通処理を重複して実装するよりも、共通基盤で一元管理する方が保守性が高く、セキュリティの一貫性も保ちやすいです。
これが、まさにKong Gatewayの得意とするところです。
ここからは以下の手順で実装します。
EKSクラスターとサンプルバックエンドAPIをセットアップする
今回は、AWSのElastic Kubernetes Service(EKS)上にKubernetesクラスターを立てます。
ローカルでDocker Desktop, Kind, minikubeあたりを使ってもいいのですが、Podのオートスケーリングなどをやりたかったので、設定が簡単なEKSにしました。
※ 1日あたり$7程度かかるので、作業が終わったらクラスターを削除することをおすすめします。
コマンドインストール
まず、以下のコマンドをローカルにインストールします。
| コマンド | 説明 |
|---|---|
kubectl |
Kubernetesクラスターを操作するためのコマンドラインツール |
helm |
Kubernetesのパッケージマネージャー |
k9s |
Kubernetesクラスターの状態をターミナル上で視覚的に確認・操作できるツール |
aws |
AWSのサービスを操作するコマンドラインツール |
eksctl |
Amazon EKSクラスターを簡単に作成・管理できるコマンドラインツール |
hey |
HTTP負荷テストツール |
Macの場合、以下のコマンドでインストールできます。
brew install kubernetes-cli helm k9s awscli eksctl hey
awsコマンドを使う際、IAMユーザーのクレデンシャルが必要なので、あらかじめAWS Management ConsoleでIAMユーザーを作成してポリシーをアタッチし、アクセスキーとシークレットアクセスキーを発行しておきます。
ポリシーは検証用なのでAdministratorAccessにしてしまいました。
以下のコマンドで、クレデンシャルなどを登録します。
aws configure
実行すると、4つの質問が順番に表示されるので入力してEnterを押します。
AWS Access Key ID [None]: <取得したアクセスキーIDを貼り付け> AWS Secret Access Key [None]: <取得したシークレットキーを貼り付け> Default region name [None]: ap-northeast-1 Default output format [None]: json
以下のコマンドで、設定したクレデンシャルが紐づくIAMユーザーが出力されればOKです。
aws sts get-caller-identity
Kubernetesクラスターの作成
それでは、EKSにクラスターを作成します。
Management Consoleから作成すると、EC2やVPCなどの設定が大変なので、eksctlコマンドで一気に作ります。
15分程度待ちます。
※eksctlを使っておくと、クラスターを削除するときにも関連リソースが全部消えるので、こちらを推奨します。
eksctl create cluster \ --name kong-techblog \ --region ap-northeast-1 \ --version 1.34 \ --nodegroup-name kong-techblog-spot \ --node-type t3.medium \ --nodes 3 \ --spot \ --managed
オプションについては、以下のとおりです。
オプションの説明
| オプション | 説明 |
|---|---|
name |
クラスター名なので、何でもOKです。 |
region |
東京リージョンにしました。 |
version |
Kubernetesクラスターのバージョンです。 |
nodegroup-name |
ノードグループ名なので、何でもOKです。 |
node-type |
t2.mircoでやったら、pod数制限にかかり起動しませんでした。 |
nodes |
ノード数です。 |
spot |
スポットインスタンスを使います。本番ではNGですが、検証用なので安いほうがいいと思います。 |
managed |
Managed Instance Groupを使います。 |
実行が終わったら、Management ConsoleでEKSクラスターが正常に作成されたことを確認します。
※東京リージョンが選択されていることを確認してください。

kong-techblogクラスターが作成されています。
作成されたクラスターをクリックし、詳細画面を開いて[コンピューティング]タブを開きます。

Nodeは1つの計算リソースを表すKubernetesの概念です。
今回で言うと、EC2インスタンスが1つのNodeに相当します。
先ほどeksctlコマンドでクラスターを作成する際にnode-type=t3.mediumとnodes=3オプションを設定したので、EC2にt3.mediumのインスタンスが3つ立ち上げられています。
次に[リソース]タブを開くと、デフォルトで「リソースタイプ > ワークロード > ポッド」が選択されています。

ここに表示されているのは、コンテナをグループ化して管理するための最小単位となるPodというKubernetesの概念です。
Podは複数のコンテナからなり、いずれかのNode上で実行され、Pod単位でスケーリングやヘルスチェックなどが行われます。
後でBookinfoやKong Gatewayをデプロイすると、Podとしてデプロイされます。
その他のKubernetesのリソースについての説明は省略します。詳しくは他のブログや公式ドキュメントを参照してください。
Bookinfoのデプロイ
さて、クラスターがデプロイできたので、次にBookinfoをデプロイします。
デプロイに関する定義は、yamlファイルに記述します(Bookinfo公式のyamlファイルを一部改変したものです)。
bookinfo.yaml
################################################################################################## # Namespace ################################################################################################## apiVersion: v1 kind: Namespace metadata: name: bookinfo --- ################################################################################################## # Details service ################################################################################################## apiVersion: v1 kind: Service metadata: name: details namespace: bookinfo labels: app: details service: details spec: ports: - port: 9080 name: http selector: app: details --- apiVersion: apps/v1 kind: Deployment metadata: name: details-v1 namespace: bookinfo labels: app: details version: v1 spec: replicas: 1 selector: matchLabels: app: details version: v1 template: metadata: labels: app: details version: v1 spec: containers: - name: details image: docker.io/istio/examples-bookinfo-details-v1:1.20.1 imagePullPolicy: IfNotPresent ports: - containerPort: 9080 securityContext: runAsUser: 1000 --- ################################################################################################## # Ratings service ################################################################################################## apiVersion: v1 kind: Service metadata: name: ratings namespace: bookinfo labels: app: ratings service: ratings spec: ports: - port: 9080 name: http selector: app: ratings --- apiVersion: apps/v1 kind: Deployment metadata: name: ratings-v1 namespace: bookinfo labels: app: ratings version: v1 spec: replicas: 1 selector: matchLabels: app: ratings version: v1 template: metadata: labels: app: ratings version: v1 spec: containers: - name: ratings image: docker.io/istio/examples-bookinfo-ratings-v1:1.20.1 imagePullPolicy: IfNotPresent ports: - containerPort: 9080 securityContext: runAsUser: 1000 --- ################################################################################################## # Reviews service ################################################################################################## apiVersion: v1 kind: Service metadata: name: reviews namespace: bookinfo labels: app: reviews service: reviews spec: ports: - port: 9080 name: http selector: app: reviews --- apiVersion: apps/v1 kind: Deployment metadata: name: reviews-v1 namespace: bookinfo labels: app: reviews version: v1 spec: replicas: 1 selector: matchLabels: app: reviews version: v1 template: metadata: labels: app: reviews version: v1 spec: containers: - name: reviews image: docker.io/istio/examples-bookinfo-reviews-v1:1.20.1 imagePullPolicy: IfNotPresent env: - name: LOG_DIR value: "/tmp/logs" ports: - containerPort: 9080 volumeMounts: - name: tmp mountPath: /tmp - name: wlp-output mountPath: /opt/ibm/wlp/output securityContext: runAsUser: 1000 volumes: - name: wlp-output emptyDir: {} - name: tmp emptyDir: {} --- apiVersion: apps/v1 kind: Deployment metadata: name: reviews-v2 namespace: bookinfo labels: app: reviews version: v2 spec: replicas: 1 selector: matchLabels: app: reviews version: v2 template: metadata: labels: app: reviews version: v2 spec: containers: - name: reviews image: docker.io/istio/examples-bookinfo-reviews-v2:1.20.1 imagePullPolicy: IfNotPresent env: - name: LOG_DIR value: "/tmp/logs" ports: - containerPort: 9080 volumeMounts: - name: tmp mountPath: /tmp - name: wlp-output mountPath: /opt/ibm/wlp/output securityContext: runAsUser: 1000 volumes: - name: wlp-output emptyDir: {} - name: tmp emptyDir: {} --- apiVersion: apps/v1 kind: Deployment metadata: name: reviews-v3 namespace: bookinfo labels: app: reviews version: v3 spec: replicas: 1 selector: matchLabels: app: reviews version: v3 template: metadata: labels: app: reviews version: v3 spec: containers: - name: reviews image: docker.io/istio/examples-bookinfo-reviews-v3:1.20.1 imagePullPolicy: IfNotPresent env: - name: LOG_DIR value: "/tmp/logs" ports: - containerPort: 9080 volumeMounts: - name: tmp mountPath: /tmp - name: wlp-output mountPath: /opt/ibm/wlp/output securityContext: runAsUser: 1000 volumes: - name: wlp-output emptyDir: {} - name: tmp emptyDir: {} --- ################################################################################################## # Productpage services ################################################################################################## apiVersion: v1 kind: Service metadata: name: productpage namespace: bookinfo labels: app: productpage service: productpage spec: # type: LoadBalancer ports: - port: 9080 name: http # - port: 80 # targetPort: 9080 # name: http selector: app: productpage --- apiVersion: apps/v1 kind: Deployment metadata: name: productpage-v1 namespace: bookinfo labels: app: productpage version: v1 spec: replicas: 1 selector: matchLabels: app: productpage version: v1 template: metadata: annotations: prometheus.io/scrape: "true" prometheus.io/port: "9080" prometheus.io/path: "/metrics" labels: app: productpage version: v1 spec: containers: - name: productpage image: docker.io/istio/examples-bookinfo-productpage-v1:1.20.1 imagePullPolicy: IfNotPresent ports: - containerPort: 9080 volumeMounts: - name: tmp mountPath: /tmp securityContext: runAsUser: 1000 volumes: - name: tmp emptyDir: {} ---
デプロイするには、この内容を./bookinfo.yamlに保存して、以下のコマンドを実行します。
kubectl apply -f ./bookinfo.yaml
30秒ほど経ったら、以下のコマンドでPodの状態を確認します。
kubectl get pods -n bookinfo
以下のように、6つのPodがREADY: 1/1, STATUS: RUNNINGとなっていることが確認できます。

READY: 0/1やSTATUS: ContainerCreatingなどとなっている場合は、もう少し待機します。
STATUS: Pendingの場合は、Podに対してNodeのリソースが不足している可能性があるので、使用するEC2インスタンスタイプを見直すか、ノード数を増やすことを検討します。
まだproductpageはクラスター外部からアクセスできるようにしていないので、/api/v1/productsにアクセスするには、クラスター内部からリクエストを送る必要があります。
kubectl run curl-test --image=curlimages/curl --rm -it --restart=Never -- \ curl http://productpage.bookinfo:9080/api/v1/products
このコマンドでは、一時的にcurl-testというPodを立てて、そこからcurlコマンドを叩いて、終わったらPodを削除しています。
このようにレスポンスが返って来ればOKです。

これでEKSクラスターとサンプルバックエンドAPI(Bookinfo)のデプロイは完了です!
Kong のインフラをセットアップする
前置きが長かったですが、ここから本題の Kong の話になります。
CPのセットアップ
まず、Kong Konnectにサインアップします。
※(2025年12月現在)サインアップ後30日間は、基本的な機能を無料で使用することができます。
サインアップ後、ログイン直後にはこのような画面が表示されます。

左のメニューで、[API Gateway]をクリックして、右上の[New gateway]で新しくゲートウェイを作成します。

ポップアップで、[Self-Managed Hybrid]を選択して、ゲートウェイの名前を決め、右下の[Next Step]をクリックします。

クリックすると画面遷移します。これで CP の作成が完了しました。
DPのデプロイとCP・DP間連携
次に、EKSにDPをデプロイし、CPと連携させる設定を行います。
この画面に遷移しているはずなので、左側のメニューの[Data Plane Nodes]をクリックします。

[Configure data plane]をクリックします。

ポップアップで、Gateway VersionはSelf-Managed Gateway 3.12を、PlatformはKubernetesを選択し、下にスクロールします。

「Advanced Kubernetes Setup」が表示されるので、基本的にはその手順に従って設定を進めます。
以下のコマンドで、Kong Gateway関連のPodをデプロイするkongNamespaceを作成し、HelmリポジトリにKong Gatewayを登録します(手順2 Set up Helm)。
kubectl create namespace kong helm repo add kong https://charts.konghq.com helm repo update
この時点では、まだKong Gatewayのインストールは行われていません。Helmチャートという、Kubernetesのデプロイ定義の雛形のようなものをダウンロードして登録しただけです。
Helmのコマンドは、初回実行時少し時間がかかります。
次に、CPとDPがmTLSにより安全に接続できるよう、CPから認証情報を払い出します(手順3 Generate certificates)。
[Generate certificate]ボタンをクリックすると「Cluster Certificate」と「Certificate Key」が表示されるので、それぞれ新しく./tls.crtと./tls.keyファイルを作成し、コピペして保存します。

以下のコマンドで、KubernetesクラスターにSecretリソースを作成します。
kubectl create secret tls kong-cluster-cert -n kong --cert=./tls.crt --key=./tls.key
続いて、Helmチャート(雛形)の変数部分を定義したvalues.yamlファイルを作成します(手順4 Configuration parameters)。
後で詳しく説明しますが、Kong GatewayのPodのオートスケールの確認のため、Konnectに表示されているものから少し変更しています。
以下の設定をコピペし、 env.cluster_control_plane、env.cluster_server_name、env.cluster_telemetry_endpoint、env.cluster_telemetry_server_nameをKonnectが自動生成したvalues.yamlの設定と同じものに書き換えて、 ./values.yamlに保存します。
values.yaml
image: repository: kong/kong-gateway tag: "3.12" secretVolumes: - kong-cluster-cert admin: enabled: false env: role: data_plane database: "off" cluster_mtls: pki cluster_control_plane: <Konnectが自動生成したvalues.yamlの設定と同じにする> cluster_dp_labels: "type:docker-kubernetesOS" cluster_server_name: <Konnectが自動生成したvalues.yamlの設定と同じにする> cluster_telemetry_endpoint: <Konnectが自動生成したvalues.yamlの設定と同じにする> cluster_telemetry_server_name: <Konnectが自動生成したvalues.yamlの設定と同じにする> cluster_cert: /etc/secrets/kong-cluster-cert/tls.crt cluster_cert_key: /etc/secrets/kong-cluster-cert/tls.key lua_ssl_trusted_certificate: system konnect_mode: "on" vitals: "off" nginx_worker_processes: "1" upstream_keepalive_max_requests: "100000" nginx_http_keepalive_requests: "100000" proxy_access_log: "off" dns_stale_ttl: "3600" router_flavor: expressions ingressController: enabled: false installCRDs: false resources: requests: cpu: 500m memory: "512Mi" limits: cpu: 2 memory: "2Gi" autoscaling: enabled: true minReplicas: 1 maxReplicas: 5 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 10 behavior: scaleDown: stabilizationWindowSeconds: 30 manager: enabled: false
その後、以下のコマンドを実行し、Kong GatewayをEKSにデプロイします。
helm install my-kong kong/kong -n kong --skip-crds --values ./values.yaml
このコマンドは、Kong公式のHelmチャート(Kubernetesのデプロイ定義の雛形)に対して、その変数部分を定義したvalues.yamlを埋め込み、Kubernetesのデプロイ定義を完成させて、それをもとにKubernetesクラスタへのデプロイを実行します。
うまくいくと、ポップアップの一番下が「Data Plane Node has been found」に変わり、右下の[Done]ボタンが押せるようになります。

これでKongのインフラのセットアップは完了です!
ここまでで構築してきたインフラの構成図は以下のとおりです。
%%{init: {'theme':'base', 'themeVariables': {'fontSize':'18px'}}}%%
graph LR
Users["🌐<br/><b>ユーザー</b>"]
Developer["👨💻<br/><b>開発者</b>"]
subgraph Konnect["<b>Kong Konnect (SaaS)</b>"]
CP["<b>Control Plane</b><br/>設定管理"]
end
subgraph AWS["<b>AWS (ap-northeast-1)</b>"]
NLB["<b>Network Load Balancer</b>"]
subgraph EKS["<b>EKS Cluster: kong-techblog-cluster</b>"]
subgraph NS_Kong["<b>Namespace: kong</b>"]
KongPods["<b>Kong Gateway Pods</b><br/>Data Plane<br/>HPA: 1-5 replicas"]
end
subgraph NS_Bookinfo["<b>Namespace: bookinfo</b>"]
ProductPage["<b>productpage</b><br/>:9080"]
Details["<b>details</b><br/>:9080"]
Reviews["<b>reviews</b><br/>:9080"]
Ratings["<b>ratings</b><br/>:9080"]
ProductPage --> Details
ProductPage --> Reviews
Reviews --> Ratings
end
end
end
Developer -.->|"Admin API<br/>(ルート/サービス/プラグイン)"| CP
Users -->|HTTP| NLB
NLB --> KongPods
KongPods --> ProductPage
KongPods -.->|mTLS 認証<br/>設定同期| CP
style Konnect fill:#e1f5ff,stroke:#333,stroke-width:3px
style AWS fill:#fff5e1,stroke:#333,stroke-width:3px
style EKS fill:#ffffff,stroke:#333,stroke-width:2px
style NS_Kong fill:#ffe1f5,stroke:#333,stroke-width:2px
style NS_Bookinfo fill:#e1ffe1,stroke:#333,stroke-width:2px
style KongPods fill:#ffd700,stroke:#333,stroke-width:2px
style ProductPage fill:#99ff99,stroke:#333,stroke-width:2px
style Details fill:#99ff99,stroke:#333,stroke-width:2px
style Reviews fill:#99ff99,stroke:#333,stroke-width:2px
style Ratings fill:#99ff99,stroke:#333,stroke-width:2px
style NLB fill:#ff9999,stroke:#333,stroke-width:2px
style CP fill:#99ccff,stroke:#333,stroke-width:2px
style Users fill:#ffffff,stroke:#333,stroke-width:2px
style Developer fill:#ffccff,stroke:#333,stroke-width:2px
自動的にNetwork Load Balancerが追加されていますが、これはKongのHelmチャートで、Kong GatewayのDPをデプロイすると自動的に作成されるように設定されています。EKS環境で実行すると、EC2にLoad Balancerが自動的にプロビジョニングされ、インターネットからのトラフィックを受け付けられるようになります。
またKong GatewayのPodのオートスケール(Horizontal Pod Autoscaler:HPA)についてですが、先ほどのvalues.yamlに以下の記述を追加していました。
resources: requests: cpu: 500m memory: "512Mi" limits: cpu: 2 memory: "2Gi" autoscaling: enabled: true minReplicas: 1 maxReplicas: 5 metrics: - type: Resource resource: name: cpu target: type: Utilization averageUtilization: 10 behavior: scaleDown: stabilizationWindowSeconds: 30
これは、初めはKong Gateway Podを1つだけデプロイしておき、PodのCPU使用率が10%を超えると、最大5個までPodをスケールアウトせよ、という命令です(あとでHPAを試すために、各Podで使用できる最大のCPUリソースと閾値となる利用率は低めに設定しています)。
また、30秒間CPU使用率が10%を下回った状態が続くと、そのPodは自動的にスケールインされます。
Kong Gatewayを設定する
CPでゲートウェイの設定に変更を加えるには、Konnectでゲートウェイごとに払い出されるAdmin APIというエンドポイントを使用します。
KonnectのGUI上で設定を変更すると、裏側でAdmin APIが叩かれます。
CPとDPはmTLSで接続され、CPでゲートウェイの設定に変更を加えると、順次DPにも設定が反映されていきます。
ちなみにこの仕組みではDP(Kubernetes)からCP(Konnect)に向けてポーリングされるので、Kubernetesへのインバウンドトラフィックを許可する必要がないセキュアな設計になっています。
GUIから設定して、インターネット上からBookinfoを叩けるようにします。
Gateway Serviceの作成
左側のメニューから[Gateway Services]を選択します。

[New gateway service]をクリックします。

Full URLにはKong Gateway DPから見た、BookinfoのアプリケーションエンドポイントURLを入力します。
今回の場合は、http://productpage.bookinfo:9080/api/v1を入力します(ドメインの部分は、<Service名>.<Namespace名>とすれば、クラスター内のDNS Podが名前解決してServiceのIPアドレスを引いてきてくれます)。
Nameは適当にbookinfo-v1として、[Save]をクリックします。

なぜhttp://productpage.bookinfo:9080にしないかというと、後でRouteのPathに誤って/を登録してしまうと、/api/v1以下以外の/productpageや/loginエンドポイントなどにアクセスできるようになってしまうためです。確実に/api/v1以下だけにアクセスを限定するために、このようにしました。
Routeの作成
次に、遷移先のページでRouteを設定します。
左のメニューの[Routes]ではなく、画面中央に並んでいる[Routes]タブをクリックし、[New Route]を選択します。
※左のメニューの[Routes]からだと、別途作成したRouteを、先ほど作成したGateway Serviceに紐づける作業が必要になります。


設定画面で、Nameをproducts、Route ConfigurationはBasicで、Pathに/productsを入力します。
Strip Pathからチェックを外して[Save]をクリックします。

Routeは、条件に当てはまるリクエストをDPが受けたときに、関連付けてあるGateway Serviceにリクエストをプロキシします。
今回はPathに/productsを設定しているので、DPに対して/productsから始まるパスでリクエストが来た場合に、関連付けたbookinfo-v1 Gateway Serviceにプロキシされます。
Strip Pathにチェックをしていると、このときマッチした部分を削除してから、Gateway Serviceにプロキシします。
Gateway Serviceは、設定したURLproductpage.bookinfo:9080/api/v1の末尾にRouteから送られてきたパスをくっつけて、バックエンドに転送します。
以下に、どのようなパスのDPへのリクエストに対して、どのようなパスでDPがバックエンド(Bookinfo)にプロキシするかを示します。
| DPへのリクエストのパス | Strip Path: trueの場合 |
Strip Path: falseの場合 |
|---|---|---|
/products |
productpage.bookinfo:9080/api/v1(404 Not Found) |
productpage.bookinfo:9080/api/v1/products(200 OK) |
/products/1 |
productpage.bookinfo:9080/api/v1/1(404 Not Found) |
productpage.bookinfo:9080/api/v1/products/1(200 OK) |
/products/1/ratings |
productpage.bookinfo:9080/api/v1/1/ratings(404 Not Found) |
productpage.bookinfo:9080/api/v1/products/1/ratings(200 OK) |
/api/v1/products/1/ratings |
Serviceにプロキシされない(404 Not Found) | Serviceにプロキシされない(404 Not Found) |
DPへのリクエストのパスにも/api/v1を含めたい場合は、いくつか方法が考えられますが、例えばRouteでStrip Path: trueとして、Pathに/api/v1を設定すると、Serviceはそのままで動きます。
動作確認
これでインターネット上からKong Gateway経由で、Bookinfoを叩けるようになりました。
先ほどのロードバランサーのURLを取得し、アクセスしてみます。
このコマンドでKong Gatewayが使用しているLoadBalancerのEXTERNAL-IPを確認し、コピーしておきます(以下、your-domain.ap-northeast-1.elb.amazonaws.comとします)。
kubectl get svc -n kong
ブラウザやcurlでhttp://your-domain.ap-northeast-1.elb.amazonaws.com/productsにアクセスし、以下のように返ってくれば成功です!

たくさんリクエストを投げてKong Gateway DPのCPU負荷を上げ、HPAが動作するかどうか見てみます。
k9sコマンドで、Podの状態をリアルタイムで監視できます。
k9s -n kong
今は1Podしか起動していません。

別のターミナルを開き、以下のコマンドを実行し、負荷をかけます。
hey -z 120s -c 100 http://your-domain.ap-northeast-1.elb.amazonaws.com/products
しばらくすると、k9s側でPodの状態が更新されていることを確認できます。


5Podまでスケールアウトしました。
heyコマンドの実行が完了してから30秒ほど経つと、スケールインが始まります。


再び1Podに戻りました。
片付け
EKSクラスターを削除します。EKSクラスターを作成したときにeksctlを使っていれば、関連リソースが一括ですべて削除されます。
15分ほど待ちます。
eksctl delete cluster --name kong-techblog
念のため、Management ConsoleからNATゲートウェイ、ロードバランサー、EC2インスタンス、EKSクラスターが削除されていることを確認しておいてください。
これらの課金が大半なので、削除されていれば高額な請求が来ることはありません。
おわりに
本記事では、Kong GatewayでKubernetesのマイクロサービスをプロキシする方法について解説しました。
今回はAWS上のKubernetes環境の1つのサービスにしかプロキシしませんでしたが、プロキシ先のサービスが増えたり、マイクロサービスのインフラ環境がハイブリッドやマルチクラウドになったりしても、大きな変更なくスケーラブルに対応できることがKong Gatewayの強みです。
また、本記事では書ききれませんでしたが、yamlファイルによる宣言的定義をもとにAdmin APIを実行してくれるdecKコマンドラインや、Kubernetes設定ファイルから自動的にKong Gatewayの設定を構築するKong Ingress Controller、API利用者に向けてOpen API Specを公開するポータルを作れるDeveloper portalなどをはじめとして、APIOpsの構築をサポートするツールが多数提供されています。
APIのサイロ化や、品質のばらつきといった課題をお持ちの方は、ぜひKongの導入を検討されてみてはいかがでしょうか?
執筆:藤澤 大世 (@ftuajii)
レビュー:@kumakura.koki
(Shodoで執筆されました)



