Blog de Amazon Web Services (AWS)

Monitoreo y administración de costos a través de Kubecost utilizando EKS Blueprints

Por Oscar Ramírez, Solutions Architect AWS México y 
 Román Lozano, Cloud Application Architect AWS México

 

Introducción

La adopción de Kubernetes ha sido notoria en los últimos años, así lo refleja la encuesta conducida por CNCF / FINOPS Foundation pero este cambio también ha representando desafíos para las organizaciones como por ejemplo la utilización adecuada de recursos de computo. En la encuesta mencionada 68% de los encuestados reportaron un repunte en los costos asociados a Kubernetes y esta tendencia es un producto de que hay mas adopción de arquitecturas “cloud native” y los despliegues de Kubernetes se están escalando cada vez dentro de las organizaciones, esto es un punto de inflexión porque ahora los despliegues basados en Kubernetes no son la excepción, sino un estándar, pero muchas organizaciones aun no tienen la practica de medir e incluso predecir los costos asociados a las aplicaciones basadas en Kubernetes.

Hallazgos de la encuesta de CNCF

  • 24% de los clientes encuestados no tienen mecanismos de monitoreo
  • 44% de los clientes encuestados solo lo hacen a través de estimados mensuales
  • La mayor parte del gasto (90%) en Kubernetes proviene de recursos de computo y de memoria

Los clientes que ejecutan Amazon EKS, pueden realizar un seguimiento de costos en los planos de control/datos usando informes de  AWS Cost and Usage Reports (AWS CUR) de forma inmediata y obtener una visón de alto nivel a nivel de servicio, pero muchas veces este nivel de detalle no es suficiente si lo que se desea es analizar y  tomar decisiones basadas en los costos a nivel de recurso en Kubernetes como por ejemplo: namespaces, cluster o pods.

A través de este blog presentaremos como implementar una solución de monitoreo de costos para cargas de trabajo basadas en Kubernetes con Kubecost en AWS utilizando EKS Blueprints.

EKS Blueprints

EKS Blueprints es una colección de módulos de Infraestructura como Código (IaC) que le ayudarán a configurar e implementar clusters de EKS con “baterías incluidas” de forma consistente en todas las cuentas y regiones. A través de EKS Blueprints se puede crear fácilmente un clúster EKS con add-ons de Amazon EKS, así como una amplia gama de add-ons populares de código abierto como por ejemplo:  Kubecost, Prometheus, Karpenter, Nginx, Traefik, AWS Load Balancer Controller, Fluent Bit, Keda, Argo CD y más.

 

Kubecost

Fundada en 2019, Kubecost se lanzó para brindar a los clientes visibilidad del gasto y la eficiencia de los recursos en los entornos de Kubernetes, y hoy ayuda a miles de equipos a enfrentar este desafío. Kubecost se construye sobre OpenCost, que recientemente fue aceptado como un proyecto Sandbox de Cloud Native Computing Foundation (CNCF), y cuenta con el apoyo activo de AWS.

Con este anuncio, los clientes de Amazon EKS pueden desplegar un paquete de Kubecost optimizado para EKS y asi obtener visibilidad de costos del clúster sin costo adicional por el uso de Kubecost y con la ventaja de poder obtener soporte de AWS. Kubecost permite a los usuarios ver los costos desglosados por los recursos de Kubernetes, incluidos namespaces, pods, nodos, etiquetas y más. Los clientes pueden proporcionar a sus equipos internos y unidades de negocio datos de costos de forma transparente y precisa en tiempo real y obtener recomendaciones personalizadas para la optimización de costos basadas en su entorno de infraestructura y patrones de uso del clúster.

Escenario

El escenario que se describe a continuación es un ambiente greenfield en la región us-west-2.

1. Pre-requisitos

  • Crear de cuenta en AWS como se describe en el enlace
  • Crear un entorno de desarrollo integrado (IDE) en AWS Cloud9 como se describe en el enlace utilizando una instancia del tipo “t3.small”
  • Instalar AWS CDK

EKS Blueprints actualmente soporta la versión v2.50.0 de CDK. Para validar la versión de AWS CDK ejecutar el siguiente comando:

cdk --version
2.50.0 (build 4c11af6)

