DEV Community

Akash for MechCloud Academy

Posted on

Part 10: The Front Door: Smart Routing with Kubernetes Ingress

So far, we have built a single, robust application. It is stateful, configurable, and has intelligent health checks. We exposed it to the world using a NodePort Service, which is great for learning.

But real-world systems are rarely a single application. They are typically a collection of microservices: a web frontend, a user API, a payment service, and so on.

How would we expose all of them? Creating a NodePort or LoadBalancer Service for every single microservice would be chaotic and expensive, resulting in a mess of different ports and public IP addresses.

What we need is a single, smart "front door" for our entire cluster. We need a component that can receive all incoming traffic and act as a reverse proxy, routing requests to the correct internal service based on the URL. This component is Ingress.

The Two Parts of Ingress: A Critical Distinction

The Ingress system is made of two parts, and it's vital to understand the difference:

  1. Ingress Resource: This is a Kubernetes object, a YAML manifest you write. It is simply a set of rules. It's a declarative blueprint that says, "If traffic comes in for myapp.com/api, send it to the api-service. If traffic is for myapp.com/blog, send it to the blog-service." It does nothing on its own.

  2. Ingress Controller: This is the actual software that implements the rules. The controller is a Pod (or set of Pods) running inside your cluster that listens for traffic from the outside world. It constantly watches for Ingress resources and configures itself to follow the rules they define.

Think of it like this: The Ingress resource is the list of instructions you leave for a receptionist. The Ingress Controller is the actual receptionist who reads the list and directs visitors. Without the receptionist (the controller), the list of instructions (the resource) is just a piece of paper.

Step 1: Install an Ingress Controller

Before we can create any Ingress rules, we need a controller running in our cluster. We will use the most popular one, the Nginx Ingress Controller. How you install it depends on your local cluster tool.

For Minikube:
Minikube makes this incredibly easy with an addon.

minikube addons enable ingress
Enter fullscreen mode Exit fullscreen mode

This will install and run the Nginx Ingress Controller for you.

For kind:
The kind documentation provides a simple apply command.

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml
Enter fullscreen mode Exit fullscreen mode


Wait a minute or two for the controller Pods to be ready. You can check their status with kubectl get pods -n ingress-nginx.

Step 2: Deploy Some Sample Applications

To see routing in action, we need more than one service. Let's create two simple, distinct applications.

Create a file named app-a.yaml:

# app-a.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp-a
spec:
  replicas: 1
  selector: { matchLabels: { app: webapp-a } }
  template:
    metadata: { labels: { app: webapp-a } }
    spec:
      containers:
      - name: app
        image: hashicorp/http-echo
        args:
        - "-text=This is WebApp A"
---
apiVersion: v1
kind: Service
metadata:
  name: service-a
spec:
  selector: { app: webapp-a }
  ports:
    - port: 80
      targetPort: 5678
Enter fullscreen mode Exit fullscreen mode

Now create a second file named app-b.yaml:

# app-b.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: webapp-b
spec:
  replicas: 1
  selector: { matchLabels: { app: webapp-b } }
  template:
    metadata: { labels: { app: webapp-b } }
    spec:
      containers:
      - name: app
        image: hashicorp/http-echo
        args:
        - "-text=Welcome to API B"
---
apiVersion: v1
kind: Service
metadata:
  name: service-b
spec:
  selector: { app: webapp-b }
  ports:
    - port: 80
      targetPort: 5678
Enter fullscreen mode Exit fullscreen mode

These manifests each create a Deployment running a simple echo server and a ClusterIP service to expose it internally. Now apply them:

kubectl apply -f app-a.yaml
kubectl apply -f app-b.yaml
Enter fullscreen mode Exit fullscreen mode

Step 3: Create the Ingress Resource (The Rules)

Now for the main event. We will define our routing rules in an Ingress manifest. Create a file named ingress.yaml.

# ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
spec:
  rules:
  - http:
      paths:
      - path: /app
        pathType: Prefix
        backend:
          service:
            name: service-a
            port:
              number: 80
      - path: /api
        pathType: Prefix
        backend:
          service:
            name: service-b
            port:
              number: 80
Enter fullscreen mode Exit fullscreen mode

This manifest is our set of instructions. It says:

  • For any HTTP traffic...
  • If the path starts with (pathType: Prefix) /app, route it to port 80 of service-a.
  • If the path starts with /api, route it to port 80 of service-b.

Now, apply the rules:

kubectl apply -f ingress.yaml
Enter fullscreen mode Exit fullscreen mode

Step 4: Test the Routing

We're ready to test our front door. We need to send a request to the Ingress Controller's IP address.

For Minikube:
Get the cluster's IP address.

minikube ip
Enter fullscreen mode Exit fullscreen mode

For Docker Desktop or kind:
The controller is exposed on localhost.

Now, using curl (or your browser), test the two paths. Your IP address may vary.

Test the first path:

# For Minikube (replace with your IP)
curl http://192.168.49.2/app

## For kind/Docker Desktop
curl http://localhost/app
Enter fullscreen mode Exit fullscreen mode

Result: You should see This is WebApp A

Test the second path:

# For Minikube (replace with your IP)
curl http://192.168.49.2/api

# For kind/Docker Desktop
curl http://localhost/api
Enter fullscreen mode Exit fullscreen mode

Result: You should see Welcome to API B

It works! A single entry point is correctly routing traffic to two different internal services based on the path.

What's Next

We now have a professional way to manage external traffic for multiple microservices. Ingress is the key to building complex, multi-service applications on Kubernetes.

As our cluster grows, another problem emerges. Our cluster is like one giant open-plan office. The teams working on WebApp A and API B can see and potentially interfere with each other's Deployments, Services, and ConfigMaps. This can lead to naming conflicts and security issues.

In the next part, we'll learn how to partition our cluster into logical, isolated "virtual clusters" using Namespaces. We will also explore how to set resource quotas on them to ensure fair play, using Requests and Limits.

Top comments (0)