Kubernetes

Implantación de Aplicaciones Web

José Juan Sánchez Hernández

Curso 2023/2024

1 Kubernetes

NOTA: El contenido de este sitio está en desarrollo.

1.1 ¿Qué es Kubernetes?

Kubernetes (K8s) es una plataforma de código abierto para automatizar la implementación, el escalado y la administración de aplicaciones en contenedores.

1.2 ¿Qué es un clúster de Kubernetes?

Un clúster de Kubernetes es un grupo de máquinas físicas o virtuales donde se ha desplegado el software de Kubernetes, para que trabajen juntas y ejecuten aplicaciones en contenedores.

Dentro de un clúster de Kubernetes existen dos tipos de nodos:

1.3 Componentes de Kubernetes

Vamos a estudiar cuáles son los componentes que utilizan cada uno de los nodos de un clúster de Kubernetes:

  1. Componentes de los nodos Master (Control Plane)
Componente Descripción
kube-apiserver Publica la API de Kubernetes y actualiza la base de datos etcd.
etcd Es una base de datos distribuida de tipo clave-valor donde se almacena la configuración y el estado del clúster.
kube-controller-manager Ejecuta los controladores que gestionan los recursos del clúster. Gestiona la creación de las réplicas para mantener el estado deseado en el clúster.
kube-scheduler Decide en qué nodo del clúster se ejecutará cada Pod.
cloud-controller-manager Interactua con proveedores externos de servicios en cloud computing como AWS, Azure o GCE. Este componente es opcional
  1. Componentes de los nodos Workers
Componente Descripción
kubelet Ejecuta y gestiona los Pods en los nodos del clúster.
kube-proxy Implementa un proxy de red para los Pods para facilitar la comunicación entre ellos.
container-runtime Runtime que ejecuta los contenedores (Docker, containerd, CRI-O, etc.)

Imagen 1: Componentes de un clúster de Kubernetes. Imagen obtenida de la página oficial de Kubernetes

1.4 ¿Cómo puedo crear un clúster de Kubernetes en un entorno de producción?

Para crear un clúster de Kubernetes existen diferentes soluciones:

  1. Utilizar Kubernetes como servicio en un proveedor de Cloud Computing.

Una solución sencilla donde no es necesario realizar ninguna instalación, es hacer uso de los servicios de Kubernetes que ofrecen algunos proveedores de Cloud Computing como:

  1. Realizar la instalación Kubernetes sobre una infraestructura determinada

Existen diferentes proyectos open source que nos permiten realizar la instalación de un clúster de Kubernetes sobre la infraestructura que nosotros queramos. Algunas soluciones son:

1.5 ¿Cómo puedo crear un clúster de Kubernetes en mi entorno de desarrollo?

También existen otros proyectos que nos permiten crear un clúster en entornos de desarrollo o entornos con recursos limitados. Algunas soluciones son:

1.6 Creación de un entorno de desarrollo con Minikube

1.6.1 Actividad 1.1. Instalación de minikube

minikube que es una herramienta de código abierto que permite ejecutar un clúster de Kubernetes de forma local.

Dependiendo del driver utilizado a la hora de crear el clúster, minikube puede ser desplegado en:

Puede encontrar más información sobre los drivers disponibles en minikube en la documentación oficial.

La primera actividad que vamos a realizar será la instalación de minikube sobre una instancia de OpenStack o AWS. El sistema operativo de la instancia tendrá que ser la última versión disponible de Ubuntu Server o Debian.

Para realizar la instalación de minikube se recomienda utilizar los scripts del siguiente repositorio:

En este repositorio puede encontrar los scripts para desplegar minikube en sistemas Debian y Ubuntu, utilizando los siguientes drivers:

Como vamos a trabajar con una instancia en OpenStack o AWS se recomienda utilizar el driver none para realizar una instalación en bare metal, de esta forma podremos utilizar la IP pública de la instancia para acceder al clúster.

1.6.2 Actividad 1.2. Creación de un clúster de un solo nodo con minikube

Una vez que hemos instalado minikube vamos a crear un clúster con un solo nodo que será el Control Plane.

Cuando creamos un clúster en minikube con el driver none necesitamos indicar qué plugin de CNI (Container Network Interface) queremos utilizar para gestionar la red del clúster. Si no indicamos un plugin de CNI, vamos a tener problemas de conectividad entre los Pods.

En nuestro caso, vamos a utilizar el plugin de red Flannel.

El comando para crear un clúster de Kubernetes de un solo nodo con minikube, utilizando el driver none y el plugin de red Flannel es el siguiente:

minikube start --driver none --network-plugin cni --cni flannel

Para comprobar el estado del clúster podemos utilizar el comando:

minikube status

Para detener el clúster podemos utilizar el comando:

minikube stop

Podemos comprobar el driver que estamos utilizando con el siguiente comando:

minikube profile list

Para eliminar el clúster podemos utilizar el comando:

minikube delete

Anexo

A continuación, se muestra un ejemplo cómo se podría el clúster de Kubernetes con otros drivers.

minikube start --driver docker
minikube start --driver virtualbox
minikube start --driver kvm2

1.6.3 Actividad 1.3. Instalación de kubectl

Para gestionar nuestro clúster de Kubernetes vamos a utilizar kubectl, que es una aplicación que nos permite interaccionar con la API de Kubernetes desde la línea de comandos.

Para realizar la instalación de kubectl se recomienda utilizar los scripts del siguiente repositorio:

1.6.4 Actividad 1.4. Creación de un clúster con varios nodos con minikube

En esta actividad tendrá que crear un clúster de Kubernetes con minikube con tres nodos:

1.7 Creación de un entorno de desarrollo con kind

1.7.1 Actividad 2.1. Instalación y configuración de kind

TODO

1.7.2 Actividad 2.2. Creación de un clúster con varios nodos con kind

En esta actividad tendrá que crear un clúster de Kubernetes con kind con tres nodos:

1.8 Objetos de Kubernetes

En esta práctica vamos a trabajar con los siguientes objetos de Kubernetes:

1.8.1 Pods

Un Pod es la unidad base de Kubernetes, es el recurso más pequeño que se puede desplegar en el clúster.

Un Pod puede tener un contenedor (principal) y varios contenedores auxiliares (init containers, ephemeral containers o sidecar containers).

Los contenedores que están dentro del mismo pod comparten la misma dirección IP y se comunican por localhost. Por este motivo, no pueden usar los mismos puertos.

En un cluster de Kubernetes podemos tener muchos Pods y cada uno tiene su propia dirección IP.

1.8.1.1 Definición de un Pod

En este ejemplo vamos a definir un objeto de tipo Pod en un archivo llamado mi-pod.yaml con el siguiente contenido.

apiVersion: v1
kind: Pod
metadata:
  name: mi-pod
  labels:
    mi-clave: mi-valor
spec:
  containers:
  - name: mi-contenedor
    image: nginx
    ports:
    - containerPort: 80
  restartPolicy: Always

1.8.1.2 Creación de un Pod

kubectl apply -f mi-pod.yaml

1.8.1.3 Obtener el listado de Pods

Para obtener el listado de Pods podemos utilizar cualquier de estas tres opciones:

kubectl get pods
kubectl get pod
kubectl get po

Podemos utilizar el flag -o wide para obtener información ampliada:

kubectl get pods -o wide

Para obtener un listado de todos los recursos podemos utilizar el comando:

kubectl get all

1.8.1.4 Obtener información detallada de un Pod

Podemos utilizar cualquiera de estas dos opciones.

kubectl describe pods mi-pod 
kubectl describe pods/mi-pod 

1.8.1.5 Mostrar los logs del contenedor del Pod

Si el Pod sólo tiene un contenedor no es necesario indicar el nombre, es opcional.

kubectl logs mi-pod 

Con el flag -f podemos indicar que la información del log se mueste en tiempo real.

kubectl logs -f mi-pod 

1.8.1.6 Ejecutar un comando dentro del contenedor del Pod

El siguiente comando ejecuta el comando /bin/bash dentro del contenedor del pod mi-pod.

kubectl exec -it mi-pod -- /bin/bash

1.8.1.7 Cómo acceder al contenedor del Pod

Para acceder a contenedor del Pod podemos hacemos hacer una redirección de puertos desde la máquina donde estamos ejecutando el comando kubectl hasta el contenedor del Pod.

En este ejemplo vamos a hacer una redirección entre el puerto 8000 de la máquina donde ejecutamos kubectl y el puerto 80 del Pod.

kubectl port-forward mi-pod 8000:80

Al ejecutar el comando veremos que la redirección está activa y finalizará cuando terminemos la ejecución del comando con Control + C.

Forwarding from 127.0.0.1:8000 -> 80
Forwarding from [::1]:8000 -> 80

^C

Para acceder al Pod lo haremos accediendo a través de la dirección de localhost de la máquina donde hemos ejecutado el comando.

curl http://localhost:8000

Si queremos hacer la redirección de puertos a una dirección IP que no sea la de localhost podemos utilizar el flag --address.

kubectl port-forward mi-pod 8000:80 --address 0.0.0.0

1.8.1.8 Eliminar un Pod

kubectl delete pods mi-pod 

1.8.2 ReplicaSet

Un ReplicaSet es un objeto que se encarga de garantizar que siempre haya en ejecución un número específico de réplicas de un Pod dentro del clúster.

1.8.2.1 Definición de un ReplicaSet

En este ejemplo vamos a definir un objeto de tipo ReplicaSet en un archivo llamado mi-replicaset.yaml con el siguiente contenido.

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: mi-replicaset
spec:
  # Número de réplicas que queremos tener en ejecución
  replicas: 2
  # Selecciona todos los Pods que tengan la etiqueta 'app: mi-app'
  selector:
    matchLabels:
      app: mi-app
  # Define la plantilla del pod que se utilizará para crear las réplicas
  template:
    metadata:
      # Añade la etiqueta 'app: mi-app' al pod para que coincida con el selector
      labels:
        app: mi-app
    spec:
      containers:
      - name: mi-contenedor
        image: nginx
        ports:
        - containerPort: 80
      restartPolicy: Always

1.8.2.2 Creación de un ReplicaSet

kubectl apply -f mi-replicaset.yaml 

1.8.2.3 Obtener el listado de ReplicasSet

Para obtener el listado de ReplicaSet podemos utilizar cualquier de estas opciones:

kubectl get replicasets.apps
kubectl get replicasets
kubectl get rs

Podemos utilizar el flag -o wide para obtener información ampliada:

kubectl get rs -o wide

Para obtener un listado de todos los recursos podemos utilizar el comando:

kubectl get all

1.8.2.4 Obtener información detallada de un ReplicaSet

Podemos utilizar cualquiera de estas opciones.

kubectl describe replicasets.apps mi-replicaset 
kubectl describe replicasets.apps/mi-replicaset

kubectl describe replicasets mi-replicaset
kubectl describe replicasets/mi-replicaset

kubectl describe rs/mi-replicaset
kubectl describe rs mi-replicaset

1.8.2.5 Mostrar los logs del Deployment

kubectl logs replicasets mi-replicaset

Con el flag -f podemos indicar que la información del log se mueste en tiempo real.

kubectl logs -f replicasets mi-replicaset

1.8.2.6 Eliminar un ReplicaSet

kubectl delete replicasets mi-replicaset

1.8.3 Deployment

El Deployment es un objeto que nos permite automatizar el despliegue y la actualización de una aplicación dentro del clúster. Este objeto utiliza en su definición los objetos Pod y ReplicaSet.

Las buenas prácticas recomiendan trabajar con Deployments en lugar de Pods.

1.8.3.1 Definición de un Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: mi-deployment
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mi-app
  # Estrategia de actualización: RollingUpdate
  strategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        app: mi-app
    spec:
      containers:
      - name: mi-contenedor
        image: nginx
        ports:
        - containerPort: 80
      restartPolicy: Always

1.8.3.2 Estrategia de actualización

Cuando se realiza una actualización sobre un Deployment que está en ejecución, es posible indicar cuál será la estrategia que se va a utilizar para reemplazar los Pods de la versión antigua por los Pods de la nueva versión.

Esta estrategia se indica en el parámetro .spec.strategy y se pueden indicar dos tipos:

1.8.3.3 Creación de un Deployment

kubectl apply -f mi-deployment.yaml

1.8.3.4 Obtener el listado de Deployments

Para obtener el listado de Deployments podemos utilizar cualquier de estas opciones:

kubectl get deployments.apps
kubectl get deployments
kubectl get deploy

Podemos utilizar el flag -o wide para obtener información ampliada:

kubectl get deploy -o wide

Para obtener un listado de todos los recursos podemos utilizar el comando:

kubectl get all

1.8.3.5 Obtener información detallada de un Deployment

Podemos utilizar cualquiera de estas opciones.

kubectl describe deployment.apps mi-deployment
kubectl describe deployment.apps/mi-deployment

kubectl describe deployment mi-deployment
kubectl describe deployment/mi-deployment

kubectl describe deploy/mi-deployment
kubectl describe deploy mi-deployment

1.8.3.6 Mostrar los logs del Deployment

kubectl logs deployments/mi-deployment

Con el flag -f podemos indicar que la información del log se mueste en tiempo real.

kubectl logs -f deployments/mi-deployment

1.8.3.7 Eliminar un Deployment

kubectl delete deployment mi-deployment

2 Referencias

3 Licencia

Licencia de Creative Commons
Esta página forma parte del curso Implantación de Aplicaciones Web de José Juan Sánchez Hernández y su contenido se distribuye bajo una licencia Creative Commons Reconocimiento-NoComercial-CompartirIgual 4.0 Internacional.