Ingress Controller and Kubernetes Using Minikube — a Tiny Demonstration

Traffic flow from the domain name to the services and pods

Using the name-based virtual hosting during our legacy hosting days to route traffic to a Kubernetes Service is the role of an Ingress Controller. This is an API object to allow access to the services in a cluster, typically HTTP. URI based routing eg: www.example.com/shop, www.example.com/admin etc. can now share a single Load-Balancer, thus reducing costs.

This assumes that you already have Kubernetes Cluster using Minikube up and running. Remember to enable the ingress addon to Minikube as well.

minikube addons enable ingress

Ok, let us proceed with our super simple demonstration.

Step-1: Two PODs Running Our Application

Create two pods. Create a YAML file called pod1.yml

apiVersion: v1
kind: Pod
metadata:
name: pod-1
labels:
app: pod-1-label
spec:
containers:
- name: py1
image: python:2.7
imagePullPolicy: IfNotPresent
command: ["/bin/bash"]
args: ["-c", "echo \"<p>This is POD1 $(hostname)</p>\" > index.html; python -m SimpleHTTPServer 8080"]
ports:
- name: http
containerPort: 8080

Now a YAML file for pod1 called pod2.yml

apiVersion: v1
kind: Pod
metadata:
name: pod-2
labels:
app: pod-2-label
spec:
containers:
- name: py1
image: python:2.7
imagePullPolicy: IfNotPresent
command: ["/bin/bash"]
args: ["-c", "echo \"<p>This is POD2 $(hostname)</p>\" > index.html; python -m SimpleHTTPServer 8080"]
ports:
- name: http
containerPort: 8080

Step-2 Two Services to Route Traffic to Our PODs

Time to create a service to send traffic to our pod1, let use use NodePort to keep it simple. Create a file called svc1.yml. Notice the selector app: pod-1-label in below which is used to detect the target pods (in this case just one pod) to load balance.

kind: Service
apiVersion: v1
metadata:
name: svc1
spec:
selector:
app: pod-1-label
ports:
- port: 80
targetPort: http
type: NodePort

Adding one more service svc2.yml to route traffic to pod2. Here we use the selector matching pods2 label, app: pod-2-label.

kind: Service
apiVersion: v1
metadata:
name: svc2
spec:
selector:
app: pod-2-label
ports:
- port: 80
targetPort: http
type: NodePort

Step-3 Create and Verify

Let us use kubectl to apply the above YAMLs

kubectl create -f pod1.yml
pod/pod-1 created
kubectl create -f pod2.yml
pod/pod-2 created
kubectl create -f svc1.yml
service/svc1 created
kubectl create -f svc2.yml
service/svc2 created

Let us verify the objects (pods and services)

kubectl get po --selector=app=pod-1-label
NAME READY STATUS RESTARTS AGE
pod-1 1/1 Running 0 8m
kubectl get po --selector=app=pod-2-label
NAME READY STATUS RESTARTS AGE
pod-2 1/1 Running 0 8m
kubectl get svc -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 28d <none>
svc1 ClusterIP 10.96.97.60 <none> 80/TCP 5m app=pod-1-label
echo $(minikube service svc1 --url)
http://192.168.99.100:31982
curl $(minikube service svc1 --url)
<p>This is POD1 pod-1</p>
curl $(minikube service svc2 --url)
<p>This is POD2 pod-2</p>

OK, our two services are able to locate the matching PODs and route the traffic as seen from the output.

Step-4 Create the Ingress Object to Route Traffic

Let us create the Ingress object to route traffic to our two services based on the URI! Here is the ing.yml file.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: ing
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
backend:
serviceName: svc2
servicePort: 80
rules:
- host: my-domain.com
http:
paths:
- path: /s1
backend:
serviceName: svc1
servicePort: 80
- path: /s2
backend:
serviceName: svc2
servicePort: 80

Let us create the ingress object.

kubectl apply -f ing.yml 
ingress.extensions/ing created
kubectl get ing
NAME HOSTS ADDRESS PORTS AGE
ing1 * 80 3s
kubectl describe ing ing
Name: ing
Namespace: default
Address: 10.0.2.15
Default backend: default-http-backend:80 (172.17.0.6:8080)
Rules:
Host Path Backends
---- ---- --------
my-domain.com
/s1 svc1:80 (<none>)
/s2 svc2:80 (<none>)

Let us try the working of our ingress object! In order to test this we can either edit our /etc/hosts file to add our domain as below

192.168.99.100 my-domain.com

or use curl with the -H option which is easier as shown below.

Routing traffic to service one using URI /s1

curl -H"Host: my-domain.com" 192.168.99.100/s2
<p>This is POD2 pod-2</p>

Routing traffic to service two using URI /s2

curl -H"Host: my-domain.com" 192.168.99.100/s1
<p>This is POD1 pod-1</p>

Routing traffic to service one as defined by the default backend in our ingress YAML

curl -H"Host: my-domain.com" 192.168.99.100
<p>This is POD1 pod-1</p>

Please note that we are not using deployment object in this demo to keep this super simple.

This completes our super Thank you for your time, please do follow for more such tiny demos!

Sreeprakash Neelakantan

Written by

AWS Certified DevOps Engineer & Solutions Architect Professional — Docker | Kubernetes | DevOps — Trainer | Running | Swimming | Cycling

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade