En este post hablaremos que son los pods y como podemos trabajar con ellos.
En el anterior post ya usamos un pod aunque realmente todavía no sabíamos nada de ellos. Si recordamos un poco cuando hicimos el run donde le indicabamos el nombre de la imagen que queriamos desplegar, lo que hizo por debajo kubernetes fué crear algo bajo el namespace pod/mario-test, ¿verdad?... pues bien para resumir lo que sería realmente un pod es una aplicación o servicio que puede tener uno o más contenedores y/o volúmenes de disco. Estos contenedores o aplicaciones están funcionando bajo el mismo namespace de networking, es decir, el conjunto de contenedores tiene la misma IP pero internamente dentro del POD los contenedores son capaces de comunicarse entre sí solo usando localhost: (es como si estuvieramos usando docker-compose con varios contenedores). La ip que reciben es privada y solo se puede acceder a través de otros PODS. Técnicamente hablando esto se conoce como que el pod esta funcionando dentro de su propio cgroup.

Un POD es la unidad mínima de recursos que podemos tener dentro de kubernetes, es decir, al menos necesitaremos un POD para poder ejecutar un contenedor. Cuando se crea un pod, kubernetes lo asigna a uno de los nodos del cluster que tengamos dependiendo de los recursos disponibles y los deseados. En kubernetes cada Pod tiene su propio ciclo de vida y podemos escalarlo o hacer lo que queramos con ellos por lo que se suele desplegar un POD por aplicación.

La declaración de un POD tiene un estilo similar a cuando trabajamos con recetas de docker-compose, es un yaml con un estilo similar a

apiVersion: v1
kind: Pod
metadata:
  name: example-app
  labels:
    app: example-app
    version: v1
    role: backend
spec:
  containers:
  - name: java
    image: companyname/java
    ports:
    - containerPort: 443
    volumeMounts:
    - mountPath: /volumes/logs
      name: logs
  - name: logger
    image: companyname/logger:v1.2.3
    ports:
    - containerPort: 9999
    volumeMounts:
    - mountPath: /logs
      name: logs
  - name: monitoring
    image: companyname/monitoring:v4.5.6
    ports:
    - containerPort: 1234

Donde como vemos tenemos la versión de la api, el tipo(pod obviamente), metadatos y spec donde declaramos los containers y su configuración deseada (esos campos son los mínimos necesarios). OJO esto es una forma declarativa de decirle a Kubernetes que es lo que queremos, luego el en su ciclo de vida, cuando toque comparará el estado actual con el deseado y hará los cambios necesarios para cumplir con lo solicitado, como por ejemplo en el caso de que no existan los contenedores los creará al igual que vimos en el post anterior.

Esto es realmente lo que hace kubectl cuando le enviamos el comando en el post anterior:

kubectl run mario-test --image=pengbai/docker-supermario:latest --port=8080

Usemos un truco para poder ver que es lo que realmente hace el comando, si ejecutamos este comando:

kubectl run mario-test --image=pengbai/docker-supermario:latest --port=8080 --dry-run=client -o yaml

Deberiamos ver algo como esto:

Captura-de-pantalla-2020-11-16-a-las-20.15.05

Esto es lo que realmente esta enviando el comando, donde a modo de resumen rápido tenemos lo siguiente:

  • apiVersion: versión de la api de kubernetes
  • kind: como sabemos estamos ahora mismo trabajando con Pods
  • metadata.creationTimestamp: Como realmente no ha sido creado no nos aparece ningún timestamp (supongamos que esta es la especificación que mantiene kubernetes para comparar con la que le mandemos nosotros por eso tiene timestamp)
  • metadata.labels: Aquí podemos incluir todo tipo de información útil, como el entorno, al final lo utilizariamos para identificar de alguna manera este POD, su finalidad....
  • name: Identificador único del POD
  • spec: Donde realmente se encuentra toda la información de los contenedores o lo que sea que este incluido en este pod

Para terminar de comprobar que no estoy mintiendo hagamos lo siguiente, vamos a crear un fichero yaml con esta configuración y lanzarsela a kubernetes a ver que pasa. Para ello lo primero creamos el fichero (OJO con el nombre que tiene un 2):

kubectl run mario-test-2 --image=pengbai/docker-supermario:latest --port=8080 --dry-run=client -o yaml > mario.yaml

Esto nos creará un fichero con la configuración que acabamos de ver, podemos comprobarlo con:

cat mario.yaml

Ahora le indicamos a kubernetes que cree lo que dice el fichero:

kubectl create -f mario.yaml

Nos indica que ya esta creado
Captura-de-pantalla-2020-11-16-a-las-20.25.45

Aunque realmente esa es la respuesta de kubernetes al comando, realmente lo creará cuando este en la fase de reconciliación de su ciclo de vida y vea que algo no cuadra entre lo que tiene y lo que se supone que debe tener según nuestros comandos.

Si ahora ejecutamos:

kubectl get pods

Podemos ver como tenemos otro contenedor creado con el nombre que le hemos indicado

Captura-de-pantalla-2020-11-16-a-las-20.28.01

Si por algún motivo no sabemos realmente que es lo que tiene un pod en cuestión podemos ver toda la información relevante usando el comando:

kubectl describe pod mario-test

Con esto veremos toda la información posible:

Captura-de-pantalla-2020-11-16-a-las-20.31.02

Como el nombre, el nodo donde se encuentra, su estadom la IP..... incluso si nos vamos al final de lo que nos ha mostrado la consola podremos ver un listado de eventos con lo que ha ido pasando con este pod

Captura-de-pantalla-2020-11-16-a-las-20.32.01

Bueno y hasta aquí este post de introducción a los PODS, en el siguiente podremos ver algo vas información y configuraciones más avanzadas, nos vemos un abrazoooooor