Deployment es la unidad de más alto nivel que podemos gestionar en Kubernetes. Nos permite definir diferentes funciones:

  • Control de replicas
  • Escabilidad de pods
  • Actualizaciones continúas
  • Despliegues automáticos
  • Rollback a versiones anteriores

deoployment

Definición yaml de un Deployment

Vamos a ver un ejemplo de definición de un Deployment en el fichero nginx-deployment.yaml:

apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: nginx
  namespace: default
  labels:
    app: nginx
spec:
  revisionHistoryLimit: 2
  strategy:
    type: RollingUpdate
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: nginx
        name: nginx
        ports:
        - name: http
          containerPort: 80

El despliegue de un Deployment crea un ReplicaSet y los Pods correspondientes. Por lo tanto en la definición de un Deployment se define también el replicaSet asociado. En la práctica siempre vamos a trabajar con Deployment. Los atributos relacionados con el Deployment que hemos indicado en la definición son:

  • revisionHistoryLimit: Indicamos cuántos ReplicaSets antiguos deseamos conservar, para poder realizar rollback a estados anteriores. Por defecto, es 10.
  • strategy: Indica el modo en que se realiza una actualización del Deployment: recreate: elimina los Pods antiguos y crea los nuevos; RollingUpdate: actualiza los Pods a la nueva versión.

Puedes encontrar más parámetros en la documentación.

Cuando creamos un Deployment, se crea el ReplicaSet asociado y todos los pods que hayamos indicado.

kubectl create -f nginx-deployment.yaml 
deployment.extensions "nginx" created

kubectl get pods
NAME                     READY     STATUS    RESTARTS   AGE
nginx-84f79f5cdd-b2bn5   1/1       Running   0          44s
nginx-84f79f5cdd-cz474   1/1       Running   0          44s

kubectl get deploy
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
nginx     2         2         2            2           49s

kubectl get rs
NAME               DESIRED   CURRENT   READY     AGE
nginx-84f79f5cdd   2         2         2         53s

kubectl get pods
NAME                     READY     STATUS    RESTARTS   AGE
nginx-84f79f5cdd-b2bn5   1/1       Running   0          56s
nginx-84f79f5cdd-cz474   1/1       Running   0          56s

Como ocurría con los replicaSets los Deployment también se pueden escalar, aumentando o disminuyendo el número de pods asociados:

kubectl scale deployment nginx --replicas=4
deployment.extensions "nginx" scaled

kubectl get rs
NAME               DESIRED   CURRENT   READY     AGE
nginx-84f79f5cdd   4         4         4         2m

kubectl get pods
NAME                     READY     STATUS    RESTARTS   AGE
nginx-84f79f5cdd-7kzls   1/1       Running   0          2m
nginx-84f79f5cdd-8zrcb   1/1       Running   0          2m
nginx-84f79f5cdd-b2bn5   1/1       Running   0          2m
nginx-84f79f5cdd-cz474   1/1       Running   0          2m

Actualización del deployment

Podemos cambiar en cualquier momentos las propiedades del deployment, por ejemplo para hacer una actualización de la aplicación:

kubectl set image deployment nginx nginx=nginx:1.13 --all
deployment.apps "nginx" image updated

También podríamos haber cambiado la versión de la imagen modificando la definición Yaml del Deployment con la siguiente instrucción:

kubectl edit deployment nginx

Y comprobamos que se ha creado un nuevo RecordSet, y unos nuevos pods con la nueva versión de la imagen.

kubectl get rs
NAME               DESIRED   CURRENT   READY     AGE
nginx-75f9c7b459   4         4         3         5s
nginx-84f79f5cdd   0         0         0         6m

kubectl get pods
NAME                     READY     STATUS    RESTARTS   AGE
nginx-75f9c7b459-87l5j   1/1       Running   0          5s
nginx-75f9c7b459-92x8s   1/1       Running   0          5s
nginx-75f9c7b459-fm6g5   1/1       Running   0          5s
nginx-75f9c7b459-pz78j   1/1       Running   0          5s

La opción --all fuerza a actualizar todos los pods aunque no estén inicializados.

Rollback de nuestra aplicación

Si queremos volver a la versión anterior de nuestro despliegue, tenemos que ejecutar:

kubectl rollout undo deployment/nginx
deployment.apps "nginx" 

T comprobamos como se activa el antiguo RecordSet y se crean nuevos pods con la versión anterior de nuestra aplicación:

kubectl get rs
NAME               DESIRED   CURRENT   READY     AGE
nginx-75f9c7b459   0         0         0         1h
nginx-84f79f5cdd   4         4         4         22h

kubectl get pods
NAME                     READY     STATUS    RESTARTS   AGE
nginx-84f79f5cdd-cwgzx   1/1       Running   0          5s
nginx-84f79f5cdd-hmd2l   1/1       Running   0          5s
nginx-84f79f5cdd-rhnkg   1/1       Running   0          5s
nginx-84f79f5cdd-vn7kd   1/1       Running   0          5s

Eliminando el despliegue

Si eliminamos el Deployment se eliminarán el RecordSet asociado y los pods que se estaban gestionando.

kubectl delete deployment nginx
deployment.extensions "nginx" deleted

kubectl get deploy
No resources found.

kubectl get rs
No resources found.

kubectl get pods
No resources found.

ReplicaSet es un recurso de Kubernetes que asegura que siempre se ejecute un número de replicas de un pod determinado. Por lo tanto, nos asegura que un conjunto de pods siempre están funcionando y disponibles. Nos proporciona las siguientes características:

  • Que no haya caída del servicio
  • Tolerancia a errores
  • Escabilidad dinámica

Definición yaml de un ReplicaSet

Vamos a ver un ejemplo de definición de ReplicaSet en el fichero nginx-rs.yaml:

apiVersion: extensions/v1beta1
kind: ReplicaSet
metadata:
  name: nginx
  namespace: default
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - image:  nginx
          name:  nginx
  • replicas: Indicamos el número de pos que siempre se van a estar ejecutando.
  • selector: Indicamos el pods que vamos a replicar y vamos a controlar con el ReplicaSet. En este caso va a controlar pods que tenga un label app cuyo valor sea nginx. Si no se indica el campo selector se seleccionar or defecto los pods cuyos labels sean iguales a los que hemos declarado en la sección siguiente.
  • template: El recurso ReplicaSet contiene la definición de un pod.

Al crear el ReplicaSet se crearán los pods que hemos indicado como número de replicas:

kubectl create -f nginx-rs.yaml
replicaset.extensions "nginx" created

Veamos el ReplicaSet creado y los pods que ha levantado.

kubectl get rs
NAME      DESIRED   CURRENT   READY     AGE
nginx     2         2         2         44s

kubectl get pods
NAME          READY     STATUS    RESTARTS   AGE
nginx-5b2rn   1/1       Running   0          1m
nginx-6kfzg   1/1       Running   0          1m

¿Qué pasaría si borro uno de los pods que se han creado? Inmediatamente se creará uno nuevo para que siempre estén ejecutándose los pods deseados, en este caso 2:

kubectl delete pod nginx-5b2rn
pod "nginx-5b2rn" deleted

kubectl get pods
NAME          READY     STATUS              RESTARTS   AGE
nginx-6kfzg   1/1       Running             0          2m
nginx-lkvzj   0/1       ContainerCreating   0          4s

kubectl get pods
NAME          READY     STATUS    RESTARTS   AGE
nginx-6kfzg   1/1       Running   0          2m
nginx-lkvzj   1/1       Running   0          8s

En cualquier momento puedo escalar el número de pods que queremos que se ejecuten:

kubectl scale rs nginx --replicas=5
replicaset.extensions "nginx" scaled

kubectl get pods --watch
NAME          READY     STATUS    RESTARTS   AGE
nginx-6kfzg   1/1       Running   0          5m
nginx-bz2gs   1/1       Running   0          46s
nginx-lkvzj   1/1       Running   0          3m
nginx-ssblp   1/1       Running   0          46s
nginx-xxg4j   1/1       Running   0          46s

Como anteriormente vimos podemos modificar las características de un ReplicaSet con la siguiente instrucción:

kubectl edit rs nginx

Por último si borramos un ReplicaSet se borraran todos los pods asociados:

kubectl delete rs nginx
replicaset.extensions "nginx" deleted

kubectl get rs
No resources found.

kubectl get pods 
No resources found.

El uso del recurso ReplicaSet sustituye al uso del recurso ReplicaController, más concretamente el uso de Deployment que define un ReplicaSet.

La unidad más pequeña de kubernetes son los Pods, con los que podemos correr contenedores. Un pod representa un conjunto de contenedores que comparten almacenamiento y una única IP. Los pods son efímeros, cuando se destruyen se pierde toda la información que contenía. Si queremos desarrollar aplicaciones persistentes tenemos que utilizar volúmenes.

Por lo tanto, aunque Kubernetes es un orquestador de contenedores, la unidad mínima de ejecución son los pods:

  • Si seguimos el principio de un proceso por contenedor, nos evitamos tener sistemas (como máquinas virtuales) ejecutando docenas de procesos,
  • pero en determinadas circunstancias necesito más de un proceso para que se ejecute mi servicio.

