Splunk Universal Forwarder en Docker como recolector de logs del sistema

Splunk Universal Forwarder en Docker como recolector de logs del sistema

Splunk es uno de los productos comerciales más reconocibles para la recolección y análisis de registros. Aunque actualmente no se realizan ventas en Rusia, eso no significa que no debamos escribir guías sobre este producto.

Tarea: recopilar registros del sistema desde nodos de docker en Splunk sin cambiar la configuración de la máquina host

Me gustaría comenzar con el enfoque oficial, que resulta un tanto extraño al utilizar Docker.
Enlace a Docker hub
Entonces, ¿qué tenemos?

1. Descargar la imagen

$ docker pull splunk/universalforwarder:latest

2. Iniciar el contenedor con los parámetros necesarios

$ docker run -d -p 9997:9997 -e 'SPLUNK_START_ARGS=--accept-license' -e 'SPLUNK_PASSWORD=' splunk/universalforwarder:latest

3. Acceder al contenedor

docker exec -it  /bin/bash

A continuación, se nos pide que vayamos a la dirección conocida en la documentación.

Y configurar el contenedor después de su inicio:


./splunk add forward-server :
./splunk add monitor /var/log
./splunk restart

Espera. ¿Qué?

Pero las sorpresas no terminan aquí. Si inicias el contenedor desde la imagen oficial en modo interactivo, verás lo siguiente:

Un poco de decepción


$ docker run -it -p 9997:9997 -e 'SPLUNK_START_ARGS=--accept-license' -e 'SPLUNK_PASSWORD=password' splunk/universalforwarder:latest

PLAY [Ejecutar la provisión predeterminada de Splunk] *******************************************************************************************************************************************************************************************************
Martes 09 de abril de 2019  13:40:38 +0000 (0:00:00.096)       0:00:00.096 *********

TASK [Recolección de Hechos] ***********************************************************************************************************************************************************************************************************************
ok: [localhost]
Martes 09 de abril de 2019  13:40:39 +0000 (0:00:01.520)       0:00:01.616 *********

TASK [Obtener el hostname actual] *******************************************************************************************************************************************************************************************************************
changed: [localhost]
Martes 09 de abril de 2019  13:40:40 +0000 (0:00:00.599)       0:00:02.215 *********
Martes 09 de abril de 2019  13:40:40 +0000 (0:00:00.054)       0:00:02.270 *********

TASK [set_fact] ******************************************************************************************************************************************************************************************************************************
ok: [localhost]
Martes 09 de abril de 2019  13:40:40 +0000 (0:00:00.075)       0:00:02.346 *********
Martes 09 de abril de 2019  13:40:40 +0000 (0:00:00.067)       0:00:02.413 *********
Martes 09 de abril de 2019  13:40:40 +0000 (0:00:00.060)       0:00:02.473 *********
Martes 09 de abril de 2019  13:40:40 +0000 (0:00:00.051)       0:00:02.525 *********
Martes 09 de abril de 2019  13:40:40 +0000 (0:00:00.056)       0:00:02.582 *********
Martes 09 de abril de 2019  13:40:41 +0000 (0:00:00.216)       0:00:02.798 *********
included: /opt/ansible/roles/splunk_common/tasks/change_splunk_directory_owner.yml for localhost
Martes 09 de abril de 2019  13:40:41 +0000 (0:00:00.087)       0:00:02.886 *********

TASK [splunk_common : Actualizar el propietario del directorio de Splunk] *****************************************************************************************************************************************************************************************
ok: [localhost]
Martes 09 de abril de 2019  13:40:41 +0000 (0:00:00.324)       0:00:03.210 *********
included: /opt/ansible/roles/splunk_common/tasks/get_facts.yml for localhost
Martes 09 de abril de 2019  13:40:41 +0000 (0:00:00.094)       0:00:03.305 *********

y así sucesivamente...

Excelente. La imagen ni siquiera tiene un artefacto. Es decir, cada vez que se inicie, se perderá tiempo descargando el archivo con los binarios, descomprimiéndolo y configurándolo.
¿Y qué pasa con el docker-way y todo eso?

No, gracias. Vamos a optar por otro camino. ¿Qué tal si realizamos todas estas operaciones en la etapa de construcción? ¡Vamos allá!

Para no hacer esperar demasiado, mostraré directamente la imagen final:

Dockerfile

