¿Cómo ahorrar en costos de la nube cuando se trabaja con Kubernetes? No existe una única solución adecuada, pero este artículo describe varias herramientas que pueden ayudarlo a administrar sus recursos de manera más efectiva y reducir sus costos de computación en la nube.
Escribí este artículo teniendo en mente Kubernetes para AWS, pero se aplicará (casi) exactamente de la misma manera a otros proveedores de nube. Supongo que sus clústeres ya tienen configurado el escalado automático (escalador automático de clúster). Eliminar recursos y reducir su implementación solo le permitirá ahorrar dinero si también reduce su flota de nodos trabajadores (instancias EC2).
Trabajar en un entorno de ritmo rápido es fantástico. Queremos organizaciones tecnológicas acelerado. Una entrega de software más rápida también significa más implementaciones de relaciones públicas, entornos de vista previa, prototipos y soluciones de análisis. Todo está implementado en Kubernetes. ¿Quién tiene tiempo para limpiar manualmente las implementaciones de prueba? Es fácil olvidarse de eliminar un experimento de una semana de antigüedad. La factura de la nube acabará subiendo por algo que olvidamos cerrar:
(Henning Jacobs:
Ziza:
(citas) Corey Quinn:
Mito: su cuenta de AWS depende de la cantidad de usuarios que tenga.
Hecho: Su puntuación de AWS es una función de la cantidad de ingenieros que tiene.
Ivan Kurnosov (en respuesta):
Hecho real: su puntuación de AWS es una función de la cantidad de cosas que olvidó deshabilitar/eliminar).
Conserje de Kubernetes (kube-janitor) ayuda a limpiar su clúster. La configuración del conserje es flexible para uso tanto global como local:
Las reglas de todo el clúster pueden definir el tiempo de vida máximo (TTL) para implementaciones de prueba/PR.
Los recursos individuales se pueden anotar con janitor/ttl, por ejemplo, para eliminar automáticamente el pico/prototipo después de 7 días.
Las reglas generales se definen en el archivo YAML. Su ruta se pasa a través del parámetro. --rules-file en kube-conserje. Aquí hay una regla de ejemplo para eliminar todos los espacios de nombres con -pr- en el nombre después de dos días:
El siguiente ejemplo regula el uso de la etiqueta de aplicación en los pods Deployment y StatefulSet para todos los nuevos Deployments/StatefulSets en 2020, pero al mismo tiempo permite la ejecución de pruebas sin esta etiqueta durante una semana:
- id: require-application-label
# удалить deployments и statefulsets без метки "application"
resources:
- deployments
- statefulsets
# см. http://jmespath.org/specification.html
jmespath: "!(spec.template.metadata.labels.application) && metadata.creationTimestamp > '2020-01-01'"
ttl: 7d
Ejecute una demostración por tiempo limitado durante 30 minutos en un clúster que ejecuta kube-janitor:
kubectl run nginx-demo --image=nginx
kubectl annotate deploy nginx-demo janitor/ttl=30m
Otra fuente de aumento de costes son los volúmenes persistentes (AWS EBS). Eliminar un Kubernetes StatefulSet no elimina sus volúmenes persistentes (PVC - PersistentVolumeClaim). Los volúmenes de EBS no utilizados pueden generar fácilmente costos de cientos de dólares al mes. Kubernetes Janitor tiene una función para limpiar PVC no utilizados. Por ejemplo, esta regla eliminará todos los PVC que no estén montados por un módulo y a los que no haga referencia StatefulSet o CronJob:
# удалить все PVC, которые не смонтированы и на которые не ссылаются StatefulSets
- id: remove-unused-pvcs
resources:
- persistentvolumeclaims
jmespath: "_context.pvc_is_not_mounted && _context.pvc_is_not_referenced"
ttl: 24h
Kubernetes Janitor puede ayudarle a mantener limpio su clúster y evitar que los costos de computación en la nube se acumulen lentamente. Para obtener instrucciones de implementación y configuración, siga README kube-conserje.
Reducir la escala durante las horas no laborales
Por lo general, los sistemas de prueba y preparación solo deben funcionar durante el horario comercial. Algunas aplicaciones de producción, como las herramientas de administración/back office, también requieren disponibilidad limitada y pueden desactivarse de la noche a la mañana.
Reducción de escala de Kubernetes (kube-downscaler) permite a los usuarios y operadores reducir el sistema durante las horas no laborables. Las implementaciones y StatefulSets pueden escalar a cero réplicas. Es posible que se suspendan CronJobs. Kubernetes Downscaler está configurado para un clúster completo, uno o más espacios de nombres o recursos individuales. Puede configurar "tiempo de inactividad" o, por el contrario, "tiempo de trabajo". Por ejemplo, para reducir el escalado tanto como sea posible durante las noches y los fines de semana:
image: hjacobs/kube-downscaler:20.4.3
args:
- --interval=30
# не отключать компоненты инфраструктуры
- --exclude-namespaces=kube-system,infra
# не отключать kube-downscaler, а также оставить Postgres Operator, чтобы исключенными БД можно было управлять
- --exclude-deployments=kube-downscaler,postgres-operator
- --default-uptime=Mon-Fri 08:00-20:00 Europe/Berlin
- --include-resources=deployments,statefulsets,stacks,cronjobs
- --deployment-time-annotation=deployment-time
Aquí hay un gráfico para escalar los nodos trabajadores del clúster los fines de semana:
Reducir la escala de ~13 a 4 nodos trabajadores ciertamente marca una diferencia notable en su factura de AWS.
Pero, ¿qué pasa si necesito trabajar durante el "tiempo de inactividad" del clúster? Ciertas implementaciones se pueden excluir permanentemente del escalamiento agregando la anotación downscaler/exclude: true. Las implementaciones se pueden excluir temporalmente mediante la anotación de reducción de escala/exclusión hasta con una marca de tiempo absoluta en el formato AAAA-MM-DD HH:MM (UTC). Si es necesario, todo el clúster se puede reducir implementando un pod con la anotación downscaler/force-uptime, por ejemplo, ejecutando nginx en blanco:
kubectl run scale-up --image=nginx
kubectl annotate deploy scale-up janitor/ttl=1h # удалить развертывание через час
kubectl annotate pod $(kubectl get pod -l run=scale-up -o jsonpath="{.items[0].metadata.name}") downscaler/force-uptime=true
ver LÉAME kube-downscaler, si está interesado en instrucciones de implementación y opciones adicionales.
Usar escalado automático horizontal
Muchas aplicaciones/servicios se enfrentan a un patrón de carga dinámico: a veces sus módulos están inactivos y otras veces funcionan a plena capacidad. Operar una flota permanente de cápsulas para hacer frente a la carga máxima máxima no es económico. Kubernetes admite el escalado automático horizontal en un recurso HorizontalPodAutoscaler (HPA). El uso de CPU suele ser un buen indicador de escalamiento:
Zalando ha creado un componente para conectar fácilmente métricas personalizadas para escalar: Adaptador de métricas de Kube (kube-metrics-adapter) es un adaptador de métricas genérico para Kubernetes que puede recopilar y ofrecer métricas personalizadas y externas para el escalado automático horizontal de pods. Admite el escalado basado en métricas de Prometheus, colas SQS y otras configuraciones. Por ejemplo, para escalar su implementación a una métrica personalizada representada por la aplicación misma como JSON en /metrics use:
Configurar el escalado automático horizontal con HPA debería ser una de las acciones predeterminadas para mejorar la eficiencia de los servicios sin estado. Spotify tiene una presentación con su experiencia y recomendaciones para HPA: escale sus implementaciones, no su billetera.
Reducir la sobreventa de recursos
Las cargas de trabajo de Kubernetes determinan sus necesidades de CPU/memoria a través de "solicitudes de recursos". Los recursos de CPU se miden en núcleos virtuales o, más comúnmente, en “millcores”, por ejemplo, 500 m implica 50 % de vCPU. Los recursos de memoria se miden en bytes y se pueden utilizar sufijos comunes, como 500Mi, que significa 500 megabytes. Las solicitudes de recursos "bloquean" la capacidad en los nodos trabajadores, lo que significa que un pod con una solicitud de CPU de 1000 m en un nodo con 4 vCPU dejará solo 3 vCPU disponibles para otros pods. [ 1 ]
Slack (exceso de reserva) es la diferencia entre los recursos solicitados y el uso real. Por ejemplo, un pod que solicita 2 GiB de memoria pero solo usa 200 MiB tiene ~1,8 GiB de memoria "excedente". El exceso cuesta dinero. Se puede estimar aproximadamente que 1 GiB de memoria redundante cuesta ~$10 por mes. [ 2 ]
Informe de recursos de Kubernetes (kube-resource-report) muestra el exceso de reservas y puede ayudarle a determinar el potencial de ahorro:
Informe de recursos de Kubernetes muestra el exceso agregado por aplicación y comando. Esto le permite encontrar lugares donde se pueden reducir las demandas de recursos. El informe HTML generado solo proporciona una instantánea del uso de recursos. Debe observar el uso de CPU/memoria a lo largo del tiempo para determinar las solicitudes de recursos adecuadas. A continuación se muestra un gráfico de Grafana para un servicio "típico" con uso intensivo de CPU: todos los pods utilizan significativamente menos de los 3 núcleos de CPU solicitados:
Reducir la solicitud de CPU de 3000 ma ~400 m libera recursos para otras cargas de trabajo y permite que el clúster sea más pequeño.
"El uso promedio de CPU de las instancias EC2 a menudo se sitúa en el rango porcentual de un solo dígito". escribe Corey Quinn. Mientras que para EC2 estimar el tamaño correcto puede ser una mala decisiónCambiar algunas consultas de recursos de Kubernetes en un archivo YAML es fácil y puede generar grandes ahorros.
Pero, ¿realmente queremos que la gente cambie los valores en los archivos YAML? No, ¡las máquinas pueden hacerlo mucho mejor! Kubernetes Escalador automático vertical de pod (VPA) hace precisamente eso: adapta las solicitudes de recursos y las limitaciones según la carga de trabajo. Aquí hay un gráfico de ejemplo de solicitudes de CPU de Prometheus (línea azul delgada) adaptadas por VPA a lo largo del tiempo:
Encerrada dorada de Fairwind es una herramienta que crea un VPA para cada implementación en un espacio de nombres y luego muestra una recomendación de VPA en su panel. Puede ayudar a los desarrolladores a configurar las solicitudes de CPU/memoria correctas para sus aplicaciones:
Por último, pero no menos importante, los costos de AWS EC2 se pueden reducir utilizando instancias Spot como nodos trabajadores de Kubernetes. [ 3 ]. Las instancias spot están disponibles con un descuento de hasta el 90 % en comparación con los precios On-Demand. Ejecutar Kubernetes en EC2 Spot es una buena combinación: debe especificar varios tipos de instancias diferentes para una mayor disponibilidad, lo que significa que puede obtener un nodo más grande por el mismo precio o por un precio menor, y la capacidad aumentada puede ser utilizada por cargas de trabajo de Kubernetes en contenedores.
¿Cómo ejecutar Kubernetes en EC2 Spot? Hay varias opciones: usar un servicio de terceros como SpotInst (ahora llamado "Spot", no me preguntes por qué), o simplemente agregar un Spot AutoScalingGroup (ASG) a tu clúster. Por ejemplo, aquí hay un fragmento de CloudFormation para un ASG puntual "con capacidad optimizada" con múltiples tipos de instancias:
¿Cuáles son sus mejores prácticas para ahorrar costos en la nube en Kubernetes? Por favor házmelo saber en Gorjeo (@try_except_).
[ 1 ] De hecho, quedarán utilizables menos de 3 vCPU ya que los recursos reservados del sistema reducen el rendimiento del nodo. Kubernetes distingue entre capacidad de nodo físico y recursos "aprovisionados" (Nodo asignable).
[ 2 ] Ejemplo de cálculo: una instancia m5.large con 8 GiB de memoria cuesta ~$84 por mes (eu-central-1, On-Demand), es decir bloquear 1/8 de nodo cuesta aproximadamente ~$10/mes.
[ 3 ] Hay muchas más formas de reducir su factura EC2, como Instancias reservadas, Plan de ahorro, etc. No cubriré esos temas aquí, ¡pero definitivamente debería investigarlos!