In this post we will setup a 3 node multi-master kubernetes cluster using k3s which is backed with mysql.

I will be installing mariadb on one of my nodes, but if you want to get mysql or mariadb running on docker, you can check out mysql on dockerhub.

Our Setup

Our IP Addresses for our nodes will be:

  • MySQL:
  • Rpi-01:
  • Rpi-02:
  • Rpi-03:


On our database node, i'm installing mariadb server 10.3:

$ sudo apt install mariadb-server-10.3 -y

The initial setup of our database for kubernetes:

$ sudo mysql_secure_password

Then enable the plugin for socket authentication:

$ sudo mysql -u root
> use mysql;
> UPDATE user SET plugin='' WHERE User='root';
> exit;

Now you can auth with your password:

$ mysql -u root -p

Create the k3s database, the rancher user that will own the database and set a password:

> CREATE database k3s;
> CREATE user 'rancher'@'%' IDENTIFIED BY 'password';
> GRANT ALL on k3s.* TO 'rancher'@'%';

> use mysql;
> UPDATE user SET plugin='' WHERE User='rancher';

Edit sudo vim /etc/mysql/mariadb.conf.d/50-server.cnf and comment out bind-address so that mysql listens on all interfaces, then restart:

$ sudo /etc/init.d/mysql restart

our database details for k3s:

user: rancher
pass: password
db: k3s

Setup Kubernetes Nodes

On our first node, install k3s and use the arguments as you prefer, but the important one is to point our database using --datastore-endpoint .

You will notice that I am also using --node-taint k3s-controlplane=true:NoExecute" on all 3 nodes, you can remove that, but I also want to show how you can remove the taints manually from node2 and node3 after the deployment.

$ curl -sfL | INSTALL_K3S_EXEC="--write-kubeconfig-mode 644 --token secret-01010101-xabcdefx --tls-san --node-taint k3s-controlplane=true:NoExecute" sh -s - server --datastore-endpoint="mysql://rancher:password@tcp("

Your kubeconfig will be available at: /etc/rancher/k3s/k3s.yaml

When we list our kubernetes nodes:

$ kubectl get nodes
rpi-01   Ready    master   16s   v1.18.4+k3s1

Do the same for node 2 and node 3, once they have been provisioned, you should see the following:

$ kubectl get nodes
rpi-01   Ready    master   2m30s   v1.18.4+k3s1
rpi-02   Ready    master   41s     v1.18.4+k3s1
rpi-03   Ready    master   25s     v1.18.4+k3s1

Untaint Nodes

As mentioned, all 3 nodes run with NoExecute taints, and now we would like to remove them from node2 and node3 as a demonstration, if you would like to do that.

You can read more up about taints from the documentation

Describe the nodes to view the taints:

$ kubectl describe nodes | grep Taints
Taints:             k3s-controlplane=true:NoExecute
Taints:             k3s-controlplane=true:NoExecute
Taints:             k3s-controlplane=true:NoExecute

Remove taint from node2:

$ kubectl taint nodes rpi-02 k3s-controlplane=true:NoExecute-
node/rpi-02 untainted

And remove from node3:

$ kubectl taint nodes rpi-03 k3s-controlplane=true:NoExecute-
node/rpi-03 untainted

Now when we describe our nodes again:

$ kubectl describe nodes | grep Taints
Taints:             k3s-controlplane=true:NoExecute
Taints:             <none>
Taints:             <none>

Deploy a sample application

To test our cluster, let's deploy a sample web application, which is a basic application that returns it's hostname:

$ wget 

$ kubectl apply -f deployment-green-hostname-rpi.yaml
namespace/color created
deployment.apps/green created
service/green created
ingress.extensions/colors-green created

Once we deployed our application, have a look at the deployment and pods:

$ kubectl get deployment,pod -n color
NAME                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/green   4/4     4            4           2m1s

NAME                         READY   STATUS    RESTARTS   AGE
pod/green-545d49b94b-cxt84   1/1     Running   0          118s
pod/green-545d49b94b-84fdm   1/1     Running   0          117s
pod/green-545d49b94b-gghnf   1/1     Running   0          118s
pod/green-545d49b94b-d5rvf   1/1     Running   0          117s

And our ingress:

$ kubectl get ingress -n color
NAME           CLASS    HOSTS                        ADDRESS         PORTS   AGE
colors-green   <none>    80      2m49s

Make a http request to our application:

$ curl -H ""
Green running on: green-545d49b94b-84fdm

Thank You

Thanks for reading, hope you found it useful.

To view more of my content, have a visit on my website or say hi on Twitter: @ruanbekker