# Тут у кого какие предпочтения
FROM centos:7

# Задаём переменные, чтобы каждый раз при старте не указывать их
ENV SPLUNK_HOME /splunkforwarder
ENV SPLUNK_ROLE splunk_heavy_forwarder
ENV SPLUNK_PASSWORD changeme
ENV SPLUNK_START_ARGS --accept-license

# Ставим пакеты
# wget - чтобы скачать артефакты
# expect - понадобится для первоначального запуска Splunk на этапе сборки
# jq - используется в скриптах, которые собирают статистику докера
RUN yum install -y epel-release 
    && yum install -y wget expect jq

# Качаем, распаковываем, удаляем
RUN wget -O splunkforwarder-7.2.4-8a94541dcfac-Linux-x86_64.tgz 'https://www.splunk.com/bin/splunk/DownloadActivityServlet?architecture=x86_64&platform=linux&version=7.2.4&product=universalforwarder&filename=splunkforwarder-7.2.4-8a94541dcfac-Linux-x86_64.tgz&wget=true' 
    && wget -O docker-18.09.3.tgz 'https://download.docker.com/linux/static/stable/x86_64/docker-18.09.3.tgz' 
    && tar -xvf splunkforwarder-7.2.4-8a94541dcfac-Linux-x86_64.tgz 
    && tar -xvf docker-18.09.3.tgz  
    && rm -f splunkforwarder-7.2.4-8a94541dcfac-Linux-x86_64.tgz 
    && rm -f docker-18.09.3.tgz

# С shell скриптами всё понятно, а вот inputs.conf, splunkclouduf.spl и first_start.sh нуждаются в пояснении. Об этом расскажу после source тэга.
COPY [ "inputs.conf", "docker-stats/props.conf", "/splunkforwarder/etc/system/local/" ]
COPY [ "docker-stats/docker_events.sh", "docker-stats/docker_inspect.sh", "docker-stats/docker_stats.sh", "docker-stats/docker_top.sh", "/splunkforwarder/bin/scripts/" ]
COPY splunkclouduf.spl /splunkclouduf.spl
COPY first_start.sh /splunkforwarder/bin/

