Cuando nuestro sistema de contenedores en docker comienza a crecer y crecer el sistema de logs configurado por defecto deja de ser práctico (o más bien, un infierno) sobre todo al realizar búsquedas.
Graylog es un sistema de recolección, análisis y visualización de logs basado en Elasticsearch. Con este sistema, además de poder recoger los logs de nuestros contenedores de docker para analizarlos y realizar búsquedas, podemos configurarlo para recoger logs de otros sistemas a través de protocolos como syslog, como routers o logs del sistema).
Para esto vamos a usar dos componentes: Graylog, que ya debe de estar previamente instalado y Promtail, un enrutador de logs.
En este post damos por hecho que Graylog ya lo tenemos instalando y funcionando. Si tengo tiempo escribiré también un post sobre como instalar Graylog en una VM sobre Proxmox, que es como lo tengo actualmente corriendo.
Graylog
La configuración “inicial” en Graylog para empezar a recibir logs es muy sencilla, solo es necesario crear un input para que empiece a escuchar logs en un puerto y los almacene.
Definición de Input
Creamos un Input
en Graylog asociado a estos logs de Docker. Para ello desde la consola de Graylog vamos a System -> Inputs. En el menú desplegable seleccionamos GELF UDP y a continuación pulsamos en Launch new input. Podemos dejar toda la configuración por defecto, solo debemos de indicar un título.
Logspout
Antes de usar Logspout intenté configurar el driver de logs de docker para escribiera directamente en Graylog con el driver GELF. Sin embargo, me encontré con estos problemas:
-
Configuración dependiente del entorno. Esto es, la configuración de los logs se encuentra en un fichero del sistema, por lo que ya no es tan fácil de configurar como ejecutar un
docker-compose
. -
En nuestras pruebas, observamos un comportamiento anómalo de docker cuando el servidor de Graylog se desconectaba o dejaba de funcionar.
-
Ya no se pueden leer los logs desde docker con un
docker logs
. Esa opción ya no estaría disponible con el driver.
Por tanto, estudiamos la posibilidad de usar un contendor para realizar esta operación, y encontramos Logspout, que entre otras cosas nos proporciona:
-
Facilidad de configuración, ya que se puede especificar toda su configuración en el mismo fichero
docker-compose
con el resto de servicios. -
No inhabilita el driver propio de docker, con lo que es posible seguir haciendo un
docker logs
.
Configuración
Logspout de forma nativa trabaja con un servidor de syslog. Tenemos dos opciones: configurar Graylog para actuar como servidor de syslog o usar un módulo de Logspout que permita enviar los logs en formato GELF como logspout-gelf
. GELF tiene mejoras respecto a syslog interesantes.
No he encontrado ninguna imagen actualizada de logspout-gelf
, por lo que he partido de esta versión para crear mi propio Dockerfile con la última versión disponible en este momento, la 3.2.13. Recuerda cambiar la versión (LOGSPOUT_VERSION
) y la suma de verificación (LOGSPOUT_DOWNLOAD_SHA256
) a la última versión disponible.
FROM golang:alpine as build
ENV LOGSPOUT_VERSION=3.2.13
ENV LOGSPOUT_DOWNLOAD_SHA256=825f00025413dd35144a2c2f30a4371d212bf5be78dd2ff934baeef333d0131c
RUN mkdir -p /go/src
WORKDIR /go/src
VOLUME /mnt/routes
EXPOSE 80
RUN apk --no-cache add curl git gcc musl-dev
RUN curl -fSL -o logspout.tar.gz "https://github.com/gliderlabs/logspout/archive/v${LOGSPOUT_VERSION}.tar.gz" \
&& echo "$LOGSPOUT_DOWNLOAD_SHA256 *logspout.tar.gz" | sha256sum -c - \
&& tar -zxvf logspout.tar.gz \
&& rm logspout.tar.gz \
&& mkdir -p /go/src/github.com/gliderlabs/ \
&& mv logspout-${LOGSPOUT_VERSION} /go/src/github.com/gliderlabs/logspout
WORKDIR /go/src/github.com/gliderlabs/logspout
RUN echo 'import ( _ "github.com/micahhausler/logspout-gelf" )' >> /go/src/github.com/gliderlabs/logspout/modules.go
RUN go get -d -v ./...
RUN go build -v -ldflags "-X main.Version=$(cat VERSION)" -o ./bin/logspout
FROM alpine:latest
COPY --from=build /go/src/github.com/gliderlabs/logspout/bin/logspout /go/bin/logspout
ENTRYPOINT ["/go/bin/logspout"]
Y en el fichero docker-compose definimos un contenedor con la imagen del Dockerfile que hemos creado antes. Cambiamos la variable de entorno ROUTE_URIS
con la dirección IP de Graylog.
version: "2.4"
services:
logspout:
container_name: logspout
build: ./logspout # Folder where is the logspout-gelf Dockerfile
volumes:
- '/var/run/docker.sock:/var/run/docker.sock'
environment:
LOGSTASH_TAGS: "docker,production"
ROUTE_URIS: "gelf://XX.XX.XX.XX:12201" # Graylog server IP and GELF UDP port configured in Graylog GUI
Arrancamos el contenedor con un docker-compose up -d
.
Pruebas
Para comprobar que todo está funcionando bien volvemos a Graylog, en el apartado de Input y veremos que el input que hemos creado anteriormente ya está recibiendo mensajes.
Se puede ver tráfico en el campo Network IO, lo que significa que ya están llegando mensajes. Si vamos al apartado de Search podremos ver los mensajes de logs que nos llegan.
Este es un log de unos de los contendores que tengo instalados (concretamente, Nextcloud).
Graylog Extractors, Dashboards, Alerts and more
Hasta aquí hemos conseguido volcar nuestros logs a la plataforma Graylog. Ahora llega lo más interesante, configurar las herramientas propias de Graylog para explotar todos esos logs con estadísticas, dashboards, búsquedas que nos faciliten el trabajo de depuración y obtención de estadísticas, fallos, etc.
En los próximos posts iré analizando cada una de las opciones con las que podemos extraer más de este sistema de logs.