Skip to content

Commit

Permalink
Add ip as an option to listeners for VirtualServer (#6180)
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexFenlon authored Sep 5, 2024
1 parent 75cfc6f commit c1e2906
Show file tree
Hide file tree
Showing 25 changed files with 4,058 additions and 75 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{{ if .Values.controller.globalConfiguration.create }}
apiVersion: k8s.nginx.org/v1alpha1
apiVersion: k8s.nginx.org/v1
kind: GlobalConfiguration
metadata:
name: {{ include "nginx-ingress.controller.fullname" . }}
Expand Down
16 changes: 16 additions & 0 deletions charts/nginx-ingress/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -994,6 +994,22 @@
"examples": [
"dns-tcp"
]
},
"ipv4ip": {
"type": "string",
"default": "",
"title": "The ipv4 ip",
"examples": [
"127.0.0.1"
]
},
"ipv6ip": {
"type": "string",
"default": "",
"title": "The ipv6 ip",
"examples": [
"::1"
]
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions config/crd/bases/k8s.nginx.org_globalconfigurations.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ spec:
items:
description: Listener defines a listener.
properties:
ipv4:
type: string
ipv6:
type: string
name:
type: string
port:
Expand Down
4 changes: 4 additions & 0 deletions deploy/crds.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ spec:
items:
description: Listener defines a listener.
properties:
ipv4:
type: string
ipv6:
type: string
name:
type: string
port:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ The `listeners:` key defines a listener (a combination of a protocol and a port)
| *port* | The port of the listener. The port must fall into the range ``1..65535`` with the following exceptions: ``80``, ``443``, the [status port](/nginx-ingress-controller/logging-and-monitoring/status-page), the [Prometheus metrics port](/nginx-ingress-controller/logging-and-monitoring/prometheus). Among all listeners, only a single combination of a port-protocol is allowed. | *int* | Yes |
| *protocol* | The protocol of the listener. Supported values: ``TCP``, ``UDP`` and ``HTTP``. | *string* | Yes |
| *ssl* | Configures the listener with SSL. This is currently only supported for ``HTTP`` listeners. Default value is ``false`` | *bool* | No |
| *ipv4* | Specifies the IPv4 address to listen on. This is currently only supported for ``HTTP`` or ``HTTPS`` listeners. | *string* | No |
| *ipv6* | Specifies the IPv6 address to listen on. This is currently only supported for ``HTTP`` or ``HTTPS`` listeners. | *string* | No |

{{</bootstrap-table>}}

---
Expand Down Expand Up @@ -173,3 +176,8 @@ Events:
```

The events section includes a Warning event with the AddedOrUpdatedWithError reason.


## Using IPV4 and IPV6 Addresses with GlobalConfiguration

You can customize the IPv4 and IPv6 Address listeners in the global configuration and apply them to your VirtualServer resources. See the corresponding example [here](https://github.com/nginxinc/kubernetes-ingress/tree/v{{< nic-version >}}/examples/custom-resources/custom-ip-listeners/virtualserver/)
237 changes: 237 additions & 0 deletions examples/custom-resources/custom-ip-listeners/virtualserver/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,237 @@
# Custom IPv4 and IPv6 Address Listeners

In this example, we will configure a VirtualServer resource with custom IPv4 and IPv6 Address using HTTP/HTTPS listeners.
This will allow IPv4 and/or IPv6 address using HTTP and/or HTTPS based requests to be made on non-default ports using separate IPs.

## Prerequisites

1. Follow the [installation](https://docs.nginx.com/nginx-ingress-controller/installation/installation-with-manifests/)
instructions to deploy the Ingress Controller with custom resources enabled.
2. Ensure the Ingress Controller is configured with the `-global-configuration` argument:

```console
args:
- -global-configuration=$(POD_NAMESPACE)/nginx-configuration
```

3. If you have a NodePort or Loadbalancer service deployed, ensure they are updated to include the custom listener ports.
Example YAML for a LoadBalancer:

```yaml
apiVersion: v1
kind: Service
metadata:
name: nginx-ingress
namespace: nginx-ingress
spec:
type: LoadBalancer
ports:
- port: 8083
targetPort: 8083
protocol: TCP
name: ip-listener-1-http
- port: 8443
targetPort: 8443
protocol: TCP
name: ip-listener-2-https
selector:
app: nginx-ingress
```
**Note:**
- **No Updates for GC:** If a GlobalConfiguration resource already exists, delete the previous one before applying the new configuration.
- **Single Replica:** Only one replica is allowed when using this configuration.
## Step 1 - Deploy the GlobalConfiguration resource
Similar to how listeners are configured in our [custom-listeners](../../custom-listeners) examples,
here we deploy a GlobalConfiguration resource with the listeners we want to use in our VirtualServer.
```yaml
apiVersion: k8s.nginx.org/v1
kind: GlobalConfiguration
metadata:
name: nginx-configuration
namespace: nginx-ingress
spec:
listeners:
- name: ip-listener-1-http
port: 8083
protocol: HTTP
ipv4: 127.0.0.1
- name: ip-listener-2-https
port: 8443
protocol: HTTP
ipv4: 127.0.0.2
ipv6: ::1
ssl: true
```
```console
kubectl create -f global-configuration.yaml
```

## Step 2 - Deploy the Cafe Application

Create the coffee and the tea deployments and services:

```console
kubectl create -f cafe.yaml
```

## Step 3 - Deploy the VirtualServer with custom listeners

The VirtualServer in this example is set to use the listeners defined in the GlobalConfiguration resource
that was deployed in Step 1. Below is the yaml of this example VirtualServer:

```yaml
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: cafe
spec:
listener:
http: ip-listener-1-http
https: ip-listener-2-https
host: cafe.example.com
tls:
secret: cafe-secret
upstreams:
- name: tea
service: tea-svc
port: 80
- name: coffee
service: coffee-svc
port: 80
routes:
- path: /tea
action:
pass: tea
- path: /coffee
action:
pass: coffee
```
1. Create the secret with the TLS certificate and key:
```console
kubectl create -f cafe-secret.yaml
```

2. Create the VirtualServer resource:

```console
kubectl create -f cafe-virtual-server.yaml
```

## Step 4 - Test the Configuration

1. Check that the configuration has been successfully applied by inspecting the events of the VirtualServer and the GlobalConfiguration:

```console
kubectl describe virtualserver cafe
```

Below you will see the events as well as the new `Listeners` field

```console
. . .
Spec:
Host: cafe.example.com
Listener:
Http: ip-listener-1-http
Https: ip-listener-2-https
. . .
Routes:
. . .
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal AddedOrUpdated 2s nginx-ingress-controller Configuration for default/cafe was added or updated
```

```console
kubectl describe globalconfiguration nginx-configuration -n nginx-ingress
```

```console
. . .
Spec:
Listeners:
ipv4: 127.0.0.1
Name: ip-listener-1-http
Port: 8083
Protocol: HTTP
ipv4: 127.0.0.2
ipv6: ::1
Name: ip-listener-2-https
Port: 8443
Protocol: HTTP
Ssl: true
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Updated 14s nginx-ingress-controller GlobalConfiguration nginx-ingress/nginx-configuration was added or updated
```

2. Since the deployed VirtualServer is using ports `8083` and `8443` in this example. you can see that the specific ips and ports
are set and listening by using the below commands:

Access the NGINX Pod:

```console
kubectl get pods -n nginx-ingress
```

```text
NAME READY STATUS RESTARTS AGE
nginx-ingress-65cd79bb8f-crst4 1/1 Running 0 97s
```

```console
kubectl debug -it nginx-ingress-65cd79bb8f-crst4 --image=busybox:1.28 --target=nginx-ingress
```

```console
/ # netstat -tulpn
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:8080 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.1:8083 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN -
tcp 0 0 127.0.0.2:8443 0.0.0.0:* LISTEN -
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN -
tcp 0 0 :::8081 :::* LISTEN -
tcp 0 0 :::8080 :::* LISTEN -
tcp 0 0 :::8083 :::* LISTEN -
tcp 0 0 ::1:8443 :::* LISTEN -
tcp 0 0 :::443 :::* LISTEN -
tcp 0 0 :::80 :::* LISTEN -
tcp 0 0 :::9113 :::* LISTEN -
```

We can see here that the two IPv4s (`127.0.0.1:8083` and `127.0.0.2:8443`) and the one IPv6 (`::1:8443`) that are set and listening.

3. Examine the NGINX config using the following command:

```console
kubectl exec -it nginx-ingress-65cd79bb8f-crst4 -n nginx-ingress -- cat /etc/nginx/conf.d/vs_default_cafe.conf
```

```console
...
server {
listen 127.0.0.1:8083;
listen [::]:8083;
server_name cafe.example.com;
set $resource_type "virtualserver";
set $resource_name "cafe";
set $resource_namespace "default";
listen 127.0.0.2:8443 ssl;
listen [::1]:8443 ssl;
...
```
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: v1
kind: Secret
metadata:
name: cafe-secret
type: kubernetes.io/tls
data:
tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURMakNDQWhZQ0NRREFPRjl0THNhWFdqQU5CZ2txaGtpRzl3MEJBUXNGQURCYU1Rc3dDUVlEVlFRR0V3SlYKVXpFTE1Ba0dBMVVFQ0F3Q1EwRXhJVEFmQmdOVkJBb01HRWx1ZEdWeWJtVjBJRmRwWkdkcGRITWdVSFI1SUV4MApaREViTUJrR0ExVUVBd3dTWTJGbVpTNWxlR0Z0Y0d4bExtTnZiU0FnTUI0WERURTRNRGt4TWpFMk1UVXpOVm9YCkRUSXpNRGt4TVRFMk1UVXpOVm93V0RFTE1Ba0dBMVVFQmhNQ1ZWTXhDekFKQmdOVkJBZ01Ba05CTVNFd0h3WUQKVlFRS0RCaEpiblJsY201bGRDQlhhV1JuYVhSeklGQjBlU0JNZEdReEdUQVhCZ05WQkFNTUVHTmhabVV1WlhoaApiWEJzWlM1amIyMHdnZ0VpTUEwR0NTcUdTSWIzRFFFQkFRVUFBNElCRHdBd2dnRUtBb0lCQVFDcDZLbjdzeTgxCnAwanVKL2N5ayt2Q0FtbHNmanRGTTJtdVpOSzBLdGVjcUcyZmpXUWI1NXhRMVlGQTJYT1N3SEFZdlNkd0kyaloKcnVXOHFYWENMMnJiNENaQ0Z4d3BWRUNyY3hkam0zdGVWaVJYVnNZSW1tSkhQUFN5UWdwaW9iczl4N0RsTGM2SQpCQTBaalVPeWwwUHFHOVNKZXhNVjczV0lJYTVyRFZTRjJyNGtTa2JBajREY2o3TFhlRmxWWEgySTVYd1hDcHRDCm42N0pDZzQyZitrOHdnemNSVnA4WFprWldaVmp3cTlSVUtEWG1GQjJZeU4xWEVXZFowZXdSdUtZVUpsc202OTIKc2tPcktRajB2a29QbjQxRUUvK1RhVkVwcUxUUm9VWTNyemc3RGtkemZkQml6Rk8yZHNQTkZ4MkNXMGpYa05MdgpLbzI1Q1pyT2hYQUhBZ01CQUFFd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFLSEZDY3lPalp2b0hzd1VCTWRMClJkSEliMzgzcFdGeW5acS9MdVVvdnNWQTU4QjBDZzdCRWZ5NXZXVlZycTVSSWt2NGxaODFOMjl4MjFkMUpINnIKalNuUXgrRFhDTy9USkVWNWxTQ1VwSUd6RVVZYVVQZ1J5anNNL05VZENKOHVIVmhaSitTNkZBK0NuT0Q5cm4yaQpaQmVQQ0k1ckh3RVh3bm5sOHl3aWozdnZRNXpISXV5QmdsV3IvUXl1aTlmalBwd1dVdlVtNG52NVNNRzl6Q1Y3ClBwdXd2dWF0cWpPMTIwOEJqZkUvY1pISWc4SHc5bXZXOXg5QytJUU1JTURFN2IvZzZPY0s3TEdUTHdsRnh2QTgKN1dqRWVxdW5heUlwaE1oS1JYVmYxTjM0OWVOOThFejM4Zk9USFRQYmRKakZBL1BjQytHeW1lK2lHdDVPUWRGaAp5UkU9Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBcWVpcCs3TXZOYWRJN2lmM01wUHJ3Z0pwYkg0N1JUTnBybVRTdENyWG5LaHRuNDFrCkcrZWNVTldCUU5semtzQndHTDBuY0NObzJhN2x2S2wxd2k5cTIrQW1RaGNjS1ZSQXEzTVhZNXQ3WGxZa1YxYkcKQ0pwaVJ6ejBza0lLWXFHN1BjZXc1UzNPaUFRTkdZMURzcGRENmh2VWlYc1RGZTkxaUNHdWF3MVVoZHErSkVwRwp3SStBM0kreTEzaFpWVng5aU9WOEZ3cWJRcCt1eVFvT05uL3BQTUlNM0VWYWZGMlpHVm1WWThLdlVWQ2cxNWhRCmRtTWpkVnhGbldkSHNFYmltRkNaYkp1dmRySkRxeWtJOUw1S0Q1K05SQlAvazJsUkthaTAwYUZHTjY4NE93NUgKYzMzUVlzeFR0bmJEelJjZGdsdEkxNURTN3lxTnVRbWF6b1Z3QndJREFRQUJBb0lCQVFDUFNkU1luUXRTUHlxbApGZlZGcFRPc29PWVJoZjhzSStpYkZ4SU91UmF1V2VoaEp4ZG01Uk9ScEF6bUNMeUw1VmhqdEptZTIyM2dMcncyCk45OUVqVUtiL1ZPbVp1RHNCYzZvQ0Y2UU5SNThkejhjbk9SVGV3Y290c0pSMXBuMWhobG5SNUhxSkpCSmFzazEKWkVuVVFmY1hackw5NGxvOUpIM0UrVXFqbzFGRnM4eHhFOHdvUEJxalpzVjdwUlVaZ0MzTGh4bndMU0V4eUZvNApjeGI5U09HNU9tQUpvelN0Rm9RMkdKT2VzOHJKNXFmZHZ5dGdnOXhiTGFRTC94MGtwUTYyQm9GTUJEZHFPZVBXCktmUDV6WjYvMDcvdnBqNDh5QTFRMzJQem9idWJzQkxkM0tjbjMyamZtMUU3cHJ0V2wrSmVPRmlPem5CUUZKYk4KNHFQVlJ6NWhBb0dCQU50V3l4aE5DU0x1NFArWGdLeWNrbGpKNkY1NjY4Zk5qNUN6Z0ZScUowOXpuMFRsc05ybwpGVExaY3hEcW5SM0hQWU00MkpFUmgySi9xREZaeW5SUW8zY2czb2VpdlVkQlZHWTgrRkkxVzBxZHViL0w5K3l1CmVkT1pUUTVYbUdHcDZyNmpleHltY0ppbS9Pc0IzWm5ZT3BPcmxEN1NQbUJ2ek5MazRNRjZneGJYQW9HQkFNWk8KMHA2SGJCbWNQMHRqRlhmY0tFNzdJbUxtMHNBRzR1SG9VeDBlUGovMnFyblRuT0JCTkU0TXZnRHVUSnp5K2NhVQprOFJxbWRIQ2JIelRlNmZ6WXEvOWl0OHNaNzdLVk4xcWtiSWN1YytSVHhBOW5OaDFUanNSbmU3NFowajFGQ0xrCmhIY3FIMHJpN1BZU0tIVEU4RnZGQ3haWWRidUI4NENtWmlodnhicFJBb0dBSWJqcWFNWVBUWXVrbENkYTVTNzkKWVNGSjFKelplMUtqYS8vdER3MXpGY2dWQ0thMzFqQXdjaXowZi9sU1JxM0hTMUdHR21lemhQVlRpcUxmZVpxYwpSMGlLYmhnYk9jVlZrSkozSzB5QXlLd1BUdW14S0haNnpJbVpTMGMwYW0rUlk5WUdxNVQ3WXJ6cHpjZnZwaU9VCmZmZTNSeUZUN2NmQ21mb09oREN0enVrQ2dZQjMwb0xDMVJMRk9ycW40M3ZDUzUxemM1em9ZNDR1QnpzcHd3WU4KVHd2UC9FeFdNZjNWSnJEakJDSCtULzZzeXNlUGJKRUltbHpNK0l3eXRGcEFOZmlJWEV0LzQ4WGY2ME54OGdXTQp1SHl4Wlp4L05LdER3MFY4dlgxUE9ucTJBNWVpS2ErOGpSQVJZS0pMWU5kZkR1d29seHZHNmJaaGtQaS80RXRUCjNZMThzUUtCZ0h0S2JrKzdsTkpWZXN3WEU1Y1VHNkVEVXNEZS8yVWE3ZlhwN0ZjanFCRW9hcDFMU3crNlRYcDAKWmdybUtFOEFSek00NytFSkhVdmlpcS9udXBFMTVnMGtKVzNzeWhwVTl6WkxPN2x0QjBLSWtPOVpSY21Vam84UQpjcExsSE1BcWJMSjhXWUdKQ2toaVd4eWFsNmhZVHlXWTRjVmtDMHh0VGwvaFVFOUllTktvCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
apiVersion: k8s.nginx.org/v1
kind: VirtualServer
metadata:
name: cafe
spec:
listener:
http: ip-listener-1-http
https: ip-listener-2-https
host: cafe.example.com
tls:
secret: cafe-secret
upstreams:
- name: tea
service: tea-svc
port: 80
- name: coffee
service: coffee-svc
port: 80
routes:
- path: /tea
action:
pass: tea
- path: /coffee
action:
pass: coffee
Loading

0 comments on commit c1e2906

Please sign in to comment.