Por lo tanto parece razonable que podamos tener más de un contenedor compartiendo almacenamiento y direccionamiento, que llamamos Pod. Además existen mas razones:

  • Kubernetes puede trabajar con distintos contenedores (Docker, Rocket, cri-o,…) por lo tanto es necesario añadir una capa de abstracción que maneje las distintas clases de contenedores.
  • Además esta capa de abstracción añade información adicional necesaria en Kubernetes como por ejemplo, políticas de reinicio, comprobación de que la aplicación esté inicializada (readiness probe), comprobación de que la aplicación haya realizado alguna acción especificada (liveness probe), …

Ejemplos de implementación en pods

  1. Un servidor web nginx con un servidor de aplicaciones PHP-FPM, lo podemos implementar en un pod, y cada servicio en un contenedor.
  2. Una aplicación WordPress con una base de datos mariadb, lo implementamos en dos pods diferenciados, uno para cada servicio.

Continue reading

Un escenario común cuando desplegamos una aplicación web puede ser el siguiente:

En este escenario tenemos los siguientes elementos:

  • Un conjunto de máquinas (normalmente virtuales) que sirven la aplicación web (frontend).
  • Un balanceador de carga externo que reparte el tráfico entre las diferentes máquinas.
  • Un número de servidores de bases de datos (backend).
  • Un balanceador de carga interno que reparte el acceso a las bases de datos.

El escenario anterior se podría montar en Kubernetes de la siguiente forma:

Los distintos recursos de Kubernetes nos proporcionan distintas características muy deseadas:

  • Pods: La unidad mínima de computación en Kubernetes, permite ejecutar contenedores. Representa un conjunto de contenedores y almacenamiento compartido que comparte una única IP.
  • ReplicaSet: Recurso de un cluster Kubernetes que asegura que siempre se ejecute un número de replicas de un pod determinado. Nos proporciona las siguientes características:
    • Que no haya caída del servicio
    • Tolerancia a errores
    • Escabilidad dinámica
  • Deployment: Recurso del cluster Kubernetes que nos permite manejar los ReplicaSets. Nos proporciona las siguientes características:
    • Actualizaciones continúas
    • Despliegues automáticos
  • Service: Nos permite el acceso a los pod.
  • Ingress: Nos permite implementar un proxy inverso para el acceso a los distintos servicios establecidos. Estos dos elementos nos proporcionan la siguiente funcionalidad:
    • Balanceo de carga
  • Otros recursos de un cluster Kubernetes nos pueden proporcional características adicionales:
    • Migraciones sencillas
    • Monitorización
    • Control de acceso basada en Roles
    • Integración y despliegue continuo

En las siguientes entradas vamos a ir estudiando cada uno de estos recursos.


Kubernetes es un sistema de código abierto que nos permite despliegues automáticos, escabilidad y gestión de contenedores de aplicaiones. kubeadm es una herramienta que nos permite el despliegue de un cluster de kubernetes de manera sencilla. El cluster lo podemos crear en máquinas físicas o virtuales, en nuestro caso, vamos a usar Debian 9 en 3 máquinas virtuales para realizar la instalación.

Instalación de los paquetes necesarios

Instalación de Docker

Lo primero que hacemos, siguiendo las instrucciones de instalación de página oficial, es instalar la última versión de docker, en los tres nodos:

$ sudo apt-get update

Instalamos los paquetes que nos permiten usar repositorios apt con https:

$ sudo apt-get install \
     apt-transport-https \
     ca-certificates \
     curl \
     gnupg2 \
     software-properties-common

Añadimos las clves GPG oficales de Docker:

$ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -

Añadimos el repositorio para nuestra versión de Debian:

$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/debian \
   $(lsb_release -cs) \
   stable"

Y por último instalamos docker:

$ sudo apt-get update
$ sudo apt-get install docker-ce

Finalmente comprobamos la versión instalada:

$ docker --version
Docker version 18.03.1-ce, build 9ee9f40

Instalación de kubeadm, kubelet and kubectl

Vamos a instalar los siguientes pauqetes en nuestras máquinas:

  • kubeadm: Instrucción que nos permite crear el cluster.
  • kubelet: Es el componente de kubernetes que se ejecuta en todos los nodos y es responsable de ejecutar los pods y los contenedores.
  • kubectl: La utilidad de línea de comandos que nos permite controlar el cluster.

Para la instalación, seguimos los pasos indicados en la documentación:

apt-get update && apt-get install -y apt-transport-https curl
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet kubeadm kubectl

Continue reading