Despliegue de una aplicación en Kubernetes
Introducción
En este post realizamos la implantación de una aplicación en Docker. En este post vamos a realizar el despliegue de la misma aplicación en Kubernetes.
Ejercicio 1: Despliegue en minikube
En mi casi caso, voy a elegir bookmedik como aplicación a desplegar. Para ello, voy a utilizar el siguiente repositorio que contiene el código de la aplicación.
Despliegue de la aplicación
- Creamos los ficheros yaml para crear un
ConfigMap
y unSecret
donde guardaremos las variables de entorno.
kubectl create cm cm-mariadb --from-literal=mysql_usuario=bookmedik \
--from-literal=basededatos=bookmedik \
-o yaml --dry-run=client > bd_datos_configmap.yaml
kubectl create secret generic secret-mariadb --from-literal=password=bookmedik \
--from-literal=rootpass=root \
-o yaml --dry-run=client > bd_passwords_secret.yaml
Creamos el volumen y el fichero de despliegue para mariadb
- Volumen para mariadb
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mariadb-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
- Despliegue de mariadb
apiVersion: apps/v1
kind: Deployment
metadata:
name: mariadb
labels:
app: mariadb
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: mariadb
tier: backend
template:
metadata:
labels:
app: mariadb
tier: backend
spec:
volumes:
- name: volumen-mariadb
persistentVolumeClaim:
claimName: mariadb-pvc
containers:
- name: contenedor-mariadb
image: mariadb:10.5
env:
- name: MARIADB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: secret-mariadb
key: rootpass
- name: MARIADB_DATABASE
valueFrom:
configMapKeyRef:
name: cm-mariadb
key: basededatos
- name: MARIADB_USER
valueFrom:
configMapKeyRef:
name: cm-mariadb
key: mysql_usuario
- name: MARIADB_PASSWORD
valueFrom:
secretKeyRef:
name: secret-mariadb
key: password
ports:
- name: mariadb-server
containerPort: 3306
volumeMounts:
- mountPath: "/var/lib/mysql"
name: volumen-mariadb
- Servicio de mariadb
apiVersion: v1
kind: Service
metadata:
name: mariadb
labels:
app: mariadb
tier: backend
spec:
type: ClusterIP
ports:
- port: 3306
targetPort: mariadb-server
selector:
app: mariadb
tier: backend
Creamos los ficheros de despliegue y servicios para bookmedik.
- Despliegue de bookmedik
apiVersion: apps/v1
kind: Deployment
metadata:
name: bookmedik
labels:
app: bookmedik
tier: frontend
spec:
replicas: 2
selector:
matchLabels:
app: bookmedik
tier: frontend
template:
metadata:
labels:
app: bookmedik
tier: frontend
spec:
containers:
- name: contenedor-bookmedik
image: legnakra/bookmedik:latest
env:
- name: USUARIO_BOOKMEDIK
valueFrom:
configMapKeyRef:
name: cm-mariadb
key: mysql_user
- name: PASS_BOOKMEDIK
valueFrom:
secretKeyRef:
name: secret-mariadb
key: mysql_password
- name: BASE_DATOS_BOOKMEDIK
valueFrom:
configMapKeyRef:
name: cm-mariadb
key: mysql_database
ports:
- name: http-server
containerPort: 80
- Servicio de bookmedik
apiVersion: v1
kind: Service
metadata:
name: bookmedik
labels:
app: bookmedik
tier: frontend
spec:
type: NodePort
ports:
- port: 80
targetPort: http-server
selector:
app: bookmedik
tier: frontend
Creamos todo y anotamos la primera versión de la aplicación.
kubectl apply -f .
Comprobamos que los recursos se han creado correctamente.
kubectl annotate deployment.apps/bookmedik kubernetes.io/change-cause="Versión 1"
- Accedemos a la aplicación y comprobamos que funciona correctamente.
Y comprobamos que podemos acceder:
Creamos el fichero Ingress para acceder a la aplicación desde el exterior.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: bookmedik-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:nano
rules:
- host: www.maria-bookmedik.org
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: bookmedik
port:
number: 80
Y lo creamos:
kubectl apply -f bookmedik-ingress.yaml
- Modificamos el fichero
/etc/hosts
para que apunte a la IP del nodo maestro.
- Accedemos a la aplicación desde el navegador.
Y accedemos a la zona de administración:
- Creamos información para probar la persistencia de la base de datos cuando borremos la base de datos de mariadb.
- Eliminamos el despliegue de mariadb.
kubectl delete deployment.apps/mariadb
- Comprobamos que la base de datos no funciona.
-
Ahora nos toca escalar el despliegue de la aplicación a 3 réplicas y lo podemos hacer de dos formas:
-
Modificando el fichero de despliegue y aplicando los cambios, haciéndolo persistente.
-
Modificando el despliegue en caliente, es decir, sin hacer persistente el cambio, ejecutando
kubectl scale <deploy-name> --replicas=<num_replicas>
.
-
En mi caso, quiero hacerlo de forma no persistente, por lo que ejecuto el comando:
kubectl scale deployment.apps/bookmedik --replicas=3
Y comprobamos que se ha escalado correctamente.
-
Vamos a crear una imagen docker, pero con alguna modficación, para probar el despliegue de una nueva versión de la aplicación.
-
Modificamos el fichero
index.php
de la aplicación para que muestre la versión de la aplicación.
En mi caso, le he cambiado el texto de la página principal y de la pestaña del navegador.
- Creamos la imagen docker con la nueva versión de la aplicación.
docker build -t legnakra/bookmedik:v1_1 .
- Subimos la imagen a docker hub.
docker push legnakra/bookmedik:v1_1
- Modificamos el fichero de despliegue para que use la nueva versión de la imagen.
- Aplicamos los cambios.
kubectl apply -f bookmedik-deployment.yaml
- Comprobamos que se ha desplegado la nueva versión de la aplicación.
Y que podemos acceder a la zona de administración.
Ejercicio 2: Despliegue en otra distribución de kubernetes
En esta parte, vamos a instalar un cluster de kubernetes. Pero lo haremos en una distribución diferente a la que hemos usado hasta ahora. Pero debemos hacerlo en otra versión, y he decidido hacerlo en k3s, que es una versión ligera de kubernetes.
- Creamos 3 nodos, uno maestro y dos esclavos.
# -*- mode: ruby -*-
# vi: set ft=ruby :
Vagrant.configure("2") do |config|
config.vm.define :controller do |controller|
controller.vm.box = "debian/buster64"
controller.vm.hostname = "controller"
controller.vm.network :private_network, ip: "192.168.0.10"
controller.nfs.verify_installed = false
controller.vm.synced_folder '.', '/vagrant', disabled: true
controller.vm.provider "libvirt" do |v|
v.memory = 3072
v.cpus = 2
end
end
config.vm.define :worker1 do |worker1|
worker1.vm.box = "debian/buster64"
worker1.vm.hostname = "worker1"
worker1.vm.network :private_network, ip: "192.168.0.20"
worker1.nfs.verify_installed = false
worker1.vm.synced_folder '.', '/vagrant', disabled: true
worker1.vm.provider "libvirt" do |v|
v.memory = 3072
v.cpus = 2
end
end
config.vm.define :worker2 do |worker2|
worker2.vm.box = "debian/buster64"
worker2.vm.hostname = "worker2"
worker2.vm.network :private_network, ip: "192.168.0.30"
worker2.nfs.verify_installed = false
worker2.vm.synced_folder '.', '/vagrant', disabled: true
worker2.vm.provider "libvirt" do |v|
v.memory = 3072
v.cpus = 2
end
end
end
- Instalamos k3s en el nodo maestro.
curl -sfL https://get.k3s.io | sh -
Y comprobamos que está listo.
kubectl get nodes
- Identificamos el token del nodo maestro.
sudo cat /var/lib/rancher/k3s/server/node-token
K100ce50339c5ff211169afea38d299cc60ea62c65b98d102b49df1e1c535b8da7f::server:611c1ed3c8c978a4048e541fac5e1061
- Ejecutamos lo siguiente:
curl -sfL https://get.k3s.io | K3S_URL=https://192.168.121.241:6443 K3S_TOKEN=K100ce50339c5ff211169afea38d299cc60ea62c65b98d102b49df1e1c535b8da7f::server:611c1ed3c8c978a4048e541fac5e1061 sh -
El comando anterior nos instala k3s en el nodo esclavo y lo añade al cluster. En el parámetro URL, debemos poner la IP del nodo maestro y en el parámetro token, el token que hemos obtenido en el paso anterior.
- Comprobamos que los nodos están listos.
kubectl get nodes

