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 0000000000..9be8d7c509 Binary files /dev/null and b/docs/images/advanced-routing.png differ 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