Kubernetes es una potente plataforma de orquestación de contenedores, pero para aprovechar todo su potencial, es importante comprender sus componentes principales, con los pods y servicios desempeñando roles fundamentales. En este artículo, profundizaremos en qué son y cómo trabajan juntos para exponer y gestionar el acceso a las aplicaciones que se ejecutan dentro de un clúster de Kubernetes.
¿Qué es un Pod?
Los pods son las unidades desplegables más pequeñas de computación que puedes crear y gestionar en Kubernetes.
Antes de crear un pod, revisemos los recursos de la API disponibles en tu clúster de Kubernetes; puedes usar el comando kubectl api-resources
. Este comando lista los recursos de la API que son compatibles con el servidor de API de Kubernetes, incluyendo sus nombres cortos, grupos de API y si están en espacio de nombres o no. Esto es útil para comprender las capacidades de tu clúster, especialmente al trabajar con recursos personalizados o explorar nuevas características de Kubernetes. El comando kubectl explain
complementa esto proporcionando información detallada sobre recursos individuales.
Creemos un archivo de configuración básico para un pod que ejecute un contenedor Nginx simple.
Crea un archivo llamado nginx-pod.yaml
:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Aquí tienes una breve explicación de los términos utilizados:
- apiVersion: v1: Especifica la versión de la API.
- kind: Pod: Indica que esta configuración es para un pod.
- metadata:name: El nombre del pod.
- metadatos: etiquetas: Pares de clave-valor que se pueden utilizar para organizar y seleccionar el pod.
- especificación:contenedores: Una lista de contenedores que se ejecutarán en el pod.
- especificación:contenedores:nombre: El nombre del contenedor.
- especificación:contenedores:imagen: La imagen del contenedor a utilizar (en este caso, la última imagen de Nginx).
- especificación:contenedores:puertos: Los puertos a exponer desde el contenedor.
Usa kubectl
para aplicar el archivo de configuración y crear el pod:
kubectl apply -f nginx-pod.yaml
Verifica el estado del pod para asegurarte de que se haya creado y esté en ejecución:
kubectl get pods
Deberías ver una salida similar a esta:
NAME READY STATUS RESTARTS AGE
nginx-pod 1/1 Running 0 10s
A continuación, elimina el pod:
kubectl delete pod nginx-pod
La salida debería ser similar a la siguiente:
kubectl get pod
No resources found in default namespace.
¿Qué es un Servicio?
Crear un servicio para un pod de Nginx en Kubernetes te permite exponer la aplicación de Nginx y hacerla accesible dentro o fuera del clúster. Aquí tienes una guía paso a paso para crear un Servicio para un pod de Nginx.
Para asegurarte de que tienes un pod de Nginx en ejecución, si aún no tienes uno, crea un archivo YAML llamado nginx-pod.yaml
:
apiVersion: v1
kind: Pod
metadata:
name: nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Aplica la configuración del Pod:
kubectl apply -f nginx-pod.yaml
Cree un archivo YAML llamado nginx-service.yaml
para definir el Servicio:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
type: ClusterIP
Aquí hay algunas cosas a tener en cuenta:
- selector: Un selector de etiqueta para que coincida con el pod de Nginx.
- app: nginx: Esto debería coincidir con la etiqueta en el pod de Nginx.
- type: ClusterIP: El tipo de Servicio. ClusterIP hace que el Servicio solo sea accesible dentro del clúster. También puedes usar NodePort o LoadBalancer para exponer el Servicio externamente.
Aplica la configuración del Servicio usando kubectl
:
kubectl apply -f nginx-service.yaml
kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
nginx-service ClusterIP 10.96.0.1 <none> 80/TCP 10s
Dado que el Servicio es de tipo ClusterIP, solo es accesible dentro del clúster. Para acceder desde fuera del clúster, puedes cambiar el tipo de Servicio a NodePort o LoadBalancer.
Para exponer el Servicio externamente usando NodePort
, modifica el archivo nginx-service.yaml
:
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app: nginx
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30007 # Specify a node port in the range 30000-32767 (optional)
type: NodePort
Aplica la configuración actualizada del Servicio:
kubectl apply -f nginx-service.yaml
Ahora puedes acceder a la aplicación Nginx utilizando la dirección IP del nodo y el puerto del nodo (por ejemplo, http://<node-ip>:30007).
Pods de varios contenedores
Usar un solo contenedor por pod proporciona la máxima granularidad y desacoplamiento. Sin embargo, hay escenarios donde desplegar múltiples contenedores, a veces denominados contenedores compuestos, dentro de un solo pod es beneficioso. Estos contenedores secundarios pueden desempeñar diversos roles: manejar el registro o mejorar el contenedor primario (concepto de sidecar), actuar como proxy para sistemas externos (concepto de embajador) o modificar datos para que se ajusten a un formato externo (concepto de adaptador). Estos contenedores secundarios complementan al contenedor primario realizando tareas que este no maneja.
A continuación se muestra un ejemplo de una configuración de Pod de Kubernetes que incluye un contenedor primario ejecutando un servidor Nginx y un contenedor secundario actuando como un sidecar para manejar el registro. El contenedor sidecar utiliza un contenedor de registro simple como BusyBox para demostrar cómo puede seguir los registros de acceso de Nginx.
apiVersion: v1
kind: Pod
metadata:
name: nginx-with-logging-sidecar
spec:
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
volumeMounts:
- name: shared-logs
mountPath: /var/log/nginx
- name: log-sidecar
image: busybox:latest
command: ["sh", "-c", "tail -f /var/log/nginx/access.log"]
volumeMounts:
- name: shared-logs
mountPath: /var/log/nginx
volumes:
- name: shared-logs
emptyDir: {}
A continuación, hará lo siguiente:
- Guarde la configuración YAML en un archivo, por ejemplo,
nginx-with-logging-sidecar.yaml
. - Aplique la configuración usando
kubectl:kubectl apply -f nginx-with-logging-sidecar.yaml
. - Verifique que el Pod esté en ejecución:
kubectl get pods
. - Revise los registros del contenedor sidecar para ver los registros de acceso de Nginx:
kubectl logs -f <nombre-del-pod> -c log-sidecar
.
Siguiendo estos pasos, eliminarás el Pod existente y aplicarás la nueva configuración, configurando un Pod con un contenedor Nginx y un contenedor sidecar para el registro. Esto asegurará que la nueva configuración esté activa y en funcionamiento en tu clúster de Kubernetes.
Los pods con múltiples contenedores en Kubernetes ofrecen varias ventajas, permitiendo despliegues y gestión de aplicaciones más flexibles y eficientes.
Patrones de Pods con Múltiples Contenedores
Patrón de Sidecar
Los contenedores sidecar pueden mejorar la aplicación principal al proporcionar funciones auxiliares como registro, gestión de configuración o proxy. Este patrón ayuda a extender la funcionalidad sin modificar el contenedor principal. Un contenedor sidecar puede encargarse del registro recopilando y reenviando registros desde el contenedor de la aplicación principal.
Patrón de Embajador
Los contenedores embajadores actúan como un proxy, gestionando la comunicación entre la aplicación principal y los servicios externos. Esto puede simplificar la integración y la configuración. Un contenedor embajador puede encargarse de la terminación de SSL o funciones de puerta de enlace API.
El patrón de embajador implica el uso de un contenedor sidecar para gestionar la comunicación entre la aplicación principal y los servicios externos. Este patrón puede encargarse de tareas como proxy, equilibrio de carga o gestión de conexiones seguras, abstrayendo así la complejidad del contenedor de la aplicación principal.
- Contenedor de Aplicación Principal: Un servidor web simple que realiza solicitudes HTTP
- Contenedor Embajador: Proxy Envoy configurado para gestionar las solicitudes a la API externa
apiVersion: v1
kind: Pod
metadata:
name: app-with-ambassador
spec:
containers:
- name: web-app
image: python:3.8-slim
command: ["python", "-m", "http.server", "8000"]
volumeMounts:
- name: config-volume
mountPath: /etc/envoy
- name: envoy-proxy
image: envoyproxy/envoy:v1.18.3
args: ["-c", "/etc/envoy/envoy.yaml"]
ports:
- containerPort: 8080
volumeMounts:
- name: config-volume
mountPath: /etc/envoy
volumes:
- name: config-volume
configMap:
name: envoy-config
---
apiVersion: v1
kind: ConfigMap
metadata:
name: envoy-config
data:
envoy.yaml: |
static_resources:
listeners:
- name: listener_0
address:
socket_address:
address: 0.0.0.0
port_value: 8080
filter_chains:
- filters:
- name: envoy.filters.network.http_connection_manager
typed_config:
"@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
stat_prefix: ingress_http
route_config:
name: local_route
virtual_hosts:
- name: local_service
domains: ["*"]
routes:
- match:
prefix: "/"
route:
cluster: external_service
http_filters:
- name: envoy.filters.http.router
clusters:
- name: external_service
connect_timeout: 0.25s
type: LOGICAL_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: external_service
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: api.example.com
port_value: 80
Este ejemplo demuestra el patrón de Embajador en Kubernetes, donde un proxy Envoy actúa como intermediario para gestionar la comunicación externa para el contenedor de la aplicación principal. Este patrón ayuda a abstraer las complejidades de la comunicación y mejora la modularidad y mantenibilidad.
Patrón Adaptador
Los contenedores de adaptador pueden modificar o transformar datos entre la aplicación principal y sistemas externos, asegurando la compatibilidad e integración. Por ejemplo, un contenedor de adaptador puede reformatear datos de registro para cumplir con los requisitos de un servicio de registro externo.
El patrón Adaptador en Kubernetes implica usar un contenedor auxiliar para transformar datos entre el contenedor de la aplicación principal y sistemas externos. Esto puede ser útil cuando la aplicación principal requiere datos en un formato específico que difiere del formato proporcionado o requerido por los sistemas externos.
Supongamos que tienes un contenedor de aplicación principal que genera registros en un formato personalizado. Necesitas enviar estos registros a un servicio de registro externo que requiere registros en un formato estándar específico. Un contenedor de adaptador puede ser utilizado para transformar los datos de registro al formato requerido antes de enviarlos al servicio externo.
- Contenedor de Aplicación Principal: Una aplicación sencilla que escribe registros en un formato personalizado.
- Contenedor de Adaptador: Un contenedor que lee los registros personalizados, los transforma al formato JSON y los envía a un servicio de registro externo.
apiVersion: v1
kind: Pod
metadata:
name: app-with-adapter
spec:
containers:
- name: log-writer
image: busybox
command: ["sh", "-c", "while true; do echo \"$(date) - Custom log entry\" >> /var/log/custom/app.log; sleep 5; done"]
volumeMounts:
- name: shared-logs
mountPath: /var/log/custom
- name: log-adapter
image: busybox
command: ["sh", "-c", "tail -f /var/log/custom/app.log | while read line; do echo \"$(echo $line | sed 's/ - / - {\"timestamp\": \"/;s/$/\"}/')\" >> /var/log/json/app.json; done"]
volumeMounts:
- name: shared-logs
mountPath: /var/log/custom
- name: json-logs
mountPath: /var/log/json
- name: log-sender
image: busybox
command: ["sh", "-c", "while true; do cat /var/log/json/app.json | grep -v '^$' | while read line; do echo \"Sending log to external service: $line\"; done; sleep 10; done"]
volumeMounts:
- name: json-logs
mountPath: /var/log/json
volumes:
- name: shared-logs
emptyDir: {}
- name: json-logs
emptyDir: {}
Este ejemplo demuestra el patrón Adaptador en Kubernetes, donde un contenedor adaptador transforma los datos del contenedor de la aplicación principal al formato requerido antes de enviarlo a un sistema externo. Este patrón ayuda a integrar aplicaciones con servicios externos al manejar transformaciones de formato de datos dentro del contenedor auxiliar.
Resumen
En resumen, pods:
- Son las unidades desplegables más pequeñas en Kubernetes.
- Representan una única instancia de un proceso en ejecución.
- Pueden contener uno o más contenedores.
Servicios:
- Proporcionan una dirección IP estable y un nombre DNS para acceder a los pods.
- Permiten el equilibrio de carga entre un conjunto de pods.
- Facilitan el descubrimiento de servicios dentro del clúster.
Source:
https://dzone.com/articles/the-ultimate-guide-to-kubernetes-pods-and-services