Cheap Kubernetes single node cluster using VPS and Ubuntu 18.04

Image for post
Image for post

This is a short tutorial showing how to build a small, single node, Kubernetes cluster that runs on a virtual private server (VPS). Perfect for small projects!

Kubernetes is great, it’s the standardized way to deploy containers into a production environment and has great tools to manage and control your entire application. However, getting a cluster from AWS, Azure or DigitalOcean can be expensive for small projects.

The cheapest solution now (08/08/2020) is KubeSail (https://kubesail.com/), they provide a free cluster with several interesting features (like automatically generate services and expose your application)

KubeSail perfect for very small projects or even if you want to study how to play with K8s, but if you have larger projects you may need more computational resources and this article shows a solution!

VPS, or a virtual dedicate server, is basically a virtual machine that you can buy as a service from hosting companies. There are several and here you can see a nice comparison table (https://www.comparevps.com/).

A nice suggestion is Contabo, they have a great deal for 5.0 eur/mo with 4vCPUs, 8 Gb RAM, 300 Gb of SSD and unlimited data transfer. But feel free to choose your preferred VPS 😊

Software versions

***This tutorial uses Ubuntu version 18.04***

***This tutorial uses Docker version 19.03.12***

***This tutorial uses Kubernetes version 1.18.6***

How install a Kubernetes single node cluster

For this part I used Raimund Rittnauer great tutorial (https://raaaimund.github.io/tech/2018/10/23/create-single-node-k8s-cluster/)

1- Install Docker

First we have to download and add the GPG public keys (to ensure we are getting the right official package)

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

Now you have to verify if the added key has the correct fingerprint

sudo apt-key fingerprint 0EBFCD88

You should get an output like this:

Image for post
Image for post

Now we have to add the Docker repository into our sources, we will use add-apt-repository to that, then, first you might have to install software-properties-common :

apt install software-properties-common

And now we can add and update the repository and install Docker:

sudo add-apt-repository "deb [arch=amd64] 
https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"

We must disable the swap memory as Kubernetes as it does not support it:

sudo swapoff -a

sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

Now we will install Kubernetes in a similar fashion as we did with Docker:

sudo apt-get update && sudo apt-get install -y apt-transport-https && curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-key add -

echo "deb http://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee -a /etc/apt/sources.list.d/kubernetes.list && sudo apt-get update

sudo apt install -y kubeadm kubelet kubernetes-cni

Now we will initialize Kubernetes control-plane node. But, before that we must check our server IP, this can be done by:

ip addr show

Your server IP address can be found on the main network adapter (generally eth0 after inet like this:

Image for post
Image for post

Or you can check your IP address by your provider too.

So now we can initialize K8s:

sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=<YOUR_SERVER_IP_ADDRESS>

Then, after some time, you will receive an output like this:

Image for post
Image for post

So you must follow the instructions to create the .kube folder with the configuration file:

mkdir -p $HOME/.kube

Now we must install the networking model for kubernetes:

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/k8s-manifests/kube-flannel-rbac.yml

And finally we must allow our master note to run and manage pods:

kubectl taint nodes --all node-role.kubernetes.io/master-

If you want to control your Kubernetes cluster from your local computer, just copy the conf file content and paste to your local machine:

cat $HOME/.kube/config

Then it will show the configuration file, copy it and then in another terminal in your local machine environment:

sudo gedit ~/.kube/config

Now paste the content from conf of your server and save it. Now (if you have kubectl installed on your computer) you will be able to manage your Kubernetes cluster from your local environment.

Enabling LoadBalancer to application exposure

This Tutorial was based on another tutorial (https://www.youtube.com/watch?v=xYiYIjlAgHY&t=423s) made by the Just me and Opensource YouTube channel

Congrats! Now you have your own Kubernetes cluster! However, one of the most important features is allow your applications be accessed from internet. You can do it with NodePort (I know, for a single node configuration maybe this is a good solution), but I think for practice and simulate a real world production environment is good to use LoadBalancer.

If you use some in cloud Kubernetes service (such the ones in AWS and Azure) the provider will take care of the Load Balancer instances. On the other hand, with a VPS you don’t have this feature, so you must use MetalLB and this tutorial will show you how:

First, just to test, we will create a simple NGINX server:

kubectl run nginx --image nginx

The command above will create a pod with the NGINX server, you can check it with:

kubectl get pods

You will receive something like:

Image for post
Image for post

Now we will try to expose this service to the internet, we can do it by simply:

kubectl expose pod nginx --port 80 --type LoadBalancer

Check now your service created (with additional information):

kubectl get service -o wide

This will output the following:

Image for post
Image for post

The EXTERNAL-IP will hang on <pending> forever as you don’t have a LoadBalancer service set.

To create a LoadBalancer service in our cluster, lets use MetalLB (https://metallb.universe.tf/) and make the installation by Manifest (https://metallb.universe.tf/installation/), following their steps:

kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/namespace.yaml

Now you have to create aConfigMap for the MetalLB namespace, in orther to do that, first modify the file below and replace the address by your cluster IP (yes two times with a trace between them).

apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- <YOUR_IP_ADDRESS>-<YOUR_IP_ADDRESS>

Then, go to the terminal and create the ConfigMap by typing the following:

cat <<EOF | kubectl create -f -
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- <YOUR_IP_ADDRESS>-<YOUR_IP_ADDRESS>
EOF

This will create a ConfigMap for your MetalLB LoadBalancer and, hopefully, your NGINX server will be able to be exposed in your IP address, then check again with:

kubectl get service -o wide

If the EXTERNAL-IP has your IP address, congratulations! You exposed your service through internet using LoadBalancer. Check it by accessing your IP address in the browser, you should get a default NGINX page.

In case your server was not correctly exposed, try to delete and recreate the exposure service by:

kubectl delete service nginx

And that’s all for now! I hope you liked the tutorial and this helped you to create your own (cheap) Kubernetes cluster!

Written by

PhD researcher in Applied Machine Learning. Loves AI, Soft. Development and Dogs

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store