Skip to content

Pod

De la misma forma que {% link “p:/linux/docker/compose/” %} nos permite ejecutar un grupo de contenedores estrechamente relacionas, kubernetes utiliza pods.

La mayoría de pods sólo tienen un contenedor, pero un contenedor siempre ha de ejecutarse dentro de un pod.

Minikube es una herramienta que te permite usar Kubernetes en un único nodo para que realizar pruebas o como entorno de desarrollo.

Crea una máquina Linux e instala {% link “/linux/docker/” %}

Terminal window
connect-wsl k8s -new
install-docker

Instala la última versión estable de minikube usando el paquete Debian :

Terminal window
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube_latest_amd64.deb
sudo dpkg -i minikube_latest_amd64.deb

Configura minikube para que tenga más “potencia”:

Terminal window
$ minikube config set cpus 8
$ minikube config set memory 8096
$ minikube config view
- cpus: 8
- memory: 8096

Inicia el cluster:

Terminal window
$ minikube start
😄 minikube v1.35.0 on Ubuntu 24.04 (amd64)
Automatically selected the docker driver. Other choices: none, ssh
Exiting due to MK_USAGE: Docker has only 7777MB memory but you specified 8096MB

Como te has excedido con la memoria (quizás no 😅), modifica la configuración correspondiente:

Terminal window
~$ minikube config set memory 6144
These changes will take effect upon a minikube delete and then a minikube start

Vamos 🚀:

Terminal window
$ minikube start
😄 minikube v1.35.0 on Ubuntu 24.04 (amd64)
Using the docker driver based on existing profile
👍 Starting "minikube" primary control-plane node in "minikube" cluster
...
🏄 Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default

Al principio, es posible que algunos servicios, como el aprovisionador de almacenamiento, aún no estén en estado de ejecución. Esta es una situación normal durante la activación del clúster y se resolverá por sí sola en unos momentos.

Comprueba el estado del clúster:

Terminal window
$ minikube status
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

Puedes comprobar que estamos utilizando el driver docker:

Terminal window
$ minikube profile list
|----------|-----------|---------|--------------|------|---------|--------|-------|----------------|--------------------|
| Profile | VM Driver | Runtime | IP | Port | Version | Status | Nodes | Active Profile | Active Kubecontext |
|----------|-----------|---------|--------------|------|---------|--------|-------|----------------|--------------------|
| minikube | docker | docker | 192.168.49.2 | 8443 | v1.32.0 | OK | 1 | * | * |
|----------|-----------|---------|--------------|------|---------|--------|-------|----------------|--------------------|

Puedes detener el clúster con el comando stop:

Terminal window
$ minikube stop
Stopping node "minikube" ...
🛑 Powering off "minikube" via SSH ...
🛑 1 node stopped.

Y también, puedes borrar el cluster con el comando delete (no hace falta que lo pruebes 🙄):

Terminal window
$ minikube delete
🔥 Deleting "minikube" in docker ...
🔥 Deleting container "minikube" ...
🔥 Removing /home/box/.minikube/machines/minikube ...
💀 Removed all traces of the "minikube" cluster.

Y si eres un poco curioso, deberías serlo 🧐, puedes entrar dentro de la màquina virtual Minikube:

Terminal window
$ minikube ssh

En este caso es “docker”, pero podria ser una màquina virtual de verdad .

Terminal window
$ minikube ssh
docker@minikube:~$ exit
logout

Como administrador debes dominar el cluster desde el shell, pero a veces es útil un entorno gráfico.

Abre un nuevo terminal, y ejecuta:

Terminal window
$ minikube dashboard
🤔 Verifying dashboard health ...
🚀 Launching proxy ...
🤔 Verifying proxy health ...
🎉 Opening http://127.0.0.1:42919/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/ in your default browser...
👉 http://127.0.0.1:42919/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/

Haz clic en el enlace que te indica 👉.

Importante El puerto es dinámico por lo que haz clic en el enlace de tu shell, no en el de la documentación ! 🫡

Instala kubectl:

Terminal window
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

Habilita el autocompletado de kubectl (te permite utilizar la tecla tab para completar los comandos):

Terminal window
echo 'source <(kubectl completion bash)' >>~/.bashrc
source ~/.bashrc

Con kubectl puedes controlar un cluster kubernetes mediante peticiones REST al servidor API que se ejecuta en el nodo “master”.

Por ejemplo, puedes obtener la información del cluster:

Terminal window
$ kubectl cluster-info
Kubernetes control plane is running at https://127.0.0.1:32781
CoreDNS is running at https://127.0.0.1:32781/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

Puedes ver que el custer está activo y diferentes URLs de varios componentes de kubernnets.

A continuación mira cuantos nodos forman parte del cluster:

Terminal window
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane 28m v1.32.0

Como era de esperar sólo hay un nodo, que es “minikube”.

Con el comando kubectl get pudes obtener una lista de diferentes tipos de objetos “kubernetes” ( en nuestro ejemplo has pedido una lista de todos los objetos de tipo “node”).

Si quieres obtener detalles adicionales de un objeto puedes utilizar el comando describe con el tipo de objeto y nombre del objeto.

Por ejemplo, obtenén los detalles del objecto “minikube” de tipo “node”:

Terminal window
$ kubectl describe node minikube
Name: minikube
Roles: control-plane
...

La descripción muestra el estado del nodo, los datos de CPU y memoria, información del sistema, los contenedores que se están ejecutando dentro del nodo, y mucha más información.

La forma más habitual y senzilla es ejectuar un pod con un solo contenedor.

A continuación ejecuta un pod con un único contenedor apache:

Terminal window
$ kubectl run apache --image=httpd
pod/apache created

Con el comando get puedes ver todos los pods que estan desplegados en el clúster:

Terminal window
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
apache 1/1 Running 0 17s

Si quieres puedes obtener una descrición de un contenedor con el comando describe:

Terminal window
$ kubectl describe pod apache
...
IP: 10.244.0.13
IPs:
IP: 10.244.0.13
Containers:
apache:
Container ID: docker://ce53a65a3e96949e84ca92e7019eab5cbfdeff2ca0cfa7dff25c8718477b70b2
Image: httpd
Image ID: docker-pullable://httpd@sha256:437b9f7d469dd606fa6d2a5f9a3be55fe3af7e0c66e0329da8c14b291ae0d31c
Port: <none>
Host Port: <none>
State: Running
Started: Sat, 01 Feb 2025 22:19:29 +0100
Ready: True
...

Puedes ver que el pod tiene la IP 10.244.0.13 i un contenedor “apache”.

También puedes ejecutar un comando en un contenedor de la misma forma que lo haces con docker:

Terminal window
$ kubectl exec apache -- ls htdocs
index.html

Como el pod sólo tiene un contenedor no hay que especificar el contenedor, pero si no fuese así tienes que especificar el contendor con el argumento -c:

Terminal window
$ kubectl exec apache -c apache -- ls htdocs
index.html

Ejecuta bash en el contenedor “apache” en un terminal interactivo:

{% sol %}

Terminal window
$ kubectl exec -it apache -- bash
root@apache:/usr/local/apache2#

{% endsol %}

La IP de un pod es interna al clúster, la comparten todos los contenedores del pod, y cambia cada vez que se crea el pod.

Elimina el pod “apache” y vuelve a crear el pod:

Terminal window
$ kubectl delete pod apache
pod "apache" deleted
$ kubectl run apache --image=httpd
pod/apache created

Mira la dirección IP del pod con el flag -o wide:

Terminal window
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
apache 1/1 Running 0 5m28s 10.244.0.14 minikube <none> <none>

Si sólo quieres la dirección IP, puedes utilizar una “plantilla Go” para formatear la información del Pod y devolver solo la dirección IP del Pod.

Terminal window
$ kubectl get pod nginx-w29j2 -o=jsonpath='{.status.podIP}'
10.244.0.14

Si ejecutas curl puedes ver que no tienes acceso a esa IP:

Terminal window
$ curl -m 2 10.244.0.14
curl: (28) Connection timed out after 2037 milliseconds

Pero si entras dentro del cluster, tienes acceso al servidor “apache”:

Terminal window
$ minikube ssh
docker@minikube:~$ curl 10.244.0.14
<html><body><h1>It works!</h1></body></html>
docker@minikube:~$ exit
logout

Como hemos explicado al principio, la IP es interna del cluster, lo que quiere decir que cualquier pod puede utilizar esa IP porque compartenla misma red.

Crea un pod “nginx” y crea una session interativa:

{% sol %}

Terminal window
$ kubectl run nginx --image=nginx
pod/nginx created
box@k8s:~$ kubectl exec -it nginx -- bash
root@nginx:/#

{% endsol %}

