PowerodIT

Ingress Rules For Kubernetes Services

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.

Kubernetes Basic Ingress Architecture Close Up
Fig. 1: Ingress example setup

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.

Kubernetes Basic Ingress Architecture
Fig. 2: Ingress request handling

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
$ kubectl create -f https://raw.githubusercontent.com/nevetS/ingress/master/examples/rbac/nginx/nginx-ingress-controller-rbac.yml

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

Step 1 – Setup Ingress Capabilities

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

Ingress Controller And Default Http Backend
Fig. 3: Ingress Controller and http Default Backend

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
$ kubectl create -f nginx-ingress-service.yml

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 service default-http-backend in the name space nginx-ingress-controller to use as the default route when the request doesn’t match with an ingress rule.

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
$ kubectl create -f nginx-ingress-deployment.yml

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

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
$ kubectl create -f default-backend.yaml

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.

Step 2 – Add Ingress Rules And Set Up Basic Application

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

Fig. 4: Ingress rule pointing to echoheaders deployment

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

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.

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
$ kubectl create -f deployment-echo-header.yaml

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

Step 3 – Test Ingress Setup

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.

Fig. 5: Echoheaders response

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.

Fig. 6: Http default backend response

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.

 

Leave a Reply

Your email address will not be published. Required fields are marked *

%d bloggers like this: