Fresh off the lab

The only difference between science and screwing around is writing it down

Kubernetes – Exposing services

In Part 3 of the “Migrating a Django app to Kubernetes” I’ve written a Helm chart to run a Django application and a few corollary services on Kubernetes, but aside from port-forwarding, it’s still stuck “inside” the box.

Time to let it out.

Kubernetes keeps applications inside of itself by default, there are a few different ways to expose them.

LoadBalancer

Load Balancers expose applications with their own IP.
Unfortunately most loadbalancers are external services that run in the cloud, and it seems like “on-prem” Kubernetes clusters are kinda B-class citizens.

Luckily, we have MetalLb

When installed as a microk8s addon, it prompts to give it one or more address ranges to assign IPs from.

I gave it the range of 192.168.1.50-192.168.1.70, and the install script did the rest.

Let’s start by exposing the dashboard on its own address.

apiVersion: v1
metadata:
  name: kube-dash-lb
  namespace: kube-system
kind: Service
spec:
  ports:
  - port: 443
    protocol: TCP
    targetPort: 8443
  selector:
    k8s-app: kubernetes-dashboard
  type: LoadBalancer

Apply with kubectl apply -f <file>, then check the service status with kubectl -n kube-system get services

NAME         TYPE         CLUSTER-IP    EXTERNAL-IP  PORT(S)       AGE
kube-dash-lb LoadBalancer 10.152.183.63 192.168.1.52 443:30114/TCP 10s

Now our dashboard is exposed on https://192.168.1.52


This is nice and everything, but what if we don’t have as many addresses as the services we want to expose? Afterall, virtual hosts have been a thing since at least 1999

Ingress

An API object that manages external access to the services in a cluster, typically HTTP.
Ingress may provide load balancing, SSL termination and name-based virtual hosting.

Kubernetes documentation

Unfortunately Kubernetes does not have a native, standard Ingress, so we’re going to need an:

Ingress controller

In this case we’re going to use Træfik Proxy, because I have previous experience with it on Docker. There’s a number of other controllers that you can use instead of the one I’m going with.

Installation is just another Helm chart, for a simple matter of keeping things organised we’ll deploy it in its own namespace

microk8s kubectl create namespace traefik
microk8s helm repo add traefik https://traefik.github.io/charts
microk8s helm install -n traefik traefik traefik/traefik

Check that it’s assigned an IP address from the LoadBalancer

NAME      TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)        AGE
traefik   LoadBalancer   10.152.183.53   192.168.1.53   443:32020/TCP  13m

And then let’s re-deploy our Helm chart after setting

ingress:
  enabled: true
  hosts:
    - host: metamonitor.k8s
      paths:
        - path: /
          pathType: ImplementationSpecific

Moments later, Kubernetes is happy

And so is Traefik, on the dashboard

After adding “metamonitor.k8s” to our DNS server (or adding it to localhost file) we can finally visit the page


To recap:

  • a Container runs a process
  • a Pod is a set of Containers
  • managed by a ReplicaSet
  • spawned by a Deployment
  • a Service matches a certain subset of Pods and creates a hostname inside the cluster
  • while an Ingress is an external-facing service-equivalent served by an Ingress Controller
  • an Ingress Controller is comprised of one or more Pods interacting with the Kubernetes API to discover Ingresses
  • they each expose one or more Services
  • which are assigned an IP by a Load Balancer

Makes total sense, right?
…right?


Posted

in

,

by

Tags: