Integrar Kyverno CLI en Pipelines CI/CD con GitHub Actions para Validación de Políticas Kubernetes
Introducción
A medida que Kubernetes se convierte en el estándar de facto para orquestar cargas de trabajo en entornos empresariales, garantizar el cumplimiento de políticas de seguridad y configuración deja de ser una opción para convertirse en una necesidad operativa. En muchos equipos, la validación de los manifiestos se hace de forma manual o directamente en el clúster, cuando el daño ya está hecho: un recurso mal configurado ha llegado a producción, ha violado una política de seguridad o ha consumido recursos de forma descontrolada.
Kyverno es un motor de políticas nativo de Kubernetes que permite definir, aplicar y auditar reglas de configuración directamente en formato YAML, sin necesidad de aprender un lenguaje específico como Rego. Y lo más importante: su interfaz de línea de comandos, el Kyverno CLI, puede integrarse en cualquier pipeline CI/CD para interceptar esos problemas antes de que lleguen al clúster.
En este artículo veremos cómo integrar Kyverno CLI en un pipeline de GitHub Actions para validar automáticamente manifiestos Kubernetes en cada pull request o push. El resultado es una capa de cumplimiento automatizada que refuerza la seguridad y la calidad del código de infraestructura sin fricciones para el equipo de desarrollo.
¿Qué es Kyverno CLI?
Kyverno es una herramienta de gestión de políticas nativa de Kubernetes. A diferencia de Open Policy Agent (OPA), que utiliza Rego como lenguaje de políticas, Kyverno define sus reglas en YAML puro, lo que lo hace mucho más accesible para equipos que ya trabajan con Kubernetes a diario.
El proyecto cuenta con dos modalidades de uso principales:
- Kyverno como admission controller: se despliega como un webhook en el clúster y evalúa los recursos en tiempo de admisión, bloqueando o mutando los manifiestos antes de que sean persistidos.
- Kyverno CLI: una herramienta de línea de comandos que permite aplicar y testear políticas contra manifiestos YAML localmente o en pipelines CI/CD, sin necesidad de un clúster activo.
Esta segunda modalidad es la que nos interesa aquí. El Kyverno CLI permite ejecutar el mismo motor de evaluación de políticas que usarías en el clúster, pero en un contexto offline, lo que lo convierte en la herramienta perfecta para el shift-left en validación de seguridad Kubernetes.
Casos de uso del Kyverno CLI en CI/CD
- Validar que ningún manifiesto usa imágenes con el tag
latest - Verificar que todos los contenedores definen
requestsylimitsde CPU y memoria - Comprobar que los Deployments tienen configurado
readinessProbeylivenessProbe - Asegurarse de que no se desplieguen contenedores en modo privilegiado
- Validar labels obligatorios en todos los recursos (por ejemplo,
app,team,environment) - Rechazar el uso de
hostNetwork: trueohostPID: true
Beneficios de Integrar Kyverno CLI en un Pipeline CI/CD
1. Validación de políticas de forma automática y temprana
El principal beneficio es detectar violaciones de políticas en la fase más temprana posible del ciclo de desarrollo: en el mismo momento en que el desarrollador abre un pull request. Esto es lo que se conoce como shift-left security: mover los controles de seguridad lo más a la izquierda posible en el pipeline, cuando el coste de corrección es mínimo.
Si la violación se detecta en el clúster mediante el admission controller, ya hay contexto de ejecución involucrado, posiblemente un despliegue fallido, y hay que identificar el problema, comunicarlo al equipo y esperar a que lo corrijan. Si se detecta en el pipeline CI/CD, el desarrollador recibe feedback inmediato en su PR y puede corregirlo en segundos.
2. Consistencia entre entornos
Cuando el mismo conjunto de políticas se aplica tanto en el admission controller del clúster como en el pipeline CI/CD, se garantiza que lo que pasa en CI también pasa en producción. No hay sorpresas al desplegar: si el pipeline verde, el clúster también lo aceptará.
3. Separación de responsabilidades
Los equipos de plataforma o de seguridad pueden definir y mantener las políticas en Kyverno, mientras que los equipos de desarrollo las consumen de forma transparente a través del pipeline. Esto crea un modelo de gobernanza claro sin necesidad de bloquear el flujo de trabajo de los desarrolladores.
4. Sin dependencias de clúster en CI
A diferencia de otros enfoques que requieren un clúster de Kubernetes activo para validar (con herramientas como kubectl apply --dry-run=server), el Kyverno CLI opera completamente en local. Esto lo hace más rápido, más barato y más portable.
5. Desarrollo más ágil
Recibir feedback inmediato sobre violaciones de políticas acelera el ciclo de desarrollo. En lugar de descubrir problemas en la fase de despliegue o, peor aún, en producción, los desarrolladores pueden corregirlos mientras el código todavía está fresco en su mente.
Configuración de Kyverno CLI en GitHub Actions
Paso 1: Instalar el Kyverno CLI
Lo primero es añadir un step en el workflow de GitHub Actions que descargue e instale el binario del Kyverno CLI. El binario está disponible en las releases oficiales del repositorio GitHub de Kyverno.
El siguiente ejemplo muestra un workflow completo con la instalación incluida:
name: CI Pipeline con validación de políticas Kyverno
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
kyverno-policy-check:
runs-on: ubuntu-latest
steps:
- name: Checkout del código
uses: actions/checkout@v4
- name: Instalar Kyverno CLI
run: |
curl -LO https://github.com/kyverno/kyverno/releases/download/v1.13.0/kyverno-cli_v1.13.0_linux_x86_64.tar.gz
tar -xzf kyverno-cli_v1.13.0_linux_x86_64.tar.gz
sudo mv kyverno /usr/local/bin/
kyverno version
Nota sobre versiones: Sustituye
v1.13.0por la versión que necesites para tu proyecto. Se recomienda fijar una versión concreta en lugar de usarlatestpara garantizar reproducibilidad en el pipeline. Puedes consultar las versiones disponibles en la página de releases de Kyverno.
Instalación alternativa mediante Krew
Si el runner ya tiene Krew instalado (el gestor de plugins de kubectl), también puedes instalar el CLI así:
kubectl krew install kyverno
Sin embargo, en runners de GitHub Actions la instalación directa del binario es más rápida y no requiere dependencias adicionales.
Paso 2: Definir las políticas de validación
Las políticas de Kyverno son recursos YAML estándar de Kubernetes. Para el CI/CD, la práctica recomendada es almacenarlas en el propio repositorio, bajo un directorio dedicado. Una estructura habitual es la siguiente:
.
└── .github
└── policies
├── disallow-latest-tag.yaml
└── require-requests-limits.yaml
De esta forma, las políticas viajan junto al código y están sujetas al mismo proceso de revisión mediante pull requests.
Política 1: Prohibir el uso del tag latest
El uso de latest en imágenes de contenedor es una práctica desaconsejada porque elimina la reproducibilidad: dos despliegues con la misma definición pueden usar versiones distintas de la imagen. Esta política rechaza cualquier Deployment, DaemonSet, StatefulSet o Pod que utilice imágenes sin tag o con el tag latest:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-latest-tag
annotations:
policies.kyverno.io/title: Prohibir tag latest en imágenes
policies.kyverno.io/description: >-
El tag 'latest' hace que los despliegues no sean reproducibles.
Todos los contenedores deben usar un tag de versión específico.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: require-image-tag
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Las imágenes de contenedor deben especificar un tag distinto de 'latest'."
pattern:
spec:
containers:
- image: "!*:latest"
Política 2: Requerir requests y limits de recursos
Sin límites de recursos, un contenedor defectuoso o malicioso puede consumir todos los recursos del nodo y provocar una interrupción de servicio. Esta política garantiza que todos los contenedores definen explícitamente sus requests y limits:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: require-requests-limits
annotations:
policies.kyverno.io/title: Requerir requests y limits de recursos
policies.kyverno.io/description: >-
Todos los contenedores deben definir requests y limits de CPU y memoria
para garantizar una planificación predecible y evitar el agotamiento de recursos.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: validate-resources
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Los contenedores deben definir resources.requests y resources.limits."
pattern:
spec:
containers:
- resources:
requests:
memory: "?*"
cpu: "?*"
limits:
memory: "?*"
cpu: "?*"
Política 3: Prohibir contenedores privilegiados
Una política de seguridad crítica en cualquier entorno de producción es evitar que los contenedores se ejecuten en modo privilegiado, ya que esto les otorga acceso casi completo al host:
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: disallow-privileged-containers
annotations:
policies.kyverno.io/title: Prohibir contenedores privilegiados
policies.kyverno.io/description: >-
Los contenedores privilegiados tienen acceso completo al host.
Esta política prohibe el uso de securityContext.privileged: true.
spec:
validationFailureAction: Enforce
background: true
rules:
- name: no-privileged
match:
any:
- resources:
kinds:
- Pod
validate:
message: "Los contenedores no pueden ejecutarse en modo privilegiado."
pattern:
spec:
containers:
- =(securityContext):
=(privileged): "false"
Paso 3: Añadir el step de validación al workflow
Con las políticas definidas y almacenadas en el repositorio, el siguiente paso es añadir al workflow de GitHub Actions el step que ejecuta la validación. El comando kyverno apply aplica las políticas del directorio indicado contra todos los manifiestos del directorio de recursos:
- name: Validar manifiestos Kubernetes con Kyverno
run: |
kyverno apply .github/policies/ -r manifests/
El flag -r (o --resource) indica el directorio o fichero que contiene los manifiestos a validar. Puedes especificar múltiples rutas o usar globs.
Gestión de fallos con notificaciones
Para mejorar la visibilidad, puedes añadir un step condicional que notifique al equipo cuando se detecte una violación de política:
- name: Notificar violación de política
if: failure()
run: echo "Se han detectado violaciones de política. Revisa los manifiestos antes de mergear."
En entornos más avanzados, este step podría enviar una notificación a Slack, crear un comentario en el PR o publicar los resultados como artefacto del workflow.
Paso 4: Workflow completo integrado
Aquí tienes el workflow de GitHub Actions completo, integrando instalación, validación y notificación:
name: Validación de políticas Kyverno
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
kyverno-policy-check:
name: Kyverno Policy Check
runs-on: ubuntu-latest
steps:
- name: Checkout del código
uses: actions/checkout@v4
- name: Instalar Kyverno CLI
run: |
KYVERNO_VERSION="v1.13.0"
curl -LO "https://github.com/kyverno/kyverno/releases/download/${KYVERNO_VERSION}/kyverno-cli_${KYVERNO_VERSION}_linux_x86_64.tar.gz"
tar -xzf "kyverno-cli_${KYVERNO_VERSION}_linux_x86_64.tar.gz"
sudo mv kyverno /usr/local/bin/
kyverno version
- name: Validar manifiestos Kubernetes con Kyverno
run: |
kyverno apply .github/policies/ -r manifests/
- name: Informar sobre violaciones de política
if: failure()
run: |
echo "::error::Se han detectado violaciones de política Kyverno."
echo "Revisa los manifiestos en el directorio 'manifests/' y corrígelos antes de continuar."
Ejemplo práctico: Detectando una violación
Supongamos que un desarrollador hace push de un Deployment de nginx con la siguiente configuración:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest # Esto debería activar una violación
Este manifiesto viola la política disallow-latest-tag. Cuando el pipeline ejecuta kyverno apply .github/policies/ -r manifests/, el resultado sería algo similar a:
Applying 2 policy rule(s) to 1 resource(s)...
policy disallow-latest-tag -> resource default/Deployment/nginx-deployment
Rule require-image-tag failed 🚫
-> Las imágenes de contenedor deben especificar un tag distinto de 'latest'.
-> Image nginx:latest violates the constraint
pass: 0, fail: 1, warn: 0, error: 0, skip: 0
El pipeline falla con código de salida no cero, bloqueando el merge del PR hasta que el desarrollador corrija la imagen. La solución sería usar un tag de versión específico:
image: nginx:1.27.3
Buenas prácticas para Kyverno CLI en CI/CD
Separar políticas de audit y enforce
En entornos donde todavía se está adoptando Kyverno, puede ser útil diferenciar entre políticas en modo Audit (que informan pero no bloquean) y políticas en modo Enforce (que bloquean el pipeline). Esto permite una adopción progresiva sin interrumpir el flujo de trabajo:
spec:
validationFailureAction: Audit # O Enforce
En el pipeline CI/CD, puedes mantener ambos conjuntos de políticas en directorios separados (por ejemplo, .github/policies/enforce/ y .github/policies/audit/) y ejecutarlos de forma independiente, tratando los fallos de audit como warnings y los de enforce como errores que bloquean el pipeline.
Cachear el binario de Kyverno CLI
Para acelerar el pipeline, puedes cachear el binario de Kyverno entre ejecuciones usando la acción actions/cache:
- name: Cachear Kyverno CLI
uses: actions/cache@v4
with:
path: /usr/local/bin/kyverno
key: kyverno-cli-v1.13.0
- name: Instalar Kyverno CLI (si no está en caché)
run: |
if ! command -v kyverno &> /dev/null; then
curl -LO "https://github.com/kyverno/kyverno/releases/download/v1.13.0/kyverno-cli_v1.13.0_linux_x86_64.tar.gz"
tar -xzf kyverno-cli_v1.13.0_linux_x86_64.tar.gz
sudo mv kyverno /usr/local/bin/
fi
Usar kyverno test para políticas más complejas
Para políticas más complejas que requieren testear tanto casos válidos como inválidos, Kyverno CLI ofrece el subcomando kyverno test. Este comando permite definir fixtures con el resultado esperado para cada recurso, lo que resulta muy útil en pipelines de CI para los propios repositorios de políticas:
kyverno test .github/policies/tests/
La estructura de un test de Kyverno incluye:
– El fichero de política
– Los manifiestos de recursos a testear
– Un fichero kyverno-test.yaml que define qué resultado se espera para cada combinación de política y recurso
Integración con repositorios de políticas centralizados
En organizaciones grandes, lo habitual es mantener las políticas en un repositorio centralizado separado del código de aplicación. En ese caso, el workflow de CI puede clonar ese repositorio de políticas como parte del pipeline:
- name: Clonar repositorio de políticas
uses: actions/checkout@v4
with:
repository: mi-org/kyverno-policies
path: kyverno-policies
token: ${{ secrets.POLICIES_REPO_TOKEN }}
- name: Validar manifiestos contra políticas corporativas
run: |
kyverno apply kyverno-policies/enforce/ -r manifests/
Relación entre Kyverno CLI y el Admission Controller
Un punto importante a tener en cuenta es que Kyverno CLI y el admission controller de Kyverno son complementarios, no sustitutos.
| Característica | Kyverno CLI (CI/CD) | Kyverno Admission Controller |
|---|---|---|
| Cuándo actúa | En el pipeline, antes del despliegue | En el clúster, en tiempo de admisión |
| Requiere clúster | No | Sí |
| Velocidad de feedback | Inmediata (en el PR) | Al intentar desplegar |
| Puede mutar recursos | No | Sí |
| Coste de corrección | Mínimo | Mayor |
La estrategia óptima es aplicar ambas capas: el CLI en CI/CD para detección temprana y el admission controller en el clúster como última línea de defensa. De esta forma, incluso si alguien intenta saltarse el pipeline y desplegar directamente con kubectl apply, el clúster seguirá protegido.
Troubleshooting habitual
El CLI no encuentra los manifiestos
Asegúrate de que la ruta especificada con -r existe y contiene ficheros YAML válidos. Puedes verificarlo con un step previo:
- name: Listar manifiestos
run: find manifests/ -name "*.yaml" -type f
Las políticas no se aplican a todos los recursos
Kyverno evalúa las políticas según el kind especificado en la regla. Si tus políticas apuntan a Pod pero tus manifiestos son Deployment, puede que necesites ajustar el match o saber que Kyverno CLI en modo apply evalúa los recursos tal como están definidos, no las plantillas de pod anidadas. En algunos casos puede ser necesario incluir los kinds de nivel superior:
match:
any:
- resources:
kinds:
- Deployment
- StatefulSet
- DaemonSet
- Pod
El pipeline falla pero no se ven los detalles del error
Añade el flag --detailed-results al comando de Kyverno para obtener más información sobre cada violación:
kyverno apply .github/policies/ -r manifests/ --detailed-results
Conclusión
Integrar Kyverno CLI en un pipeline de GitHub Actions es una de las formas más eficaces de aplicar el principio de shift-left security en entornos Kubernetes. Con una inversión mínima — unas pocas líneas de YAML en el workflow y un directorio de políticas en el repositorio — se obtiene una capa de validación automática que:
- Detecta violaciones de políticas de seguridad y configuración antes de que lleguen al clúster
- Proporciona feedback inmediato a los desarrolladores en cada pull request
- Mantiene la consistencia entre los entornos de desarrollo, staging y producción
- Reduce el coste de corrección al desplazar los controles a la fase más temprana posible
El Kyverno CLI no reemplaza al admission controller desplegado en el clúster, sino que lo complementa formando una estrategia de defensa en profundidad. Juntos, garantizan que los recursos de Kubernetes cumplan con las políticas corporativas tanto en el momento de revisión del código como en el momento del despliegue.
Para profundizar más en Kubernetes y sus patrones de seguridad, consulta la guía completa de Kubernetes Architecture Patterns donde encontrarás todos los conceptos fundamentales y avanzados explicados paso a paso.