Collecte de logs Kubernetes

Cette page explique comment collecter des logs à partir des fichiers de logs Kubernetes.

Lorsque vos applications conteneurisées écrivent leurs journaux sur la sortie standard et l’erreur (stdout/stderr), le runtime de conteneur et Kubernetes gèrent automatiquement les journaux pour vous. Le modèle par défaut est que Kubernetes stocke ces flux de journaux sous forme de fichiers sur l’hôte dans le dossier /var/log/pods et les sous-dossiers pour chaque Pod et conteneur.

L’Agent Datadog peut collecter ces fichiers journaux Kubernetes pour ces conteneurs en utilisant les instructions ci-dessous. Cette option s’adapte bien à la nature éphémère des Pods que Kubernetes crée et est plus efficace en termes de ressources que la collecte des journaux à partir du socket Docker. Datadog recommande cette méthode pour la collecte des journaux dans Kubernetes.

Alternativement, l’Agent Datadog peut également collecter des journaux par des requêtes répétées à l’API Docker via le socket Docker. Cependant, cela nécessite Docker comme runtime de conteneur pour votre cluster Kubernetes. C’est également plus gourmand en ressources que l’utilisation des fichiers journaux. Pour voir comment collecter des journaux en utilisant le socket Docker, consultez Collecte de journaux avec le socket Docker. Si vos applications conteneurisées écrivent dans des fichiers journaux stockés dans le conteneur, cela peut compliquer la collecte des journaux. Voir la collecte des journaux à partir d’un fichier.

Configuration

Collecte des journaux

Avant de commencer la collecte des logs d’application, assurez-vous que l’Agent Datadog est en cours d’exécution dans votre cluster Kubernetes.

Pour configurer manuellement la collecte des journaux dans le DaemonSet, consultez Collecte des journaux DaemonSet. Dans le cas contraire, suivez les instructions ci-dessous :

Mettez à jour votre manifeste datadog-agent.yaml avec :

apiVersion: datadoghq.com/v2alpha1
kind: DatadogAgent
metadata:
  name: datadog
spec:
  global:
    credentials:
      apiKey: <DATADOG_API_KEY>

  features:
    logCollection:
      enabled: true
      containerCollectAll: true

Ensuite, appliquez la nouvelle configuration :

kubectl apply -n $DD_NAMESPACE -f datadog-agent.yaml

Voir l’exemple manifeste avec collecte de journaux, de métriques et d’APM activée pour un exemple supplémentaire. Vous pouvez définir features.logCollection.containerCollectAll sur true pour collecter les journaux de tous les conteneurs découverts par défaut. Lorsqu’il est défini sur false (par défaut), vous devez spécifier les configurations d’autodécouverte de logs pour activer la collecte des journaux. Pour plus d’informations, voir Découverte des journaux - Filtrage.

Pour activer la collecte des journaux avec Helm, mettez à jour votre fichier datadog-values.yaml avec la configuration de collecte des journaux suivante. Ensuite, mettez à jour votre Helm chart Datadog :

datadog:
  logs:
    enabled: true
    containerCollectAll: true

Vous pouvez définir datadog.logs.containerCollectAll sur true pour collecter les journaux de tous les conteneurs découverts par défaut. Lorsqu’il est défini sur false (par défaut), vous devez spécifier les configurations d’autodécouverte de logs pour activer la collecte des journaux. Pour plus d’informations, voir Découverte des journaux - Filtrage.

Non privilégié

(Optionnel) Pour exécuter une installation non privilégiée, ajoutez ce qui suit à la ressource personnalisée DatadogAgent :

apiVersion: datadoghq.com/v2alpha1
kind: DatadogAgent
metadata:
  name: datadog
spec:
  global:
    credentials:
      apiKey: <DATADOG_API_KEY>

  features:
    logCollection:
      enabled: true
      containerCollectAll: true

  override:
    nodeAgent:
      securityContext:
        runAsUser: <USER_ID>
        supplementalGroups:
          - <DOCKER_GROUP_ID>
  • Remplacez <USER_ID> par l’UID pour exécuter l’Agent
  • Remplacez <DOCKER_GROUP_ID> par l’ID de groupe qui possède le socket Docker ou containerd.

(Optionnel) Pour exécuter une installation non privilégiée, ajoutez ce qui suit dans le fichier values.yaml :

