Introducción
Buenas, en este post vamos a desplegar un cluster sencillo de kubernetes con la herramienta k3s
, tendremos un nodo controller
y dos worker
y la gestión del cluster la haremos desde nuestra máquina anfitriona.
Escenario
El escenario que haremos será sencillo como ya hemos dicho anteriormente, usaremos vagrant
para hacer las tres máquinas con libvirt
, el fichero Vagrantfile
es el siguiente:
Vagrant.configure("2") do |config|
config.vm.define :controller do |controller|
controller.vm.box = "generic/debian10"
controller.vm.hostname = "controller"
controller.vm.synced_folder ".", "/vagrant", disabled: true
controller.vm.provider :libvirt do |libvirt|
libvirt.uri = 'qemu+unix:///system'
libvirt.host = "debian"
libvirt.cpus = 1
libvirt.memory = 1024
end
end
config.vm.define :worker1 do |worker1|
worker1.vm.box = "generic/debian10"
worker1.vm.hostname = "worker1"
worker1.vm.synced_folder ".", "/vagrant", disabled: true
worker1.vm.provider :libvirt do |libvirt|
libvirt.uri = 'qemu+unix:///system'
libvirt.host = "debian"
libvirt.cpus = 1
libvirt.memory = 1024
end
end
config.vm.define :worker2 do |worker2|
worker2.vm.box = "generic/debian10"
worker2.vm.hostname = "worker2"
worker2.vm.synced_folder ".", "/vagrant", disabled: true
worker2.vm.provider :libvirt do |libvirt|
libvirt.uri = 'qemu+unix:///system'
libvirt.host = "debian"
libvirt.cpus = 1
libvirt.memory = 1024
end
end
end
Para arrancar el escenario:
vagrant up
Instalación de k3s en controller
Una vez arrancado el escenario, entramos en el nodo controller
:
vagrant ssh controller
Y ejecutaremos el siguiente comando para que se haga la instalación automática de k3s
curl -sfL https://get.k3s.io | sh -
Aparte de k3s
, también se han instalado las siguiente utilidades:
- kubectl
- crictl
- k3s-killall.sh
- k3s-uninstall.sh
Una vez instalado, podremos obtener información de los nodos:
sudo kubectl get nodes
NAME STATUS ROLES AGE VERSION
controller Ready control-plane,master 20m v1.20.4+k3s1
Parámetros necesarios para workers
Para hacer la instalación en los workers, necesitaremos dos parámetros de nuestro controller
:
-
La dirección ip
INTERNAL-IP
:sudo kubectl get nodes -o wide NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME controller Ready control-plane,master 71m v1.20.4+k3s1 192.168.121.22 <none> Debian GNU/Linux 10 (buster) 4.19.0-14-amd64 containerd://1.4.3-k3s3
-
El token que genera
k3s
, alojado en:sudo cat /var/lib/rancher/k3s/server/node-token K105bb06e0ec50dae9f73cc17c3181f8c003a9cb915fbc40adcd8364e027b61c50b::server:5b5a5f9c0b7cda8d05350fbd52e5b712
Una vez obtenidos los dos parámetros, pasaremos a la instalación en los dos worker
Instalación k3s en workers
La instalación será de igual forma para las dos máquinas, primero declaramos las variables obtenidas del controller
, siendo la primera la dirección url y el puerto usado por defecto por k3s
:
k3s_url="https://192.168.121.22:6443"
k3s_token="K105bb06e0ec50dae9f73cc17c3181f8c003a9cb915fbc40adcd8364e027b61c50b::server:5b5a5f9c0b7cda8d05350fbd52e5b712"
Ahora procedemos a la instalación con el script proporcionado por k3s
:
curl -sfL https://get.k3s.io | K3S_URL=${k3s_url} K3S_TOKEN=${k3s_token} sh
...
[INFO] systemd: Starting k3s-agent
Una vez realizado en los dos workers, si vamos al nodo controller y obtenemos los nodos:
sudo kubectl get nodes
NAME STATUS ROLES AGE VERSION
controller Ready control-plane,master 28m v1.20.4+k3s1
worker1 Ready <none> 22m v1.20.4+k3s1
worker2 Ready <none> 20m v1.20.4+k3s1
Gestión del cluster desde máquina anfitriona
Para poder gestionar el cluster desde nuestra máquina, tendremos que irnos al controller
y copiar el siguiente fichero:
sudo cat /etc/rancher/k3s/k3s.yaml
apiVersion: v1
clusters:
- cluster:
certificate-authority-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkekNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdGMyVnkKZG1WeUxXTmhRREUyTVRRNE56a3lNakl3SGhjTk1qRXdNekEwTVRjek16UXlXaGNOTXpFd016QXlNVGN6TXpReQpXakFqTVNFd0h3WURWUVFEREJock0zTXRjMlZ5ZG1WeUxXTmhRREUyTVRRNE56a3lNakl3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFUWUNsVE1abFhaSm1PR2U3WlJhd09EbE12NFkzL2RpcXFWazBjNVlDUm4KM2dlNXhRb2xjdXFUMlVXLzJ0SmwraWp3M1k4Q3Q0Z2ptWS92TGczSkNvR1ZvMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVTV0N0ZnOFkrTU9IOW1HZ3ppTS9MCjZDNkhGWEV3Q2dZSUtvWkl6ajBFQXdJRFNBQXdSUUlnVXpNS3EzMHp1STRGbXBaeGg1WjZFS1NiWEpyYmlzUWMKcm04akZQRVo0b0lDSVFDNXFDaTAzbjZuVnMrdndpZWJ2RHhsZmYxV3ZLaFVwRy9yWlB2VlNpMDk3UT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0K
server: https://127.0.0.1:6443
name: default
contexts:
- context:
cluster: default
user: default
name: default
current-context: default
kind: Config
preferences: {}
users:
- name: default
user:
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJrVENDQVRlZ0F3SUJBZ0lJWUpUcTNmTk0raDh3Q2dZSUtvWkl6ajBFQXdJd0l6RWhNQjhHQTFVRUF3d1kKYXpOekxXTnNhV1Z1ZEMxallVQXhOakUwT0RjNU1qSXlNQjRYRFRJeE1ETXdOREUzTXpNME1sb1hEVEl5TURNdwpOREUzTXpNME1sb3dNREVYTUJVR0ExVUVDaE1PYzNsemRHVnRPbTFoYzNSbGNuTXhGVEFUQmdOVkJBTVRESE41CmMzUmxiVHBoWkcxcGJqQlpNQk1HQnlxR1NNNDlBZ0VHQ0NxR1NNNDlBd0VIQTBJQUJEaW9Oa1UzOGt0Mmg0dzQKL3VYRVVkZHMxT0VrZ0ZWeUEvTHpGa0xXc2Z3NGxRK08yUFRsOWJaclBXZFM1bGdyUlg5Wmk2aEtWVjNVZkZ6NQo2c3pqWkFtalNEQkdNQTRHQTFVZER3RUIvd1FFQXdJRm9EQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFmCkJnTlZIU01FR0RBV2dCUnczSXhBQjdvVFZIUUpPQUtmNG04RDlTTzI1ekFLQmdncWhrak9QUVFEQWdOSUFEQkYKQWlBVk5HZEpyOFcxank0RVYxVFpncDQzN0s4NDlYMVZPeGNWeDN2TFZ1eThOQUloQU5NeHA3dFVUQzlnV1ZkKwpuTWtrZFFwbm1va0tmdVdJSGdMWTRaRGlUZ1l6Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0KLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUJkakNDQVIyZ0F3SUJBZ0lCQURBS0JnZ3Foa2pPUFFRREFqQWpNU0V3SHdZRFZRUUREQmhyTTNNdFkyeHAKWlc1MExXTmhRREUyTVRRNE56a3lNakl3SGhjTk1qRXdNekEwTVRjek16UXlXaGNOTXpFd016QXlNVGN6TXpReQpXakFqTVNFd0h3WURWUVFEREJock0zTXRZMnhwWlc1MExXTmhRREUyTVRRNE56a3lNakl3V1RBVEJnY3Foa2pPClBRSUJCZ2dxaGtqT1BRTUJCd05DQUFSc0kyV2pMTmliTk1oVENwTE5rZ1JPZVhjZU5iVXNzQXFNNGNHcWtDMm8KaWIzTk5WMlpaRWFFT2JzRlhoa1pKU0tpbEFVZkhNSk1RQUx3OGxxdFdsWm9vMEl3UURBT0JnTlZIUThCQWY4RQpCQU1DQXFRd0R3WURWUjBUQVFIL0JBVXdBd0VCL3pBZEJnTlZIUTRFRmdRVWNOeU1RQWU2RTFSMENUZ0NuK0p2CkEvVWp0dWN3Q2dZSUtvWkl6ajBFQXdJRFJ3QXdSQUlnTDBtd0FwT3RzQi82QkVYckphekxlK0g5Y2h2ZXF0SWsKVUF2MlFuSjBEWWNDSUYzUitwaHpQeW9ySVRIREV3OUp5ZnZPK3hucWtWWFpHLzhud3VDTHpYMHcKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
client-key-data: LS0tLS1CRUdJTiBFQyBQUklWQVRFIEtFWS0tLS0tCk1IY0NBUUVFSUcyMmJDeHZlbFZRbW5XeXVMbndhcXlBclhjR0FwWXVhZkc0dUlxWmRBekJvQW9HQ0NxR1NNNDkKQXdFSG9VUURRZ0FFT0tnMlJUZnlTM2FIakRqKzVjUlIxMnpVNFNTQVZYSUQ4dk1XUXRheC9EaVZENDdZOU9YMQp0bXM5WjFMbVdDdEZmMW1McUVwVlhkUjhYUG5xek9Oa0NRPT0KLS0tLS1FTkQgRUMgUFJJVkFURSBLRVktLS0tLQo=
Ahora en nuestra máquina anfitriona, ya instalado kubectl
previamente, si no lo tenemos instalado, instalamos:
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl
Copiaremos el fichero a la siguiente ruta, no sin antes cambiar la ip, poniendo la ip de nuestro controller
:
~/.kube/config
Ahora, cargamos el fichero con las credenciales:
export KUBECONFIG=~/.kube/config
Y comprobamos que podemos obtener los nodos:
kubectl get nodes
NAME STATUS ROLES AGE VERSION
worker2 Ready <none> 29m v1.20.4+k3s1
controller Ready control-plane,master 37m v1.20.4+k3s1
worker1 Ready <none> 31m v1.20.4+k3s1
Despliegue Letschat
A continuación haremos el despliegue de la aplicación de Letschat. Para ello, tenemos clonado este repositorio, el cuál tiene bastantes ejemplos y utilización de kubectl
Para el despliegue, nos iremos a la siguiente ruta:
kubernetes-storm/unidad3/ejemplos-3.2/ejemplo8/
Y ejecutamos:
kubectl apply -f .
Warning: networking.k8s.io/v1beta1 Ingress is deprecated in v1.19+, unavailable in v1.22+; use
networking.k8s.io/v1 Ingress
ingress.networking.k8s.io/ingress-letschat created
deployment.apps/letschat created
service/letschat created
deployment.apps/mongo created
service/mongo created
Cada fichero desplegará lo siguiente:
-
letschat-deployment
: desplegará unpod
con la aplicaciónletschat
con una replica. -
mongo-deployment
: desplegará la base de datos necesaria para poder ejecutarletschat
. -
letschat-srv
: desplegará el servicio para que la base de datos pueda conectar conletschat
. -
mongo-srv
: desplegará el servicio para que la aplicaciónletschat
pueda conectar con la base de datos. -
ingress
: añadirá el componenteingress
para que se pueda acceder a la aplicación mediante un nombre.
Empezarán a crearse los desliegues:
kubectl get all,ingress
NAME READY STATUS RESTARTS AGE
pod/letschat-7c66bd64f5-wcbkn 0/1 ContainerCreating 0 11s
pod/mongo-5c694c878b-qjtfj 0/1 ContainerCreating 0 11s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 43m
service/letschat NodePort 10.43.43.122 <none> 8080:30437/TCP 11s
service/mongo ClusterIP 10.43.255.141 <none> 27017/TCP 10s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/letschat 0/1 1 0 11s
deployment.apps/mongo 0/1 1 0 11s
NAME DESIRED CURRENT READY AGE
replicaset.apps/letschat-7c66bd64f5 1 1 0 11s
replicaset.apps/mongo-5c694c878b 1 1 0 11s
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress.networking.k8s.io/ingress-letschat <none> www.letschat.com 192.168.121.213 80 11s
Y pasados unos segundos, todo estará listo:
kubectl get all,ingress
NAME READY STATUS RESTARTS AGE
pod/mongo-5c694c878b-qjtfj 1/1 Running 0 30s
pod/letschat-7c66bd64f5-wcbkn 1/1 Running 1 30s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 43m
service/letschat NodePort 10.43.43.122 <none> 8080:30437/TCP 30s
service/mongo ClusterIP 10.43.255.141 <none> 27017/TCP 29s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/mongo 1/1 1 1 30s
deployment.apps/letschat 1/1 1 1 30s
NAME DESIRED CURRENT READY AGE
replicaset.apps/mongo-5c694c878b 1 1 1 30s
replicaset.apps/letschat-7c66bd64f5 1 1 1 30s
NAME CLASS HOSTS ADDRESS PORTS AGE
ingress.networking.k8s.io/ingress-letschat <none> www.letschat.com 192.168.121.213 80 30s
Escalado
Para comprobar que funciona el escalado, bastaría con ejecutar lo siguiente:
kubectl scale deployment letschat --replicas=10
Y comprobamos que se empezarán a escalar las réplicas deseadas:
kubectl get all
NAME READY STATUS RESTARTS AGE
pod/mongo-5c694c878b-qjtfj 1/1 Running 0 17m
pod/letschat-7c66bd64f5-wcbkn 1/1 Running 1 17m
pod/letschat-7c66bd64f5-fqzsv 0/1 ContainerCreating 0 12s
pod/letschat-7c66bd64f5-9brf8 0/1 ContainerCreating 0 12s
pod/letschat-7c66bd64f5-4lncv 0/1 ContainerCreating 0 12s
pod/letschat-7c66bd64f5-wsrbg 0/1 ContainerCreating 0 12s
pod/letschat-7c66bd64f5-mlkfh 0/1 ContainerCreating 0 12s
pod/letschat-7c66bd64f5-cpv4w 1/1 Running 0 12s
pod/letschat-7c66bd64f5-6242w 1/1 Running 0 12s
pod/letschat-7c66bd64f5-p59vr 1/1 Running 0 12s
pod/letschat-7c66bd64f5-q2sdf 1/1 Running 0 12s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 60m
service/letschat NodePort 10.43.43.122 <none> 8080:30437/TCP 17m
service/mongo ClusterIP 10.43.255.141 <none> 27017/TCP 17m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/mongo 1/1 1 1 17m
deployment.apps/letschat 5/10 10 5 17m
NAME DESIRED CURRENT READY AGE
replicaset.apps/mongo-5c694c878b 1 1 1 17m
replicaset.apps/letschat-7c66bd64f5 10 10 5 17m
Y si volvemos a comprobar al cabo de unos segundos:
kubectl get all
NAME READY STATUS RESTARTS AGE
pod/mongo-5c694c878b-qjtfj 1/1 Running 0 19m
pod/letschat-7c66bd64f5-wcbkn 1/1 Running 1 19m
pod/letschat-7c66bd64f5-cpv4w 1/1 Running 0 94s
pod/letschat-7c66bd64f5-6242w 1/1 Running 0 94s
pod/letschat-7c66bd64f5-p59vr 1/1 Running 0 94s
pod/letschat-7c66bd64f5-q2sdf 1/1 Running 0 94s
pod/letschat-7c66bd64f5-4lncv 1/1 Running 0 94s
pod/letschat-7c66bd64f5-wsrbg 1/1 Running 0 94s
pod/letschat-7c66bd64f5-9brf8 1/1 Running 0 94s
pod/letschat-7c66bd64f5-mlkfh 1/1 Running 0 94s
pod/letschat-7c66bd64f5-fqzsv 1/1 Running 0 94s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.43.0.1 <none> 443/TCP 62m
service/letschat NodePort 10.43.43.122 <none> 8080:30437/TCP 19m
service/mongo ClusterIP 10.43.255.141 <none> 27017/TCP 19m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/mongo 1/1 1 1 19m
deployment.apps/letschat 10/10 10 10 19m
NAME DESIRED CURRENT READY AGE
replicaset.apps/mongo-5c694c878b 1 1 1 19m
replicaset.apps/letschat-7c66bd64f5 10 10 10 19m
Componente ingress
Para comprobar que está funcionando el componente ingress
, vamos a acceder a la página a través de nuestro navegador, no sin antes añadir a nuestro fichero:
/etc/hosts
La siguiente línea:
192.168.121.22 www.letschat.com
Y comprobamos: