Aller au contenu
Conteneurs & Orchestration medium

Popeye : scanner de santé pour clusters Kubernetes

15 min de lecture

logo popeye

Popeye scanne votre cluster Kubernetes en temps réel et génère un rapport de santé avec un score de 0 à 100. L’outil détecte les mauvaises configurations courantes : images taguées latest, absence de limites CPU/mémoire, pods sans probes, conteneurs root, secrets inutilisés. En 30 secondes, vous savez ce qui doit être corrigé.

Ce guide vous montre comment :

  • Installer Popeye via mise, Homebrew ou binaire
  • Lancer un scan et interpréter les résultats
  • Filtrer l’analyse par namespace ou type de ressource
  • Personnaliser les règles avec spinach.yaml
  • Intégrer dans une CI/CD avec seuil de score minimal

Kubernetes accepte de déployer des manifestes même s’ils violent les bonnes pratiques. Un Deployment sans limites de ressources ? Accepté. Une image nginx:latest ? Déployée. Un pod qui tourne en root ? Aucune erreur.

Ces configurations fonctionnent… jusqu’au jour où :

  • Un pod consomme toute la mémoire du node et fait crasher les autres
  • Une mise à jour automatique de latest casse l’application
  • Une vulnérabilité exploite les privilèges root du conteneur

Popeye détecte ces problèmes avant qu’ils ne surviennent en analysant ce qui tourne réellement dans le cluster (pas les fichiers YAML sur disque).

Ce que Popeye vérifieExemple de problème détecté
ImagesTag latest, image sans tag
RessourcesPas de requests/limits CPU/mémoire
ProbesPas de liveness/readiness probe
SécuritéContainer root, pas de NetworkPolicy
RBACClusterRoles/Roles inutilisés
Ressources orphelinesConfigMaps, Secrets non référencés
Fenêtre de terminal
mise install popeye@latest
mise use popeye@latest
Fenêtre de terminal
brew install derailed/popeye/popeye
Fenêtre de terminal
# Télécharger depuis GitHub
curl -LO https://github.com/derailed/popeye/releases/download/v0.22.1/popeye_linux_amd64.tar.gz
tar -xzf popeye_linux_amd64.tar.gz
sudo mv popeye /usr/local/bin/

Vérification :

Fenêtre de terminal
popeye version
Version: 0.22.1
Commit: 35b554961dcdabfa7aba6bd070673c6c24c70884
Date: 2025-01-28T15:31:22Z

Popeye utilise votre kubeconfig actif (comme kubectl). Lancez un scan complet :

Fenêtre de terminal
popeye

Résultat sur un cluster Kind fraîchement créé :

GENERAL [KIND-POPEYE-TEST]
┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅
· Connectivity.............................✅
· MetricServer.............................💥
CLUSTER (1 SCANNED) 💥 0 😱 0 🔊 0 ✅ 1 100٪
┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅
· Version..................................✅
✅ [POP-406] K8s version OK.
DEPLOYMENTS (2 SCANNED) 💥 0 😱 1 🔊 1 ✅ 0 50٪
┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅
· demo/nginx-bad...........................😱
🐳 nginx
😱 [POP-101] Image tagged "latest" in use.
😱 [POP-106] No resources requests/limits defined.
· demo/nginx-good..........................🔊
🐳 nginx
🔊 [POP-108] Unnamed port 8080.
SUMMARY
┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅┅
Your cluster score: A (91)
IcôneNiveauSignificationAction
OKRessource conformeRien à faire
🔊InfoRecommandationAmélioration optionnelle
😱WarnProblème potentielÀ corriger
💥ErrorProblème critiqueAction immédiate requise
CodeMessageExplicationSolution
POP-101Image tagged “latest”L’image peut changer sans préavisSpécifier une version : nginx:1.27.0
POP-102No probes definedKubernetes ne sait pas si l’app est saineAjouter liveness/readiness probes
POP-106No resources requests/limitsLe pod peut consommer toutes les ressourcesDéfinir requests et limits
POP-107No resource limitsLimits absentes (requests présentes)Ajouter limits CPU/memory
POP-300Uses “default” ServiceAccountRisque de permissions excessivesCréer un ServiceAccount dédié
POP-302Pod running as rootRisque de sécuritéAjouter runAsNonRoot: true
POP-400Unable to locate referenceConfigMap/Secret inutiliséSupprimer ou utiliser la ressource
POP-1204Not secured by NetworkPolicyTrafic non filtréAjouter une NetworkPolicy

