Kubernetes Gateway による通信制御

NGINXをDataplaneとしてKubernetes Gatewayを利用する方法を紹介します。 Kubernetes Gatewayの情報は GitHub: nginx-gateway-fabric を参照してください

Note

本資料作成時点では、NGINX OSSを利用した動作確認となります

この章では、実際にデプロイしたNGINX Kubernetes Gatewayを使った通信制御方法を確認します 設定例は GitHub nginx-gateway-fabric/examples の内容となります

シンプルなWebアプリケーション

シンプルなWebアプリケーションをデプロイします。

https://github.com/nginxinc/nginx-gateway-fabric/tree/main/examples/cafe-example

サンプルアプリケーションをデプロイ

cd ~/nginx-gateway-fabric/examples/cafe-example/
kubectl apply -f cafe.yaml
kubectl apply -f gateway.yaml
kubectl apply -f cafe-routes.yaml

リソースの確認

作成したリソースの内容を確認します

cat gateway.yaml
実行結果サンプル
 1apiVersion: gateway.networking.k8s.io/v1beta1
 2kind: Gateway
 3metadata:
 4  name: gateway
 5  labels:
 6    domain: k8s-gateway.nginx.org
 7spec:
 8  gatewayClassName: nginx
 9  listeners:
10  - name: http
11    port: 80
12    protocol: HTTP
cat cafe-routes.yaml
実行結果サンプル
 1apiVersion: gateway.networking.k8s.io/v1beta1
 2kind: HTTPRoute
 3metadata:
 4  name: coffee
 5spec:
 6  parentRefs:
 7  - name: gateway
 8    sectionName: http
 9  hostnames:
10  - "cafe.example.com"
11  rules:
12  - matches:
13    - path:
14        type: PathPrefix
15        value: /coffee
16    backendRefs:
17    - name: coffee
18      port: 80
19---
20apiVersion: gateway.networking.k8s.io/v1beta1
21kind: HTTPRoute
22metadata:
23  name: tea
24spec:
25  parentRefs:
26  - name: gateway
27    sectionName: http
28  hostnames:
29  - "cafe.example.com"
30  rules:
31  - matches:
32    - path:
33        type: Exact
34        value: /tea
35    backendRefs:
36    - name: tea

正しくリソースが作成されたことを確認します

kubectl get gateway
実行結果サンプル
1NAME      CLASS   ADDRESS   PROGRAMMED   AGE
2gateway   nginx             True         72s

httproute を確認します。 cafe.example.com のHostnameに対し、 coffeetea がデプロイされています

kubectl get httproute
実行結果サンプル
1NAME     HOSTNAMES              AGE
2coffee   ["cafe.example.com"]   57s
3tea      ["cafe.example.com"]   57s

coffee と tea の Podがデプロイされていることが確認できます

kubectl get pod
実行結果サンプル
1NAME                      READY   STATUS    RESTARTS        AGE
2coffee-7c86d7d67c-dxw9s   1/1     Running   1 (152m ago)    11h
3tea-5c457db9-wrtn6        1/1     Running   1 (3h34m ago)   11h

リソースの詳細を確認します

Gatewayは通信の待ち受けに関する設定です

kubectl describe gateway gateway
実行結果サンプル
  1Name:         gateway
  2Namespace:    default
  3Labels:       domain=k8s-gateway.nginx.org
  4Annotations:  <none>
  5API Version:  gateway.networking.k8s.io/v1beta1
  6Kind:         Gateway
  7Metadata:
  8  Creation Timestamp:  2023-05-25T01:18:02Z
  9  Generation:          1
 10  Managed Fields:
 11    API Version:  gateway.networking.k8s.io/v1beta1
 12    Fields Type:  FieldsV1
 13    fieldsV1:
 14      f:metadata:
 15        f:annotations:
 16          .:
 17          f:kubectl.kubernetes.io/last-applied-configuration:
 18        f:labels:
 19          .:
 20          f:domain:
 21      f:spec:
 22        .:
 23        f:gatewayClassName:
 24        f:listeners:
 25          .:
 26          k:{"name":"http"}:
 27            .:
 28            f:allowedRoutes:
 29              .:
 30              f:namespaces:
 31                .:
 32                f:from:
 33            f:name:
 34            f:port:
 35            f:protocol:
 36    Manager:      kubectl-client-side-apply
 37    Operation:    Update
 38    Time:         2023-05-25T01:18:02Z
 39    API Version:  gateway.networking.k8s.io/v1beta1
 40    Fields Type:  FieldsV1
 41    fieldsV1:
 42      f:status:
 43        f:addresses:
 44        f:conditions:
 45          k:{"type":"Accepted"}:
 46            f:lastTransitionTime:
 47            f:message:
 48            f:observedGeneration:
 49            f:reason:
 50            f:status:
 51        f:listeners:
 52          .:
 53          k:{"name":"http"}:
 54            .:
 55            f:attachedRoutes:
 56            f:conditions:
 57              .:
 58              k:{"type":"Accepted"}:
 59                .:
 60                f:lastTransitionTime:
 61                f:message:
 62                f:observedGeneration:
 63                f:reason:
 64                f:status:
 65                f:type:
 66              k:{"type":"Conflicted"}:
 67                .:
 68                f:lastTransitionTime:
 69                f:message:
 70                f:observedGeneration:
 71                f:reason:
 72                f:status:
 73                f:type:
 74              k:{"type":"ResolvedRefs"}:
 75                .:
 76                f:lastTransitionTime:
 77                f:message:
 78                f:observedGeneration:
 79                f:reason:
 80                f:status:
 81                f:type:
 82            f:name:
 83            f:supportedKinds:
 84    Manager:         gateway
 85    Operation:       Update
 86    Subresource:     status
 87    Time:            2023-05-25T01:18:03Z
 88  Resource Version:  204507
 89  UID:               b680933d-a7a2-4780-a89e-c5e751abb971
 90Spec:
 91  Gateway Class Name:  nginx
 92  Listeners:
 93    Allowed Routes:
 94      Namespaces:
 95        From:  Same
 96    Name:      http
 97    Port:      80
 98    Protocol:  HTTP
 99Status:
100  Addresses:
101    Type:   IPAddress
102    Value:  192.168.127.2
103  Conditions:
104    Last Transition Time:  2023-05-25T01:18:08Z
105    Message:               Gateway is accepted
106    Observed Generation:   1
107    Reason:                Accepted
108    Status:                True
109    Type:                  Accepted
110  Listeners:
111    Attached Routes:  2
112    Conditions:
113      Last Transition Time:  2023-05-25T01:18:08Z
114      Message:               Listener is accepted
115      Observed Generation:   1
116      Reason:                Accepted
117      Status:                True
118      Type:                  Accepted
119      Last Transition Time:  2023-05-25T01:18:08Z
120      Message:               All references are resolved
121      Observed Generation:   1
122      Reason:                ResolvedRefs
123      Status:                True
124      Type:                  ResolvedRefs
125      Last Transition Time:  2023-05-25T01:18:08Z
126      Message:               No conflicts
127      Observed Generation:   1
128      Reason:                NoConflicts
129      Status:                False
130      Type:                  Conflicted
131    Name:                    http
132    Supported Kinds:
133      Group:  gateway.networking.k8s.io
134      Kind:   HTTPRoute
135Events:       <none>

HTTP RouteはHTTP通信の転送に関連するリソースです。 coffee の HTTP Routeの内容が以下です

kubectl describe httproute coffee
実行結果サンプル
 1Name:         coffee
 2Namespace:    default
 3Labels:       <none>
 4Annotations:  <none>
 5API Version:  gateway.networking.k8s.io/v1beta1
 6Kind:         HTTPRoute
 7Metadata:
 8  Creation Timestamp:  2023-05-25T01:18:06Z
 9  Generation:          1
10  Managed Fields:
11    API Version:  gateway.networking.k8s.io/v1beta1
12    Fields Type:  FieldsV1
13    fieldsV1:
14      f:metadata:
15        f:annotations:
16          .:
17          f:kubectl.kubernetes.io/last-applied-configuration:
18      f:spec:
19        .:
20        f:hostnames:
21        f:parentRefs:
22        f:rules:
23    Manager:      kubectl-client-side-apply
24    Operation:    Update
25    Time:         2023-05-25T01:18:06Z
26    API Version:  gateway.networking.k8s.io/v1beta1
27    Fields Type:  FieldsV1
28    fieldsV1:
29      f:status:
30        .:
31        f:parents:
32    Manager:         gateway
33    Operation:       Update
34    Subresource:     status
35    Time:            2023-05-25T01:18:07Z
36  Resource Version:  204508
37  UID:               126217a6-b7d4-4dc4-bceb-b969bdb94194
38Spec:
39  Hostnames:
40    cafe.example.com
41  Parent Refs:
42    Group:         gateway.networking.k8s.io
43    Kind:          Gateway
44    Name:          gateway
45    Section Name:  http
46  Rules:
47    Backend Refs:
48      Group:
49      Kind:    Service
50      Name:    coffee
51      Port:    80
52      Weight:  1
53    Matches:
54      Path:
55        Type:   PathPrefix
56        Value:  /coffee
57Status:
58  Parents:
59    Conditions:
60      Last Transition Time:  2023-05-25T01:18:08Z
61      Message:               The route is accepted
62      Observed Generation:   1
63      Reason:                Accepted
64      Status:                True
65      Type:                  Accepted
66      Last Transition Time:  2023-05-25T01:18:08Z
67      Message:               All references are resolved
68      Observed Generation:   1
69      Reason:                ResolvedRefs
70      Status:                True
71      Type:                  ResolvedRefs
72    Controller Name:         k8s-gateway.nginx.org/nginx-gateway-controller
73    Parent Ref:
74      Group:         gateway.networking.k8s.io
75      Kind:          Gateway
76      Name:          gateway
77      Namespace:     default
78      Section Name:  http
79Events:              <none>

