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?

Kong GatewayのSaaS版であるKonnectに対応したTerraform ProviderがひっそりとGitHubに公開されている
'24/6/13現在まだベータ版でありTerraformのページではドキュメントも公開されていない状態だが、使おうと思えば使える状態なので試しに使ってみる。

※'24/10/8追記:'24/9/12に1.0がリリースされました。ドキュメントも今は揃ってます。

ここでは以下をTerraformでやってみる

  1. ControlPlaneの構築
  2. ServiceとRouteの作成
  3. レート制限の設定

なお、DataPlaneに関してはKonnect APIの管轄外なのでKonnectのProviderからデプロイせず、別で行う必要がある(Cloud Gatewayの場合はデプロイ可能)。
別のProviderを使ってTerraform化は出来そうだがここでは対象外とした。
あと今回使うtfファイル・ディレクトリの配置に関しては適当なので、好みに合わせて適宜修正して欲しい。

terraform-provider-konnectとは

Kong KonnectのためのTerraform Providerで、以下のようなものの自動構築が可能となっている(らしい)。

  • Control Planeの構築
  • Cloud Gatewayの構築
  • Kong Gatewayの基本コンポーネント(Service、Route、Upstream、Consumer等)の設定
  • 一部のPluginの設定(AI関連や認証、レート制限、キャッシュ等範囲は広い)
  • その他もろもろ(Dev Portal、API Product、Organization、etc)

Konnectを自動構築する場合、これまではdeckで行うことが一般的だったが新しい選択肢が増えたといえる。

なお、deckと比較するとこんな感じじゃないかと思われる。

deck Terraform
基本機能のカバー範囲 Keyなどは含まれない Keyなど含んでやや広い
ControlPlane/DataPlaneのデプロイ 出来ない 出来る(DPはCloudGatewayのみ)
Plugin 完全サポート 特定のもののみ
サポートプラットフォーム Kong Gateway/Konnect Konnect+その他色々なプラットフォーム
実装の容易さ 慣れれば簡単 ドキュメントなく難
移植(Konnect↔KongGateway)の容易さ コード修正不要 別でコードが必要
CI/CDとの相性 バッチリ バッチリ

Terraform Providerだとドキュメントがないのとサポートプラグインが限られるのが非常に痛いが、ここが改善されるとdeckを置き換えても良さそう。

前提

以下が用意されているものとする。

  • Konnectのアカウントがある
  • Konnect上にOrganizationを作成済み

Konnectは無料枠でも問題ない。メールアドレスさえあれば利用できる。

構築・設定

KonnectのTerraform Providerを使って構築・設定を行っていく。
最終的には以下のファイルを作成する。

.
├── main.tf
├── modules
│   ├── control-planes
│   │   ├── main.tf
│   │   ├── output.tf
│   │   └── provider.tf
│   └── gateway-configs
│       ├── httpbin-ratelimit.tf
│       ├── httpbin-rt.tf
│       ├── httpbin-svc.tf
│       ├── main.tf
│       ├── provider.tf
│       └── variables.tf
├── provider.tf
└── variables.tf

なお、上記のファイルは以下に置いたので、実際に試したい人で作成するのが面倒であればそちらから入手して欲しい。
konnect-provider-sample

Terraform CLIの導入

この辺を参考に自PCにCLIをインストールする。
ここではMacの手順で進める。

brew tap hashicorp/tap
brew install hashicorp/tap/terraform

基本となるファイルの作成

KonnectへのAPIの発行はKonnectのPAT(Personal Access Token)を使う。
持っていない人はKonnectのPersonal Access Tokenのページに飛んで、Generate TokenでTokenを生成する。
次にトークンを環境変数に設定する。
TF_VAR_がついた環境変数はterraformコマンド実行時に変数として扱えるので、以下のような感じでトークンを設定する。

export TF_VAR_konnect_token=kpat_Qbzexxxxx