Le score (0-100) est calculé par type de ressource, puis agrégé. Chaque problème réduit le score selon sa sévérité :

  • Error : forte pénalité
  • Warn : pénalité moyenne
  • Info : faible impact

Un cluster de production devrait viser 80+ (note B minimum).

ScoreNoteInterprétation
90-100AExcellent, peu de corrections
80-89BBon, quelques améliorations
70-79CAcceptable, corrections recommandées
60-69DInsuffisant, action requise
0-59FCritique, problèmes majeurs
Fenêtre de terminal
# Un seul namespace
popeye -n demo
# Tous les namespaces
popeye -A

Utilisez l’option -s (sections) avec les alias de ressources :

Fenêtre de terminal
# Pods et Deployments uniquement
popeye -n demo -s po,deploy
RessourceAlias
Podpo
Deploymentdp, deploy
Servicesvc
ConfigMapcm
Secretsec
ServiceAccountsa
Ingressing
StatefulSetsts
DaemonSetds
Jobjob
CronJobcj
PersistentVolumeClaimpvc
NetworkPolicynp
HorizontalPodAutoscalerhpa

Afficher uniquement les problèmes warn et plus :

Fenêtre de terminal
popeye -l warn

Valeurs possibles : ok, info, warn, error

Fenêtre de terminal
popeye
Fenêtre de terminal
popeye -o json > rapport.json
Fenêtre de terminal
POPEYE_REPORT_DIR=\$(pwd) popeye --save --out html --output-file rapport.html
Fenêtre de terminal
popeye -o score
# Retourne uniquement le chiffre, ex: 91
  • yaml : rapport YAML
  • junit : format JUnit pour intégration CI
  • jurassic : texte sans couleurs ni icônes
  • prometheus : métriques Prometheus

Créez un fichier spinach.yaml pour adapter les règles à votre contexte :

spinach.yaml
# Configuration Popeye
popeye:
# Seuils d'utilisation des ressources
allocations:
cpu:
underPercUtilization: 200 # Alerte si CPU sous-utilisé > 200%
overPercUtilization: 50 # Alerte si CPU sur-utilisé > 50%
memory:
underPercUtilization: 200
overPercUtilization: 50
# Exclusions
excludes:
# Exclusions globales (tous les linters)
global:
fqns: [rx:^kube-] # Ignorer kube-system, kube-public...
codes: ["300"] # Ignorer le code POP-300
# Exclusions par linter
linters:
pods:
instances:
- fqns: [kube-system/coredns]
codes: ["302"] # Ignorer "running as root" pour CoreDNS
namespaces:
codes: ["100"] # Ignorer namespace inactif
# Seuils pour les pods
resources:
pod:
restarts: 5 # Alerte si > 5 restarts
limits:
cpu: 80
memory: 75
# Registries autorisés (tout autre registre = erreur)
registries:
- docker.io
- ghcr.io
- quay.io
- registry.k8s.io
# Modifier la sévérité d'un code
overrides:
- code: "206" # PodDisruptionBudget manquant
severity: 1 # Réduire à Info (1=info, 2=warn, 3=error)

Lancez Popeye avec ce fichier :

