4
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?

Kong Operatorの使い方

4
Last updated at Posted at 2025-12-05

本記事は「Kong Advent Calendar 2025」の6日目のエントリとして、Kong Operatorの使い方について解説する。

今までKong GatewayのエンティティのKubernetesサポートという観点では2つの方法が提供されてきた。
1つはKong Gateway Operatorで、もう1つはKong Ingress Controller(KIC)である。
これがKong Gateway Operator 2.0を機に統合され、Kong Operatorとして提供されるようになった。
(公開時のアナウンスはこちら)

現時点で操作できるものは以下となっている。

機能 サポート状況
Gateway Control Planes サポート済み
Gateway Configuration サポート済み
Dedicated Cloud Gateways 部分サポート
Kong Mesh 計画中
Developer Portal 計画中
Catalog 計画中
Analytics 計画中
Team Management 計画中
Organization Configuration 計画中

Kong Gateway OperatorではKongのエンティティを独自のカスタムリソースで定義し、KongServiceやKongRouteといったリソースを作成することでKong Gatewayの設定を行う。
一方で、Kong Ingress ControllerではKubernetesの標準リソースであるkind: Servicekind: Gatewayを使ってKong Gatewayの設定を行う。
Kong Operatorはそれら2つの方法をサポートしており、両方の方法でKong Gatewayの設定を行うことが出来る。

今回、検証ではそれら2つの方法が適切に動作するかを確認する。

検証環境

今回はk3dで検証した。
構築手順はこちらを参照。
またKong Konnectを利用するため、Databaseは用意せず、Control Planeについてはカスタムリソースとして定義してKonnect内に作成する。

準備 - Kong Operatorのインストール

公式のインストール手順に従って構築する。

最初にGateway APIリソースを使うためのCRDをインストールする。

kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/standard-install.yaml

cert-managerとの連携が出来るみたいなので、こちらの手順に従いcert-managerもインストールする。

helm install \
  cert-manager oci://quay.io/jetstack/charts/cert-manager \
  --version v1.19.1 \
  --namespace cert-manager \
  --create-namespace \
  --set crds.enabled=true

Helmのリポジトリを追加する。

helm repo add kong https://charts.konghq.com
helm repo update

cert-managerとの連携を有効にしてKong Operatorをインストールする。

helm upgrade --install kong-operator kong/kong-operator -n kong-system \
  --create-namespace \
  --set image.tag=2.0.5 \
  --set env.ENABLE_CONTROLLER_KONNECT=true \
  --set global.webhooks.options.certManager.enabled=true

インストール後のkong-system Namespaceの様子は以下の通り。

$ kubectl get all -n kong-system
NAME                                                                 READY   STATUS    RESTARTS   AGE
pod/kong-operator-kong-operator-controller-manager-db5fb9f6c-bjqhj   1/1     Running   0          116s

NAME                                                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)            AGE
service/kong-operator-kong-operator                   ClusterIP   10.43.201.235   <none>        8443/TCP           117s
service/kong-operator-kong-operator-metrics-service   ClusterIP   10.43.225.128   <none>        8080/TCP           117s
service/kong-operator-kong-operator-webhook           ClusterIP   10.43.2.168     <none>        443/TCP,5443/TCP   117s

NAME                                                             READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/kong-operator-kong-operator-controller-manager   1/1     1            1           117s

NAME                                                                       DESIRED   CURRENT   READY   AGE
replicaset.apps/kong-operator-kong-operator-controller-manager-db5fb9f6c   1         1         1       117s

検証 - KICを使わない構成

Data Planeの作成

こちらの手順に従ってData Planeを作成する。
最初にKonnectにアクセスするためのトークンを環境変数に設定する。
今回はKonnectのOrganizationのSystem Accountsから作成できるシステムトークンを使う。(Organization Admin権限を付与)
以下のように取得したトークンをKONNECT_TOKENという環境変数に設定する。

export KONNECT_TOKEN="spat_hC..."

次にKonnectへのAPI認証に使うカスタムリソースを作成する。
最初にkongというNamespaceを作成する。

kubectl create namespace kong

次にAPI認証用のカスタムリソースを作成する。

echo '
kind: KonnectAPIAuthConfiguration
apiVersion: konnect.konghq.com/v1alpha1
metadata:
  name: konnect-api-auth
  namespace: kong
