tutoriales.com

Optimización de Rendimiento en Kubernetes: Limpieza de Recursos con Kube-Janitor y Políticas Avanzadas ✨

Este tutorial te guiará a través de la implementación de Kube-Janitor para la limpieza automática y eficiente de recursos de Kubernetes. Aprenderás a definir políticas de limpieza, configurar Kube-Janitor y asegurar que tus clusters permanezcan optimizados y libres de recursos huérfanos, mejorando la eficiencia y reduciendo costes operativos.

Intermedio15 min de lectura32 views
Reportar error

Introducción: La Necesidad de Limpieza en Kubernetes 🧹

En entornos de Kubernetes dinámicos, es común que se acumulen recursos que ya no son necesarios: Pods completados, Deployments antiguos, PVCs huérfanos, Services de prueba o Ingresses que quedaron atrás. Esta acumulación, conocida como resource sprawl, puede llevar a varios problemas:

  • Aumento de Costes: Recursos persistentes no utilizados consumen CPU, memoria y almacenamiento, resultando en facturas más altas.
  • Ineficiencia Operativa: Dificultad para identificar recursos activos entre la maraña de elementos obsoletos.
  • Riesgos de Seguridad: Recursos antiguos con configuraciones potencialmente vulnerables o accesos no deseados.
  • Consumo de IPs: Los Services y Ingresses consumen IPs, que son un recurso finito en muchos entornos cloud.
  • Entorno Desordenado: Un cluster lleno de basura es más difícil de gestionar, depurar y auditar.

Tradicionalmente, la limpieza se realiza de forma manual, lo cual es propenso a errores y poco escalable. Aquí es donde herramientas como Kube-Janitor entran en juego, automatizando este proceso crucial y permitiendo a los equipos DevOps centrarse en tareas de mayor valor.

💡 Consejo: Considera la limpieza de recursos como una parte esencial del ciclo de vida de tus aplicaciones, no como una tarea opcional.

¿Qué es Kube-Janitor y Cómo Funciona? 🤖

Kube-Janitor es un controlador de Kubernetes de código abierto diseñado para escanear y eliminar automáticamente recursos que cumplen ciertos criterios de caducidad. Es altamente configurable, permitiendo definir políticas complejas basadas en etiquetas (labels), anotaciones (annotations) y tipos de recursos.

Su funcionamiento básico es el siguiente:

  1. Observación: Kube-Janitor monitorea el cluster de Kubernetes, listando los recursos de los tipos configurados.
  2. Evaluación de Políticas: Para cada recurso, aplica un conjunto de reglas de expiración definidas. Estas reglas pueden basarse en la antigüedad del recurso (usando creationTimestamp o una anotación personalizada) o en la presencia de etiquetas específicas.
  3. Marcado para Eliminación (Opcional): Antes de eliminar, Kube-Janitor puede añadir una anotación al recurso indicando que ha sido marcado para eliminación. Esto da un período de gracia para que los operadores puedan intervenir si es necesario.
  4. Eliminación: Si un recurso cumple las políticas de expiración y, opcionalmente, ha pasado su período de gracia, Kube-Janitor procede a eliminarlo.

Kube-Janitor se ejecuta como un Pod dentro de tu cluster, lo que facilita su despliegue y gestión.

🔥 Importante: Siempre prueba tus políticas de Kube-Janitor en un entorno de desarrollo o staging antes de aplicarlas a producción para evitar eliminaciones accidentales.
1. Escaneo del Cluster 2. ¿Recurso cumple política de expiración? No No hace nada Si 3. ¿Tiene período de gracia? Si 4. Marca para eliminación y espera No Termina gracia 5. Elimina recurso

Tipos de Recursos Soportados 📂

Kube-Janitor puede gestionar la limpieza de una amplia gama de recursos de Kubernetes, incluyendo, pero no limitado a:

  • Pods
  • Deployments
  • ReplicaSets
  • StatefulSets
  • Jobs y CronJobs
  • PersistentVolumeClaims (PVCs)
  • Services
  • Ingresses
  • ConfigMaps y Secrets (con precaución)
  • Custom Resource Definitions (CRDs) y sus instancias

La flexibilidad para definir políticas por tipo de recurso es una de sus mayores fortalezas.

Preparación del Entorno 🛠️

Antes de desplegar Kube-Janitor, asegúrate de tener acceso a un cluster de Kubernetes y las herramientas básicas:

  • kubectl: Para interactuar con tu cluster.
  • helm (opcional): Para una instalación más sencilla de Kube-Janitor.

Creando un Namespace Dedicado 🎯

Es una buena práctica desplegar Kube-Janitor en su propio namespace.

kubectl create namespace kube-janitor

Permisos Necesarios: RBAC 🔐

Kube-Janitor necesita permisos para listar, obtener, actualizar y eliminar los recursos que va a gestionar. Esto se logra a través de ServiceAccount, ClusterRole y ClusterRoleBinding.

A continuación, se muestra un ejemplo básico de RBAC. Kube-Janitor generalmente viene con sus propios manifiestos de RBAC que puedes adaptar.

# service-account.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: kube-janitor-sa
  namespace: kube-janitor
---
# cluster-role.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: kube-janitor-role
rules:
  - apiGroups: ["*"]
    resources: ["*"]
    verbs: ["get", "list", "watch", "delete", "update", "patch"]
---
# cluster-role-binding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: kube-janitor-binding
subjects:
  - kind: ServiceAccount
    name: kube-janitor-sa
    namespace: kube-janitor
roleRef:
  kind: ClusterRole
  name: kube-janitor-role
  apiGroup: rbac.authorization.k8s.io
⚠️ Advertencia: El `ClusterRole` de ejemplo concede permisos muy amplios (`apiGroups: ["*"]`, `resources: ["*"]`). En un entorno de producción, es crucial restringir estos permisos solo a los tipos de recursos y verbos que Kube-Janitor realmente necesita para operar, siguiendo el principio de *menor privilegio*.

Para aplicar estos recursos:

kubectl apply -f service-account.yaml -n kube-janitor
kubectl apply -f cluster-role.yaml
kubectl apply -f cluster-role-binding.yaml

Despliegue de Kube-Janitor 🚀

La forma más sencilla de desplegar Kube-Janitor es usando Helm.

Añadir el repositorio de Helm

helm repo add kube-janitor https://navikt.github.io/helm-charts
helm repo update

Instalar Kube-Janitor con Helm

La instalación de Kube-Janitor se realiza con el comando helm install, donde especificaremos el ServiceAccount que creamos previamente y configuraremos las políticas.

helm install kube-janitor kube-janitor/kube-janitor \
  --namespace kube-janitor \
  --set serviceAccount.create=false \
  --set serviceAccount.name=kube-janitor-sa \
  --set janitor.dryRun=true \
  --set janitor.interval="5m" \
  --set janitor.policies[0].apiGroup="*" \
  --set janitor.policies[0].kind="Pod" \
  --set janitor.policies[0].ttl="1h" \
  --set janitor.policies[0].selector.matchLabels.janitor-enabled="true" \
  --set janitor.policies[0].selector.matchLabels.environment!="production" \
  --set janitor.policies[1].apiGroup="batch" \
  --set janitor.policies[1].kind="Job" \
  --set janitor.policies[1].ttl="2h" \
  --set janitor.policies[1].selector.matchLabels.type="ci-job" \
  --set janitor.policies[2].apiGroup="" \
  --set janitor.policies[2].kind="PersistentVolumeClaim" \
  --set janitor.policies[2].ttl="24h" \
  --set janitor.policies[2].selector.matchLabels.status="orphan" \
  --set janitor.policies[3].apiGroup="apps" \
  --set janitor.policies[3].kind="Deployment" \
  --set janitor.policies[3].ttl="48h" \
  --set janitor.policies[3].selector.matchLabels.status="deprecated" \
  --set janitor.policies[3].selector.matchExpressions[0].key="app.kubernetes.io/instance" \
  --set janitor.policies[3].selector.matchExpressions[0].operator="DoesNotExist"

Analicemos los parámetros clave:

  • --namespace kube-janitor: Despliega Kube-Janitor en el namespace kube-janitor.
  • --set serviceAccount.create=false --set serviceAccount.name=kube-janitor-sa: Indica que usaremos un ServiceAccount existente.
  • --set janitor.dryRun=true: MUY IMPORTANTE. Inicialmente, Kube-Janitor se ejecutará en modo dry-run, lo que significa que solo reportará qué recursos serían eliminados, sin ejecutar la eliminación real. Esto es crucial para probar las políticas.
  • --set janitor.interval="5m": Define el intervalo de escaneo del cluster (en este caso, cada 5 minutos).
  • --set janitor.policies[...]: Aquí es donde definimos nuestras reglas de limpieza. Cada índice en el array policies representa una política diferente.
    • apiGroup, kind: Especifica el tipo de recurso al que aplica la política (e.g., kind: Pod sin apiGroup para recursos core, apiGroup: batch, kind: Job).
    • ttl: Time To Live, el tiempo después del cual el recurso es elegible para eliminación (e.g., 1h para 1 hora, 24h para 24 horas).
    • selector: Un labelSelector para filtrar los recursos. Solo se considerarán los recursos que coincidan con estos selectores.
      • matchLabels: Coincidencia exacta de etiquetas (e.g., janitor-enabled: "true"). También se pueden usar negaciones como environment!= "production".
      • matchExpressions: Coincidencia más compleja, con operadores como In, NotIn, Exists, DoesNotExist.

Políticas de Ejemplo Explicadas

  1. Pods de desarrollo o testing: Eliminar Pods que tengan la etiqueta janitor-enabled: "true" y que no sean del entorno de production, después de 1 hora de su creación.
  2. Jobs de CI: Eliminar Jobs con la etiqueta type: "ci-job" después de 2 horas.
  3. PVCs huérfanas: Eliminar PersistentVolumeClaims marcadas con status: "orphan" después de 24 horas. (Esto requeriría un proceso externo que marque las PVCs huérfanas).
  4. Deployments obsoletos: Eliminar Deployments con la etiqueta status: "deprecated" y que no tengan la etiqueta app.kubernetes.io/instance (indicando que no son parte de una aplicación Helm activa, por ejemplo) después de 48 horas.
📌 Nota: Puedes usar `--set-file values.yaml=` si tienes muchas políticas o configuraciones complejas para Kube-Janitor en un archivo `values.yaml` separado.
# values.yaml (ejemplo de configuración de políticas)
janitor:
  dryRun: true
  interval: "10m"
  policies:
    - apiGroup: ""
      kind: "Pod"
      ttl: "30m"
      selector:
        matchLabels:
          temp-resource: "true"
    - apiGroup: "batch"
      kind: "Job"
      ttl: "1h"
      selector:
        matchExpressions:
          - key: "job-type"
            operator: "In"
            values:
              - "cleanup"
              - "test"

Verificación del Despliegue ✅

Comprueba que el Pod de Kube-Janitor se ha desplegado correctamente y está corriendo:

kubectl get pods -n kube-janitor

Deberías ver un output similar a:

NAME                               READY   STATUS    RESTARTS   AGE
kube-janitor-xxxxxxxxx-yyyyy       1/1     Running   0          5m

También puedes ver los logs para observar las acciones que Kube-Janitor estaría realizando en modo dryRun:

kubectl logs -f -n kube-janitor <nombre-del-pod-de-kube-janitor>

Busca mensajes que indiquen qué recursos serían eliminados (Would delete resource...).


Creando Recursos para la Limpieza 🧪

Para probar nuestras políticas, crearemos algunos recursos temporales.

Pod Temporal con janitor-enabled y environment: development

# temp-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-temp-dev-pod
  labels:
    janitor-enabled: "true"
    environment: "development"
spec:
  containers:
    - name: busybox
      image: busybox
      command: ["sh", "-c", "sleep 3600"]
  restartPolicy: Never
kubectl apply -f temp-pod.yaml

Después de aplicar, Kube-Janitor debería detectar este Pod y, si ha pasado el ttl (1 hora en nuestro ejemplo de Helm), reportaría su eliminación en los logs (en modo dry-run).

Job de CI con type: ci-job

# temp-ci-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: my-ci-cleanup-job
  labels:
    type: "ci-job"
spec:
  template:
    spec:
      containers:
        - name: cleaner
          image: alpine/git
          command: ["sh", "-c", "echo 'Cleaning up CI artifacts...' && sleep 60"]
      restartPolicy: OnFailure
  backoffLimit: 4
kubectl apply -f temp-ci-job.yaml

Este Job debería ser candidato para eliminación después de 2 horas.

Deployment con status: deprecated (sin app.kubernetes.io/instance)

# deprecated-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: old-api-gateway
  labels:
    status: "deprecated"
spec:
  replicas: 1
  selector:
    matchLabels:
      app: old-api-gateway
  template:
    metadata:
      labels:
        app: old-api-gateway
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80
kubectl apply -f deprecated-deployment.yaml

Este Deployment debería ser eliminado después de 48 horas.


Configuración Avanzada de Políticas ✨

Las políticas de Kube-Janitor son increíblemente flexibles y permiten escenarios de limpieza muy específicos.

Usando Anotaciones para Control Fino 🏷️

Además de creationTimestamp y labels, Kube-Janitor puede utilizar anotaciones para definir la expiración. La anotación clave es janitor.kubernetes.io/ttl.

💡 Consejo: Usa `janitor.kubernetes.io/ttl` para anular la política global de TTL de Kube-Janitor para un recurso específico, o para definir expiraciones personalizadas si no quieres depender solo del `creationTimestamp`.

Ejemplo de un Pod con ttl definido por anotación:

apiVersion: v1
kind: Pod
metadata:
  name: pod-with-custom-ttl
  labels:
    janitor-enabled: "true"
  annotations:
    janitor.kubernetes.io/ttl: "15m"
spec:
  containers:
    - name: busybox
      image: busybox
      command: ["sh", "-c", "sleep 3600"]
  restartPolicy: Never

Si Kube-Janitor está configurado para buscar la anotación janitor.kubernetes.io/ttl, este Pod será elegible para eliminación después de 15 minutos, independientemente de la política ttl definida en la configuración general para Pods.

Períodos de Gracia y Marcado de Recursos ⏳

Kube-Janitor puede ser configurado para marcar un recurso antes de eliminarlo, dándole un gracePeriod. Esto se hace añadiendo la anotación janitor.kubernetes.io/expires-at con una marca de tiempo UTC en formato ISO 8601.

Puedes configurar Kube-Janitor para que primero añada esta anotación y solo elimine los recursos que ya tienen la anotación janitor.kubernetes.io/expires-at y cuya fecha/hora haya pasado.

janitor:
  ... (otras configuraciones)
  addExpiresAt: true # Kube-Janitor añadirá la anotación janitor.kubernetes.io/expires-at
  gracePeriod: "1h" # Período de gracia de 1 hora después de marcarlo

Con esta configuración, Kube-Janitor haría lo siguiente:

  1. Identifica un recurso que cumple una política de limpieza.
  2. Añade la anotación janitor.kubernetes.io/expires-at al recurso, con la fecha actual + gracePeriod.
  3. En un ciclo posterior, si la fecha de janitor.kubernetes.io/expires-at ha pasado, elimina el recurso.

