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

  1. Creamos los ficheros yaml para crear un ConfigMap y un Secret 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
  1. 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
  1. 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
  1. 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"
  1. Accedemos a la aplicación y comprobamos que funciona correctamente.

Y comprobamos que podemos acceder:

  1. 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
  1. Modificamos el fichero /etc/hosts para que apunte a la IP del nodo maestro.
  1. Accedemos a la aplicación desde el navegador.
Y accedemos a la zona de administración:
  1. 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.
  1. 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.

  1. 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.

  1. 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
  1. Instalamos k3s en el nodo maestro.
curl -sfL https://get.k3s.io | sh -

Y comprobamos que está listo.

kubectl get nodes
  1. Identificamos el token del nodo maestro.
sudo cat /var/lib/rancher/k3s/server/node-token
K100ce50339c5ff211169afea38d299cc60ea62c65b98d102b49df1e1c535b8da7f::server:611c1ed3c8c978a4048e541fac5e1061
  1. 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.

  1. Comprobamos que los nodos están listos.
kubectl get nodes
  1. Instalamos git en el nodo maestro ( controller).
apt install git
  1. Clonamos el repositorio de la aplicación.
git clone https://github.com/Legnakra/Kubernetes-bookmedik.git
  1. Rehacemos los pasos que hicimos en el ejercicio anterior:
  • Creamos los ficheros yaml para crear un ConfigMap y un Secret donde guardaremos las variables de entorno.
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.

  1. 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.