Make your Kubernetes services accessible outside the cluster using DNS names and well-known ports

This guide is about how to set up a basic web application called echoheaders in our Kubernetes cluster and making it accessible to the outside world by a DNS address on the well known http/80 port.

Ingress rules will help us make this possible, but to make them work we will need an ingress controller to handle the requests and manage the rules.

Working with ingress rules will help you make services available to other clients outside your Kubernetes cluster.

Prerequisites

Working Kubernetes Cluster

DNS Cluster Services

This guide is based on my All in One Kubernetes Cluster with kubeadm which will need an additional RBAC policy. From this policy you will have to use following resources in your setup:

namespace nginx-ingress

serviceaccount nginx-ingress-serviceaccount



user@computer$ kubectl create -f https://raw.githubusercontent.com/nevetS/ingress/master/examples/rbac/nginx/nginx-ingress-controller-rbac.yml

Step 1 – Setup Ingress Capabilities

As RBAC isn’t our focus in this guide, we won’t dive deeper into RBAC policies.

We begin by enabling our Kubernetes cluster to handle ingress rules.

We set up the service which makes our ingress controller available outside the Kubernetes cluster. In our case to be able to use well-known ports like http/80 we will make use of the externalIPs directive.

nginx-ingress-service.yml apiVersion: v1

kind: Service

metadata:

name: nginx-ingress

namespace: nginx-ingress

spec:

externalIPs:

– 192.168.0.217

ports:

– port: 80

name: http

selector:

k8s-app: nginx-ingress-lb

user@computer$ kubectl create -f nginx-ingress-service.yml

default-http-backend

nginx-ingress-controller

nginx-ingress-deployment.yml apiVersion: extensions/v1beta1

kind: Deployment

metadata:

name: nginx-ingress-controller

namespace: nginx-ingress

spec:

replicas: 2

template:

metadata:

labels:

k8s-app: nginx-ingress-lb

spec:

serviceAccountName: nginx-ingress-serviceaccount

containers:

– name: nginx-ingress-controller

image: gcr.io/google_containers/nginx-ingress-controller:0.8.3

args:

– /nginx-ingress-controller

– –default-backend-service=nginx-ingress/default-http-backend

env:

– name: POD_NAME

valueFrom:

fieldRef:

fieldPath: metadata.name

– name: POD_NAMESPACE

valueFrom:

fieldRef:

fieldPath: metadata.namespace

ports:

– containerPort: 80

Next let’s create the ingress controller which will handle all incoming request from this service and manage the corresponding ingress rules. We tell the controller to use the servicein the name spaceto use as the default route when the request doesn’t match with an ingress rule.

user@computer$ kubectl create -f nginx-ingress-deployment.yml

default-backend.yaml apiVersion: extensions/v1beta1

kind: Deployment

metadata:

name: default-http-backend

labels:

k8s-app: default-http-backend

namespace: nginx-ingress

spec:

replicas: 1

template:

metadata:

labels:

k8s-app: default-http-backend

spec:

terminationGracePeriodSeconds: 60

containers:

– name: default-http-backend

image: gcr.io/google_containers/defaultbackend:1.3

livenessProbe:

httpGet:

path: /healthz

port: 8080

scheme: HTTP

initialDelaySeconds: 30

timeoutSeconds: 5

ports:

– containerPort: 8080

resources:

limits:

cpu: 10m

memory: 20Mi

requests:

cpu: 10m

memory: 20Mi

—

apiVersion: v1

kind: Service

metadata:

name: default-http-backend

namespace: nginx-ingress

labels:

k8s-app: default-http-backend

spec:

ports:

– port: 80

targetPort: 8080

selector:

k8s-app: default-http-backend

Next step is to set up our missing default http backend so that our ingress controller can redirect non-matching requests to the service.

user@computer$ kubectl create -f default-backend.yaml

Step 2 – Add Ingress Rules And Set Up Basic Application

We made our Kubernetes cluster ready for handling and managing external http traffic by setting up the core components ingress service, ingress controller pod and the default http backend service and pod. Now we are ready to work with ingress rules.

We now will need to tell the ingress controller what to do with the incoming requests. That’s where ingress rules come into play.

We first set up an ingress rule that will redirect http traffic to the destination host echoheaders.powerodit.ch to the service echoheaders-x .

ingress-echoheader.yaml apiVersion: extensions/v1beta1

kind: Ingress

metadata:

name: echoheader

spec:

rules:

– host: echoheader.powerodit.ch

http:

paths:

– path: /

backend:

serviceName: echoheaders-x

servicePort: 80

$kubectl create -f ingress-echoheader.yaml

deployment-echo-header.yaml apiVersion: extensions/v1beta1

apiVersion: v1

kind: Service

metadata:

name: echoheaders-x

labels:

app: echoheaders-x

spec:

ports:

– port: 80

targetPort: 8080

protocol: TCP

name: http

selector:

app: echoheaders

—

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

name: echoheaders

spec:

replicas: 1

template:

metadata:

labels:

app: echoheaders

spec:

containers:

– name: echoheaders

image: gcr.io/google_containers/echoserver:1.8

ports:

– containerPort: 8080

Now we need the corresponding service and pod with the web application to be reached by this ingress rule. We will make use of echoheaders app which shows us basic request information to the pod.

user@computer$ kubectl create -f deployment-echo-header.yaml

Step 3 – Test Ingress Setup

Great we set up our ingress rule to redirect http traffic to our deployed echoheaders application. Now let’s see if it all works

For our setup you will need to adjust your hosts file to point the subdomain echoheader.powerodit.ch to your all in one kubeadm clusters external IP.

In my case this is

/etc/hosts 192.168.0.217 echoheader.powerodit.ch

Now let’s open our browser and call the subdomain we just configured. You should see a page with plain text information about our request.

But wait, there is more. Remember our default http backend when no request is matched! Let’s just request a web page with the IP address of your all in one kubeadm cluster and we get the default http backend answering, as the request didn’t match any ingress rule inside our cluster.

Our basic tests to see if our ingress setup is working were successful.

Conclusion

We have successfully set up a basic ingress controller which handles requests and manages ingress rules and implemented a basic ingress rule example.

From here on you could also try setting up our basic WordPress example from Kubernetes Patterns: Stateful Applications.