tea の HTTP Routeの内容が以下です

kubectl describe httproute tea
実行結果サンプル
 1Name:         tea
 2Namespace:    default
 3Labels:       <none>
 4Annotations:  <none>
 5API Version:  gateway.networking.k8s.io/v1beta1
 6Kind:         HTTPRoute
 7Metadata:
 8  Creation Timestamp:  2023-05-25T01:18:06Z
 9  Generation:          1
10  Managed Fields:
11    API Version:  gateway.networking.k8s.io/v1beta1
12    Fields Type:  FieldsV1
13    fieldsV1:
14      f:metadata:
15        f:annotations:
16          .:
17          f:kubectl.kubernetes.io/last-applied-configuration:
18      f:spec:
19        .:
20        f:hostnames:
21        f:parentRefs:
22        f:rules:
23    Manager:      kubectl-client-side-apply
24    Operation:    Update
25    Time:         2023-05-25T01:18:06Z
26    API Version:  gateway.networking.k8s.io/v1beta1
27    Fields Type:  FieldsV1
28    fieldsV1:
29      f:status:
30        .:
31        f:parents:
32    Manager:         gateway
33    Operation:       Update
34    Subresource:     status
35    Time:            2023-05-25T01:18:08Z
36  Resource Version:  204509
37  UID:               901df757-fc2a-4d2d-9e9f-c36253cbdd19
38Spec:
39  Hostnames:
40    cafe.example.com
41  Parent Refs:
42    Group:         gateway.networking.k8s.io
43    Kind:          Gateway
44    Name:          gateway
45    Section Name:  http
46  Rules:
47    Backend Refs:
48      Group:
49      Kind:    Service
50      Name:    tea
51      Port:    80
52      Weight:  1
53    Matches:
54      Path:
55        Type:   Exact
56        Value:  /tea
57Status:
58  Parents:
59    Conditions:
60      Last Transition Time:  2023-05-25T01:18:08Z
61      Message:               The route is accepted
62      Observed Generation:   1
63      Reason:                Accepted
64      Status:                True
65      Type:                  Accepted
66      Last Transition Time:  2023-05-25T01:18:08Z
67      Message:               All references are resolved
68      Observed Generation:   1
69      Reason:                ResolvedRefs
70      Status:                True
71      Type:                  ResolvedRefs
72    Controller Name:         k8s-gateway.nginx.org/nginx-gateway-controller
73    Parent Ref:
74      Group:         gateway.networking.k8s.io
75      Kind:          Gateway
76      Name:          gateway
77      Namespace:     default
78      Section Name:  http
79Events:              <none>

動作確認

cafe.example.com/coffee に対してリクエストを送ります

curl -H "Host:cafe.example.com" http://localhost/coffee
実行結果サンプル
1Server address: 192.168.127.60:8080
2Server name: coffee-7c86d7d67c-dxw9s
3Date: 25/May/2023:01:21:02 +0000
4URI: /coffee
5Request ID: 9fb7dcfd60d04a9dbb510ab7bda6583a

cafe.example.com/tea に対してリクエストを送ります

curl -H "Host:cafe.example.com" http://localhost/tea
実行結果サンプル
1Server address: 192.168.127.62:8080
2Server name: tea-5c457db9-wrtn6
3Date: 25/May/2023:01:21:16 +0000
4URI: /tea
5Request ID: d2caeeaa2fe6722b3df9b8cbf145b382

リソースの削除

cd ~/nginx-gateway-fabric/examples/cafe-example/
kubectl delete -f cafe.yaml
kubectl delete -f gateway.yaml
kubectl delete -f cafe-routes.yaml

HTTPSの処理

HTTPSの終端とWebアプリケーションをデプロイします。

https://github.com/nginxinc/nginx-gateway-fabric/tree/main/examples/https-termination

サンプルアプリケーションをデプロイ

cd ~/nginx-gateway-fabric/examples/https-termination
kubectl apply -f cafe.yaml
kubectl apply -f gateway.yaml
kubectl apply -f cafe-routes.yaml
kubectl apply -f certificate-ns-and-cafe-secret.yaml
kubectl apply -f reference-grant.yaml

リソースの確認

主要なリソースの内容を確認します

cat gateway.yaml
実行結果サンプル
 1apiVersion: gateway.networking.k8s.io/v1beta1
 2kind: Gateway
 3metadata:
 4  name: gateway
 5  labels:
 6    domain: k8s-gateway.nginx.org
 7spec:
 8  gatewayClassName: nginx
 9  listeners:
10  - name: http
11    port: 80
12    protocol: HTTP
13  - name: https
14    port: 443
15    protocol: HTTPS
16    tls:
17      mode: Terminate
18      certificateRefs:
19      - kind: Secret
20        name: cafe-secret
21        namespace: default

listeners 待ち受ける通信を記述しています。また、httpsの配下に tls を記述し、TLSを終端すること(Terminate)や、利用する証明書(certificateRefs)を記述しています。

HTTPRouteの内容を確認します

cat cafe-routes.yaml
実行結果サンプル
 1apiVersion: gateway.networking.k8s.io/v1beta1
 2kind: HTTPRoute
 3metadata:
 4  name: cafe-tls-redirect
 5spec:
 6  parentRefs:
 7  - name: gateway
 8    sectionName: http
 9  hostnames:
10  - "cafe.example.com"
11  rules:
12  - filters:
13    - type: RequestRedirect
14      requestRedirect:
15        scheme: https
16        port: 443
17---
18apiVersion: gateway.networking.k8s.io/v1beta1
19kind: HTTPRoute
20metadata:
21  name: coffee
22spec:
23  parentRefs:
24  - name: gateway
25    sectionName: https
26  hostnames:
27  - "cafe.example.com"
28  rules:
29  - matches:
30    - path:
31        type: PathPrefix
32        value: /coffee
33    backendRefs:
34    - name: coffee
35      port: 80
36---
37apiVersion: gateway.networking.k8s.io/v1beta1
38kind: HTTPRoute
39metadata:
40  name: tea
41spec:
42  parentRefs:
43  - name: gateway
44    sectionName: https
45  hostnames:
46  - "cafe.example.com"
47  rules:
48  - matches:
49    - path:
50        type: PathPrefix
51        value: /tea
52    backendRefs:
53    - name: tea
54      port: 80

HTTPRouteを3つ指定しています。 1つ目のHTTPRouteはHTTPのりクストをHTTPSにリダイレクトします。parentRefsでGatewayの http を参照しています。 2つ目が /coffee に関する設定、3つ目が /tea に関する設定となります。parentRefsでGatewayの https を参照しています。

作成されたリソースの情報を確認します

kubectl get pod
実行結果サンプル
1NAME                      READY   STATUS    RESTARTS   AGE
2coffee-7c86d7d67c-x8rc6   1/1     Running   0          62s
3tea-5c457db9-gbxlp        1/1     Running   0          62s
kubectl get secret
実行結果サンプル
1default-token-rs5nm   kubernetes.io/service-account-token   3      182d
kubectl get gateway
実行結果サンプル
1NAME      CLASS   ADDRESS   PROGRAMMED   AGE
2gateway   nginx             True         100s
kubectl get httproute
実行結果サンプル
1NAME                HOSTNAMES              AGE
2cafe-tls-redirect   ["cafe.example.com"]   99s
3coffee              ["cafe.example.com"]   99s
4tea                 ["cafe.example.com"]   99s

動作確認

httpcafe.example.com/coffee に対してリクエストを送ります

