Ce que vous devez savoir sur la journalisation des clusters dans Kubernetes

La journalisation des serveurs et des applications est une fonctionnalité importante pour les développeurs, les opérateurs et les équipes de sécurité pour comprendre l’état d’une application en cours d’exécution dans leur environnement de production.
La journalisation permet aux opérateurs de déterminer si les applications et les composants requis fonctionnent correctement et de détecter si quelque chose d’inhabituel se produit afin qu’ils puissent réagir à la situation.
Pour les développeurs, la journalisation donne une visibilité pour dépanner le code pendant et après le développement. Dans un environnement de production, le développeur s’appuie généralement sur une fonction de journalisation sans outils de débogage. Couplé à la journalisation des systèmes, les développeurs peuvent travailler main dans la main avec les opérateurs pour résoudre efficacement les problèmes.
Le bénéficiaire le plus important des installations de journalisation est l’équipe de sécurité, en particulier dans un environnement cloud natif. La possibilité de collecter des informations à partir des applications et des journaux système permet à l’équipe de sécurité d’analyser les données de l’authentification, de l’accès des applications aux activités malveillantes où elles peuvent y répondre si nécessaire.
Kubernetes est la principale plate-forme de conteneurs où de plus en plus d’applications sont déployées en production. Je pense que comprendre l’architecture de journalisation de Kubernetes est une entreprise très importante que chaque équipe de développement, d’exploitation et de sécurité doit prendre au sérieux.
Dans cet article, je discute du fonctionnement des différents modèles de journalisation des conteneurs dans Kubernetes.
Contents
Journalisation du système et journalisation des applications
Avant d’approfondir l’architecture de journalisation Kubernetes, j’aimerais explorer les différentes approches de journalisation et comment les deux fonctionnalités sont des caractéristiques essentielles de la journalisation Kubernetes.
Il existe deux types de composants système : ceux qui s’exécutent dans un conteneur et ceux qui ne le font pas. Par exemple:
- Le planificateur Kubernetes et
kube-proxy
courir dans un conteneur. - Les
kubelet
et le runtime de conteneur ne s’exécutent pas dans des conteneurs.
Semblables aux journaux de conteneur, les journaux de conteneur système sont stockés dans le /var/log
répertoire, et vous devez les faire pivoter régulièrement.
Ici, je considère la journalisation des conteneurs. Tout d’abord, je regarde la journalisation au niveau du cluster et pourquoi elle est importante pour les opérateurs de cluster. Les journaux de cluster fournissent des informations sur les performances du cluster. Des informations telles que la raison pour laquelle les pods ont été expulsés ou le nœud meurt. La journalisation des clusters peut également capturer des informations telles que l’accès aux clusters et aux applications et la façon dont l’application utilise les ressources de calcul. Dans l’ensemble, une fonction de journalisation de cluster fournit aux opérateurs de cluster des informations utiles pour le fonctionnement et la sécurité du cluster.
L’autre moyen de capturer les journaux de conteneurs consiste à utiliser la fonction de journalisation native de l’application. La conception d’applications modernes a très probablement un mécanisme de journalisation qui aide les développeurs à résoudre les problèmes de performances des applications via une sortie standard (stdout
) et les flux d’erreurs (stderr
).
Pour disposer d’une fonction de journalisation efficace, la mise en œuvre de Kubernetes nécessite à la fois des composants de journalisation des applications et du système.
3 types de journalisation des conteneurs Kubernetes
Il existe trois méthodes principales de journalisation au niveau du cluster que vous voyez dans la plupart des implémentations Kubernetes de nos jours.
- Agent de journalisation au niveau du nœud
- Application de conteneur side-car pour la journalisation
- Exposition des journaux d’application directement au backend de journalisation
Agent de journalisation au niveau du nœud
J’aimerais considérer l’agent de journalisation au niveau du nœud. Vous les implémentez généralement en utilisant un DaemonSet comme stratégie de déploiement pour déployer un pod (qui agit comme un agent de journalisation) dans tous les nœuds Kubernetes. Cet agent de journalisation est ensuite configuré pour lire les journaux de tous les nœuds Kubernetes. Vous configurez généralement l’agent pour lire les nœuds /var/logs
capture de répertoire stdout
/stderr
flux et l’envoyer au stockage principal de journalisation.
La figure ci-dessous montre la journalisation au niveau du nœud exécutée en tant qu’agent dans tous les nœuds.
Pour configurer la journalisation au niveau du nœud à l’aide de la fluentd
approche à titre d’exemple, vous devez procéder comme suit :
- Tout d’abord, vous devez créer un ServiceAccount appelé
fluentdd
. Ce compte de service est utilisé par les pods Fluentd pour accéder à l’API Kubernetes, et vous devez les créer dans l’espace de noms de journalisation avec le libelléapp: fluentd
.#fluentd-SA.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: fluentd
namespace: logging
labels:
app: fluentdVous pouvez voir l’exemple complet dans ce dépôt.
- Vous devez ensuite créer un ConfigMap
fluentd-configmap
. Cela fournit un fichier de configuration aufluentd daemonset
avec toutes les propriétés requises.#fluentd-daemonset.yaml
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: fluentd
namespace: logging
labels:
app: fluentd
kubernetes.io/cluster-service: "true"
spec:
selector:
matchLabels:
app: fluentd
kubernetes.io/cluster-service: "true"
template:
metadata:
labels:
app: fluentd
kubernetes.io/cluster-service: "true"
spec:
serviceAccount: fluentd
containers:
- name: fluentd
image: fluent/fluentd-kubernetes-daemonset:v1.7.3-debian-elasticsearch7-1.0
env:
- name: FLUENT_ELASTICSEARCH_HOST
value: "elasticsearch.logging.svc.cluster.local"
- name: FLUENT_ELASTICSEARCH_PORT
value: "9200"
- name: FLUENT_ELASTICSEARCH_SCHEME
value: "http"
- name: FLUENT_ELASTICSEARCH_USER
value: "elastic"
- name: FLUENT_ELASTICSEARCH_PASSWORD
valueFrom:
secretKeyRef:
name: efk-pw-elastic
key: password
- name: FLUENT_ELASTICSEARCH_SED_DISABLE
value: "true"
resources:
limits:
memory: 512Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
- name: fluentconfig
mountPath: /fluentd/etc/fluent.conf
subPath: fluent.conf
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
- name: fluentconfig
configMap:
name: fluentdconfVous pouvez voir l’exemple complet dans ce dépôt.
Maintenant, je regarde le code sur la façon de déployer un fluentd daemonset
en tant qu’agent de journalisation.
#fluentd-daemonset.yaml
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: fluentd
namespace: logging
labels:
app: fluentd
kubernetes.io/cluster-service: "true"
spec:
selector:
matchLabels:
app: fluentd
kubernetes.io/cluster-service: "true"
template:
metadata:
labels:
app: fluentd
kubernetes.io/cluster-service: "true"
spec:
serviceAccount: fluentd
containers:
- name: fluentd
image: fluent/fluentd-kubernetes-daemonset:v1.7.3-debian-elasticsearch7-1.0
env:
- name: FLUENT_ELASTICSEARCH_HOST
value: "elasticsearch.logging.svc.cluster.local"
- name: FLUENT_ELASTICSEARCH_PORT
value: "9200"
- name: FLUENT_ELASTICSEARCH_SCHEME
value: "http"
- name: FLUENT_ELASTICSEARCH_USER
value: "elastic"
- name: FLUENT_ELASTICSEARCH_PASSWORD
valueFrom:
secretKeyRef:
name: efk-pw-elastic
key: password
- name: FLUENT_ELASTICSEARCH_SED_DISABLE
value: "true"
resources:
limits:
memory: 512Mi
requests:
cpu: 100m
memory: 200Mi
volumeMounts:
- name: varlog
mountPath: /var/log
- name: varlibdockercontainers
mountPath: /var/lib/docker/containers
readOnly: true
- name: fluentconfig
mountPath: /fluentd/etc/fluent.conf
subPath: fluent.conf
terminationGracePeriodSeconds: 30
volumes:
- name: varlog
hostPath:
path: /var/log
- name: varlibdockercontainers
hostPath:
path: /var/lib/docker/containers
- name: fluentconfig
configMap:
name: fluentdconf
Pour mettre ça ensemble :
kubectl apply -f fluentd-SA.yaml
-f fluentd-configmap.yaml
-f fluentd-daemonset.yaml
Application de conteneur side-car pour la journalisation
L’autre approche consiste à utiliser un conteneur side-car dédié avec un agent de journalisation. La mise en œuvre la plus courante du conteneur side-car consiste à utiliser Courant en tant que collecteur de journaux. Dans le déploiement d’entreprise (où vous ne vous soucierez pas d’une petite surcharge de ressources de calcul), un conteneur side-car utilisant fluentd
(ou similaire) offre une flexibilité par rapport à la journalisation au niveau du cluster. En effet, vous pouvez régler et configurer l’agent collecteur en fonction du type de journaux, de la fréquence et d’autres réglages possibles que vous devez capturer.
La figure ci-dessous montre un conteneur side-car en tant qu’agent de journalisation.
Par exemple, un pod exécute un seul conteneur et le conteneur écrit dans deux fichiers journaux différents en utilisant deux formats différents. Voici un fichier de configuration pour le pod :
#log-sidecar.yaml
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
image: busybox
args: [/bin/sh, -c, 'tail -n+1 -f /var/log/1.log']
volumeMounts:
- name: varlog
mountPath: /var/log
volumes:
- name: varlog
emptyDir: {}
Pour mettre tout cela ensemble, vous pouvez exécuter ce pod :
$ kubectl apply -f log-sidecar.yaml
Pour vérifier si le conteneur side-car fonctionne comme un agent de journalisation, vous pouvez effectuer :
$ kubectl logs counter count-log
Le résultat attendu devrait ressembler à ceci :
$ kubectl logs counter count-log-1Thu 04 Nov 2021 09:23:21 NZDT
Thu 04 Nov 2021 09:23:22 NZDT
Thu 04 Nov 2021 09:23:23 NZDT
Thu 04 Nov 2021 09:23:24 NZDT
Exposition des journaux d’application directement au backend de journalisation
La troisième approche, qui (à mon avis) est la solution de journalisation la plus flexible pour les journaux de conteneurs et d’applications Kubernetes, consiste à envoyer les journaux directement vers la solution principale de journalisation. Bien que ce modèle ne repose pas sur la capacité native de Kubernetes, il offre la flexibilité dont la plupart des entreprises ont besoin, comme :
- Étendez une plus grande variété de prise en charge des protocoles réseau et des formats de sortie.
- Permet la capacité d’équilibrage de charge et améliore les performances.
- Configurable pour accepter des exigences de journalisation complexes via l’agrégation en amont
Étant donné que cette troisième approche repose sur une fonctionnalité non Kubernetes en poussant les journaux directement à partir de chaque application, elle est en dehors de la portée de Kubernetes.
Conclusion
La fonction de journalisation Kubernetes est un composant très important pour un déploiement d’entreprise d’un cluster Kubernetes. J’ai discuté de trois modèles possibles qui sont disponibles pour une utilisation. Vous devez trouver un modèle adapté à vos besoins.
Comme indiqué, la journalisation au niveau du nœud utilisant daemonset
est le modèle de déploiement le plus simple à utiliser, mais il présente également certaines limitations qui peuvent ne pas répondre aux besoins de votre organisation. D’autre part, le modèle side-car offre une flexibilité et une personnalisation qui vous permettent de personnaliser le type de journaux à capturer, ce qui vous donne une surcharge de ressources de calcul. Enfin, l’exposition des journaux d’application directement à la fonction de journal principal est une autre approche attrayante qui permet une personnalisation plus poussée.
Le choix t’appartient. Il vous suffit de trouver l’approche qui correspond aux besoins de votre organisation.