Esto proporciona una capa de seguridad adicional, permitiendo la intervención manual si un recurso marcado no debería ser eliminado.

⚠️ Advertencia: Asegúrate de que el formato de fecha/hora para `janitor.kubernetes.io/expires-at` sea correcto (ISO 8601). Un formato incorrecto puede hacer que Kube-Janitor ignore la anotación o se comporte de manera inesperada.

Excluyendo Recursos Específicos 🚫

Incluso con políticas bien definidas, puede que necesites excluir ciertos recursos de la limpieza. Kube-Janitor permite esto a través de anotaciones o etiquetas.

La anotación janitor.kubernetes.io/do-not-sweep: "true" o janitor.kubernetes.io/do-not-sweep-until: "YYYY-MM-DDTHH:MM:SSZ" impedirá que Kube-Janitor elimine el recurso.

Ejemplo:

apiVersion: v1
kind: Pod
metadata:
  name: important-long-running-pod
  labels:
    janitor-enabled: "true"
    environment: "development"
  annotations:
    janitor.kubernetes.io/do-not-sweep: "true" # Este Pod nunca será eliminado por Kube-Janitor
spec:
  containers:
    - name: long-runner
      image: busybox
      command: ["sh", "-c", "sleep 86400"]
  restartPolicy: Never

También puedes usar janitor.kubernetes.io/do-not-sweep-until para posponer la limpieza hasta una fecha específica.


Monitoreo y Alertas 📊

Para garantizar que Kube-Janitor funciona como se espera y para detectar problemas (como eliminaciones inesperadas o políticas que no funcionan), es crucial integrarlo con tu sistema de monitoreo.

Kube-Janitor expone métricas Prometheus. Puedes configurarlo para que estas métricas sean recolectadas por Prometheus y visualizadas en Grafana.

Métricas Clave a Monitorear:

  • kubejanitor_scanned_resources_total: Número total de recursos escaneados por tipo.
  • kubejanitor_deleted_resources_total: Número total de recursos eliminados por tipo y política.
  • kubejanitor_dryrun_deleted_resources_total: Número de recursos que serían eliminados en modo dry-run.
  • kubejanitor_resource_errors_total: Errores encontrados al procesar recursos.
Ejemplo de Alerta Prometheus/Alertmanager
# alertmanager.yaml
alertmanager:
  ... (configuración existente)

rules:
  - alert:
      name: KubeJanitorTooManyDeletions
      expr: increase(kubejanitor_deleted_resources_total[5m]) > 100
      for: 5m
      labels:
        severity: warning
      annotations:
        summary: "Kube-Janitor está eliminando una gran cantidad de recursos en un corto período."
        description: "Kube-Janitor ha eliminado más de 100 recursos en los últimos 5 minutos. Esto podría indicar una configuración incorrecta de las políticas."

  - alert:
      name: KubeJanitorDryRunReportUnexpected
      expr: (increase(kubejanitor_dryrun_deleted_resources_total{kind="Pod", policy="pods-dev"}[1h]) > 0) and on() (kube_pod_info{pod=~"my-important-prod-pod.*", namespace="production"} == 1)
      for: 15m
      labels:
        severity: critical
      annotations:
        summary: "Kube-Janitor en dry-run reporta eliminación de un recurso de producción."
        description: "Kube-Janitor, incluso en modo dry-run, ha identificado un recurso de producción crucial para eliminación. ¡Revisa las políticas URGENTE!"

Paneles de Grafana 📈

Un panel de Grafana te permitiría visualizar:

  • Recursos eliminados a lo largo del tiempo, agrupados por tipo.
  • Recursos que serían eliminados en modo dry-run.
  • Errores de Kube-Janitor.
  • Tendencias de limpieza y su impacto en el consumo de recursos.
Kube-Janitor Emite Métricas Prometheus Recolección (Pull) Grafana Visualización Alertmanager Gestión de Alertas HTTP /metrics PromQL Push Alertas