spec:
  type: token
  token: "'$KONNECT_TOKEN'"
  serverURL: us.api.konghq.com
' | kubectl apply -f -

YAMLを見てもらえれば分かるが、接続先リージョンはUSとなっているので、もしリージョンを変更したい場合はserverURLの値を変更する。

次にControl Planeを構築する。これもカスタムリソースとして定義できる。

echo '
kind: KonnectGatewayControlPlane
apiVersion: konnect.konghq.com/v1alpha2
metadata:
  name: gateway-control-plane
  namespace: kong
spec:
  createControlPlaneRequest:
    name: my-operator-demo
  konnect:
    authRef:
      name: konnect-api-auth
' | kubectl apply -f -

spec.konnect.authRef.nameには先程作成したAPI認証用のカスタムリソース名を指定する。
あと、spec.createControlPlaneRequest.nameにはKonnect上で作成されるControl Planeの名前を指定する。
ここでは作成するControl Planeの名前をmy-operator-demoとして、動作を理解するために敢えてmetadata.nameとは異なる名前にしている。

作成が完了するとUI上からも確認できる。
20251201165923.png

次にKonnectExtensionというカスタムリソースを作成する。

echo '
kind: KonnectExtension
apiVersion: konnect.konghq.com/v1alpha2
metadata:
  name: my-konnect-config
  namespace: kong
spec:
  clientAuth:
    certificateSecret:
      provisioning: Automatic
  konnect:
    controlPlane:
      ref:
        type: konnectNamespacedRef
        konnectNamespacedRef:
          name: gateway-control-plane' | kubectl apply -f -

これはData PlaneがControl Planeに接続するための設定を定義するもので、ここでは自動的に証明書をプロビジョニングするように設定している。
spec.konnect.controlPlane.ref.konnectNamespacedRef.nameには先程作成したControl Planeのカスタムリソース名を指定する。
以上でData Planeをデプロイするための前提が整う。

次にData Planeをデプロイする。

echo '
apiVersion: gateway-operator.konghq.com/v1beta1
kind: DataPlane
metadata:
  name: dataplane-example
  namespace: kong
spec:
  extensions:
  - kind: KonnectExtension
    name: my-konnect-config
    group: konnect.konghq.com
  deployment:
    podTemplateSpec:
      spec:
        containers:
        - name: proxy
          image: kong/kong-gateway:3.12
' | kubectl apply -f -

先程作成したKonnectExtensionをspec.extensionsで指定することで、Control Planeとの紐づけを行う。
デプロイが完了するとUI上からも確認できる。
20251201170540.png

起動後のkong Namespaceの様子は以下の通り。

$ kubectl get all -n kong
NAME                                                     READY   STATUS    RESTARTS   AGE
pod/dataplane-dataplane-example-m8w7t-5965cc84bc-5p6fx   1/1     Running   0          68s

NAME                                                TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
service/dataplane-admin-dataplane-example-2pzp5     ClusterIP      None            <none>        8444/TCP                     69s
service/dataplane-ingress-dataplane-example-vvzfl   LoadBalancer   10.43.220.173   172.18.0.3    80:30360/TCP,443:30289/TCP   68s

NAME                                                READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/dataplane-dataplane-example-m8w7t   1/1     1            1           68s

NAME                                                           DESIRED   CURRENT   READY   AGE
replicaset.apps/dataplane-dataplane-example-m8w7t-5965cc84bc   1         1         1       68s

Data Planeへのアクセスはtype: LoadBalancerでport80と443に対して提供されていることが分かる。
Secretを確認すると動的に証明書が作成されていることも分かる。

$ kubectl describe secret dataplane-dataplane-example-4bzlx -n kong
Name:         dataplane-dataplane-example-4bzlx
Namespace:    kong
Labels:       gateway-operator.konghq.com/managed-by=dataplane
              gateway-operator.konghq.com/service-secret=dataplane-admin-dataplane-example-2pzp5
              konghq.com/secret=true
Annotations:  <none>

Type:  kubernetes.io/tls

Data
====
ca.crt:   648 bytes
tls.crt:  867 bytes
tls.key:  227 bytes

適当なPodから動作確認として443ポートにアクセスした結果は以下となる。

$ curl -k https://172.18.0.3:443
{
  "message":"no Route matched with those values",
  "request_id":"378cfa111c30f20c5a0cda7179a70a45"
}

問題なさそうだ。

Service, Route, Pluginの作成

Service, Route, Pluginもカスタムリソースとして定義できる。
最初にServiceを作成する。

echo '
kind: KongService
apiVersion: configuration.konghq.com/v1alpha1
metadata:
  name: service
  namespace: kong
spec:
  name: service
  host: httpbin.konghq.com
  controlPlaneRef:
    type: konnectNamespacedRef
    konnectNamespacedRef:
      name: gateway-control-plane
' | kubectl apply -f -

ここではKong社がホスティングしているhttpbinをServiceとして定義している。
spec.controlPlaneRefには先程作成したControl Planeのカスタムリソース名を指定する。

次にRouteを作成する。

echo '
kind: KongRoute
apiVersion: configuration.konghq.com/v1alpha1
metadata:
  name: route-with-service
  namespace: kong
spec:
  name: route-with-service
  protocols:
  - http
  paths:
  - "/"
  serviceRef:
    type: namespacedRef
    namespacedRef:
      name: service
' | kubectl apply -f -

spec.serviceRefには先程作成したServiceのカスタムリソース名を指定する。
作成後は以下のような感じになる。

$ kubectl get kongservice,kongroute -n kong
NAME                                           HOST                 PROTOCOL   PROGRAMMED
kongservice.configuration.konghq.com/service   httpbin.konghq.com              True

NAME                                                    PROGRAMMED
kongroute.configuration.konghq.com/route-with-service   True

ちなみにServiceとRouteはKong Gatewayのエンティティとしては親子関係的な関係になるが、Kong Operatorではそれぞれ独立したリソースとして定義され、ownerReferencesも設定されない。

アクセスすると以下のようになる。

$ curl localhost:80/ip
{
  "origin": "10.42.0.1"
}

Pluginも同様にカスタムリソースとして定義できる。

echo '
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: rate-limit-5-per-min
  namespace: kong
plugin: rate-limiting
config:
  minute: 5
  limit_by: ip
  policy: local
' | kubectl apply -f -

Pluginは単体では特定のエンティティとは紐づかない。
エンティティとの紐づけにはKongPluginBindingというカスタムリソースで紐づける。

echo '
kind: KongPluginBinding
apiVersion: configuration.konghq.com/v1alpha1
metadata:
  name: binding-route-example-rate-limiting
  namespace: kong
spec:
  pluginRef:
    kind: KongPlugin
    name: rate-limit-5-per-min
  targets:
    routeRef:
      group: configuration.konghq.com
      kind: KongRoute
      name: route-with-service
  controlPlaneRef:
    type: konnectNamespacedRef
    konnectNamespacedRef:
      name: gateway-control-plane
' | kubectl apply -f -

spec.pluginRefには先程作成したPluginのカスタムリソース名を指定し、spec.targets.routeRefにはPluginを適用するRouteのカスタムリソース名を指定する。
KongPluginBindingを作成した後にアクセスすると、ヘッダからRate Limiting Pluginが動作していることが分かる。

$ curl -s localhost:80/ip -i |grep Rate
X-RateLimit-Limit-Minute: 5
X-RateLimit-Remaining-Minute: 3
RateLimit-Reset: 38
RateLimit-Remaining: 3
RateLimit-Limit: 5

注意点

deckなどを使ってKubernetes API経由以外でリソースを削除した場合、一時的に削除されるがリコンサイルされて元に戻る。
逆にKubernetes APIを経由せずに作成したエンティティはKubernetes上では感知出来ないため、そのまま残り続ける。
deckの使い方として定常的に実行して設定のドリフトを検知・修正するという使い方があるが、Kubernetesリソースで管理する場合は矛盾が生じやすくなるため、deckは使わない方が良さそう。

検証 - KICを使う構成

Kong Ingress Controllerの特徴として、既存のKubernetesのkind: Serviceと紐づけてKong GatewayのServiceとして定義できる点がある。
これが適切にKong Operatorでも利用できるかも確認する。
先程はControl PlaneやData Planeを個別のカスタムリソースとして定義したが、ここではGatewayConfigurationリソースを使って一括で管理する方法を使ってみる。

準備

検証を進めやすくするために作成したリソースのうち、以下を削除する。

kubectl delete kongroute route-with-service -n kong
kubectl delete kongservice service -n kong
kubectl delete dataplane dataplane-example -n kong

