From a066e47678a4f2f0fa21e447261c2f4b7b0210e6 Mon Sep 17 00:00:00 2001 From: Saylor Berman Date: Thu, 17 Aug 2023 15:53:58 -0600 Subject: [PATCH] Add advanced routing guide Problem: As a potential user of NKG I want a guide to help me understand how I can direct traffic to my set of applications, utilizing different paths, http verbs, and hostnames, headers, and query parameters. So that I can easily understand how to immediately start using NKG in my environment. Solution: Add a guide describing how to configure more advanced HTTPRoutes using various parameters. --- docs/guides/README.md | 2 + docs/guides/advanced-routing.md | 359 ++++++++++++++++++ docs/images/advanced-routing.png | Bin 0 -> 64807 bytes docs/images/src/advanced-routing.mermaid | 38 ++ docs/installation.md | 4 - docs/release-process.md | 5 +- examples/advanced-routing/README.md | 153 +------- examples/advanced-routing/cafe-routes.yaml | 8 +- .../{cafe.yaml => coffee.yaml} | 66 ---- examples/advanced-routing/gateway.yaml | 2 +- examples/advanced-routing/tea.yaml | 65 ++++ 11 files changed, 473 insertions(+), 229 deletions(-) create mode 100644 docs/guides/advanced-routing.md create mode 100644 docs/images/advanced-routing.png create mode 100644 docs/images/src/advanced-routing.mermaid rename examples/advanced-routing/{cafe.yaml => coffee.yaml} (50%) create mode 100644 examples/advanced-routing/tea.yaml diff --git a/docs/guides/README.md b/docs/guides/README.md index 7aceccb35b..2268d72087 100644 --- a/docs/guides/README.md +++ b/docs/guides/README.md @@ -6,6 +6,8 @@ This directory contains guides for configuring NGINX Kubernetes Gateway for vari - [Routing Traffic to Your Application](routing-traffic-to-your-app.md): How to use NGINX Kubernetes Gateway to route all Ingress traffic to your Kubernetes application. +- [Routing to Applications Using HTTP Matching Conditions](advanced-routing.md): Guide on how to deploy multiple + applications and HTTPRoutes with request conditions such as paths, methods, headers, and query parameters. - [Securing Traffic using Let's Encrypt and Cert-Manager](integrating-cert-manager.md): Shows how to secure traffic from clients to NGINX Kubernetes Gateway with TLS using Let's Encrypt and Cert-Manager. - [Using NGINX Kubernetes Gateway to Upgrade Applications without Downtime](upgrade-apps-without-downtime.md): diff --git a/docs/guides/advanced-routing.md b/docs/guides/advanced-routing.md new file mode 100644 index 0000000000..d930b7b6c0 --- /dev/null +++ b/docs/guides/advanced-routing.md @@ -0,0 +1,359 @@ +# Routing to Applications Using HTTP Matching Conditions + +In this guide we will configure advanced routing rules for multiple applications. These rules will showcase request +matching by path, headers, query parameters, and method. For an introduction to exposing your application, it is +recommended to go through the [basic guide](/docs/guides/routing-traffic-to-your-app.md) first. + +The following image shows the traffic flow that we will be creating with these rules. + +![Traffic Flow Diagram](/docs/images/advanced-routing.png) + +The goal is to create a set of rules that will result in client requests being sent to specific backends based on +the request attributes. In this diagram, we have two versions of the `coffee` service. Traffic for v1 needs to be +directed to the old application, while traffic for v2 needs to be directed towards the new application. We also +have two `tea` services, one that handles GET operations and one that handles POST operations. Both the `tea` +and `coffee` applications share the same Gateway. + +## Prerequisites + +- [Install](/docs/installation.md) NGINX Kubernetes Gateway. +- [Expose NGINX Kubernetes Gateway](/docs/installation.md#expose-nginx-kubernetes-gateway) and save the public IP + address and port of NGINX Kubernetes Gateway into shell variables: + + ```text + GW_IP=XXX.YYY.ZZZ.III + GW_PORT= + ``` + +> **Note** +> In a production environment, you should have a DNS record for the external IP address that is exposed, +> and it should refer to the hostname that the gateway will forward for. + +## Coffee Applications + +### Deploy the Coffee Applications + +Begin by deploying the `coffee-v1` and `coffee-v2` applications: + +```shell +kubectl apply -f https://raw.githubusercontent.com/nginxinc/nginx-kubernetes-gateway/main/examples/advanced-routing/coffee.yaml +``` + +### Deploy the Gateway API Resources for the Coffee Applications + +The [Gateway](https://gateway-api.sigs.k8s.io/api-types/gateway/) resource is typically deployed by the +[cluster operator][roles-and-personas]. To deploy the Gateway: + +```yaml +kubectl apply -f - < **Note** +> If you have a DNS record allocated for `cafe.example.com`, you can send the request directly to that +> hostname, without needing to resolve. + +```shell +curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/coffee +``` + +This request should receive a response from the `coffee-v1` Pod. + +```text +Server address: 10.244.0.9:8080 +Server name: coffee-v2-68bd55f798-s9z5q +``` + +If we want our request to be routed to `coffee-v2`, then we need to meet the defined conditions. We can include +a header: + +```shell +curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/coffee -H "version:v2" +``` + +or include a query parameter: + +```shell +curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/coffee?TEST=v2 +``` + +Either request should result in a response from the `coffee-v2` Pod. + +```text +Server address: 10.244.0.9:8080 +Server name: coffee-v2-68bd55f798-s9z5q +``` + +## Tea Applications + +Let's deploy a different set of applications now called `tea` and `tea-post`. These applications will +have their own set of rules, but will still attach to the same Gateway listener as the `coffee` apps. + +### Deploy the Tea Applications + +```shell +kubectl apply -f https://raw.githubusercontent.com/nginxinc/nginx-kubernetes-gateway/main/examples/advanced-routing/tea.yaml +``` + +### Deploy the HTTPRoute for the Tea Services + +We are reusing the previous Gateway for these applications, so all we need to create is the HTTPRoute. + +```yaml +kubectl apply -f - < **Note** +> If you have a DNS record allocated for `cafe.example.com`, you can send the request directly to that +> hostname, without needing to resolve. + +```shell +curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/tea +``` + +This GET request should receive a response from the `tea` Pod. + +```text +Server address: 10.244.0.10:8080 +Server name: tea-df5655878-5fmfg +``` + +If we want our request to be routed to `tea-post`, then we need to send a POST request: + +```shell +curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/tea -X POST +``` + +```text +Server address: 10.244.0.7:8080 +Server name: tea-post-b59b8596b-g586r +``` + +This request should receive a response from the `tea-post` Pod. Any other type of method, such as PATCH, will +result in a `404 Not Found` response. + + +## Troubleshooting + +If you have any issues while sending traffic, try the following to debug your configuration and setup: + +- Make sure you set the shell variables $GW_IP and $GW_PORT to the public IP and port of the NGINX Kubernetes Gateway + Service. Instructions for finding those values are [here](/docs/installation.md#expose-nginx-kubernetes-gateway). + +- Check the status of the Gateway: + + ```shell + kubectl describe gateway cafe + ``` + + The Gateway status should look like this: + + ```text + Status: + Addresses: + Type: IPAddress + Value: 10.244.0.85 + Conditions: + Last Transition Time: 2023-08-15T20:57:21Z + Message: Gateway is accepted + Observed Generation: 1 + Reason: Accepted + Status: True + Type: Accepted + Last Transition Time: 2023-08-15T20:57:21Z + Message: Gateway is programmed + Observed Generation: 1 + Reason: Programmed + Status: True + Type: Programmed + Listeners: + Attached Routes: 2 + Conditions: + Last Transition Time: 2023-08-15T20:57:21Z + Message: Listener is accepted + Observed Generation: 1 + Reason: Accepted + Status: True + Type: Accepted + Last Transition Time: 2023-08-15T20:57:21Z + Message: Listener is programmed + Observed Generation: 1 + Reason: Programmed + Status: True + Type: Programmed + Last Transition Time: 2023-08-15T20:57:21Z + Message: All references are resolved + Observed Generation: 1 + Reason: ResolvedRefs + Status: True + Type: ResolvedRefs + Last Transition Time: 2023-08-15T20:57:21Z + Message: No conflicts + Observed Generation: 1 + Reason: NoConflicts + Status: False + Type: Conflicted + Name: http + ``` + + Check that the conditions match and that the attached routes for the `http` listener equals 2. If it is less than + 2, there may be an issue with the routes. + +- Check the status of the HTTPRoutes: + + ```shell + kubectl describe httproute coffee + ``` + + ```shell + kubectl describe httproute tea + ``` + + Each HTTPRoute status should look like this: + + ```text + Status: + Parents: + Conditions: + Last Transition Time: 2023-08-15T20:57:21Z + Message: The route is accepted + Observed Generation: 1 + Reason: Accepted + Status: True + Type: Accepted + Last Transition Time: 2023-08-15T20:57:21Z + Message: All references are resolved + Observed Generation: 1 + Reason: ResolvedRefs + Status: True + Type: ResolvedRefs + Controller Name: gateway.nginx.org/nginx-gateway-controller + Parent Ref: + Group: gateway.networking.k8s.io + Kind: Gateway + Name: cafe + Namespace: default + ``` + + Check for any error messages in the conditions. + +## Further Reading + +To learn more about the Gateway API and the resources we created in this guide, check out the following resources: + +- [Gateway API Overview](https://gateway-api.sigs.k8s.io/concepts/api-overview/) +- [Deploying a simple Gateway](https://gateway-api.sigs.k8s.io/guides/simple-gateway/) +- [HTTP Routing](https://gateway-api.sigs.k8s.io/guides/http-routing/) diff --git a/docs/images/advanced-routing.png b/docs/images/advanced-routing.png new file mode 100644 index 0000000000000000000000000000000000000000..9be8d7c509f59e5e161a2ac6a2b0453f85e83717 GIT binary patch literal 64807 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 literal 0 HcmV?d00001 diff --git a/docs/images/src/advanced-routing.mermaid b/docs/images/src/advanced-routing.mermaid new file mode 100644 index 0000000000..e17679cc9a --- /dev/null +++ b/docs/images/src/advanced-routing.mermaid @@ -0,0 +1,38 @@ +%% mermaid source for advanced-routing.png diagram +graph LR + users[Users] + nkgSvc["Public Endpoint\nfor\ncafe.example.com"] + subgraph cluster [Kubernetes Cluster] + subgraph clusterPadding [" "] + subgraph clusterPadding2 [" "] + subgraph gwNS [Namespace\nnginx-gateway] + nkgPod[Pod\nnginx-gateway] + end + end + end + subgraph appNs [Namespace\ndefault] + subgraph nsPadding [" "] + coffeeV1Pod[Pod\ncoffee v1] + coffeeV2Pod[Pod\ncoffee v2] + teaPod[Pod\ntea] + teaPostPod[Pod\ntea-post] + end + end + end + nkgSvc --> nkgPod + nkgPod --/coffee--> coffeeV1Pod + nkgPod --/coffee\nheader: version=v2\nOR\n/coffee?TEST=v2--> coffeeV2Pod + nkgPod --GET /tea--> teaPod + nkgPod --POST /tea--> teaPostPod + users --> nkgSvc + class clusterPadding,nsPadding,clusterPadding2 noBorder + class gwNS,appNs namespace + class nkgSvc,nkgPod nginxNode + class coffeeV1Pod,coffeeV2Pod coffeeNode + class teaPod,teaPostPod teaNode + classDef noBorder stroke:none,fill:none + classDef default fill:#FFFFFF,stroke:#000000 + classDef namespace fill:#FFFFFF,stroke:#036ffc,stroke-dasharray: 5 5,text-align:center + classDef nginxNode fill:#b4e0ad,stroke:#2AA317 + classDef coffeeNode fill:#edbd8c,stroke:#D9822B + classDef teaNode fill:#ff8f6a,stroke:#e5805f diff --git a/docs/installation.md b/docs/installation.md index 11f540bfd7..dd2b1d3561 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -114,10 +114,6 @@ Create a Service with type `LoadBalancer` using the appropriate manifest for you nslookup ``` -### Use NGINX Kubernetes Gateway - -To get started, follow the tutorials in the [examples](../examples) directory. - ## Uninstalling NGINX Kubernetes Gateway ### Uninstall NGINX Kubernetes Gateway from Manifests diff --git a/docs/release-process.md b/docs/release-process.md index 49c61f6312..2792e45f11 100644 --- a/docs/release-process.md +++ b/docs/release-process.md @@ -44,8 +44,9 @@ To create a new release, follow these steps: file. 6. Generate the installation manifests by running `make generate-manifests`. 7. Modify any `git clone` instructions to use `vX.Y.Z` tag. - 8. Update the [README](../README.md) to include information about the release. - 9. Update the [changelog](../CHANGELOG.md). The changelog includes only important (from the user perspective) + 8. Modify any docs links that refer to `main` to instead refer to `vX.Y.Z`. + 9. Update the [README](../README.md) to include information about the release. + 10. Update the [changelog](../CHANGELOG.md). The changelog includes only important (from the user perspective) changes to NKG. This is in contrast with the autogenerated full changelog, which is created in the next step. As a starting point, copy the important features, bug fixes, and dependencies from the autogenerated draft of the full changelog. This draft can be found under diff --git a/examples/advanced-routing/README.md b/examples/advanced-routing/README.md index 0dd76a39c1..1f7dc0a9b3 100644 --- a/examples/advanced-routing/README.md +++ b/examples/advanced-routing/README.md @@ -1,154 +1,3 @@ # Advanced Routing -In this example we will deploy NGINX Kubernetes Gateway and configure advanced routing rules for a simple cafe -application. We will use HTTPRoute resources to route traffic to the cafe application based on a combination of the -request method, headers, and query parameters. - -The cafe application consists of four Services: `coffee-v1-svc`, `coffee-v2-svc`, `tea-svc`, and `tea-post-svc`. In the -next section we will create the following routing rules for the cafe application: - -- For the path `/coffee` route requests with the header `version` set to `v2` or with the query param `TEST` set to `v2` - to `coffee-v2-svc`, and all other requests to `coffee-v1-svc`. -- For the path `/tea` route POST requests to `tea-post-svc`, and all other requests, such as `GET` requests, - to `tea-svc`. - -## Running the Example - -## 1. Deploy NGINX Kubernetes Gateway - -1. Follow the [installation instructions](/docs/installation.md) to deploy NGINX Kubernetes Gateway. - -1. Save the public IP address of NGINX Kubernetes Gateway into a shell variable: - - ```text - GW_IP=XXX.YYY.ZZZ.III - ``` - -1. Save the port of NGINX Kubernetes Gateway: - - ```text - GW_PORT= - ``` - -## 2. Deploy the Cafe Application - -1. Create the coffee and the tea Deployments and Services: - - ```shell - kubectl apply -f cafe.yaml - ``` - -1. Check that the Pods are running in the `default` Namespace: - - ```shell - kubectl -n default get pods - ``` - - ```text - NAME READY STATUS RESTARTS AGE - coffee-v1-75869cf7ff-vlfpq 1/1 Running 0 17m - coffee-v2-67499ff985-2k6cc 1/1 Running 0 17m - tea-6fb46d899f-hjzwr 1/1 Running 0 17m - tea-post-648dfcdd6c-2rlqb 1/1 Running 0 17m - ``` - -## 3. Configure Routing - -1. Create the Gateway: - - ```shell - kubectl apply -f gateway.yaml - ``` - -1. Create the HTTPRoute resources: - - ```shell - kubectl apply -f cafe-routes.yaml - ``` - -## 4. Test the Application - -We will use `curl` to send requests to the `/coffee` and `/tea` endpoints of the cafe application. - -### 4.1 Access coffee - -Send a request with the header `version:v2` and confirm that the response comes from `coffee-v2-svc`: - -```shell -curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/coffee -H "version:v2" -``` - -```text -Server address: 10.116.2.67:8080 -Server name: coffee-v2-67499ff985-gw6vt -... -``` - -Send a request with the query parameter `TEST=v2` and confirm that the response comes from `coffee-v2-svc`: - -```shell -curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/coffee?TEST=v2 -``` - -```text -Server address: 10.116.2.67:8080 -Server name: coffee-v2-67499ff985-gw6vt -... -``` - -Send a request without the header or the query parameter and confirm the response comes from `coffee-v1-svc`: - -```shell -curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/coffee -``` - -```text -Server address: 10.116.2.70:8080 -Server name: coffee-v1-75869cf7ff-vlfpq -... -``` - -### 4.2 Access tea - -Send a POST request and confirm that the response comes from `tea-post-svc`: - -```shell -curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/tea -X POST -``` - -```text -Server address: 10.116.2.72:8080 -Server name: tea-post-648dfcdd6c-2rlqb -... -``` - -Send a GET request and confirm that the response comes from `tea-svc`: - -```shell -curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/tea -``` - -```text -Server address: 10.116.3.30:8080 -Server name: tea-6fb46d899f-hjzwr -... -``` - -The `/tea` endpoint has routing rules configured for GET and POST requests. If you send a request with a different -method, NGINX Kubernetes Gateway will return a 404. - -Send a PUT request and confirm the 404 Not Found response: - -```shell -curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/tea -X PUT -``` - -```text - -404 Not Found - -

404 Not Found

-
nginx/1.21.3
- - -``` +This directory contains the YAML files used in the [Advanced Routing](/docs/guides/advanced-routing.md) guide. diff --git a/examples/advanced-routing/cafe-routes.yaml b/examples/advanced-routing/cafe-routes.yaml index accdaa0072..6cc3039f99 100644 --- a/examples/advanced-routing/cafe-routes.yaml +++ b/examples/advanced-routing/cafe-routes.yaml @@ -4,9 +4,9 @@ metadata: name: coffee spec: parentRefs: - - name: gateway + - name: cafe hostnames: - - "cafe.example.com" + - cafe.example.com rules: - matches: - path: @@ -38,9 +38,9 @@ metadata: name: tea spec: parentRefs: - - name: gateway + - name: cafe hostnames: - - "cafe.example.com" + - cafe.example.com rules: - matches: - path: diff --git a/examples/advanced-routing/cafe.yaml b/examples/advanced-routing/coffee.yaml similarity index 50% rename from examples/advanced-routing/cafe.yaml rename to examples/advanced-routing/coffee.yaml index 40236b7138..2f94d7b801 100644 --- a/examples/advanced-routing/cafe.yaml +++ b/examples/advanced-routing/coffee.yaml @@ -63,69 +63,3 @@ spec: name: http selector: app: coffee-v2 ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: tea-post -spec: - replicas: 1 - selector: - matchLabels: - app: tea-post - template: - metadata: - labels: - app: tea-post - spec: - containers: - - name: tea-post - image: nginxdemos/nginx-hello:plain-text - ports: - - containerPort: 8080 ---- -apiVersion: v1 -kind: Service -metadata: - name: tea-post-svc -spec: - ports: - - port: 80 - targetPort: 8080 - protocol: TCP - name: http - selector: - app: tea-post ---- -apiVersion: apps/v1 -kind: Deployment -metadata: - name: tea -spec: - replicas: 1 - selector: - matchLabels: - app: tea - template: - metadata: - labels: - app: tea - spec: - containers: - - name: tea - image: nginxdemos/nginx-hello:plain-text - ports: - - containerPort: 8080 ---- -apiVersion: v1 -kind: Service -metadata: - name: tea-svc -spec: - ports: - - port: 80 - targetPort: 8080 - protocol: TCP - name: http - selector: - app: tea diff --git a/examples/advanced-routing/gateway.yaml b/examples/advanced-routing/gateway.yaml index 03566e3f99..1d029ef08a 100644 --- a/examples/advanced-routing/gateway.yaml +++ b/examples/advanced-routing/gateway.yaml @@ -1,7 +1,7 @@ apiVersion: gateway.networking.k8s.io/v1beta1 kind: Gateway metadata: - name: gateway + name: cafe spec: gatewayClassName: nginx listeners: diff --git a/examples/advanced-routing/tea.yaml b/examples/advanced-routing/tea.yaml new file mode 100644 index 0000000000..56183d4a43 --- /dev/null +++ b/examples/advanced-routing/tea.yaml @@ -0,0 +1,65 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tea-post +spec: + replicas: 1 + selector: + matchLabels: + app: tea-post + template: + metadata: + labels: + app: tea-post + spec: + containers: + - name: tea-post + image: nginxdemos/nginx-hello:plain-text + ports: + - containerPort: 8080 +--- +apiVersion: v1 +kind: Service +metadata: + name: tea-post-svc +spec: + ports: + - port: 80 + targetPort: 8080 + protocol: TCP + name: http + selector: + app: tea-post +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: tea +spec: + replicas: 1 + selector: + matchLabels: + app: tea + template: + metadata: + labels: + app: tea + spec: + containers: + - name: tea + image: nginxdemos/nginx-hello:plain-text + ports: + - containerPort: 8080 +--- +apiVersion: v1 +kind: Service +metadata: + name: tea-svc +spec: + ports: + - port: 80 + targetPort: 8080 + protocol: TCP + name: http + selector: + app: tea