
Recopilant els LOGs de VMware ESXi a Elasticsearch i visualitzant-los a Grafana
Bueno pues hoy toca otro post sobre recopilación de logs, cómo tratarlos y sobre todo cómo visualizarlos; en este documento veremos cómo realizar todo el proceso con los Logs del hipervisor VMware ESXi, tratarlos con Elastic Stack y finalmente visualizar en Grafana lo que nos interese, como puedan ser logs de errores, de inicios de sesión incorrectos…
Todos los que trabajamos con infraestructuras de VMware conocemos que toda la base se sustenta en un fabuloso hipervisor, nuestros queridos los hosts ESXi. Un hipervisor basado en la seguridad y estabilidad, que pocos problemas suelen dar, pero que no viene nada mal recoger sus logs en un lugar centralizado para tener controlada su salud. Com sabem, podremos almacenar sus logs en un syslog, así que aprovechándonos de eso, mandaremos los Logs a Logstash. Logstash se encargará de recibir y ordenar los logs, separando tediosas cadenas de texto en distintos campos con datos válidos, para finalmente enviar a Elasticsearch estos datos y sean almacenados en un índice. Luego ya mediante Kibana o Grafana podremos visualizar de una manera gráfica ese contenido, y ver los intentos de login al host (por SSH, GUI…), ver simplemente accesos, conocer los eventos con errores, comparar distintos hipervisores entre sí, conocer errores repetitivos… y todo esto como siempre en tiempo real o para realizar históricos con datos de las últimas 24h, setmana, mes, any…
Primero obviamente tenemos que tener la parte de Elastic Stack instalada, el que ve sent Logstash, Elasticsearch y Kibana; luego ya sería indicarle a cada hipervisor que envíe los Logs a Logstash, al puerto que nos de la gana. Per això, tenemos muchas maneras de hacerlo, host a host, desde GUI, CLI, des de vCenter…
Lo más cómo si tienes pocos hosts, desde vCenter vamos a cada host, en “Configurar” > Configuración avanzada del sistema” > i busquem “syslog.global”, editamos ‘Syslog.global.logHost” indicando en formato tcp/udp://DIRECCION_IP:PUERTO el destino de nuestros Logs. O mejor aún con PowerShell:
Get-VMHostSysLogServer -VMHost NOMBRE_HOST_ESXi Set-VMHostSysLogServer -VMHost NOMBRE_HOST_ESXi -SysLogServer 'udp://DIRECCION_IP:PUERTO Set-VMHostSysLogServer -VMHost NOMBRE_HOST_ESXi -SysLogServer 'tcp://DIRECCION_IP:PUERTO Get-VMHostSysLogServer -VMHost NOMBRE_HOST_ESXi Get-VMhostFireWallException -VMhost NOMBRE_HOST_ESXi -Name syslog Get-VMHostFireWallException -VMHost NOMBRE_HOST_ESXi -Name Syslog | Set-VMHostFirewallException -Enabled:$True.
input { tcp { type => "ESXi" port => "1514" tags => ["VMware","ESXi"] } } filter { if [type] == "ESXi" { grok { match => { "message" => [ "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} Hostd: %{WORD:Log_nivel} %{PROG:Log_proceso}\[%{INT:Evento_id}\] \[Originator@6876 sub=%{GREEDYDATA:Títol} opID=%{GREEDYDATA:Op_id} user=%{GREEDYDATA:Usuari}\] %{GREEDYDATA:Evento_tipo} %{GREEDYDATA:Evento_codigo} : %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} Hostd: %{WORD:Log_nivel} %{PROG:Log_proceso}\[%{INT:Evento_id}\] \[Originator@6876 sub=%{GREEDYDATA:Títol} opID=%{GREEDYDATA:Op_id} user=%{GREEDYDATA:Usuari}\] %{GREEDYDATA:Evento_codigo}: %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} Hostd: %{WORD:Log_nivel} %{PROG:Log_proceso}\[%{INT:Evento_id}\] \[Originator@6876 sub=%{GREEDYDATA:Títol} opID=%{GREEDYDATA:Op_id} user=%{GREEDYDATA:Usuari}\] \(%{GREEDYDATA:Evento_codigo}\)", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} Hostd: %{WORD:Log_nivel} %{PROG:Log_proceso}\[%{INT:Evento_id}\] \[Originator@6876 sub=%{GREEDYDATA:Títol} opID=%{GREEDYDATA:Op_id}\] \[%{GREEDYDATA:Evento_codigo}\]: %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} Hostd: %{WORD:Log_nivel} %{PROG:Log_proceso}\[%{INT:Evento_id}\] \[Originator@6876 sub=%{GREEDYDATA:Títol} opID=%{GREEDYDATA:Op_id}\] %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} Hostd: %{WORD:Log_nivel} %{PROG:Log_proceso}\[%{INT:Evento_id}\] \[Originator@6876 sub=%{GREEDYDATA:Títol}\] %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} Hostd: %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} Vpxa: %{WORD:Log_nivel} %{PROG:Log_proceso}\[%{INT:Evento_id}\] \[Originator@6876 sub=%{GREEDYDATA:Títol} opID=%{GREEDYDATA:Op_id}\] %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} Vpxa: %{WORD:Log_nivel} %{PROG:Log_proceso}\[%{INT:Evento_id}\] \[Originator@6876 sub=%{GREEDYDATA:Títol}\] %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} Vpxa: %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} Rhttpproxy: %{WORD:Log_nivel} %{PROG:Log_proceso}\[%{INT:Evento_id}\] \[Originator@6876 sub=%{GREEDYDATA:Títol}\] %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} Rhttpproxy: %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} apiForwarder: %{WORD:Log_nivel} %{PROG:Log_proceso}\[%{INT:Evento_id}\] \[Originator@6876 sub=%{GREEDYDATA:Títol}\] %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} VSANMGMTSVC: %{WORD:Log_nivel} %{PROG:Log_proceso}\[%{INT:Evento_id}\] \[opID=%{GREEDYDATA:Títol}\] %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} vsansystem: %{WORD:Log_nivel} %{PROG:Log_proceso}\[%{INT:Evento_id}\] \[%{GREEDYDATA:Títol}\] %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} vsansystem: %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} vmkernel: %{WORD:CPU_core}:%{INT:Evento_id}\)%{GREEDYDATA:Títol}: %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} vmkernel: %{WORD:CPU_core}:%{INT:Evento_id} opID=%{PROG:Op_id}\)%{GREEDYDATA:Títol}: %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} vmkernel: %{WORD:CPU_core}:%{INT:Evento_id}\)%{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} vmkwarning: %{WORD:CPU_core}:%{INT:Evento_id}\)%{GREEDYDATA:Títol}: %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} Fdm: %{WORD:Log_nivel} %{PROG:Log_proceso}\[%{INT:Evento_id}\] \[Originator@6876 sub=%{GREEDYDATA:Títol} opID=%{PROG:Op_id}\] %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} Fdm: %{WORD:Log_nivel} %{PROG:Log_proceso}\[%{INT:Evento_id}\] \[Originator@6876 sub=%{GREEDYDATA:Títol}\] %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} hostd-probe: %{WORD:Log_nivel} %{PROG:Log_proceso}\[%{INT:Evento_id}\] \[Originator@6876 sub=%{GREEDYDATA:Títol}\] %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} %{PROG:Log_proceso}\[%{INT:Evento_id}\]: USER %{WORD:Usuari} pid %{INT:pid} %{WORD:Tipo_proceso} %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} %{PROG:Log_proceso}\[%{INT:Evento_id}\]: %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} esxtokend: %{WORD:Log_nivel} %{PROG:Log_proceso}\[%{INT:Evento_id}\] \[Originator@6876 sub=%{GREEDYDATA:Títol} opID=%{DATA:Op_id}\] %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} kmxa: %{WORD:Log_nivel} %{PROG:Log_proceso}\[%{INT:Evento_id}\] \[Originator@6876 sub=%{GREEDYDATA:Títol} opID=%{DATA:Op_id}\] %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} kmxa: %{WORD:Log_nivel} %{PROG:Log_proceso}\[%{INT:Evento_id}\] \[Originator@6876 sub=%{GREEDYDATA:Títol}\] %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} vobd: \[%{WORD:Log_nivel}\] %{WORD:Log_id}: \[%{GREEDYDATA:Títol}\] %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} configStoreBackup: %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} ConfigStore\[%{INT:Evento_id}\]: %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} heartbeat: %{WORD:Uptime_estado} %{WORD:Uptime_tiempo}, %{GREEDYDATA:MVs_encendidas}; %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} iscsid: %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} smartd: \[%{WORD:Log_nivel}\] %{GREEDYDATA:Títol}: %{GREEDYDATA:Mensaje}", "<%{POSINT:syslog_pri}>%{TIMESTAMP_ISO8601:Data} %{HOSTNAME:Host_ESXi} %{PROG:Log_proceso}\[%{INT:Evento_id}\]: %{GREEDYDATA:Mensaje}" ] } } } } output { if ([type]=="ESXi"){ elasticsearch { index => "vmware_esxi-%{+YYYY.MM.dd}" hosts => "DIRECCION_IP_ELASTICSEARCH:9200" } } }
Ahora toca Logstash, así que una vez conectados a él, creamos por un fichero de configuración , per exemple: ‘/etc/logstash/conf.d/vmware-esxi.conf’. Y será ahí donde indiquemos el puerto de escucha, si escogimos tcp o udp y además vienen los filtros. Así como siempre pido que no me tiren piedras los gurús, pero estos groks son válidos para parsear Logs de VMware ESXi 7.0, això sí, mejorables y mucho 😉 Bueno, tras separar los logs en trozos le indicaremos que lo vamos a almacenar en Elasticsearch, y ponemos un índice. Recordar no ser como yo y además añadir credenciales, això és: username & password.
Un cop creat el fitxer de configuració, recordar reiniciar el servicio de Logstash para recargar la nueva configuración. Després, anirem a Kibana i un cop les dades estiguin entrant ja podrem anar a "Management" > "Stack management" > "Kibana" > "Index Patterns" > "Crea't index pattern" per crear el patró de l'índex, el que s' ha dit, com habitualment (en aquest cas i sense les cometes) ‘vmware_esxi-*’ y tendremos los datos ya en Elasticsearch almacenados de manera correcta. Ahora podríamos conectarnos desde “Discover” a nuestro índice de VMware ESXi y visualizar que está recogiendo datos, que todos los hosts envían…
Y para acabar, tras crear el índice en Kibana, ahora en Grafana deberíamos crear un “Data Source” que apunte contra nuestro Elasticsearch y el índice recién creado de VMware ESXi. Després ja és deixar volar la imaginació, fer un Dashboard amb diferents Panells, amb diferents dades a visualitzar, un panel de estilo Sankey para ver IPs origen/destino y el tráfico que se envían, en formato columnas, en taules per veure dades concretes de per exemple els intents d'accessos, correctes, incorrectes, fer un top amb els logs d'errors i intentar solucionar-los, comparar entre distintos hosts la ‘normalidad’ de la frecuencia de ciertos logs de info, warning, error….
Com sempre, todo esto para intentar inspiraros si necesitáis, per agafar idees i millorar-les, así que con esto podréis ver qué pasa en vuestros ESXi’s en tiempo real, posant un refresc automàtic cada 10 segundos queda muy impresionante, també ens servirà per analitzar el resum de l'últim dia, o conocer cuando algo extraño sucede… Como siempre, gracias a todos y a tope con los que movéis este tipo de contenidos en redes sociales!!!