Verifica que desde el contenedor “nginx” tienes acceso al contenedor “apache”:

Terminal window
$ curl 10.244.0.14
<html><body><h1>It works!</h1></body></html>

Otra manera de conectar-se a un pod para hacer pruebas, o para “debugging”, es mediante un port forwarding:

Terminal window
$ kubectl port-forward apache 8000:80
Forwarding from 127.0.0.1:8000 -> 80
Forwarding from [::1]:8000 -> 80

Ahora te puedes conectar directamente desde el navegador: http://localhost:8000/.

En {% link ”./service/” %} aprenderás como exponer un pod al exterior mediante la configuración de servicios.

De la misma forma que en {% link “p:/linux/docker/compose/” %} utilizas un fichero yaml para definir una composición de contenedores, con kuberntes también puede utilizar un fichero yaml para definir un pod.

A continuación mira la definicón del pod que está en ejecución en formato yaml:

$ kubectl get pod apache -o yaml
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: "2025-02-01T21:19:23Z"
labels:
run: apache
name: apache
namespace: default
resourceVersion: "3554"
uid: c58a72ec-83c7-4d4e-b49e-3413a72a2a2c
spec:
containers:
- image: httpd
imagePullPolicy: Always
name: apache
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
volumeMounts:
- mountPath: /var/run/secrets/kubernetes.io/serviceaccount
name: kube-api-access-gjqjw
readOnly: true
...

Puede parecer muy complicado al principio, pero a medida que aprendas los conceptos básicos y aprendas a distinguir las partes importatnes de lo que son detalles menores verás que es muy fácil de entender.

Además, para definir un pod no necesitas escribir todo esto.

A continuación vas a desplegar un pod con {% link “/data/mongodb/” %}

Crea un fichero mongodb.yaml:

apiVersion: v1
kind: Pod
metadata:
name: mongodb
spec:
containers:
- image: mongo
name: mongodb
ports:
- containerPort: 27017
protocol: TCP

Puedes ver que en la definición de un pod:

  • metadata incluye el nombre, el espacio de nombres, etiquetas y otra información acerca del pod.
  • spec incluye la descripción de los contenidos del pod, como son los contenedores, volumenes y otros datso.
  • status incluye la información acerca de la ejecución del pod, por lo que no forma parte del fichero de definición.

Puedes consultar para que sirve cada entrada del fichero con el comando explain.

Importante!. El puerto es sólo descriptivo, para que tu o cualquier otro sepa que puertos utiliza el contenedor.

Por ejemplo:

Terminal window
$ kubectl explain pod.spec
KIND: Pod
VERSION: v1
FIELD: spec <PodSpec>
...

Utiliza el comando create para crear un pod a partir de un fichero yaml:

Terminal window
$ kubectl create -f mongodb.yaml
pod/mongodb created

Puedes ver que ahora tines dos pods:

Terminal window
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
apache 1/1 Running 0 41m
mongodb 1/1 Running 0 54s

Conectacte a la base de datos mongodb desde el exterior con mongosh:

{% sol %} Abre otro terminal y haz un port forward:

Terminal window
$ kubectl port-forward mongodb 27017:27017
Forwarding from 127.0.0.1:27017 -> 27017
Forwarding from [::1]:27017 -> 27017

Conéctate com mongosh:

Terminal window
$ docker run --rm -it --network host mongo mongosh
Current Mongosh Log ID: 679ea6b415ca11579ae94969
Connecting to: mongodb://127.0.0.1:27017/?directConnection=true&serverSelectionTimeoutMS=2000&appName=mongosh+2.3.4
Using MongoDB: 8.0.4
Using Mongosh: 2.3.4
...
test>

{% endsol %}

Las aplicaciones que se ejectucan en contenedores normalmente no escriben los “logs” en ficheros, sinó que los envía a la salida estàndard, de tal forma que los usuarios pueden acceder a esa información de una manera simple y estàndar.

De esta forma, Docker redirige esos “streams” a ficheros que te permiten acceder a los “logs” de los contenedores a través de Docker de forma homogenea.

Puedes utilizar kubectl para acceder a esos logs, por ejemplo los de apache:

