Local kubernetes configuration using k3d on a Mac/Raspberry Pi/Linux

We will setup a local kubernetes cluster using k3d which is a wrapper around another tool called k3s, which is a lightweight Kubernetes distribution designed for resource-constrained environments. The beauty of k3d is that you can spin up a multi-node cluster on your machine with a single command. In our example the cluster will provide a simple website with a hello world message. This will give you the basis to setup any other complex cluster running your application. I tested this with heavy applications and works really well. I wouldn’t use it for a production environment handling a heavy load, but it’s perfect to replicate a production cluster locally for testing or developing purposes.

Prerequisites

Before we start we need to install some basic tools and also I would recommend some other extra, not necessary tools, that will make your like easier like k9s.

I assume you are familiar with the command line interface, if not, check my video here! I also assume you have docker installed and you are familiar with it as well, otherwise check this other video here. Also I assume you have some familiarity with Kubernetes, if not I recommend The Kubernetes Book by Nigel Poulton.

In this video I’m going to use homebrew for Mac and for Linux as well. For those not familiar with it, homebrew is a package manager for macOS and Linux, which will simplify the installation process. In case of Linux some might think “why using another package manager, we already have one for Linux!” that’s true, but installing these tools in Linux without Homebrew require more steps because not all of them are available in the usual repositories. There’s plenty of documentation on how to install them on Linux and at of this post, I left instructions.

If you don’t have Homebrew go to this link and install it. The process is straight forward. Once you have it installed continue here:

brew install k3d kubectl k9s

k9s is not strictly necessary but I really recommend installing it. We will use it in this tutorial, it’s an extremely helpful and handy tool to have. You can do everything k9s does with kubectl but why wasting time when we have a took that makes our life way easier.

Create the registry

Before we create the cluster, it’s not mandatory, but we better create a registry. This will allow us to upload our Docker images similar to a real scenario.

Here I’m using port 5001 because on macOS the port 5000 is already used. You can use any port you want, as long as it’s free to use.

k3d registry create registry --port 5001

Create the cluster

We need to create the cluster first. It will deploy a series of Docker containers that will be responsible to run our cluster. We won’t have to deal with these containers, it’s all managed internally by k3d.

k3d cluster create mycluster -p "8080:80@loadbalancer" --registry-use k3d-registry:5001 --agents 1

With this command we will create a cluster called mycluster

If we type docker ps we can see the containers that run our cluster:

CONTAINER ID   IMAGE                            COMMAND                  CREATED          STATUS          PORTS                                           NAMES
cbdc37d82bab   ghcr.io/k3d-io/k3d-tools:5.8.3   "/app/k3d-tools noop"    54 seconds ago   Up 54 seconds                                                   k3d-mycluster-tools
e45f49af592a   ghcr.io/k3d-io/k3d-proxy:5.8.3   "/bin/sh -c nginx-pr…"   19 hours ago     Up 49 seconds   0.0.0.0:8080->80/tcp, 0.0.0.0:49517->6443/tcp   k3d-mycluster-serverlb
30741d5c522b   rancher/k3s:v1.31.5-k3s1         "/bin/k3d-entrypoint…"   19 hours ago     Up 50 seconds                                                   k3d-mycluster-agent-0
9c641645e023   rancher/k3s:v1.31.5-k3s1         "/bin/k3d-entrypoint…"   19 hours ago     Up 53 seconds                                                   k3d-mycluster-server-0
02da975b678a   registry:2                       "/entrypoint.sh /etc…"   19 hours ago     Up 19 hours     0.0.0.0:5001->5000/tcp                          k3d-myregistry

Create the container application

Let’s create a container application. I have one image available to download, it just presents a Hello World message at port 8000

docker pull pietrozuco/helloworld:basic-latest

Next we need to push this image to our k3d registry:

docker tag pietrozuco/helloworld:basic-latest localhost:5001/helloworld:basic-latest

This will tag our image to point to the local registry. Finally we push it:

docker push localhost:5001/helloworld:basic-latest

To make sure the image is in the local registry we can use a couple of curl commands. The first will list the repository name:

$ curl -X GET http://localhost:5001/v2/_catalog
{"repositories":["helloworld"]}

The second, using that name will output the images:

$ curl -X GET http://localhost:5001/v2/helloworld/tags/list
{"name":"helloworld","tags":["basic-latest"]}

Now we are good to go to create our manifests to deploy the cluster

Deploying the cluster

Make sure our cluster is running

$ k3d cluster list
NAME        SERVERS   AGENTS   LOADBALANCER
mycluster   1/1       1/1      true

We see servers 1/1 and agents 1/1 meaning the cluster is running.

We can check the kubernetes contexts:

$ kubectl config get-contexts
CURRENT   NAME            CLUSTER         AUTHINFO              NAMESPACE
*         k3d-mycluster   k3d-mycluster   admin@k3d-mycluster

In this case we won’t bother to setup a namespace because for testing purposes the default is fine. But k3d is powerful enough to handle almost all kubernetes operations. It’s a great tool for learning and testing.

To deploy we just do the same as if we have a cluster running in the cloud or anywhere else. In this case we use simple manifests, but we can also use helm.