datadog:
  securityContext:
    runAsUser: <USER_ID>
    supplementalGroups:
      - <DOCKER_GROUP_ID>
  • Remplacez <USER_ID> par l’UID pour exécuter l’Agent.
  • Remplacez <DOCKER_GROUP_ID> par l’ID de groupe qui possède le socket Docker ou containerd.
Avertissement pour les installations non privilégiées

Lors de l'exécution d'une installation non privilégiée, l'Agent doit pouvoir lire les fichiers journaux dans /var/log/pods.

Si vous utilisez le runtime containerd, les fichiers journaux dans /var/log/pods sont lisibles par les membres du root groupe. Avec les instructions ci-dessus, l'Agent s'exécute avec le root groupe. Aucune action n'est requise.

Si vous utilisez le runtime Docker, les fichiers journaux dans /var/log/pods sont des liens symboliques vers /var/lib/docker/containers, qui n'est accessible que par le root utilisateur. Par conséquent, avec le runtime Docker, un Agent non privilégié ne peut pas lire les journaux.root Agent de lire les journaux dans /var/log/pods. Le socket Docker doit être monté dans le conteneur Agent, afin qu'il puisse obtenir les journaux des Pods via le démon Docker.

Pour collecter les journaux de conteneurs, lorsque le socket Docker est monté, définissez la variable d'environnement (ou dans …) sur [valeur appropriée]. Cela force l'Agent à utiliser le mode de collecte de fichiers. /var/log/pods lorsque le socket Docker est monté, définissez la variable d'environnement DD_LOGS_CONFIG_K8S_CONTAINER_USE_FILE (ou logs_config.k8s_container_use_file dans datadog.yaml) sur true. Cela force l'Agent à utiliser le mode de collecte de fichiers.

Découverte des journaux

L’Agent Datadog dans Kubernetes est déployé par un DaemonSet (géré par l’Opérateur Datadog ou Helm). Ce DaemonSet planifie une réplique du Pod Agent sur chaque nœud du cluster. Chaque Pod Agent est alors responsable de la remontée des journaux des autres Pods et conteneurs sur son nœud respectif. Lorsque la fonctionnalité “Collecter tous les conteneurs” est activée, l’Agent remonte les journaux d’un conteneur avec une étiquette et correspondant au nom d’image court du conteneur.

Filtrage

Lorsque “Collecter tous les conteneurs” est activé, vous pouvez configurer de quels conteneurs vous souhaitez collecter les journaux. Cela peut être utile pour empêcher la collecte des journaux de l’Agent Datadog, si désiré. Vous pouvez le faire en passant des configurations à l’Agent Datadog pour contrôler ce qu’il collecte, ou en passant des configurations au Pod Kubernetes pour exclure certains journaux de manière plus explicite.

Lorsque vous filtrez des journaux par des méthodes comme DD_CONTAINER_EXCLUDE_LOGS ou ad.datadoghq.com/logs_exclude, l’Agent ignore la collecte de journaux, quelle que soit la configuration de collecte de journaux explicitement définie dans les annotations d’autodécouverte ou les fichiers de configuration d’autodécouverte.

Lorsque “Container Collect All” est désactivé (par défaut), vous n’avez pas besoin d’ajouter de filtrage car tout est exclu par défaut. Pour inclure la collecte uniquement pour les pods sélectionnés, vous pouvez activer la configuration des journaux par les annotations d’autodécouverte ou les fichiers de configuration d’autodécouverte pour les pods souhaités.

Consultez la section Gestion de la détection des conteneurs (en anglais) pour en savoir plus sur le filtrage.

Étiquetage

L’Agent Datadog étiquette les journaux des conteneurs Kubernetes avec les étiquettes Kubernetes par défaut, ainsi que toutes les étiquettes extraites personnalisées. Lorsque “Collecter tous les conteneurs” est activé, l’Agent remonte les journaux d’un conteneur en lui associant une étiquette source et service correspondant au nom d’image court du conteneur. Par exemple, les journaux d’un conteneur utilisant l’image de conteneur gcr.io/owner/example-image:latest auraient example-image comme valeur d’étiquette source, service et short_image.

L’étiquette service peut également être définie par l’étiquette de Pod tags.datadoghq.com/service: "<SERVICE>" de l’étiquetage de service unifié. Pour plus d’informations sur les attributs source et service, voir Attributs réservés.

