776 - La guía definitiva de Logs en Podman. Automatización, Quadlets y Vector
Aprende a gestionar logs en Podman con JournalD. Descubre scripts para monitorizar Quadlets, configurar límites de disco y automatizar tu seguridad.
Estamos ya a un solo episodio de configurar Traefik en Podman, con todo lo que eso conlleva. Pero, antes de meternos en ese jardín quiero dejar completamente resuelto una parte, que yo considero realmente importante, como son los logs. Soy consciente que hay quien no le dedica ni un segundo al asunto de los logs, porque le resulta mas sencillo directamente, preguntar a cualquiera porque no funciona mi contenedor. Sin embargo, los logs dan justo la respuesta a este tipo de preguntas. Y es mas, hoy en día gracias a los modelos de lenguaje, la facilidad que tienes para resolverla es enorme. Ya no es necesario ser un auténtico experto en la materia, para poder interpretar los logs y encontrar la solución a tus problemas. De hecho, es mas, con un poco de práctica, vas a ser capaz de interpretar los logs de una forma realmente sencilla. Y eso es lo que te voy a contar hoy, como gestionar los logs en Podman. Pero incluso, si no quieres ni aprender a interpretarlos, simplemente, lo que tienes que hacer es copiar el log y pegarlo en Gemini, ChatGPT o cualquier otro modelo de lenguaje, y te va a dar la solución a tu problema. Así de sencillo. Y es que, los logs son la clave para resolver cualquier problema que tengas con tus contenedores. Así que, si quieres ser un auténtico experto en la materia, no puedes dejar de aprender a gestionar los logs en Podman.

