Kubernetes Ingress resources give you a single entry point for routing external HTTP and HTTPS traffic to services inside your cluster. On RHEL 8, the Nginx Ingress Controller is a popular choice because it integrates cleanly with bare-metal deployments and supports TLS termination, name-based virtual hosting, and path-based routing out of the box. This tutorial walks you through installing the Nginx Ingress Controller, defining Ingress rules, opening the required firewall ports, and testing your configuration end to end. By the end you will be routing real traffic to cluster services through a single NodePort.

Prerequisites

  • A running Kubernetes cluster on RHEL 8 (single-node or multi-node)
  • kubectl configured with cluster-admin privileges
  • firewall-cmd available and the firewalld service active
  • DNS or /etc/hosts entries pointing your test hostname to the node IP
  • Optional: a TLS certificate/key pair for the HTTPS section

Step 1 — Install the Nginx Ingress Controller

Apply the official bare-metal manifest from the Kubernetes ingress-nginx project. The bare-metal variant uses a NodePort Service instead of a cloud load balancer, which is appropriate for on-premises RHEL 8 nodes.

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.10.1/deploy/static/provider/baremetal/deploy.yaml

Watch the controller pod reach the Running state before proceeding:

kubectl get pods -n ingress-nginx -w

Once the ingress-nginx-controller pod shows Running, note the NodePort assigned to port 80 and 443:

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

Step 2 — Open Firewall Ports

By default the bare-metal manifest exposes the controller on NodePorts 30080 (HTTP) and 30443 (HTTPS). Open those ports on the RHEL 8 firewall so external clients can reach the cluster.

sudo firewall-cmd --permanent --add-port=30080/tcp
sudo firewall-cmd --permanent --add-port=30443/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-ports

If the controller was assigned different NodePort values in your cluster, substitute those numbers instead.

Step 3 — Deploy a Sample Application

Create a simple deployment and ClusterIP service to act as the backend for the Ingress rule.

kubectl create deployment demo-app --image=nginxdemos/hello --port=80
kubectl expose deployment demo-app --port=80 --target-port=80 --name=demo-app-svc

Verify the service is available:

kubectl get svc demo-app-svc

Step 4 — Create an Ingress Resource

Save the following YAML as demo-ingress.yaml. It routes all requests for demo.example.com to the demo-app-svc service on port 80.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: demo-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
    - host: demo.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: demo-app-svc
                port:
                  number: 80
kubectl apply -f demo-ingress.yaml
kubectl get ingress demo-ingress

Step 5 — Add TLS with a Kubernetes Secret

For HTTPS, create a Secret containing your certificate and private key, then reference it in the Ingress spec.

kubectl create secret tls demo-tls-secret 
  --cert=demo.example.com.crt 
  --key=demo.example.com.key

Add a tls block to your Ingress YAML and reapply:

spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - demo.example.com
      secretName: demo-tls-secret
  rules:
    - host: demo.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: demo-app-svc
                port:
                  number: 80
kubectl apply -f demo-ingress.yaml

Step 6 — Test the Ingress

Send a request using curl with a Host header to simulate name-based routing. Replace NODE_IP with your RHEL 8 node’s IP address.

# HTTP via NodePort
curl -v -H 'Host: demo.example.com' http://NODE_IP:30080/

# HTTPS via NodePort (skip cert verification for self-signed certs)
curl -v -k -H 'Host: demo.example.com' https://NODE_IP:30443/

A successful response displays the Nginx demo page HTML, confirming the Ingress controller is routing traffic correctly.

Conclusion

You have installed the Nginx Ingress Controller on a bare-metal RHEL 8 Kubernetes cluster, defined an Ingress resource with host and path routing rules, opened the required firewall NodePorts, secured traffic with a TLS Secret, and verified routing with curl. The Ingress layer consolidates all external HTTP traffic through a single controller, making it far easier to manage multiple services behind a single IP address.

Next steps: Configure cert-manager for automatic TLS certificate issuance, Set up rate limiting and authentication annotations on Nginx Ingress, and Deploy multiple services under different path prefixes on the same hostname.