DEV Community

Cover image for Ahorra con Amazon EKS
Javi Mora for AWS Español

Posted on

Ahorra con Amazon EKS

Cuando nos planteamos el diseño de una nueva arquitectura para nuestra plataforma uno de los aspectos que suele influenciar en el diseño es el coste. Pero ya no solo es el coste, sino también el impacto medioambiental que supone el hecho de optimizar los recursos de los que disponemos. En muchas ocasiones tenemos distintos entornos que no tienen porque ser usados las 24 horas (desarrollo, qa, staging, ...). En este caso, os voy a mostrar cómo poder ahorrar costes haciendo un scale down de los nodos de vuestros clusters de kubernetes en AWS a través de una Lambda, de esta manera podréis optimizar costes con aquellos entornos que no necesitáis tener encendidos durante todo el día.

Image description

Para realizar este proyecto usaremos Serverless Framework para crear y desplegar nuestro pequeño sistema de apagado automático, el cual realizaremos en NodeJS con Typescript.

Instalar serverless framework

Lo primero de todo es instalar serverless framework con el siguiente comando desde un terminal

npm install -g serverless
Enter fullscreen mode Exit fullscreen mode

Una vez instalado creamos nuestro proyecto en un nuevo directorio ejecutamos el siguiente comando:

sls create -t aws-nodejs-typescript

Enter fullscreen mode Exit fullscreen mode

Esto nos creará un proyecto serverless con typescript. Al abrirlo veréis como ha creado el serverless.ts y una función de ejemplo “hello”. En el fichero de serverless.ts debéis poner los datos referentes a vuestra cuenta de aws.

Ahora ya podéis probar que el proyecto se ha creado correctamente invocando la función hello desde local:

sls invoke local -f start
Enter fullscreen mode Exit fullscreen mode

Lambda

Una vez que comprobamos que el ejemplo funciona, ya podemos empezar a modificar nuestra lambda, o bien podemos crear una nueva. Lo primero que necesitamos es la sdk de aws:

npm i aws-sdk
Enter fullscreen mode Exit fullscreen mode

y luego añadimos este código a nuestra lambda:

import type { ValidatedEventAPIGatewayProxyEvent } from '@libs/api-gateway';
import { formatJSONResponse } from '@libs/api-gateway';
import { middyfy } from '@libs/lambda';
import { NodegroupScalingConfig, UpdateNodegroupConfigRequest, UpdateNodegroupConfigResponse } from 'aws-sdk/clients/eks';
import { AWSError, EKS } from 'aws-sdk';

import schema from './schema';
import { PromiseResult } from 'aws-sdk/lib/request';

const stop: ValidatedEventAPIGatewayProxyEvent<typeof schema> = async (event) => {

  const CLUSTER_NAME:string = '[CLUSTER_NAME]';
  const NODE_GROUP_NAME:string = '[NODE_GROUP_NAME]';

  let nodeGroupConfig:NodegroupScalingConfig = {
    desiredSize: 0,
    maxSize: 1,
    minSize: 0

  };

  let nodeGroupRequest:UpdateNodegroupConfigRequest = {
    clusterName: CLUSTER_NAME,
    nodegroupName: NODE_GROUP_NAME,
    scalingConfig: nodeGroupConfig
  };


  let response:PromiseResult<UpdateNodegroupConfigResponse, AWSError> = await new EKS().updateNodegroupConfig(nodeGroupRequest).promise();
  console.log(response);


  return formatJSONResponse({
    message: 'NodeGroupScaling updated to 0',
    event,
  });
};

export const main = middyfy(stop);
Enter fullscreen mode Exit fullscreen mode

En el código podemos ver cómo modificamos la configuración de escalado de los nodos, poniéndola a 0. Antes debemos modificar los datos para indicar cual es nuestro cluster y nuestro node group name.

Lambda scheduler

La lambda podemos ejecutarla manualmente, a través de una llamada a un endpoint de API Gateway o a través de una tarea periódica con CloudWatch Rules.

Para ello vamos al archivo index.ts y vemos que está configurado para llamar a la lambda a través de un endpoint de API Gateway, sustituimos ese código por el siguiente:

import { handlerPath } from '@libs/handler-resolver';
export default {
  handler: `${handlerPath(__dirname)}/handler.main`,
  events: [
    {
      schedule: 'cron(0 19 ? * MON-FRI *)',
    }
  ],
};
Enter fullscreen mode Exit fullscreen mode

De esta manera nuestra lambda hará un scale down cada día, de lunes a viernes a las 7 de la tarde.

Lambda role (I)

Para que la lambda tenga acceso a nuestro cluster de eks debemos hacer que su rol tenga acceso a la policy que permite modificar la configuración de escalado de los nodos:

provider: {
    name: 'aws',
    iamRoleStatements: [
      {
        'Effect': 'Allow',
        'Action': ['eks:UpdateNodegroupConfig'],
        'Resource': '*'
      }
    ],
Enter fullscreen mode Exit fullscreen mode

Deploy

Ahora tenemos todo nuestro código preparado para ralizar la función que queremos, solo queda desplegarlo, y es tan simple como hacer lo siguiente:

sls deploy
Enter fullscreen mode Exit fullscreen mode

Image description

Lambda role (II)

Una vez desplegados podemos ver que la lambda tiene asignado un rol

Image description

Debemos copiar el arn de ese rol, ya que debemos configurar nuestro cluster para permitir a ese rol realizar cambios, tal y como se explica en la documentación oficial https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html

eksctl create iamidentitymapping \
    --cluster cluster-name \
    --region=xx-xxxx-x \
    --arn arn:aws:iam::0000000000000:role/eks-management-dev-xx-xxxx-x-lambdaRole \
    --group group:example
Enter fullscreen mode Exit fullscreen mode

Esto creará un registro nuevo en el mapa de identidades de nuestro cluster

eksctl get iamidentitymapping --cluster cluster-name --region=xx-xxxx-x
Enter fullscreen mode Exit fullscreen mode

y con esa acción podremos comprobar que realmente se ha añadido. Con esto ya hemos conseguido dar acceso a nuestra lambda.

Os dejo la documentación oficial donde se detalla como funciona la API de la SDK de AWS: https://docs.aws.amazon.com/eks/latest/APIReference/API_UpdateNodegroupConfig.html

Os dejo también el repositorio GitHub donde está subido este ejemplo: https://github.com/fjaviermoradiaz/aws-eks-manager

Top comments (1)

Collapse
 
israel870730 profile image
Israel

Hola, me gusto mucho el tema sobre el que trata esta entrada, ahora tengo una duda, ¿cuál es la diferencia entre usar esta opción que propones usando Lambda, la cual veo que está genial, pero un poco compleja, a usar el ASG del clúster y programarle una tarea en "Scheduled actions" para que haga ese mismo proceso todos los días?

Slds y gracias por la entrada, todo lo que sea optimización de costos siempre es bienvenido :)