- Instalamos git en el nodo maestro (
controller
).
apt install git
- Clonamos el repositorio de la aplicación.
git clone https://github.com/Legnakra/Kubernetes-bookmedik.git
-
Rehacemos los pasos que hicimos en el ejercicio anterior:
- Creamos los ficheros yaml para crear un
ConfigMap
y unSecret
donde guardaremos las variables de entorno.
- Creamos los ficheros yaml para crear un
kubectl create cm cm-mariadb --from-literal=mysql_usuario=bookmedik --from-literal=basededatos=bookmedik
kubectl create secret generic secret-mariadb --from-literal=password=bookmedik --from-literal=rootpass=root
- Creamos los recursos:
kubectl apply -f pvc-bookmedik.yaml
kubectl apply -f mariadb-deployment.yaml
kubectl apply -f mariadb-service.yaml
kubectl apply -f bookmedik-deployment.yaml
kubectl apply -f bookmedik-service.yaml
kubectl apply -f bookmedik-ingress.yaml
- Comprobamos que todo está listo.
kubectl get all
- Accedemos a la dirección que hemos establecido en el fichero ‘bookmedik-ingress.yaml’.
Y que podemos acceder a la zona de administración.
-
Escalamos el despliegue como hemos hecho en el ejercicio anterior, y lo realizaremos con 3 replicas. Para ello, primero, veamos de nuevo que contamos con 2 replicas y vamos a extenderlo a 1 más.
-
Antes de escalar el despliegue, vamos a ver las replicas que tenemos.
kubectl get pods -o wide
- Ahora, vamos a escalar el despliegue.
kubectl scale deployment.apps/bookmedik --replicas=3
- Comprobamos que se ha escalado correctamente y que tenemos 3 replicas.
kubectl get pods -o wide
- Comprobamos que podemos acceder a la aplicación.
Y que podemos acceder a la zona de administración.