L’étiquette source peut être importante pour vos journaux, car les pipelines de journaux prêts à l’emploi sont filtrés en utilisant cette étiquette. Cependant, ces pipelines peuvent être entièrement personnalisés selon vos souhaits. Vous pouvez voir les étapes dans la section Journaux d’intégration ci-dessous pour personnaliser davantage les étiquettes de vos journaux.

Journaux d’intégration

L’autodécouverte vous permet d’utiliser des modèles pour configurer la collecte de journaux (et d’autres capacités) sur les conteneurs. Cela peut être utilisé pour activer la collecte de journaux, personnaliser l’étiquetage et ajouter des règles de collecte avancées. Pour configurer la collecte de journaux pour une intégration avec l’autodécouverte, vous pouvez soit :

  • Spécifier une configuration de journal en tant qu’annotations d’autodécouverte sur un Pod donné, pour configurer les règles pour un conteneur donné (Recommandé)
  • Spécifier une configuration de journal en tant que fichier de configuration, pour configurer les règles pour chaque conteneur correspondant par image.

Au minimum, ces configurations de journalisation nécessitent une étiquette source et une étiquette service. Vous souhaiterez peut-être faire correspondre la balise source à l’un des pipelines de journalisation prêts à l’emploi de Datadog pour aider à enrichir automatiquement vos journaux. Vous pouvez également trouver une bibliothèque de pipelines dans Datadog.

Annotations d’autodécouverte

Avec Autodiscovery, l’Agent recherche automatiquement les modèles d’intégration dans les annotations des pods.

Pour appliquer une configuration spécifique à un conteneur donné, ajoutez l’annotation ad.datadoghq.com/<CONTAINER_NAME>.logs à votre Pod avec la configuration de journalisation au format JSON.

Remarque : Les annotations d’autodécouverte identifient les conteneurs par nom, pas par image. Il essaie de faire correspondre <CONTAINER_NAME> au .spec.containers[i].name, pas à .spec.containers[i].image.

Si vous définissez directement vos Pods Kubernetes (avec les annotations appropriées), ajoutez les annotations de chaque Pod dans leur section, comme indiqué dans la section suivante. kind:Pod), ajoutez les annotations de chaque Pod dans son metadata section, comme indiqué dans la section suivante.

Si vous définissez indirectement vos Pods Kubernetes (avec des contrôleurs de réplication, des ReplicaSets ou des Déploiements), ajoutez les annotations de Pod au modèle de Pod comme indiqué. .spec.template.metadata.

Configurer un seul conteneur

Pour configurer la collecte des logs pour un conteneur donné dans un pod, ajoutez les annotations suivantes à votre pod :

apiVersion: v1
kind: Pod
# (...)
metadata:
  name: '<POD_NAME>'
  annotations:
    ad.datadoghq.com/<CONTAINER_NAME>.logs: '[<LOG_CONFIG>]'
    # (...)
spec:
  containers:
    - name: '<CONTAINER_NAME>'
# (...)

Exemple d’annotations d’autodécouverte de journal

L’annotation de Pod suivante définit le modèle d’intégration pour un conteneur d’exemple. Il est défini dans les annotations du modèle de Pod, plutôt que sur le Déploiement lui-même. Cette configuration de journalisation définit tous les journaux du conteneur app avec les balises source:java, service:example-app, et la balise supplémentaire foo:bar.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: example
  labels:
    app: example-app
spec:
  selector:
    matchLabels:
      app: example-app
  template:
    metadata:
      labels:
        app: example-app
      annotations:
        ad.datadoghq.com/app.logs: '[{"source":"java", "service":"example-app", "tags":["foo:bar"]}]'
    spec:
      containers:
        - name: app
          image: owner/example-image:latest

Configurer deux conteneurs différents

Pour appliquer deux modèles d’intégration différents à deux conteneurs différents dans votre Pod, <CONTAINER_NAME_1> et <CONTAINER_NAME_2>, ajoutez les annotations suivantes à votre Pod :

apiVersion: v1
kind: Pod
# (...)
metadata:
  name: '<POD_NAME>'
  annotations:
    ad.datadoghq.com/<CONTAINER_NAME_1>.logs: '[<LOG_CONFIG_1>]'
    # (...)
    ad.datadoghq.com/<CONTAINER_NAME_2>.logs: '[<LOG_CONFIG_2>]'
spec:
  containers:
    - name: '<CONTAINER_NAME_1>'
    # (...)
    - name: '<CONTAINER_NAME_2>'
# (...)

Fichiers de configuration d’autodécouverte