La guía definitiva de Logs en Podman. Automatización, Quadlets y Vector
El log de Podman
Podman utiliza principalmente dos drivers para capturar la salida estándar (stdout) y el error estándar (stderr) de tus contenedores, journald y k8s-file. El driver journald envía los logs directamente al sistema de registro de systemd, lo que permite una integración fluida con las herramientas de monitoreo y análisis de logs de systemd. Por otro lado, el driver k8s-file escribe los logs en archivos específicos en el sistema de archivos, lo que facilita su acceso y gestión.
Si quieres configurarlo al lanzar un contenedor, simplemente tienes que añadir la opción --log-driver seguida del nombre del driver que deseas utilizar. Por ejemplo, para usar journald, el comando sería:
podman run --log-driver journald <nombre-del-contenedor>
Y si lo quisieras hacer en el Quadlet, utiliza la opción LogDriver dentro de la sección [Contaier], como por ejemplo,
[Container]
Image="nginx:latest"
LogDriver="journald"
Algunas opciones de configuración
Como sabes, uno de los problemas a los que nos enfrentamos a la hora de gestionar los logs, es que pueden crecer de forma descontrolada, ocupando todo el espacio disponible en el disco. Para evitar esto, Podman ofrece varias opciones de configuración para limitar el tamaño de los logs y controlar su rotación. Por ejemplo, desde la línea de comandos puedes hacerlo de la siguiente forma,
podman run -d \
--log-driver=k8s-file \
--log-opt max-size=10mb \
--log-opt max-file=3 \
nginx
Esto mantendrá un máximo de 3 archivos de 10MB cada uno, borrando el más antiguo automáticamente.
Pero la gran magia viene de los Quadlets y su integración con systemd. Al configurar el driver journald, los logs de tus contenedores se integrarán directamente con el sistema de registro de systemd, lo que te permitirá utilizar herramientas como journalctl para acceder a ellos de una forma mucho más sencilla y eficiente. De esta manera, no te tienes que preucupar por la gestión de los archivos de logs, ya que systemd se encargará de rotarlos y gestionarlos automáticamente, asegurando que no ocupen más espacio del necesario en tu disco.
En este sentido, es importante tener configurado determinados aspectos de journald en lo que a la política de retención de logs se refiere para evitar que los logs crezcan de forma descontrolada. Para ello, puedes configurar parámetros como SystemMaxUse, SystemKeepFree, SystemMaxFileSize y SystemMaxFiles en el archivo de configuración de journald (/etc/systemd/journald.conf).
| Directiva | Qué hace | Ejemplo de valor |
|---|---|---|
| SystemMaxUse | Espacio máximo total en disco. | SystemMaxUse=2G |
| SystemKeepFree | Espacio mínimo que debe quedar libre en el disco. | SystemKeepFree=10G |
| MaxRetentionSec | Tiempo máximo que se guarda un log (edad). | MaxRetentionSec=1month |
| MaxFileSec | Tiempo máximo antes de saltar a un nuevo archivo de journal. | MaxFileSec=1week |
Por ejemplo el archivo /etc/systemd/journald.conf podría quedar de la siguiente forma,
[Journal]
# Asegura que los logs se guarden en disco y no solo en RAM
Storage=persistent
# Compresión automática para ahorrar espacio
Compress=yes
# LÍMITES DE ESPACIO
# No usar más de 1GB en total para todos los logs (sistema + usuario)
SystemMaxUse=1G
# Mantener al menos el 10% del disco libre de logs
SystemKeepFree=100G
# LÍMITES DE TIEMPO
# Borrar logs que tengan más de 2 semanas (ajusta según necesites)
MaxRetentionSec=2week
# Evitar que un proceso loco inunde el journal (Rate Limiting)
# Máximo 10,000 mensajes cada 30 segundos
RateLimitIntervalSec=30s
RateLimitBurst=10000
Una vez hecho esto, simplemente aplicas los cambios con sudo systemctl restart systemd-journald y ya tendrás tu sistema de logs configurado para que no se te descontrole.
Una vez reiniciado, puedes comprobar que el sistema está funcionado como se espera utilizando los siguientes comandos,
# Ver cuánto ocupan los logs ahora mismo
journalctl --disk-usage
# Ver si hay mensajes de rotación o borrado por espacio
sudo journalctl -u systemd-journald
Como tus Quadlets corren en el espacio de usuario, si quieres forzar una limpieza de tus logs específicos sin afectar a los del sistema, puedes usar el comando de vacío,
- Por tiempo:
journalctl --user --vacuum-time=7d - Por tamaño:
journalctl --user --vacuum-size=200M
Por curiosidad, si quieres ver la fecha del primer mensaje en tu journal, puedes usar el siguiente comando,
journalctl | head -n 1
Y para rematar la operación, podemos hacer un script en fish que nos reporte el estado de salud de nuestros Quadlets,
#!/usr/bin/fish
function check_scope -a scope
set -l cmd systemctl
set -l j_scope ""
if test "$scope" = "--user"
set cmd systemctl --user
set j_scope "--user"
end
# Obtenemos las unidades, limpiamos el punto (●) y filtramos solo .service
set -l units ($cmd list-units --type=service --all --no-legend | awk '{print $1}' | string match -v "●" | string match "*.service")
for unit in $units
# Verificamos si es realmente un servicio de Podman/Quadlet mediante su descripción o dependencias
if $cmd show $unit --property=Description,Wants,Requires | string match -rq "podman|quadlet"
set -l state ($cmd is-active $unit)
set -l color (set_color red)
if test "$state" = "active"; set color (set_color green); end
# Buscamos errores en las últimas 24h
set -l errors (journalctl $j_scope -u $unit --since "-24h" -p 3..0 | wc -l)
set -l err_color (set_color normal)
if test "$errors" -gt 0; set err_color (set_color --bold red); end
printf "[%-7s] %-45s %s%-10s%s Errores: %s%s%s\n" \
(string replace -- "--" "" $scope) $unit $color $state (set_color normal) $err_color $errors (set_color normal)
end
end
end
function check_quadlets --description "Revisa el estado de los servicios de los Quadlets "
echo (set_color --bold blue)"=== Reporte de Salud de Quadlets ==="(set_color normal)
check_scope --system
check_scope --user
end
Vector
Esto ya no tiene que ver exactamente con la gesión de logs en Podman, pero es que no puedo evitar hablar de Vector, una herramienta de recolección y procesamiento de logs que se integra perfectamente con journald. Con Vector, puedes enviar tus logs a una variedad de destinos, como Elasticsearch, Kafka o incluso a un servicio de monitoreo en la nube. Esto te permite centralizar tus logs y analizarlos de una forma mucho más eficiente, especialmente si tienes múltiples contenedores corriendo en tu sistema.
Así, el flujo de datos sería algo como lo que te muestro a continuación,
Contenedor (Quadlet) → journald → Vector → Otras apps (OpenObserve)
Actualmente estoy utilizando OpenObserve como plataforma de monitoreo y análisis de logs, y la verdad es que la integración con Vector ha sido realmente sencilla. Con unos pocos ajustes en la configuración de Vector, he podido enviar mis logs directamente a OpenObserve, lo que me permite tener una visión completa de lo que está sucediendo en mis contenedores y detectar cualquier problema de forma rápida y eficiente.
Así, por ejemplo, si quisieras configurar Vector para enviar tus logs a OpenObserve, podrías hacerlo de la siguiente forma,
sources:
journal_logs:
type: "journald"
# Filtrar para no enviar logs de todo el sistema si no quieres
# Puedes incluir solo los de tus servicios de usuario
include_units:
- "mi-servicio-quadlet.service"
transforms:
parse_logs:
type: "remap"
inputs: ["journal_logs"]
source: |
.message = parse_json(.message) ?? .message
.container_name = .CONTAINER_NAME
.timestamp = .get_entry_timestamp!
sinks:
openobserve_out:
type: "http"
inputs: ["parse_logs"]
uri: "https://tu-instancia-openobserve/api/default/ingest/_json"
method: "post"
auth:
strategy: "basic"
user: "${OPENOBSERVE_USER}"
password: "${OPENOBSERVE_PASSWORD}"
encoding:
codec: "json"
Una de las grandes ventajas de utilizar Vector es que te permite procesar tus logs antes de enviarlos a tu plataforma de monitoreo. Por ejemplo, puedes utilizar transformaciones para extraer información relevante de tus logs, como el nombre del contenedor o la marca de tiempo, lo que facilita enormemente el análisis posterior en OpenObserve. Pero no solo esto, si no que también puedes definir múltiples destinos para tus logs, lo que te permite tener una estrategia de monitoreo más robusta y flexible. Por ejemplo, podrías enviar tus logs a OpenObserve para el análisis en tiempo real, pero también mandarlos a otra aplicación tipo Fail2Ban, para análisis.
Esta solución es bastante mejor que utilizar Fail2Ban,
- Pre-procesamiento. Vector ya te entrega el JSON parseado. Tu app no tiene que pelearse con Regex; solo hace un serde_json::from_str en Rust y ya tiene la IP y el código de error.
- Menos I/O de disco. Si usas sockets, los logs pasan de un proceso a otro sin tocar el SSD de la Raspberry Pi, alargando su vida útil.
- Filtros inteligentes. Puedes configurar Vector para que solo envíe a tu app los logs que tengan un status_code de 400, 401 o 404, ahorrándole trabajo de procesamiento.
Por ejemplo,
- Contar ocurrencias de client_ip.
- Si path contiene «wp-login» o «.env» y se repite 3 veces…
- Ejecutar un comando de baneo (vía nftables o incluso la API de Cloudflare si la usas). O mas sencillo todavía, si estás utilizando Traefik, puedes configurar una regla de bloqueo directamente en Traefik, sin necesidad de una aplicación externa. Por ejemplo, podrías configurar una regla que bloquee cualquier IP que intente acceder a rutas específicas como
/wp-logino/.envmás de 3 veces en un período de tiempo determinado. Esto se puede hacer utilizando la funcionalidad de middlewares de Traefik, como elRateLimito elIPWhitelist, para proteger tu aplicación de ataques comunes.
Conclusión
Soy consciente que esto de los logs es algo que no llama la atención de nadie, pero es que es realmente importante. De hecho, es la clave para resolver cualquier problema que tengas con tus contenedores. Así que, si quieres ser un auténtico experto en la materia, no puedes dejar de aprender a gestionar los logs en Podman. Y recuerda, si no quieres ni aprender a interpretarlos, simplemente, lo que tienes que hacer es copiar el log y pegarlo en Gemini, ChatGPT o cualquier otro modelo de lenguaje, y te va a dar la solución a tu problema. Así de sencillo.