This article provides step-by-step guidance for configuring RKE2’s built-in ingress-nginx controller to run behind an external LoadBalancer. It supports environments like AWS, GCP, Azure, and MetalLB, and replaces the default hostNetwork + DaemonSet configuration with a Deployment and LoadBalancer service.

Running RKE2 Ingress-NGINX with an External LoadBalancer

Section 1: Summary and Use Case

Summary

By default, RKE2 deploys the ingress controller as a DaemonSet with host networking. This is ideal for bare-metal setups but not suitable for cloud-native ingress via a LoadBalancer. This guide helps configure the controller to run as a Deployment with a LoadBalancer service, suitable for environments like AWS ELB or MetalLB.

Use Case

You may want to:

  • Integrate ingress-nginx with your cloud provider’s LoadBalancer
  • Use MetalLB for bare-metal LoadBalancer IP assignment
  • Disable host networking for better isolation
  • Scale ingress-nginx using Deployments

Section 2: Configuration Instructions

Prerequisites

  • A running RKE2 cluster
  • Access to the control plane node(s)
  • A LoadBalancer integration (e.g., AWS, GCP, Azure, or MetalLB)

Step 1: Create a HelmChartConfig Override

Create the following file on all RKE2 server nodes:

cat > /var/lib/rancher/rke2/server/manifests/ingress-nginx.yaml << 'EOF'
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: rke2-ingress-nginx
  namespace: kube-system
spec:
  valuesContent: |
    controller:
      hostNetwork: false
      kind: Deployment
      replicaCount: 3
      service:
        enabled: true
        type: LoadBalancer
EOF

This config:

  • Converts the controller to a Deployment
  • Disables host networking
  • Enables a LoadBalancer-type service

Step 2: Wait for RKE2 to Apply Changes

RKE2 automatically reconciles manifests from this directory. To confirm deployment:

kubectl -n kube-system get deploy,svc -l app.kubernetes.io/name=ingress-nginx

You should see a Deployment and a LoadBalancer service.


Step 3: Verification

Check that a LoadBalancer was successfully provisioned:

kubectl get svc -n kube-system ingress-nginx-controller

Example Output (AWS):

NAME                     TYPE           CLUSTER-IP       EXTERNAL-IP                                                               PORT(S)                      AGE
ingress-nginx-controller LoadBalancer   10.43.248.207    a1b2c3d4e5f6g7h8-1234567890.us-west-2.elb.amazonaws.com   80:31014/TCP,443:32478/TCP   2m
  

You can now route ingress traffic to the ELB hostname or associate a custom domain.


Step 4: Example Ingress Resource

Here is a simple Ingress manifest for testing:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example
  namespace: default
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: example.yourdomain.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: your-service
            port:
              number: 80

Point the DNS for example.yourdomain.com to the ELB address or external IP.


Notes

  • Adjust replicaCount as needed
  • Ensure firewall/security groups allow ports 80/443
  • For MetalLB, ensure address pools are properly configured
  • This override is persistent across cluster upgrades

References