#  Даём права на исполнение, добавляем пользователя и выполняем первоначальную настройку
RUN chmod +x /splunkforwarder/bin/scripts/*.sh 
    && groupadd -r splunk 
    && useradd -r -m -g splunk splunk 
    && echo "%sudo ALL=NOPASSWD:ALL" >> /etc/sudoers 
    && chown -R splunk:splunk $SPLUNK_HOME 
    && /splunkforwarder/bin/first_start.sh 
    && /splunkforwarder/bin/splunk install app /splunkclouduf.spl -auth admin:changeme 
    && /splunkforwarder/bin/splunk restart

# Копируем инит скрипты
COPY [ "init/entrypoint.sh", "init/checkstate.sh", "/sbin/" ]

# По желанию. Кому нужно локально иметь конфиги/логи, кому нет.
VOLUME [ "/splunkforwarder/etc", "/splunkforwarder/var" ]

HEALTHCHECK --interval=30s --timeout=30s --start-period=3m --retries=5 CMD /sbin/checkstate.sh || exit 1

ENTRYPOINT [ "/sbin/entrypoint.sh" ]
CMD [ "start-service" ]

Entonces, ¿qué contiene

first_start.sh

#!/usr/bin/expect -f
set timeout -1
spawn /splunkforwarder/bin/splunk start --accept-license
expect "Please enter an administrator username: "
send -- "adminr"
expect "Please enter a new password: "
send -- "changemer"
expect "Please confirm new password: "
send -- "changemer"
expect eof

En el primer inicio, Splunk solicita que se le asigne un usuario/contraseña, PERO estos datos se utilizan solo para ejecutar comandos administrativos en esta instalación específica, es decir, dentro del contenedor. En nuestro caso, solo queremos iniciar el contenedor para que todo funcione y los registros fluyan sin cesar. Por supuesto, esto es un hardcode, pero no encontré otras alternativas.

A continuación, se ejecuta el script

/splunkforwarder/bin/splunk install app /splunkclouduf.spl -auth admin:changeme

splunkclouduf.spl — Este es el archivo de credenciales para Splunk Universal Forwarder, que se puede descargar desde la interfaz web.

Dónde hacer clic para descargar (en las imágenes)Splunk Universal Forwarder en Docker como recolector de logs del sistema

Splunk Universal Forwarder en Docker como recolector de logs del sistema
Es un archivo comprimido común que se puede descomprimir. Dentro hay certificados y la contraseña para conectarse a nuestro SplunkCloud y outputs.conf con la lista de nuestras instancias de entrada. Este archivo será válido hasta que reinstales tu instalación de Splunk o agregues nodos de entrada, si la instalación es local. Por lo tanto, no hay nada de malo en agregarlo dentro del contenedor.

Y por último, reiniciar. Sí, para aplicar los cambios, es necesario reiniciar.

En nuestro inputs.conf agregamos los registros que queremos enviar a Splunk. No es necesario agregar este archivo a la imagen, si, por ejemplo, distribuyes la configuración a través de Puppet. Lo principal es que el Forwarder vea las configuraciones al iniciar el daemon, de lo contrario será necesario .\/splunk restart.

¿Y qué hay de los scripts de docker stats? En GitHub hay una solución antigua de outcoldman, los scripts se tomaron de allí y se modificaron para funcionar con las versiones actuales de Docker (ce-17.*) y Splunk (7.*).

Con los datos obtenidos se pueden construir estos

tableros: (un par de imágenes)Splunk Universal Forwarder en Docker como recolector de logs del sistema

Splunk Universal Forwarder en Docker como recolector de logs del sistema
El código fuente de los tableros está en el repositorio mencionado al final del artículo. Ten en cuenta que hay 2 campos de selección: 1 — selección del índice (se buscan según la máscara), selección de host/contenedor. Es probable que tengas que actualizar la máscara del índice, dependiendo de los nombres que utilices.

Para concluir, quiero resaltar la función start() en

entrypoint.sh

start() {
    trap teardown EXIT
	if [ -z $SPLUNK_INDEX ]; then
	echo "La variable de entorno 'SPLUNK_INDEX' está vacía o no está definida. Debe ser 'dev' o 'prd'." >&2
	exit 1
	else
	sed -e "s/@index@/$SPLUNK_INDEX/" -i ${SPLUNK_HOME}/etc/system/local/inputs.conf
	fi
	sed -e "s/@hostname@/$(cat /etc/hostname)/" -i ${SPLUNK_HOME}/etc/system/local/inputs.conf
    sh -c "echo 'iniciando' > /tmp/splunk-container.state"
	${SPLUNK_HOME}/bin/splunk start
    watch_for_failure
}

En mi caso, para cada entorno y cada entidad individual, ya sea una aplicación en un contenedor o una máquina anfitriona, utilizamos un índice separado. De este modo, no se verá afectada la velocidad de búsqueda con una acumulación significativa de datos. La nomenclatura de los índices sigue una regla simple: _. Por lo tanto, para que el contenedor sea universal, antes de iniciar el daemon, reemplazamos sed-el wildcard por el nombre del entorno. La variable con el nombre del entorno se pasa a través de variables de entorno. Suena divertido.

También hay que destacar que, por alguna razón, el parámetro docker no afecta a Splunk. hostname. De todos modos, seguirá enviando logs con el id de su contenedor al campo host. Como solución, se puede montar /etc/hostname desde la máquina host y al iniciar hacer un reemplazo, similar a los nombres de índices.

Ejemplo de docker-compose.yml

version: '2'
services:
  splunk-forwarder:
    image: "${IMAGE_REPO}\/docker-stats-splunk-forwarder:${IMAGE_VERSION}"
    environment:
      SPLUNK_INDEX: ${ENVIRONMENT}
    volumes:
    - "/etc/hostname:/etc/hostname:ro"
    - "/var/log:/var/log"
    - "/var/run/docker.sock:/var/run/docker.sock:ro"

Summary

Sí, es posible que la solución no sea perfecta y desde luego no universal para todos, ya que hay mucho «hardcode». Pero sobre esa base, cada uno puede construir su propia imagen y guardarla en su propio artefacto privado, si acaso necesita un Splunk Forwarder específicamente en Docker.

Enlaces:

La solución del artículo
La solución de outcoldman que inspiró reutilizar parte de la funcionalidad
Documentación oficial sobre la configuración de Universal Forwarder

Fuente: habr.com

Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS 🔥 Compra un hosting fiable para sitios web con protección contra DDoS, servidores VPS VDS | ProHoster