Terminal window
$ kubectl logs apache
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.244.0.4. Set the 'ServerName' directive globally to suppress this message
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.244.0.4. Set the 'ServerName' directive globally to suppress this message
[Sat Feb 01 21:19:29.784649 2025] [mpm_event:notice] [pid 1:tid 1] AH00489: Apache/2.4.63 (Unix) configured -- resuming normal operations
[Sat Feb 01 21:19:29.785020 2025] [core:notice] [pid 1:tid 1] AH00094: Command line: 'httpd -D FOREGROUND'
10.244.0.1 - - [01/Feb/2025:21:22:34 +0000] "GET / HTTP/1.1" 200 45
127.0.0.1 - - [01/Feb/2025:21:34:38 +0000] "GET / HTTP/1.1" 200 45
127.0.0.1 - - [01/Feb/2025:21:34:38 +0000] "GET /favicon.ico HTTP/1.1" 404 196

Ten en cuenta que cuando borras un pod ya no tienes acceso a los logs de los contenedores de ese pod.

Terminal window
$ kubectl delete pod apache
pod "apache" deleted
$ kubectl logs apache
error: error from server (NotFound): pods "apache" not found in namespace "default"

Si quieres conservar los logs de los pods incluso después de que sean eliminados, tienes que implementar un registro centralizado que guarde los logs de todo el clúster.

Un clúster kubernetes está pensado para desplegar centenares y miles de pods.

Por suerte, puedes poner etiquetas a los pods para organizar y poner orden.

De echo, puedes etiquetar cualquier tipo de objeto kubernetes.

Crea un pod con un contenedor nginx:

{% sol %}

Terminal window
$ kubectl run nginx --image nginx
pod/nginx created

{% endsol %}

A continuación vamos a etiquetar los tres pods con una etiqueta type:

Terminal window
$ kubectl label pod apache type=web
pod/apache labeled
$ ...

Por defecto el comando kubectl get pods no muestro las etiquetas, pero puedes hacer que se muestren con el paràmetro --show-labels:

Terminal window
$ kubectl get pods --show-labels
NAME READY STATUS RESTARTS AGE LABELS
apache 1/1 Running 0 17m run=apache,type=web
mongodb 1/1 Running 0 5m3s type=db
nginx 1/1 Running 0 8h run=nginx,type=web

Puede ver que además de nuestra etiqueta, los pods apache y nginx tienen la etiqueta run porque no los has creado a partir de un fichero sino directamente con kubectl run.

Además de la etiqueta type, añade la etiqueta env para indicar si un pod se ejectuda en entorno de producció o depuración:

Terminal window
$ kubectl label pod mongodb env=prod
pod/mongodb labeled
...

En lugar de ver todas las etiquetas con --show-labels, podemos seleccionar las etiquetas que queremos ver con el flafg -L, de tal manera que cada etiqueta se despliega en su propia columna:

Terminal window
$ kubectl get pods -L type,env
NAME READY STATUS RESTARTS AGE TYPE ENV
apache 1/1 Running 0 29m web prod
mongodb 1/1 Running 0 16m db prod
nginx 1/1 Running 0 8h web debug

Para modificar una etiqueta necesitas utilitzar el flag --overwrite, para evitar una modificación accidental:

Terminal window
$ kubectl label pod nginx env=test
error: 'env' already has a value (debug), and --overwrite is false
$ kubectl label pod nginx env=test --overwrite
pod/nginx labeled

Puedes ver que es fácil añadir etiquetas a los recursos y modificarlas.

En {% link ”./replication/” %} verás una de las utilidades más importantes que tienen.

De momento nos limitaremos a filtrar recursos mediante un selector de etiquetas.

Para ver todos los pods que estan en entorno de producción (etiquetados con env=prod), haz lo siguiente:

Terminal window
$ kubectl get pods -l env=prod
NAME READY STATUS RESTARTS AGE
apache 1/1 Running 0 41m
mongodb 1/1 Running 0 28m

Para tener una lista de todos los pods que tiene la etiqueta run, sin importar el valor de la etiqueta:

Terminal window
$ kubectl get pods -l run
NAME READY STATUS RESTARTS AGE
apache 1/1 Running 0 43m
nginx 1/1 Running 0 8h

I aquellos que no tienen la etiqueta run:

Terminal window
$ kubectl get pods -l '!run'
NAME READY STATUS RESTARTS AGE
mongodb 1/1 Running 0 31m

Observación. Tienes que utilizar comillas simple alrededor de !run para que el shell no evalue el signo de exclamación.

También puedes incluir diversos criterios separados por coma:

Terminal window
$ kubectl get pods -l env=prod,type=web
NAME READY STATUS RESTARTS AGE
apache 1/1 Running 0 47m