上記のリソースに相当するリソースはGatewayリソースを作成する時に自動で生成される。
KongPluginは使うので残しておく。

Kong Operatorもインストールし直す。
恐らく元の設定でも問題なさそうだが、マイグレーションのページにあったオプションでインストールしなおす。

helm upgrade --install kong-operator kong/kong-operator \
  -n kong-system \
  --create-namespace \
  --take-ownership \
  --set env.ENABLE_CONTROLLER_KONNECT=true \
  --set ko-crds.enabled=true \
  --set global.conversionWebhook.enabled=true \
  --set global.conversionWebhook.certManager.enabled=true 

アクセス確認用のhttpbin.orgへのServiceを作成する。

echo '
apiVersion: v1
kind: Service
metadata:
  name: httpbin-external
  namespace: kong
  annotations:
    konghq.com/protocol: "https"
    konghq.com/port: "443"
    konghq.com/host-header: "httpbin.org"
spec:
  type: ExternalName
  externalName: httpbin.org
  ports:
  - name: https
    port: 443
    targetPort: 443
    protocol: TCP
' | kubectl apply -f -

アノテーションはKong Gatewayに対する設定となる。
今回はプラグインはRouteに設定するのでHTTPRouteリソース側のアノテーションに記載するが、Serviceにプラグインを設定したい場合は上記のアノテーションに追加する形で設定する。

KICモードの設定

KICモードで動作させるため、KonnectGatewayControlPlaneのcluster_typeCLUSTER_TYPE_K8S_INGRESS_CONTROLLERを設定する。
ここのパラメータはイミュータブルで変更できないので、一度リソースを削除してから作り直す。

kubectl delete konnectgatewaycontrolplane gateway-control-plane -n kong
echo '
kind: KonnectGatewayControlPlane
apiVersion: konnect.konghq.com/v1alpha2
metadata:
  name: gateway-control-plane
  namespace: kong
spec:
  createControlPlaneRequest:
    name: my-operator-demo
    cluster_type: CLUSTER_TYPE_K8S_INGRESS_CONTROLLER
  konnect:
    authRef:
      name: konnect-api-auth
' | kubectl apply -f -

次にGatewayConfigurationリソースを作成する。
これはKong Gatewayの設定を定義するもので、kind: GatewayClassと組み合わせて利用する。

echo '
kind: GatewayConfiguration
apiVersion: gateway-operator.konghq.com/v2beta1
metadata:
  name: kong
  namespace: kong
spec:
  extensions:
  - kind: KonnectExtension
    name: my-konnect-config
    group: konnect.konghq.com
  controlPlaneOptions:
    translation:
      combinedServicesFromDifferentHTTPRoutes: enabled
' | kubectl apply -f -

spec.controlPlaneOptions.translation.combinedServicesFromDifferentHTTPRoutesenabledに設定しているのはHTTPRouteとの統合のためで、設定の仕方はKOのアナウンスから流用した。
なお、この後Data Planeを作成するが、その仕様はspec.dataPlaneOptionsで指定することが出来る。(今回はデフォルト値を使用)

次にkind: Gatewaykind: GatewayClassを作成するが、その前にData Planeで使うポートをk3dで穴あけしておく。

k3d cluster edit dev --port-add "8000:8000@loadbalancer"

上記のはk3d固有の話なので、別環境でやっている人は無視してOK。
GatewayClassとGatewayのManifestは以下となる。

echo '
kind: GatewayClass
apiVersion: gateway.networking.k8s.io/v1
metadata:
  name: kong
  namespace: kong
spec:
  controllerName: konghq.com/gateway-operator
  parametersRef:
    group: gateway-operator.konghq.com
    kind: GatewayConfiguration
    name: kong
    namespace: kong
---
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1
metadata:
  name: kong
  namespace: kong
spec:
  gatewayClassName: kong
  listeners:
  - name: http
    protocol: HTTP
    port: 8000
    hostname: "proxy.hogehoge.info"
    allowedRoutes:
      namespaces:
        from: All
' | kubectl apply -f -

Gatewayリソースを作成すると、自動的にDataPlaneリソースも作成される。
なお、ホスト名は解決できるようにしておくこと。(自分の場合はRoute53で管理しているドメインを指定した)

