Getting Started with Kubernetes Ingress-Nginx on Minikube

Fernando Diaz
6 min readSep 1, 2018

--

I have been working on Kubernetes Ingress-Nginx for some time now, and I’ve noticed that there aren’t many tutorials that go over the very basics. I hope that this post will help out those which are new to Kubernetes and getting started deploying their applications.

What is an Ingress? It is a door, a way into your application.

“yellow 8-panel door beside window” by Jünior Rodríguez on Unsplash

How does Ingress work in Kubernetes? In Kubernetes, Ingress works by configuring rules for accessing your applications.

There are 4 items which we will be looking at, Pods, Services, Ingress Resources, and the Ingress Controller. WARNING: I’m going to use alot of door metaphors.

  • A Pod is a group of one or more containers, with shared storage/network, and a specification for how to run the containers. That definition is straight from Kubernetes. It’s the actual application, sitting behind the door.
  • A Service identifies a set of pods that are running your application, and routes traffic to those pods. It does this using label selectors. It’s what’s behind the door, pointing at the application.
  • The Ingress Resource is a collection of rules that allows incoming connections to reach your Services. It is the door.
  • The Ingress Controller uses Ingress Resources to configure application access. In Ingress-Nginx, an Nginx configuration is built from the ingress resources, setting up the routing rules. It is the door person, which opens and closes the door to users.
S=Service, P=Pod, N=Node. From my presentation in KubeCon 2018 Europe.

Tutorial

Now, let’s get started with putting all the above into action!

Prerequisites

  • Kubectl
  • Hypervisor (minikube can be set to auto-install HyperKit)
  • VT-x/AMD-v virtualization must be enabled in BIOS
  • Internet connection on first run

Minikube

Minikube makes it easy to get started with Kubernetes. It runs a single-node Kubernetes cluster inside a VM on your laptop. It’s really easy to install and use.

NOTE: I’m using OSX, but the install should be simple for other platforms as well. If using another Operating System, see the installation instructions here. All commands, besides the brew commands, should be the same.

$ brew cask install minikube
🍺 minikube was successfully installed!
$ minikube version
minikube version: v1.12.2
$ minikube --memory 4096 --cpus 2 start --vm=true
😄 minikube v1.12.2 on Darwin 10.15.5
✨ Automatically selected the hyperkit driver
👍 Starting control plane node minikube in cluster minikube
🔥 Creating hyperkit VM (CPUs=2, Memory=4096MB, Disk=20000MB) ...
🐳 Preparing Kubernetes v1.18.3 on Docker 19.03.12 ...
🔎 Verifying Kubernetes components...
🌟 Enabled addons: default-storageclass, storage-provisioner
🏄 Done! kubectl is now configured to use "minikube"
$ minikube status
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
$ minikube addons enable ingress
🔎 Verifying ingress addon...
🌟 The 'ingress' addon is enabled
# wait a min for the pod to be up and running
$ kubectl get pods -n kube-system | grep ingress-nginx-controller
NAME READY STATUS
ingress-nginx-controller-69ccf5d9d8-vkg5f 1/1 Running

If you had any issues, most times its because there was a previous minikube installation, if that’s the case for you, try again after uninstalling minikube.

$ minikube delete
Deleting local Kubernetes cluster...
$ brew cask uninstall minikube
==> Uninstalling Cask minikube
==> Unlinking Binary '/usr/local/bin/minikube'.
==> Purging files for version 0.28.2 of Cask minikube
$ rm -rf /usr/local/bin/minikube
$ rm -rf ~/.minikube .kube

Deploying an Application

Now that our cluster is running we can go ahead and start deploying stuff.

  1. Deploy our pods(containers), using deployments. A deployment, pretty much just manages the state of our pods, It’s out of the scope of this tutorial, but you can learn more here.
$ echo "
apiVersion: apps/v1
kind: Deployment
metadata:
name: meow
spec:
replicas: 2
selector:
matchLabels:
app: meow
template:
metadata:
labels:
app: meow
spec:
containers:
- name: meow
image: gcr.io/kubernetes-e2e-test-images/echoserver:2.1
ports:
- containerPort: 8080
" | kubectl apply -f -
# wait a min for the deployment to be created
$ kubectl get deploy
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE
meow 2 2 2 2
# you should have 2 pods running
$ kubectl get pods
NAME READY STATUS
meow-5557bc7c54-cw2ck 1/1 Running
meow-5557bc7c54-kfzm5 1/1 Running