You can download the files from the repository associated to this video and run the following commands inside the repo:

kubectl apply -f k8s/deployment.yaml
kubectl apply -f k8s/service.yaml
kubectl apply -f k8s/ingress.yaml

We can see how the deployment is going by using the command kubectl

$ kubectl get pods
NAME                                     READY   STATUS    RESTARTS   AGE
hello-world-deployment-d678cff85-bjhfk   1/1     Running   0          6s
hello-world-deployment-d678cff85-rbmxq   1/1     Running   0          42s

Two replicas of our web app are running.

We can also check the rest of the configuration:

$ kubectl get svc
NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
hello-world-service   ClusterIP   10.43.120.255   <none>        80/TCP    103s
kubernetes            ClusterIP   10.43.0.1       <none>        443/TCP   2m37s

$ kubectl get ingress
NAME                  CLASS     HOSTS   ADDRESS                 PORTS   AGE
hello-world-ingress   traefik   *       172.20.0.4,172.20.0.5   80      107s

We can try our configuration at localhost:8080 and we should see the message Hello World

Typical commands with k3d which are self explanatory

k3d cluster list
k3d registry list
k3d cluster delete mycluster
k3d registry delete k3d-registry

Linux / Raspberry Pi Installation

k3d has a very good installation documentation, check it here.

k9s can be installed on most distributions, check it here.

Finally kubectl can be installed following the instructions from the kubernetes website

How to Install Python like a Pro

This is how Python is usually installed in a development environment to be used with other developers. This is the way I usually installed it with my teams and the way other developers use it. If you are using Python only for your own projects, then maybe there’s no need to go the extra mile.

We are going to use a command called pyenv, which basically allows you to have multiple versions of Python installed in your system. This is useful because you might clone different projects that were developed using a particular version of Python, so you can run them with the right version.

The instructions here are command line based and for Linux, but they are very similar for macOS as well. This doesn’t cover how to install it on Windows.

I’m going to assume a minimum Linux installation, so you can see exactly all that is required.

I also assume you have some knowledge of the command line interface, if you don’t, then checkout my video about getting from zero to hero with the command line.

Installation

macOS

If you are using macOS just go to brew.sh follow the instructions to install Homebrew, which is a package manager for macOS.
Then run:

brew install pyenv

And that’s pretty much it, pyenv will be installed in your system. Ir order to configure it, you can follow the same instructions at the end of the Linux installation where we talk about configuring the shell init script.

Linux

If you want to save time and you don’t care much about the details, you can run this command:

curl https://pyenv.run | bash

Basically it downloads a script and does the rest for you. I found some issues running it in some systems, so I will go ahead and do the manual part, but if it works for you and that’s all you care, feel free to skip to the next section where we learn how to use pyenv.

Here I’m using Debian, this works on any Debian derivative Linux distribution. For other distributions the process is very similar, just make sure you are using the right package manager:

$ sudo apt-get update
$ sudo apt-get install -y build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm libncurses5-dev xz-utils libncursesw5-dev tk-dev libffi-dev liblzma-dev git

Finally we need to clone pyenv repository. Usually it’s cloned in the home directory, but you can technically clone it anywhere you want:

git clone https://github.com/pyenv/pyenv.git ~/.pyenv

Configuration

This part is common for macOS and Linux. Basically add the following lines to your shell init script. It could be .bashrc or .zshrc depending on which shell you are using.

if [ -d "$HOME/.pyenv" ] ; then
    export PYENV_ROOT="$HOME/.pyenv"
    command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"
    eval "$(pyenv init -)"
fi

That’s it, now when you login again in your machine, you should have fully functional pyenv.

Using pyenv

This part is common for macOS and Linux. At this point, most probably you already have some version of Python installed in your system, but we don’t really care about it at this point because we will manage all of that with pyenv.

$ pyenv versions
$ pyenv versions
* system (set by /home/mc/.pyenv/version)
$

This means that no particular version of Python has been installed. To get a full list of all the versions and flavours of Python that pyenv supports, execute:

pyenv install --list

The list is huge, so let’s just focus for now to install the latest version, that at the time of writing this article the latest version is 3.12.2, just run:

pyenv install 3.12

This will install the latest version of 3.12, in your system. It might take some time depending on how fast is your machine. If you run again:

$ pyenv versions
* system (set by /home/mc/.pyenv/version)
  3.12.2

We can confirm that 3.12.2 has been installed. We want to make it global so we can use it every time we open a terminal. To do that, type:

$ pyenv global 3.12.2

Checking again the versions:

$ pyenv versions
  system
* 3.12.2 (set by /home/mc/.pyenv/version)

The asterisk shows which is the current active version. To confirm that this is really the version of python available, just execute:

$ python --version
Python 3.12.2

This confirms that Python is available and the version that we selected. Go ahead and experiment installing other versions of Python in your system.

Remember to check the other videos in ZUCO.DEV Channel for more.

ZUCO.DEV
Privacy Overview

This website uses cookies so that we can provide you with the best user experience possible. Cookie information is stored in your browser and performs functions such as recognising you when you return to our website and helping our team to understand which sections of the website you find most interesting and useful.