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 all 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.

284 changes: 284 additions & 0 deletions docs/content/tutorials/nginx-ingress-istio.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,284 @@
---
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"
---

## Using NGINX Ingress Controller with Istio service mesh

NGINX Ingress Controller can now be used as the ingress controller for applications running inside an Istio service mesh. This allows you to continue using the advanced capabilities that NGINX IC provides on Istio-based environments without resorting to any workarounds.
This is accomplished using the special setting [use-cluster-ip](https://docs.nginx.com/nginx-ingress-controller/configuration/virtualserver-and-virtualserverroute-resources/#upstream) for the backend.


Here is a standard deployment of NGINX Ingress Controller without a sidecar proxy injected into the pod.

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

Notice that NGINX Ingress Controller enumerates the pods of the backend service and balances traffic directly to them, granting full control of the backend load balancer and stickiness behavior.
If your service pods support TLS, then NIC can re-encrypt the traffic to them and provide end-to-end encryption.

But then, if your services could do that, you might not be implementing a Service Mesh.


To begin, Istio needs to be installed into your cluster.
jasonwilliams14 marked this conversation as resolved.
Show resolved Hide resolved

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

Link to Istio install guide:
[Installing istio](https://istio.io/latest/docs/setup/install/)

It is crucial to make sure you install Istio **BEFORE** installing NGINX Ingress Controller. This ensures that the Istio sidecar is injected correctly into the NGINX Ingress controller pod.

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

```
jasonwilliams14 marked this conversation as resolved.
Show resolved Hide resolved
istioctl install --set profile=minimal
```

We need to ensure that Istio injects sidecar proxies into our namespace for testing. To do so, we need to tell Istio what namespaces to inject sidecars into. We can do that with the following command:

```bash

kubectl label ns <namespace_specified> istio-injection=enabled
```
jasonwilliams14 marked this conversation as resolved.
Show resolved Hide resolved
Before proceeding, and before installing NGINX Ingress Controller you need to tell Istio that it will be injecting sidecars with the NGINX Ingress controller pods as they are deployed.

```bash

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:

```bash

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 set up and configured Istio, we can deploy NGINX Plus Ingress and 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).

The image below shows how an NGINX Ingress Controller and Istio deployment looks:

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


## Install NGINX Ingress Controller

Once Istio is installed, you can install NGINX Ingress Controller.


## Setting up NGINX Plus Ingress controller deployment for Istio.

When deploying NGINX Plus Ingress Controller with Istio, you must modify your Deployment file to include the specific annotations required 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 Istio's website.
[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'
```


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


We can now see that after configuring Istio, an Istio sidecar proxy has been installed into the same pod as NGINX Ingress Controller. Now, there are two containers in the same pod for NGINX Ingress Controller: the NGINX Ingress controller container and 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
```

Here is our VirtualServer configuration for Istio service mesh (note `use-cluster-ip` and `requestHeaders`). These settings are required when using Istio service mesh:


```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.
The value of `requestHeaders` should be: `<service.namespace.svc.cluster.local>`. Adjust the value for your specific environment.


When `use-cluster-ip` is set to `true`, NGINX forwards requests to the service IP. In our example above, that would be `tea-svc` and `coffee-svc`.

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
```

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.


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 that our curl request is sent and received by NGINX Ingress Controller. We can see that the envoy sidecar proxy sends the request to the service IP to the application (coffee). The full request is complete and correct. Now we have a full working NGINX+ Ingress with Istio as the sidecar proxies are deployed.



## Additional Technical information details

By default, for NGINX Ingress Controller, we populate the upstream server addresses with the endpoint IPs of the pods.

When using the new `use-cluster-ip` feature, we will no populate the upstream with the `service` IP address, instead of the endpoint IP addresses.
travisamartin marked this conversation as resolved.
Show resolved Hide resolved

In the 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 `action.proxy.requestHeaders` this ensures that only one set of headers will be sent to the upstream server. In summary, by setting `action.proxy.requestHeaders` in the `VirtualServer` CRD, NGINX Ingress will only send the specified headers that have been defined.



Here is the output of `nginx -T` to show our upstreams and proxy_set_header values.
travisamartin marked this conversation as resolved.
Show resolved Hide resolved
The server IP address the upstream is the IP address of the service for that given application.
jasonwilliams14 marked this conversation as resolved.
Show resolved Hide resolved


```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";
}
}
```

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.