0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Bookinfoの内部にKong Gatewayを挟む

Last updated at Posted at 2025-05-01

BookinfoといえばIstioのデモで有名なアプリケーションで、以下のようなマイクロサービスの構造を持っている。
Bookinfo

今回、Bookinfoの仕様の確認ついでに以下の図のような感じでProductpageと他のサービスの間にKong Gatewayを挟んでみる。
20250501120730.png

なお、Bookinfoは利用するもののIstioは利用しない。
あくまでもマイクロサービスのサンプルとして利用する。

Bookinfoの仕様

Bookinfoは前述のようにマイクロサービスの構造を持っていて、入口にはProduct pageがあり、そこから各サービスにアクセスする形になっている。
これのソースコードは以下となる。
https://github.com/istio/istio/blob/master/samples/bookinfo/src/productpage/productpage.py

内部での各サービスへのアクセス先は以下のよう定義されている。

reviews = {
    "name": "http://{0}{1}:{2}".format(reviewsHostname, servicesDomain, reviewsPort),
    "endpoint": "reviews",
    "children": [ratings]
}

実際にアクセスする際は以下のように値を使う。

    url = reviews['name'] + "/" + reviews['endpoint'] + "/" + str(product_id)
    res = send_request(url, headers=headers, timeout=3.0)

サービス間の接続はhttp://reviewsHostname:reviewsPort:servicesDomain/endpointで行われるが、ここのreviewsHostnameservicesDomainreviewsPortは環境変数で上書きすることが可能である。

環境変数 意味 デフォルト値
SERVICES_DOMAIN 共通ドメイン なし
DETAILS_HOSTNAME detailsへアクセスするためのホスト名 details
DETAILS_SERVICE_PORT detailsへアクセスするためのポート番号 9080
RATINGS_HOSTNAME ratingsへアクセスするためのホスト名 ratings
RATINGS_SERVICE_PORT ratingsへアクセスするためのポート番号 9080
REVIEWS_HOSTNAME reviewsへアクセスするためのホスト名 reviews
REVIEWS_SERVICE_PORT reviewsへアクセスするためのポート番号 9080

endpointは書き換え不可でホスト名のデフォルト値が適用される。

Kong Gatewayを挟む場合は上記の環境変数を使ってData Planeを指すように設定すればやりたいことが出来るようになる。

なお、上記のコードの中で以下のようなブロックがあるが、これはProductpageから各サービスに対してAPIが発行できるようになっているためである。
20250501130558.png

このパスは前述の環境変数で指定できるパスとは別物で、仕様に関してはOpen API Specが公開されているので気になる人はこちらを参照するとよい。

検証環境

今回は以下の環境で検証した。

  • Kubernetes:EKS
  • Ingress:Contour
  • Kong Gateway:Konnect

Konnectについてはdeckでアクセスする際に使う情報を以下の環境変数で設定している。

KONNECT_TOKEN=<Konnectのトークン>
KONNECT_CP=<KonnectのControl Plane名>

Ingressは検証目的として以下のように雑に作成済みである。検証するのになくても問題ない。

Data Plane
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: kong-dp
  namespace: kong
spec:
  rules:
  - host: dp.114.185.191.224.nip.io
    http:
      paths:
      - backend:
          service:
            name: my-kong-kong-proxy
            port:
              number: 80
        path: /
        pathType: Prefix
Bookinfo
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: bookinfo
spec:
  rules:
  - host: 114.185.191.224.nip.io
    http:
      paths:
      - backend:
          service:
            name: productpage
            port:
              number: 9080
        path: /
        pathType: Prefix

検証

Kong Gatewayを挟む

上述のように環境変数でProductpageから各サービスへのアクセス先が指定できるので以下のようにbookinfoのManifest内にあるProductpageのDeployment記載箇所に環境変数を追加する。なおオリジナルのManifestはこちらから入手できる。

