Setting up a single node K3s cluster

When I decided to rebuild my website, I also decided I was done with cheap, crappy web hosting. After some research, and some recommendations, I settled on a cloud VPS from Hetzner. They’re affordable, reliable, offer great support and the servers perform really well. I’ve had no issues in over two years. If you’re in the market for a VPS, dedicated server or cloud storage, I’d recommend them. Check them out here – note, this is a referral link.

Running a VPS rather than using a basic LAMP stack meant a change in approach. I also wanted to get to grips with managing a Kubernetes environment, so I did some reading and settled on K3s, rather than full blown K8s.

K3s is a certified Kubernetes distribution designed for production environments in low resource locations, such as IoT devices. It’s managed and released by SUSE, of chameleon shaped Linux distribution fame, and can be installed alongside Rancher, their Kubernetes management platform.

In this blog post, I’ll walk you through setting up K3s and Rancher on a Hetzner VPS, but it’ll probably apply to any server environment. This blog also assumes you’re running Ubuntu or a similar Linux distro. This is by no means a comprehensive guide on everything K3s, or Rancher. It’s simply meant as a very quick, step by step guide to getting something up and running quickly.

Prerequisites

You’ll first need to set up your VPS in Hetzner / your chosen host (I’ll be using Hetzner from here on out).

Once your server is provisioned and ready, you’ll need to create and SSH key (unless you already created one during provisioning). Follow your hosts documentation to do this.

Installing K3s

Log in via SSH to your new server, and let’s get the installation underway.

ssh -i /path/to/key/id_rsa root@SERVER-IP

Next, we’ll want to make sure everything is up to date before we progress;

apt update && apt upgrade -y

Now, we’re ready to install K3s.

curl -sfL https://get.k3s.io | sh -

Now, lets grab the Kubeconfig file so we can do all the Kubectl things we need to from our local machine.

mkdir ~/.kube
cp /etc/rancher/k3s/k3s.yaml ~/.kube/config

Lastly, lets verify everything is up and running correctly. To do this, we just run;

kubectl get nodes

And this should return something like this;

root@k3s-dev:~# kubectl get nodes
NAME      STATUS   ROLES                  AGE     VERSION
k3s-dev   Ready    control-plane,master   1m13s   v1.30.1+k3s2

Congratulations, you now have a fully operational K3s cluster.

DNS Configuration

If you want to set up a DNS name and hook it all up to Let’s Encrypt for SSL, you’ll need to point your domain’s DNS records at your new VPS. Personally, I use Cloudflare for my DNS, but you can add these to your records via any registrar / DNS provider.

*.apps.YOURDOMAIN.tld -> ServerIP

This will allow you to reach applications running in your K3s cluster.

If you also want to set up Rancher, you’ll also need to add;

rancher.YOURDOMAIN.tld -> ServerIP

Helms Deep

Deploying Rancher is easier via Helm, so we’ll firstly install that. Thankfully, it’s really simple;

curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh

Deploying Rancher

Now, we can deploy Rancher to manage our K3s cluster.

Start by adding the repo

helm repo add rancher-stable https://releases.rancher.com/server-charts/stable

Next, we’ll create a namespace for Rancher. We’ll use the suggested one from SUSE.

kubectl create namespace cattle-system

Next, we’ll install Cert-Manager to manage SSL certificates within the cluster. Note, there are newer versions of cert-manager, but I had a few issues with them. This is the version I got working, but your mileage may vary. Try the latest version first, and step backwards if you have issues.

kubectl apply -f https://github.com/jetstack/cert-manager/releases/download/v1.5.1/cert-manager.crds.yaml

helm repo add jetstack https://charts.jetstack.io

helm repo update

helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --version v1.5.1

Now, assuming your DNS is all configured, we can install Rancher using Helm.

helm install rancher rancher-stable/rancher \
  --namespace cattle-system \
  --set hostname=rancher.YOURDOMAIN.tld \
  --set bootstrapPassword=ADMINPASSWORD

And, finally, lets verify the install;

kubectl -n cattle-system rollout status deploy/rancher

Next, we need to allow our ingress controller to communicate to our host on ports 80 and 433, so in a text editor, create a file called traefik.yml, and paste in the following;

apiVersion: v1
kind: Service
metadata:
  name: traefik
  namespace: kube-system
spec:
  type: LoadBalancer

And then apply it via Kubectl;

kubectl apply -f traefik.yml

Now, if all went to plan, you should be able to access Rancher at https://rancher.yourdomain.tld

Wrapping up

You now have a fully functioning, single node K3s cluster and Rancher to manage it. Via Rancher, you can create deployments & services, install applications, and more. You can check out the getting started docs here: https://ranchermanager.docs.rancher.com/how-to-guides/new-user-guides