Exposing Kubernetes Services in Minikube Using Ingress: A Practical Guide

Learn how to expose Kubernetes services in Minikube using Ingress controllers, with step-by-step instructions and troubleshooting tips for local development environments.

Exposing Kubernetes Services in Minikube Using Ingress: A Practical Guide

Table of Contents

Exposing Kubernetes Services in Minikube Using Ingress: A Practical Guide

While working with Kubernetes on Minikube, one of the major roadblocks developers face is exposing services externally without relying on a cloud LoadBalancer. This guide walks you through how to use an Ingress controller in Minikube to route traffic to your services, replacing the need for a cloud LoadBalancer — with all the troubleshooting included.

Objective

To expose a Kubernetes nginx service running in Minikube using an Ingress controller, making it accessible via a custom domain (nginx.local) without using a cloud provider LoadBalancer.


Prerequisites

Before diving in, ensure you have the following tools installed and configured:

Important: Before starting Minikube, ensure Docker is running on your system. Minikube uses Docker as its default driver to pull container images and manage the Kubernetes node.


Step-by-Step Setup

1. Start Minikube

Run the following command to start your Minikube cluster:

minikube start

This initializes a single-node Kubernetes cluster using the Docker driver. Verify Docker is running beforehand, as Minikube will fail to start without it.

Note: Depending on your computer’s specifications, Minikube may take several minutes to start, especially on the first run when it needs to download images. Be patient and don’t interrupt the process. If you’re on a system with limited resources, this could take even longer.

After Minikube starts, verify that the necessary Docker images have been downloaded:

docker images | grep minikube

You should see several images related to Minikube. Also, check that the Minikube containers are running:

docker ps | grep minikube

You should see at least one container running for Minikube.


2. Create NGINX Deployment and Service

We’ll deploy a simple NGINX web server and expose it via a Kubernetes service.

Save the following as nginx-deployment.yaml:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 1
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - port: 80
      targetPort: 80

Explanation of nginx-deployment.yaml

This YAML file defines two Kubernetes resources: a Deployment and a Service. Let’s break it down:

Deployment Section:

  • apiVersion: apps/v1: Specifies the Kubernetes API version for deployments.
  • kind: Deployment: Indicates we’re creating a Deployment resource to manage a set of pods.
  • metadata: Provides metadata like the deployment’s name (nginx-deployment).
  • spec:
    • replicas: 1: Ensures one pod is running.
    • selector: Links the deployment to pods with the label app: nginx.
    • template: Defines the pod configuration.
      • metadata: Assigns the label app: nginx to the pod.
      • spec:
        • containers: Defines the container(s) in the pod.
          • name: nginx: Names the container.
          • image: nginx: Uses the official NGINX image from Docker Hub.
          • ports: Exposes port 80 on the container for HTTP traffic.

Service Section:

  • apiVersion: v1: Uses the core Kubernetes API for services.
  • kind: Service: Creates a Service to expose the deployment.
  • metadata: Names the service nginx-service.
  • spec:
    • selector: Routes traffic to pods with the label app: nginx.
    • ports:
      • port: 80: The service listens on port 80.
      • targetPort: 80: Forwards traffic to port 80 on the pods.

Apply the configuration:

kubectl apply -f nginx-deployment.yaml

This creates the NGINX deployment and service in your Minikube cluster.

To verify the service is running, run:

kubectl get svc nginx-service

and then to verify the pods are running, run:

kubectl get pods -l app=nginx

3. Enable Ingress Addon in Minikube

Run the following command to enable the Ingress addon:

minikube addons enable ingress

What Does the Ingress Addon Do?

The Ingress addon in Minikube deploys an NGINX Ingress Controller, a Kubernetes resource that manages external HTTP/HTTPS traffic. Here’s a detailed explanation:

  • Ingress Controller: A specialized pod that runs an NGINX web server configured to handle Ingress rules. It acts as a reverse proxy, routing external traffic to the appropriate services based on rules defined in Ingress resources.
  • Deployment: The addon deploys the controller in the ingress-nginx namespace, along with necessary configurations like services and ConfigMaps.
  • Service Exposure: The controller is exposed as a LoadBalancer service, which Minikube simulates locally using its networking setup.
  • Automation: Minikube’s addon simplifies the setup by pre-configuring the NGINX Ingress Controller, saving you from manually installing and configuring it (e.g., via Helm or raw manifests).

Verify the controller is running:

kubectl get pods -n ingress-nginx

Look for a pod named ingress-nginx-controller-... in the Running state. This confirms the controller is ready to handle Ingress rules.


4. Create an Ingress Resource

Save the following as nginx-ingress.yaml:

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

Explanation of nginx-ingress.yaml

This YAML defines an Ingress resource to route traffic to the nginx-service. Here’s a detailed breakdown:

  • apiVersion: networking.k8s.io/v1: Uses the networking API for Ingress resources.
  • kind: Ingress: Specifies an Ingress resource.
  • metadata: Names the Ingress nginx-ingress.
  • annotations:
    • nginx.ingress.kubernetes.io/rewrite-target: /: Rewrites the URL path to / before forwarding to the service. This ensures requests to nginx.local/* are routed correctly.
  • spec:
    • rules: Defines routing rules.
      • host: nginx.local: Routes requests for the nginx.local domain.
      • http:
        • paths:
          • path: /: Matches all requests to the root path.
          • pathType: Prefix: Allows matching of paths starting with /.
          • backend: Specifies the target service.
            • service:
              • name: nginx-service: Forwards traffic to the nginx-service.
              • port:
                • number: 80: Targets port 80 on the service.

Apply the configuration:

kubectl apply -f nginx-ingress.yaml

This creates the Ingress resource, which the NGINX Ingress Controller uses to route traffic.

To verify the Ingress resource is created, run:

kubectl get ingress nginx-ingress

5. Update Your /etc/hosts File

To resolve nginx.local locally, add an entry to your /etc/hosts file:

127.0.0.1    nginx.local

Note: Use 127.0.0.1 (localhost) instead of Minikube’s IP, as the minikube tunnel (covered next) binds the Ingress controller to your local machine’s network interface. On Windows, edit C:\Windows\System32\drivers\etc\hosts as Administrator. On macOS/Linux, use sudo nano /etc/hosts.


6. Start the Minikube Tunnel

Run the following in a separate terminal:

minikube tunnel

Note: Keep this terminal open! The tunnel exposes the Ingress controller’s LoadBalancer service to your local network, allowing traffic to reach nginx.local.


🧪 Testing the Setup

With the tunnel running, test the setup:

curl http://nginx.local

You should see the default NGINX welcome page HTML. Alternatively, open http://nginx.local in your browser to view the page.


🐞 Troubleshooting Journey

Setting up Ingress on Minikube can be tricky. Here are issues we encountered and their fixes:

❌ Ingress Resource Not Working

  • Issue: Running kubectl get pods -n ingress-nginx showed:

    No resources found in ingress-nginx namespace
    
  • Fix: The Ingress addon hadn’t finished deploying. Wait a few moments and recheck. If it persists, re-run minikube addons enable ingress.

❌ DNS Resolution Error

  • Issue: Curl returned:

    curl: (6) Could not resolve host: nginx.local
    
  • Fix: Ensure 127.0.0.1 nginx.local is added to /etc/hosts.

❌ Port 80 Not Accessible

  • Issue: Curl failed with:

    curl: (28) Failed to connect to nginx.local port 80
    
  • Fix: Start the minikube tunnel to expose the LoadBalancer service.

🛠️ Manually Patched the Service

To explicitly set the Ingress controller’s service to LoadBalancer,run:

kubectl patch svc ingress-nginx-controller -n ingress-nginx -p '{"spec": {"type": "LoadBalancer"}}'

This was optional, as Minikube’s tunnel handles this, but it helped confirm the service configuration.


✅ Summary

By following this guide, you’ve:

  • Deployed an NGINX application.
  • Enabled and verified the NGINX Ingress Controller.
  • Created an Ingress rule to route traffic to nginx.local.
  • Configured /etc/hosts for local DNS resolution.
  • Used minikube tunnel to expose the service.

🧵 Cleaning Up

When you’re done experimenting, it’s important to properly clean up your resources to free up system resources. Follow these steps:

1. Stop the Minikube Tunnel

If you have the minikube tunnel running in a terminal, press Ctrl+C to stop it.

2. Delete the Kubernetes Resources

Remove the Ingress, Service, and Deployment:

kubectl delete ingress nginx-ingress
kubectl delete service nginx-service
kubectl delete deployment nginx-deployment

3. Stop Minikube

Stop the Minikube cluster:

minikube stop

This will shut down the Minikube VM but preserve your cluster state.

4. Delete Minikube (Optional)

If you want to completely remove the Minikube cluster:

minikube delete

This will delete all cluster data and the Minikube VM.


🧠 Final Thoughts

Using Ingress in Minikube simulates cloud-like service exposure in a local environment. While it requires manual steps like editing /etc/hosts and running a tunnel, it offers a cost-free way to learn Kubernetes networking and gain hands-on experience with Ingress controllers.

Table of Contents