変数を定義するvariables.yamlを作成する

variables.yaml
variable "konnect_token" {
  description = "Konnect PAT"
  type = string
  sensitive = true
}

Terraform Providerを定義する。

provider.tf
terraform {
  required_providers {
    konnect = {
      source  = "kong/konnect"
    }
  }
}

provider "konnect" {
  personal_access_token = var.konnect_token
  server_url            = "https://us.api.konghq.com"
}

一旦ここでterraform initを実行してProviderが使えるか確認する。

$ terraform init

Initializing the backend...

Initializing provider plugins...
- Finding latest version of kong/konnect...
- Installing kong/konnect v0.2.5...
:(省略)
Terraform has been successfully initialized!
:(省略)

上記のように出力されればOK。

ControlPlaneの構築

Control Planeのtfファイルの格納用ディレクトリを作成する。

mkdir -p modules/control-planes

またこちらの下にもprovider.tfを配置する。

modules/control-planes/provider.tf
terraform {
  required_providers {
    konnect = {
      source  = "kong/konnect"
    }
  }
}

ControlPlaneはkonnect_gateway_control_planeで定義できる。
サンプルを参考に以下のように作成した。

modules/control-planes/main.tf
resource "konnect_gateway_control_plane" "tfdemo" {
  name         = "Control Plane by Terraform"
  description  = "Created by Terraform"
  cluster_type = "CLUSTER_TYPE_HYBRID"
  auth_type    = "pinned_client_certs"
}

少し補足する。
cluster_typeはControlPlaneをデプロイする時のタイプを指定するもので、以下の4️つから選択できる。

  • CLUSTER_TYPE_CONTROL_PLANE:Cloud Gateway用?
  • CLUSTER_TYPE_CONTROL_PLANE_GROUP:Control Plane Groupを選択したのと同じ
  • CLUSTER_TYPE_HYBRID:Kong Gateway( Self-Managed Gateway)を選択したのと同じ
  • CLUSTER_TYPE_K8S_INGRESS_CONTROLLER:Kong Ingress Controllerを選択したのと同じ

auth_typeControlPlaneとDataPlaneの通信方法を設定する箇所で、以下の2つから選択できる。

  • pinned_client_certs:Pinned mode(鍵認証)で動作
  • pki_client_certs:PKI mode(証明書による認証)で動作

Control Planeモジュールを読み込むためのmain.tfを作成する

main.tf
module "control-planes" {
  source = "./modules/control-planes"
}

モジュールを読み込ませる。

terraform init

設定を適用する。

terraform apply

問題なければ以下のようなメッセージが表示される。

Apply complete! Resources: 1 added, 0 changed, 0 destroyed.

Konnectにアクセスすると、以下のように設定した内容でControl Planeが作成されていることが分かる。
20240613141836.png

ServiceとRouteの作成

次にServiceとRouteを設定する。
Service・Route側でControl Planeを参照できるよう、outputでControlPlaneを出力する。

output.tf
output "cp" {
    value = konnect_gateway_control_plane.tfdemo
}

Service・Route作成に使うtfファイルの格納用ディレクトリを作成する。

mkdir -p modules/gateway-configs

またこちらの下にもprovider.tfを配置する。

modules/gateway-configs/provider.tf
terraform {
  required_providers {
    konnect = {
      source  = "kong/konnect"
    }
  }
}

ControlPlaneを参照するための変数を用意する。

modules/gateway-configs/variables.tf
variable "control_plane" {
  type = any
}

次にServiceを作成する。Serviceはここではhttpbinを利用する。
作成するファイルは以下となる。

modules/gateway-configs/httpbin-svc.tf
resource "konnect_gateway_service" "httpbin" {
  name             = "HTTPBin"
  protocol         = "https"
  host             = "httpbin.org"
  port             = 443
  path             = "/"
  control_plane_id = var.control_plane.id
}