The image is the location of the container. When deploying your own application, you would select your image. gcr.io/kubernetes-e2e-test-images/echoserver:2.1 just responds with information about the request.

Also note that containerPort: 8080 is the port that the application is running on.

2. Expose our pods using Services. More info about exposure here.

$ echo "
apiVersion: v1
kind: Service
metadata:
name: meow-svc
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
selector:
app: meow
" | kubectl apply -f -
# wait a min for the service to be created
$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S)
meow-svc ClusterIP 10.107.78.24 <none> 80/TCP

Note the targetPort: 8080 is the port we target when we access the service. port: 80 is the port used to access the service.

3. Setup the Ingress Rules.

$ echo "
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: meow-ingress
spec:
rules:
- http:
paths:
- path: /meow
backend:
serviceName: meow-svc
servicePort: 80
" | kubectl apply -f -
# wait a min for the ingress resource to be created
$ kubectl get ing
NAME CLASS HOSTS ADDRESS PORTS AGE
meow-ingress <none> * 80 21s

This allows us to access the service meow-svc via the /meow path. Since we didn’t specify a host, then we can access it using the clusterIP.

Accessing your application

Now the Ingress rules are configured, we can test everything out. Now let’s send some requests.

$ minikube ip
192.168.99.100
$ curl 192.168.99.100/meow
Hostname: meow-799b895f78-v4l4f
Pod Information:
-no pod information available-
Server values:
server_version=nginx: 1.12.2 - lua: 10010
Request Information:
client_address=172.17.0.5
method=GET
real path=/meow
query=
request_version=1.1
request_scheme=http
request_uri=http://192.168.99.100:8080/meow
Request Headers:
accept=*/*
connection=close
host=192.168.99.100
user-agent=curl/7.54.0
x-forwarded-for=192.168.99.1
x-forwarded-host=192.168.99.100
x-forwarded-port=443
x-forwarded-proto=https
x-original-uri=/meow
x-real-ip=192.168.99.1
x-request-id=a1c65aa5ae7a574e47aaff49548160c5
x-scheme=https
Request Body:
-no body in request-

Note: If we curl other, none-existing endpoint, we get a 404.

$ curl 192.168.99.100/arepa
<html>
<head><title>404 Not Found</title></head>
<body>
<center><h1>404 Not Found</h1></center>
<hr><center>nginx/1.19.0</center>
</body>
</html>

Basic Debugging

In this section, we will explore a few basics of debugging. The following show how to gather basic information, which can be useful to determine what’s going on.

Describe the Pods:

Prints a detailed description of the selected pods, which includes events.

$ kubectl get pods -n kube-system | grep ingress-nginx-controller
ingress-nginx-controller-69ccf5d9d8-vkg5f 1/1 Running
$ kubectl describe pods -n kube-system ingress-nginx-controller-69ccf5d9d8-vkg5f
Name: ingress-nginx-controller-69ccf5d9d8-vkg5f
Namespace: kube-system
Priority: 0
Node: minikube/192.168.64.3
Start Time: Tue, 11 Aug 2020 14:25:42 -0500
....

View the Logs:

Prints the logs for the nginx-ingress-controller.

$ kubectl get pods -n kube-system | grep ingress-nginx-controller
ingress-nginx-controller-69ccf5d9d8-vkg5f 1/1 Running
$ kubectl logs -n kube-system ingress-nginx-controller-69ccf5d9d8-vkg5f
....
I0831 21:45:34.090212 5 nginx.go:271] Starting NGINX process
....

View the Nginx Conf:

Displays how nginx configures the application routing rules.

$ kubectl get pods -n kube-system | grep ingress-nginx-controller
ingress-nginx-controller-69ccf5d9d8-vkg5f 1/1 Running
$ kubectl exec -it -n kube-system ingress-nginx-controller-69ccf5d9d8-vkg5f cat /etc/nginx/nginx.conf
# Configuration checksum: 1983714050352580293
....

Conclusion

Hope you enjoyed this post! For learning more about Ingress-Nginx on Kubernetes, checkout their twitter page!!!

--

--

Fernando Diaz

Senior Technical Marketing @ GitLab 🦊, Developer 👨🏻‍💻, Alien 👽