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

ingress/gateway-api: expose listeners on host network #30840

Merged

Conversation

mhofstetter
Copy link
Member

@mhofstetter mhofstetter commented Feb 19, 2024

This PR introduces support for exposing the Envoy Listeners created by the Ingress Controller and/or Gateway API directly on the host network. This is useful in some edge cases where one don't want / can't to use K8s LoadBalancer/NodePort functionality (dev environments, cluster-external loadbalancer, ...)

Expose Envoy listeners on host network

This commit adds support for exposing the L7 Envoy Listeners directly on the host network - and no longer use Kubernetes Services of type LoadBalancer or NodePort.

The listener is exposed on all interfaces (0.0.0.0 for IPv4 and/or :: for IPv6).

Enable HostNetwork support via Helm

  • Ingress Controller: ingressController.hostNetwork.enabled=true
  • Gateway API: gatewayAPI.hostNetwork.enabled=true

Configure listener port

  • Shared Ingress: configurable via Helm
    (ingressController.hostNetwork.sharedHTTPPort & ingressController.hostNetwork.sharedTLSPassthroughPort)
  • Dedicated Ingress: configurable via Annotation on the resource Ingress
    (ingress.cilium.io/http-host-port & ingress.cilium.io/tls-passthrough-host-port)
  • Gateway API: configurable via spec.listeners.port on the resource Gateway

Be aware that missconfiguration might result in port clashes.

Expose Envoy listeners on subset of nodes

This commit adds support for exposing L7 Envoy Listeners only on a subset of Cilium Nodes. This only works in combination with the hostnetwork mode.

Configure node labelselector via Helm

  • Ingress Controller: ingressController.hostNetwork.nodes.matchLabels
  • Gateway API: gatewayAPI.hostNetwork.nodes.matchLabels
ingressController:
  hostNetwork:
    nodes:
      matchLabels:
        role: infra
        component: ingress

An empty selector selects all Nodes and continues to expose the functionality on all Cilium Nodes.


Please review the individual commits.

Fixes: #21390

@mhofstetter mhofstetter added kind/feature This introduces new functionality. release-note/misc This PR makes changes that have no direct user impact. area/servicemesh GH issues or PRs regarding servicemesh feature/k8s-gateway-api feature/k8s-ingress labels Feb 19, 2024
@mhofstetter mhofstetter force-pushed the pr/mhofstetter/ingress-hostnetwork branch from 18ac415 to 578d407 Compare February 19, 2024 09:35
@mhofstetter
Copy link
Member Author

/test

@mhofstetter mhofstetter marked this pull request as ready for review February 19, 2024 15:38
@mhofstetter mhofstetter requested review from a team as code owners February 19, 2024 15:38
Copy link
Member

@gandro gandro left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Helm LGTM!

@mhofstetter mhofstetter added release-note/minor This PR changes functionality that users may find relevant to operating Cilium. and removed release-note/misc This PR makes changes that have no direct user impact. labels Feb 20, 2024
@mhofstetter mhofstetter force-pushed the pr/mhofstetter/ingress-hostnetwork branch from 578d407 to 20d79f9 Compare February 23, 2024 07:49
@mhofstetter
Copy link
Member Author

rebased to main to resolve conflicts

Copy link
Contributor

@learnitall learnitall left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docs look good, thanks!

Ingestion of an Passthrough listener (`IngressPassthrough`) never uses the
parameters `defaultSecretNamespace` and `defaultSecretName`.

Therefore, this commit removes these from the function signature.

Signed-off-by: Marco Hofstetter <marco.hofstetter@isovalent.com>
Currently, the reconciliation of `Gateway` fails with an error if
the status of the corresponding loadbalancer service isn't ready.

Returning an error leads to an additional reconciliation and logs the error.

There are cases (upcoming hostnetwork support) where the status of the
loadbalancer service is never set which leads to reconciliation loops.

Therefore, with this commit, a missing status no longer results in an error. This
should also be enough in all other cases because a reconciliation should be
triggered on an update of the loadbalancer service itself.

Signed-off-by: Marco Hofstetter <marco.hofstetter@isovalent.com>
This commit adds support for exposing the L7 Envoy Listeners
directly on the host network - and no longer use Kubernetes Services
of type `LoadBalancer` or `NodePort`.

The listener is exposed on all interfaces (`0.0.0.0` for IPv4 and/or `::` for IPv6).

**Enable HostNetwork support via Helm**

* Ingress Controller: `ingressController.hostNetwork.enabled=true`
* Gateway API: `gatewayAPI.hostNetwork.enabled=true`

**Configure listener port**

* Shared Ingress: configurable via Helm
  (`ingressController.hostNetwork.sharedHTTPPort` & `ingressController.hostNetwork.sharedTLSPassthroughPort`)
* Dedicated Ingress: configurable via Annotation on the resource `Ingress`
  (`ingress.cilium.io/http-host-port` & `ingress.cilium.io/tls-passthrough-host-port`)
* Gateway API: configurable via `spec.listeners.port` on the resource `Gateway`

Be aware that missconfiguration might result in port clashes.

Signed-off-by: Marco Hofstetter <marco.hofstetter@isovalent.com>
This commit adds support for exposing L7 Envoy Listeners only on a
subset of Cilium Nodes. This only works in combination with the hostnetwork
mode.

**Configure node labelselector via Helm**

* Ingress Controller: `ingressController.hostNetwork.nodes.matchLabels`
* Gateway API: `gatewayAPI.hostNetwork.nodes.matchLabels`

```
ingressController:
  hostNetwork:
    nodes:
      matchLabels:
        role: infra
        component: ingress
```

An empty selector selects all Nodes and continues to expose the functionality
on all Cilium Nodes.

Signed-off-by: Marco Hofstetter <marco.hofstetter@isovalent.com>
@mhofstetter mhofstetter force-pushed the pr/mhofstetter/ingress-hostnetwork branch from 20d79f9 to 24126f3 Compare February 28, 2024 07:51
@mhofstetter
Copy link
Member Author

rebased to main and resolved conflicts

@mhofstetter
Copy link
Member Author

/test

@maintainer-s-little-helper maintainer-s-little-helper bot added the ready-to-merge This PR has passed all tests and received consensus from code owners to merge. label Feb 28, 2024
@julianwiedmann julianwiedmann added this pull request to the merge queue Feb 28, 2024
Merged via the queue into cilium:main with commit 91fc572 Feb 28, 2024
62 checks passed
@mhofstetter mhofstetter deleted the pr/mhofstetter/ingress-hostnetwork branch February 28, 2024 12:37
@maxpain
Copy link

maxpain commented Mar 7, 2024

The listener is exposed on all interfaces (0.0.0.0 for IPv4 and/or :: for IPv6).

[2024-03-07 15:37:30.207][7][error][config] [external/envoy/source/extensions/listener_managers/listener_manager/listener_manager_impl.cc:1179] listener 'kube-system/cilium-ingress/listener' failed to bind or apply socket options: cannot bind '0.0.0.0:80': Permission denied
[2024-03-07 15:37:30.210][7][warning][config] [external/envoy/source/extensions/config_subscription/grpc/grpc_subscription_impl.cc:138] gRPC config for type.googleapis.com/envoy.config.listener.v3.Listener rejected: Error adding/updating listener(s) kube-system/cilium-ingress/listener: cannot bind '0.0.0.0:80': Permission denied

@mhofstetter
Copy link
Member Author

mhofstetter commented Mar 12, 2024

The listener is exposed on all interfaces (0.0.0.0 for IPv4 and/or :: for IPv6).

[2024-03-07 15:37:30.207][7][error][config] [external/envoy/source/extensions/listener_managers/listener_manager/listener_manager_impl.cc:1179] listener 'kube-system/cilium-ingress/listener' failed to bind or apply socket options: cannot bind '0.0.0.0:80': Permission denied
[2024-03-07 15:37:30.210][7][warning][config] [external/envoy/source/extensions/config_subscription/grpc/grpc_subscription_impl.cc:138] gRPC config for type.googleapis.com/envoy.config.listener.v3.Listener rejected: Error adding/updating listener(s) kube-system/cilium-ingress/listener: cannot bind '0.0.0.0:80': Permission denied

👋 @maxpain

Thanks for testing the feature. Envoy should have permissions to bind to privileged ports - but that might depend on the actual environment. At least it was working on a local dev kind cluster when i tested this the last time.

If this is not working there's still the option to change the default port for the shared listener (HTTP/HTTPS & TLS Passthrough) to an unprivileged port via the helm values ingressController.hostNetwork.sharedHTTPPort & ingressController.hostNetwork.sharedTLSPassthroughPort.

Otherwise, feel free to raise a GH issue and provide some more information by attaching a sysdump. Thanks!

@mhofstetter
Copy link
Member Author

Update: It looks like binding to privileged ports works on kind clusters because Docker lowers the unprivileged port start from 1024 to 0 (moby/moby#41030)

root@kind-worker:/home/cilium# sysctl net | grep port_start
net.ipv4.ip_unprivileged_port_start = 0

Unfortunately it looks like it's not enough to just add the capability NET_BIND_SERVICE to the Pod where Cilium's Envoy instance is running (either Cilium Agent (embedded mode) or Cilium Proxy (daemonset mode)) - because since Cilium 1.15 the Envoy process itself no longer has the privileges (capabilities are dropped before starting the process) - see #27498.

Therefore, binding to privileged ports will not work in clusters where this sysctl option is not set.

I try to find a solution. In the meantime it's recommended to test the feature by explicitly configuring an unprivileged port.

/cc @maxpain

@kahirokunn
Copy link
Contributor

Amazing!! Thx!!!

@mhofstetter
Copy link
Member Author

updates / related changes:

Further information can be found in the PRs. Please open a new issue if you have any questions / problems.

/cc @maxpain - and thanks again for reporting!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/servicemesh GH issues or PRs regarding servicemesh feature/k8s-gateway-api feature/k8s-ingress kind/feature This introduces new functionality. ready-to-merge This PR has passed all tests and received consensus from code owners to merge. release-note/minor This PR changes functionality that users may find relevant to operating Cilium.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

CFP: make cilium ingress work on bare metal without any extra components
7 participants