Vous pouvez fournir à l’Agent Datadog des fichiers de configuration pour que l’Agent exécute une intégration spécifiée lorsqu’il découvre un conteneur utilisant l’identifiant d’image correspondant. Cela vous permet de créer une configuration de journalisation générique qui s’applique à un ensemble d’images de conteneurs.

Vous pouvez personnaliser la collecte des journaux par intégration avec une surcharge dans le override.nodeAgent.extraConfd.configDataMap. Cette méthode crée le ConfigMap et monte le fichier de configuration souhaité sur le conteneur de l’Agent.

apiVersion: datadoghq.com/v2alpha1
kind: DatadogAgent
metadata:
  name: datadog
spec:
  #(...)
  override:
    nodeAgent:
      extraConfd:
        configDataMap:
          <INTEGRATION_NAME>.yaml: |-
            ad_identifiers:
            - <CONTAINER_IMAGE>
        
            logs:
            - source: example-source
              service: example-service

Le <CONTAINER_IMAGE> doit correspondre au nom court de l’image du conteneur auquel vous souhaitez que cela s’applique. Voir le manifeste d’exemple avec mappage ConfigMap pour un exemple supplémentaire.

Vous pouvez personnaliser la collecte des journaux par intégration dans datadog.confd. Cette méthode crée le ConfigMap et monte le fichier de configuration souhaité sur le conteneur de l’Agent.

datadog:
  #(...)
  confd:
    <INTEGRATION_NAME>.yaml: |-
      ad_identifiers:
      - <CONTAINER_IMAGE>
      
      logs:
      - source: example-source
        service: example-service

Le <CONTAINER_IMAGE> doit correspondre au nom court de l’image du conteneur auquel vous souhaitez que cela s’applique.

Les commandes etcd suivantes créent un modèle d’intégration Redis avec un paramètre password personnalisé et étiquettent les journaux avec les attributs source et service corrects :

etcdctl mkdir /datadog/check_configs/redis
etcdctl set /datadog/check_configs/redis/logs '[{"source": "redis", "service": "redis", "tags": ["env:prod"]}]'

Remarquez que chacune des trois valeurs est une liste. L’autodécouverte assemble les éléments de la liste dans les configurations d’intégration en fonction des index de liste partagés. Dans ce cas, elle compose la première (et unique) configuration de vérification à partir de check_names[0], init_configs[0] et instances[0].

Contrairement aux fichiers de configuration automatique, les magasins de valeurs clés peuvent utiliser le nom d’image court OU long comme identifiants de conteneur, par exemple, redis OU redis:latest.

Autodiscovery peut utiliser Consul, Etcd et Zookeeper comme sources de modèles d’intégration.

Pour utiliser un magasin de valeurs clés, configurez-le dans le fichier de configuration de l’Agent datadog.yaml et montez ce fichier à l’intérieur de l’Agent conteneurisé. Sinon, passez votre magasin de valeurs clés en tant que variables d’environnement à l’Agent conteneurisé.

Dans datadog.yaml

Dans le fichier datadog.yaml, définissez l’adresse <KEY_VALUE_STORE_IP> et <KEY_VALUE_STORE_PORT> de votre magasin de valeurs clés :

config_providers:
  - name: etcd
    polling: true
    template_dir: /datadog/check_configs
    template_url: '<KV_STORE_IP>:<KV_STORE_PORT>'
    username:
    password:

  - name: consul
    polling: true
    template_dir: datadog/check_configs
    template_url: '<KV_STORE_IP>:<KV_STORE_PORT>'
    ca_file:
    ca_path:
    cert_file:
    key_file:
    username:
    password:
    token:

  - name: zookeeper
    polling: true
    template_dir: /datadog/check_configs
    template_url: '<KV_STORE_IP>:<KV_STORE_PORT>'
    username:
    password:

Redémarrez ensuite l’Agent pour prendre en compte le changement de configuration.

Dans les variables d’environnement

Avec le magasin de valeurs clés activé en tant que source de modèle, l’Agent recherche des modèles sous la clé /datadog/check_configs. L’autodécouverte s’attend à une hiérarchie de clés-valeurs comme ceci :

/datadog/
  check_configs/
    <CONTAINER_IMAGE>/
      - logs: ["<LOGS_CONFIG>"]
    ...

