Skip to content

Commit

Permalink
Document listener collisions
Browse files Browse the repository at this point in the history
  • Loading branch information
pleshakov committed Mar 1, 2021
1 parent df74b67 commit 93c3ef9
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,20 @@
# Handling Host Collisions
# Handling Host and Listener Collisions

A host collision occurs when multiple resources configure the same `host`. The Ingress Controller supports two options for handling host collisions:
This document explains how the Ingress Controller handles host and listener collisions among resources.

## Winner Selection Algorithm

If multiple resources contend for the same host/listener, the Ingress Controller will pick the winner based on the `creationTimestamp` of the resources: the oldest resource will win. In case there are more than one oldest resource (their `creationTimestamp` is the same), the Ingress Controller will choose the resource with the lexicographically smallest `uid`.

Note: the `creationTimestamp` and `uid` fields are part of the resource [ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#objectmeta-v1-meta).

## Host Collisions

A host collision occurs when multiple Ingress, VirtualServer, and TransportServer (configured for TLS Passthrough) resources configure the same `host`. The Ingress Controller supports two options for handling host collisions:
* Choosing the winner so that only one resource handles the host.
* Merging configuration of the conflicting resources.

## Choosing the Winner
### Choosing the Winner

Consider the following two resources:
* `cafe-ingress` Ingress:
Expand All @@ -31,11 +41,7 @@ Consider the following two resources:
. . .
```

If a user creates both resources in the cluster, a host collision will occur. As a result, the Ingress Controller will pick the winner using the following algorithm:

> If multiple resources contend for the same host, the Ingress Controller will pick the winner based on the `creationTimestamp` of the resources: the oldest resource will win. In case there are more than one oldest resources (their `creationTimestamp` is the same), the Ingress Controller will choose the resource with the lexicographically smallest `uid`.

> Note: the `creationTimestamp` and `uid` fields are part of the resource [ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.19/#objectmeta-v1-meta).
If a user creates both resources in the cluster, a host collision will occur. As a result, the Ingress Controller will pick the winner using the [winner selection algorithm](#winner-selection-algorithm).

In our example, if `cafe-virtual-server` was created first, it will win the host `cafe.example.com` and the Ingress Controller will reject `cafe-ingress`. This will be reflected in the events and in the resource's status field:
```
Expand All @@ -62,8 +68,56 @@ Events:

Similarly, if `cafe-ingress` was created first, it will win `cafe.example.com` and the Ingress Controller will reject `cafe-virtual-server`.

## Merging Configuration for the Same Host
### Merging Configuration for the Same Host

It is possible to merge configuration for multiple Ingress resources for the same host. One common use case for this approach is distributing resources across multiple namespaces. See the [Cross-namespace Configuration](/nginx-ingress-controller/configuration/ingress-resources/cross-namespace-configuration/) doc for more information.

It is *not* possible to merge the configurations for multiple VirtualServer resources for the same host. However, you can split the VirtualServers into multiple VirtualServerRoute resources, which a single VirtualServer can then reference. See the [corresponding example](https://github.com/nginxinc/kubernetes-ingress/tree/master/examples-of-custom-resources/cross-namespace-configuration) on GitHub.

It is *not* possible to merge configuration for multiple TransportServer resources.

## Listener Collisions

Listener collisions occur when multiple TransportServer resources (configured for TCP/UDP load balancing) configure the same `listener`. The Ingress Controller will choose the winner, which will own the listener.

### Choosing the Winner

Consider the following two resources:
* `tcp-1` TransportServer:
```yaml
apiVersion: k8s.nginx.org/v1alpha1
kind: TransportServer
metadata:
name: tcp-1
spec:
listener:
name: dns-tcp
protocol: TCP
. . .
```
* `tcp-2` TransportServer:
```yaml
apiVersion: k8s.nginx.org/v1alpha1
kind: TransportServer
metadata:
name: tcp-2
spec:
listener:
name: dns-tcp
protocol: TCP
. . .
```

If a user creates both resources in the cluster, a listener collision will occur. As a result, the Ingress Controller will pick the winner using the [winner selection algorithm](#winner-selection-algorithm).

In our example, if `tcp-1` was created first, it will win the listener `dns-tcp` and the Ingress Controller will reject `tcp-2`. This will be reflected in the events and in the resource's status field:
```
$ kubectl describe ts tcp-2
. . .
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning Rejected 10s nginx-ingress-controller Listener dns-tcp is taken by another resource
```

Similarly, if `tcp-2` was created first, it will win `dns-tcp` and the Ingress Controller will reject `tcp-1`.
2 changes: 1 addition & 1 deletion docs-web/configuration/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Configuration
global-configuration/index
ingress-resources/index
virtualserver-and-virtualserverroute-resources
handling-host-collisions
handling-host-and-listener-collisions
policy-resource
transportserver-resource
configuration-examples
6 changes: 2 additions & 4 deletions docs-web/configuration/transportserver-resource.md
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,5 @@ The [ConfigMap](/nginx-ingress-controller/configuration/global-configuration/con
## Limitations
As of Release 1.7, the TransportServer resource is a preview feature. Currently, it comes with the following limitations:
* When using TLS Passthrough, it is not possible to configure [Proxy Protocol](https://github.com/nginxinc/kubernetes-ingress/tree/master/examples/proxy-protocol) for port 443 both for regular HTTPS and TLS Passthrough traffic.
* If multiple TCP (or UDP) TransportServers reference the same listener, only one of them will receive the traffic. Moreover, until there is only one TransportServer, NGINX will fail to reload. If this happens, the IC will report a warning event with the `AddedOrUpdatedWithError` reason for the resource, which caused the problem, and also report the error in the logs.
* If multiple TLS Passthrough TransportServers have the same hostname, only one of them will receive the traffic. If this happens, the IC will report a warning in the logs like `host "app.example.com" is used by more than one TransportServers`.
The TransportServer resource is a preview feature. Currently, it comes with the following limitation:
* When using TLS Passthrough, it is not possible to configure [Proxy Protocol](https://github.com/nginxinc/kubernetes-ingress/tree/master/examples/proxy-protocol) for port 443 both for regular HTTPS and TLS Passthrough traffic.

0 comments on commit 93c3ef9

Please sign in to comment.