diff --git a/content/fr/docs/concepts/cluster-administration/logging.md b/content/fr/docs/concepts/cluster-administration/logging.md new file mode 100644 index 0000000000..18e80dc650 --- /dev/null +++ b/content/fr/docs/concepts/cluster-administration/logging.md @@ -0,0 +1,358 @@ +--- +reviewers: +- piosz +- x13n +title: Architecture de Journalisation d'évènements (logging) +content_template: templates/concept +weight: 60 +--- + +{{% capture overview %}} + +La journalisation des évènements systèmes et d'applications peut aider à +comprendre ce qui se passe dans un cluster. Les journaux sont particulièrement +utiles pour débogguer les problèmes et surveiller l'activité du cluster. La +plupart des application modernes ont un mécanisme de journalisation +d'évènements, et la plupart des environnements d'exécution de conteneurs ont été +conçus pour supporter la journalisation des évènements. La méthode de +journalisation la plus facile et la plus répandue pour des applications +conteneurisées est d'écrire dans les flux de sortie standard et d'erreur +standard (`stdout` et `stderr`). + +Malgré cela, la fonctionnalité de journalisation fournie nativement par +l'environnement d'exécution de conteneurs n'est pas suffisante comme solution +complète de journalisation. Quand un conteneur crash, quand un Pod est expulsé +ou quand un nœud disparaît, il est utile de pouvoir accéder au journal +d'événement de l'application. C'est pourquoi les journaux doivent avoir leur +propre espace de stockage et un cycle de vie indépendamment des nœuds, Pods ou +conteneurs. Ce concept est appelé _journalisation des évènements au niveau du +cluster_ (cluster-level-logging). Un backend dédié pour stocker, analyser et +faire des requêtes est alors nécessaire. Kubernetes n'offre pas nativement de +solution de stockage pour les journaux mais il est possible d'intégrer de +nombreuses solutions de journalisation d'évènements dans un cluster Kubernetes. + + +{{% /capture %}} + + +{{% capture body %}} + +L'architecture de journalisation des évènements au niveau du cluster est décrite +en considérant qu'un backend de journalisation est présent à l'intérieur ou à +l'extérieur du cluster. Même sans avoir l'intention de journaliser les +évènements au niveau du cluster, il est intéressant de savoir comment les +journaux sont conservés et gérés au niveau d'un nœud. + +## Journalisation simple d'évènements dans Kubernetes + +Dans cette section, on va utiliser un exemple simple de journalisation +d'évènements avec le flux de sortie standard. Cette démonstration utilise un +manifeste pour un Pod avec un seul conteneur qui écrit du texte sur le flux +de sortie standard toutes les secondes. + +{{< codenew file="debug/counter-pod.yaml" >}} + +Pour lancer ce Pod, utilisez la commande suivante : + +```shell +kubectl apply -f https://k8s.io/examples/debug/counter-pod.yaml +``` +Le résultat est : +``` +pod/counter created +``` + +Pour récupérer les événements du conteneur d'un pod, utilisez la commande +`kubectl logs` de la manière suivante : + +```shell +kubectl logs counter +``` +Le résultat est : +``` +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 +... +``` + +Utilisez `kubectl logs` pour récupérer les évènements de l'instanciation +précédente d'un Pod en utilisant l'option `--previous` quand par exemple le +conteneur a crashé. + +Si le Pod a plusieurs conteneurs, il faut spécifier le nom du conteneur dont on +veut récupérer le journal d'évènement. Dans notre exemple le conteneur s'appelle +`count` donc vous pouvez utiliser `kubectl logs counter count`. Plus de détails +dans la [documentation de `kubectl +logs`] (/docs/reference/generated/kubectl/kubectl-commands#logs) + +## Journalisation d'évènements au niveau du nœud + +![Journalisation d'évènements au niveau du +nœud](/images/docs/user-guide/logging/logging-node-level.png) + +Tout ce qu'une application conteneurisée écrit sur `stdout` ou `stderr` est pris +en compte et redirigé par l'environment d'exécution des conteneurs. Par exemple, +Docker redirige ces deux flux à un [driver de journalisation +(EN)](https://docs.docker.com/config/containers/logging/configure/) qui est +configuré dans Kubernetes pour écrire dans un fichier au format json. + +{{< note >}} Le driver json de Docker traite chaque ligne comme un message +différent. Avec ce driver il n'y a pas de support direct pour des messages +multi-lignes. Il faut donc traiter les messages multi-lignes au niveau de +l'agent de journalisation ou plus haut. {{< /note >}} + +Par défaut quand un conteneur redémarre, le kubelet ne conserve le journal que +du dernier conteneur terminé. Quand un Pod est expulsé d'un nœud, tous ses +conteneurs sont aussi expulsés avec leurs journaux d'évènements. + +Quand on utilise la journalisation d'évènements au niveau du nœud, il faut +prendre garde à mettre en place une politique de rotation des journaux adéquate +afin qu'ils n'utilisent pas tout l'espace de stockage du nœud. Kubernetes n'a +pas en charge la rotation des journaux, c'est à l'outil de déploiement de le +prendre en compte. + +Par exemple, dans les clusters Kubernetes déployés avec le script `kube-up.sh` +[`logrotate`](https://linux.die.net/man/8/logrotate) est configuré pour +s'exécuter toutes les heures. Il est aussi possible de configurer +l'environnement d'exécution des conteneurs pour que la rotation des journaux +s'exécute automatiquement, e.g. en utilisant le paramètre `log-opt` de Docker. +Dans le script `kube-up.sh`, c'est cette méthode qui est utilisée pour des +images COS sur GCP et sinon c'est la première méthode dans tous les autres cas. +Quel que soit la méthode choisie par `kube-up.sh` la rotation est configurée par +defaut quand la taille d'un journal atteint 10 Mo. + +Ce [script][cosConfigureHelper] montre de manière détaillée comment `kube-up.sh` +met en place la journalisation d'évènement pour des images COS sur GCP. + +Quand [`kubectl logs`](/docs/reference/generated/kubectl/kubectl-commands#logs) +s'exécute comme dans le premier exemple de journalisation simple le kubelet du +nœud gère la requête et lit directement depuis le fichier de journal et retourne +son contenu dans la réponse. + +{{< note >}} Si un système externe a effectué la rotation des journaux, seul le +contenu du dernier fichier journal sera disponible avec `kubectl logs`. Par +exemple quand le journal atteint 10 Mo, `logrotate` effectue une rotation, il y a +alors 2 fichers, un de 10 Mo et un de vide, à ce moment là `kubectl logs` +retournera une réponse vide. {{< /note >}} + +[cosConfigureHelper]: https://github.com/kubernetes/kubernetes/blob/{{< param +"githubbranch" >}}/cluster/gce/gci/configure-helper.sh + +### Journalisation des évènements des composants système + +Il y a deux types de composants système selon qu'ils s'exécutent dans un +conteneur ou pas. + +Par exemple : + +* Le scheduler Kubernetes et kube-proxy s'exécutent dans un conteneur. +* Kubelet et l'environment d'exécution de conteneurs, comme par exemple +Docker, ne s'exécutent pas dans un conteneur. + +Sur les systèmes avec systemd, kubelet et l'environment d'exécution de +conteneurs écrivent dans journald. Si systemd n'est pas présent, ils écrivent +dans un fichier `.log` dans le répertoire `/var/log`. + +Les composants système qui s'exécutent dans un conteneur écrivent toujours dans +le répertoire `/var/log`, en contournant le mécanisme de journalisation par +défaut. Ils utilisent la bibliothèque de journalisation [klog][klog]. Les +conventions pour la sévérité des évènements pour ces composants se trouvent dans +cette [documentation sur les conventions de journalisation des évènements dans +kubernetes] +(https://github.com/kubernetes/community/blob/master/contributors/devel/sig-instrumentation/logging.md). + +De la même manière que les journaux des conteneurs, les journaux des composants +systèmes doivent avoir une politique de rotation. Dans un cluster créé avec +le script `kube-up.sh`, les journaux ont une rotation journalière ou quand leur +taille atteint 100 Mo. + +[klog]: https://github.com/kubernetes/klog + +## Architecture de journalisation des évènements au niveau du cluster + +Kubernetes ne fournit pas de solution native pour la journalisation des +évènements au niveau du cluster. Mais il y a différentes approches qui peuvent +être considérées : + +* Utiliser un agent de journalisation au niveau du nœud sur chacun des nœuds. +* Inclure un conteneur side-car pour journaliser les évènements du Pod +applicatif. +* Envoyer les évènements directement a un backend depuis l'application. + +### Utiliser un agent de journalisation au niveau du nœud + +![Utiliser un agent de journalisation au niveau du +nœud](/images/docs/user-guide/logging/logging-with-node-agent.png) + +Vous pouvez implémenter une journalisation au niveau du cluster en incluant un +_agent de journalisation au niveau du nœud_ sur chacun des nœuds. L'agent de +journalisation est un outil dédié qui met à disposition ou envoie les journaux à +un backend. Communément l'agent de journalisation est un conteneur qui a accès +au répertoire qui contient les journaux des conteneurs applicatifs sur ce nœud. + +Comme l'agent de journalisation doit s'exécuter sur chacun des nœuds, on utilise +soit un DaemonSet, soit un manifeste de Pod, soit un processus dédié natif sur +le nœud. Ces deux dernières options sont obsolètes et fortement découragées. + +Utiliser un agent de journalisation au niveau du nœud est l'approche la plus +commune et recommandée pour un cluster Kubernetes parce qu'un seul agent par +nœud est créé et qu'aucune modification dans l'application n'est nécessaire. +Mais cette approche _ne fonctionne correctement que pour les flux standard de +sortie et d'erreurs des applications_. + +Kubernetes ne définit pas d'agent de journalisation, mais deux agents de +journalisation optionnels sont fournis avec la version de Kubernetes : +[Stackdriver (EN)](/docs/user-guide/logging/stackdriver) pour utiliser sur +Google Cloud Platform, et [Elasticsearch +(EN)](/docs/user-guide/logging/elasticsearch). Les deux utilisent +[fluentd](http://www.fluentd.org/) avec une configuration spécifique comme agent +sur le nœud. Les liens précédents fournissent plus d'informations et les +instructions pour les utiliser et configurer. + +### Inclure un conteneur side-car pour journaliser les évènements du Pod applicatif + +Vous pouvez utiliser un conteneur side-car d'une des manières suivantes : + +* Le conteneur side-car diffuse les journaux de l'application sur son propre +`stdout`. +* Le conteneur side-car exécute un agent de journalisation qui est configuré +pour récupérer les journaux du conteneur applicatif. + +#### Conteneur side-car diffusant (Streaming sidecar container) + +![Conteneur side-car +diffusant](/images/docs/user-guide/logging/logging-with-streaming-sidecar.png) + +Comme le conteneur side-car diffuse les journaux sur ses propres flux `stdout` +et `stderr`, on peut bénéficier du kubelet et de l'agent de journalisation qui +s'exécute déjà sur chaque nœud. Les conteneurs side-car lisent les journaux +depuis un fichier, un socket ou bien journald. Chaque conteneur side-car écrit +son journal sur son propre flux `stdout` ou `stderr`. + +Cette méthode permet de séparer les flux de journaux de différentes +parties de votre application même si elles ne supportent pas d'écrire sur +`stdout` ou `stderr`. La logique de rediriger les journaux est minime et +le surcoût est non significatif. De plus comme les flux standards `stdout` et +`stderr` sont gérés par kubelet, les outils natifs comme `kubectl logs` peuvent +être utilisés. + +Regardez l'exemple qui suit. + +Un Pod exécute un unique conteneur et ce conteneur écrit dans deux fichiers de +journaux différents en utilisant deux format différents. Voici le manifeste du +Pod : + +{{< codenew file="admin/logging/two-files-counter-pod.yaml" >}} + +Il serait très désordonné d'avoir des évènements avec des formats différents +dans le même journal en redirigeant les évènements dans le flux de sortie +`stdout` d'un seul conteneur. Il est plutôt souhaitable d'utiliser deux +conteneurs side-car, un pour chaque type de journaux. Chaque conteneur side-car +suit un des fichiers et renvoie les évènements sur son propre `stdout`. + +Ci-dessous se trouve le manifeste pour un Pod avec deux conteneurs side-car. + +{{< codenew file="admin/logging/two-files-counter-pod-streaming-sidecar.yaml" +>}} + +Quand ce Pod s'exécute, chaque journal peut être diffusé séparément en +utilisant les commandes suivantes : + +```shell +kubectl logs counter count-log-1 +``` +``` +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 +... +``` + +```shell +kubectl logs counter count-log-2 +``` +``` +Mon Jan 1 00:00:00 UTC 2001 INFO 0 +Mon Jan 1 00:00:01 UTC 2001 INFO 1 +Mon Jan 1 00:00:02 UTC 2001 INFO 2 +... +``` + +L'agent au niveau du nœud installé dans le cluster récupère les deux flux de +journaux sans aucune configuration supplémentaire. Il est possible de configurer +l'agent pour qu'il analyse syntaxiquement les évènements en fonction du +conteneur source. + +Notez que bien que la consommation en CPU et mémoire soit faible ( de l'ordre de +quelques milicores pour la CPU et quelques mégaoctets pour la mémoire), ecrire +les évènements dans un fichier et les envoyer ensuite dans `stdout` peut doubler +l'espace disque utilisé. Quand une application écrit dans un seul fichier de +journal il est préférable de configurer `/dev/stdout` comme destination plutôt +que d'implémenter un conteneur side-car diffusant. + +Les conteneurs side-car peuvent être utilisés pour faire la rotation des +journaux quand l'application n'en est pas capable elle même. Un exemple serait +un petit conteneur side-car qui effectuerait cette rotation périodiquement. +Toutefois il est recommandé d'utiliser `stdout` et `stderr` directement et de +laisser la rotation et les politiques de rétentions au kubelet. + +### Conteneur side-car avec un agent de journalisation + +![Conteneur side-car avec un agent de +journalisation](/images/docs/user-guide/logging/logging-with-sidecar-agent.png) + +Quand un agent de journalisation au niveau du nœud n'est pas assez flexible pour +votre utilisation vous pouvez créer un conteneur side-car avec un agent de +journalisation séparé que vous avez configuré spécialement pour qu'il s'exécute +avec votre application. + +{{< note >}} +Utiliser un agent de journalisation dans un conteneur side-car peut entraîner +une consommation de ressource significative. De plus vous n'avez plus accès aux +journaux avec la commande `kubectl` parce qu'ils ne sont plus gérés par +kubelet. +{{< /note >}} + +Comme exemple, vous pouvez utiliser +[Stackdriver](/docs/tasks/debug-application-cluster/logging-stackdriver/) où + fluentd est l'agent de journalisation. Ci-dessous se trouvent deux +configurations qui implémentent cette méthode. + +Le premier fichier contient un +[ConfigMap](/docs/tasks/configure-pod-container/configure-pod-configmap/) pour +configurer fluentd. + +{{< codenew file="admin/logging/fluentd-sidecar-config.yaml" >}} + +{{< note >}} +La configuration de fluentd est hors du cadre de cet article. Vous trouverez +des informations pour configurer fluentd dans la [documentation officielle de +fluentd](http://docs.fluentd.org/). +{{< /note >}} + +Le second fichier est un manifeste pour un Pod avec un conteneur side-car qui +exécute fluentd. Le Pod monte un volume où fluentd peut récupérer sa +configuration. + +{{< codenew file="admin/logging/two-files-counter-pod-agent-sidecar.yaml" >}} + +Apres quelques minutes, les évènements apparaîtront dans l'interface de +Stackdriver. + +Ce n'est qu'un exemple et vous pouvez remplacer fluentd par n'importe quel +agent de journalisation qui lit depuis n'importe quelle source de votre +application. + +### Envoyer les évènements directement depuis l'application. + +![Envoyer les évènements directement a un backend depuis +l'application.](/images/docs/user-guide/logging/logging-from-application.png) + +Vous pouvez implémenter la journalisation au niveau cluster en mettant à +disposition ou en envoyant les journaux directement depuis chaque application; +Toutefois l'implémentation de ce mécanisme de journalisation est hors du cadre +de Kubernetes. + + +{{% /capture %}} diff --git a/content/fr/examples/admin/logging/fluentd-sidecar-config.yaml b/content/fr/examples/admin/logging/fluentd-sidecar-config.yaml new file mode 100644 index 0000000000..eea1849b03 --- /dev/null +++ b/content/fr/examples/admin/logging/fluentd-sidecar-config.yaml @@ -0,0 +1,25 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: fluentd-config +data: + fluentd.conf: | + + type tail + format none + path /var/log/1.log + pos_file /var/log/1.log.pos + tag count.format1 + + + + type tail + format none + path /var/log/2.log + pos_file /var/log/2.log.pos + tag count.format2 + + + + type google_cloud + diff --git a/content/fr/examples/admin/logging/two-files-counter-pod-agent-sidecar.yaml b/content/fr/examples/admin/logging/two-files-counter-pod-agent-sidecar.yaml new file mode 100644 index 0000000000..b37b616e6f --- /dev/null +++ b/content/fr/examples/admin/logging/two-files-counter-pod-agent-sidecar.yaml @@ -0,0 +1,39 @@ +apiVersion: v1 +kind: Pod +metadata: + name: counter +spec: + containers: + - name: count + image: busybox + args: + - /bin/sh + - -c + - > + i=0; + while true; + do + echo "$i: $(date)" >> /var/log/1.log; + echo "$(date) INFO $i" >> /var/log/2.log; + i=$((i+1)); + sleep 1; + done + volumeMounts: + - name: varlog + mountPath: /var/log + - name: count-agent + image: k8s.gcr.io/fluentd-gcp:1.30 + env: + - name: FLUENTD_ARGS + value: -c /etc/fluentd-config/fluentd.conf + volumeMounts: + - name: varlog + mountPath: /var/log + - name: config-volume + mountPath: /etc/fluentd-config + volumes: + - name: varlog + emptyDir: {} + - name: config-volume + configMap: + name: fluentd-config diff --git a/content/fr/examples/admin/logging/two-files-counter-pod-streaming-sidecar.yaml b/content/fr/examples/admin/logging/two-files-counter-pod-streaming-sidecar.yaml new file mode 100644 index 0000000000..87bd198cfd --- /dev/null +++ b/content/fr/examples/admin/logging/two-files-counter-pod-streaming-sidecar.yaml @@ -0,0 +1,38 @@ +apiVersion: v1 +kind: Pod +metadata: + name: counter +spec: + containers: + - name: count + image: busybox + args: + - /bin/sh + - -c + - > + i=0; + while true; + do + echo "$i: $(date)" >> /var/log/1.log; + echo "$(date) INFO $i" >> /var/log/2.log; + i=$((i+1)); + sleep 1; + done + volumeMounts: + - name: varlog + mountPath: /var/log + - name: count-log-1 + image: busybox + args: [/bin/sh, -c, 'tail -n+1 -f /var/log/1.log'] + volumeMounts: + - name: varlog + mountPath: /var/log + - name: count-log-2 + image: busybox + args: [/bin/sh, -c, 'tail -n+1 -f /var/log/2.log'] + volumeMounts: + - name: varlog + mountPath: /var/log + volumes: + - name: varlog + emptyDir: {} diff --git a/content/fr/examples/admin/logging/two-files-counter-pod.yaml b/content/fr/examples/admin/logging/two-files-counter-pod.yaml new file mode 100644 index 0000000000..6ebeb717a1 --- /dev/null +++ b/content/fr/examples/admin/logging/two-files-counter-pod.yaml @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: Pod +metadata: + name: counter +spec: + containers: + - name: count + image: busybox + args: + - /bin/sh + - -c + - > + i=0; + while true; + do + echo "$i: $(date)" >> /var/log/1.log; + echo "$(date) INFO $i" >> /var/log/2.log; + i=$((i+1)); + sleep 1; + done + volumeMounts: + - name: varlog + mountPath: /var/log + volumes: + - name: varlog + emptyDir: {} diff --git a/content/fr/examples/debug/counter-pod.yaml b/content/fr/examples/debug/counter-pod.yaml new file mode 100644 index 0000000000..f997886386 --- /dev/null +++ b/content/fr/examples/debug/counter-pod.yaml @@ -0,0 +1,10 @@ +apiVersion: v1 +kind: Pod +metadata: + name: counter +spec: + containers: + - name: count + image: busybox + args: [/bin/sh, -c, + 'i=0; while true; do echo "$i: $(date)"; i=$((i+1)); sleep 1; done']