curl -v --resolve cafe.example.com:80:127.0.0.1 http://cafe.example.com:80/coffee
実行結果サンプル
 1*   Trying 127.0.0.1:80...
 2* TCP_NODELAY set
 3* Connected to localhost (127.0.0.1) port 80 (#0)
 4> GET /coffee HTTP/1.1
 5> Host:cafe.example.com
 6> User-Agent: curl/7.68.0
 7> Accept: */*
 8>
 9* Mark bundle as not supporting multiuse
10< HTTP/1.1 302 Moved Temporarily
11< Server: nginx/1.23.4
12< Date: Thu, 25 May 2023 04:08:09 GMT
13< Content-Type: text/html
14< Content-Length: 145
15< Connection: keep-alive
16< Location: https://cafe.example.com:443/coffee
17<
18<html>
19<head><title>302 Found</title></head>
20<body>
21<center><h1>302 Found</h1></center>
22<hr><center>nginx/1.23.4</center>
23</body>
24</html>
25* Connection #0 to host localhost left intact

httpでアクセスした場合には 302 Moved Temporarily が応答され、Location Header が Location: https://cafe.example.com:443/coffee と返されていることがわかります

次にHTTPSで通信ができることを確認します

httpscafe.example.com/coffee に対してリクエストを送ります

curl -kv --resolve cafe.example.com:443:127.0.0.1 https://cafe.example.com:443/coffee
実行結果サンプル
 1* Added cafe.example.com:443:127.0.0.1 to DNS cache
 2* Hostname cafe.example.com was found in DNS cache
 3*   Trying 127.0.0.1:443...
 4* TCP_NODELAY set
 5* Connected to cafe.example.com (127.0.0.1) port 443 (#0)
 6* ALPN, offering h2
 7* ALPN, offering http/1.1
 8* successfully set certificate verify locations:
 9*   CAfile: /etc/ssl/certs/ca-certificates.crt
10  CApath: /etc/ssl/certs
11* TLSv1.3 (OUT), TLS handshake, Client hello (1):
12* TLSv1.3 (IN), TLS handshake, Server hello (2):
13* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
14* TLSv1.3 (IN), TLS handshake, Certificate (11):
15* TLSv1.3 (IN), TLS handshake, CERT verify (15):
16* TLSv1.3 (IN), TLS handshake, Finished (20):
17* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
18* TLSv1.3 (OUT), TLS handshake, Finished (20):
19* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
20* ALPN, server accepted to use http/1.1
21* Server certificate:
22*  subject: CN=cafe.example.com
23*  start date: Jul 14 21:52:39 2022 GMT
24*  expire date: Jul 14 21:52:39 2023 GMT
25*  issuer: CN=cafe.example.com
26*  SSL certificate verify result: self signed certificate (18), continuing anyway.
27> GET /coffee HTTP/1.1
28> Host: cafe.example.com
29> User-Agent: curl/7.68.0
30> Accept: */*
31>
32* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
33* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
34* old SSL session ID is stale, removing
35* Mark bundle as not supporting multiuse
36< HTTP/1.1 200 OK
37< Server: nginx/1.23.4
38< Date: Thu, 25 May 2023 04:21:02 GMT
39< Content-Type: text/plain
40< Content-Length: 163
41< Connection: keep-alive
42< Expires: Thu, 25 May 2023 04:21:01 GMT
43< Cache-Control: no-cache
44<
45Server address: 192.168.127.9:8080
46Server name: coffee-7c86d7d67c-x8rc6
47Date: 25/May/2023:04:21:02 +0000
48URI: /coffee
49Request ID: f82492f218b7b865c2a9745e859cf394
50* Connection #0 to host cafe.example.com left intact

200 OK が応答されており、正しく通信ができることが確認できます

同様に httpscafe.example.com/tea に対してリクエストを送ります

curl -kv --resolve cafe.example.com:443:127.0.0.1 https://cafe.example.com:443/tea
実行結果サンプル
 1* Added cafe.example.com:443:127.0.0.1 to DNS cache
 2* Hostname cafe.example.com was found in DNS cache
 3*   Trying 127.0.0.1:443...
 4* TCP_NODELAY set
 5* Connected to cafe.example.com (127.0.0.1) port 443 (#0)
 6* ALPN, offering h2
 7* ALPN, offering http/1.1
 8* successfully set certificate verify locations:
 9*   CAfile: /etc/ssl/certs/ca-certificates.crt
10  CApath: /etc/ssl/certs
11* TLSv1.3 (OUT), TLS handshake, Client hello (1):
12* TLSv1.3 (IN), TLS handshake, Server hello (2):
13* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
14* TLSv1.3 (IN), TLS handshake, Certificate (11):
15* TLSv1.3 (IN), TLS handshake, CERT verify (15):
16* TLSv1.3 (IN), TLS handshake, Finished (20):
17* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
18* TLSv1.3 (OUT), TLS handshake, Finished (20):
19* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
20* ALPN, server accepted to use http/1.1
21* Server certificate:
22*  subject: CN=cafe.example.com
23*  start date: Jul 14 21:52:39 2022 GMT
24*  expire date: Jul 14 21:52:39 2023 GMT
25*  issuer: CN=cafe.example.com
26*  SSL certificate verify result: self signed certificate (18), continuing anyway.
27> GET /tea HTTP/1.1
28> Host: cafe.example.com
29> User-Agent: curl/7.68.0
30> Accept: */*
31>
32* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
33* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
34* old SSL session ID is stale, removing
35* Mark bundle as not supporting multiuse
36< HTTP/1.1 200 OK
37< Server: nginx/1.23.4
38< Date: Thu, 25 May 2023 04:22:10 GMT
39< Content-Type: text/plain
40< Content-Length: 155
41< Connection: keep-alive
42< Expires: Thu, 25 May 2023 04:22:09 GMT
43< Cache-Control: no-cache
44<
45Server address: 192.168.127.6:8080
46Server name: tea-5c457db9-gbxlp
47Date: 25/May/2023:04:22:10 +0000
48URI: /tea
49Request ID: dd548205c65fbbab524ccb3d0cce1ba8
50* Connection #0 to host cafe.example.com left intact

リソースの削除

cd ~/nginx-gateway-fabric/examples/https-termination
kubectl delete -f cafe.yaml
kubectl delete -f gateway.yaml
kubectl delete -f cafe-routes.yaml
kubectl delete -f reference-grant.yaml
kubectl delete -f certificate-ns-and-cafe-secret.yaml

通信内容の条件分岐(Advanced Routing)

より柔軟な通信の制御方法を確認します

https://github.com/nginxinc/nginx-gateway-fabric/tree/main/examples/advanced-routing

サンプルアプリケーションをデプロイ

## cd ~/nginx-gateway-fabric/examples/advanced-routing
kubectl apply -f cafe.yaml
kubectl apply -f gateway.yaml
kubectl apply -f cafe-routes.yaml

リソースの確認

cafe-route.yaml の内容を確認します。

## cd ~/nginx-gateway-fabric/examples/advanced-routing
cat cafe-routes.yaml
実行結果サンプル
 1apiVersion: gateway.networking.k8s.io/v1beta1
 2kind: HTTPRoute
 3metadata:
 4  name: coffee
 5spec:
 6  parentRefs:
 7  - name: gateway
 8  hostnames:
 9  - "cafe.example.com"
10  rules:
11  - matches:
12    - path:
13        type: PathPrefix
14        value: /coffee
15    backendRefs:
16    - name: coffee-v1-svc
17      port: 80
18  - matches:
19    - path:
20        type: PathPrefix
21        value: /coffee
22      headers:
23      - name: version
24        value: v2
25    - path:
26        type: PathPrefix
27        value: /coffee
28      queryParams:
29      - name: TEST
30        value: v2
31    backendRefs:
32    - name: coffee-v2-svc
33      port: 80
34---
35apiVersion: gateway.networking.k8s.io/v1beta1
36kind: HTTPRoute
37metadata:
38  name: tea
39spec:
40  parentRefs:
41  - name: gateway
42  hostnames:
43  - "cafe.example.com"
44  rules:
45  - matches:
46    - path:
47        type: PathPrefix
48        value: /tea
49      method: POST
50    backendRefs:
51    - name: tea-post-svc
52      port: 80
53  - matches:
54    - path:
55        type: PathPrefix
56        value: /tea
57      method: GET
58    backendRefs:
59    - name: tea-svc
60      port: 80

1つ目が /coffee 、2つ目が /tea の内容となります。双方 rules が定義されており、その配下に通信の転送条件を指定しています 設定の内容を読み解くと以下のようになります。

  • /cofee

type

key

value

backend

header

version

v2

coffee-v2-svc

query

TEST

v2

coffee-v2-svc

-

-

-

coffee-v1-svc

  • /tea

type

value

backend

method

POST

tea-post-svc

method

GET

tea-svc

リソースを確認します

kubectl get pod
実行結果サンプル
1NAME                         READY   STATUS    RESTARTS   AGE
2coffee-v1-6b78998db9-25vv6   1/1     Running   0          24s
3coffee-v2-748cbbb49f-v4s47   1/1     Running   0          24s
4tea-5c457db9-fwxwm           1/1     Running   0          24s
5tea-post-7db8cd8bf-wz4sw     1/1     Running   0          24s
kubectl get svc | grep -v kubernetes
実行結果サンプル
1NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
2coffee-v1-svc   ClusterIP   10.98.220.232   <none>        80/TCP    34s
3coffee-v2-svc   ClusterIP   10.98.18.61     <none>        80/TCP    33s
4tea-post-svc    ClusterIP   10.101.63.1     <none>        80/TCP    33s
5tea-svc         ClusterIP   10.105.150.72   <none>        80/TCP    33s
kubectl get gateway
実行結果サンプル
1NAME      CLASS   ADDRESS         PROGRAMMED   AGE
2gateway   nginx   192.168.127.2                23s
kubectl get httproute
実行結果サンプル
1NAME     HOSTNAMES              AGE
2coffee   ["cafe.example.com"]   22s
3tea      ["cafe.example.com"]   22s

動作確認

先程の表に示した内容と同じ結果となることを確認します。

/coffee 宛のリクエストでHTTPヘッダーに値を指定します

curl -H "Host:cafe.example.com" http://localhost/coffee -H "version:v2"
実行結果サンプル
1Server address: 192.168.127.7:8080
2Server name: coffee-v2-748cbbb49f-v4s47
3Date: 25/May/2023:07:51:49 +0000
4URI: /coffee
5Request ID: 49189037592857bbdb7d814c80a7bce2

/coffee 宛のリクエストでQuery Parameterを指定します

curl -H "Host:cafe.example.com" http://localhost/coffee?TEST=v2
実行結果サンプル
1erver address: 192.168.127.7:8080
2Server name: coffee-v2-748cbbb49f-v4s47
3Date: 25/May/2023:07:52:04 +0000
4URI: /coffee?TEST=v2
5Request ID: 88ef837322389f2ef34fd70b8be890d9

/coffee 宛のリクエストで何も指定を行いません

curl -H "Host:cafe.example.com" http://localhost/coffee
実行結果サンプル
1Server address: 192.168.127.10:8080
2Server name: coffee-v1-6b78998db9-25vv6
3Date: 25/May/2023:07:52:16 +0000
4URI: /coffee
5Request ID: e3c5a1e8a74193c71906583d4dcbb4b6

/tea 宛のリクエストでPOST Methodを指定します

curl -H "Host:cafe.example.com" http://localhost/tea -X POST
実行結果サンプル
1Server address: 192.168.127.8:8080
2Server name: tea-post-7db8cd8bf-wz4sw
3Date: 25/May/2023:07:52:32 +0000
4URI: /tea
5Request ID: 1a6f6f4d8c205e70001769f8450a784c

/tea 宛のリクエストでGET Methodを指定します

curl -H "Host:cafe.example.com" http://localhost/tea -X GET
実行結果サンプル
1Server address: 192.168.127.14:8080
2Server name: tea-5c457db9-fwxwm
3Date: 25/May/2023:07:52:42 +0000
4URI: /tea
5Request ID: 68272b109b4e7f0aaf82d2b0f8541b35

/tea 宛のリクエストでPUT Methodを指定します。こちらのMethodは条件に含まれていないためエラーとなります。

curl -H "Host:cafe.example.com" http://localhost/tea -X PUT
実行結果サンプル
1<html>
2<head><title>404 Not Found</title></head>
3<body>
4<center><h1>404 Not Found</h1></center>
5<hr><center>nginx/1.23.4</center>
6</body>
7</html>

リソースの削除

## cd ~/nginx-gateway-fabric/examples/advanced-routing
kubectl delete -f cafe.yaml
kubectl delete -f gateway.yaml
kubectl delete -f cafe-routes.yaml

割合を指定した分散 (Traffic Split)

トラフィック分割を確認します

https://github.com/nginxinc/nginx-gateway-fabric/tree/main/examples/traffic-splitting

サンプルアプリケーションをデプロイ

cd ~/nginx-gateway-fabric/examples/traffic-splitting
kubectl apply -f cafe.yaml
kubectl apply -f gateway.yaml
kubectl apply -f cafe-route.yaml

リソースの確認

作成したリソースの内容を確認します

cat cafe-route.yaml
実行結果サンプル
 1apiVersion: gateway.networking.k8s.io/v1beta1
 2kind: HTTPRoute
 3metadata:
 4  name: cafe-route
 5spec:
 6  parentRefs:
 7  - name: gateway
 8    sectionName: http
 9  hostnames:
10  - "cafe.example.com"
11  rules:
12  - matches:
13    - path:
14        type: PathPrefix
15        value: /coffee
16    backendRefs:
17    - name: coffee-v1
18      port: 80
19      weight: 80
20    - name: coffee-v2
21      port: 80
22      weight: 20

backendRefs で通信の転送先サービスを指定する箇所で、 weight を指定しています。 coffee-v1weight 80coffee-v2weight 20 となります

正しくリソースが作成されたことを確認します

kubectl get gateway
実行結果サンプル
1NAME      CLASS   ADDRESS         PROGRAMMED   AGE
2gateway   nginx   192.168.127.2                12s
kubectl get httproute
実行結果サンプル
1NAME         HOSTNAMES              AGE
2cafe-route   ["cafe.example.com"]   4s
kubectl get pod
実行結果サンプル
1NAME                         READY   STATUS    RESTARTS   AGE
2coffee-v1-6b78998db9-vtpvz   1/1     Running   0          56s
3coffee-v2-748cbbb49f-ndvp8   1/1     Running   0          56s
kubectl get svc | grep -v kubernetes
実行結果サンプル
1NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
2coffee-v1    ClusterIP   10.111.57.103   <none>        80/TCP    66s
3coffee-v2    ClusterIP   10.97.133.169   <none>        80/TCP    66s

動作確認

Curlコマンドで複数回リクエストを送ると、 coffee-v1coffee-v2 のそれぞれに転送されていることが確認できます

curl -s -H "Host: cafe.example.com" http://localhost/coffee
実行結果サンプル
1Server address: 192.168.127.11:8080
2Server name: coffee-v2-748cbbb49f-ndvp8
3Date: 25/May/2023:08:19:17 +0000
4URI: /coffee
5Request ID: cc8c76a2a5e04c6dc43b99f7a740f8ae
curl -s -H "Host: cafe.example.com" http://localhost/coffee
実行結果サンプル
1Server address: 192.168.127.13:8080
2Server name: coffee-v1-6b78998db9-vtpvz
3Date: 25/May/2023:08:19:20 +0000
4URI: /coffee
5Request ID: bb7154122f4fe64cccb002c113cdb364

以下コマンドを参考に複数回Curlを実行し、その結果をファイルに記録します。記録の内容より coffee-v1coffee-v2 転送した数を確認できます。 分散する割合は少しばらつきが発生しますが、参考として分散した数の結果を確認してください。

## cd ~/nginx-gateway-fabric/examples/traffic-splitting
> split.txt ;\
for i in {1..20}; \
do curl -s -H "Host: cafe.example.com" http://localhost/coffee | grep "Server name" >> split.txt ; \
done ; \
echo -n "v1:" ; grep v1 split.txt  | wc -l ; echo -n "v2:"  ; grep v2 split.txt  | wc -l
実行結果サンプル
1v1:16
2v2:4

実行タイミングによって結果は頻繁に変わりますが、大まかに 8:2 の割合で通信が転送できることがわかります。

割合の変更

割合を 8:2 から、 5:5(同じ割合) に変更します。

これから適用するHTTPRouteと現在設定している内容を比較します。

diff -u cafe-route.yaml cafe-route-equal-weight.yaml
実行結果サンプル
1 --- cafe-route.yaml     2023-05-25 08:58:27.326066185 +0900
2 +++ cafe-route-equal-weight.yaml        2023-05-25 08:58:27.326066185 +0900
3 @@ -19,4 +19,4 @@
4        weight: 80
5      - name: coffee-v2
6        port: 80
7 -      weight: 20
8 +      weight: 80

差分から、 coffee-v2weight 80 とすることで、 1:1 の割合となるようにしています。

設定を反映します。

kubectl apply -f cafe-route-equal-weight.yaml

動作確認

Curlコマンドの結果に変化はありません。

curl -s -H "Host: cafe.example.com" http://localhost/coffee

以下コマンドを実行し、転送される割合を確認します。

## cd ~/nginx-gateway-fabric/examples/traffic-splitting
> split-equal.txt ;\
for i in {1..20}; \
do curl -s -H "Host: cafe.example.com" http://localhost/coffee | grep "Server name" >> split-equal.txt ; \
done ; \
echo -n "v1:" ; grep v1 split-equal.txt  | wc -l ; echo -n "v2:"  ; grep v2 split-equal.txt  | wc -l
実行結果サンプル
1v1:10
2v2:10

指定した割合となっていることが確認できます

リソースの削除

## cd ~/nginx-gateway-fabric/examples/traffic-splitting
kubectl delete -f gateway.yaml
kubectl delete -f cafe-route-equal-weight.yaml
kubectl delete -f cafe.yaml