Remarque : Pour appliquer une configuration spécifique à un conteneur donné, l’autodécouverte identifie les conteneurs par image lors de l’utilisation des magasins de valeurs clés en essayant de faire correspondre <CONTAINER_IMAGE> à .spec.containers[0].image.

Pour associer une configuration de journal à un ensemble de conteneurs avec plus de granularité que le nom d’image court du conteneur, voir Identifiants de conteneurs d’autodécouverte.

Collecte avancée des journaux

Utilisez les étiquettes de log Autodiscovery afin d’appliquer la logique de processing pour la collecte de logs avancée, par exemple :

À partir d’un fichier journal local de conteneur

Datadog recommande d’utiliser les flux de sortie stdout et stderr pour les applications conteneurisées, afin de pouvoir configurer automatiquement la collecte des journaux.

Cependant, l’Agent peut également collecter directement des journaux à partir d’un fichier basé sur une annotation. Pour collecter ces journaux, utilisez ad.datadoghq.com/<CONTAINER_NAME>.logs avec une configuration type: file et path. Les journaux collectés à partir de fichiers avec une telle annotation sont automatiquement étiquetés avec le même ensemble d’étiquettes que les journaux provenant du conteneur lui-même. Datadog recommande d’utiliser les flux de sortie stdout et stderr pour les applications conteneurisées, afin de pouvoir configurer automatiquement la collecte des journaux. Pour plus d’informations, voir les Configurations recommandées.

Ces chemins de fichiers sont relatifs au conteneur de l’Agent. Par conséquent, le répertoire contenant le fichier journal doit être monté à la fois dans l’application et le conteneur de l’Agent afin que l’Agent puisse avoir une visibilité appropriée.

Par exemple, vous pouvez le faire avec un volume partagé hostPath. Le Pod ci-dessous émet des journaux dans le fichier /var/log/example/app.log. Cela se fait dans le répertoire /var/log/example, où un volume et un volumeMount ont défini cela comme un hostPath.

apiVersion: v1
kind: Pod
metadata:
  name: logger
  annotations:
    ad.datadoghq.com/busybox.logs: |
      [{
          "type": "file",
          "path": "/var/log/example/app.log",
          "source": "example-source",
          "service": "example-service"
      }]
spec:
  containers:
   - name: busybox
     image: busybox
     command: [ "/bin/sh", "-c", "--" ]
     args: [ "while true; do sleep 1; echo `date` example file log >> /var/log/example/app.log; done;" ]
     volumeMounts:
     - name: applogs
       mountPath: /var/log/example
  volumes:
     - name: applogs
       hostPath:
         path: /var/log/example

Le même volume et le même chemin volumeMount doivent être définis dans le conteneur de l’Agent pour qu’il puisse lire ce fichier de log.

  containers:
  - name: agent
    # (...)
    volumeMounts:
    - mountPath: /var/log/example
      name: applogs
    # (...)
  volumes:
  - name: applogs
    hostPath:
      path: /var/log/example
    # (...)
  • Cette stratégie peut fonctionner pour un pod donné, mais peut devenir encombrante avec plusieurs applications utilisant cette stratégie. Vous pouvez également rencontrer des problèmes si plusieurs répliques utilisent le même chemin de journal. Si possible, Datadog recommande d’exploiter la variable de modèle Autodiscovery template variable %%kube_pod_name%%. Par exemple, vous pouvez définir votre path pour référencer cette variable : "path": "/var/log/example/%%kube_pod_name%%/app.log". Votre pod d’application doit également écrire ses fichiers journaux par rapport à ce nouveau chemin. Vous pouvez utiliser l’API Downward pour aider votre application à déterminer le nom de son Pod.

  • Lorsque vous utilisez ce type d’annotation avec un conteneur, stdout et stderr les journaux ne sont pas collectés automatiquement à partir du conteneur. Si la collecte à partir des deux flux de sortie du conteneur et du fichier est nécessaire, activez cela explicitement dans l’annotation. Exemple :

    ad.datadoghq.com/<CONTAINER_IMAGE>.logs: |
      [
        {"type":"file","path":"/var/log/example/app.log","source":"file","service":"example-service"},
        {"source":"container","service":"example-service"}
      ]
    
  • Lorsque vous utilisez ce type de combinaison, source et service n’ont pas de valeur par défaut pour les journaux collectés à partir d’un fichier et doivent être définis explicitement dans l’annotation.

Dépannage

Pour les étapes de dépannage, voir Dépannage de la collecte des journaux de conteneur.

Lectures complémentaires