En caso de que el entorno de AWS Cloud9 no tenga esta versión, se debe seguir el procedimiento de instalación y actualización de AWS CDK como se indica en el enlace

  • Instalar herramientas de Kubernetes, para mas detalle consultar el siguiente enlace
    • kubectl
    • aws-cli
    • jq, gettext, bash-completion y moreutils
  • Creación de un rol de Administrador en AWS Identity and Access Management (IAM) para el entorno de AWS Cloud9 de acuerdo al siguiente enlace y actualizarlo en el entorno de Cloud9 como se describe en el enlace

2.  Desplegar Kubecost con EKS Blueprints

  • Preparar la cuenta con AWS CDK

Configurar el ambiente de AWS Cloud9 y AWS Command Line Interface (CLI) con la información de la cuenta y la región de AWS a utilizar mediante el siguiente comando.

export ACCOUNT_ID=$(aws sts get-caller-identity --output text --query Account)
export AWS_REGION=$(curl -s 169.254.169.254/latest/dynamic/instance-identity/document | jq -r '.region')

  • Bootstrapping con AWS CDK

Hacer el bootstrapping de la cuenta con AWS CDK. Bootstrapping se refiere al proceso de aprovisionar los recursos necesarios para que AWS CDK pueda hacer el despliegue de los componentes en los ambientes de AWS.

cdk bootstrap --trust=$ACCOUNT_ID \
  --cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess \
  aws://$ACCOUNT_ID/$AWS_REGION

La siguiente imagen muestra el resultado que debemos obtener al completar el bootstrapping.

 

  • Crear un proyecto de AWS CDK

En primer lugar, debemos crear un repositorio de AWS CodeCommit el cual utilizaremos para almacenar el código de la aplicación que se desplegará con EKS Blueprints y que será nuestro repositorio fuente para la ejecución del pipeline.

aws codecommit create-repository --repository-name my-eks-kubecost 

Para crear una nueva aplicación con AWS CDK ejecutamos los siguientes comandos. En este ejemplo usaremos Typescript.

mkdir my-eks-kubecost
cd my-eks-kubecost
cdk init app --language typescript

  • Instalar los modulos de EKS Blueprints

EKS Blueprints hace uso de la última versión de Typescript, por lo que es necesario actualizar las librerías de Typescript con el siguiente comando.

npm i typescript@~4.8.4 

A continuación, se debe instalar los módulos de EKS Blueprints en nuestra aplicación.

npm i @aws-quickstart/eks-blueprints

De igual forma instalar las librerías del módulo de Kubecost para poder importarlas en nuestra aplicación.

$ npm install @kubecost/kubecost-eks-blueprints-addon

Dentro la estructura de directorios de nuestra aplicación, debemos modificar el archivo <proyecto>/lib/my-eks-kubecost-stack.ts como se muestra a continuación.

 

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as blueprints from '@aws-quickstart/eks-blueprints';
import { KubecostAddOn } from '@kubecost/kubecost-eks-blueprints-addon';
import * as cpactions from 'aws-cdk-lib/aws-codepipeline-actions';

export default class PipelineConstruct extends Construct {
  constructor(scope: Construct, id: string, props?: cdk.StackProps){
    super(scope, id)

    const account = props?.env?.account!;
    const region = props?.env?.region!;
    
    const addOnKubecost = new KubecostAddOn();
    const addOnAWSLBC = new blueprints.AwsLoadBalancerControllerAddOn();

    const blueprint = blueprints.EksBlueprint.builder()
    .account(account)
    .region(region)
    .addOns(new blueprints.ClusterAutoScalerAddOn,
            addOnKubecost,
            addOnAWSLBC)
    .teams();
  
    blueprints.CodePipelineStack.builder()
      .name("eks-kubecost-pipeline")
      .codeBuildPolicies(blueprints.DEFAULT_BUILD_POLICIES)
      .repository({
          codeCommitRepoName: 'my-eks-kubecost',
          targetRevision: 'main',
          codeCommitOptions:{
            trigger: cpactions.CodeCommitTrigger.EVENTS
          }
      })
      // WE ADD THE STAGES IN WAVE FROM THE PREVIOUS CODE
      .wave({
        id: "environment",
        stages: [
          { id: "develop", stackBuilder: blueprint.clone('us-west-2')}
        ]
      })
      .build(scope, id+'-stack', props);
  }
}

 