control_plane_idはどのControlPlaneと紐づけるかを指定するためにControlPlaneのIDを指定する。
ControlPlaneのリソースがvar.control_planeに格納されるように後ほど設定する。
なお、おそらくIDのベタ書きでも行けるとは思う。

次にRouteを作成する。

modules/gateway-configs/httpbin-rt.tf
resource "konnect_gateway_route" "httpbin" {
  name    = "httpbin"
  paths   = ["/httpbin"]
  strip_path = true
  control_plane_id = var.control_plane.id
  service = {
    id = konnect_gateway_service.httpbin.id
  }
}

Serviceと同じ要領でcontrol_plane_idはControlPlane作成時に設定される変数の情報を使って引っ張る。
service.idについては同一モジュール内からリソース(konnect_gateway_service.httpbin)を直接参照してRouteを紐づける。
また、モジュールにはmain.tfが必要なので空ファイルを作成する。

touch modules/gateway-configs/main.tf

最後にroot直下のmain.tfに以下を追記する。

main.tf
module "gateway-configs" {
  source = "./modules/gateway-configs"
  control_plane = module.control-planes.cp
}

gateway-configsの中のvariables.tfで定義したcontrol_planeはここで設定した。

動かしてみる。

terraform apply

以下のような出力が得られるはずだ。

Apply complete! Resources: 2 added, 0 changed, 0 destroyed.

Konnect側でもService、Routeが作成されたことが確認できる。
20240613161625.png

ここで動作確認用にDataPlaneもデプロイしてhttpbinにアクセスできるかを確認する。
DataPlaneのデプロイ方法についてはTerraformを使っていないため割愛する。
ここではMac上にDockerでデプロイした。

Data Planeが提供するProxy経由でアクセスしてみる。

$ curl -i localhost:8000/httpbin/ip
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 47
Connection: keep-alive
Date: Thu, 13 Jun 2024 07:24:01 GMT
Server: gunicorn/19.9.0
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
X-Kong-Upstream-Latency: 731
X-Kong-Proxy-Latency: 1
Via: kong/3.7.0.0-enterprise-edition
X-Kong-Request-Id: 0c066f075523c4032279af617e1cb80c

{
  "origin": "192.168.127.1, xxx.xxx.xxx.xxx"
}

無事httpbinにアクセスできることが確認できた。

レート制限の設定

最後にRate Limit Pluginを使ってレート制限を設定する。
Rate Limit Pluginはリソースkonnect_gateway_plugin_rate_limitingで用意されているので以下のようにtfファイルを作成する。

modules/gateway-configs/httpbin-ratelimit.tf
resource "konnect_gateway_plugin_rate_limiting" "httpbin_rate_limiting_plugin" {
  enabled = true
  config = {
    minute = 5
    policy = "local"
  }
  protocols        = ["http", "https"]
  control_plane_id = var.control_plane.id
  route = {
    id = konnect_gateway_route.httpbin.id
  }
}

1分間のアクセス可能な上限を5回とした。
ServiceやRouteと書き方は変わらないので、ここでは書き方については補足説明は特にしない。
ファイル作成後、適用する。

terraform apply

Konnect上で適用されていることが分かる。
20240613174732.png

動作確認する。6回アクセスしてみる。

for((i=0;i<6;i++)); do curl -I localhost:8000/httpbin/ip | grep "HTTP\|Limit"; sleep 1 ; done

6回目で以下が表示されて上限に達したことが分かる。

HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit-Minute: 5
X-RateLimit-Remaining-Minute: 0
RateLimit-Remaining: 0
RateLimit-Limit: 5
RateLimit-Reset: 8

Pluginの適用も問題なさそうだ。

所感

Konnectの自動構築はdeckでも出来るが、他の環境も含めてまとめて一元管理・まとめて構築したい場合はTerraformが使えるのは嬉しい。
まだドキュメントがなくて使うにはかなりキツイが、今後の発展を見守りたい。

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?