Kubernetes utiliza diferentes espacios de nombres para agrupar y separar recursos.

En un espacio de nombres el nombre del recurso debe ser único, pero puede haber recursos con el mismo nombre en diferentes espacios de nombres.

Mira los espacios de nombre que hay en tu cluster:

Terminal window
$ kubectl get namespaces
NAME STATUS AGE
default Active 21h
kube-node-lease Active 21h
kube-public Active 21h
kube-system Active 21h

Hasta ahora has utilizado el espacio de nombres default, que es el que se utiliza por defecto con kubectl.

Mira los pods que hay en el espacio de nombres kube-system:

Terminal window
$ kubectl get pods --namespace kube-system
NAME READY STATUS RESTARTS AGE
coredns-668d6bf9bc-qbhmr 1/1 Running 1 (9h ago) 21h
etcd-minikube 1/1 Running 1 (9h ago) 21h
kube-apiserver-minikube 1/1 Running 1 (9h ago) 21h
kube-controller-manager-minikube 1/1 Running 1 (9h ago) 21h
kube-proxy-x7ghr 1/1 Running 1 (9h ago) 21h
kube-scheduler-minikube 1/1 Running 1 (9h ago) 21h
storage-provisioner 1/1 Running 3 (9h ago) 21h

Tip. Puedes utilizar -n en lugar de --namespace.

En otras actividades aprenderás acerca de estos pods, pero a partir del nombre kube-system puedes intuir que se trata de pods relacions con el sistema de ejecución de kubernetes.

Los espacios de nombre permiten aislar recursos y permitir que sólo determinados usuarios puedan acceder a dichos recursos o incluso limitar la capacidad de los recursos de usuarios concretos.

Un espacio de nombres es como cualquier otro recurso, y lo podemos crear con un fichero yaml:

apiVersion: v1
kind: Namespace
metadata:
name: xtec

Utiliza kubectl para enviar el fichero al servidor API kubernetes:

Terminal window
$ kubectl create -f namespace.yaml
namespace/xtec created

Como puedes haver adivinado también lo puedes crear directamente por linea de comandos:

Terminal window
$ kubectl create namespace keko
namespace/keko created

A continuación crea un servidor caddy con el nombre “caddy” en el espacio de nombres xtec:

Terminal window
$ kubectl run caddy --image=caddy -n xtec
pod/caddy created

Puedes ver que no aparece en el espacio de nombres default:

Terminal window
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
apache 1/1 Running 0 72m
mongodb 1/1 Running 0 59m
nginx 1/1 Running 0 9h

Pero si en el espacio de nombres xtec:

{% sol %}

Terminal window
$ kubectl get pods -n xtec
NAME READY STATUS RESTARTS AGE
caddy 1/1 Running 0 76s

{% endsol %}

Haz un “port fowrard”:

Terminal window
$ kubectl port-forward caddy 3000:80 -n xtec
Forwarding from 127.0.0.1:3000 -> 80
Forwarding from [::1]:3000 -> 80
Handling connection for 3000

Puedes ver el servidor caddy funcionando: http://localhost:3000/.

Aunque los pods se ejecuten en espacios separados, se pueden comunicar entre ellos en función del tipo de solución de red se haya desplegado en el cluster.

Nuestro “minikube” utiliza una solució simple como puedes ver a continuación:

Terminal window
$ kubectl get pod -o wide | grep apache
apache 1/1 Running 0 84m 10.244.0.16 minikube <none> <none>
$ kubectl exec -it caddy -n xtec -- sh
/srv $ apk add curl
OK: 13 MiB in 30 packages
/srv $ curl 10.244.0.16
<html><body><h1>It works!</h1></body></html>

A diferencia de docker, con kubernetes no puedes parar contenedores, sólo los puedes crear o eliminar pods.

Puedes elimar un pod por su nombre:

Terminal window
$ kubectl delete pod mongodb
pod "mongodb" deleted

O eliminar un conjunto de pods mediante un selector de etiquetas:

Terminal window
$ kubectl delete pod -l type=web
pod "apache" deleted
pod "nginx" deleted

Incluso puedes eliminar todo un espacio de nombres (incluyendo todos los recursos):

Terminal window
$ kubectl delete ns xtec
namespace "xtec" deleted

El contingut d'aquest lloc web té llicència CC BY-NC-ND 4.0.

©2022-2025 xtec.dev