有一篇关于使用 Terraform 构建 Konnect 环境 的文章,介绍了如何用 Terraform 配置 Konnect 环境。本文不涉及 Konnect,而是记录如何用 Terraform 配置本地(On-prem)Kong Gateway。

本次使用的 Terraform provider 如下:

https://github.com/Kong/terraform-provider-kong-gateway

https://registry.terraform.io/providers/Kong/kong-gateway/latest/docs

Kong 和 Terraform 的安装过程略。

最低所需文件

  • 指定 provider 及 Kong Gateway Admin API 地址
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
terraform {
  required_providers {
    kong-gateway = {
      source = "kong/kong-gateway"
    }
  }
}

provider "kong-gateway" {
  server_url = "http://localhost:8001"
}
  • Service 定义
1
2
3
4
5
6
7
resource "kong-gateway_service" "httpbin" {
  name     = "HTTPBin"
  protocol = "http"
  host     = "httpbin.org"
  port     = 80
  path     = "/"
}
  • Route 定义,通过 ID 关联 Service
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
resource "kong-gateway_route" "hello" {
  methods = ["GET"]
  name    = "Anything"
  paths   = ["/anything"]

  strip_path = false

  service = {
    id = kong-gateway_service.httpbin.id
  }
}

应用配置

Kong Gateway 的配置非常轻量,处理速度很快。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
terraform apply

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
  + create

Terraform will perform the following actions:

  # kong-gateway_route.hello will be created
  + resource "kong-gateway_route" "hello" {
      + created_at                 = (known after apply)
      + destinations               = (known after apply)
      + headers                    = (known after apply)
      + hosts                      = (known after apply)
      + https_redirect_status_code = (known after apply)
      + id                         = (known after apply)
      + methods                    = [
          + "GET",
        ]
      + name                       = "Anything"
      + path_handling              = (known after apply)
      + paths                      = [
          + "/anything",
        ]
      + preserve_host              = (known after apply)
      + protocols                  = (known after apply)
      + regex_priority             = (known after apply)
      + request_buffering          = (known after apply)
      + response_buffering         = (known after apply)
      + service                    = {
          + id = (known after apply)
        }
      + snis                       = (known after apply)
      + sources                    = (known after apply)
      + strip_path                 = false
      + tags                       = (known after apply)
      + updated_at                 = (known after apply)
    }

  # kong-gateway_service.httpbin will be created
  + resource "kong-gateway_service" "httpbin" {
      + ca_certificates    = (known after apply)
      + client_certificate = (known after apply)
      + connect_timeout    = (known after apply)
      + created_at         = (known after apply)
      + enabled            = (known after apply)
      + host               = "httpbin.org"
      + id                 = (known after apply)
      + name               = "HTTPBin"
      + path               = "/"
      + port               = 80
      + protocol           = "http"
      + read_timeout       = (known after apply)
      + retries            = (known after apply)
      + tags               = (known after apply)
      + tls_verify         = (known after apply)
      + tls_verify_depth   = (known after apply)
      + updated_at         = (known after apply)
      + write_timeout      = (known after apply)
    }

Plan: 2 to add, 0 to change, 0 to destroy.

Do you want to perform these actions?
  Terraform will perform the actions described above.
  Only 'yes' will be accepted to approve.

  Enter a value: yes

kong-gateway_service.httpbin: Creating...
kong-gateway_service.httpbin: Creation complete after 0s [id=13137290-ba88-432c-a9ea-d10465ffaa8f]
kong-gateway_route.hello: Creating...
kong-gateway_route.hello: Creation complete after 0s [id=152c5f85-cf3b-466a-8d0f-ead33de8f6ca]

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

动作确认

Service 和 Route 已新建

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
http :8001/services/13137290-ba88-432c-a9ea-d10465ffaa8f
...

{
    "ca_certificates": null,
    "client_certificate": null,
    "connect_timeout": 60000,
    "created_at": 1728370653,
    "enabled": true,
    "host": "httpbin.org",
    "id": "13137290-ba88-432c-a9ea-d10465ffaa8f",
    "name": "HTTPBin",
    "path": "/",
    "port": 80,
    "protocol": "http",
    "read_timeout": 60000,
    "retries": 5,
    "tags": null,
    "tls_verify": null,
    "tls_verify_depth": null,
    "updated_at": 1728370653,
    "write_timeout": 60000
}


http :8001/routes/152c5f85-cf3b-466a-8d0f-ead33de8f6ca
...

