website/content/es/docs/tasks/debug-application-cluster/logging-stackdriver.md

367 lines
15 KiB
Markdown

---
title: Escribiendo Logs con Stackdriver
content_type: concept
---
<!-- overview -->
Antes de seguir leyendo esta página, deberías familiarizarte con el
[resumen de escritura de logs en Kubernetes](/docs/concepts/cluster-administration/logging).
{{< note >}}
Por defecto, Stackdriver recolecta toda la salida estándar de tus contenedores, así
como el flujo de la salida de error. Para recolectar cualquier log tu aplicación escribe en un archivo (por ejemplo),
ver la [estrategia de sidecar](/docs/concepts/cluster-administration/logging#sidecar-container-with-a-logging-agent)
en el resumen de escritura de logs en Kubernetes.
{{< /note >}}
<!-- body -->
## Despliegue
Para ingerir logs, debes desplegar el agente de Stackdriver Logging en cada uno de los nodos de tu clúster.
Dicho agente configura una instancia de `fluentd`, donde la configuración se guarda en un `ConfigMap`
y las instancias se gestionan a través de un `DaemonSet` de Kubernetes. El despliegue actual del
`ConfigMap` y el `DaemonSet` dentro de tu clúster depende de tu configuración individual del clúster.
### Desplegar en un nuevo clúster
#### Google Kubernetes Engine
Stackdriver es la solución por defecto de escritura de logs para aquellos clústeres desplegados en Google Kubernetes Engine.
Stackdriver Logging se despliega por defecto en cada clúster a no ser que se le indique de forma explícita no hacerlo.
#### Otras plataformas
Para desplegar Stackdriver Logging en un *nuevo* clúster que estés creando con
`kube-up.sh`, haz lo siguiente:
1. Configura la variable de entorno `KUBE_LOGGING_DESTINATION` con el valor `gcp`.
1. **Si no estás trabajando en GCE**, incluye `beta.kubernetes.io/fluentd-ds-ready=true`
en la variable `KUBE_NODE_LABELS`.
Una vez que tu clúster ha arrancado, cada nodo debería ejecutar un agente de Stackdriver Logging.
Los `DaemonSet` y `ConfigMap` se configuran como extras. Si no estás usando `kube-up.sh`,
considera la posibilidad de arrancar un clúster sin una solución pre-determinada de escritura de logs
y entonces desplegar los agentes de Stackdriver Logging una vez el clúster esté ejecutándose.
{{< warning >}}
El proceso de Stackdriver Logging reporta problemas conocidos en plataformas distintas
a Google Kubernetes Engine. Úsalo bajo tu propio riesgo.
{{< /warning >}}
### Desplegar a un clúster existente
1. Aplica una etiqueta en cada nodo, si no estaba presente ya.
El despliegue del agente de Stackdriver Logging utiliza etiquetas de nodo para
determinar en qué nodos debería desplegarse. Estas etiquetas fueron introducidas
para distinguir entre nodos de Kubernetes de la versión 1.6 o superior.
Si el clúster se creó con Stackdriver Logging configurado y el nodo tiene la
versión 1.5.X o inferior, ejecutará fluentd como un pod estático. Puesto que un nodo
no puede tener más de una instancia de fluentd, aplica únicamente las etiquetas
a los nodos que no tienen un pod de fluentd ya desplegado. Puedes confirmar si tu nodo
ha sido etiquetado correctamente ejecutando `kubectl describe` de la siguiente manera:
```
kubectl describe node $NODE_NAME
```
La salida debería ser similar a la siguiente:
```
Name: NODE_NAME
Role:
Labels: beta.kubernetes.io/fluentd-ds-ready=true
...
```
Asegúrate que la salida contiene la etiqueta `beta.kubernetes.io/fluentd-ds-ready=true`.
Si no está presente, puedes añadirla usando el comando `kubectl label` como se indica:
```
kubectl label node $NODE_NAME beta.kubernetes.io/fluentd-ds-ready=true
```
{{< note >}}
Si un nodo falla y tiene que volver a crearse, deberás volver a definir
la etiqueta al nuevo nodo. Para facilitar esta tarea, puedes utilizar el
parámetro de línea de comandos del Kubelet para aplicar dichas etiquetas
cada vez que se arranque un nodo.
{{< /note >}}
1. Despliega un `ConfigMap` con la configuración del agente de escritura de logs ejecutando el siguiente comando:
```
kubectl apply -f https://k8s.io/examples/debug/fluentd-gcp-configmap.yaml
```
Este comando crea el `ConfigMap` en el espacio de nombres `default`. Puedes descargar el archivo
manualmente y cambiarlo antes de crear el objeto `ConfigMap`.
1. Despliega el agente `DaemonSet` de escritura de logs ejecutando el siguiente comando:
```
kubectl apply -f https://k8s.io/examples/debug/fluentd-gcp-ds.yaml
```
Puedes descargar y editar este archivo antes de usarlo igualmente.
## Verificar el despliegue de tu agente de escritura de logs
Tras el despliegue del `DaemonSet` de StackDriver, puedes comprobar el estado de
cada uno de los despliegues de los agentes ejecutando el siguiente comando:
```shell
kubectl get ds --all-namespaces
```
Si tienes 3 nodos en el clúster, la salida debería ser similar a esta:
```
NAMESPACE NAME DESIRED CURRENT READY NODE-SELECTOR AGE
...
default fluentd-gcp-v2.0 3 3 3 beta.kubernetes.io/fluentd-ds-ready=true 5m
...
```
Para comprender cómo funciona Stackdriver, considera la siguiente especificación
de un generador de logs sintéticos [counter-pod.yaml](/examples/debug/counter-pod.yaml):
{{< codenew file="debug/counter-pod.yaml" >}}
Esta especificación de pod tiene un contenedor que ejecuta una secuencia de comandos bash
que escribe el valor de un contador y la fecha y hora cada segundo, de forma indefinida.
Vamos a crear este pod en el espacio de nombres por defecto.
```shell
kubectl apply -f https://k8s.io/examples/debug/counter-pod.yaml
```
Puedes observar el pod corriendo:
```shell
kubectl get pods
```
```
NAME READY STATUS RESTARTS AGE
counter 1/1 Running 0 5m
```
Durante un período de tiempo corto puedes observar que el estado del pod es 'Pending', debido a que el kubelet
tiene primero que descargar la imagen del contenedor. Cuando el estado del pod cambia a `Running`
puedes usar el comando `kubectl logs` para ver la salida de este pod contador.
```shell
kubectl logs counter
```
```
0: Mon Jan 1 00:00:00 UTC 2001
1: Mon Jan 1 00:00:01 UTC 2001
2: Mon Jan 1 00:00:02 UTC 2001
...
```
Como se describe en el resumen de escritura de logs, este comando visualiza las entradas de logs
del archivo de logs del contenedor. Si se termina el contenedor y Kubernetes lo reinicia,
todavía puedes acceder a los logs de la ejecución previa del contenedor. Sin embargo,
si el pod se desaloja del nodo, los archivos de log se pierden. Vamos a demostrar este
comportamiento mediante el borrado del contenedor que ejecuta nuestro contador:
```shell
kubectl delete pod counter
```
```
pod "counter" deleted
```
y su posterior re-creación:
```shell
kubectl create -f https://k8s.io/examples/debug/counter-pod.yaml
```
```
pod/counter created
```
Tras un tiempo, puedes acceder a los logs del pod contador otra vez:
```shell
kubectl logs counter
```
```
0: Mon Jan 1 00:01:00 UTC 2001
1: Mon Jan 1 00:01:01 UTC 2001
2: Mon Jan 1 00:01:02 UTC 2001
...
```
Como era de esperar, únicamente se visualizan las líneas de log recientes. Sin embargo,
para una aplicación real seguramente prefieras acceder a los logs de todos los contenedores,
especialmente cuando te haga falta depurar problemas. Aquí es donde haber habilitado
Stackdriver Logging puede ayudarte.
## Ver logs
El agente de Stackdriver Logging asocia metadatos a cada entrada de log, para que puedas usarlos posteriormente
en consultas para seleccionar sólo los mensajes que te interesan: por ejemplo,
los mensajes de un pod en particular.
Los metadatos más importantes son el tipo de recurso y el nombre del log.
El tipo de recurso de un log de contenedor tiene el valor `container`, que se muestra como
`GKE Containers` en la UI (incluso si el clúster de Kubernetes no está en Google Kubernetes Engine).
El nombre de log es el nombre del contenedor, de forma que si tienes un pod con
dos contenedores, denominados `container_1` y `container_2` en la especificación, sus logs
tendrán los nombres `container_1` y `container_2` respectivamente.
Los componentes del sistema tienen el valor `compute` como tipo de recursos, que se muestra como
`GCE VM Instance` en la UI. Los nombres de log para los componentes del sistema son fijos.
Para un nodo de Google Kubernetes Engine, cada entrada de log de cada componente de sistema tiene uno de los siguientes nombres:
* docker
* kubelet
* kube-proxy
Puedes aprender más acerca de cómo visualizar los logs en la [página dedicada a Stackdriver](https://cloud.google.com/logging/docs/view/logs_viewer).
Uno de los posibles modos de ver los logs es usando el comando de línea de interfaz
[`gcloud logging`](https://cloud.google.com/logging/docs/api/gcloud-logging)
del [SDK de Google Cloud](https://cloud.google.com/sdk/).
Este comando usa la [sintaxis de filtrado](https://cloud.google.com/logging/docs/view/advanced_filters) de StackDriver Logging
para consultar logs específicos. Por ejemplo, puedes ejecutar el siguiente comando:
```none
gcloud beta logging read 'logName="projects/$YOUR_PROJECT_ID/logs/count"' --format json | jq '.[].textPayload'
```
```
...
"2: Mon Jan 1 00:01:02 UTC 2001\n"
"1: Mon Jan 1 00:01:01 UTC 2001\n"
"0: Mon Jan 1 00:01:00 UTC 2001\n"
...
"2: Mon Jan 1 00:00:02 UTC 2001\n"
"1: Mon Jan 1 00:00:01 UTC 2001\n"
"0: Mon Jan 1 00:00:00 UTC 2001\n"
```
Como puedes observar, muestra los mensajes del contenedor contador tanto de la
primera como de la segunda ejecución, a pesar de que el kubelet ya había eliminado los logs del primer contenedor.
### Exportar logs
Puedes exportar los logs al [Google Cloud Storage](https://cloud.google.com/storage/)
o a [BigQuery](https://cloud.google.com/bigquery/) para llevar a cabo un análisis más profundo.
Stackdriver Logging ofrece el concepto de destinos, donde puedes especificar el destino de
las entradas de logs. Más información disponible en la [página de exportación de logs](https://cloud.google.com/logging/docs/export/configure_export_v2) de StackDriver.
## Configurar los agentes de Stackdriver Logging
En ocasiones la instalación por defecto de Stackdriver Logging puede que no se ajuste a tus necesidades, por ejemplo:
* Puede que quieras añadir más recursos porque el rendimiento por defecto no encaja con tus necesidades.
* Puede que quieras añadir un parseo adicional para extraer más metadatos de tus mensajes de log,
como la severidad o referencias al código fuente.
* Puede que quieras enviar los logs no sólo a Stackdriver o sólo enviarlos a Stackdriver parcialmente.
En cualquiera de estos casos, necesitas poder cambiar los parámetros del `DaemonSet` y el `ConfigMap`.
### Prerequisitos
Si estás usando GKE y Stackdriver Logging está habilitado en tu clúster, no puedes
cambiar su configuración, porque ya está gestionada por GKE.
Sin embargo, puedes deshabilitar la integración por defecto y desplegar la tuya propia.
{{< note >}}
Tendrás que mantener y dar soporte tú mismo a la nueva configuración desplegada:
actualizar la imagen y la configuración, ajustar los recuros y todo eso.
{{< /note >}}
Para deshabilitar la integración por defecto, usa el siguiente comando:
```
gcloud beta container clusters update --logging-service=none CLUSTER
```
Puedes encontrar notas acerca de cómo instalar los agentes de Stackdriver Logging
en un clúster ya ejecutándose en la [sección de despliegue](#deploying).
### Cambiar los parámetros del `DaemonSet`
Cuando tienes un `DaemonSet` de Stackdriver Logging en tu clúster, puedes simplemente
modificar el campo `template` en su especificación, y el controlador del daemonset actualizará los pods por ti. Por ejemplo,
asumamos que acabas de instalar el Stackdriver Logging como se describe arriba. Ahora quieres cambiar
el límite de memoria que se le asigna a fluentd para poder procesar más logs de forma segura.
Obtén la especificación del `DaemonSet` que corre en tu clúster:
```shell
kubectl get ds fluentd-gcp-v2.0 --namespace kube-system -o yaml > fluentd-gcp-ds.yaml
```
A continuación, edita los requisitos del recurso en el `spec` y actualiza el objeto `DaemonSet`
en el apiserver usando el siguiente comando:
```shell
kubectl replace -f fluentd-gcp-ds.yaml
```
Tras un tiempo, los pods de agente de Stackdriver Logging se reiniciarán con la nueva configuración.
### Cambiar los parámetros de fluentd
La configuración de Fluentd se almacena en un objeto `ConfigMap`. Realmente se trata de un conjunto
de archivos de configuración que se combinan conjuntamente. Puedes aprender acerca de
la configuración de fluentd en el [sitio oficial](http://docs.fluentd.org).
Imagina que quieres añadir una nueva lógica de parseo a la configuración actual, de forma que fluentd pueda entender
el formato de logs por defecto de Python. Un filtro apropiado de fluentd para conseguirlo sería:
```
<filter reform.**>
type parser
format /^(?<severity>\w):(?<logger_name>\w):(?<log>.*)/
reserve_data true
suppress_parse_error_log true
key_name log
</filter>
```
Ahora tienes que añadirlo a la configuración actual y que los agentes de Stackdriver Logging la usen.
Para ello, obtén la versión actual del `ConfigMap` de Stackdriver Logging de tu clúster
ejecutando el siguiente comando:
```shell
kubectl get cm fluentd-gcp-config --namespace kube-system -o yaml > fluentd-gcp-configmap.yaml
```
Luego, como valor de la clave `containers.input.conf`, inserta un nuevo filtro justo después
de la sección `source`.
{{< note >}}
El orden es importante.
{{< /note >}}
Actualizar el `ConfigMap` en el apiserver es más complicado que actualizar el `DaemonSet`.
Es mejor considerar que un `ConfigMap` es inmutable. Así, para poder actualizar la configuración, deberías
crear un nuevo `ConfigMap` con otro nombre y cambiar el `DaemonSet` para que apunte al nuevo
siguiendo la [guía de arriba](#changing-daemonset-parameters).
### Añadir plugins de fluentd
Fluentd está desarrollado en Ruby y permite extender sus capacidades mediante el uso de
[plugins](http://www.fluentd.org/plugins). Si quieres usar un plugin que no está incluido en
la imagen por defecto del contenedor de Stackdriver Logging, debes construir tu propia imagen.
Imagina que quieres añadir un destino Kafka para aquellos mensajes de un contenedor en particular
para poder procesarlos posteriormente. Puedes reusar los [fuentes de imagen de contenedor](https://git.k8s.io/contrib/fluentd/fluentd-gcp-image)
con algunos pequeños cambios:
* Cambia el archivo Makefile para que apunte a tu repositorio de contenedores, ej. `PREFIX=gcr.io/<your-project-id>`.
* Añade tu dependencia al archivo Gemfile, por ejemplo `gem 'fluent-plugin-kafka'`.
Luego, ejecuta `make build push` desde ese directorio. Cuando el `DaemonSet` haya tomado los cambios de la nueva imagen,
podrás usar el plugin que has indicado en la configuración de fluentd.