
👀 Un sanitizador de recursos de clúster Kubernetes
Popeye es una utilidad que escanea clústeres Kubernetes en ejecución e informa posibles problemas con los recursos y configuraciones desplegados. A medida que el panorama de Kubernetes crece, se vuelve un desafío para un humano hacer seguimiento de la multitud de manifiestos y políticas que orquestan un clúster. Popeye escanea tu clúster basándose en lo que está desplegado, no en lo que está en el disco. Al hacer linting de tu clúster, detecta configuraciones incorrectas, recursos obsoletos y te ayuda a asegurar que se sigan las mejores prácticas, previniendo así futuros dolores de cabeza. Su objetivo es reducir la sobrecarga cognitiva que uno enfrenta al operar un clúster Kubernetes en producción. Además, si tu clúster utiliza un servidor de métricas, informa sobre posibles sobre/subasignaciones de recursos e intenta advertirte si tu clúster se queda sin capacidad.
¡Popeye es una herramienta de solo lectura, no altera ninguno de tus recursos de Kubernetes de ninguna manera!
Puedes volcar el informe de escaneo a HTML.
Popeye publica métricas de Prometheus. Proveemos un dashboard de muestra de Popeye para que comiences en este repositorio.
Popeye está disponible en plataformas Linux, OSX y Windows.
Los binarios para Linux, Windows y Mac están disponibles como tarballs en la página de lanzamientos.
Para OSX/Unix usando Homebrew/LinuxBrew ```shell brew install derailed/popeye/popeye
Usando go install
go install github.com/derailed/popeye@latest
Compilando desde el código fuente Popeye fue compilado usando go 1.21+. Para compilar Popeye desde el código fuente debes:
Clonar el repositorio
Añadir el siguiente comando en tu archivo go.mod
replace (
github.com/derailed/popeye => MY_POPEYE_CLONED_GIT_REPO
)
Compilar y ejecutar el ejecutable
go run main.go
Receta rápida para los impacientes: ```shell
git clone https://github.com/derailed/popeye cd popeye
make build
popeye
Popeye usa el modo terminal de 256 colores. En sistemas `Nix, asegúrate de que TERM esté configurado correctamente.
export TERM=xterm-256color
Puedes usar Popeye a pleno rendimiento o utilizando una configuración yaml de spinach para ajustar tus linters. Los detalles sobre el archivo de configuración de Popeye se encuentran a continuación.```shell
popeye version
popeye
fred namespacepopeye -n fred
popeye -A
popeye -f spinach.yaml
popeye --context olive
popeye -n ns1 -s pod,svc --logs none
popeye -n ns1 --logs /tmp/fred.log -v4
popeye help
---
## Linters
Popeye escanea tu clúster en busca de mejores prácticas y posibles problemas.
Actualmente, Popeye solo examina un conjunto determinado de recursos de Kubernetes.
¡Pronto vendrán más!
Esperamos que los amigos de Kubernetes contribuyan para mejorar aún más a Popeye.
El objetivo de los linters es detectar configuraciones incorrectas, como
desajustes de puertos, recursos muertos o no utilizados, utilización de métricas,
sondas, imágenes de contenedores, reglas RBAC, recursos desnudos, etc.
Popeye no es otra herramienta de análisis estático. Se ejecuta e inspecciona los recursos de Kubernetes en
clústeres en vivo y lint los recursos tal como están en producción.
Aquí hay una lista de algunos de los linters disponibles:
| | Resource | Linters | Aliases |
|----|-------------------------|-------------------------------------------------------------------------|------------|
| 🛀 | Node | | no |
| | | Condiciones, p. ej., no listo, sin memoria/disco, red, pids, etc. | |
| | | Tolerancias de pods que hacen referencia a taints de nodos | |
| | | Métricas de uso de CPU/MEM, se activa si supera los límites (predet. 80% CPU/MEM) | |
| 🛀 | Namespace | | ns |
| | | Inactivo | |
| | | Namespaces muertos | |
| 🛀 | Pod | | po |
| | | Estado del pod | |
| | | Estados de los contenedores | |
| | | Presencia de ServiceAccount | |
| | | CPU/MEM en contenedores por encima de un límite configurado (predet. 80% CPU/MEM) | |
| | | Imagen de contenedor sin etiquetas | |
| | | Imagen de contenedor usando la etiqueta `latest` | |
| | | Presencia de solicitudes/límites de recursos | |
| | | Presencia de sondas de vida/disponibilidad | |
| | | Puertos nombrados y sus referencias | |
| 🛀 | Service | | svc |
| | | Presencia de endpoints | |
| | | Etiquetas de pods coincidentes | |
| | | Puertos nombrados y sus referencias | |
| 🛀 | ServiceAccount | | sa |
| | | No utilizado, detecta SA potencialmente no utilizadas | |
| 🛀 | Secrets | | sec |
| | | No utilizado, detecta secretos o claves asociadas potencialmente no utilizadas | |
| 🛀 | ConfigMap | | cm |
| | | No utilizado, detecta cm o claves asociadas potencialmente no utilizados | |
| 🛀 | Deployment | | dp, deploy |
| | | No utilizado, validación de plantilla de pod, utilización de recursos | |
| 🛀 | StatefulSet | | sts |
| | | No utilizado, validación de plantilla de pod, utilización de recursos | |
| 🛀 | DaemonSet | | ds |
| | | No utilizado, validación de plantilla de pod, utilización de recursos | |
| 🛀 | PersistentVolume | | pv |
| | | No utilizado, verificar volumen vinculado o error de volumen | |
| 🛀 | PersistentVolumeClaim | | pvc |
| | | No utilizado, verificar vinculación o error de montaje de volumen | |
| 🛀 | HorizontalPodAutoscaler | | hpa |
| | | No utilizado, utilización, comprobaciones de ráfaga máxima | |
| 🛀 | PodDisruptionBudget | | |
| | | No utilizado, verificar configuración de minAvailable | pdb |
| 🛀 | ClusterRole | | |
| | | No utilizado | cr |
| 🛀 | ClusterRoleBinding | | |
| | | No utilizado | crb |
| 🛀 | Role | | |
| | | No utilizado | ro |
| 🛀 | RoleBinding | | |
| | | No utilizado | rb |
| 🛀 | Ingress | | |
| | | Válido | ing |
| 🛀 | NetworkPolicy | | |
| | | Válido, Obsoleto, Protegido | np |
| 🛀 | PodSecurityPolicy | | |
| | | Válido | psp |
| 🛀 | Cronjob | | |
| | | Válido, Suspendido, Ejecuciones | cj |
| 🛀 | Job | | |
| | | Verificaciones de pod | job |
| 🛀 | GatewayClass | | |
| | | Válido, No utilizado | gwc |
| 🛀 | Gateway | | |
| | | Válido, No utilizado | gw |
| 🛀 | HTTPRoute | | |
| | | Válido, No utilizado | gwr |
También puedes consultar la [lista completa de códigos](https://github.com/derailed/popeye/blob/HEAD/docs/codes.md).
---
## Guardado de Escaneos
Para guardar el informe de Popeye en un archivo, pasa el flag `--save` al comando.
Por defecto, se creará un directorio temporal y se almacenará el informe allí.
La ruta del directorio temporal se imprimirá en STDOUT.
Si necesitas especificar el directorio de salida para el informe,
puedes usar la variable de entorno `POPEYE_REPORT_DIR`. La ruta final será `<POPEYE_REPORT_DIR>/<cluster>/<context>`.
Por defecto, el nombre del archivo de salida sigue el siguiente formato: `lint_<cluster-name>_<time-UnixNano>.<output-extension>` (por ejemplo: "lint-mycluster-1594019782530851873.html").
Si también deseas especificar el nombre del archivo de salida para el informe, puedes pasar el flag `--output-file` con el nombre de archivo que desees como parámetro.
Ejemplo para guardar el informe en el directorio de trabajo:```shell
POPEYE_REPORT_DIR=$(pwd) popeye --save
Ejemplo para guardar el informe en el directorio de trabajo en formato HTML con el nombre "report.html" :```shell POPEYE_REPORT_DIR=$(pwd) popeye --save --out html --output-file report.html
### Guardar en Almacén de Objetos S3
Alternativamente, puede enviar los informes generados a un almacén de objetos AWS S3 o Minio proporcionando el indicador `--s3-bucket`.
Para los parámetros, debe proporcionar el nombre del bucket S3 donde desea almacenar el informe.
Para guardar el informe en un subdirectorio del bucket, proporcione el parámetro del bucket como `bucket/path/to/report`.
Ejemplo para guardar informe en S3:```shell
# AWS S3
# NOTE: You must provide env vars for AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
# This will create bucket my-popeye if not present and upload a popeye json report to /fred/scan.json
popeye --s3-bucket s3://my-popeye/fred --s3-region us-west-2 --out json --save --output-file scan.json
# Minio Object Store
# NOTE: You must provide env vars for AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY and a minio server URI
# This will create bucket my-popeye if not present and upload a popeye json report to /fred/scan.json
popeye --s3-bucket minio://my-popeye/fred --s3-region us-east --s3-endpoint localhost:9000 --out json --save --output-file scan.json
También puedes ejecutar Popeye en un contenedor ejecutándolo directamente desde el repositorio oficial de Docker en Quay.
El comando predeterminado al ejecutar el contenedor Docker es popeye, por lo que puedes personalizar el escaneo usando las banderas de CLI compatibles.
Para acceder a tus clústeres, mapea tu directorio local de kubeconfig dentro del contenedor con -v :```shell
docker run --rm -it -v $HOME/.kube:/root/.kube quay.io/derailed/popeye --context foo -n bar
Al ejecutar el comando docker anterior con `--rm`, significa que el contenedor se elimina cuando Popeye finaliza. Cuando usas `--save`, lo escribe en /tmp dentro del contenedor y luego elimina el contenedor cuando Popeye finaliza, lo que significa que pierdes la salida ;( Para solucionar esto, mapea /tmp al /tmp del contenedor.
> NOTA: Puedes anular la ubicación predeterminada del directorio de salida estableciendo la variable de entorno `POPEYE_REPORT_DIR`.```shell
docker run --rm -it \
-v $HOME/.kube:/root/.kube \
-e POPEYE_REPORT_DIR=/tmp/popeye \
-v /tmp:/tmp \
quay.io/derailed/popeye --context foo -n bar --save --output-file my_report.txt
# Docker has exited, and the container has been deleted, but the file
# is in your /tmp directory because you mapped it into the container
cat /tmp/popeye/my_report.txt
<snip>
Popeye puede generar informes de linter en una variedad de formatos. Puede usar la opción -o de la CLI y elegir su veneno allí.
Popeye puede publicar métricas de Prometheus directamente desde un escaneo. Necesitará tener acceso a un pushgateway de Prometheus y credenciales.
¡NOTA! Estos están sujetos a cambios según los comentarios y uso de los usuarios!!
Para publicar métricas, deben estar presentes argumentos adicionales de la CLI.```shell
popeye --push-gtwy-url http://localhost:9091
popeye -o html --save --push-gtwy-url http://localhost:9091
### Métricas de PopProm
Las siguientes métricas de prometheus de Popeye se publican:
* `popeye_severity_total` [gauge] rastrea varios conteos basados en severidad.
* `popeye_code_total` [gauge] rastrea conteos por códigos de linter de Popeye.
* `popeye_linter_tally_total` [gauge] rastrea conteos por linters.
* `popeye_report_errors_total` [gauge] rastrea totales de errores de escaneo.
* `popeye_cluster_score` [gauge] rastrea puntuaciones de informes de escaneo.
### PopGraf
En este repositorio se puede encontrar un panel de [Grafana](https://grafana.com) de ejemplo para empezar.
> ¡NOTA! Trabajo en progreso, siéntase libre de contribuir si tiene experiencia en UX/grafana/promql.
---
## SpinachYAML
Se puede especificar un archivo de configuración YAML de spinach mediante la opción `-f` para configurar aún más los linters. Este archivo puede especificar
el umbral de utilización del contenedor y configuraciones específicas del linter, así como recursos y códigos que serán excluidos del linter.
> ¡NOTA! Este archivo cambiará a medida que Popeye madure.
Bajo la clave `excludes` puede configurar para omitir ciertos recursos o códigos de linter.
Los linters de Popeye reciben su nombre de los nombres de recursos de k8s.
Por ejemplo, el linter PodDisruptionBudget se llama `poddisruptionbudgets` y escanea `policy/v1/poddisruptionbudgets`.
> ¡NOTA! El linter usa la forma plural del `tipo` de recurso y todo está escrito en minúsculas.
En el archivo spinach se usa un nombre de recurso completamente calificado, también conocido como `FQN`, para identificar un nombre de recurso, es decir, `namespace/nombre_recurso`.
Por ejemplo, el FQN de un pod llamado `fred-1234` en el namespace `blee` será `blee/fred-1234`. Esto permite diferenciar `fred/p1` y `blee/p1`.
Para recursos de ámbito de clúster, el FQN es equivalente al nombre.
Las reglas de exclusión pueden ser una coincidencia de cadena directa o una expresión regular. En este último caso, la expresión regular debe especificarse mediante el prefijo `rx:`.
> ¡NOTA! Tenga cuidado con su expresión regular, ya que más recursos de los esperados podrían ser excluidos del informe con una regla de expresión regular *flexible*.
> Cuando los recursos de su clúster cambien, esto podría dar lugar a escaneos subóptimos.
> Por lo tanto, recomendamos ejecutar Popeye `a pleno rendimiento` de vez en cuando para asegurarse de detectar cualquier nuevo problema que pueda haber surgido en sus clústeres…
Aquí hay un archivo spinach de ejemplo tal como está en esta versión.
Hay un archivo spinach más completo basado en eks y aks en este repositorio, en la carpeta `spinach`.
(Por cierto: para los recién llegados al proyecto, podría ser una excelente manera de contribuir añadiendo PRs de archivos spinach específicos para clústeres...)```yaml
# spinach.yaml
# A Popeye sample configuration file
popeye:
# Checks resources against reported metrics usage.
# If over/under these thresholds a linter warning will be issued.
# Your cluster must run a metrics-server for these to take place!
allocations:
cpu:
underPercUtilization: 200 # Checks if cpu is under allocated by more than 200% at current load.
overPercUtilization: 50 # Checks if cpu is over allocated by more than 50% at current load.
memory:
underPercUtilization: 200 # Checks if mem is under allocated by more than 200% at current load.
overPercUtilization: 50 # Checks if mem is over allocated by more than 50% usage at current load.
# Excludes excludes certain resources from Popeye scans
excludes:
# [NEW!] Global exclude resources and codes globally of any linters.
global:
fqns: [rx:^kube-] # => excludes all resources in kube-system, kube-public, etc..
# [NEW!] Exclude resources for all linters matching these labels
labels:
app: [bozo, bono] #=> exclude any resources with labels matching either app=bozo or app=bono
# [NEW!] Exclude resources for all linters matching these annotations
annotations:
fred: [blee, duh] # => exclude any resources with annotations matching either fred=blee or fred=duh
# [NEW!] Exclude scan codes globally via straight codes or regex!
codes: ["300", "206", "rx:^41"] # => exclude issue codes 300, 206, 410, 415 (Note: regex match!)
# [NEW!] Configure individual resource linters
linters:
# Configure the namespaces linter for v1/namespaces
namespaces:
# [NEW!] Exclude these codes for all namespace resources straight up or via regex.
codes: ["100", "rx:^22"] # => exclude codes 100, 220, 225, ...
# [NEW!] Excludes specific namespaces from the scan
instances:
- fqns: [kube-public, kube-system] # => skip ns kube-pulbic and kube-system
- fqns: [blee-ns]
codes: [106] # => skip code 106 for namespace blee-ns
# Skip secrets in namespace bozo.
secrets:
instances:
- fqns: [rx:^bozo]
# Configure the pods linter for v1/pods.
pods:
instances:
# [NEW!] exclude all pods matching these labels.
- labels:
app: [fred,blee] # Exclude codes 102, 105 for any pods with labels app=fred or app=blee
codes: [102, 105]
resources:
# Configure node resources.
node:
# Limits set a cpu/mem threshold in % ie if cpu|mem > limit a lint warning is triggered.
limits:
# CPU checks if current CPU utilization on a node is greater than 90%.
cpu: 90
# Memory checks if current Memory utilization on a node is greater than 80%.
memory: 80
# Configure pod resources
pod:
# Restarts check the restarts count and triggers a lint warning if above threshold.
restarts: 3
# Check container resource utilization in percent.
# Issues a lint warning if about these threshold.
limits:
cpu: 80
memory: 75
# [New!] overrides code severity
overrides:
# Code specifies a custom severity level ie critical=3, warn=2, info=1
- code: 206
severity: 1
# Configure a list of allowed registries to pull images from.
# Any resources not using the following registries will be flagged!
registries:
- quay.io
- docker.io
Popeye está contenerizado y se puede ejecutar directamente en tus clústeres de Kubernetes como una tarea única o un CronJob. Aquí hay una configuración de ejemplo; modifícala según tus necesidades/deseos. Los manifiestos para esto están en el directorio k8s de este repositorio.```shell kubectl apply -f k8s/popeye
ENTRADA:```yaml
---
apiVersion: v1
kind: Namespace
metadata:
name: popeye
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: popeye
namespace: popeye
spec:
schedule: "* */1 * * *" # Fire off Popeye once an hour
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
spec:
serviceAccountName: popeye
restartPolicy: Never
containers:
- name: popeye
image: derailed/popeye:vX.Y.Z
imagePullPolicy: IfNotPresent
args:
- -o
- yaml
- --force-exit-zero
resources:
limits:
cpu: 500m
memory: 100Mi
The --force-exit-zero debería estar configurado. De lo contrario, los pods terminarán en estado de error.
¡NOTA! Popeye sale con un código de error distinto de cero si se detectan errores de lint.
Para que Popeye pueda hacer su trabajo, el usuario que haya iniciado sesión debe tener suficientes privilegios RBAC para obtener/listar los recursos mencionados anteriormente.
Reglas RBAC de muestra para Popeye (tenga en cuenta que están sujetas a cambios).
¡NOTA! Revise y ajuste según las políticas de su clúster.```yaml
apiVersion: v1 kind: ServiceAccount metadata: name: popeye namespace: popeye
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: popeye rules:
apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: popeye subjects:
---
## Morfología del informe
El informe de linting muestra cada grupo de recursos escaneados y sus posibles problemas.
El informe está codificado por colores/emojis en términos de niveles de severidad del linter:
| Nivel | Icono | Jurásico | Color | Descripción |
|-------|------|----------|-----------|-----------------|
| Ok | ✅ | OK | Verde | ¡Feliz! |
| Info | 🔊 | I | VerdeAzul | Para tu información |
| Warn | 😱 | W | Amarillo | Posible problema |
| Error | 💥 | E | Rojo | Se requiere acción |
La sección de encabezado para cada recurso de Kubernetes escaneado proporciona un recuento resumido
para cada una de las categorías anteriores.
La sección de Resumen proporciona una **Puntuación Popeye** basada en el pase del linter en el clúster dado.
---
## Problemas conocidos
Esta versión inicial es frágil. Popeye probablemente explotará cuando…
* Estés ejecutando versiones antiguas de Kubernetes. Popeye funciona mejor con Kubernetes 1.25.X.
* No tengas suficiente potencia RBAC para administrar tu clúster (consulta la sección RBAC)
---
## Descargo de responsabilidad
¡Esto es trabajo en progreso! Si hay suficiente interés en la comunidad de Kubernetes,
mejoraremos según tus recomendaciones/contribuciones.
También si te gusta este esfuerzo, ¡háznoslo saber!
---
## ¡Bien por las chicas/los chicos!
Popeye se basa en muchos proyectos y bibliotecas de código abierto. Nuestro *sincero*
agradecimiento a todos los colaboradores de OSS que trabajan noches y fines de semana
para hacer realidad este proyecto.
### Información de contacto
1. **Correo electrónico**: [email protected]
2. **Twitter**: [@kitesurfer](https://twitter.com/kitesurfer?lang=en)
---
<img src="https://raw.githubusercontent.com/derailed/popeye/master/assets/imhotep_logo.png" width="32" height="auto"/> © 2025 Imhotep Software LLC.
Todos los materiales están bajo licencia [Apache v2.0](http://www.apache.org/licenses/LICENSE-2.0)
| Formato | Descripción | Predeterminado | Créditos |
|---|
| standard | La salida completa iconizada y coloreada | sí | |
| jurassic | Sin íconos ni color como en 1979 | ||
| yaml | Como YAML | ||
| html | Como HTML | ||
| json | Como JSON | ||
| junit | Para los melancólicos de Java | ||
| prometheus | Vuelca el informe como métricas de Prometheus | dardanel | |
| score | Devuelve un único valor de puntuación del linter del clúster (0-100) | kabute |