Fenêtre de terminal
popeye -f spinach.yaml
.github/workflows/popeye.yaml
name: Kubernetes Lint
on:
push:
branches: [main]
schedule:
- cron: '0 6 * * *' # Tous les jours à 6h
jobs:
popeye:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup kubeconfig
run: |
mkdir -p ~/.kube
echo "\${{ secrets.KUBECONFIG }}" | base64 -d > ~/.kube/config
- name: Install Popeye
run: |
curl -LO https://github.com/derailed/popeye/releases/download/v0.22.1/popeye_linux_amd64.tar.gz
tar -xzf popeye_linux_amd64.tar.gz
sudo mv popeye /usr/local/bin/
- name: Run Popeye
run: |
popeye -A --min-score 80 -o json > popeye-report.json
- name: Upload Report
uses: actions/upload-artifact@v4
with:
name: popeye-report
path: popeye-report.json

L’option --min-score 80 fait échouer le job si le score est inférieur à 80.

.gitlab-ci.yml
popeye:
stage: validate
image: quay.io/derailed/popeye:v0.22.1
script:
- popeye -A --min-score 75 --force-exit-zero -o yaml
rules:
- if: \$CI_PIPELINE_SOURCE == "schedule"

Popeye peut tourner directement dans Kubernetes via un CronJob :

popeye-cronjob.yaml
apiVersion: v1
kind: Namespace
metadata:
name: popeye
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: popeye
namespace: popeye
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: popeye
rules:
- apiGroups: [""]
resources: [configmaps, endpoints, namespaces, nodes, persistentvolumes,
persistentvolumeclaims, pods, secrets, serviceaccounts, services]
verbs: [get, list]
- apiGroups: [apps]
resources: [daemonsets, deployments, statefulsets, replicasets]
verbs: [get, list]
- apiGroups: [networking.k8s.io]
resources: [ingresses, networkpolicies]
verbs: [get, list]
- apiGroups: [autoscaling]
resources: [horizontalpodautoscalers]
verbs: [get, list]
- apiGroups: [policy]
resources: [poddisruptionbudgets]
verbs: [get, list]
- apiGroups: [rbac.authorization.k8s.io]
resources: [clusterroles, clusterrolebindings, roles, rolebindings]
verbs: [get, list]
- apiGroups: [metrics.k8s.io]
resources: [pods, nodes]
verbs: [get, list]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: popeye
subjects:
- kind: ServiceAccount
name: popeye
namespace: popeye
roleRef:
kind: ClusterRole
name: popeye
apiGroup: rbac.authorization.k8s.io
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: popeye
namespace: popeye
spec:
schedule: "0 */6 * * *" # Toutes les 6 heures
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
spec:
serviceAccountName: popeye
restartPolicy: Never
containers:
- name: popeye
image: quay.io/derailed/popeye:v0.22.1
args:
- -A
- -o
- yaml
- --force-exit-zero
resources:
limits:
cpu: 500m
memory: 256Mi
Fenêtre de terminal
kubectl apply -f popeye-cronjob.yaml

Planifiez un scan quotidien ou après chaque déploiement majeur. Les problèmes s’accumulent vite.

Sur un grand cluster, analysez d’abord un namespace critique :

Fenêtre de terminal
popeye -n production -l warn

Si vous excluez des règles dans spinach.yaml, documentez pourquoi :

excludes:
linters:
pods:
instances:
# CoreDNS tourne en root par design (upstream)
# Voir: https://github.com/coredns/coredns/issues/...
- fqns: [kube-system/coredns]
codes: ["302"]

Exportez les rapports JSON et suivez l’évolution du score. Un score qui baisse indique une dette technique croissante.

ProblèmeCause probableSolution
MetricServer 💥metrics-server non installéInstaller metrics-server ou ignorer
Timeout sur grand clusterTrop de ressources à scannerFiltrer par namespace -n
Permissions insuffisantesRBAC manquantVérifier les droits get/list
Score très bas sur kube-systemComposants système non optimisésExclure via spinach.yaml
  • Popeye analyse le cluster en temps réel (pas les fichiers YAML)
  • Le score de 0 à 100 donne une vue d’ensemble rapide
  • Les codes POP-xxx identifient précisément chaque problème
  • spinach.yaml permet d’adapter les règles à votre contexte
  • Intégrez dans la CI/CD avec --min-score pour bloquer les régressions
  • Popeye est en lecture seule : il ne modifie jamais vos ressources

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.