Logs
Sin importar el tipo de aplicación que se esté desplegando los logs siempre son una pieza importante de la solución. En entornos de microservicios son todavía más importantes.
La forma más popular de resolver el problema de centralización y visualización de logs es a través del stack ELK. Esta solución es muy robusta y provee muchas features, pero su operación, en especial Elastic Search, es bastante compleja. Por eso, si no se cuenta con un stack ELK como servicio, quizá sea mejor analizar otras opciones.
Otra solución que está ganando tracción es Grafana Loki. Esta solución hace foco en la facilidad de operación a costa de indexar los logs sobre labels en vez de hacer full-text-search.
A continuación se muestra una forma de realizar una instalación funcional mínima de Loki, Grafana y Prometheus, ya que es la herramienta con la que venimos trabajando. Vale la pena aclarar, que si en su institución se decide ir por alguna otra solución sería bueno que comparta su experiencia con la comunidad.
Modificación de dominio base
Para facilitar los siguientes pasos, deberia encontrarse ubicado en el directorio expedientes
Ejecute el siguiente comando para hacer el cambio de dominio base
export DOMAIN_NAME_URL=universidad.edu.ar
sed -i "s/uunn\.local/${DOMAIN_NAME_URL}/g" \
./prod/servicios/monitoreo.yml \
./prod/servicios/config/prometheus.yml \
./prod/servicios/config/grafana/provisioning/datasources/datasource.yml
Servicio de Loki
Password de acceso
Para generar la password de loki, debemos modificar del comando debajo la seccion de < password.loki >
con la contraseña que queramos asignarle, la cual se encriptara y se guardara en la variable $CLAVE
CLAVE=$(openssl passwd -apr1 < password.loki > | sed 's/\$/\$\$/g')
echo $CLAVE
Ésta misma clave encriptada la guardaremos en ./prod/servicios/monitoreo.yml
mediante el siguiente sed
.
sed -i "s/password\.loki/${CLAVE}/g" \
./prod/servicios/monitoreo.yml
Luego la clave sin encriptar debemos guardarla en los siguientes archivos ./prod/servicios/config/grafana/provisioning/datasources/datasource.yml
y ./prod/servicios/promtail/promtail-config.yml
mediante el sed
.
export CLAVE= < password.loki.sinEncriptar >
sed -i "s/password\.loki/${CLAVE}/g" \
./prod/servicios/config/grafana/provisioning/datasources/datasource.yml \
./prod/servicios/promtail/promtail-config.yml
En caso que el ambiente en el que este desplegando los servicios utilice una CA auto firmada, debe dirigirse en este paso a
./prod/servicios/config/grafana/provisioning/datasources/datasource.yml
y descomentar los parametrostlsSkipVerify
para que grafana pueda configurar correctamente los datasource
Plugin loki en docker swarm
Instalación
Para configurar el plugin de loki ejecutar en cada nodo de swarm el comando:
docker plugin install grafana/loki-docker-driver:2.3.0 --alias loki --grant-all-permissions
Configuración tentativa
Para que cada nodo del swarm envíe automaticamente los logs a loki debemos crear el archivo de configuracion del daemon de docker. Para esto, creamos el archivo /etc/docker/daemon.json
con el siguiente contenido (prestando especial atencion a la indentación y el formateo .json)
{
"debug" : false,
"log-driver": "loki",
"log-opts": {
"loki-url": "https://loki: < password.loki > @ < DOMAIN_NAME_URL > /loki/loki/api/v1/push",
"loki-batch-size": "400",
"loki-timeout": "3s",
"loki-retries": "3"
}
}
En caso de ser necesario mas detalles de los logs, hay que cambiar la variable "debug" : true
(tener en cuenta que en un entorno productivo tener logs a nivel debug pueden ocupar mucho espacio en el disco).
Para poder utilizar certificados self-signed deberá insertar la siguiente linea:
"loki-tls-insecure-skip-verify": "true"
Una vez que el archivo esté creado, para que se apliquen los cambios debemos reiniciar docker (para esto se podria utilizar systemctl restart docker
). Tener en cuenta que esto conllevara a que se reinicien todos los contenedores que tenemos levantados.
Para mas información o configuraciones adicionales la documentación del plugin es esta https://github.com/grafana/loki/blob/v1.5.0/docs/clients/docker-driver/README.md
Configuración alternativa
Si no desea los logs del nodo completo puede configurar loki por servicio:
https://grafana.com/docs/loki/latest/clients/docker-driver/configuration/
o por contenedor:
https://grafana.com/docs/loki/latest/clients/docker-driver/configuration/
Servicio de Prometheus
Previo a inicializar prometheus junto con los servicios exportadores de metricas (node-exporter, cAdvisor, blackbox-exporter y postgres exporter) debemos realizar una configuracion inicial especificamente para asegurarnos del correcto funcionamiento del postgres exporter:
Configuracion inicial
En primera instancia debemos crear un usuario en postgres para el exportador, asignarle una contraseña, y darle acceso a pg_monitor. Esto lo haremos entrando en la db y ejecutando el siguiente comando:
CREATE USER postgres_exporter WITH PASSWORD ' < password > ';
GRANT pg_monitor to postgres_exporter;
Posterior a haber creado el nuevo usuario para postgres_exporter, debemos crear un secret del mismo, con la misma pass, de la siguiente manera:
printf ' < password > ' | docker secret create pgexporter_pass -
Luego tenemos que ir al archivo prod/servicios/monitoreo.yml y cambiar los valores de conexión a la db:
environment:
- DATA_SOURCE_URI=postgres-db:5432/postgres?sslmode=disable
- DATA_SOURCE_USER=postgres_exporter
- DATA_SOURCE_PASS_FILE=/run/secrets/pgexporter_pass
- PG_EXPORTER_EXTEND_QUERY_PATH=/etc/postgres_exporter/queries.yaml
Finalmente, en caso que la base de datos se encuentre en un servidor externo y no local, debemos habilitar el acceso a este nuevo usuario a dicha base para su correcta conexión. Para hacer esto, es necesario agregar la siguiente linea en /etc/postgresql/ < version > /main/pg_hba.conf
host all postgres_exporter < ip-del-servidor-con-postgres-exporter > md5
(Opcional) Endpoint de acceso para prometheus
NOTA: En caso de no activar el endpoint de acceso a prometheus, proseguir con la parte de configuracion Grafana.
Activar el endpoint de acceso a prometheus nos permitirá acceder al dashboard del mismo. Con él es posible verificar servicios de los cuales se colectan logs y su estado. Sin embargo en un ambiente productivo no es recomendado habilitar el endpoint sin un ipwhitelist de por medio (ya sea de traefik u otro proxy reverso), de lo contrario podria accederse desde cualquier lado.
Para activar el endpoint de prometheus y asi poder ver su dashboard lo que tenemos que hacer es ingresar en monitoreo.yml y descomentar las siguientes labels:
labels:
- "traefik.enable=true"
- "traefik.http.routers.prometheus.entrypoints=web-secured"
- "traefik.http.routers.prometheus.rule=Host(`uunn.local`) && PathPrefix(`/prometheus`)"
- "traefik.http.routers.prometheus.tls=true"
- "traefik.http.middlewares.prometheus-auth.basicauth.users=prometheus:$$apr1$$nJtnozKc$$VHJC0yD2C398geG/5Yu/e1"
- "traefik.http.routers.prometheus.middlewares=prometheus-auth@docker"
- "traefik.http.services.prometheus.loadbalancer.server.port=9090"
Luego en el ./config/prometheus.yml debemos descomentar la siguiente seccion y proceder a comentar la parte de dns_sd_configs:
metrics_path: /prometheus/metrics
scrape_interval: 15s
scheme: https
static_configs:
- targets: ['uunn.local']
basic_auth:
username: 'prometheus'
password: 'password.prometheus'
Para generar la password de prometheus seguiremos los mismos pasos que cuando generamos la password de loki
CLAVE=$(openssl passwd -apr1 < password.prometheus > | sed 's/\$/\$\$/g')
echo $CLAVE
Ésta misma clave encriptada la guardaremos en ./prod/servicios/monitoreo.yml
mediante el siguiente sed
.
sed -i "s/password\.prometheus/${CLAVE}/g" \
./prod/servicios/monitoreo.yml
Luego la clave sin encriptar debemos guardarla en los siguientes archivos ./prod/servicios/config/grafana/provisioning/datasources/datasource.yml
y ./prod/servicios/promtail/promtail-config.yml
mediante el sed
.
export CLAVE= < password.prometheus.sinEncriptar >
sed -i "s/password\.prometheus/${CLAVE}/g" \
./prod/servicios/config/prometheus.yml \
./prod/servicios/config/grafana/provisioning/datasources/datasource.yml
Por ultimo tenemos que ir a datasource.yml comentar la url que esta por defecto, y descomentar la url que se va a utilizar url: https://uunn.local/prometheus
Luego en ese mismo archivo mas abajo encontraremos la seccion basicAuth
el cual deberemos poner en true, descomentar el basicAuthPassword y constatar que tenga el usuario y password correspondiente
# < bool > enable/disable basic auth
basicAuth: false
# < string > basic auth username, if used
basicAuthUser: prometheus
secureJsonData:
basicAuthPassword: password.loki
Finalmente solo queda volver a deployear el stack de monitoreo y tendriamos habilitado el endpoint uunn.local/prometheus.
(Opcional) Servicio de Promtail
Promtail es un servicio (agente) encargado de enviar el contenido de los logs locales del sistema a una instancia centralizada de grafana/loki. Permite integrar sistemas y/o servicios tipo "legacy", ya sean instalados "onpremise" por fuera de un cluster Docker Swarm, o que generan logs en múltiples archivos.
Nota: Debe ser desplegado en cada uno de los servidores en donde se requiera recolectar logs locales para ser enviados a grafana/loki.
A modo explicativo, se describirá a continuación el contenido de los archivos esenciales para desplegar este servicio mediante Docker (pero en otro servidor, fuera del cluster Docker Swarm). Es posible utilizar además los archivos que se encuentran en el repositorio de EEI en la carpeta "servicios/promtail", los cuales ya tienen cargados los paths de algunos servicios esenciales (Apache2, PostgresSQL, etc) y posibles aplicativos satélites del EEI (Pilaga, Diaguita, Mapuche).
docker-compose.yml
Este es el archivo donde levantaremos un contenedor de promtail. Es importante entender que en este mismo archivo debe montarse como volumenes los logs que querramos que lea promtail debajo del parametro volumes
. A modo de ejemplo están comentadas 2 lineas.
Notas:
- El parametro
restart:always
es para que en caso de que se reinicie el servidor/docker el contenedor se vuelva a levantar automáticamente. - El volumen
${PWD}:/mnt/config
básicamente monta el archivo de config en el mismo path/directorio que el archivo compose. Esto lo termina confirmando promtail en la lineacommand: -config.file=/mnt/config/promtail-config.yml
. Si decide guardar el archivo de configuración en un directorio distinto, debe modificar éste volumen por el path/directorio que corresponda.
version: "3.9"
services:
promtail:
image: grafana/promtail:2.6.1
volumes:
#Formato: - < Directorio/del/path/local > : < Directorio/del/path/contenedor >
#Ejemplo: - /var/log/apache2:/srv/apache2 o /var/log/apache2:/srv/apache2:ro para montar como read-only
- ${PWD}:/mnt/config
command: -config.file=/mnt/config/promtail-config.yml
restart: always
promtail-config.yml
Archivo de configuracion. Aquí se especificará tanto la url del servicio de loki donde enviaremos los logs, como los labels y otros datos referidos a los logs montados en el contenedor.
Notas:
- Debajo del bloque
clients
está el parametrourl
. Acá debe modificarse el endpoint al correspondiente al servicio de loki donde promtail centralizará los logs. - En caso de probar esta instalación en un ambiente de desarrollo/prueba con un certificado autofirmdao se debe cambiar el valor del parámetro
insecure_skip_verify
atrue
ya que de otra manera promtail arrojará un error. - Para más información acerca del bloque
scrape_configs
y sobre__path__
, referirse al README ubicado en la carpeta servicios/promtail.
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: https:// < loki.user > : < loki.pass > @ < uunn.siu.edu.ar > /loki/loki/api/v1/push
tls_config:
insecure_skip_verify: false # dejar en true para ambiente de desarrollo, con certificado self signed
scrape_configs:
- job_name: system
static_configs:
- targets:
- localhost
labels:
job: legacyappslogs
source: stderr
host: < nombre-del-server >
__path__: /srv/*/error.log # el path debe ser de donde se encuentra el log en el contenedor, NO en el host.
Finalmente para levantar el servicio, basta con solo usar docker compose up
Configuración grafana
Crear secret
La clave de grafana se puede generar con
printf 'grafanapassword' | docker secret create grafana_pass -
o mediante el ./prod/arai/secrets.sh.dist
con el resto de las claves
Acceso desde otras redes
Por default Grafana solo soporta acceso local. para setear las redes desde las cuales necesita acceder puede editar prod/servicios/monitoreo.yml
la sección
- "traefik.http.middlewares.grafana-ipwhitelist.ipwhitelist.sourcerange=127.0.0.1/32, < IP-RED/MASCARA > "
reemplace < IP-RED/MASCARA > por la IP o RED a autorizar el acceso
Deploy del stack
En el directorio prod/servicios/
se incluye un stack mínimo de deploy de monitoreo. Para utilizarlo, ejecute:
docker stack deploy \
-c prod/servicios/monitoreo.yml \
monitoreo
Es importante notar estos 2 volumenes:
log-data
. Este volumen es el que se debe backupear para salvar la historia de logs.grafana-data
. Este volumen es el que debe backupear para salvar la configuración, usuarios y dashboards de Grafana.
Acceso y configuracion de Grafana
Para poder acceder a la aplicación desde el navegador universidad.edu.ar/metricas
utilice como credencial de usuario admin
y como clave la que usted haya setteado en el secret.
Siga las instrucciones en https://github.com/grafana/loki/blob/v1.5.0/docs/getting-started/grafana.md#loki-in-grafana para poder ver los logs a través de Grafana.
Con respecto a loki: tenga en cuenta que instalación NO es escalable horizontalmente ya que utiliza un backend de Storage (BoltDB) que no lo soporta. Es decir, no puede haber más de 1 replica del servicio. Si esto es deseable, por el momento puede referirse a la documentación de Loki: https://github.com/grafana/loki/tree/v1.5.0/docs.
Siga las instrucciones en (grafana-dashboard.md) para poder configurar los dashboards predeterminados de EEI.
Visualización de logs
Si todo funcionó correctamente, a medida que vaya interactuando con los contenedores de su clúster los logs empezarán a aparecer en Grafana. Por defecto se puede filtrar por las siguientes categorías:
También puede construir queries bastante más ricas utilizando el lenguaje provisto por la herramienta, llamado LogQL