Skip to content

Commit f71b6a0

Browse files
authored
Add advanced routing guide (#993)
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.
1 parent 1fafb5e commit f71b6a0

11 files changed

+473
-229
lines changed

docs/guides/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ This directory contains guides for configuring NGINX Kubernetes Gateway for vari
66

77
- [Routing Traffic to Your Application](routing-traffic-to-your-app.md): How to use NGINX Kubernetes Gateway to route
88
all Ingress traffic to your Kubernetes application.
9+
- [Routing to Applications Using HTTP Matching Conditions](advanced-routing.md): Guide on how to deploy multiple
10+
applications and HTTPRoutes with request conditions such as paths, methods, headers, and query parameters.
911
- [Securing Traffic using Let's Encrypt and Cert-Manager](integrating-cert-manager.md): Shows how to secure
1012
traffic from clients to NGINX Kubernetes Gateway with TLS using Let's Encrypt and Cert-Manager.
1113
- [Using NGINX Kubernetes Gateway to Upgrade Applications without Downtime](upgrade-apps-without-downtime.md):

docs/guides/advanced-routing.md

Lines changed: 359 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,359 @@
1+
# Routing to Applications Using HTTP Matching Conditions
2+
3+
In this guide we will configure advanced routing rules for multiple applications. These rules will showcase request
4+
matching by path, headers, query parameters, and method. For an introduction to exposing your application, it is
5+
recommended to go through the [basic guide](/docs/guides/routing-traffic-to-your-app.md) first.
6+
7+
The following image shows the traffic flow that we will be creating with these rules.
8+
9+
![Traffic Flow Diagram](/docs/images/advanced-routing.png)
10+
11+
The goal is to create a set of rules that will result in client requests being sent to specific backends based on
12+
the request attributes. In this diagram, we have two versions of the `coffee` service. Traffic for v1 needs to be
13+
directed to the old application, while traffic for v2 needs to be directed towards the new application. We also
14+
have two `tea` services, one that handles GET operations and one that handles POST operations. Both the `tea`
15+
and `coffee` applications share the same Gateway.
16+
17+
## Prerequisites
18+
19+
- [Install](/docs/installation.md) NGINX Kubernetes Gateway.
20+
- [Expose NGINX Kubernetes Gateway](/docs/installation.md#expose-nginx-kubernetes-gateway) and save the public IP
21+
address and port of NGINX Kubernetes Gateway into shell variables:
22+
23+
```text
24+
GW_IP=XXX.YYY.ZZZ.III
25+
GW_PORT=<port number>
26+
```
27+
28+
> **Note**
29+
> In a production environment, you should have a DNS record for the external IP address that is exposed,
30+
> and it should refer to the hostname that the gateway will forward for.
31+
32+
## Coffee Applications
33+
34+
### Deploy the Coffee Applications
35+
36+
Begin by deploying the `coffee-v1` and `coffee-v2` applications:
37+
38+
```shell
39+
kubectl apply -f https://raw.githubusercontent.com/nginxinc/nginx-kubernetes-gateway/main/examples/advanced-routing/coffee.yaml
40+
```
41+
42+
### Deploy the Gateway API Resources for the Coffee Applications
43+
44+
The [Gateway](https://gateway-api.sigs.k8s.io/api-types/gateway/) resource is typically deployed by the
45+
[cluster operator][roles-and-personas]. To deploy the Gateway:
46+
47+
```yaml
48+
kubectl apply -f - <<EOF
49+
apiVersion: gateway.networking.k8s.io/v1beta1
50+
kind: Gateway
51+
metadata:
52+
name: cafe
53+
spec:
54+
gatewayClassName: nginx
55+
listeners:
56+
- name: http
57+
port: 80
58+
protocol: HTTP
59+
EOF
60+
```
61+
62+
This Gateway defines a single listener on port 80. Since no hostname is specified, this listener matches on all hostnames.
63+
64+
The [HTTPRoute](https://gateway-api.sigs.k8s.io/api-types/httproute/) is typically deployed by the
65+
[application developer][roles-and-personas]. To deploy the `coffee` HTTPRoute:
66+
67+
```yaml
68+
kubectl apply -f - <<EOF
69+
apiVersion: gateway.networking.k8s.io/v1beta1
70+
kind: HTTPRoute
71+
metadata:
72+
name: coffee
73+
spec:
74+
parentRefs:
75+
- name: cafe
76+
sectionName: http
77+
hostnames:
78+
- cafe.example.com
79+
rules:
80+
- matches:
81+
- path:
82+
type: PathPrefix
83+
value: /coffee
84+
backendRefs:
85+
- name: coffee-v1-svc
86+
port: 80
87+
- matches:
88+
- path:
89+
type: PathPrefix
90+
value: /coffee
91+
headers:
92+
- name: version
93+
value: v2
94+
- path:
95+
type: PathPrefix
96+
value: /coffee
97+
queryParams:
98+
- name: TEST
99+
value: v2
100+
backendRefs:
101+
- name: coffee-v2-svc
102+
port: 80
103+
EOF
104+
```
105+
106+
This HTTPRoute has a few important properties:
107+
108+
- The `parentRefs` references the Gateway resource that we created, and specifically defines the `http` listener
109+
to attach to, via the `sectionName` field.
110+
- `cafe.example.com` is the hostname that is matched for all requests to the backends defined in this HTTPRoute.
111+
- The first rule defines that all requests with the path prefix `/coffee` and no other matching conditions are sent
112+
to the `coffee-v1` Service.
113+
- The second rule defines two matching conditions. If *either* of these conditions match, requests are forwarded to
114+
the `coffee-v2` Service:
115+
- Request with the path prefix `/coffee` and header `version=v2`
116+
- Request with the path prefix `/coffee` and the query parameter `TEST=v2`
117+
If you want both conditions to be required, you can define headers and queryParams in the same match object.
118+
119+
[roles-and-personas]: https://gateway-api.sigs.k8s.io/concepts/roles-and-personas/#roles-and-personas_1
120+
121+
### Send Traffic to Coffee
122+
123+
Using the external IP address and port for NGINX Kubernetes Gateway, we can send traffic to our coffee
124+
applications.
125+
126+
> **Note**
127+
> If you have a DNS record allocated for `cafe.example.com`, you can send the request directly to that
128+
> hostname, without needing to resolve.
129+
130+
```shell
131+
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/coffee
132+
```
133+
134+
This request should receive a response from the `coffee-v1` Pod.
135+
136+
```text
137+
Server address: 10.244.0.9:8080
138+
Server name: coffee-v2-68bd55f798-s9z5q
139+
```
140+
141+
If we want our request to be routed to `coffee-v2`, then we need to meet the defined conditions. We can include
142+
a header:
143+
144+
```shell
145+
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/coffee -H "version:v2"
146+
```
147+
148+
or include a query parameter:
149+
150+
```shell
151+
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/coffee?TEST=v2
152+
```
153+
154+
Either request should result in a response from the `coffee-v2` Pod.
155+
156+
```text
157+
Server address: 10.244.0.9:8080
158+
Server name: coffee-v2-68bd55f798-s9z5q
159+
```
160+
161+
## Tea Applications
162+
163+
Let's deploy a different set of applications now called `tea` and `tea-post`. These applications will
164+
have their own set of rules, but will still attach to the same Gateway listener as the `coffee` apps.
165+
166+
### Deploy the Tea Applications
167+
168+
```shell
169+
kubectl apply -f https://raw.githubusercontent.com/nginxinc/nginx-kubernetes-gateway/main/examples/advanced-routing/tea.yaml
170+
```
171+
172+
### Deploy the HTTPRoute for the Tea Services
173+
174+
We are reusing the previous Gateway for these applications, so all we need to create is the HTTPRoute.
175+
176+
```yaml
177+
kubectl apply -f - <<EOF
178+
apiVersion: gateway.networking.k8s.io/v1beta1
179+
kind: HTTPRoute
180+
metadata:
181+
name: tea
182+
spec:
183+
parentRefs:
184+
- name: cafe
185+
hostnames:
186+
- cafe.example.com
187+
rules:
188+
- matches:
189+
- path:
190+
type: PathPrefix
191+
value: /tea
192+
method: POST
193+
backendRefs:
194+
- name: tea-post-svc
195+
port: 80
196+
- matches:
197+
- path:
198+
type: PathPrefix
199+
value: /tea
200+
method: GET
201+
backendRefs:
202+
- name: tea-svc
203+
port: 80
204+
EOF
205+
```
206+
207+
The properties of this HTTPRoute include:
208+
209+
- The same Gateway is referenced as before.
210+
- The same hostname is used as with the `coffee` apps.
211+
- The first rule defines that a POST request to the `/tea` path is routed to the `tea-post` Service.
212+
- The second rule defines that a GET request to the `/tea` path is routed to the `tea` Service.
213+
214+
### Send Traffic to Tea
215+
216+
Using the external IP address and port for NGINX Kubernetes Gateway, we can send traffic to our tea
217+
applications.
218+
219+
> **Note**
220+
> If you have a DNS record allocated for `cafe.example.com`, you can send the request directly to that
221+
> hostname, without needing to resolve.
222+
223+
```shell
224+
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/tea
225+
```
226+
227+
This GET request should receive a response from the `tea` Pod.
228+
229+
```text
230+
Server address: 10.244.0.10:8080
231+
Server name: tea-df5655878-5fmfg
232+
```
233+
234+
If we want our request to be routed to `tea-post`, then we need to send a POST request:
235+
236+
```shell
237+
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/tea -X POST
238+
```
239+
240+
```text
241+
Server address: 10.244.0.7:8080
242+
Server name: tea-post-b59b8596b-g586r
243+
```
244+
245+
This request should receive a response from the `tea-post` Pod. Any other type of method, such as PATCH, will
246+
result in a `404 Not Found` response.
247+
248+
249+
## Troubleshooting
250+
251+
If you have any issues while sending traffic, try the following to debug your configuration and setup:
252+
253+
- Make sure you set the shell variables $GW_IP and $GW_PORT to the public IP and port of the NGINX Kubernetes Gateway
254+
Service. Instructions for finding those values are [here](/docs/installation.md#expose-nginx-kubernetes-gateway).
255+
256+
- Check the status of the Gateway:
257+
258+
```shell
259+
kubectl describe gateway cafe
260+
```
261+
262+
The Gateway status should look like this:
263+
264+
```text
265+
Status:
266+
Addresses:
267+
Type: IPAddress
268+
Value: 10.244.0.85
269+
Conditions:
270+
Last Transition Time: 2023-08-15T20:57:21Z
271+
Message: Gateway is accepted
272+
Observed Generation: 1
273+
Reason: Accepted
274+
Status: True
275+
Type: Accepted
276+
Last Transition Time: 2023-08-15T20:57:21Z
277+
Message: Gateway is programmed
278+
Observed Generation: 1
279+
Reason: Programmed
280+
Status: True
281+
Type: Programmed
282+
Listeners:
283+
Attached Routes: 2
284+
Conditions:
285+
Last Transition Time: 2023-08-15T20:57:21Z
286+
Message: Listener is accepted
287+
Observed Generation: 1
288+
Reason: Accepted
289+
Status: True
290+
Type: Accepted
291+
Last Transition Time: 2023-08-15T20:57:21Z
292+
Message: Listener is programmed
293+
Observed Generation: 1
294+
Reason: Programmed
295+
Status: True
296+
Type: Programmed
297+
Last Transition Time: 2023-08-15T20:57:21Z
298+
Message: All references are resolved
299+
Observed Generation: 1
300+
Reason: ResolvedRefs
301+
Status: True
302+
Type: ResolvedRefs
303+
Last Transition Time: 2023-08-15T20:57:21Z
304+
Message: No conflicts
305+
Observed Generation: 1
306+
Reason: NoConflicts
307+
Status: False
308+
Type: Conflicted
309+
Name: http
310+
```
311+
312+
Check that the conditions match and that the attached routes for the `http` listener equals 2. If it is less than
313+
2, there may be an issue with the routes.
314+
315+
- Check the status of the HTTPRoutes:
316+
317+
```shell
318+
kubectl describe httproute coffee
319+
```
320+
321+
```shell
322+
kubectl describe httproute tea
323+
```
324+
325+
Each HTTPRoute status should look like this:
326+
327+
```text
328+
Status:
329+
Parents:
330+
Conditions:
331+
Last Transition Time: 2023-08-15T20:57:21Z
332+
Message: The route is accepted
333+
Observed Generation: 1
334+
Reason: Accepted
335+
Status: True
336+
Type: Accepted
337+
Last Transition Time: 2023-08-15T20:57:21Z
338+
Message: All references are resolved
339+
Observed Generation: 1
340+
Reason: ResolvedRefs
341+
Status: True
342+
Type: ResolvedRefs
343+
Controller Name: gateway.nginx.org/nginx-gateway-controller
344+
Parent Ref:
345+
Group: gateway.networking.k8s.io
346+
Kind: Gateway
347+
Name: cafe
348+
Namespace: default
349+
```
350+
351+
Check for any error messages in the conditions.
352+
353+
## Further Reading
354+
355+
To learn more about the Gateway API and the resources we created in this guide, check out the following resources:
356+
357+
- [Gateway API Overview](https://gateway-api.sigs.k8s.io/concepts/api-overview/)
358+
- [Deploying a simple Gateway](https://gateway-api.sigs.k8s.io/guides/simple-gateway/)
359+
- [HTTP Routing](https://gateway-api.sigs.k8s.io/guides/http-routing/)

docs/images/advanced-routing.png

63.3 KB
Loading

0 commit comments

Comments
 (0)