Mejores Prácticas y Consideraciones 🤔

1. Empieza con dryRun=true

Siempre, siempre despliega Kube-Janitor con dryRun=true en tu entorno de producción hasta que estés 100% seguro de que las políticas son correctas. Monitorea los logs y las métricas de dryrun_deleted_resources_total.

2. Políticas Granulares y Específicas

Evita políticas genéricas (kind: "*"). Sé muy específico con los kind y utiliza labels y annotations para acotar los recursos a limpiar. Las políticas deben ser explícitas para evitar eliminaciones accidentales.

3. Uso de Etiquetas y Anotaciones para el Ciclo de Vida

Define un conjunto de etiquetas estándar en tu organización para indicar el ciclo de vida o la naturaleza temporal de un recurso (e.g., environment: dev, temp-resource: true, owner: team-x). Esto facilita la creación de políticas de Kube-Janitor.

4. Exclusiones Explícitas para Recursos Críticos

Usa janitor.kubernetes.io/do-not-sweep: "true" o janitor.kubernetes.io/do-not-sweep-until para proteger explícitamente recursos que NUNCA deben ser eliminados, incluso si accidentalmente coinciden con una política.

5. Monitoreo y Alertas

Configura alertas para eliminaciones inesperadamente altas o para cuando Kube-Janitor detecte recursos críticos que serían eliminados en dryRun.

6. Comunicación con los Desarrolladores

Asegúrate de que los equipos de desarrollo estén al tanto de las políticas de limpieza. Explica cómo etiquetar sus recursos temporales para que sean limpiados y cómo excluir los persistentes.

7. Consideraciones sobre el Tiempo de Vida (TTL)

Establece TTLs razonables. No quieres eliminar recursos demasiado pronto, pero tampoco quieres que persistan indefinidamente. Considera la frecuencia de uso de los entornos de desarrollo/pruebas.

8. Limpieza de Recursos Externos (Opcional)

Kube-Janitor se enfoca en recursos de Kubernetes. Si tienes recursos externos (bases de datos en la nube, buckets S3) que deben limpiarse junto con los recursos de Kubernetes, necesitarás una solución complementaria (como scripts o herramientas de IaC).

Tabla Comparativa: Limpieza Manual vs. Kube-Janitor

CaracterísticaLimpieza ManualKube-Janitor
---------
EficienciaBaja, consume tiempo y es repetitivaAlta, proceso automatizado
PrecisiónPropensa a errores humanosBasada en políticas, alta precisión
---------
EscalabilidadMuy baja, no escala bienAlta, gestiona clusters grandes
ConsistenciaVariada, depende del operadorAlta, políticas aplicadas uniformemente
---------
Detección de HuérfanosDifícil de identificarExcelente, basado en reglas de TTL
Curva de AprendizajeBaja, comandos básicosModerada, configuración de políticas
---------
Impacto en CostesReducción lentaReducción proactiva y continua
Automatización de Limpieza: 90%

Conclusión ✅

Kube-Janitor es una herramienta poderosa y esencial para mantener la higiene y optimización de tus clusters de Kubernetes. Al automatizar la identificación y eliminación de recursos no utilizados, no solo reduces costes y liberas espacio, sino que también mejoras la eficiencia operativa y la seguridad de tu infraestructura.

La clave del éxito con Kube-Janitor radica en una planificación cuidadosa de tus políticas, un despliegue gradual comenzando con dryRun, y una integración robusta con tus herramientas de monitoreo y alerta. Invertir tiempo en configurar Kube-Janitor correctamente te ahorrará innumerables horas de trabajo manual y problemas futuros.

¡Anímate a implementar Kube-Janitor y transforma la gestión de tus recursos de Kubernetes!

Tutoriales relacionados

Comentarios (0)

Aún no hay comentarios. ¡Sé el primero!