xpeditis2.0/infra/prod/k8s/monitoring/02-promtail.yaml
2026-09-07 21:40:50 +02:00

186 lines
5.6 KiB
YAML

# =============================================================================
# Promtail -- collecte des journaux de conteneurs
# =============================================================================
# k3s utilise containerd, pas Docker : la decouverte se fait via l'API
# Kubernetes et la lecture de /var/log/pods, et non via le socket Docker comme
# en preprod.
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: promtail
namespace: monitoring
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: promtail
rules:
# Lecture seule, strictement ce qu'exige la decouverte de pods.
- apiGroups: [""]
resources: [nodes, nodes/proxy, services, endpoints, pods]
verbs: [get, list, watch]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: promtail
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: promtail
subjects:
- kind: ServiceAccount
name: promtail
namespace: monitoring
---
apiVersion: v1
kind: ConfigMap
metadata:
name: promtail-config
namespace: monitoring
data:
promtail.yaml: |
server:
http_listen_port: 9080
log_level: warn
positions:
filename: /run/promtail/positions.yaml
clients:
- url: http://loki:3100/loki/api/v1/push
batchwait: 1s
batchsize: 1048576
timeout: 10s
scrape_configs:
- job_name: kubernetes-pods
kubernetes_sd_configs:
- role: pod
pipeline_stages:
# Format CRI de containerd : "<ts> <stream> <flags> <message>".
- cri: {}
- drop:
older_than: 15m
drop_counter_reason: entry_too_old
# Les sondes de sante representent l'essentiel du volume et n'ont
# aucune valeur d'analyse : on les jette avant ingestion.
- drop:
expression: '(GET /api/v1/health|GET /api/health|/ready|/metrics)'
drop_counter_reason: healthcheck
# Journaux pino du backend (LOG_FORMAT=json).
- json:
expressions:
level: level
msg: msg
context: context
reqId: reqId
- template:
source: level
template: >-
{{ if eq .Value "10" }}trace{{ else if eq .Value "20" }}debug{{ else if eq .Value "30" }}info{{ else if eq .Value "40" }}warn{{ else if eq .Value "50" }}error{{ else if eq .Value "60" }}fatal{{ else }}{{ .Value }}{{ end }}
- labels:
level:
context:
relabel_configs:
- source_labels: [__meta_kubernetes_pod_node_name]
target_label: node
- source_labels: [__meta_kubernetes_namespace]
target_label: namespace
- source_labels: [__meta_kubernetes_pod_name]
target_label: pod
- source_labels: [__meta_kubernetes_pod_container_name]
target_label: container
- source_labels: [__meta_kubernetes_pod_label_app_kubernetes_io_name]
target_label: service
# Chemin reel des journaux sur l'hote.
- source_labels: [__meta_kubernetes_pod_uid, __meta_kubernetes_pod_container_name]
target_label: __path__
separator: /
replacement: /var/log/pods/*$1/*.log
# On ne collecte que les namespaces utiles : pas de bruit kube-system
# hormis l'ingress.
- source_labels: [__meta_kubernetes_namespace]
regex: (xpeditis-prod|monitoring|kube-system)
action: keep
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: promtail
namespace: monitoring
labels:
app.kubernetes.io/name: promtail
spec:
selector:
matchLabels:
app.kubernetes.io/name: promtail
template:
metadata:
labels:
app.kubernetes.io/name: promtail
spec:
serviceAccountName: promtail
securityContext:
# Les journaux de /var/log/pods appartiennent a root : Promtail doit
# pouvoir les lire. C'est la raison pour laquelle le namespace
# monitoring est en "baseline" et non "restricted".
runAsUser: 0
seccompProfile:
type: RuntimeDefault
containers:
- name: promtail
image: grafana/promtail:3.3.2
args: ["-config.file=/etc/promtail/promtail.yaml"]
env:
- name: HOSTNAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
ports:
- name: http
containerPort: 9080
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
cpu: 300m
memory: 256Mi
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
volumeMounts:
- name: config
mountPath: /etc/promtail
- name: positions
mountPath: /run/promtail
- name: pods
mountPath: /var/log/pods
readOnly: true
- name: containers
mountPath: /var/lib/rancher/k3s/agent/containerd
readOnly: true
volumes:
- name: config
configMap:
name: promtail-config
- name: positions
emptyDir: {}
- name: pods
hostPath:
path: /var/log/pods
- name: containers
hostPath:
path: /var/lib/rancher/k3s/agent/containerd
tolerations:
- effect: NoSchedule
operator: Exists