diff -u bookinfo.yaml gw-bookinfo.yaml
--- bookinfo.yaml	2025-05-01 09:56:14
+++ gw-bookinfo.yaml	2025-05-01 13:48:47
@@ -329,6 +329,21 @@
         volumeMounts:
         - name: tmp
           mountPath: /tmp
+        env:
+        - name: SERVICES_DOMAIN
+          value: "kong.svc"
+        - name: DETAILS_HOSTNAME
+          value: "my-kong-kong-proxy"
+        - name: DETAILS_SERVICE_PORT
+          value: "80/details"
+        - name: RATINGS_HOSTNAME
+          value: "my-kong-kong-proxy"
+        - name: RATINGS_SERVICE_PORT
+          value: "80/ratings"
+        - name: REVIEWS_HOSTNAME
+          value: "my-kong-kong-proxy"
+        - name: REVIEWS_SERVICE_PORT
+          value: "80/reviews"
       volumes:
       - name: tmp
         emptyDir: {}

共通ドメインとしてSERVICES_DOMAINにNamespaceであるkong.svcを指定する。
Kong GatewayでProxyする際の都合上http://my-kong-kong-proxy.kong.svc/<サービス名>でサービスを分けるため、<サービス名>_HOSTNAMEには全てmy-kong-kong-proxyを指定する。
<サービス名>_SERVICE_PORTについてはポート指定部分で文字列が渡せるため、DPのポート番号80とサービス名を足した80/<サービス名>を指定する。
この状態でBookinfoを起動すると以下のようにエラーが出る状態で起動する。
20250501134417.png

Kong Gateway側の設定が終わっていないので、Productpageから各サービスにアクセスできないためエラーとなる。
次にKong Gatewayの設定を行う。
以下のdeck用YAMLを用意した。

kong.yaml
_format_version: "3.0"
services:
- host: details.bookinfo
  name: details-service
  path: /
  port: 9080
  protocol: http
  routes:
  - name: details-route
    paths:
    - ~/details
- host: ratings.bookinfo
  name: ratings-service
  path: /
  port: 9080
  protocol: http
  routes:
  - name: ratings-route
    paths:
    - ~/ratings
- host: reviews.bookinfo
  name: reviews-service
  path: /
  port: 9080
  protocol: http
  routes:
  - name: reviews-service
    paths:
    - ~/reviews

DPからBookinfo内のkind:ServiceにアクセスするためにKong側Serviceのhostには<Service名>.bookinfoを指定し、RouteのパスはBookinfoの<サービス名>_SERVICE_PORTで指定したパスを指定する。
これを以下のようにdeckでKong Gatewayに適用する。

deck --konnect-addr https://us.api.konghq.com --konnect-token $KONNECT_TOKEN --konnect-control-plane-name $KONNECT_CP gateway sync ../kong.yaml

この状態でProductpageにアクセスすると以下のように他のサービスも含めて表示される。
20250501152108.png

ちなみにKonnectを利用しているので、適用後は各サービスのアクセス状況も可視化できる。
20250501152405.png

Kong Gatewayのプラグインの適用

ここではBook Details部分にRate Limiting Pluginを適用して保護できるか確認する。
KonnectのWebUIから作成したRouteを選択し、PluginsからRate Limiting Pluginを追加する。
20250501153807.png

なお、設定値はここでは1分辺りのリクエスト数上限を3として設定した。
設定後、ブラウザで何度かアクセスしてみる。
すると以下のようにDetails部分だけエラーとなるのが確認できる。
20250501153929.png

プラグインが正常に動作したようだ。
KonnectのUIからもRate Limiting Pluginが作動し429エラーが発生していることが確認できる。
20250501154046.png

感想

既存のマイクロサービスの中にKong Gatewayを置くようなケースでは、Bookinfoのように環境変数で接続先が簡単に切り替えられる作りになっていないとコード修正が必要になる可能性もあり、12Factorに沿ったアプリケーション開発が重要になりそうだと感じた。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?