Cómo instalar la pila de registro Elasticsearch, Fluentd y Kibana (EFK) en Ubuntu 22.04
La monitorización y el análisis de logs es una parte esencial de la infraestructura de servidores o contenedores, y resulta útil cuando se manejan aplicaciones complejas. Una de las soluciones de registro más populares es la pila Elasticsearch, Fluentd y Kibana (EFK). Antes de adentrarnos en el tutorial, conozcamos los componentes de la pila.
Elasticsearch es un motor de búsqueda en tiempo real, distribuido y escalable que permite realizar búsquedas y análisis de texto completo. Se utiliza para indexar y buscar en grandes cantidades de datos. Suele desplegarse junto con Kibana, un potente panel de visualización de datos para Elasticsearch. Kibana te permite explorar los datos de registro de Elasticsearch y crear cuadros de mando y consultas para obtener información sobre tu aplicación. Fluentd recoge, transforma y envía los datos de registro al backend de Elasticsearch.
En este tutorial, instalaremos la pila EFK utilizando Docker en una máquina Ubuntu 22.04 y enviaremos los registros del contenedor a Kibana después de filtrarlos y transformarlos utilizando Fluentd.
Requisitos previos
- Un servidor que ejecute Ubuntu 22.04 con un mínimo de 6 GB de RAM.
- Un usuario no root con privilegios sudo.
- El cortafuegos sin complicaciones (UFW) está activado y en ejecución.
- Un nombre de dominio totalmente cualificado (FQDN) que apunte al servidor como, por ejemplo,
kibana.example.com
. - Todo está actualizado.
$ sudo apt update && sudo apt upgrade
Paso 1 – Configurar el Cortafuegos
Antes de instalar ningún paquete, el primer paso es configurar el cortafuegos para que permita las conexiones HTTP y HTTPS.
Comprueba el estado del cortafuegos.
$ sudo ufw status
Deberías ver algo como lo siguiente
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
Permitir puertos HTTP y HTTPs.
$ sudo ufw allow http
$ sudo ufw allow https
Vuelve a comprobar el estado para confirmarlo.
$ sudo ufw status
Status: active
To Action From
-- ------ ----
OpenSSH ALLOW Anywhere
80/tcp ALLOW Anywhere
443 ALLOW Anywhere
OpenSSH (v6) ALLOW Anywhere (v6)
80/tcp (v6) ALLOW Anywhere (v6)
443 (v6) ALLOW Anywhere (v6)
Paso 2 – Instala Docker y Docker Compose
Añade la clave GPG oficial de Docker.
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker.gpg
Ejecuta el siguiente comando para añadir el repositorio de Docker.
$ echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
Actualiza el sistema para incluir el repositorio de Docker.
$ sudo apt update
Instala Docker y el plugin Docker Compose.
$ sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin
Este tutorial utilizará el plugin Docker Compose v2 en lugar del antiguo binario heredado. Por lo tanto, el comando para ejecutarlo ha cambiado de docker-compose
a docker compose
y esto se refleja aquí.
Docker se ejecuta con privilegios elevados, por lo que tendrás que utilizar sudo
con frecuencia para ejecutar comandos. La mejor opción es añadir tu cuenta de usuario Linux al grupo de usuarios docker
.
$ sudo usermod -aG docker ${USER}
La variable ${USER}
recoge la cuenta del sistema actualmente conectada. Si no has iniciado sesión con el usuario al que quieres dar privilegios, sustituye ${USER}
por el nombre de usuario.
Para solicitar la pertenencia al nuevo grupo, sal del servidor y vuelve a entrar, o utiliza el siguiente comando. Se te pedirá la contraseña del usuario.
$ su - ${USER}
Paso 3 – Crear el archivo Docker Compose
En primer lugar, crea el directorio para el proyecto EFK.
$ mkdir ~/efk
Cambia al directorio.
$ cd ~/efk
Crea y abre el archivo docker-compose.yml
para editarlo.
$ nano docker-compose.yml
Pega en él el siguiente código.
services:
# Deploy using the custom image automatically be created during the build process.
fluentd:
build: ./fluentd
volumes:
- ./fluentd/conf:/fluentd/etc
links: # Sends incoming logs to the elasticsearch container.
- elasticsearch
depends_on:
- elasticsearch
ports: # Exposes the port 24224 on both TCP and UDP protocol for log aggregation
- 24224:24224
- 24224:24224/udp
elasticsearch:
image: elasticsearch:8.7.1
expose:
- 9200
environment:
- discovery.type=single-node # Runs as a single-node
- xpack.security.enabled=false
volumes: # Stores elasticsearch data locally on the esdata Docker volume
- esdata:/usr/share/elasticsearch/data
kibana:
image: kibana:8.7.1
links: # Links kibana service to the elasticsearch container
- elasticsearch
depends_on:
- elasticsearch
ports:
- 5601:5601
environment: # Defined host configuration
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
# Define the Docker volume named esdata for the Elasticsearch container.
volumes:
esdata:
Guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te pida. Hemos configurado para iniciar tres servicios, uno para cada uno, Fluentd, Elasticsearch y Kibana.
Para Fluentd, construiremos un contenedor en lugar de una imagen preparada. Los archivos de compilación para Fluentd se configurarán en el siguiente paso. Hemos montado un directorio para sus archivos de compilación y un volumen para los archivos de configuración, y hemos expuesto el puerto 24224 en los protocolos TCP y UDP para la agregación de registros.
El siguiente servicio es Elasticsearch y estamos utilizando la última versión disponible en el momento de escribir este tutorial. Lo hemos expuesto a través del puerto 9200 y hemos configurado algunas variables de entorno para que podamos ejecutarlo como un clúster de un solo nodo y hemos desactivado las funciones de seguridad. Esto no suele recomendarse, pero habilitar la seguridad está fuera del alcance de este tutorial. También hemos montado un volumen local para los datos de Elasticsearch.
Por último, configuramos Kibana y lo exponemos a través del puerto 5601, que se utilizará para acceder al panel de control. También configuramos una variable para configurar el host de Elasticsearch al que accederá.
Paso 4 – Configurar los archivos de construcción de Fluentd
Crea Fluentd y el directorio de configuración.
$ mkdir fluentd/conf -p
Ejecuta el comando tree
para verificar la estructura del directorio.
$ tree
Debería tener el siguiente aspecto.
Cambia al directorio de Fluentd.
$ cd fluentd
Crea y abre el archivo Dockerfile
para editarlo.
$ nano Dockerfile
Pega en él el siguiente código. Este código extrae la imagen Docker de Fluentd Debian e instala el plugin de Fluentd para Elasticsearch.
# fluentd/Dockerfile
FROM fluent/fluentd:v1.16-debian-1
USER root
RUN ["gem", "install", "fluent-plugin-elasticsearch", "--no-document", "--version", "5.3.0"]
USER fluent
Guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te solicite.
Cambia al directorio de configuración.
$ cd conf
Crea y abre el archivo fluentd.conf
para editarlo.
$ nano fluentd.conf
Pega en él el siguiente código.
# bind fluentd on IP 0.0.0.0
# port 24224
<source>
@type forward
port 24224
bind 0.0.0.0
</source>
# sendlog to the elasticsearch
# the host must match to the elasticsearch
# container service
<match *.**>
@type copy
<store>
@type elasticsearch_dynamic
hosts elasticsearch:9200
logstash_format true
logstash_prefix fluentd
logstash_dateformat %Y%m%d
include_tag_key true
tag_key @log_name
include_timestamp true
flush_interval 30s
</store>
<store>
@type stdout
</store>
</match>
Guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te solicite.
La directiva fuente anterior utiliza el complemento forward
, que convierte a Fluentd en un punto final TCP para aceptar paquetes TCP.
La directiva match busca eventos con etiquetas coincidentes, lo que en este caso significa que coincide con todos los eventos. Utilizaremos el complemento elasticsearch_dynamic
para el almacenamiento, que permite especificar valores de configuración de forma dinámica. El campo hosts
especifica el nombre de host de la aplicación Elasticsearch, que es el nombre del servicio en el archivo Docker compose. El campo logstash_format
está configurado como verdadero, lo que significa que Fluentd utiliza el formato de nombre convencional logstash-%Y.%m.%dlogstash-%Y.%m.%d
. El nombre del prefijo para escribir los eventos se establece en fluend
. El include_tag_key
se establece en true, lo que añade la etiqueta Fluentd en el formato JSON. La variable tag_key
es el nombre de campo que se extrae para la etiqueta. Si se establece la variable include_timestamp
a verdadero, se añade un campo de marca de tiempo al registro. La variable flush_interval
especifica el intervalo entre las descargas de datos. También utilizamos el complemento stdout
para imprimir eventos/registros en la salida estándar.
Paso 5 – Ejecuta los contenedores Docker
Vuelve al directorio EFK.
$ cd ~/efk
Inicia los contenedores utilizando el siguiente comando.
$ docker compose up -d
Comprueba el estado de los contenedores en ejecución.
$ docker ps
b3780c311154 efk-fluentd "tini -- /bin/entryp…" 9 seconds ago Up 8 seconds 5140/tcp, 0.0.0.0:24224->24224/tcp, 0.0.0.0:24224->24224/udp, :::24224->24224/tcp, :::24224->24224/udp efk-fluentd-1
5a48f0a9ade1 kibana:8.7.1 "/bin/tini -- /usr/l…" 9 seconds ago Up 7 seconds 0.0.0.0:5601->5601/tcp, :::5601->5601/tcp efk-kibana-1
dab3a0ab0312 elasticsearch:8.7.1 "/bin/tini -- /usr/l…" 9 seconds ago Up 8 seconds 9200/tcp, 9300/tcp efk-elasticsearch-1
También puedes utilizar el siguiente comando para ello.
$ docker compose ps
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
efk-elasticsearch-1 elasticsearch:8.7.1 "/bin/tini -- /usr/l…" elasticsearch 37 seconds ago Up 36 seconds 9200/tcp, 9300/tcp
efk-fluentd-1 efk-fluentd "tini -- /bin/entryp…" fluentd 37 seconds ago Up 36 seconds 5140/tcp, 0.0.0.0:24224->24224/tcp, 0.0.0.0:24224->24224/udp, :::24224->24224/tcp, :::24224->24224/udp
efk-kibana-1 kibana:8.7.1 "/bin/tini -- /usr/l…" kibana 37 seconds ago Up 36 seconds 0.0.0.0:5601->5601/tcp, :::5601->5601/tcp
Ejecuta los siguientes comandos para comprobar los registros del proceso de construcción del EFK.
$ docker logs efk-fluentd-1
$ docker logs efk-kibana-1
$ docker logs efk-elasticsearch-1
Inspecciona el contenedor Elasticsearch. Imprimirá la configuración detallada del contenedor.
$ docker inspect efk-elasticsearch-1
Puedes observar la dirección IP dada al contenedor.
[
{
"Id": "dab3a0ab03120d3a7192045e1ea84fdd0f8fdb7819cc6d6780e05109d61e0b66",
"Created": "2023-05-04T09:58:00.256169904Z",
"Path": "/bin/tini",
"Args": [
"--",
"/usr/local/bin/docker-entrypoint.sh",
"eswrapper"
],
"State": {
"Status": "running",
"Running": true,
"Paused": false,
"Restarting": false,
"OOMKilled": false,
"Dead": false,
"Pid": 23619,
"ExitCode": 0,
"Error": "",
"StartedAt": "2023-05-04T09:58:00.563700803Z",
"FinishedAt": "0001-01-01T00:00:00Z"
},
"Image": "sha256:59075530be34d3a06866f894ae9735f6d739a7a751ad45efb86dec3c9bd16836",
"ResolvConfPath": "/var/lib/docker/containers/dab3a0ab03120d3a7192045e1ea84fdd0f8fdb7819cc6d6780e05109d61e0b66/resolv.conf",
"HostnamePath": "/var/lib/docker/containers/dab3a0ab03120d3a7192045e1ea84fdd0f8fdb7819cc6d6780e05109d61e0b66/hostname",
"HostsPath": "/var/lib/docker/containers/dab3a0ab03120d3a7192045e1ea84fdd0f8fdb7819cc6d6780e05109d61e0b66/hosts",
"LogPath": "/var/lib/docker/containers/dab3a0ab03120d3a7192045e1ea84fdd0f8fdb7819cc6d6780e05109d61e0b66/dab3a0ab03120d3a7192045e1ea84fdd0f8fdb7819cc6d6780e05109d61e0b66-json.log",
"Name": "/efk-elasticsearch-1",
"RestartCount": 0,
"Driver": "overlay2",
"Platform": "linux",
"MountLabel": "",
"ProcessLabel": "",
"AppArmorProfile": "docker-default",
"ExecIDs": null,
"HostConfig": {
"Binds": null,
"ContainerIDFile": "",
"LogConfig": {
"Type": "json-file",
"Config": {}
},
"NetworkMode": "efk_default",
"PortBindings": {},
"RestartPolicy": {
"Name": "",
"MaximumRetryCount": 0
},
"AutoRemove": false,
"VolumeDriver": "",
"VolumesFrom": null,
"ConsoleSize": [
0,
0
],
"CapAdd": null,
"CapDrop": null,
"CgroupnsMode": "private",
"Dns": null,
"DnsOptions": null,
"DnsSearch": null,
"ExtraHosts": [],
"GroupAdd": null,
"IpcMode": "private",
"Cgroup": "",
"Links": null,
"OomScoreAdj": 0,
"PidMode": "",
"Privileged": false,
"PublishAllPorts": false,
"ReadonlyRootfs": false,
"SecurityOpt": null,
"UTSMode": "",
"UsernsMode": "",
"ShmSize": 67108864,
"Runtime": "runc",
"Isolation": "",
"CpuShares": 0,
"Memory": 0,
"NanoCpus": 0,
"CgroupParent": "",
"BlkioWeight": 0,
"BlkioWeightDevice": null,
"BlkioDeviceReadBps": null,
"BlkioDeviceWriteBps": null,
"BlkioDeviceReadIOps": null,
"BlkioDeviceWriteIOps": null,
"CpuPeriod": 0,
"CpuQuota": 0,
"CpuRealtimePeriod": 0,
"CpuRealtimeRuntime": 0,
"CpusetCpus": "",
"CpusetMems": "",
"Devices": null,
"DeviceCgroupRules": null,
"DeviceRequests": null,
"MemoryReservation": 0,
"MemorySwap": 0,
"MemorySwappiness": null,
"OomKillDisable": null,
"PidsLimit": null,
"Ulimits": null,
"CpuCount": 0,
"CpuPercent": 0,
"IOMaximumIOps": 0,
"IOMaximumBandwidth": 0,
"Mounts": [
{
"Type": "volume",
"Source": "efk_esdata",
"Target": "/usr/share/elasticsearch/data",
"VolumeOptions": {}
}
],
"MaskedPaths": [
"/proc/asound",
"/proc/acpi",
"/proc/kcore",
"/proc/keys",
"/proc/latency_stats",
"/proc/timer_list",
"/proc/timer_stats",
"/proc/sched_debug",
"/proc/scsi",
"/sys/firmware"
],
"ReadonlyPaths": [
"/proc/bus",
"/proc/fs",
"/proc/irq",
"/proc/sys",
"/proc/sysrq-trigger"
]
},
"GraphDriver": {
"Data": {
"LowerDir": "/var/lib/docker/overlay2/ee03648cf34e03601848b1769569b4d3bb7192db118102ca050215ba87060bbf-init/diff:/var/lib/docker/overlay2/51d6cfcb59e473a3f163e68984a1ba1325a2c816ed7925c4dffdefcf2e104d11/diff:/var/lib/docker/overlay2/b9c096454bda31f1cb2ea33f108be8b29b2e94827ebe94cc17563eb596b7cab1/diff:/var/lib/docker/overlay2/effe604c5b015ba02cf3b7a238bd3ff5dad7970a72e689ef5275fcf03fd0bcd1/diff:/var/lib/docker/overlay2/72fbf23251467ea2f6af8d9458c7fdd8fa3ef716eeafd9319ceff59d07d96788/diff:/var/lib/docker/overlay2/02094ec9e4ebb04371f782744a3a46852a00bf6fd7e8820d466a3576aeb9d5fc/diff:/var/lib/docker/overlay2/ce364cdd636b67e10c879aa152360d965d08fe456663ed8fbe78c3bd37bde6c7/diff:/var/lib/docker/overlay2/33bf44b475ea5ea249845b7eed75ded47dd9dc7877b9231fa4195b4753071945/diff:/var/lib/docker/overlay2/4f19bd8089599ef879075012c710ec464d8e0446fc0a0813850657dddd23a5dc/diff:/var/lib/docker/overlay2/a39a61b12d8565c6d5b33c17a04d47c8bd47609a787e0548fbac0d47d00eecc8/diff:/var/lib/docker/overlay2/cbd9d77eb9ed6b600511f9a676aab511d2aa2b3dbd18d5403559699558546996/diff",
"MergedDir": "/var/lib/docker/overlay2/ee03648cf34e03601848b1769569b4d3bb7192db118102ca050215ba87060bbf/merged",
"UpperDir": "/var/lib/docker/overlay2/ee03648cf34e03601848b1769569b4d3bb7192db118102ca050215ba87060bbf/diff",
"WorkDir": "/var/lib/docker/overlay2/ee03648cf34e03601848b1769569b4d3bb7192db118102ca050215ba87060bbf/work"
},
"Name": "overlay2"
},
"Mounts": [
{
"Type": "volume",
"Name": "efk_esdata",
"Source": "/var/lib/docker/volumes/efk_esdata/_data",
"Destination": "/usr/share/elasticsearch/data",
"Driver": "local",
"Mode": "z",
"RW": true,
"Propagation": ""
}
],
"Config": {
"Hostname": "dab3a0ab0312",
"Domainname": "",
"User": "elasticsearch:root",
"AttachStdin": false,
"AttachStdout": true,
"AttachStderr": true,
"ExposedPorts": {
"9200": {},
"9200/tcp": {},
"9300/tcp": {}
},
"Tty": false,
"OpenStdin": false,
"StdinOnce": false,
"Env": [
"xpack.security.enabled=false",
"discovery.type=single-node",
"PATH=/usr/share/elasticsearch/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"ELASTIC_CONTAINER=true"
],
"Cmd": [
"eswrapper"
],
"Image": "elasticsearch:8.7.1",
"Volumes": null,
"WorkingDir": "/usr/share/elasticsearch",
"Entrypoint": [
"/bin/tini",
"--",
"/usr/local/bin/docker-entrypoint.sh"
],
"OnBuild": null,
"Labels": {
"com.docker.compose.config-hash": "51c818791aa87ea7eccc389578c76ec4d596265eba8baefb8833bf5df13777e3",
"com.docker.compose.container-number": "1",
"com.docker.compose.depends_on": "",
"com.docker.compose.image": "sha256:59075530be34d3a06866f894ae9735f6d739a7a751ad45efb86dec3c9bd16836",
"com.docker.compose.oneoff": "False",
"com.docker.compose.project": "efk",
"com.docker.compose.project.config_files": "/home/navjot/efk/docker-compose.yml",
"com.docker.compose.project.working_dir": "/home/navjot/efk",
"com.docker.compose.service": "elasticsearch",
"com.docker.compose.version": "2.17.3",
"org.label-schema.build-date": "2023-04-27T04:33:42.127815583Z",
"org.label-schema.license": "Elastic-License-2.0",
"org.label-schema.name": "Elasticsearch",
"org.label-schema.schema-version": "1.0",
"org.label-schema.url": "https://www.elastic.co/products/elasticsearch",
"org.label-schema.usage": "https://www.elastic.co/guide/en/elasticsearch/reference/index.html",
"org.label-schema.vcs-ref": "f229ed3f893a515d590d0f39b05f68913e2d9b53",
"org.label-schema.vcs-url": "https://github.com/elastic/elasticsearch",
"org.label-schema.vendor": "Elastic",
"org.label-schema.version": "8.7.1",
"org.opencontainers.image.created": "2023-04-27T04:33:42.127815583Z",
"org.opencontainers.image.documentation": "https://www.elastic.co/guide/en/elasticsearch/reference/index.html",
"org.opencontainers.image.licenses": "Elastic-License-2.0",
"org.opencontainers.image.ref.name": "ubuntu",
"org.opencontainers.image.revision": "f229ed3f893a515d590d0f39b05f68913e2d9b53",
"org.opencontainers.image.source": "https://github.com/elastic/elasticsearch",
"org.opencontainers.image.title": "Elasticsearch",
"org.opencontainers.image.url": "https://www.elastic.co/products/elasticsearch",
"org.opencontainers.image.vendor": "Elastic",
"org.opencontainers.image.version": "8.7.1"
}
},
"NetworkSettings": {
"Bridge": "",
"SandboxID": "bf47cd7764585766349085d35100611e086cf233fc9fc655c6eb9e086f1cd59a",
"HairpinMode": false,
"LinkLocalIPv6Address": "",
"LinkLocalIPv6PrefixLen": 0,
"Ports": {
"9200/tcp": null,
"9300/tcp": null
},
"SandboxKey": "/var/run/docker/netns/bf47cd776458",
"SecondaryIPAddresses": null,
"SecondaryIPv6Addresses": null,
"EndpointID": "",
"Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"IPAddress": "",
"IPPrefixLen": 0,
"IPv6Gateway": "",
"MacAddress": "",
"Networks": {
"efk_default": {
"IPAMConfig": null,
"Links": null,
"Aliases": [
"efk-elasticsearch-1",
"elasticsearch",
"dab3a0ab0312"
],
"NetworkID": "1bc8ac0185982b84a24a201852f2cddc0432a3ffff1a2bd4008074875f696cac",
"EndpointID": "e1c67199e679f350d1da47f0b1e208ec6a7767eb57d60f773ba08b88a6962dcf",
"Gateway": "172.23.0.1",
"IPAddress": "172.23.0.2",
"IPPrefixLen": 16,
"IPv6Gateway": "",
"GlobalIPv6Address": "",
"GlobalIPv6PrefixLen": 0,
"MacAddress": "02:42:ac:17:00:02",
"DriverOpts": null
}
}
}
}
]
Como puedes ver, el contenedor tiene 172.23.0.2
como dirección IP. Ejecuta el siguiente comando para verificar si Elasticsearch funciona correctamente.
$ curl 172.23.0.2:9200
{
"name" : "dab3a0ab0312",
"cluster_name" : "docker-cluster",
"cluster_uuid" : "gldMFBtQSxS5sL93rBAdzA",
"version" : {
"number" : "8.7.1",
"build_flavor" : "default",
"build_type" : "docker",
"build_hash" : "f229ed3f893a515d590d0f39b05f68913e2d9b53",
"build_date" : "2023-04-27T04:33:42.127815583Z",
"build_snapshot" : false,
"lucene_version" : "9.5.0",
"minimum_wire_compatibility_version" : "7.17.0",
"minimum_index_compatibility_version" : "7.0.0"
},
"tagline" : "You Know, for Search"
}
Paso 6 – Configurar Kibana
Ahora que la pila EFK está desplegada, es hora de configurar Kibana. Abre la URL http://<yourserverIP>:5601
en el navegador.
Haz clic en el botón Explorar por mi cuenta para acceder al panel de control de Kibana.
Haz clic en el enlace Gestión de la pila para configurar la vista de datos de Kibana. Selecciona la opción Kibana >> Vistas de datos de la barra lateral izquierda para abrir la página de vistas de datos.
Haz clic en el botón Crear vista de datos para continuar.
Introduce el nombre de la vista de datos y el patrón de índice como fluentd-*
. Asegúrate de que el campo Marca de tiempo está configurado como @timestamp
. El campo fuente se actualizará automáticamente. Haz clic en el botón Guardar vista de datos en Kibana para terminar de crear la vista de datos.
A continuación, haz clic en el menú superior (elipsis), y haz clic en la opción Descubrir para mostrar la monitorización de registros.
Obtendrás la siguiente página confirmando que tu configuración funciona perfectamente. Todos los logs proceden de Elasticsearch y son enviados por la agregación de logs Fluentd.
Paso 7 – Instalar Nginx
Ubuntu 22.04 viene con una versión antigua de Nginx. Necesitas descargar el repositorio oficial de Nginx para instalar la última versión.
Importa la clave de firma de Nginx.
$ curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
| sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
Añade el repositorio de la versión estable de Nginx.
$ echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg arch=amd64] \
http://nginx.org/packages/ubuntu `lsb_release -cs` nginx" \
| sudo tee /etc/apt/sources.list.d/nginx.list
Actualiza los repositorios del sistema.
$ sudo apt update
Instala Nginx.
$ sudo apt install nginx
Verifica la instalación.
$ nginx -v
nginx version: nginx/1.24.0
Iniciar el servidor Nginx.
$ sudo systemctl start nginx
Paso 8 – Instalar SSL
El primer paso es instalar el certificado SSL Let’s Encrypt. Necesitamos instalar Certbot para generar el certificado SSL. Puedes instalar Certbot utilizando el repositorio de Ubuntu o descargar la última versión utilizando la herramienta Snapd. Nosotros utilizaremos la versión Snapd.
Ubuntu 22.04 viene con Snapd instalado por defecto. Ejecuta los siguientes comandos para asegurarte de que tu versión de Snapd está actualizada.
$ sudo snap install core && sudo snap refresh core
Instala Certbot.
$ sudo snap install --classic certbot
Utiliza el siguiente comando para asegurarte de que se puede ejecutar el comando Certbot creando un enlace simbólico al directorio /usr/bin
.
$ sudo ln -s /snap/bin/certbot /usr/bin/certbot
Genera el certificado SSL para el dominio kibana.example.com
.
$ sudo certbot certonly --nginx --agree-tos --no-eff-email --staple-ocsp --preferred-challenges http -m [email protected] -d kibana.example.com
El comando anterior descargará un certificado en el directorio /etc/letsencrypt/live/kibana.example.com
de tu servidor.
Genera un certificado de grupo Diffie-Hellman.
$ sudo openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096
Comprueba el servicio del programador de renovaciones de Certbot.
$ sudo systemctl list-timers
Encontrarás snap.certbot.renew.service
como uno de los servicios programados para ejecutarse.
NEXT LEFT LAST PASSED UNIT ACTIVATES
------------------------------------------------------------------------------------------------------------------------------------
Mon 2023-05-06 13:37:57 UTC 3h 45min left Mon 2023-05-01 07:20:42 UTC 2h 31min ago ua-timer.timer ua-timer.service
Mon 2023-05-06 14:39:29 UTC 4h 47min left Sat 2023-02-04 16:04:18 UTC 2 months ago motd-news.timer motd-news.service
Mon 2023-05-06 15:53:00 UTC 6h left n/a n/a snap.certbot.renew.timer snap.certbot.renew.service
Realiza una ejecución en seco del proceso para comprobar si la renovación SSL funciona correctamente.
$ sudo certbot renew --dry-run
Si no ves ningún error, ya está todo listo. Tu certificado se renovará automáticamente.
Paso 9 – Configurar Nginx
Crea y abre el archivo de configuración de Nginx para Kibana.
$ sudo nano /etc/nginx/conf.d/kibana.conf
Pega en él el siguiente código. Sustituye la dirección IP por la dirección IP privada de tu servidor Elasticsearch.
server {
listen 80; listen [::]:80;
server_name kibana.example.com;
return 301 https://$host$request_uri;
}
server {
server_name kibana.example.com;
charset utf-8;
listen 443 ssl http2;
listen [::]:443 ssl http2;
access_log /var/log/nginx/kibana.access.log;
error_log /var/log/nginx/kibana.error.log;
ssl_certificate /etc/letsencrypt/live/kibana.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/kibana.example.com/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/kibana.example.com/chain.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:MozSSL:10m;
ssl_session_tickets off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
resolver 8.8.8.8;
ssl_stapling on;
ssl_stapling_verify on;
ssl_dhparam /etc/ssl/certs/dhparam.pem;
location / {
proxy_pass http://localhost:5601;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
Guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te solicite.
Abre el archivo /etc/nginx/nginx.conf
para editarlo.
$ sudo nano /etc/nginx/nginx.conf
Añade la siguiente línea antes de la línea include /etc/nginx/conf.d/*.conf;
.
server_names_hash_bucket_size 64;
Guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te solicite.
Verifica la configuración.
$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Reinicia el servicio Nginx.
$ sudo systemctl restart nginx
Queda un paso más. Abre el archivo Docker compose para editarlo.
$ nano ~/docker-compose.yml
Pega la línea SERVER_PUBLICBASEURL=https://kibana.example.com
en la sección de entorno bajo el servicio Kibana como se indica a continuación.
environment: # Defined host configuration
- ELASTICSEARCH_HOSTS=http://elasticsearch:9200
- SERVER_PUBLICBASEURL=https://kibana.example.com
Guarda el archivo pulsando Ctrl + X e introduciendo Y cuando se te pida una vez hayas terminado.
Detén y elimina los contenedores.
$ docker compose down --remove-orphans
Inicia de nuevo los contenedores con la configuración actualizada.
$ docker compose up -d
Tu panel de control de Kibana debería ser accesible a través de la URL https://kibana.example.com
desde cualquier lugar que desees.
Paso 10 – Ejecutar un contenedor Docker con Fluentd Log Driver
Ahora, ejecutaremos un contenedor Docker con el controlador de registro Fluentd, que enviará automáticamente los registros a la pila. Haremos la prueba utilizando el contenedor Nginx.
Saca la imagen de Nginx del registro de Docker Hub. Estamos utilizando la versión alpine
porque es la versión más pequeña de la imagen.
$ docker pull nginx:alpine
Ejecuta el siguiente comando para crear e iniciar el contenedor Nginx. Hemos configurado el controlador de registro como Fluentd
y el puerto como 8080 porque el puerto 80 por defecto ya está siendo utilizado por el servidor Nginx en modo proxy.
$ docker run --name nginx-fluentd-test -d --log-driver=fluentd -p 8080:80 nginx:alpine
Comprueba el estado del contenedor.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
038c43e4e1a3 nginx:alpine "/docker-entrypoint.…" 12 seconds ago Up 11 seconds 0.0.0.0:8080->80/tcp, :::8080->80/tcp nginx-fluentd-test
a94ca706bd0c efk-fluentd "tini -- /bin/entryp…" 8 hours ago Up 8 hours 5140/tcp, 0.0.0.0:24224->24224/tcp, 0.0.0.0:24224->24224/udp, :::24224->24224/tcp, :::24224->24224/udp efk-fluentd-1
0cf04a446425 kibana:8.7.1 "/bin/tini -- /usr/l…" 8 hours ago Up 8 hours 0.0.0.0:5601->5601/tcp, :::5601->5601/tcp efk-kibana-1
7c7ad8f9b123 elasticsearch:8.7.1 "/bin/tini -- /usr/l…" 8 hours ago Up 8 hours 9200/tcp, 9300/tcp efk-elasticsearch-1
Ejecuta el siguiente comando para acceder al contenedor Nginx y generar registros de acceso.
$ curl localhost:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
Alternativamente, puedes abrir la URL http://<yourserverIP>:8080
en tu navegador y obtendrás la siguiente página.
Abre el panel de control de Kibana y haz clic en el enlace Descubrir del menú de la barra lateral izquierda. Haz clic en el signo + del menú superior para que aparezca la ventana emergente Añadir filtro.
Selecciona el campo container_name
en el desplegable, is
como operador y rellena el nombre del contenedor ( nginx-fluentd-test
) como valor del campo.
Haz clic en el botón Añadir filtro para visualizar los datos del contenedor Nginx.
Conclusión
Con esto concluye nuestro tutorial sobre la instalación de la pila de registro Elasticsearch, Fluentd y Kibana (EFK) en una máquina Ubuntu 22.04. Si tienes alguna pregunta, publícala en los comentarios a continuación.