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á unpodcon la aplicaciónletschatcon 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ónletschatpueda conectar con la base de datos. -
ingress: añadirá el componenteingresspara 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:
