<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Javi Mora</title>
    <description>The latest articles on DEV Community by Javi Mora (@jvimora).</description>
    <link>https://dev.to/jvimora</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1260842%2Fbba45b05-cce3-4e88-b1cf-39c9c508b601.jpeg</url>
      <title>DEV Community: Javi Mora</title>
      <link>https://dev.to/jvimora</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jvimora"/>
    <language>en</language>
    <item>
      <title>Aumenta la disponibilidad de tus sistemas Legacy</title>
      <dc:creator>Javi Mora</dc:creator>
      <pubDate>Tue, 09 Jul 2024 07:00:00 +0000</pubDate>
      <link>https://dev.to/aws-espanol/aumenta-la-disponibilidad-de-tus-sistemas-legacy-4ip3</link>
      <guid>https://dev.to/aws-espanol/aumenta-la-disponibilidad-de-tus-sistemas-legacy-4ip3</guid>
      <description>&lt;p&gt;Muchos de nosotros trabajamos con servicios legacy o bien servicios que no son capaces de escalar correctamente, ya sea por problemas de diseño o por requerimientos técnicos. Estos sistemas que tienen esas dificultad para escalar son mas propensos a sufrir paradas de servicio, lo que supone un gran problema, sobre todo para los sistemas que reciben notificaciones asíncronas de otros sistemas.&lt;br&gt;
Es en este último tipo de comunicaciones en el que nos vamos a centrar en este artículo.&lt;/p&gt;

&lt;p&gt;Si tenemos un sistema, obsoleto, legacy, mal construido o bien que no hemos podido perfeccionarlo todo lo que hemos podido, y que recibe comunicaciones asíncronas, las cuales no podemos perder ya que cada mensaje no recibido supone una pérdida de información, no hace falta que invirtamos una gran cantidad de tiempo y/o dinero en actualizar nuestro sistema. Podemos aplicar una solución muy sencilla, muy barata y muy fácil de mantener que resolverá todos nuestros problemas ante posibles caídas. Esta solución también se puede aplicar a instancias de tipo Spot, que únicamente reciben comunicaciones asíncronas, y de esta manera poder tener este tipo de instancias incluso en entornos productivos, reduciendo los costes considerablemente.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solución
&lt;/h2&gt;

&lt;p&gt;Nuestra solución se basa en añadir una capa serverless sobre nuestra aplicación, que nos permita gestionar las comunicaciones asíncronas a hacia nuestra API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw6vfj7bfgm749xo3slro.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw6vfj7bfgm749xo3slro.png" alt="Capa superior a nuestra API" width="248" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Este diseño permitirá una comunicación en tiempo real con nuestra API y un backup en caso de caída del servicio que nos permitirá recuperar la comunicación con los mensajes perdidos durante la caída.&lt;/p&gt;

&lt;h2&gt;
  
  
  Arquitectura
&lt;/h2&gt;

&lt;p&gt;Para implementar esta solución descrita anteriormente, solo necesitamos implementar 3 servicios muy comunes dentro del catálogo de servicios de AWS&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Amazon API Gateway&lt;/li&gt;
&lt;li&gt;AWS Lambda&lt;/li&gt;
&lt;li&gt;Amazon SQS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6f6zs8pusnd25ooypb1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo6f6zs8pusnd25ooypb1.png" alt="Arquitectura servicios asíncronos" width="578" height="129"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Con estos tres servicios conseguiremos una comunicación asíncrona con disponibilidad total (99,9% de disponibilidad cada uno de ellos)&lt;/p&gt;

&lt;p&gt;Existe la posibilidad incluso de ahorrarnos uno de los tres servicios descritos anteriormente y hacer uso únicamente de Amazon API Gateway y Amazon SQS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffhuqgsrkitoaqsfim9ym.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffhuqgsrkitoaqsfim9ym.png" alt="Arquitectura servicios asíncronos v2" width="483" height="126"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Este caso no lo recomendamos ya que el mensaje que llega a nuestra API debe tener una estructura determinada para poder ser enviado directamente al servicio de SQS. Con el uso del servicio de Lambda conseguimos una mayor flexibilidad, pudiendo modificar el mensaje, añadir control de excepciones, etc. &lt;/p&gt;

&lt;h2&gt;
  
  
  Comunicación con nuestra API
&lt;/h2&gt;

&lt;p&gt;Ahora toca comunicar la nueva arquitectura con nuestra API. Existen varias opciones para establecer esta comunicación, por un lado podemos enviar los mensajes recibidos directamente a nuestra API o podemos hacer que nuestra API vaya a buscar los mensajes a nuestra servicio de mensajería. Ambas opciones son igualmente válidas y dependería de nuestra solución el usar una u otra opción.&lt;/p&gt;

&lt;h3&gt;
  
  
  SQS to API
&lt;/h3&gt;

&lt;p&gt;Esta sería la comunicación mas lógica en un inicio, donde cada mensaje que llega a nuestra nueva capa de servicios serverless es enviada directamente a nuestra API&lt;/p&gt;

&lt;p&gt;Y aquí también tenemos dos opciones. En la primera imagen vemos como el mensaje que llega a nuestro servicio de colas puede ser enviado a nuestra API. Amazon SQS permite implementar Listeners dentro de nuestra API que permita recibir los mensajes que se encolan en nuestro servicio.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3orrpi7x5pceli8p5qml.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3orrpi7x5pceli8p5qml.png" alt="Envío de mensajes a nuestra API - Listener" width="800" height="139"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pero en el caso que la tecnología usada en nuestra API no permita conectarnos a nuestro servicio de SQS a través del Listener, podemos optar por una segunda opción, la cual sería añadir una Lambda que nos permita establecer la comunicación entre nuestro servicio de colas y nuestra API.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fscf7cxj5u8zdf7stup08.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fscf7cxj5u8zdf7stup08.png" alt="Envío de mensajes a nuestra API - Lambda" width="800" height="116"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  API to SQS
&lt;/h3&gt;

&lt;p&gt;La segunda opción se trata de delegar la responsabilidad a nuestra API de la lectura de mensajes, es una opción menos usada pero que es efectiva si queremos tener el control de cuanta información queremos procesar o si queremos procesarla a una hora determinada del dia.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0gkvcu3igfilc16tbxh4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0gkvcu3igfilc16tbxh4.png" alt="Lectura de mensajes en el servicio de SQS" width="791" height="138"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Otra de las ventajas de esta última opción, es que en el caso de caída de nuestra API, los mensajes no serán leídos, y cuando nuestra API vuelva a estar operativa se volverán a procesar.&lt;/p&gt;

&lt;p&gt;Pero entonces, ¿qué pasaría si decidimos implementar la primera de las opciones descritas?&lt;/p&gt;

&lt;h3&gt;
  
  
  SQS to API - DLQ
&lt;/h3&gt;

&lt;p&gt;En el caso que nuestra API no esté disponible, hay mecanismos (o configuraciones) que nos permiten reprocesar nuestros mensajes en otro momento. &lt;/p&gt;

&lt;p&gt;Es el caso de las colas DLQ (Amazon SQS Dead Letter Queues), son colas a la que podemos enviar los mensajes fallidos de una cola SQS. Podemos establecer un número de reintentos de lectura en nuestra cola SQS y una vez realizado ese número de reintentos el mensaje de la SQS pasaría automáticamente a la DLQ, cuyo comportamiento es el mismo que el de una SQS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7xcd34fzu5lg9qpzhydr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F7xcd34fzu5lg9qpzhydr.png" alt="SQS Dead Letter Queue" width="800" height="269"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Los mensajes permanecerán en esta cola hasta que nuestra API vuelva a estar disponible, y cuando eso ocurra, podremos volver a leer esos mensajes, ya sea accediendo a la DLQ desde nuestra API&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn569443h908rf87kc4p4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fn569443h908rf87kc4p4.png" alt="Lectura de API a DLQ" width="800" height="302"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O bien, haciendo uso de una lambda que se encargue de comprobar la disponibilidad de nuestra API y una vez esté disponible sea la encargada de leer y enviar de nuevo los mensajes de la DLQ a nuestra API&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frc0ymlrbwpu2g1fjyv9z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frc0ymlrbwpu2g1fjyv9z.png" alt="Lectura de API a DLQ - Lambda" width="800" height="306"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Y con esta simple arquitectura podemos implementar una capa asíncrona y con una disponibilidad del 99,9% sin necesidad de hacer grandes cambios en nuestra API.&lt;/p&gt;

&lt;p&gt;En el siguiente post crearemos esta infraestructura con CDK y Python paso a paso y lo tendréis disponible en GitHub para que podáis adaptar y desplegar esta solución en pocos minutos.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>legacy</category>
      <category>serverless</category>
      <category>availability</category>
    </item>
    <item>
      <title>WebSockets con Api Gateway</title>
      <dc:creator>Javi Mora</dc:creator>
      <pubDate>Fri, 19 Apr 2024 07:26:21 +0000</pubDate>
      <link>https://dev.to/aws-espanol/websockets-con-api-gateway-2329</link>
      <guid>https://dev.to/aws-espanol/websockets-con-api-gateway-2329</guid>
      <description>&lt;p&gt;¿Alguna vez has querido que tu app hable con tus usuarios en tiempo real, como por arte de magia? Pues bien, ¡hoy es tu día de suerte! En este post vamos a meternos de lleno en cómo darle súper poderes a tus proyectos usando WebSockets con AWS. Vamos a usar dos herramientas muy conocidas dentro del Cloud de AWS: API Gateway y Lambda. Te voy a llevar paso a paso para que crees tu propio websocket en menos de 10 minutos. &lt;/p&gt;

&lt;h2&gt;
  
  
  Crear el proyecto con cdk
&lt;/h2&gt;

&lt;p&gt;Vamos a crear el proyecto con cdk y vamos a implementarlo con python, para ello vamos a crear nuestro directorio del proyecto y crearemos el proyecto con cdk&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 shell
mkdir websocket-poc
cd websocket-poc
cdk init app --language python


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Ahora activamos el entorno virtual&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 shell
source .venv/bin/activate


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Y por último instalamos las dependencias necesarias:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 shell
pip install -r requirements.txt


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Este sería el contenido de nuestro requirements.txt&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;

aws-cdk-lib==2.114.1
constructs&amp;gt;=10.0.0,&amp;lt;11.0.0


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Creación de lambda
&lt;/h2&gt;

&lt;p&gt;Usaremos una lambda para enviar un mensaje a través de nuestro websocket, para ello en nuestro proyecto cdk, y dentro de nuestro stack creamos la lambda con el siguiente código:&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 python
lambda_function = lambda_.Function(
            self, 'WebSocketHandler',
            runtime=lambda_.Runtime.PYTHON_3_8,
            handler='ws_function.handler',
            code=lambda_.Code.from_asset('./lambda'),
            timeout=core.Duration.seconds(10)
        )

lambda_function.add_to_role_policy(iam.PolicyStatement(
            actions=["execute-api:ManageConnections"],
            resources=["arn:aws:execute-api:REGION:ACCOUNT-ID:API-ID/STAGE-NAME/*"],
            effect=iam.Effect.ALLOW
        ))


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;execute-api:ManageConnections&lt;/strong&gt; permite a funciones autorizadas gestionar conexiones de clientes en API Gateway WebSockets.&lt;/p&gt;

&lt;p&gt;Y este sería el código de la lambda, bastante sencillo, simplemente recibimos los parámetros de conexión y la url del websocket, esto podría ser fijo, pero en caso que tengamos mas de un websocket podríamos re-utilzar el código de la lambda, y por último, enviamos el mensaje "&lt;strong&gt;Hello, WebSocket!&lt;/strong&gt;"&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 python
import boto3

def handler(event, context):
    connection_id = event['requestContext']['connectionId']
    gatewayapi = boto3.client("apigatewaymanagementapi",
                              endpoint_url = "https://" + event["requestContext"]["domainName"] + "/" + event["requestContext"]["stage"])

    post_data = "Hello, WebSocket!"

    gatewayapi.post_to_connection(ConnectionId=connection_id, Data=post_data.encode('utf-8'))

    return {
        'statusCode': 200,
        'body': 'Message sent'
    }



&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Creación de la API
&lt;/h2&gt;

&lt;p&gt;Ahora vamos a crear nuestra API que permitirá el envío de mensajes por websocket.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 python
api = apigw.WebSocketApi(self, "WebsocketApi")


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Luego creamos un stage dentro de nuestra api:&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 python
stage = apigw.WebSocketStage(
            self, 'DevStage',
            web_socket_api=api,
            stage_name='dev',
            auto_deploy=True
        )


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Y por último añadimos una ruta específica (sendMessage" al websocket de la api y lo vinculamos a la función lambda que hemos creado previamente.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
 python
api.add_route("sendMessage",
  integration=WebSocketLambdaIntegration("SendMessageIntegration", lambda_function)
)


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  Outputs
&lt;/h2&gt;

&lt;p&gt;Necesitamos conocer la url de nuestro websocket para poder establecer una comunicación con el, por lo que hacemos que nos la muestre en el terminal cuando complete el despliegue de la api&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;

&lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;CfnOutput&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;WebSocketURL&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;stage&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;


&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
  
  
  WebScocket client
&lt;/h2&gt;

&lt;p&gt;Ahora vamos a usar una herramienta para simular nuestro cliente de websocket, podríamos crear una web o una app para probarlo, pero esta herramienta nos permite probar nuestro websocket mucho mas rápido y de una forma mas sencilla.&lt;/p&gt;

&lt;p&gt;La herramienta es &lt;strong&gt;websocketking&lt;/strong&gt; (&lt;a href="https://websocketking.com/" rel="noopener noreferrer"&gt;https://websocketking.com/&lt;/a&gt;) y es muy fácil de usar.&lt;/p&gt;

&lt;p&gt;Lo primero que debemos hacer es añadir la url de nuestro websocket que nos ha devuelto el deploy de nuestro proyecto cdk. En nuestro caso sería &lt;strong&gt;wss://kiyi70kcll.execute-api.eu-west-1.amazonaws.com/dev&lt;/strong&gt; &lt;br&gt;
y le damos a conectar&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsr0gxtjuhv83jem9c257.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsr0gxtjuhv83jem9c257.png" alt="Conectar websocket"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;una vez conectados enviaremos un mensaje (puede estar vacio),simplemente es la forma mas sencilla de conocer nuestro connectionId que lo necesitaremos luego en el test de la lambda para poder enviar un mensaje a través del websocket.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmwycuekv4gztl1yico0q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmwycuekv4gztl1yico0q.png" alt="Enviar mensaje al ws"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Forbidden"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"connectionId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"WbqM9csoDoECF9w="&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"requestId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"WbqUVE-OjoEFwjw="&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;


&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;ahora copiamos nuestro connectionId y creamos un test en la lambda&lt;/p&gt;

&lt;p&gt;y ahora enviaremos un mensaje a nuestro websocket con este JSON&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"requestContext"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"connectionId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"WbqM9csoDoECF9w="&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"domainName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kiyi70kcll.execute-api.eu-west-1.amazonaws.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"stage"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"dev"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;



&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;donde tenemos:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;connectionId&lt;/strong&gt;: obtenido previamente&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;domainName&lt;/strong&gt;: url de nuestro websocket&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;stage&lt;/strong&gt;: stage de nuestra api&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzs6tc4e7hmnrr00dctho.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzs6tc4e7hmnrr00dctho.png" alt="Lambda test"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;y realizamos nuestro test ....&lt;/p&gt;

&lt;p&gt;comprobamos que nuestra lambda se ha ejecutado correctamente&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fygnc3cx92skdzyd1cc59.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fygnc3cx92skdzyd1cc59.png" alt="Lambda response"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;y comprobamos nuestra aplicación cliente de websocket&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frwoa4xx3wiihosop3yx0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frwoa4xx3wiihosop3yx0.png" alt="WebSocket output"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Como se puede comprobar en la imagen, nuestra comunicación a través de websocket a funcionado perfectamente :) &lt;/p&gt;

&lt;h2&gt;
  
  
  Precios
&lt;/h2&gt;

&lt;p&gt;Ahora viene el dato delicado, si, muy bonito, pero cuanto me va a costar. Ya sabemos que el coste en AWS (y en el resto de Clouds) es de pago por uso, por lo que antes de implementar te aconsejo que vayas a la web de AWS para consultar los precios:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aws.amazon.com/es/api-gateway/pricing/" rel="noopener noreferrer"&gt;AWS Api Gateway Pricing&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O bien también puedes ir a la calculadora de AWS y calcularlo en función de tus métricas&lt;/p&gt;

&lt;p&gt;&lt;a href="https://calculator.aws/#/" rel="noopener noreferrer"&gt;AWS Princing Calculator&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Te pongo un ejemplo de costes calculados con la calculadora:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;800 Messages/minutes&lt;/li&gt;
&lt;li&gt;80 (kb) Average message size&lt;/li&gt;
&lt;li&gt;20 (seconds) Average connection duration)&lt;/li&gt;
&lt;li&gt;300 Average connection rate / minute&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Y esto hace un total de &lt;strong&gt;121,11 UDS / Mes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Cabe destacar que existe una capa gratuita los 12 primeros meses:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;En el caso de las API WebSocket, la capa gratuita de API Gateway incluye un millón de mensajes (enviados o recibidos) y 750 000 minutos de conexión durante un máximo de doce meses.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Dependiendo de cada proyecto puede compensar o no pagar este tipo de soluciones frente a otras que necesiten mas desarrollo. &lt;/p&gt;

&lt;h2&gt;
  
  
  Github
&lt;/h2&gt;

&lt;p&gt;El proyecto lo podéis encontrar en mi repositorio de Github&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/fjaviermoradiaz/aws-blog-websocket" rel="noopener noreferrer"&gt;https://github.com/fjaviermoradiaz/aws-blog-websocket&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>websocket</category>
      <category>apigateway</category>
      <category>cdk</category>
    </item>
    <item>
      <title>Ahorra con Amazon EKS</title>
      <dc:creator>Javi Mora</dc:creator>
      <pubDate>Thu, 28 Mar 2024 08:21:38 +0000</pubDate>
      <link>https://dev.to/aws-espanol/ahorra-con-amazon-eks-2oi</link>
      <guid>https://dev.to/aws-espanol/ahorra-con-amazon-eks-2oi</guid>
      <description>&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiscyppgc425wgrlyzzso.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiscyppgc425wgrlyzzso.png" alt="Image description" width="379" height="115"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para realizar este proyecto usaremos &lt;a href="https://www.serverless.com/"&gt;Serverless Framework&lt;/a&gt; para crear y desplegar nuestro pequeño sistema de apagado automático, el cual realizaremos en NodeJS con Typescript.&lt;/p&gt;

&lt;h3&gt;
  
  
  Instalar serverless framework
&lt;/h3&gt;

