Guía de instalación · 17 min read · Dec 18, 2025

Cómo instalar la pila de registro Elasticsearch, Fluentd y Kibana (EFK) en Ubuntu 22.04

El monitoreo y análisis de registros es una parte esencial de la infraestructura de servidores o contenedores y es útil al manejar aplicaciones complejas. Una de las soluciones de registro más populares es la pila Elasticsearch, Fluentd y Kibana (EFK). Antes de profundizar en el tutorial, aprendamos sobre los componentes de la pila.

Elasticsearch es un motor de búsqueda distribuido, escalable y en tiempo real que permite la búsqueda y análisis de texto completo. Se utiliza para indexar y buscar grandes cantidades de datos. Se despliega comúnmente junto a Kibana, un poderoso panel de visualización de datos para Elasticsearch. Kibana te permite explorar los datos de registro de Elasticsearch y construir paneles y consultas para obtener información sobre tu aplicación. Fluentd recopila, transforma y envía los datos de registro al backend de Elasticsearch.

En este tutorial, instalaremos la pila EFK usando Docker en una máquina Ubuntu 22.04 y enviaremos los registros de contenedores a Kibana después de filtrarlos y transformarlos usando Fluentd.

Prerrequisitos

  • Un servidor que ejecute Ubuntu 22.04 con un mínimo de 6GB de RAM.
  • Un usuario no root con privilegios de sudo.
  • El Firewall sin complicaciones (UFW) está habilitado y en funcionamiento.
  • Un nombre de dominio completamente calificado (FQDN) apuntando al servidor como, kibana.example.com.
  • Todo está actualizado. $ sudo apt update && sudo apt upgrade

Paso 1 - Configurar el Firewall

Antes de instalar cualquier paquete, el primer paso es configurar el firewall para permitir conexiones HTTP y HTTPS.

Verifica el estado del firewall.

$ sudo ufw status

Deberías ver algo como lo siguiente.

Estado: activo

Para                         Acción      Desde
--                         ------      ----
OpenSSH                    PERMITIR       En cualquier lugar
OpenSSH (v6)               PERMITIR       En cualquier lugar (v6)

Permitir los puertos HTTP y HTTPS.

$ sudo ufw allow http
$ sudo ufw allow https

Verifica el estado nuevamente para confirmar.

$ sudo ufw status
Estado: activo

Para                         Acción      Desde
--                         ------      ----
OpenSSH                    PERMITIR       En cualquier lugar
80/tcp                     PERMITIR       En cualquier lugar
443                        PERMITIR       En cualquier lugar
OpenSSH (v6)               PERMITIR       En cualquier lugar (v6)
80/tcp (v6)                PERMITIR       En cualquier lugar (v6)
443 (v6)                   PERMITIR       En cualquier lugar (v6)

Paso 2 - Instalar Docker y Docker Compose

Agrega 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 agregar 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 de 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 binario legado anterior. 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 necesitarás usar sudo con frecuencia para ejecutar comandos. La mejor opción es agregar tu cuenta de usuario de 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 deseas otorgar privilegios, reemplaza ${USER} con el nombre de usuario.

Para aplicar la nueva membresía de grupo, cierra sesión en el servidor y vuelve a iniciar sesión, o usa el siguiente comando. Se te pedirá la contraseña del usuario.

$ su - ${USER}

Paso 3 - Crear el archivo Docker Compose

Primero, crea el directorio para el proyecto EFK.

$ mkdir ~/efk

Cambia al directorio.

$ cd ~/efk

Crea y abre el archivo docker-compose.yml para editar.

$ nano docker-compose.yml

Pega el siguiente código en él.

services:
  # Desplegar usando la imagen personalizada que se creará automáticamente durante el proceso de construcción.
  fluentd:
    build: ./fluentd
    volumes:
      - ./fluentd/conf:/fluentd/etc
    links: # Envía los registros entrantes al contenedor de elasticsearch.
      - elasticsearch
    depends_on:
      - elasticsearch
    ports: # Expone el puerto 24224 en ambos protocolos TCP y UDP para la agregación de registros
      - 24224:24224
      - 24224:24224/udp

  elasticsearch:
    image: elasticsearch:8.7.1
    expose:
      - 9200
    environment:
      - discovery.type=single-node # Se ejecuta como un solo nodo
      - xpack.security.enabled=false
    volumes: # Almacena datos de elasticsearch localmente en el volumen Docker esdata
      - esdata:/usr/share/elasticsearch/data

  kibana:
    image: kibana:8.7.1
    links: # Vincula el servicio kibana al contenedor de elasticsearch
      - elasticsearch
    depends_on:
      - elasticsearch
    ports:
      - 5601:5601
    environment: # Configuración del host definida
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200

# Define el volumen Docker llamado esdata para el contenedor de Elasticsearch.
volumes:
  esdata:

Guarda el archivo presionando Ctrl + X y entrando 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 lista. Los archivos de construcción para Fluentd se configurarán en el siguiente paso. Hemos montado un directorio para sus archivos de construcción, y un volumen para los archivos de configuración, y expuesto el puerto 24224 en ambos protocolos TCP y UDP para la agregación de registros.

El siguiente servicio es Elasticsearch y estamos usando la última versión disponible en el momento de escribir este tutorial. Lo hemos expuesto a través del puerto 9200 y configurado algunas variables de entorno para que podamos ejecutarlo como un clúster de un solo nodo y hemos deshabilitado las características de seguridad. Esto no se recomienda generalmente, pero habilitar la seguridad está fuera del alcance de este tutorial. También hemos montado un volumen local para los datos de Elasticsearch.

Finalmente, configuramos Kibana y lo exponemos a través del puerto 5601 que se utilizará para acceder al panel. También configuramos una variable para configurar el host de Elasticsearch para que pueda 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 verse como lo siguiente.

Salida del comando tree

Cambia al directorio Fluentd.

$ cd fluentd

Crea y abre el Dockerfile para editar.

$ nano Dockerfile

Pega el siguiente código en él. Este código extrae la imagen Docker de Debian de Fluentd 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 presionando Ctrl + X y entrando Y cuando se te pida.

Cambia al directorio de configuración.

$ cd conf

Crea y abre el archivo fluentd.conf para editar.

$ nano fluentd.conf

Pega el siguiente código en él.

# vincular fluentd en IP 0.0.0.0
# puerto 24224

  @type forward
  port 24224
  bind 0.0.0.0


# enviar registros al elasticsearch
# el host debe coincidir con el contenedor de elasticsearch
# servicio

  @type copy
  
    @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
  
  
    @type stdout
  

Guarda el archivo presionando Ctrl + X y entrando Y cuando se te pida.

La directiva source anterior utiliza el plugin forward que convierte 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. Usaremos el plugin elasticsearch_dynamic para almacenamiento que permite que los valores de configuración se especifiquen dinámicamente. El campo hosts especifica el nombre de host para la aplicación Elasticsearch, que es el nombre del servicio en el archivo de Docker compose. El logstash_format se establece en verdadero, lo que significa que Fluentd utiliza el formato de nombre convencional logstash-%Y.%m.%dlogstash-%Y.%m.%d. El nombre de prefijo para escribir los eventos se establece en fluend. La variable include_tag_key se establece en verdadero, lo que agrega la etiqueta de Fluentd en el formato JSON. La tag_key es el nombre del campo a extraer para la etiqueta. Establecer la variable include_timestamp en verdadero agrega un campo de marca de tiempo al registro. El flush_interval especifica el intervalo entre los vaciados de datos. También usamos el plugin stdout para imprimir eventos/registros en la salida estándar.

Paso 5 - Ejecutar los contenedores de Docker

Cambia de nuevo al directorio EFK.

$ cd ~/efk

Inicia los contenedores usando el siguiente comando.

$ docker compose up -d

Verifica el estado de los contenedores en ejecución.

$ docker ps
b3780c311154   efk-fluentd           "tini -- /bin/entryp…"   9 segundos atrás   Up 8 segundos   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 segundos atrás   Up 7 segundos   0.0.0.0:5601->5601/tcp, :::5601->5601/tcp                                                                efk-kibana-1
dab3a0ab0312   elasticsearch:8.7.1   "/bin/tini -- /usr/l…"   9 segundos atrás   Up 8 segundos   9200/tcp, 9300/tcp                                                                                       efk-elasticsearch-1

También puedes usar 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 segundos atrás      Up 36 segundos       9200/tcp, 9300/tcp
efk-fluentd-1         efk-fluentd           "tini -- /bin/entryp…"   fluentd             37 segundos atrás      Up 36 segundos       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 segundos atrás      Up 36 segundos       0.0.0.0:5601->5601/tcp, :::5601->5601/tcp

Ejecuta los siguientes comandos para verificar los registros del proceso de construcción de EFK.

$ docker logs efk-fluentd-1
$ docker logs efk-kibana-1
$ docker logs efk-elasticsearch-1

Inspecciona el contenedor de Elasticsearch. Imprimirá la configuración detallada del contenedor.

$ docker inspect efk-elasticsearch-1

Puedes notar la dirección IP asignada 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 obtuvo 172.23.0.2 como la dirección IP. Ejecuta el siguiente comando para verificar si Elasticsearch está funcionando 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://:5601 en el navegador.

Página de bienvenida de Kibana

Haz clic en el botón Explorar por mi cuenta para proceder al panel de Kibana.

Panel de Kibana

Haz clic en el enlace Gestión de pila para configurar la vista de datos de Kibana. Selecciona la opción Kibana >> Vistas de datos en la barra lateral izquierda para abrir la página de vista de datos.

Página de vista de datos de Kibana

Haz clic en el botón Crear vista de datos para proceder.

Crear vista de datos de Kibana

Ingresa el nombre de la vista de datos y el patrón de índice como fluentd-*. Asegúrate de que el campo de marca de tiempo esté configurado en @timestamp. El campo de origen se actualizará automáticamente. Haz clic en el botón Guardar vista de datos en Kibana para finalizar la creación de la vista de datos.

A continuación, haz clic en el menú superior (elipsis) y haz clic en la opción Descubrir para mostrar el monitoreo de registros.

Obtendrás la siguiente página confirmando que tu configuración está funcionando perfectamente. Los registros se toman todos de Elasticsearch y se envían por la agregación de registros de Fluentd.

Registros de monitoreo de Fluentd en Kibana

Paso 7 - Instalar Nginx

Ubuntu 22.04 viene con una versión más 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

Agrega el repositorio para 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

Inicia el servidor Nginx.

$ sudo systemctl start nginx

Paso 8 - Instalar SSL

El primer paso es instalar el certificado SSL de Let’s Encrypt. Necesitamos instalar Certbot para generar el certificado SSL. Puedes instalar Certbot usando el repositorio de Ubuntu o obtener la última versión usando la herramienta Snapd. Usaremos la versión de 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

Usa el siguiente comando para asegurarte de que el comando Certbot pueda ejecutarse 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 en tu servidor.

Genera un certificado de grupo Diffie-Hellman.

$ sudo openssl dhparam -dsaparam -out /etc/ssl/certs/dhparam.pem 4096

Verifica el servicio programador de renovación 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

Haz una prueba en seco del proceso para verificar si la renovación de SSL está funcionando bien.

$ sudo certbot renew --dry-run

Si no ves errores, estás 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 el siguiente código en él. Reemplaza la dirección IP con 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 presionando Ctrl + X y entrando Y cuando se te pida.

Abre el archivo /etc/nginx/nginx.conf para editar.

$ sudo nano /etc/nginx/nginx.conf

Agrega la siguiente línea antes de la línea include /etc/nginx/conf.d/*.conf;.

server_names_hash_bucket_size  64;

Guarda el archivo presionando Ctrl + X y entrando Y cuando se te pida.

Verifica la configuración.

$ sudo nginx -t
nginx: el archivo de configuración /etc/nginx/nginx.conf tiene una sintaxis correcta
nginx: la prueba del archivo de configuración /etc/nginx/nginx.conf fue exitosa

Reinicia el servicio Nginx.

$ sudo systemctl restart nginx

Hay un paso más necesario. Abre el archivo de Docker compose para editar.

$ nano ~/docker-compose.yml

Pega la línea SERVER_PUBLICBASEURL=https://kibana.example.com bajo la sección de entorno bajo el servicio Kibana como sigue.

    environment: # Configuración del host definida
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
      - SERVER_PUBLICBASEURL=https://kibana.example.com

Guarda el archivo presionando Ctrl + X y entrando Y cuando se te pida una vez que hayas terminado.

Detén y elimina los contenedores.

$ docker compose down --remove-orphans

Inicia los contenedores nuevamente con la configuración actualizada.

$ docker compose up -d

Tu panel 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 el controlador de registro Fluentd

Ahora, ejecutaremos un contenedor Docker con el controlador de registro Fluentd, enviando automáticamente registros a la pila. Probaremos usando el contenedor de Nginx.

Extrae la imagen de Nginx del registro de Docker Hub. Estamos usando 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 y comenzar el contenedor de Nginx. Hemos establecido el controlador de registro en Fluentd y el puerto como 8080 porque el puerto predeterminado 80 ya está en uso por el servidor Nginx en modo proxy.

$ docker run --name nginx-fluentd-test -d --log-driver=fluentd -p 8080:80 nginx:alpine

Verifica 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 de Nginx y generar registros de acceso.

$ curl localhost:8080



¡Bienvenido a nginx!



¡Bienvenido a nginx!

Si ves esta página, el servidor web nginx está instalado y funcionando correctamente. Se requiere una configuración adicional.

Para documentación y soporte en línea, consulta nginx.org.
El soporte comercial está disponible en nginx.com.

Gracias por usar nginx.

Alternativamente, puedes abrir la URL http://:8080 en tu navegador y obtendrás la siguiente página.

Página de inicio de Nginx

Abre el panel de Kibana y haz clic en el enlace Descubrir en el menú de la barra lateral izquierda. Haz clic en el signo + en el menú superior para mostrar el popup de Agregar filtro.

Popup de agregar filtro de Kibana

Selecciona el campo container_name del menú desplegable, is como el operador y completa el nombre del contenedor (nginx-fluentd-test) como el valor del campo.

Consulta de selección de contenedor de Kibana

Haz clic en el botón Agregar filtro para visualizar los datos del contenedor de Nginx.

Registro de Fluentd del contenedor Nginx

Conclusión

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ícalas en los comentarios a continuación.

Share: X/Twitter LinkedIn

Recibe nuevas publicaciones en tu bandeja de entrada.

No spam. Cancela la suscripción en cualquier momento.