Es importante observar, que mediante EKS Blueprints podemos hacer uso de los complementos (add-ons) para crear los módulos de AutoScaler, AWS Load Balancer Controller y Kubecost.

Finalmente, debemos asegurar que podemos acceder al Construct de nuestro pipeline y para ello necesitamos importarlo y crear una instancia. Para ello debemos modificar el archivo <proyecto/bin/my-eks-kubecost.ts como se ilustra a continuación.

import * as cdk from 'aws-cdk-lib';
import PipelineConstruct from '../lib/my-eks-kubecost-stack';

const app = new cdk.App();
const account = process.env.CDK_DEFAULT_ACCOUNT!;
const region = process.env.CDK_DEFAULT_REGION!;
const env = { account, region }

new PipelineConstruct(app, 'pipeline', { env });

 

Para confirmar que nuestra aplicación y su despliegue están listos a través del pipeline debemos ejecutar el comando cdk list y debemos observar el siguiente resultado:

El comando cdk list mostrará los stacks identificados por cdk de acuerdo al modelo definido en el código de nuestra aplicación. Estos stack posteriormente producirán los templates de CloudFormation que se utilizarán para desplegar la aplicación. En nuestro ejemplo observamos que se define un pipeline.

  • Iniciar el pipeline

Ejecutar el “commit” de los cambios realizados en los pasos anteriores en el repositorio de AWS CodeCommit

git add .
git commit -m "Setting up EKS Kubecost deployment pipeline"
git branch -M main
git push origin main

Ejecutar el despliegue del stack con AWS CDK

A través de AWS CDK se realizará la instalación del cluster de EKS y los add-ons agregados como parte de la configuración IaC.

cdk deploy pipeline-stack

El despliegue del pipeline se mostrará en la consola de AWS CodePipeline en el siguiente enlace:

https://us-west-2.console.aws.amazon.com/codesuite/codepipeline/start?region=us-west-2

 

  • Acceso al cluster de EKS

Para obtener acceso al cluster de EKS por medio del AWS CLI, es necesario actualizar kubeconfig usando kubectl.

export KUBE_CONFIG=$(aws cloudformation describe-stacks --stack-name develop-develop-blueprint | jq -r '.Stacks[0].Outputs[] | select(.OutputKey|match("ConfigCommand"))| .OutputValue')
$KUBE_CONFIG

Para confirmar la correcta configuración ejecutamos el siguiente comando de kubectl.

kubectl get svc

3. Uso del tablero de monitoreo de Kubecost

  • Configuración para el acceso al tablero de monitoreo de costos de Kubecost

Para habilitar el acceso al tablero de monitoreo de Kubecost debemos generar un recurso de tipo “Kubernetes Ingress” el cual nos permitirá generar un AWS Application Load Balancer (ALB) como endpoint de entrada a los servicios de Kubecost. Lo primero que debemos hacer es validar el estatus de los pods de Kubecost, por default, estos se generan dentro del namespace kubecost.

kubectl get nodes -n kubecost

De igual forma debemos identificar el nombre del “Kubernetes Service” creado para poder acceder los pods, en este caso al tablero de Kubecost. Para ello podemos ejecutar el siguiente comando.

kubectl get svc -n kubecost

Como resultado de este comando, podemos identificar que el nombre del recurso del tipo  “Kubernetes Service” es kubecost-cost-analyzer-cost-analyzer. Utilizaremos este nombre para crear el recurso “Kubernetes Ingress” que nos permitirá generar un AWS ALB y acceder al tablero de Kubecost. Para ello, en este ejercicio utilizaremos un archivo manifiesto como el que se muestra en la siguiente imagen para poder enrutar las solicitudes basadas en el prefijo hacia el servicio de Kubecost existente.

 

Crear el recurso en el cluster de EKS

kubectl apply -f alb-cost-analyzer.yaml

Una vez creado el recurso,  se tendrá un nuevo AWS ALB como endpoint de entrada al tablero de Kubecost, como se muestra a continuación.

 

  • Explorar el tablero de Kubecost

