Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

NGINX Ingress with Istio Service Mesh document #2768

Merged
merged 25 commits into from
Aug 4, 2022
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
8c122a8
adding tutorial for KIC and Istio
jasonwilliams14 Jun 14, 2022
f2f4235
Fixed images for NGINX Ingress and Istio
jasonwilliams14 Jun 14, 2022
c10e008
removed backup file
jasonwilliams14 Jun 14, 2022
e6244d3
Added suggested changes to document
jasonwilliams14 Jun 15, 2022
34cbd67
Updated Ingress + Istio doc per changes for review
jasonwilliams14 Jun 22, 2022
219b018
small changes to review
jasonwilliams14 Jun 23, 2022
b21491e
small changes to review second
jasonwilliams14 Jun 23, 2022
383143f
small change to doc for review
jasonwilliams14 Jun 30, 2022
4e8ae43
minor updates to doc
jasonwilliams14 Jul 1, 2022
1feacd2
final revision
jasonwilliams14 Jul 6, 2022
8481883
Final revision updated for blog
jasonwilliams14 Jul 11, 2022
bed10f7
Apply suggestions from code review
jasonwilliams14 Jul 12, 2022
5165a52
Update docs/content/tutorials/nginx-ingress-istio.md
jasonwilliams14 Jul 21, 2022
5010df7
Update docs/content/tutorials/nginx-ingress-istio.md
jasonwilliams14 Jul 21, 2022
f1380f8
Update docs/content/tutorials/nginx-ingress-istio.md
jasonwilliams14 Jul 21, 2022
7c42a61
Update docs/content/tutorials/nginx-ingress-istio.md
jasonwilliams14 Jul 21, 2022
9dc2d17
Update docs/content/tutorials/nginx-ingress-istio.md
jasonwilliams14 Jul 21, 2022
dc23046
Update docs/content/tutorials/nginx-ingress-istio.md
jasonwilliams14 Jul 21, 2022
aeb81e5
Update docs/content/tutorials/nginx-ingress-istio.md
jasonwilliams14 Jul 21, 2022
05b4822
Update docs/content/tutorials/nginx-ingress-istio.md
jasonwilliams14 Jul 21, 2022
dd3dd75
Update docs/content/tutorials/nginx-ingress-istio.md
jasonwilliams14 Jul 21, 2022
d5e3eac
Update nginx-ingress-istio.md
jasonwilliams14 Jul 21, 2022
fe8b5c9
Update docs/content/tutorials/nginx-ingress-istio.md
jasonwilliams14 Jul 26, 2022
5bba982
Update docs/content/tutorials/nginx-ingress-istio.md
jasonwilliams14 Jul 26, 2022
feb635a
Merge branch 'main' into tutorials-2.2
lucacome Aug 4, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/content/tutorials/_index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
title: Tutorials
description:
weight: 2100
menu:
docs:
parent: NGINX Ingress Controller
---
9 changes: 0 additions & 9 deletions docs/content/tutorials/index.md

This file was deleted.

290 changes: 290 additions & 0 deletions docs/content/tutorials/nginx-ingress-istio.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,290 @@
---
title: NGINX Ingress Controller and Istio Service Mesh
description: |
Use NGINX Ingress Controller with Istio Service Mesh.
weight: 1800
doctypes: ["concept"]
toc: true
docs: "DOCS-889"
---

You can use NGINX Ingress Controller fpr applications that are running inside an Istio service mesh. This allows to continue using the advanced capabilities that NGINX Ingress Controleler in a istio service mesh environments without resorting to any workarounds.
jasonwilliams14 marked this conversation as resolved.
Show resolved Hide resolved


Prior to 1.11 release, a configuration below would send two host headers to the backend;
jasonwilliams14 marked this conversation as resolved.
Show resolved Hide resolved

```yaml
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: foo
spec:
host: foo.example.com
upstreams:
- name: foo
port: 8080
service: backend-svc
routes:
- path: "/"
action:
proxy:
upstream: foo
requestHeaders:
set:
- name: Host
value: bar.example.com
```

In 1.11 release, NGINX Ingress controller will only send one host header, depending on how you configure Ingress. By default NGINX Ingress Controller will send `proxy_set_header $host`. If Ingress has been configured with `requestHeaders` per the above example, this ensures that only one set of headers will be sent to the upstream server. In short, by setting `action-proxy-requestHeaders` in the `VirtualServer` CRD, NGINX Ingress will only send the specified hears that have been defined.
jasonwilliams14 marked this conversation as resolved.
Show resolved Hide resolved

Here is a standard deployment of NGINX Ingress controller without any service mesh deployed:
jasonwilliams14 marked this conversation as resolved.
Show resolved Hide resolved