{
    "created_at": 1728370654,
    "destinations": null,
    "headers": null,
    "hosts": null,
    "https_redirect_status_code": 426,
    "id": "152c5f85-cf3b-466a-8d0f-ead33de8f6ca",
    "methods": [
        "GET"
    ],
    "name": "Anything",
    "path_handling": "v0",
    "paths": [
        "/anything"
    ],
    "preserve_host": false,
    "protocols": [
        "http",
        "https"
    ],
    "regex_priority": 0,
    "request_buffering": true,
    "response_buffering": true,
    "service": {
        "id": "13137290-ba88-432c-a9ea-d10465ffaa8f"
    },
    "snis": null,
    "sources": null,
    "strip_path": false,
    "tags": null,
    "updated_at": 1728370654
}

访问也没问题

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
http :8000/anything
HTTP/1.1 200 OK
...

{
    "args": {},
    "data": "",
    "files": {},
    "form": {},
    "headers": {
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate",
        "Host": "httpbin.org",
        "User-Agent": "HTTPie/2.6.0",
        "X-Amzn-Trace-Id": "Root=1-6704d7fb-33cba6d66cde8b1d7c734b11",
        "X-Forwarded-Host": "localhost",
        "X-Forwarded-Path": "/anything",
        "X-Kong-Request-Id": "7b13371017a1973e83cde51b8d9d1d45"
    },
    "json": null,
    "method": "GET",
    "origin": "172.21.0.1, 18.178.66.113",
    "url": "http://localhost/anything"
}

添加插件

为 Service 添加 Basic Auth 插件。目标 Service 可用 ID 指定。

1
2
3
4
5
6
7
8
9
resource "kong-gateway_plugin_basic_auth" "my_pluginbasicauth" {
  enabled = true
  service = {
    id = kong-gateway_service.httpbin.id
  }
  protocols = [
    "http"
  ]
}

接着定义 Consumer,并为其设置认证信息。

1
2
3
4
resource "kong-gateway_consumer" "alice" {
  username  = "alice"
  custom_id = "alice"
}
1
2
3
4
5
6
7
8
resource "kong-gateway_basic_auth" "my_basicauth" {
  username = "alice-test"
  password = "demo"

  consumer = {
    id = kong-gateway_consumer.alice.id
  }
}

再次动作确认

再次 terraform apply 后,如果不设置认证信息,访问会失败:

1
2
3
4
5
6
http :8000/anything
HTTP/1.1 401 Unauthorized
...
{
    "message": "Unauthorized"
}

加上用户名和密码后,访问成功:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
http :8000/anything --auth alice-test:demo
HTTP/1.1 200 OK
...

{
    "args": {},
    "data": "",
    "files": {},
    "form": {},
    "headers": {
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate",
        "Authorization": "Basic YWxpY2UtdGVzdDpkZW1v",
        "Host": "httpbin.org",
        "User-Agent": "HTTPie/2.6.0",
        "X-Amzn-Trace-Id": "Root=1-6704e137-4b63183d4b63d8bf460a923a",
        "X-Consumer-Custom-Id": "alice",
        "X-Consumer-Id": "5a32c0e9-035a-404c-95d1-1df3313a768d",
        "X-Consumer-Username": "alice",
        "X-Credential-Identifier": "alice-test",
        "X-Forwarded-Host": "localhost",
        "X-Forwarded-Path": "/anything",
        "X-Kong-Request-Id": "a541603da784b779c217c81ff65b9556"
    },
    "json": null,
    "method": "GET",
    "origin": "172.21.0.1, 18.178.66.113",
    "url": "http://localhost/anything"
}

删除配置

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
terraform destroy
...

Plan: 0 to add, 0 to change, 5 to destroy.

Do you really want to destroy all resources?
  Terraform will destroy all your managed infrastructure, as shown above.
  There is no undo. Only 'yes' will be accepted to confirm.

  Enter a value: yes

kong-gateway_basic_auth.my_basicauth: Destroying... [id=9f419547-0b9b-41c9-a595-f22c1539ff34]
kong-gateway_route.hello: Destroying... [id=152c5f85-cf3b-466a-8d0f-ead33de8f6ca]
kong-gateway_plugin_basic_auth.my_pluginbasicauth: Destroying... [id=741a6c67-5ef0-4c4e-94ec-f8597ce89992]
kong-gateway_basic_auth.my_basicauth: Destruction complete after 0s
kong-gateway_plugin_basic_auth.my_pluginbasicauth: Destruction complete after 0s
kong-gateway_consumer.alice: Destroying... [id=5a32c0e9-035a-404c-95d1-1df3313a768d]
kong-gateway_route.hello: Destruction complete after 0s
kong-gateway_service.httpbin: Destroying... [id=13137290-ba88-432c-a9ea-d10465ffaa8f]
kong-gateway_consumer.alice: Destruction complete after 0s
kong-gateway_service.httpbin: Destruction complete after 0s

Destroy complete! Resources: 5 destroyed.

所感

(20250403 更新)该 Issue 已解决,现在 RBAC 环境也能用了!

https://github.com/Kong/terraform-provider-kong-gateway/pull/7