最後にHTTPRouteリソースを作成する。

echo '
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: httpbin-route
  namespace: kong
  annotations:
    konghq.com/strip-path: "true"
    konghq.com/plugins: rate-limit-5-per-min
spec:
  parentRefs:
  - name: kong
  hostnames:
  - "proxy.hogehoge.info"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /httpbin
    backendRefs:
    - name: httpbin-external
      port: 443
' | kubectl apply -f -      

spec.parentRefsには先程作成したGatewayの名前を指定し、spec.rules.backendRefsには先程作成したkind: Serviceの名前を指定する。
またアノテーションでRouteの設定(Strip Path)やPluginの適用(先程作成したKongPluginを指定)も行っている。

動作確認

Gatewayで公開したポートを指定してアクセスしてみる。

curl http://proxy.hogehoge.info:8000/httpbin/user-agent -i

正常に動作していれば以下のようなレスポンスが返ってくる。

HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 33
Connection: keep-alive
X-RateLimit-Limit-Minute: 5
X-RateLimit-Remaining-Minute: 4
RateLimit-Reset: 12
RateLimit-Remaining: 4
RateLimit-Limit: 5
Date: Tue, 02 Dec 2025 01:39:48 GMT
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
X-Kong-Upstream-Latency: 6
X-Kong-Proxy-Latency: 1
Via: 1.1 kong/3.11.0.6-enterprise-edition
X-Kong-Request-Id: 28d346624a6f401a0586ec1784234c55

{
  "user-agent": "curl/8.7.1"
}

ヘッダからRate Limiting Pluginも適切に動作していることが分かる。

なお、Gatewayリソースの親子関係は以下となる。

$ kubectl tree gateway -n kong kong
NAMESPACE  NAME                                                          READY  REASON  STATUS   AGE
kong       Gateway/kong                                                  -              -        58m
kong       ├─ControlPlane/kong-gzt66                                     True   Ready   Current  58m
kong       │ └─Secret/controlplane-kong-gzt66-n2bkd                      -              -        58m
kong       ├─DataPlane/kong-5brt6                                        True   Ready   Current  58m
kong       │ ├─Deployment/dataplane-kong-5brt6-tcfqp                     -              -        58m
kong       │ │ ├─ReplicaSet/dataplane-kong-5brt6-tcfqp-6f774b5965        -              -        57m
kong       │ │ │ └─Pod/dataplane-kong-5brt6-tcfqp-6f774b5965-xnt24       True           Current  57m
kong       │ │ ├─ReplicaSet/dataplane-kong-5brt6-tcfqp-7476549495        -              -        58m
kong       │ │ └─ReplicaSet/dataplane-kong-5brt6-tcfqp-797d8f68c4        -              -        57m
kong       │ ├─Secret/dataplane-kong-5brt6-bt8mz                         -              -        58m
kong       │ ├─Service/dataplane-admin-kong-5brt6-gkmq4                  -              -        58m
kong       │ │ └─EndpointSlice/dataplane-admin-kong-5brt6-gkmq4-gwcm2    -              -        58m
kong       │ └─Service/dataplane-ingress-kong-5brt6-k2gff                -              -        58m
kong       │   └─EndpointSlice/dataplane-ingress-kong-5brt6-k2gff-d2s57  -              -        58m
kong       └─NetworkPolicy/kong-5brt6-limit-admin-api-qcb6n              -              -        57m

Control PlaneとData Planeが作成された事が分かる。

Konnect上で見た場合はこんな感じ。
20251202104242.png

作成したリソースがプラグイン含めて確認できる。

まとめ

Kong Operatorを使うと以下の2つのアプローチが出来ることを確認した。

  • カスタムリソースを使ってKong GatewayのエンティティをManifestとして管理できる
  • Kubernetesのネイティブリソースを使ってKong GatewayのエンティティをManifestとして管理できる

所感としてはKong Gateway OperatorとKong Ingress Controllerがいい感じで統合されていて、使い勝手とかはそれ程変わっていなさそうだった。
それぞれ使っている人は違和感なく移行できそうに思えた。
一方で、ドキュメントが不足しているようでカスタムリソースのYAMLの書き方が分からず結構苦労して検証した。
実運用に組み込む場合はある程度の試行錯誤が必要そうなので、十分に検証してから導入するのが良さそうだ。

関連記事

4
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
4
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?