Kubernetes: EC2 Spot Instances in EKS

Una de las tareas que tarde o temprano siempre hace acto de presencia en el Journey to Cloud de una organización, es aquella enfocada a la reducción de costes. Al fin y al cabo, el supuesto ahorro derivado de la economía de escala, pago por uso (OPEX) o a la ausencia de una inversión inicial en infraestructura (CAPEX), era uno de los pilares centrales sobre los que sustentar la transformación digital del negocio.

El problema es que rara vez se realiza un análisis exhaustivo del coste real de un entorno, ya sea por falta de tiempo, conocimiento o una mezcla de ambos. Para sorpresa de nadie, casi todo en la nube lleva un coste asociado, por mínimo que pueda parecer, pero que en conjunto pueden provocar un desagradable disgusto debido a una factura sustancialmente mayor de la esperada.

Por ello, en el presente artículo se pretender detallar cómo hacer uso de las EC2 Spot Instances en EKS, con las que arañar algunos euros en aquellos casos de uso en los que sea posible.

Caso de uso

Se requiere aprovisionar un cluster de EKS compuesto única y exclusivamente por nodos de tipo EC2 Spot Instances.

Amazon EC2 Spot Instances

Tal y como señala la documentación oficial de AWS, Amazon EKS es un servicio administrado que permite ejecutar Kubernetes en AWS sin necesidad de instalar ni operar el control plane o los worker nodes. Es otras palabras, es el PaaS de Kubernetes de la nube de Amazon.

Una de las configuraciones a realizar cuando se aprovisiona un EKS, es el tipo de maquina sobre la que correrán las cargas de trabajo o pods, y aquí es precisamente donde entran en juego las EC2 Spot Instances. Este tipo de maquinas permiten aprovechar la capacidad de EC2 sin usar en la nube de AWS, con un descuento de hasta el 90 % en comparación con los precios on-demand, aunque el ahorro real tiende a ser del 30-70%. Así, Amazon publica en la siguiente pagina el precio de estas, con una frecuencia de actualización de 5 minutos.

La magia reside en que Amazon puede interrumpir su ejecución cuando requiera de ellas, con una notificación previa de dos minutos. Es decir, en cualquier momento AWS puede “quitarte” la maquina si así lo precisa, por lo que su uso solo se recomienda para aquellas aplicaciones stateless y tolerantes a fallos. De ahí a que en la introducción se matizara que puede suponer un ahorro de costes, pero solo en aquellos casos de uso en los que fuera posible, como, por ejemplo, en aquellos entornos no productivos en los que las caídas esporádicas no supongan un contratiempo importante a la organización.

Fuente Original

EKS Cluster provisioning

El primer paso consiste en configurar el uso de las Spot Instances en el grupo de nodos que darán vida al EKS. A diferencia de otros artículos publicados en esta misma casa, esta vez se escenificará como IaC, en concreto, vía Terraform.

Tomando como base la documentación oficial de Terraform, a continuación se muestra un pequeño fragmento de código en el que se configura el aws_eks_node_group, con el parámetro capacity_type como SPOT, el factor diferencial en este asunto. Con este sencillo cambio, AWS aprovisionara las maquinas como EC2 Spot Instances.

resource "aws_eks_node_group" "eks_spot_node_group" {
  cluster_name    = aws_eks_cluster.eks-cluster.name
  node_group_name = "eks_spot_node_group-001"
  node_role_arn   = aws_iam_role.eks-node-iam.arn
  subnet_ids      = var.subnet_ids
  scaling_config {
    desired_size = var.spot_workers_scaling_config.desired_size
    max_size     = var.spot_workers_scaling_config.max_size
    min_size     = var.spot_workers_scaling_config.min_size
  }
  capacity_type  = "SPOT"
  instance_types = var.spot_workers_instance_types

  # Ensure that IAM Role permissions are created before and deleted after EKS Node Group handling.
  # Otherwise, EKS will not be able to properly delete EC2 Instances and Elastic Network Interfaces.
  depends_on = [
    aws_iam_role_policy_attachment.example-AmazonEKSWorkerNodePolicy,
    aws_iam_role_policy_attachment.example-AmazonEKS_CNI_Policy,
    aws_iam_role_policy_attachment.example-AmazonEC2ContainerRegistryReadOnly,
  ]
}

En el caso de que no se quiera crear un modulo de Terraform personalizado para el EKS, siempre es posible hacer uso de aquellos desarrollados por la comunidad. En este sentido, se recomienda encarecidamente el uso del módulo terraform-aws-eks, el cual también tiene soporte para las Spot Instances.

A continuación se muestra un sencillo ejemplo de configuración basado en la documentación oficial del mismo.

module "my-cluster" {
  source          = "terraform-aws-modules/eks/aws"
  cluster_name    = "my-cluster"
  cluster_version = "1.17"
  subnets         = ["subnet-abcde012", "subnet-bcde012a", "subnet-fghi345a"]
  vpc_id          = "vpc-1234556abcdef"

  worker_groups = [
    {
      name                = "spot-1"
      spot_price          = "0.199"
      instance_type       = "c4.xlarge"
      asg_max_size        = 20
      kubelet_extra_args  = "--node-labels=node.kubernetes.io/lifecycle=spot"
      suspended_processes = ["AZRebalance"]
    }
  ]
}

A diferencia del ejemplo anterior, en este se emplea un parámetro spot_price con el que se determina el precio máximo a pagar por una Spot Instance. Si no especifica un precio máximo, el precio máximo predeterminado es el precio on-demand, siendo esta la recomendación de Amazon.

Spot Instance Interrupt Handler

Una vez aprovisionado el cluster EKS, es el momento de instalar el k8s-spot-termination-handler, un daemonset encargado de consultar el EC2 Spot Instance Termination Notices, de tal forma que cuando AWS requiera de la instancia, el nodo pueda ser correctamente drenado antes de la terminación.

Su instalación mediante Helm no guarda misterio alguno.

helm install stable/k8s-spot-termination-handler

Cluster Autoscaler

Finalmente, no queda mas que instalar el cluster autoscaler, un pod encargado de gestionar todas las actividades relacionadas con el escalado de los nodos, en base a los parámetros desired_size, max_size y min_size descritos previamente. Su instalación es trascendental, ya que sin él no se reemplazarían automáticamente las instancias perdidas a causa de las terminaciones o interrupciones.

Este proceso de instalación también puede llevarse a cabo vía Helm, aunque en este caso es necesario facilitar un conjunto de variables.

helm install stable/cluster-autoscaler --values=./values.yaml

El contenido del ficheros values.yaml debería ser el siguiente, sustituyendo las dos variables destacadas.

rbac:
  create: true

cloudProvider: aws
awsRegion: SET_AWS_REGION

autoDiscovery:
  clusterName: SET_EKS_CLUSTER_NAME
  enabled: true

Conclusiones

En conclusión, las Spot Instance son un tipo de maquinas que permiten aprovechar la capacidad de EC2 sin usar en la nube de AWS, con un descuento real del 30-70%. Ahora bien, Amazon puede interrumpir su ejecución cuando requiera de ellas, por lo que su uso solo se recomienda para aquellas aplicaciones stateless, tolerantes a fallos y en entornos no productivos en los que las caídas esporádicas no supongan un contratiempo importante a la organización.

En el artículo se muestra un caso de uso muy muy sencillo, pero tened en cuenta que es posible jugar con esto, mezclando instancias de distintos tipos o moviendo pods entre ellas.

Referencias

Se recomienda encarecidamente leer los siguientes artículos que han servido de base para el escrito:

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s