&lt;p&gt;Lo primero de todo es instalar serverless framework con el siguiente comando desde un terminal&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm install -g serverless
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Una vez instalado creamos nuestro proyecto en un nuevo directorio ejecutamos el siguiente comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sls create -t aws-nodejs-typescript

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;Ahora ya podéis probar que el proyecto se ha creado correctamente invocando la función hello desde local:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sls invoke local -f start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Lambda
&lt;/h3&gt;

&lt;p&gt;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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;npm i aws-sdk
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;y luego añadimos este código a nuestra lambda:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;ValidatedEventAPIGatewayProxyEvent&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@libs/api-gateway&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;formatJSONResponse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@libs/api-gateway&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;middyfy&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@libs/lambda&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;NodegroupScalingConfig&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;UpdateNodegroupConfigRequest&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;UpdateNodegroupConfigResponse&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-sdk/clients/eks&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;AWSError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;EKS&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-sdk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./schema&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;PromiseResult&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;aws-sdk/lib/request&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;ValidatedEventAPIGatewayProxyEvent&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt; &lt;span class="nx"&gt;schema&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;CLUSTER_NAME&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[CLUSTER_NAME]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="na"&gt;NODE_GROUP_NAME&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;[NODE_GROUP_NAME]&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;nodeGroupConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;NodegroupScalingConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;desiredSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;maxSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;minSize&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;nodeGroupRequest&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;UpdateNodegroupConfigRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;clusterName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;CLUSTER_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;nodegroupName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;NODE_GROUP_NAME&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;scalingConfig&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;nodeGroupConfig&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;


  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="na"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;PromiseResult&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;UpdateNodegroupConfigResponse&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;AWSError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;EKS&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;updateNodegroupConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;nodeGroupRequest&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;


  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;formatJSONResponse&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;NodeGroupScaling updated to 0&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;middyfy&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stop&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;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.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lambda scheduler
&lt;/h3&gt;

&lt;p&gt;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.&lt;/p&gt;

&lt;p&gt;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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;handlerPath&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@libs/handler-resolver&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;handlerPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;/handler.main`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;events&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;schedule&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;cron(0 19 ? * MON-FRI *)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;De esta manera nuestra lambda hará un scale down cada día, de lunes a viernes a las 7 de la tarde.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lambda role (I)
&lt;/h3&gt;

&lt;p&gt;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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;provider:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;name:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'aws'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;iamRoleStatements:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;'Effect':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'Allow'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;'Action':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;'eks:UpdateNodegroupConfig'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="err"&gt;'Resource':&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;'*'&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deploy
&lt;/h3&gt;

&lt;p&gt;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:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sls deploy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd9o1mqcldam5y6q01wn5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd9o1mqcldam5y6q01wn5.png" alt="Image description" width="438" height="117"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Lambda role (II)
&lt;/h3&gt;

&lt;p&gt;Una vez desplegados podemos ver que la lambda tiene asignado un rol&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F51yssrsssna74knpxwxg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F51yssrsssna74knpxwxg.png" alt="Image description" width="720" height="164"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;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 &lt;a href="https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html"&gt;https://docs.aws.amazon.com/eks/latest/userguide/add-user-role.html&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;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
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Esto creará un registro nuevo en el mapa de identidades de nuestro cluster&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;eksctl get iamidentitymapping --cluster cluster-name --region=xx-xxxx-x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



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

&lt;p&gt;Os dejo la documentación oficial donde se detalla como funciona la API de la SDK de AWS: &lt;a href="https://docs.aws.amazon.com/eks/latest/APIReference/API_UpdateNodegroupConfig.html"&gt;https://docs.aws.amazon.com/eks/latest/APIReference/API_UpdateNodegroupConfig.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Os dejo también el repositorio GitHub donde está subido este ejemplo: &lt;a href="https://github.com/fjaviermoradiaz/aws-eks-manager"&gt;https://github.com/fjaviermoradiaz/aws-eks-manager&lt;/a&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>eks</category>
      <category>kubernetes</category>
      <category>typescript</category>
    </item>
  </channel>
</rss>
