Tener dos nodos master no va a dotar a nuestra infraestructura de mas velocidad o capacidad de ejecutar pods, sin embargo si nos va a permitir tener una tolerancia a fallos en uno de los nodos maestros bien sea por un fallo hardware, un bug en el software o simplemente una actualización. Por lo tanto la decisión depende del numero de Raspberrys que tengamos; para un despliegue en HA recomendaría un mínimo de 4 placas: dos que harían las veces de master y las dos restantes de workers. ¿Podríamos tener solo un worker? definitivamente si, ya que podríamos activar la opción de ejecutar pods también en los nodos master como ya veremos más adelante, pero personalmente no me parece una buena idea.
Instalación
Primero voy a detallar la instalación de los Master Nodes ya sea como Single Master o bien en High Availability. El despliegue de los Workers Nodes sería común a ambos entornos.
Single Master
La estructura de ésta instalación sería la que podemos ver a continuación:

Los elementos que constituyen la instalación son:
- K3sUser: Es nuestro servidor o portátil donde tenemos instalado kubectl, que es la utilidad de Kubernetes para gestionar el cluster por línea de comandos.
- SQLite: Es la base de datos donde se almacenan todos los datos del cluster, está embebida en el propio nodo. Ésta será la gran diferencia con la instalación en HA.
- Agent Nodes: O workers, donde vamos a ejecutar nuestros amplicativos
- Load Balancer: En base a la carga del cluster, decide a que nodo nuestra petición.
- External Traffic: Poco que añadir, es nuestra petición que realizamos al cluster.
Asuminendo que ya estamos dentro del nodo seleccionado, seguimos los siguientes pasos:
Establecer las variables de entorno
$ export K3S_KUBECONFIG_MODE="644" $ export INSTALL_K3S_EXEC=" --no-deploy servicelb --disable traefik"
La primera linea nos permite manejar el cluster sin ser usuario root. La segunda necesita una pequeña explicación; por defecto, K3s despliega un Load Balancer y un Proxy propio llamados servicelb y traefik. En su momento me encontré con bastantes problemas para hacerlo funcionar con mis pods, por lo que decidí utilizar metalb como Load Balancer y el más que conocido Nginx como Proxy. Mediante esos flags, evitamos que se instalen esos servicios por defecto, para poder instalar después de manera manual metalb y nginx.
Ejecutar el instalador
Simple y directo, una sola línea y él se encarga de todo.
$ curl -sfL https://get.k3s.io | sh - [INFO] Finding latest release [INFO] Using v1.18.3+k3s as release [INFO] Downloading hash https://github.com/rancher/k3s/releases/download/v1.18.3+k3s/sha256sum-arm.txt [INFO] Downloading binary https://github.com/rancher/k3s/releases/download/1.18.3+k3s/k3s-armhf [INFO] Verifying binary download [INFO] Installing k3s to /usr/local/bin/k3s [INFO] Creating /usr/local/bin/kubectl symlink to k3s [INFO] Creating /usr/local/bin/crictl symlink to k3s [INFO] Creating /usr/local/bin/ctr symlink to k3s [INFO] Creating killall script /usr/local/bin/k3s-killall.sh [INFO] Creating uninstall script /usr/local/bin/k3s-uninstall.sh [INFO] env: Creating environment file /etc/systemd/system/k3s.service.env [INFO] systemd: Creating service file /etc/systemd/system/k3s.service [INFO] systemd: Enabling k3s unit Created symlink /etc/systemd/system/multi-user.target.wants/k3s.service → /etc/systemd/system/k3s.service. [INFO] systemd: Starting k3s
Verificar la instalación
El instalador crea un servicio que se puede usar para iniciar, parar, reiniciar y verificar su estado actual:
pi@noldork3sM:~ $ sudo systemctl status k3s
● k3s.service - Lightweight Kubernetes
Loaded: loaded (/etc/systemd/system/k3s.service; enabled; vendor preset: enab
Active: active (running) since Sat 2020-07-04 17:16:24 CEST; 4h 16min ago
Docs: https://k3s.io
Process: 25865 ExecStartPre=/sbin/modprobe br_netfilter (code=exited, status=0
Process: 25866 ExecStartPre=/sbin/modprobe overlay (code=exited, status=0/SUCC
Main PID: 25867 (k3s-server)
Tasks: 15
Memory: 124.2M
(...)
Igualmente, el instalador despliega el Kubernetes Command Line Tools kubectl, para que podemos interactuar con el cluster:
pi@noldork3sM:~ $ kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP noldork3sm Ready master 5m v1.18.3+k3s1 192.168.1.245
También podemos ver los pods que se han desplegado con la instalación:
$ kubectl get pods -A -o wide NAMESPACE NAME READY STATUS kube-system metrics-server-7566d596c8-rgwgm 1/1 Running kube-system local-path-provisioner-6d59f47c7-xh6t5 1/1 Running kube-system coredns-8655855d6-pkxmp 1/1 Running
Alta Disponibilidad (HA)
Nuestra instalación en este caso, tendría la siguiente estructura:

Las diferencias notables entre ésta instalación y la anterior son dos: la primera es que contamos con un o varios nodos que actúan como masters y la segunda, y más importante, es que la base de datos para a ser una base de datos externa.
Por lo tanto, si optamos por opción, deberemos tener lista otra raspberry (o placa arm por continuar con la misma arquitectura) externa donde se pueda ejecutar nuestro servidor de base de datos.
Una vez tengamos el servidor de base de datos listo, creamos nuestra base de datos, usuario y contraseña mediante los siguientes comandos :
mysql> CREATE database <database>; mysql> CREATE USER <user>'@'%' IDENTIFIED BY '<password>'; mysql> GRANT ALL ON <database>.* TO '<user>'@'%'; mysql> flush privileges;
Ahora solo nos resta continuar con los siguientes pasos que deberemos ejecutar en todos los nodos que vayan a ser Master, y que como veréis son prácticamente los mismos que la instalación Single Master :
Establecer las variables de entorno
$ NODE_TOKEN=$(echo $(hostname) $(date +%s) | shasum | base64)
$ export K3S_KUBECONFIG_MODE="644"
$ export INSTALL_K3S_EXEC=" -t ${NODE_TOKEN} --tls-san <hostname> --no-deploy servicelb --disable traefik --node-taint k3s-controlplane=true:NoExecute --datastore-endpoint mysql://<dbuser>:<dbpassword>@tcp(<dbhostname>:3306)/<database>"
La primera linea no es una diferencia como tal, ya que la vamos a usar también en una instalación Single Master cuando vayamos a añadir los workers. Sin embargo, en esta modalidad, vamos a utilizar mas de un Master Node por lo que necesitamos este token para crear nuestro cluster. Apuntar bien el valor de esa variable puesto que la necesitaremos más adelante, para ello ejecutamos este comando:
$ echo $NODE_TOKEN
La segunda línea es común a la instalación anterior. Sin embargo en la tercera línea si encontramos diferencias:
- –tls-san <hostname> / <ip>: es necesaria para evitar errores de certificados en la configuración del cluster. Debemos especificar el hostname o la ip de nuestro nodo master.
- –node-taint k3s-controlplane=true:NoExecute: esta opción es opcional, de hecho, la podríamos especificar también en una instalación Single Node . Nos sirve para evitar que los pods se ejecuten en nuestro nodo Master, lo que es muy util si nuestras placas no tienen suficiente potencia.
- –datastore-endpoint mysql://<dbuser>:<dbpassword>@tcp(<dbhostname>:3306)/: es quizás la más importante de todas y la clave de todo. Estamos especificando el usuario, contraseña y hostname/ip de nuestro servidor donde se ejecuta nuestra base de datos, en este ejemplo MYSQL
Ejecutar el instalador
Exactamente igual que con un solo master node:
$ curl -sfL https://get.k3s.io | sh - [INFO] Finding latest release [INFO] Using v1.18.3+k3s as release [INFO] Downloading hash https://github.com/rancher/k3s/releases/download/v1.18.3+k3s/sha256sum-arm.txt [INFO] Downloading binary https://github.com/rancher/k3s/releases/download/1.18.3+k3s/k3s-armhf [INFO] Verifying binary download [INFO] Installing k3s to /usr/local/bin/k3s [INFO] Creating /usr/local/bin/kubectl symlink to k3s [INFO] Creating /usr/local/bin/crictl symlink to k3s [INFO] Creating /usr/local/bin/ctr symlink to k3s [INFO] Creating killall script /usr/local/bin/k3s-killall.sh [INFO] Creating uninstall script /usr/local/bin/k3s-uninstall.sh [INFO] env: Creating environment file /etc/systemd/system/k3s.service.env [INFO] systemd: Creating service file /etc/systemd/system/k3s.service [INFO] systemd: Enabling k3s unit Created symlink /etc/systemd/system/multi-user.target.wants/k3s.service → /etc/systemd/system/k3s.service. [INFO] systemd: Starting k3s
Una vez estén listos todos los Master Nodes podemos comprobar su estado mediante el comando kubectl:
pi@noldork3sM:~ $ kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP noldork3sm Ready master 5m v1.18.3+k3s1 192.168.1.245 noldork3sm2 Ready master 5m v1.18.3+k3s1 192.168.1.246
Workers Nodes
La instalación de los Workers Nodes es igual en ambos entornos, y consta de los siguientes pasos:
Establecer las variables de entorno
$ export K3S_KUBECONFIG_MODE="644" $ export K3S_URL="https://ip_master_node:6443" $ export K3s_TOKEN=<token_master_node>
Recordar el token del Master Node que obtuvimos anteriormente. Si por lo que sea lo hemos perdido, podemos recuperarlo entrando por ssh en cualquiera de los Master Nodes ejecutando el siguiente comando:
$ sudo cat /var/lib/rancher/k3s/server/node-token
Ejecutar el instalador
Como veréis es igual que con los Master Nodes:
$ curl -sfL https://get.k3s.io | sh - [INFO] Finding latest release [INFO] Using v1.18.3+k3s as release [INFO] Downloading hash https://github.com/rancher/k3s/releases/download/v1.18.3+k3s/sha256sum-arm.txt [INFO] Downloading binary https://github.com/rancher/k3s/releases/download/1.18.3+k3s/k3s-armhf [INFO] Verifying binary download [INFO] Installing k3s to /usr/local/bin/k3s [INFO] Creating /usr/local/bin/kubectl symlink to k3s [INFO] Creating /usr/local/bin/crictl symlink to k3s [INFO] Creating /usr/local/bin/ctr symlink to k3s [INFO] Creating killall script /usr/local/bin/k3s-killall.sh [INFO] Creating uninstall script /usr/local/bin/k3s-uninstall.sh [INFO] env: Creating environment file /etc/systemd/system/k3s.service.env [INFO] systemd: Creating service file /etc/systemd/system/k3s.service [INFO] systemd: Enabling k3s unit Created symlink /etc/systemd/system/multi-user.target.wants/k3s.service → /etc/systemd/system/k3s.service. [INFO] systemd: Starting k3s
Una vez hecho en todos nuestros workers, podemos comprobar el estado de nuestro cluster:
pi@noldork3sM:~ $ kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION noldork3sn1 Ready <none> 3d21h v1.18.2+k3s1 noldork3sm2 Ready master 3d21h v1.18.2+k3s1 noldork3sm Ready master 3d22h v1.18.2+k3s1 noldork3sn3 Ready <none> 3d21h v1.18.2+k3s1
Como podeis observar tenemos nuestro cluster activo, con dos Master Nodes y dos Worker Nodes. Veréis que éstos últimos no tienen un rol asignado, no es preocupéis, es normal.
Accediendo al cluster de manera remota.
Para acceder a nuestro cluster, o gestionarlo, no es necesario acceder a cualquiera de los nodos, podemos hacerlo desde cualquier sistema Linux, OSx o Windows. Para ello solamente tenemos que instalar la herramienta kubectl, que ya viene instalada en nuestro cluster. Después solo tendremos que copiar el fichero de configuración de nuestro cluster a la maquina.
- Instalar kubectl en nuestra máquina
Solamente tenéis que leer y seguir los pasos descritos en documentación oficial para instalarla en cualquier entorno.
- Copiar el fichero de configuración de nuestro nodo master a nuestra máquina
Mediante el comando scp podemos copiar información desde una maquina a otra por ssh. De ésta manera, podremos descargar el fichero /etc/rancher/k3s/k3s.yaml de nuestro nodo master a nuestra máquina local, en el path ~/.kube/config.
scp i5js@nanoserver:/etc/rancher/k3s/k3s.yaml ~/.kube/config
Ahora solo tenemos que editarlo y cambiar la dirección ip que es 127.0.0.1 por la ip de nuestro nodo master, en mi caso 192.168.1.240. Podemos hacerlo mediante el editor que mas cómodo os resulte o bien, mediante el comando sed:
sed -i '' 's/127\.0\.0\.1/192\.168\.1\.240/g' ~/.kube/config
- Probar
kubectldesde nuestra máquina local
i5js@nanoserver:~ $ kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION noldork3sn1 Ready <none> 3d21h v1.18.2+k3s1 noldork3sm2 Ready master 3d21h v1.18.2+k3s1 noldork3sm Ready master 3d22h v1.18.2+k3s1 noldork3sn3 Ready <none> 3d21h v1.18.2+k3s1
