Agent-almanac optimize-cloud-costs
git clone https://github.com/pjt222/agent-almanac
T=$(mktemp -d) && git clone --depth=1 https://github.com/pjt222/agent-almanac "$T" && mkdir -p ~/.claude/skills && cp -r "$T/i18n/es/skills/optimize-cloud-costs" ~/.claude/skills/pjt222-agent-almanac-optimize-cloud-costs-1b7c7a && rm -rf "$T"
i18n/es/skills/optimize-cloud-costs/SKILL.mdOptimizar Costos en la Nube
Implementa estrategias integrales de optimización de costos para clústeres Kubernetes para reducir el gasto en la nube.
Cuándo Usar
- Cuando los costos de infraestructura en la nube crecen sin el correspondiente aumento del valor de negocio
- Al necesitar visibilidad sobre la asignación de costos por equipo, aplicación o entorno
- Cuando las solicitudes/límites de recursos no están alineados con los patrones de uso real
- Cuando el escalado manual lleva al sobreaprovisionamiento y el desperdicio
- Al querer aprovechar instancias spot/preemptibles para cargas de trabajo no críticas
- Al necesitar implementar showback o chargeback para la asignación interna de costos
- Al buscar establecer una cultura FinOps con conciencia y responsabilidad de costos
Entradas
- Requerido: Clúster Kubernetes con cargas de trabajo en ejecución
- Requerido: Acceso a la API de facturación del proveedor de la nube
- Requerido: Servidor de métricas o Prometheus para métricas de recursos
- Opcional: Datos históricos de uso para análisis de tendencias
- Opcional: Requisitos de asignación de costos (por namespace, etiqueta, equipo)
- Opcional: Objetivos de nivel de servicio (SLOs) para restricciones de rendimiento
- Opcional: Límites de presupuesto u objetivos de reducción de costos
Procedimiento
Consulta Ejemplos Extendidos para archivos de configuración completos y plantillas.
Paso 1: Desplegar Herramientas de Visibilidad de Costos
Instala Kubecost u OpenCost para el monitoreo y la asignación de costos.
Instalar Kubecost:
# Add Kubecost Helm repository helm repo add kubecost https://kubecost.github.io/cost-analyzer/ helm repo update # Install Kubecost with Prometheus integration helm install kubecost kubecost/cost-analyzer \ --namespace kubecost \ --create-namespace \ --set kubecostToken="your-token-here" \ --set prometheus.server.global.external_labels.cluster_id="production-cluster" \ --set prometheus.nodeExporter.enabled=true \ --set prometheus.serviceAccounts.nodeExporter.create=true # For existing Prometheus, configure Kubecost to use it helm install kubecost kubecost/cost-analyzer \ --namespace kubecost \ --create-namespace \ --set prometheus.enabled=false \ --set global.prometheus.fqdn="http://prometheus-server.monitoring.svc.cluster.local" \ --set global.prometheus.enabled=true # Verify installation kubectl get pods -n kubecost kubectl get svc -n kubecost # Access Kubecost UI kubectl port-forward -n kubecost svc/kubecost-cost-analyzer 9090:9090 # Open http://localhost:9090
Configurar la integración con el proveedor de la nube:
# kubecost-cloud-integration.yaml apiVersion: v1 kind: Secret metadata: name: cloud-integration namespace: kubecost type: Opaque stringData: # For AWS cloud-integration.json: | { "aws": [ { "serviceKeyName": "AWS_ACCESS_KEY_ID", "serviceKeySecret": "AWS_SECRET_ACCESS_KEY", "athenaProjectID": "cur-query-results", "athenaBucketName": "s3://your-cur-bucket", "athenaRegion": "us-east-1", "athenaDatabase": "athenacurcfn_my_cur", "athenaTable": "my_cur" } ] } --- # For GCP apiVersion: v1 kind: Secret metadata: name: gcp-key namespace: kubecost type: Opaque data: key.json: <base64-encoded-service-account-key> --- # For Azure apiVersion: v1 kind: ConfigMap metadata: name: azure-config namespace: kubecost data: azure.json: | { "azureSubscriptionID": "your-subscription-id", "azureClientID": "your-client-id", "azureClientSecret": "your-client-secret", "azureTenantID": "your-tenant-id", "azureOfferDurableID": "MS-AZR-0003P" }
Aplica la integración con la nube:
kubectl apply -f kubecost-cloud-integration.yaml # Verify cloud costs are being imported kubectl logs -n kubecost -l app=cost-analyzer -c cost-model --tail=100 | grep -i "cloud" # Check Kubecost API for cost data kubectl port-forward -n kubecost svc/kubecost-cost-analyzer 9090:9090 & curl http://localhost:9090/model/allocation\?window\=7d | jq .
Esperado: Pods de Kubecost en ejecución correctamente. Interfaz accesible mostrando el desglose de costos por namespace, despliegue, pod. Los costos del proveedor de la nube se importan (puede tardar 24-48 horas para la sincronización inicial). La API devuelve datos de asignación.
En caso de fallo:
- Comprueba que Prometheus está en ejecución y accesible:
kubectl get svc -n monitoring prometheus-server - Verifica que las credenciales de la nube tienen acceso a la API de facturación
- Revisa los registros del modelo de costos:
kubectl logs -n kubecost -l app=cost-analyzer -c cost-model - Asegúrate de que el servidor de métricas o el exportador de nodos de Prometheus está recopilando métricas de recursos
- Comprueba las políticas de red que bloquean el acceso a las API de facturación de la nube
Paso 2: Analizar la Utilización Actual de Recursos
Identifica los recursos sobreaprovisionados y las oportunidades de optimización.
Consulta la utilización de recursos:
# Get resource requests vs usage for all pods kubectl top pods --all-namespaces --containers | \ awk 'NR>1 {print $1,$2,$3,$4,$5}' > current-usage.txt # Compare requests to actual usage cat <<'EOF' > analyze-utilization.sh #!/bin/bash echo "Pod,Namespace,CPU-Request,CPU-Usage,Memory-Request,Memory-Usage" for ns in $(kubectl get ns -o jsonpath='{.items[*].metadata.name}'); do kubectl get pods -n $ns -o json | jq -r ' .items[] | select(.status.phase == "Running") | { name: .metadata.name, namespace: .metadata.namespace, containers: [ .spec.containers[] | { name: .name, cpuReq: .resources.requests.cpu, memReq: .resources.requests.memory } ] } | "\(.name),\(.namespace),\(.containers[].cpuReq // "none"),\(.containers[].memReq // "none")" ' 2>/dev/null done EOF chmod +x analyze-utilization.sh ./analyze-utilization.sh > resource-requests.csv # Get actual usage from metrics server kubectl top pods --all-namespaces --containers > actual-usage.txt
Usa las recomendaciones de Kubecost:
# Get right-sizing recommendations via API curl "http://localhost:9090/model/savings/requestSizing?window=7d" | jq . > recommendations.json # Extract top wasteful resources jq '.data[] | select(.totalRecommendedSavings > 10) | { cluster: .clusterID, # ... (see EXAMPLES.md for complete configuration)
Crea el panel de utilización:
# grafana-utilization-dashboard.yaml apiVersion: v1 kind: ConfigMap metadata: name: utilization-dashboard namespace: monitoring # ... (see EXAMPLES.md for complete configuration)
Esperado: Vista clara de las solicitudes de recursos actuales frente al uso real. Identificación de pods con <30% de utilización (sobreaprovisionados). Lista de oportunidades de optimización con ahorros estimados. Panel mostrando tendencias de utilización a lo largo del tiempo.
En caso de fallo:
- Asegúrate de que el servidor de métricas está en ejecución:
kubectl get deployment metrics-server -n kube-system - Comprueba si Prometheus tiene métricas del exportador de nodos:
curl http://prometheus:9090/api/v1/query?query=node_cpu_seconds_total - Verifica que los pods han estado en ejecución el tiempo suficiente para datos significativos (al menos 24 horas)
- Comprueba las lagunas en la recopilación de métricas: revisa la retención y los intervalos de extracción de Prometheus
- Para Kubecost, asegúrate de que ha recopilado al menos 48 horas de datos
Paso 3: Implementar el Escalado Automático Horizontal de Pods (HPA)
Configura el escalado automático basado en CPU, memoria o métricas personalizadas.
Crea HPA para el escalado basado en CPU:
# hpa-cpu.yaml apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: api-server-hpa namespace: production # ... (see EXAMPLES.md for complete configuration)
Despliega y verifica el HPA:
kubectl apply -f hpa-cpu.yaml # Check HPA status kubectl get hpa -n production kubectl describe hpa api-server-hpa -n production # Monitor scaling events kubectl get events -n production --field-selector involvedObject.kind=HorizontalPodAutoscaler --watch # Generate load to test autoscaling kubectl run load-generator --rm -it --image=busybox -- /bin/sh -c \ "while true; do wget -q -O- http://api-server.production.svc.cluster.local; done" # Watch replicas scale watch kubectl get hpa,deployment -n production
Esperado: HPA creado y mostrando las métricas actuales/objetivo. Los pods escalan hacia arriba bajo carga. Los pods escalan hacia abajo cuando la carga disminuye (después del período de estabilización). Los eventos de escalado registrados. Sin comportamiento oscilante (ciclos rápidos de escala arriba/abajo).
En caso de fallo:
- Verifica que el servidor de métricas está en ejecución:
kubectl get apiservice v1beta1.metrics.k8s.io - Comprueba si el despliegue tiene establecidas las solicitudes de recursos (HPA lo requiere)
- Revisa los eventos de HPA:
kubectl describe hpa api-server-hpa -n production - Asegúrate de que el despliegue destino no está en el máximo de réplicas
- Para métricas personalizadas, verifica que el adaptador de métricas está instalado y configurado
- Comprueba los registros del controlador HPA:
kubectl logs -n kube-system -l app=kube-controller-manager | grep horizontal-pod-autoscaler
Paso 4: Configurar el Escalado Automático Vertical de Pods (VPA)
Ajusta automáticamente las solicitudes de recursos basándose en los patrones de uso reales.
Instala VPA:
# Clone VPA repository git clone https://github.com/kubernetes/autoscaler.git cd autoscaler/vertical-pod-autoscaler # Install VPA ./hack/vpa-up.sh # Verify installation kubectl get pods -n kube-system | grep vpa # Check VPA CRDs kubectl get crd | grep verticalpodautoscaler
Crea políticas VPA:
# vpa-policies.yaml apiVersion: autoscaling.k8s.io/v1 kind: VerticalPodAutoscaler metadata: name: api-server-vpa namespace: production # ... (see EXAMPLES.md for complete configuration)
Despliega y monitorea el VPA:
kubectl apply -f vpa-policies.yaml # Check VPA recommendations kubectl get vpa -n production kubectl describe vpa api-server-vpa -n production # View detailed recommendations kubectl get vpa api-server-vpa -n production -o jsonpath='{.status.recommendation}' | jq . # Monitor VPA-initiated pod updates kubectl get events -n production --field-selector involvedObject.kind=VerticalPodAutoscaler --watch # Compare recommendations to current requests kubectl get deployment api-server -n production -o json | \ jq '.spec.template.spec.containers[].resources.requests'
Esperado: VPA proporcionando recomendaciones o actualizando automáticamente las solicitudes de recursos. Las recomendaciones basadas en patrones de uso por percentil (típicamente P95). Los pods se reinician con nuevas solicitudes al usar el modo Auto/Recreate. Sin conflictos entre HPA y VPA (usa HPA para réplicas, VPA para recursos por pod).
En caso de fallo:
- Asegúrate de que el servidor de métricas tiene datos suficientes (VPA necesita varios días para recomendaciones precisas)
- Comprueba que los componentes VPA están en ejecución:
kubectl get pods -n kube-system | grep vpa - Revisa los registros del controlador de admisión VPA:
kubectl logs -n kube-system -l app=vpa-admission-controller - Verifica que el webhook está registrado:
kubectl get mutatingwebhookconfigurations vpa-webhook-config - No uses VPA y HPA en la misma métrica (CPU/memoria) - causa conflictos
- Comienza con el modo "Off" para revisar las recomendaciones antes de habilitar las actualizaciones automáticas
Paso 5: Aprovechar las Instancias Spot/Preemptibles
Configura la programación de cargas de trabajo en instancias spot rentables.
Crea grupos de nodos con instancias spot:
# For AWS (via Karpenter) apiVersion: karpenter.sh/v1alpha5 kind: Provisioner metadata: name: spot-provisioner spec: # ... (see EXAMPLES.md for complete configuration)
Configura las cargas de trabajo para instancias spot:
# spot-workload.yaml apiVersion: apps/v1 kind: Deployment metadata: name: batch-processor namespace: production # ... (see EXAMPLES.md for complete configuration)
Despliega y monitorea el uso de spot:
kubectl apply -f spot-workload.yaml # Monitor spot node allocation kubectl get nodes -l node-type=spot # Check workload distribution # ... (see EXAMPLES.md for complete configuration)
Esperado: Las cargas de trabajo programadas en nodos spot correctamente. Reducción significativa de costos (típicamente 60-90% frente a bajo demanda). Manejo gracioso de las interrupciones spot con reprogramación de pods. El monitoreo muestra la tasa de interrupción spot y la recuperación correcta.
En caso de fallo:
- Verifica la disponibilidad de instancias spot en tu región/zonas
- Comprueba que las etiquetas y manchas de los nodos coinciden con las tolerancias de la carga de trabajo
- Revisa los registros de Karpenter:
kubectl logs -n karpenter -l app.kubernetes.io/name=karpenter - Asegúrate de que las cargas de trabajo son sin estado o tienen una gestión de estado adecuada para las interrupciones
- Prueba el manejo de interrupciones: acorralona y vacía manualmente el nodo spot
- Monitorea la tasa de interrupción: si es demasiado alta, considera el retroceso a nodos bajo demanda
Paso 6: Implementar Cuotas de Recursos y Alertas de Presupuesto
Establece límites estrictos y alertas para el control de costos.
Crea cuotas de recursos:
# resource-quotas.yaml apiVersion: v1 kind: ResourceQuota metadata: name: production-quota namespace: production # ... (see EXAMPLES.md for complete configuration)
Configura alertas de presupuesto:
# kubecost-budget-alerts.yaml apiVersion: v1 kind: ConfigMap metadata: name: budget-alerts namespace: kubecost # ... (see EXAMPLES.md for complete configuration)
Aplica y monitorea:
kubectl apply -f resource-quotas.yaml kubectl apply -f kubecost-budget-alerts.yaml # Check quota usage kubectl get resourcequota -n production kubectl describe resourcequota production-quota -n production # ... (see EXAMPLES.md for complete configuration)
Esperado: Las cuotas de recursos aplican límites por namespace. La creación de pods se bloquea cuando se supera la cuota. Las alertas de presupuesto se activan cuando se superan los umbrales. La detección de picos de costos funciona. Se envían informes regulares a las partes interesadas.
En caso de fallo:
- Verifica que ResourceQuota y LimitRange se aplicaron correctamente:
kubectl get resourcequota,limitrange -A - Comprueba los pods fallando debido a la cuota:
kubectl get events -n production | grep quota - Revisa la configuración de alertas de Kubecost:
kubectl logs -n kubecost -l app=cost-analyzer | grep alert - Asegúrate de que Prometheus tiene métricas de Kubecost:
curl http://prometheus:9090/api/v1/query?query=kubecost_monthly_cost - Prueba el enrutamiento de alertas: verifica la configuración de webhook de correo electrónico/Slack
Validación
- Kubecost u OpenCost desplegado y mostrando datos de costos precisos
- Integración de facturación del proveedor de la nube funcionando (los costos coinciden con las facturas reales)
- El análisis de utilización de recursos identifica cargas de trabajo sobreaprovisionadas
- HPA escala los pods según la carga (verificado con prueba de carga)
- VPA proporcionando recomendaciones o ajustando automáticamente las solicitudes de recursos
- Las instancias spot manejan las interrupciones de forma graciosa
- Las cuotas de recursos aplican límites por namespace
- Las alertas de presupuesto se activan cuando se superan los umbrales
- El costo mensual tiende a la baja o se mantiene dentro del presupuesto
- Informes de showback generados para equipos/proyectos
- Sin degradación del rendimiento por las optimizaciones de costos
- Documentación actualizada con prácticas de optimización
Errores Comunes
-
Dimensionamiento correcto agresivo: No apliques inmediatamente las recomendaciones del VPA. Comienza con el modo "Off", revisa las sugerencias durante una semana, luego aplícalas gradualmente. Los cambios repentinos pueden causar OOMKills o estrangulamiento de CPU.
-
Conflicto HPA + VPA: Nunca uses HPA y VPA en la misma métrica (CPU/memoria). Usa HPA para el escalado horizontal, VPA para el ajuste de recursos por pod, o HPA en métricas personalizadas + VPA en recursos.
-
Spot sin tolerancia a fallos: Solo ejecuta cargas de trabajo tolerantes a fallos y sin estado en spot. Nunca bases de datos, servicios con estado o servicios críticos de réplica única. Usa siempre PodDisruptionBudgets.
-
Período de monitoreo insuficiente: Las decisiones de optimización de costos necesitan datos históricos. Espera al menos 7 días antes de hacer cambios, 30 días para las recomendaciones de VPA, 90 días para el análisis de tendencias.
-
Ignorar los requisitos de ráfaga: Establecer límites demasiado bajos basándose en el uso promedio causa estrangulamiento durante los picos de tráfico. Usa percentiles P95 o P99, no el promedio, para la planificación de capacidad.
-
Costos de salida de red: Los costos de cómputo son visibles en Kubecost, pero la salida (transferencia de datos) puede ser significativa. Monitorea el tráfico entre zonas de disponibilidad, usa enrutamiento con conocimiento de la topología, considera los costos de transferencia de datos en la arquitectura.
-
Almacenamiento pasado por alto: Los costos de PersistentVolume a menudo se olvidan. Audita los PVC no utilizados, ajusta el tamaño de los volúmenes, usa la expansión de volúmenes en lugar del sobreaprovisionamiento, implementa políticas de limpieza de PV.
-
Cuota demasiado restrictiva: Establecer cuotas demasiado bajas bloquea el crecimiento legítimo. Revisa el uso de cuotas mensualmente, ajusta según las necesidades reales, comunica los límites a los equipos antes de la aplicación.
-
Ahorros falsos por métricas incorrectas: Usar CPU/memoria como única métrica de optimización pasa por alto los costos de E/S, red y almacenamiento. Considera el costo total de propiedad, no solo el cómputo.
-
Chargeback antes de la confianza: Implementar el chargeback antes de que los equipos entiendan y confíen en los datos de costos causa fricción. Comienza con showback (informativo), construye una cultura de conciencia de costos, luego pasa al chargeback.
Habilidades Relacionadas
- Despliegue de aplicaciones con solicitudes de recursos apropiadasdeploy-to-kubernetes
- Infraestructura de monitoreo para métricas de costossetup-prometheus-monitoring
- Planificación de capacidad basada en costos y rendimientoplan-capacity
- Desarrollo local para evitar costos de la nubesetup-local-kubernetes
- Plantillas de solicitudes y límites de recursoswrite-helm-chart
- GitOps para configuraciones optimizadas en costosimplement-gitops-workflow