{{< img src="./img/nginx_plain.png" alt="NGINX stand alone." >}}


When deploying NGINX Ingress controller with Istio, you must deploy the envoy sidecar proxy into the NGINX Ingress controller pod.
The image below is what NGINX Ingress and Istio deployment looks like:

{{< img src="./img/nginx-envoy.png" alt="NGINX with envoy sidecar." >}}


By default for NGINX Ingress Controller, we populate the upstream server addresses with the endpoint IPs of the pods. NGINX Ingress Controller 1.11 release now supports the ability to configure NGINX Ingress CRDs (virtualServer/virtualServerRoute)to use the `service/cluster IP`. Using this flag, NGINX Ingress will generate the .conf with the `service/cluster IP` of the service in the `upstreams/servers` section, instead of pod endpoint IPs of the pods.
jasonwilliams14 marked this conversation as resolved.
Show resolved Hide resolved

To enable NGINX Ingress to route to the `Service IP`, we are going to use a new feature released in 1.11; [use-cluster-ip](https://docs.nginx.com/nginx-ingress-controller/configuration/virtualserver-and-virtualserverroute-resources/#upstream).
jasonwilliams14 marked this conversation as resolved.
Show resolved Hide resolved

Here is a simple example of what your `upstream` section will look like now in `virtualServer/virtualServerRoute`:

```yaml
upstreams:
- name: tea
service: tea-svc
port: 80
use-cluster-ip: true
- name: coffee
service: coffee-svc
port: 80
use-cluster-ip: true
```

Now NGINX Ingress `upstreams` will be populated with the `Service/cluster IP`. In the example above, the service/cluster IPs for `tea-svc` and `coffee-svc` will be added to the `upstream` configuration as the `server` addresses.

## Setting up NGINX Plus Ingress controller for Istio.

When deploying NGINX Plus Ingress Controller with Istio, you will need to modify your Depoloyment file to include the specific items needed to work with Istio. Those four specific lines are:

```yaml
traffic.sidecar.istio.io/includeInboundPorts: ""
traffic.sidecar.istio.io/excludeInboundPorts: "80,443"
traffic.sidecar.istio.io/excludeOutboundIPRanges: "substitute_for_correct_subnet_range"
sidecar.istio.io/inject: 'true'
```

Additional information on the above annotations can be found on Istios website.
jasonwilliams14 marked this conversation as resolved.
Show resolved Hide resolved
[Istio Service Mesh Annotations](https://istio.io/latest/docs/reference/config/annotations/)


Your updated nginx-plus-ingress.yaml file will look something like this with the added annotations:

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-ingress
namespace: nginx-ingress
spec:
replicas: 1
selector:
matchLabels:
app: nginx-ingress
template:
metadata:
labels:
app: nginx-ingress
annotations:
traffic.sidecar.istio.io/includeInboundPorts: ""
traffic.sidecar.istio.io/excludeInboundPorts: "80,443"
traffic.sidecar.istio.io/excludeOutboundIPRanges: "10.90.0.0/16,10.45.0.0/16"
sidecar.istio.io/inject: 'true'
```

## Install Istio
jasonwilliams14 marked this conversation as resolved.
Show resolved Hide resolved

Link to Istio install guide:
jasonwilliams14 marked this conversation as resolved.
Show resolved Hide resolved
[Installing istio](https://istio.io/latest/docs/setup/install/)

You can then install Istio by your preferred method (helm, operator etc.). Deploy Istio into your cluster. In this case, I ran the following command to install Istio into my cluster:

```
istioctl install --set profile=minimal
```

We need to make sure that Istio injects sidecar proxies into our namespace for our testing. To do so, we need to tell Istio what namespaces to inject sidecars into. We can do that with the following command:
```
kubectl label ns <namespace_specified> istio-injection=enabled
```
Since we installed NGINX ingress and my application into the same namespace as our test application, I specified nginx-ingress with the istio-injection=enabled label on that namespace.

```
kubectl label namespace nginx-ingress istio-injection=enabled
```


Using kubectl we can see that the namespace for our demo (nginx-ingress) now has istio-injection=enabled specified:

```
kubectl get namespacess -A --show-labels


default Active 28h <none>
istio-system Active 24h istio-injection=disabled
kube-node-lease Active 28h <none>
kube-public Active 28h <none>
kube-system Active 28h <none>
kubernetes-dashboard Active 16h <none>
local-path-storage Active 28h <none>
nginx-ingress Active 27h istio-injection=enabled
```

After we have setup and configured Istio, we can then deploy NGINX Plus Ingress as well as our applications that will be part of the service mesh. Istio will now inject sidecar proxies based upon how we have configured Istio (namespace configuration).
Now, our deployment will look like the following (with Envoy sidecar proxies).


{{< img src="./img/nginx_istio_small.png" alt="NGINX Ingress pod with envoy sidecar." >}}

![nginx-ingress](../../../docs/static/img/nic_istio_small.png)


We can now see that after configuring Istio with the necessary pieces needed to install a sidecar proxy into the same pod as NGINX Ingress Controller. There are now, two containers in the same pod for Nginx Ingress controller: one is NGINX Ingress controller container, the other is the istio sidecar proxy container.

```
kubectl get pods -A

NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-854c77959c-h2vrq 1/1 Running 0 60m
kube-system metrics-server-86cbb8457f-fct86 1/1 Running 0 60m
kube-system local-path-provisioner-5ff76fc89d-5hjbl 1/1 Running 0 60m
istio-system istiod-7c9c9d46d4-qpgff 1/1 Running 0 60m
nginx-ingress nginx-ingress-5898f94c49-v4jrf 2/2 Running 1 41s
```


For our application, we are using two new features released in v1.11. These are avaiable in `VirtualServer/VirtualServeroute`.

Here is our VirtualServer configuration to use with Istio: (note `use-cluster-ip` and `requestHeaders`)

```yaml
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: cafe
namespace: nginx-ingress
spec:
host: cafe.example.com
tls:
secret: cafe-secret
upstreams:
- name: tea
service: tea-svc
port: 80
use-cluster-ip: true
- name: coffee
service: coffee-svc
port: 80
use-cluster-ip: true
routes:
- path: /tea
action:
proxy:
upstream: tea
requestHeaders:
set:
- name: Host
value: tea-svc.nginx-ingress.svc.cluster.local
- path: /coffee
action:
proxy:
upstream: coffee
requestHeaders:
set:
- name: Host
value: coffee-svc.nginx-ingress.svc.cluster.local
```

With our new Host header control in v1.11, when VirtualServer is configured with `requestHeaders`, the value specified will be used and `proxy_set_header $host` will NOT be used. By enabling `use-cluster-ip` to **true**, NGINX will forward requests to the service IP. In our above example, that would be `tea-svc` and `coffee-svc`.

Here is the output of `nginx -T` to show our upstreams and proxy_set_header values
The server in the upstream is the IP address of the service for that given application)

```bash
upstream vs_nginx-ingress_cafe_tea {
zone vs_nginx-ingress_cafe_tea 256k;
random two least_conn;
server 10.96.222.104:80 max_fails=1 fail_timeout=10s max_conns=0;
}

upstream vs_nginx-ingress_cafe_coffee {
zone vs_nginx-ingress_cafe_coffee 256k;
random two least_conn;
server 10.96.252.249:80 max_fails=1 fail_timeout=10s max_conns=0;
}

server {
listen 80;

location /tea {

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $vs_connection_header;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $scheme;

proxy_set_header Host "tea-svc.nginx-ingress.svc.cluster.local";
}

location /coffee {

proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $vs_connection_header;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $scheme;

proxy_set_header Host "coffee-svc.nginx-ingress.svc.cluster.local";
}
}
```

Notice the abscence of `proxy_set_header $host`. This is because we are using `action-proxy-requestHeaders` option to specify what headers we want to pass to Istio sidecar. This is required by Istio.
jasonwilliams14 marked this conversation as resolved.
Show resolved Hide resolved

Now we can test our NGINX Ingress with Istio setup with a simple curl request to our application.

```bash
curl -kI https://cafe.example.com/coffee

HTTP/1.1 200 OK
Server: nginx/1.19.5
Date: Thu, 25 Mar 2021 18:47:21 GMT
Content-Type: text/plain
Content-Length: 159
Connection: keep-alive
expires: Thu, 25 Mar 2021 18:47:20 GMT
cache-control: no-cache
x-envoy-upstream-service-time: 0
x-envoy-decorator-operation: coffee-svc.nginx-ingress.svc.cluster.local:80/*
```

We can see in the above output, our curl request is sent and received by NGINX Ingress. We can see that the envoy sidecar proxy then sends the request to the service IP to the application (coffee), with the full request being complete and correct. Now we have a full working NGINX+ Ingress with Istio as the sidecar proxies are deployed.


For disabling/removing sidecar proxies and autoinjection:


To remove label from the namespace:
```bash
kubectl lable ns default istio-injection-
```
Binary file added docs/static/img/nginx-envoy.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/static/img/nginx_istio_small.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/static/img/nginx_plain.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.