En el menú de la izquierda dentro del tablero de Kubescost, a través de la opción “Cost Allocation” se pueden visualizar los costos de EKS de forma agrupada por diferentes categorías como, por ejemplo: namespaces, nodos o por cualquier otro tipo de recurso estándar de Kubernetes como se ilustra en la siguiente imagen.

El desglose de costos permite visualizar una granularidad a nivel de recurso como CPU, memoria, red, almacenamiento, balanceadores de carga, lo que permite identificar los principales contribuyentes al costo total.

La opción “Aggregate by” localizada en la parte superior del tablero permite seleccionar varias categorías para agrupar los costos. Por ejemplo: namespace y pod y así poder visualizar los costos a nivel pod en los namespaces del cluster.

De igual forma, se pueden analizar los costos de los servicios que se ejecutan en cada uno de los nodos del cluster de EKS.

Una funcionalidad muy útil de Kubecost, es la posibilidad de hacer “zoom-in” de los costos, por ejemplo, al filtrar por un namespace especifico, se actualizan los resultados con el detalle específico.

En la parte inferior de la pantalla, en la sección “Controllers”, se puede visualizar un análisis detallado de costos a nivel de deployment de Kubernetes en dicho namespace.

 

En la opción “Savings” es posible visualizar las recomendaciones que Kubecost determina basado en el histórico y perfil del cluster de EKS.

En la opción “Breakdown” es posible visualizar el detalle a nivel de contenedor y poder analizar a nivel de pod el consumo de recursos actual y los ahorros potenciales asociados a mejoras en la eficiencia de los recursos de computo utilizados.

 

Al ver el detalle a nivel de pod, es posible visualizar el histórico de utilización de recursos directamente en el tablero de Grafana por cada cada uno, con lo que se obtiene la granularidad mas fina para un cluster de Kubernetes.

Es importante mencionar que Kubecost utiliza Prometheus como servidor de métricas y Grafana como visualizador, ambos proyectos de código abierto ampliamente utilizados. Ambos componentes son instalados automáticamente a través de AWS CDK con el add-on de Kubecost, con lo que se reduce significativamente la configuración necesaria para tener Kubecost listo para ser consultado.

Kubecost es una excelente opción para monitorizar en tiempo real los costos en un cluster de EKS en AWS y tomar decisiones orientadas a la optimización de costos sin impactar la disponibilidad o el estado del cluster

Para realizar cálculos de asignación de costos para un clúster de Amazon EKS, Kubecost recupera la información de precios públicos de los servicios y recursos de AWS de la API de lista de precios de AWS. También puede integrar Kubecost con AWS CUR para mejorar la precisión de la información de precios específica de su cuenta de AWS (por ejemplo, programas de descuento para empresas, uso de instancias reservadas, planes de ahorro y uso de computo Spot).

 

5. Limpieza

El uso de los recursos creados como parte de este blog incurre en costos asociados, si desea eliminarlos, ejecute el siguiente comando de AWS CDK para eliminar el stack desde la consola de AWS Cloud9

cdk destroy pipeline-stack

Costos

Para poder estimar el costo aproximado de esta solución, le recomendamos consultar los precios de Amazon EKS

Conclusión

Kubecost provee una perspectiva muy granular  (a nivel de recurso de Kubernetes) de los costos incurridos en un cluster de EKS permitiendo una administración en tiempo real orientada a la toma de decisiones en la gestión del cluster. Por otra parte, la información histórica enriquecida o contextualizada con los precios de los servicios permite obtener recomendaciones orientadas a la optimización de costos que representan un beneficio directo para los clientes que usan EKS.

Finalmente, el uso de un add-on de EKS Blueprints para desplegar Kubecost en un cluster de EKS reduce significativamente el tiempo y recursos necesarios para su configuración y puesta en marcha, lo cual acelera su adopción.

Para obtener más información sobre EKS Blueprints, puede consultar la documentación de EKS Blueprints y Kubecost

Referencias

 


Acerca de los autores

Oscar Ramírez es Solutions Architect en AWS México

 

 

 

 

Román Lozano  es Cloud Application Architect en AWS México

 

 

 

 

Revisores

Saúl Carranza es Senior Solutions Architect con especialidad en Contenedores en AWS México

 

 

 

 

Alan Oberto Jimenez es Cloud Application Architect en AWS Alemania