<?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: Jose Yapur</title>
    <description>The latest articles on DEV Community by Jose Yapur (@develozombie).</description>
    <link>https://dev.to/develozombie</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%2F838315%2Faf98a621-1f03-4943-8539-4104d8196904.png</url>
      <title>DEV Community: Jose Yapur</title>
      <link>https://dev.to/develozombie</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/develozombie"/>
    <language>en</language>
    <item>
      <title>Picturesocial - Cómo añadir integración continua y entrega continua a mi aplicación</title>
      <dc:creator>Jose Yapur</dc:creator>
      <pubDate>Mon, 08 May 2023 16:35:02 +0000</pubDate>
      <link>https://dev.to/aws/como-anadir-integracion-continua-y-entrega-continua-a-tu-aplicacion-51jk</link>
      <guid>https://dev.to/aws/como-anadir-integracion-continua-y-entrega-continua-a-tu-aplicacion-51jk</guid>
      <description>&lt;p&gt;Episodio escrito por: &lt;a href="https://linkedin.com/in/ricardoceci" rel="noopener noreferrer"&gt;Ricardo Ceci&lt;/a&gt; y &lt;a href="https://linktr.ee/develozombie" rel="noopener noreferrer"&gt;Jose Yapur&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/2Eptv00imxo"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;Si es la primera vez que llegas a escuchar o leer sobre Picturesocial es una serie de contenido en la que aprendemos de cero el proceso de desarrollo, integración, despliegue y mantenimiento de una red social ficticia creada para aprender sobre tecnología con ayuda de especialistas de Nube, Seguridad, Software y DevOps, puedes encontrar todos los episodios de la serie en &lt;a href="https://bit.ly/m/picturesocial" rel="noopener noreferrer"&gt;https://bit.ly/m/picturesocial&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;En la temporada anterior de Picturesocial aprendimos sobre el proceso de construcción de nuestra aplicación desde cero, sin embargo, hoy día nos enfrentamos a los retos de llevar una aplicación a producción y que debemos planificar desde el inicio. Sabemos tambien, que los escenarios ideales, en la mayoría de los casos, son propios de la academia y no de la vida real. Picturesocial nació como un proyecto que estaba “listo” para ir a producción, porque “¿Qué es lo peor que puede pasar?”&lt;/p&gt;

&lt;p&gt;La ingenuidad, el exceso de fe o el elevado amor personal de desarrolladores senior 😆, nos llevó a donde estamos el día de hoy, con una red social en donde los pases a producción tardan días, se hacen muchos cambios al mismo tiempo por cada pase y es muy difícil detectar dónde están los problemas y por ende también a resolverlos.&lt;/p&gt;

&lt;p&gt;En el mundo ideal queremos que Picturesocial tenga procesos libres de mamíferos (tal cual como suena 😅), en donde los desarrolladores solo hagan push a sus repositorios, los flujos de aprobación entren en vigor y una vez que se haga merge al repositorio principal entonces todo lo demás que aprendimos en la temporada anterior lo hagan los seres binarios perfectos (las máquinas)&lt;/p&gt;

&lt;p&gt;Completamente conscientes de nuestras deficiencias para resolverlo solos, es que decidimos llamar a personas brillantes de las comunidades de AWS en todo América Latina, para que nos rescaten. En esta primera entrega hemos invitado a Ricardo Cecci, quien es AWS Community Builder y miembro del AWS UG de Buenos Aires, quien nos ayudará a resolver este problema y con quien estoy co-escribiendo este artículo.&lt;/p&gt;

&lt;p&gt;Los retos por los que pasa Picturesocial son comunes en muchos proyectos, es usualmente al momento de pasar a producción, cuando observamos a ciencia cierta que los pases tardan días, porque dependen de muchas personas y necesitan que se hagan de forma ordenada (no se puede hacer un despliegue y luego una compilación, o si? 🥶), este proceso de días, afecta directamente el time to market y a la vez ocasiona esa sensación de que nuestro corazón se va a detener o el mundo va a explotar si omitimos un paso en el proceso que ya está en ejecución.&lt;/p&gt;

&lt;p&gt;Un flujo de Integración Continua / Despliegue Continuo (CI/CD en inglés), nos va a permitir que nuestro proyecto pase por un circuito controlado automatizado de despliegue, donde, por ejemplo cada cambio en la rama master o main de nuestro repositorio haga que se muevan ciertas piezas automáticamente y nuestro código termine en producción si todos los chequeos pasaron, o no termine en producción si algo falló en el medio. En este circuito nosotros podremos definir todos los controles que queremos que ocurran y cómo va a ser ese despliegue a producción.&lt;/p&gt;

&lt;p&gt;En AWS existen las siguientes herramientas que nos pueden ayudar en el proceso:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS Codepipeline, con quien coordinaremos todo el proceso de salida a producción&lt;/li&gt;
&lt;li&gt;AWS CodeBuild, con esta herramienta haremos el build de nuestra imágen y la subiremos al repositorio de ECR.&lt;/li&gt;
&lt;li&gt;Por lo general también se utiliza AWS CodeDeploy, pero en este caso como estamos utilizando EKS no va a ser necesario utilizarlo.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Recuerdo cuando desplegabamos código manualmente, era como un rito, había que dejar de hacer todo, nos conectabamos servidor por servidor, e íbamos haciendo un pull en cada uno de los servidores, procurando no olvidarnos de ninguno, y que todas las librerías y dependencias estén actualizados en todos, que en ninguno nos hayamos olvidado de algún paso y cuando pasaba que nos olvidábamos (porque somos humanos) o algún servidor quedaba trabado en mitad del proceso, saltaban las alarmas y había que atacar servidor por servidor.&lt;/p&gt;

&lt;p&gt;Si había que hacer migraciones o modificaciones en las bases de datos que requerían hacer un lanzamiento similar a un blue/green, había que armar una regla específica en el load balancer para que rutee cierta parte del tráfico manualmente y podamos probar y luego manualmente rutear todo el tráfico, si bien había herramientas para hacerlo más fácil, no dejaba de ser manual.&lt;/p&gt;

&lt;p&gt;Una vez que implementamos el circuito de CI/CD, todo fue más fácil, podemos manejar salidas a producción con un click o tocando un botón y estaremos tranquilos de que si algo falla, podremos volver atrás o en el mejor de los casos se volverá automáticamente para atrás sin nuestra intervención y se nos avisará. &lt;/p&gt;

&lt;p&gt;En este caso, vamos a usar toda esa experiencia para implementar un proceso de CI/CD en el despliegue del servicio Pictures.&lt;/p&gt;

&lt;p&gt;Crearemos una solución que haga lo siguiente:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Detectar nuevos push a nuestro repositorio de código (Github/CodeCommit), en la branch principal. Suele llamarse ‘main’.&lt;/li&gt;
&lt;li&gt;A partir de allí un pipeline de AWS CodePipeline escuchará el cambio.&lt;/li&gt;
&lt;li&gt;A través de AWS CodeBuild construiremos la imagen de Docker y la subiremos a Elastic Container Registry (ECR)&lt;/li&gt;
&lt;li&gt;Luego haremos que nuestro cluster de EKS tome la nueva imagen y así nuestro servicio estará desplegado a producción.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Y lo más divertido es que todo se producirá automáticamente sin intervención nuestra, salvo la de crear la automatización en primer lugar 😃&lt;/p&gt;

&lt;p&gt;Lo primero que te recomendamos aquí es armarte de paciencia, dado que esto es algo que harás una sola vez, e iteraras algunas otras sobre la mejora de la implementación, si no cambias tus procesos no tendrás que prácticamente tocarlo una vez que lo tengas pulido y solo tendrás que ocuparte de hacer commits y push a las diferentes ramas que tu pipeline este escuchando.&lt;/p&gt;

&lt;p&gt;Los Servicios de AWS que vamos a utilizar son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS CodePipeLine.&lt;/li&gt;
&lt;li&gt;AWS CodeBuild&lt;/li&gt;
&lt;li&gt;Amazon EKS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hemos preparado una branch con todo lo que necesitas para ejecutar este episodio&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/aws-samples/picture-social-sample.git &lt;span class="nt"&gt;-b&lt;/span&gt; cicd
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Primero hemos agregado un archivo Dockerfile dentro de la carpeta de nuestro servicio pictures.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Contenido del archivo:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;mcr.microsoft.com/dotnet/sdk:6.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build-env&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="c"&gt;# Copy everything&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . ./&lt;/span&gt;
&lt;span class="c"&gt;# Restore as distinct layers&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;dotnet restore
&lt;span class="c"&gt;# Build and publish a release&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;dotnet publish &lt;span class="nt"&gt;-c&lt;/span&gt; Release &lt;span class="nt"&gt;-o&lt;/span&gt; out
&lt;span class="c"&gt;# Build runtime image&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; mcr.microsoft.com/dotnet/aspnet:6.0&lt;/span&gt;
&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /app&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=build-env /app/out .&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 5075&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; ASPNETCORE_URLS=http://+:5075&lt;/span&gt;
&lt;span class="k"&gt;ENTRYPOINT&lt;/span&gt;&lt;span class="s"&gt; ["dotnet", "pictures.dll"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Una vez que hemos hecho esto, vamos a armar el pipeline, nuestro pipeline en este caso va a tener 2 pasos:&lt;/p&gt;

&lt;p&gt;Paso 1:&lt;br&gt;
Pull del Repositorio&lt;br&gt;
Paso 2:&lt;br&gt;
Armado de la imágen con CodeBuild, Publicación en ECR y en EKS&lt;br&gt;
Al final del episodio el Pipeline debería de quedar así:&lt;br&gt;
&lt;a href="https://media2.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%2F74sjhhqfrmwxrjco9sv3.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F74sjhhqfrmwxrjco9sv3.jpg" alt="Picturesocial" width="800" height="460"&gt;&lt;/a&gt;&lt;br&gt;
Primero desde la barra de búsqueda de nuestra Consola de administración Buscamos CodePipeline&lt;br&gt;
&lt;a href="https://media2.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%2F97wj00qv9fzj721reon7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F97wj00qv9fzj721reon7.png" alt="Picturesocial" width="800" height="187"&gt;&lt;/a&gt;&lt;br&gt;
Presionamos: Create pipeline&lt;br&gt;
&lt;a href="https://media2.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%2Fba2n7vjsokwy9ehplgoq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fba2n7vjsokwy9ehplgoq.png" alt="Picturesocial" width="800" height="186"&gt;&lt;/a&gt;&lt;br&gt;
Ingresamos el nombre que queramos darle, en este caso PicturesService-CICD, y creamos un rol, pongamos un nombre que podamos recordar porque este rol más tarde lo modificaremos y le agregaremos unos permisos adicionales y presionamos Next&lt;br&gt;
&lt;a href="https://media2.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%2Fvizjx9rpnlhtwdc0pdo3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fvizjx9rpnlhtwdc0pdo3.png" alt="Picturesocial" width="800" height="546"&gt;&lt;/a&gt;&lt;br&gt;
En Source Provider, en este caso vamos a elegir Github Versión 2, que es donde tenemos alojado nuestro repositorio:&lt;br&gt;
Nota: En este caso te recomendamos que crees tu propio repositorio y lo conectes a tu cuenta, así puedes probar el pipeline sin problemas.&lt;br&gt;
&lt;a href="https://media2.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%2F8ugiaib7ll7spwpp1g64.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F8ugiaib7ll7spwpp1g64.png" alt="Picturesocial" width="800" height="340"&gt;&lt;/a&gt;&lt;br&gt;
Luego nos pedirá conectarnos a github con nuestras credenciales, o bien si ya nos hemos conectado con anterioridad, para elegir una cuenta existente.&lt;br&gt;
&lt;a href="https://media2.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%2Fanls1ufd5slxbzzzrom1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fanls1ufd5slxbzzzrom1.png" alt="Picturesocial" width="800" height="405"&gt;&lt;/a&gt;&lt;br&gt;
En el paso siguiente elegimos el repositorio desde el cual vamos a tomar el código y el branch (la rama) que queremos monitorear.&lt;br&gt;
&lt;a href="https://media2.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%2F3u0l2ct7qcit8nhk4429.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F3u0l2ct7qcit8nhk4429.png" alt="Picturesocial" width="800" height="609"&gt;&lt;/a&gt;&lt;br&gt;
Presionamos Next y nos pedira en el siguiente paso elegir el Build Provider, en este caso vamos a elegir AWS CodeBuild&lt;br&gt;
&lt;a href="https://media2.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%2Fpie6ltq732qe74qijjcq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fpie6ltq732qe74qijjcq.png" alt="Picturesocial" width="800" height="270"&gt;&lt;/a&gt;&lt;br&gt;
Luego de elegir CodeBuild, seleccionamos: Crear nuevo proyecto (Create new project)&lt;br&gt;
&lt;a href="https://media2.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%2Fu2qyjhb58vzkacoa1t6y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fu2qyjhb58vzkacoa1t6y.png" alt="Picturesocial" width="800" height="409"&gt;&lt;/a&gt;&lt;br&gt;
Se nos abrirá una ventana y pasamos a completar lo que nos solicita:&lt;br&gt;
Ponemos un nombre&lt;br&gt;
&lt;a href="https://media2.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%2Fy5ajzdfl8ky1qtjps6zi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fy5ajzdfl8ky1qtjps6zi.png" alt="Picturesocial" width="800" height="355"&gt;&lt;/a&gt;&lt;br&gt;
Environment:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Elegimos Managed Image (estas imágenes son administradas por AWS CodeBuild y no tendremos que preocuparnos por la gestión de seguridad y actualización del OS de esas imágenes)&lt;/li&gt;
&lt;li&gt;AmazonLinux 2 como sistema operativo&lt;/li&gt;
&lt;li&gt;Runtime: Standard&lt;/li&gt;
&lt;li&gt;Image: En este caso la última versión vigente la momento de escribir este articulo es la 4.0&lt;/li&gt;
&lt;li&gt;Environment type: Linux&lt;/li&gt;
&lt;li&gt;Muy importante: Dado que con este entorno vamos a crear nuevas imágenes de docker, debemos asegurarnos de que la casilla Privileged, esté activada.
&lt;img src="https://media2.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%2F2bxkaatg1z8itbp8k0o5.png" alt="Picturesocial" width="800" height="475"&gt;
&lt;/li&gt;
&lt;li&gt;Creamos un service role nuevo (Anotar el nombre)
&lt;img src="https://media2.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%2F4xbqkg1oh2yaqau2ugg5.png" alt="Picturesocial" width="800" height="310"&gt;
&lt;/li&gt;
&lt;li&gt;Desplegamos donde dice Additional Configuration para poder crear algumas variables de entorno que vamos a utilizar en el próximo paso:&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Creamos las siguientes variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;AWS_DEFAULT_REGION : us-east-1
IMAGE_REPO_NAME: nombre de la imagen que estamos generando &lt;span class="o"&gt;(&lt;/span&gt;en nuestro caso pictures&lt;span class="o"&gt;)&lt;/span&gt;
AWS_ACCOUNT_ID : Nuestro número de cuenta de AWS
AWS_CLUSTER_NAME : nombre de nuestro cluster de EKS &lt;span class="o"&gt;(&lt;/span&gt;en nuestro caso picturesocial-823&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.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%2Fmqdqx37v974tkpok580y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fmqdqx37v974tkpok580y.png" alt="Picturesocial" width="800" height="265"&gt;&lt;/a&gt;&lt;br&gt;
El próximo paso es indicarle a CodeBuild dónde van a estar las instrucciones de “Build de nuestro proyecto”, existen 2 opciones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Con un archivo buildspec.yml en la carpeta raíz del repositorio (al mismo nivel que el Dockerfile) &lt;/li&gt;
&lt;li&gt;Escribiendo las instrucciones de construcción en el proyecto. Vamos a elegir esta opcion y presionamos Switch to editor&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fw490qxt7b9hm0w148j7z.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fw490qxt7b9hm0w148j7z.png" alt="Picturesocial" width="800" height="276"&gt;&lt;/a&gt;&lt;br&gt;
En el repositorio les hemos dejado el archivo Buildspec-example.yml que es el que usaremos para completar el código.&lt;/p&gt;

&lt;p&gt;¿Qué estamos haciendo aqui?&lt;br&gt;
Declaramos la versión que vamos a usar y el listado de fases:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.2&lt;/span&gt;
&lt;span class="na"&gt;phases&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Primero declaramos las Fases&lt;br&gt;
Fase 1: Pre-Build&lt;br&gt;
En esta fase lo que estamos haciendo es&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;iniciando sesión en ECR&lt;/li&gt;
&lt;li&gt;Descargando y configurando kubectl para que se conecte con nuestro cluster de EKS&lt;/li&gt;
&lt;li&gt;Creamos una variable de entorno que utilizaremos luego como el tag que identificara la imágen imagen.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;pre_build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo Logging in to Amazon ECR...&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;curl -o kubectl https://s3.us-west-2.amazonaws.com/amazon-eks/1.25.6/2023-01-30/bin/linux/amd64/kubectl&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;chmod +x ./kubectl&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mkdir -p $HOME/bin &amp;amp;&amp;amp; cp ./kubectl $HOME/bin/kubectl &amp;amp;&amp;amp; export PATH=$PATH:$HOME/bin&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo 'export PATH=$PATH:$HOME/bin' &amp;gt;&amp;gt; ~/.bashrc&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;source ~/.bashrc&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;aws eks --region $AWS_DEFAULT_REGION update-kubeconfig --name $AWS_CLUSTER_NAME&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;IMAGE_TAG=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Luego viene la fase de Build:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Escribimos un mensaje en la consola para reconocer que comenzó la generación de las imágenes&lt;/li&gt;
&lt;li&gt;Cambiamos de directorio y nos movemos a la carpeta Pictures, donde se encuentra el Dockerfile&lt;/li&gt;
&lt;li&gt;Hacemos el build de la imágen tal como aprendimos en el episodio 1&lt;/li&gt;
&lt;li&gt;Aplicamos un tag a nuestra imágen para luego subirla a ECR
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;build: commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;- echo Build started on `date` - echo Building the Docker image... - cd pictures - docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG . - docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Una vez que tenemos la imagen armada, vamos ahora si a enviarla a ECR y luego a EKS&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enviamos un mensaje a la consola para registrar el momento en el que se terminó de hacer el build de la imágen y avisamos que vamos a subir la imágen a ECR&lt;/li&gt;
&lt;li&gt;Subimos la imágen a ECR&lt;/li&gt;
&lt;li&gt;En el repositorio que les dejamos en el archivo manifest.yml hemos cambiado el nombre de la imágen a ECR_IMAGE_PLACEHOLDER, en este paso lo que estamos haciendo es reemplazar ese placeholder por le nombre real de la imágen genreada durante la fase de Build.&lt;/li&gt;
&lt;li&gt;Luego hacemos un kubectl apply -f del archivo manifest.yml y con esto ya tendremos nuestra imágen publicada.
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;post_build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo Build completed on `date`&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo Pushing the Docker image...&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo Replacing in manifest with the image name&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sed -i "s/ECR_IMAGE_PLACEHOLDER/${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com\/${IMAGE_REPO_NAME}:${IMAGE_TAG}/g" manifest.yml&lt;/span&gt;
 &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;kubectl apply -f manifest.yml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;El archivo final debera quedarnos así:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;
&lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0.2&lt;/span&gt;

&lt;span class="na"&gt;phases&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pre_build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo Logging in to Amazon ECR...&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;curl -o kubectl https://s3.us-west-2.amazonaws.com/amazon-eks/1.25.6/2023-01-30/bin/linux/amd64/kubectl&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;chmod +x ./kubectl&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;mkdir -p $HOME/bin &amp;amp;&amp;amp; cp ./kubectl $HOME/bin/kubectl &amp;amp;&amp;amp; export PATH=$PATH:$HOME/bin&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo 'export PATH=$PATH:$HOME/bin' &amp;gt;&amp;gt; ~/.bashrc&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;source ~/.bashrc&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;aws eks --region $AWS_DEFAULT_REGION update-kubeconfig --name $AWS_CLUSTER_NAME&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;IMAGE_TAG=$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo Build started on `date`&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo Building the Docker image...&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;cd pictures&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG .&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG&lt;/span&gt;      
  &lt;span class="na"&gt;post_build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;commands&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo Build completed on `date`&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo Pushing the Docker image...&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG_V2&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;echo Replacing in manifest with the image name&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;sed -i "s/ECR_IMAGE_PLACEHOLDER/${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com\/${IMAGE_REPO_NAME}:${IMAGE_TAG}/g" manifest.yml&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;kubectl apply -f manifest.yml&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Reemplazamos el contenido del editor por el del archivo:&lt;br&gt;
&lt;a href="https://media2.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%2Ffuwlc4ij7bh6cvy53d5o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ffuwlc4ij7bh6cvy53d5o.png" alt="Picturesocial" width="800" height="415"&gt;&lt;/a&gt;&lt;br&gt;
Luego seleccionamos continue to CodePipeline&lt;br&gt;
&lt;a href="https://media2.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%2F45dujs8v1h4usy8jhusr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F45dujs8v1h4usy8jhusr.png" alt="Picturesocial" width="800" height="554"&gt;&lt;/a&gt;&lt;br&gt;
De vuelta en CodePipeline presionamos: Next y saltamos el paso de Deploy Stage dado que ya lo hemos hecho en el paso anterior.&lt;br&gt;
&lt;a href="https://media2.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%2Fqird9jmo5umjpkydkggf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fqird9jmo5umjpkydkggf.png" alt="Picturesocial" width="800" height="459"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.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%2Fi5163qx5dc4ye9dgwtoe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fi5163qx5dc4ye9dgwtoe.png" alt="Picturesocial" width="800" height="274"&gt;&lt;/a&gt;&lt;br&gt;
Nos pedirá confirmar todo y luego de confirmar nuestro pipeline ya estará creado.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Enhorabuena!&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://media2.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%2Fujauilr7dsxmyfrtcmo3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fujauilr7dsxmyfrtcmo3.png" alt="Picturesocial" width="800" height="380"&gt;&lt;/a&gt;&lt;br&gt;
Esto no termina aqui, seguramente nuestra pipeline falle porque CodeBuild no tiene permisos para poder publicar en ECR, ni en EKS&lt;br&gt;
&lt;a href="https://media2.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%2Fzbb1sthn9cqq3w58t161.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fzbb1sthn9cqq3w58t161.png" alt="Picturesocial" width="800" height="435"&gt;&lt;/a&gt;&lt;br&gt;
Vamos a darle los permisos que necesita:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Vamos a modificar el Rol creado cuando estabamos creando el proyecto en CodeBuild y vamos a darle los permisos que necesitamos, para esto nos vamos a IAM: &lt;a href="https://us-east-1.console.aws.amazon.com/iamv2/home?region=us-east-1" rel="noopener noreferrer"&gt;https://us-east-1.console.aws.amazon.com/iamv2/home?region=us-east-1&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Ya en IAM nos vamos a Roles&lt;/li&gt;
&lt;li&gt;Allí buscamos el rol que creamos en el momento de crear el proyecto de CodeBuild&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fmjvw5q31cd9nl9ibsrq9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fmjvw5q31cd9nl9ibsrq9.png" alt="Picturesocial" width="800" height="339"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Vamos a agregar permisos creando una nueva Policy&lt;br&gt;
&lt;a href="https://media2.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%2Fek6shdop5kyo7a40pscc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fek6shdop5kyo7a40pscc.png" alt="Picturesocial" width="800" height="398"&gt;&lt;/a&gt;&lt;br&gt;
&lt;a href="https://media2.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%2Faq204tybxqssag5d74p9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Faq204tybxqssag5d74p9.png" alt="Picturesocial" width="800" height="232"&gt;&lt;/a&gt;&lt;br&gt;
Nos vamos a la solapa JSON y pegamos el siguiente contenido:&lt;/p&gt;

&lt;p&gt;Reemplazar donde dice ACCOUNT-ID por tu número de cuenta, y CLUSTER NAME por el nombre del cluster de EKS&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VisualEditor0"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"Action"&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="s2"&gt;"ecr:CompleteLayerUpload"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"eks:DescribeCluster"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"ecr:UploadLayerPart"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"ecr:InitiateLayerUpload"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"ecr:BatchCheckLayerAvailability"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"ecr:PutImage"&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;"Resource"&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="s2"&gt;"arn:aws:ecr:us-east-1:[ACCOUNT-ID]:repository/pictures"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
                &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:eks:us-east-1:[ACCOUNT-ID]:cluster/[CLUSTER-NAME]"&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Sid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"VisualEditor1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ecr:GetAuthorizationToken"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;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;En nuestro caso quedaría asi:&lt;br&gt;
&lt;a href="https://media2.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%2F438106i363m1d4ubazdr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F438106i363m1d4ubazdr.png" alt="Picturesocial" width="800" height="437"&gt;&lt;/a&gt;&lt;br&gt;
Presionamos Siguiente, Ingresamos un nombre a nuestra policy&lt;br&gt;
&lt;a href="https://media2.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%2Fdwc6yv1s1qkmtdz1ytey.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fdwc6yv1s1qkmtdz1ytey.png" alt="Picturesocial" width="800" height="458"&gt;&lt;/a&gt;&lt;br&gt;
Luego presionamos Create policy y nuestra política estará creada.&lt;/p&gt;

&lt;p&gt;Luego agregamos los permisos a nuestro rol:&lt;br&gt;
&lt;a href="https://media2.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%2Fb1okb1ewa2xm8w9u6rxm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fb1okb1ewa2xm8w9u6rxm.png" alt="Picturesocial" width="800" height="316"&gt;&lt;/a&gt;&lt;br&gt;
Así debería quedar:&lt;br&gt;
&lt;a href="https://media2.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%2Fh7p9g9t1y4cfascyq551.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fh7p9g9t1y4cfascyq551.png" alt="Picturesocial" width="800" height="371"&gt;&lt;/a&gt;&lt;br&gt;
Copiemos el ARN de nuestro rol ya que lo vamos a utilizar para el próximo paso&lt;/p&gt;

&lt;p&gt;Ahora lo que nos queda hacer, es darle permiso a CodeBuild en nuestro cluster de EKS para que pueda ejecutar el comando apply, para esto hay que a través de un Role Based Access Control darle permiso:&lt;br&gt;
Desde nuestra consola ejecutamos el siguiente comando:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl edit cm aws-auth &lt;span class="nt"&gt;-n&lt;/span&gt; kube-system
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Luego dentro de mapRoles agregamos una nueva entrada:&lt;/p&gt;

&lt;p&gt;Aqui reemplazamos el ARN por el que copiamos anteriormente, notese que quitamos el path /service-role/ del nombre del ARN&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;groups&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt;&lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;system:masters&lt;/span&gt;
 &lt;span class="na"&gt;rolearn&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;arn:aws:iam::XXXXXXXX:role/PicturesBuildServiceRole&lt;/span&gt; 
 &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CodeBuild Role to Access EKS&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Ahora si, podemos volver a nuestro pipeline, y lo tenemos listo para trabajar, presionemos “Release change”&lt;/p&gt;

&lt;p&gt;Y veremos cómo ahora si se completa el trabajo:&lt;br&gt;
&lt;a href="https://media2.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%2Fq3bo7lwqed2cny3qiamb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fq3bo7lwqed2cny3qiamb.png" alt="Picturesocial" width="800" height="460"&gt;&lt;/a&gt;&lt;br&gt;
&lt;strong&gt;Ahora:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Realiza algún cambio mínimo en el código y verás como cada vez que se haga un push a la rama que hayas configurado, automáticamente se desplegará en el Cluster.&lt;/p&gt;

&lt;p&gt;Si llegaste hasta acá, hoy aprendiste cómo usar algunas de las capacidades de CI/CD que tienes disponibles en AWS y cómo es que puedes aplicarlas a tus proyectos contenerizados. En el siguiente episodio aprenderemos cómo agregar observabilidad a Picturesocial y por qué deberíamos hacerlo. Nos vemos en el siguiente episodio!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Sobre los autores&lt;/strong&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fzrhhojyuvi08f1a8gyra.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fzrhhojyuvi08f1a8gyra.png" alt="Picturesocial" width="160" height="160"&gt;&lt;/a&gt;&lt;strong&gt;José Yapur&lt;/strong&gt; es Senior Developer Advocate en AWS con experiencia en Arquitectura de Software y pasión por el desarrollo especialmente en .NET y PHP. Trabajó como Arquitecto de Soluciones por varios años, ayudando a empresas y personas en LATAM.&lt;br&gt;
&lt;a href="https://media2.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%2Fobj2jbsr1u5hlz3x9fp0.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fobj2jbsr1u5hlz3x9fp0.jpg" alt="Picturesocial" width="160" height="160"&gt;&lt;/a&gt;&lt;strong&gt;Ricardo Ceci&lt;/strong&gt; es CTO @ Halsbrook y Fundador de .VNS | Software Agency, es un desarrollador apasionado por arquitecturas en la nube y desarrollo con nuevas tecnologías.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>aws</category>
      <category>kubernetes</category>
      <category>cicd</category>
    </item>
    <item>
      <title>Picturesocial - Cómo es la arquitectura de una aplicación</title>
      <dc:creator>Jose Yapur</dc:creator>
      <pubDate>Fri, 30 Dec 2022 21:39:23 +0000</pubDate>
      <link>https://dev.to/aws/picturesocial-como-es-la-arquitectura-de-una-aplicacion-dmm</link>
      <guid>https://dev.to/aws/picturesocial-como-es-la-arquitectura-de-una-aplicacion-dmm</guid>
      <description>&lt;p&gt;Crear Picturesocial ha sido todo un viaje, cuando comenzamos me propuse crear una red social de cero, con el solo propósito de que aprendamos juntos el proceso de llevar una solución contenerizada a Amazon Web Services. &lt;/p&gt;

&lt;p&gt;Algo que tal vez no dejé claro es que yo aprendí de AWS creando esta serie, comencé hace poco más de 1 año y solo sabía mi nombre y mi edad. Pero hoy me siento orgulloso de todo lo que hemos logrado y aprendido juntos. &lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/YEmFv_tjwyE"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;




&lt;p&gt;Acá les dejo los enlaces con todo el contenido de la primera temporada.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;    &lt;a href="https://bit.ly/3MrneKU?r=lp" rel="noopener noreferrer"&gt;Cómo crear un container&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;    &lt;a href="https://go.aws/3wucSns?r=lp" rel="noopener noreferrer"&gt;Qué es Kubernetes&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;    &lt;a href="https://go.aws/3GwBnEY?r=lp" rel="noopener noreferrer"&gt;Cómo crear un clúster de Kubernetes&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;    &lt;a href="https://go.aws/3zZCVpF?r=lp" rel="noopener noreferrer"&gt;Cómo desplegar aplicaciones a Kubernetes&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;    &lt;a href="https://go.aws/3PxPyga?r=lp" rel="noopener noreferrer"&gt;Cómo usar reconocimiento de imágenes&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;    &lt;a href="https://go.aws/3QDBIJV?r=lp" rel="noopener noreferrer"&gt;Cómo delegar accesos a servicios de AWS en Kubernetes&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;    &lt;a href="https://go.aws/3ShIc1I?r=lp" rel="noopener noreferrer"&gt;Cómo usar una base de datos documental&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;    &lt;a href="https://go.aws/3tk1SI6?r=lp" rel="noopener noreferrer"&gt;Cómo exponer las API's&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;    &lt;a href="https://bit.ly/3j4ox9m?r=lp" rel="noopener noreferrer"&gt;Cómo escalar el clúster de Kubernetes con cómputo Just-in-Time&lt;/a&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;p&gt;Estos 10 episodios marcan el fin de nuestra primera temporada que se ha enfocado en el descubrimiento. La siguiente temporada estará pensada en la vida real, esa que no suele ser color de rosa, donde las cosas pueden fallar, podemos tener algunos problemas de disponibilidad, seguridad o gastar más de lo que creíamos, casi todo puede prevenirse y nos vamos a enfocar en crear una mejor experiencia para todos y todas. Por eso me pareció que debíamos cerrar la temporada pensando en arquitectura, a manera de resumen de todo lo que hemos hecho hasta ahora y de pensar en el futuro. He invitado a Gustavo Fandiño quien es arquitecto de soluciones en AWS para que nos guíe en entender cuáles son los retos y el futuro de Picturesocial para el siguiente año.&lt;/p&gt;

&lt;p&gt;Lo primero que hicimos fue entender la arquitectura as-is y los servicios que hemos explorado en los diferentes episodios de la serie.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fwfrww69ziqsa016u2dt5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fwfrww69ziqsa016u2dt5.png" alt="Picturesocial - Arquitecture actual" width="701" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Para luego revisar la primera fase de lo que será nuestra nueva arquitectura, donde iremos agregando Entrega e Integración continua así como el offloading de cómputo de nuestro clúster de Kubernetes hacia componentes Serverless.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fkm4ta7sfno8e4bikheqq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fkm4ta7sfno8e4bikheqq.png" alt="Picturesocial - Arquitectura to-be" width="714" height="721"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Este post no tiene mucho detalle porque creo que lo más valioso es la conversación del video así que espero sus comentarios y sugerencias. Todo lo que me escriban será tomado en cuenta para la siguiente temporada. &lt;/p&gt;

&lt;p&gt;¿Nos leemos el próximo año?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>graphql</category>
      <category>api</category>
      <category>rest</category>
    </item>
    <item>
      <title>Picturesocial - Cómo desplegar un cluster de Kubernetes en AWS usando Terraform</title>
      <dc:creator>Jose Yapur</dc:creator>
      <pubDate>Tue, 07 Jun 2022 15:31:28 +0000</pubDate>
      <link>https://dev.to/develozombie/picturesocial-como-desplegar-un-cluster-de-kubernetes-en-aws-usando-terraform-614</link>
      <guid>https://dev.to/develozombie/picturesocial-como-desplegar-un-cluster-de-kubernetes-en-aws-usando-terraform-614</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/OCc8D-ePvqo"&gt;
&lt;/iframe&gt;
&lt;br&gt;
En nuestro último post descubrimos sobre Kubernetes y por qué lo estamos usando en Picturesocial. En este post vamos a aprender sobre infraestructura cómo código, y específicamente sobre cómo desplegar un Amazon Elastic Kubernetes Service usando Terraform.&lt;/p&gt;

&lt;p&gt;He trabajado en proyectos de TI por varios años y algo recurrente, en mi experiencia, ha sido cómo los desarrolladores trabajan junto con los Sysadmins, especialmente cuando la aplicación fuerza cambios en la infraestructura y en la forma en la que las cosas son hechas tradicionalmente, ¿La aplicación tiene que adaptarse a la infraestructura o la infraestructura debe adaptarse a la aplicación?, ¿Qué pasa si los cambios en infraestructura representan problemas para hacer rollback a versiones anteriores de la aplicación de forma sencilla?&lt;/p&gt;

&lt;p&gt;En el pasado, diseñamos aplicaciones sabiendo que en la mayoría de los casos la infraestructura era estática, que teníamos que lidiar con las limitaciones como algo axiomático e inamovible. A medida que avanzamos en nuestro camino a la computación en la nube, ese paradigma comenzó a romperse con la posibilidad de tener teóricamente todo el poder de computo que necesitábamos al alcance de nuestras manos y casi de forma inmediata. Ese cambio ayudó a crear un nuevo set de soluciones diseñadas para esas nuevas capacidades, una de ellas fue Infraestructura como Código (IaC)&lt;/p&gt;

&lt;p&gt;Pero, ¿Qué es infraestructura como código?&lt;/p&gt;

&lt;p&gt;Cuando estaba en el colegio me gustaba escribir historias de Calabozos y Dragones, donde el personaje principal tenía que tomar decisiones irreversibles que eran seleccionadas por el lector, y dependiendo de la elección podrías ir a través una serie de aventuras que podían ser potencialmente largas y complejas o simplemente hacían que la historia termine en ese momento. Así es como suceden las cosas con la infraestructura, comienzas con algunos supuestos que te obligan a elegir el tamaño de tu infra, dimensionamiento de redes, uso de balanceadores, etc. La mayoría de cambios que hagas sobre la infraestructura base son potencialmente irreversibles a menos que conozcas exactamente lo que pasó desde el inicio y cada acción que se realizó. Esto significa que mantener versionamiento de la infraestructura y su configuración en conjunto con la aplicación puede ser posible pero se vuelve bastante difícil, y es ahí donde la Infraestructura como Código entra a la acción.&lt;/p&gt;

&lt;p&gt;La Infraestructura como Código te permite definir tu infraestructura y configuración de manera similar a como los desarrolladores de software definen sus aplicaciones y está compuesto por archivos de configuración. Estos archivos de configuración son interpretados y transformados en infraestructura en tu ambiente de nube pública o híbrida. IaC te permite mantener versionamiento de cada cambio, así como hacer rollback hacia versiones anteriores, incluso puedes crear pruebas para entender qué representan esos cambios antes de aplicarlos.&lt;/p&gt;

&lt;p&gt;Para Picturesocial decidí usar Hashicorp Terraform, para nuestras definiciones de IaC, debido a que es una herramienta que vengo usando por años y me siento seguro de poder escalar mi arquitectura e infraestructura sin gastar mucho tiempo aprendiendo una nueva herramienta. Sin embargo, hay otras excelentes herramientas en el mercado como AWS Cloud Development Toolkit, AWS CloudFormation, Pulumi, Ansible, Chef, Puppet, entre otras. Estas herramientas también pueden ayudarte, la mejor opción es la que te haga sentir más cómodo y productivo.&lt;/p&gt;

&lt;p&gt;¿Qué es Hashicorp Terraform?&lt;/p&gt;

&lt;p&gt;Terraform es una herramienta de IaC creada por Hashicorp que te ayuda a definir una infraestructura completa de una forma en la que puedes versionarla y reutilizarla. Usa Hashicorp Configuration Language (HCL) para su estructura. Todos los archivos de configuración de Terraform deben ser guardados con la extensión .tf &lt;/p&gt;

&lt;p&gt;Algunas definiciones básicas a tener en cuenta son:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Providers&lt;/em&gt;: Aquí es donde le dices a Terraform que estás usando un proveedor de nube específico [providers (&lt;a href="https://registry.terraform.io/browse/providers)"&gt;https://registry.terraform.io/browse/providers)&lt;/a&gt;], por ejemplo, si quieres desplegar tu infraestructura a AWS, necesitas definir un proveedor como en el ejemplo a continuación. Tener en cuenta que especificar la versión del proveedor es opcional, si no la especificas usará la última disponible como versión por defecto.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "&amp;gt;= 3.20.0"
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Resources&lt;/em&gt;: Acá es donde defines la infraestructura. Puedes definir los recursos como piezas de infraestructura tipo: instancias, redes, storage, etc. Un recurso necesita dos parametros declarativos: 1/ el tipo de recurso y 2/ el id del recurso. Por ejemplo, abajo estamos definiendo una instancia de AWS con un AMI específico y tipo de instancia t2.micro.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_instance" "web" {
  ami           = "ami-a1b2c3d4"
  instance_type = "t2.micro"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Variables&lt;/em&gt;: 

&lt;ul&gt;
&lt;li&gt;Input: Estas son las variables que usas para solicitar información de los usuarios o runtime antes de aplicar algún cambio. Este tipo de variables son parámetros que debes ingresar en el Terraform CLI [CLI (&lt;a href="https://www.terraform.io/cli)"&gt;https://www.terraform.io/cli)&lt;/a&gt;]
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "project_code" {
  type = string
}

variable "availability_zone" {
  type    = list(string)
  default = ["us-east-1a"]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* Output: Estas son variables que retornarán información de la ejecución. Por ejemplo, nombre del repositorio, id del cluster, etc.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;output "ec2_ip" {  value = aws_instance.server.private_ip}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;* Locals: Estas son variables que estableces en tu código y pueden ser referenciadas en cualquier parte del proyecto. El ejemplo a continuación creará una etiqueta común para todos los recursos que creemos y concatenará los valores de las variables project_code y environment
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
locals {
  project_code = "pso"
  environment        = "dev"
}
common_tags = {
  project_name = "pe-${local.project_code}-${local.environment}01"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Modules&lt;/em&gt;: Usamos los módulos para agrupar diferentes recursos que son utilizados de forma conjunta en una arquitectura, de esa forma en vez de tener una plantilla de Terraform de 30 paginas y 2 volúmenes, podemos estandarizar escenarios como un solo objeto. Por ejemplo: Cada Amazon EKS Cluster necesita una VPC con 6 subnets, 2 Elastic Load Balancers, 2 Worker Groups con al menos 3 instancias de EC2 cada grupo, etc. En vez de crear todos los recursos por cluster, podemos crear un módulo y reutilizarlo para simplificar las creaciones futuras.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module "aws-vpc" {
  source = "./mods/aws-vpc"
  base_cidr_block = "11.0.0.0/16"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Me gusta pensar en Terraform como una herramienta de IaC de 4 pasos (inclusive si tenemos más opciones), vamos a usar 4 comandos básicos que aplicarán a todos nuestros proyectos, esos pasos necesitan ser ejecutados en el siguiente orden:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;terraform init&lt;/code&gt;
Usa este comando para inicializar tu proyecto de Terraform, solo debes ejecutar este comando una vez por proyecto.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;terraform plan&lt;/code&gt;
Este comando se usa para probar qué es lo que se creará, actualizará o eliminará en tu ambiente de nube y antes de ejecutar cualquier cambio.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;terraform apply&lt;/code&gt;
Este comando ejecuta terraform plan como paso 1 y luego en base a tu confirmación, ejecuta los cambios finales en tu ambiente de nube.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;terraform destroy&lt;/code&gt;
Cuando ya no necesitas tu ambiente de nube, puedes destruirlo por completo. Esto es súper útil para ambientes de certificación que solo son usados cuando sale un nuevo release, por ejemplo.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Ahora que entendemos algunos conceptos básicos de IaC y Terraform ¡Vamos a desplegar un Cluster de Amazon EKS desde el inicio!&lt;/p&gt;

&lt;p&gt;Pre-requisitos&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Una cuenta de AWS, si no tienes puedes pedir una aquí: &lt;a href="https://aws.amazon.com/free/"&gt;https://aws.amazon.com/free/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Si estás usando Microsoft Windows te sugiero trabajar usando WSL2: &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/install"&gt;https://docs.microsoft.com/en-us/windows/wsl/install&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Si no tienes Git, desde acá puedes instalarlo: &lt;a href="https://github.com/git-guides/install-git"&gt;https://github.com/git-guides/install-git&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Instala la línea de comandos de Terraform &lt;a href="https://learn.hashicorp.com/tutorials/terraform/install-cli"&gt;https://learn.hashicorp.com/tutorials/terraform/install-cli&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Necesitarás el AWS CLI v2 &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html"&gt;https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Si esta es tu primera vez trabajando con AWS CLI o necesitas un refresh de como setear tus credenciales en el terminal te sugiero seguir este paso a paso: &lt;a href="https://aws.amazon.com/es/getting-started/guides/setup-environment/"&gt;https://aws.amazon.com/es/getting-started/guides/setup-environment/&lt;/a&gt;. Si no quieres instalar todo desde cero, en este mismo link podrás seguir los pasos para configurar Amazon Cloud9 que es un entorno de desarrollo virtual, que incluye casi todo el toolset que necesitas para este paso a paso.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Paso a Paso&lt;/p&gt;

&lt;p&gt;En este paso a paso vamos a crear un Cluster de Amazon EKS en la región us-east-1 usando 3 zonas de disponibilidad, nuestra propia VPC, un worker group con 3 instancias t2.small y security rules para prevenir acceso no restringido a nuestro worker group. He creado este repositorio en Github &lt;a href="https://github.com/aws-samples/picture-social-sample"&gt;https://github.com/aws-samples/picture-social-sample&lt;/a&gt; con todo el código necesario para seguir este paso a paso. Asegúrate de seleccionar la branch “ep3”.&lt;br&gt;
In this walkthrough we are going to create an Amazon EKS Cluster on the us-east-1 region using 3 availability zones, our own VPC, a worker group with 3 t2.small instances and security rules to prevent unrestricted access to our worker group. &lt;br&gt;
I created a repository on Github &lt;a href="https://github.com/aws-samples/picture-social-sample"&gt;https://github.com/aws-samples/picture-social-sample&lt;/a&gt; with all the code needed to follow this walkthrough, make sure you select branch “ep3”.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Primero, vamos a clonar nuestro repositorio base para tener todos los archivos de terraform que necesitaremos para crear nuestro cluster.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/aws-samples/picture-social-sample --branch ep3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Una vez clonado, vayamos al directorio creado. Aseguremonos de siempre estar dentro de este directorio por el resto de esta guía, de esa forma todo se ejecutará sin problemas.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd picture-social-sample
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Ahora que estamos en el directorio correcto y hemos clonado la branch, vamos a iniciar con el archivo config.tf. Este archivo contiene toda la configuración básica de nuestro proyecto de Terraform, como: región por defecto de AWS, nombre del cluster, variables para generar valores aleatorios, etc. Podemos referencias cualquiera de estos valores en el proyecto.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;variable "region" {
  default     = "us-east-1"
  description = "Region of AWS"
}

provider "aws" {
  region = var.region
}

data "aws_availability_zones" "available" {}

locals {
  cluster_name = "picturesocial-${random_integer.suffix.result}"
}

resource "random_integer" "suffix" {
  min = 100
  max = 999
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;El archivo vpc.tf es donde configuramos nuestra red y zonas de disponibilidad. Si quieres aprender más sobre VPC, puedes dar una mirada a este link: &lt;a href="https://docs.aws.amazon.com/vpc/latest/userguide/vpc-getting-started.html"&gt;https://docs.aws.amazon.com/vpc/latest/userguide/vpc-getting-started.html&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module "vpc" {
  source  = "terraform-aws-modules/vpc/aws"
  version = "3.2.0"

  name                 = "picturesocial-vpc"
  cidr                 = "10.0.0.0/16"
  azs                  = data.aws_availability_zones.available.names
  private_subnets      = ["10.0.1.0/24", "10.0.2.0/24", "10.0.3.0/24"]
  public_subnets       = ["10.0.4.0/24", "10.0.5.0/24", "10.0.6.0/24"]
  enable_nat_gateway   = true
  single_nat_gateway   = true
  enable_dns_hostnames = true

  tags = {
    "kubernetes.io/cluster/${local.cluster_name}" = "shared"
  }

  public_subnet_tags = {
    "kubernetes.io/cluster/${local.cluster_name}" = "shared"
    "kubernetes.io/role/elb"                      = "1"
  }

  private_subnet_tags = {
    "kubernetes.io/cluster/${local.cluster_name}" = "shared"
    "kubernetes.io/role/internal-elb"             = "1"
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Ahora que hemos configurado nuestra VPC, vamos a crear los Security Groups. Estos serán los que tienen a cargo la autorización o denegación del tráfico a las instancias de EC2 de nuestro Amazon EKS. Para este caso habilitaremos el trafico al puerto 22 de entrada desde algunos segmentos de red llamados cidr_blocks
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resource "aws_security_group" "worker_group_mgmt_one" {
  name_prefix = "worker_group_mgmt_one"
  vpc_id      = module.vpc.vpc_id

  ingress {
    from_port = 22
    to_port   = 22
    protocol  = "tcp"

    cidr_blocks = [
      "10.0.0.0/8",
    ]
  }
}

resource "aws_security_group" "worker_group_mgmt_two" {
  name_prefix = "worker_group_mgmt_two"
  vpc_id      = module.vpc.vpc_id

  ingress {
    from_port = 22
    to_port   = 22
    protocol  = "tcp"

    cidr_blocks = [
      "192.168.0.0/16",
    ]
  }
}

resource "aws_security_group" "all_worker_mgmt" {
  name_prefix = "all_worker_management"
  vpc_id      = module.vpc.vpc_id

  ingress {
    from_port = 22
    to_port   = 22
    protocol  = "tcp"

    cidr_blocks = [
      "10.0.0.0/8",
      "172.16.0.0/12",
      "192.168.0.0/16",
    ]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;El archivo eks-cluster.tf es donde se une todo lo que creamos en los pasos anteriores, usa un módulo público de AWS que podemos reutilizar para simplificar la creación de nuestro cluster. Vamos a establecer el nombre del cluster referenciando las variables que creamos en el config.tf, seleccionamos la versión de Kubernetes y referenciamos la VPC y subnets definidas en el archivo vpc.tf
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module "eks" {
  source          = "terraform-aws-modules/eks/aws"
  version         = "17.24.0"
  cluster_name    = local.cluster_name
  cluster_version = "1.20"
  subnets         = module.vpc.private_subnets

  vpc_id = module.vpc.vpc_id

  workers_group_defaults = {
    root_volume_type = "gp2"
  }

  worker_groups = [
    {
      name                          = "group-1"
      instance_type                 = "t2.small"
      additional_security_group_ids = [aws_security_group.worker_group_mgmt_one.id]
      asg_desired_capacity          = 3
    },
  ]
}

data "aws_eks_cluster" "cluster" {
  name = module.eks.cluster_id
}

data "aws_eks_cluster_auth" "cluster" {
  name = module.eks.cluster_id
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Y finalmente vamos a revisar los outputs luego que se entregarán al finalizar la ejecución del proyecto de Terraform en el archivo outputs.tf Este archivo producirá el archivo Config de Kubernetes o kubeconfig, esto es neceario para que Kubectl o el Kubernetes REST API sepa quien eres, si tienes acceso y si puede confiar en ti. Y además es una de las piezas más importantes para obtener acceso al cluster de Amazon EKS.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;output "cluster_id" {
  value       = module.eks.cluster_id
}

output "cluster_endpoint" {
  value       = module.eks.cluster_endpoint
}

output "cluster_security_group_id" {
  value       = module.eks.cluster_security_group_id
}

output "kubectl_config" {
  value       = module.eks.kubeconfig
}

output "config_map_aws_auth" {
  value       = module.eks.config_map_aws_auth
}

output "region" {
  value       = var.region
}

output "cluster_name" {
  value       = local.cluster_name
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Ahora asegurémonos que tenemos terraform correctamente instalado, vamos a ejecutar el comando a continuación en el terminal que prefieras. Si todo está bien deberías recibir la versión de Terraform instalada, necesitas al menos la versión 1.1.7.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;terraform —version
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Ahora vamos a inicializar nuestro proyecto al ejecutar el siguiente comando:
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;El comando anterior descargará todos los módulos públicos y archivos que necesita el proveedor de Terraform para AWS. Si recibes el siguiente mensaje en la línea de comandos “Terraform has been successfully initialized!"  entonces estamos listos para continuar. Si recibes algún error, revisa el mensaje de error donde te dirán la línea y archivo que tienen problemas, no te preocupes el error suele ser un error en nombre de variable o que te falta una comilla :)&lt;/li&gt;
&lt;li&gt;Ahora vamos a probar nuestra configuración:
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;El comando plan retornará un resumen de todas las cosas que se agregarán, cambiarán o destruirán. Esto nos dará una buena idea de cómo funcionará todo antes de ejecutar cambios.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Terraform used the selected providers to generate the following execution plan. Resource
actions are indicated with the following symbols:
  + create
 &amp;lt;= read (data resources)

Terraform will perform the following actions:

  # data.aws_eks_cluster.cluster will be read during apply
  # (config refers to values not yet known)
 &amp;lt;= data "aws_eks_cluster" "cluster"  {
      + arn                       = (known after apply)
      + certificate_authority     = (known after apply)
      + created_at                = (known after apply)
      + enabled_cluster_log_types = (known after apply)
      + endpoint                  = (known after apply)
      + id                        = (known after apply)
      + identity                  = (known after apply)
      + kubernetes_network_config = (known after apply)
      + name                      = (known after apply)
      + platform_version          = (known after apply)
      + role_arn                  = (known after apply)
      + status                    = (known after apply)
      + tags                      = (known after apply)
      + version                   = (known after apply)
      + vpc_config                = (known after apply)
    }

  #,
 .
 .
 .
*Plan: 50 to add, 0 to change, 0 to destroy.
*
Changes to Outputs:
  + cluster_endpoint          = (known after apply)
  + cluster_id                = (known after apply)
  + cluster_name              = (known after apply)
  + cluster_security_group_id = (known after apply)
  + config_map_aws_auth       = [
      + {
          + binary_data = null
          + data        = (known after apply)
          + id          = (known after apply)
          + metadata    = [
              + {
                  + annotations      = null
                  + generate_name    = null
                  + generation       = (known after apply)
                  + labels           = {
                      + "app.kubernetes.io/managed-by" = "Terraform"
                      + "terraform.io/module"          = "terraform-aws-modules.eks.aws"
                    }
                  + name             = "aws-auth"
                  + namespace        = "kube-system"
                  + resource_version = (known after apply)
                  + uid              = (known after apply)
                },
            ]
        },
    ]
  + kubectl_config            = (known after apply)
  + region                    = "us-east-1"

───────────────────────────────────────────────────────────────────────────────────────────────

Note: You didn't use the -out option to save this plan, so Terraform can't guarantee to take
exactly these actions if you run "terraform apply"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Ahora que estamos seguros, vamos a ejecutar los cambios en AWS. Para ello ejecutaremos el comando a continuación. Deberás escribir explícitamente “yes” para confirmar que estás de acuerdo con los cambios antes de ejecutarlos.
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Este proceso tardará alrededor de 15 a 20 minutos, pero dependiendo de tu propia configuración puede ser significativamente más o menos tiempo. Ten en cuenta que tu terminal necesita ser accesible y estar conectada a internet mientras el comando se ejecuta y finaliza la ejecución. Es un bueno momento para hacerte un buen café y ver videos de gatos cantando.&lt;/li&gt;
&lt;li&gt;Una vez que el comando termine de ejecutarse, deberás recibir el siguiente mensaje:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Apply complete! Resources: 50 added, 0 changed, 0 destroyed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Vamos a extraer todos los outputs que configuramos en el archivo outputs.tf, esos outputs además, son parte del mensaje que sale abajo de Apply complete! Todo esto será usado para construir el kubeconfig. Para extraer esos valores usaremos el comando a continuación:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws eks --region $(terraform output --raw region) update-kubeconfig --name $(terraform output --raw cluster_name)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;¡Estamos Listos! Ahora confirmemos que el cluster ha sido creado correctamente ejecutando el siguiente comando:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws eks list-clusters
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Si todo funcionó como lo esperábamos entonces deberías tener un output similar a este:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{"clusters": ["picturesocial-129"]}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Si tienes experiencia con Kubernetes y tienes una carga de trabajo que quieras probar, sientete libre de comenzar a jugar. Pero, si no tienes experiencia en cómo desplegar aplicaciones en Kubernetes te sugiero que elimines toda la infraestructura y la re-despliegues en el siguiente episodio, de esa forma evitas cargos innecesarios en tu cuenta por recursos que no usarás. Puedes borrar todo ejecutando el siguiente comando:
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;



&lt;p&gt;Wow! Realmente, este fue un artículo largo pero lo hicimos! Puedes reutilizar esta plantilla para crear tus propios clusters o incluso para crear tus propios módulos en el futuro.&lt;/p&gt;

&lt;p&gt;En el siguiente post aprenderemos a desplegar una aplicación a Kubernetes y creo que es una de las partes más satisfactorias de la serie porque es cuando vemos la aplicación finalmente ejecutandose y aprovechando las ventajas de Kubernetes como self-healing, auto escalamiento, balanceo de carga, etc.&lt;/p&gt;

&lt;p&gt;Espero que aprendieras leyendo este post, nos vemos en el siguiente!&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>aws</category>
      <category>terraform</category>
      <category>iac</category>
    </item>
    <item>
      <title>Picturesocial – ¿Qué es Kubernetes y por qué debería importarme?</title>
      <dc:creator>Jose Yapur</dc:creator>
      <pubDate>Tue, 10 May 2022 16:09:56 +0000</pubDate>
      <link>https://dev.to/develozombie/picturesocial-que-es-kubernetes-y-por-que-deberia-importarme-34gn</link>
      <guid>https://dev.to/develozombie/picturesocial-que-es-kubernetes-y-por-que-deberia-importarme-34gn</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/oOP0pPU_Ekk"&gt;
&lt;/iframe&gt;
&lt;br&gt;
En el post anterior, aprendimos sobre Containers y los pasos necesarios para contenerizar una aplicación. Sin embargo, crear un container sin pensar dónde desplegarlo es como tener tu casa dentro de una caja flotando en el medio del mar. Por más que suene tentador o escalofriante, definitivamente necesitarás electricidad, agua, gas, recolección de desechos, comida y tal vez un poco de interacción humana, si quieres llevar una vida sana y productiva. En este artículo vamos a aprender sobre Kubernetes, una de las piezas más importantes en la arquitectura de Picturesocial.&lt;/p&gt;

&lt;p&gt;Picturesocial tendrá varias APIs que queremos que sean mantenidas, desplegadas y desarrolladas de forma independiente, es por eso que decidimos usar una arquitectura de containers. Hablar de este tipo de arquitecturas no es tan complejo como suena. Simplemente significa que estás usando containers y un orquestador de containers. Un orquestador de containers es el que está a cargo de manejar todos los containers, réplicas, redes, almacenamiento y en general la infraestructura necesaria. El orquestador de contenedores más popular es Kubernetes gracias a su comunidad activa, soporte y ecosistema de integración.&lt;/p&gt;

&lt;p&gt;Kubernetes, o k8s para los amigos, es un orquestador de código abierto con un ecosistema amplio y de rápido crecimiento. Te ayuda a administrar el escalamiento y failover de tus containers, además te podría ayudar con:&lt;br&gt;
• Balanceo de Carga y Descubrimiento de Servicios: te permite balancear el trafico de red entre los containers y la infraestructura, así como a descubrir nuevas réplicas de containers o containers que fueron removidos.&lt;br&gt;
• Despliegue y rollback automático: puedes elegir cómo desplegar tus containers, cómo manejar actualizaciones y cómo prevenir caídas debido a updates, fallos en la infraestructura o errores en el contenedor.&lt;br&gt;
• Bin packing Automático: Kubernetes usará, optimizará se adaptará al poder de cómputo disponible basado en los límites que tu establezcas.&lt;br&gt;
• Autocuración: si un container falla, Kubernetes lo reiniciará hasta que funcione o lo eliminará y creará uno nuevo.&lt;/p&gt;

&lt;p&gt;Desplegar y mantener tu propio clúster de Kubernetes desde cero no es algo trivial y requiere un conocimiento profundo de cómo funciona Kubernetes, Linux, Virtualización, Redes, Seguridad y un abanico de otras tecnologías. Es por eso que Amazon Web Services tiene Amazon Elastic Kubernetes Engine (Amazon EKS), una solución de Kubernetes administrada por AWS que te ayuda a reducir la complejidad de la preparación de infraestructura y el setup de Kubernetes. Además, te ayuda a tener un entorno de Kubernetes más seguro con actualizaciones de seguridad aplicadas de forma automática a tu cluster.&lt;br&gt;
El manifiesto o El YAML&lt;/p&gt;

&lt;p&gt;Puedes comunicarte nativamente con un clúster de Kubernetes de dos formas: Kubectl (Kube Control) y llamando una API REST. Ambos métodos usan un cuerpo de petición común en formato YAML (Yet Another Markup Language), a este YAML lo llamamos el Manifiesto y contiene instrucciones detalladas sobre:&lt;br&gt;
• Lo que estamos desplegando.&lt;br&gt;
• Cómo lo estamos desplegando.&lt;br&gt;
• Qué estamos exponiendo.&lt;br&gt;
• Cómo lo estamos exponiendo.&lt;br&gt;
El siguiente, es un ejemplo de YAML que usaremos como plantilla para varias aplicaciones contenerizadas. Revisaremos los conceptos básicos de este YAML en este blog post.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#########################
# POD Definition
#########################
apiVersion: apps/v1
kind: Deployment
metadata:
  name: deploymentName
  labels:
    app: applicationName
spec:
  replicas: 1
  selector:
    matchLabels:
      app: applicationName
  template:
    metadata:
      labels:
        app: applicationName
    spec:
      containers:
      - name: applicationName
        image: [aws account id].dkr.ecr.[aws region].amazonaws.com/imageName
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
---
#########################
# Service Definition
#########################
kind: Service
apiVersion: v1
metadata:
  name: service-name
spec:
  selector:
    app: applicationName
  ports:
  - port: 80
    targetPort: 80
  type: LoadBalancer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Label
&lt;/h2&gt;

&lt;p&gt;Todo lo que esté dentro de Kubernetes necesita un Label, de esa forma identificas todos los recursos en el clúster y además es la forma en la que le dices a Kubernetes dónde mirar cada vez que ejecutas comandos Kubectl o peticiones al API REST.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;template:
    metadata:
      labels:
        app: applicationName
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Pods
&lt;/h2&gt;

&lt;p&gt;Un pod es el objecto más pequeño en Kubernetes y es el lugar donde los containers viven. Un pod puede tener más de un container pero se recomienda una relación de un container por pod para evitar acoplamiento y puntos únicos de fallo. Algunas consideraciones importantes son:&lt;br&gt;
• Los pods son efímeros, eso significa que si el container dentro de un pod falla entonces el resultado más probable es que Kubernetes reiniciará o eliminará el pod y creará uno nuevo. Cuando despliegas nuevas versiones del container, también se crean pods nuevos. Por lo que no debemos nunca asumir el pod como algo estático.&lt;br&gt;
• Una imagen de container debe ser especificada. Siempre se define como el nombre del repositorio y el nombre de la imagen, por ejemplo: [aws account id].dkr.ecr.[aws region].amazonaws.com/imageName&lt;br&gt;
• Es una buena práctica establecer límites de recursos. Tenemos dos tipos de control:&lt;br&gt;
o   Requests: este límite es la garantía de computo del pod. Es como cuando pides una pizza y tienes 30 minutos de garantía, eso no significa que la pizza no puede llegar antes, es solo un indicador para saber cuantos pedidos puede manejar un solo repartidor. Es lo mismo con Requests, especifica la garantía mínima de cómputo en un cluster. Si tus nodos tiene capacidad ociosa, lo más probable es que el pod obtenga más de lo garantizado.&lt;br&gt;
o   Limits: este es un límite estático para cualquier pod. Si tu especificas un Limit, incluso si tuvieras capacidad ociosa de cómputo, ese pod no consumirá más de lo que estableciste. Usando el mismo ejemplo del repartidor de pizza, es como decirle que bajo ninguna circunstancia puede entregar más de 3 pizzas al mismo tiempo.&lt;br&gt;
• Las unidades que usamos comúnmente en Kubernetes son:&lt;br&gt;
o   Mebibytes (MiB) expresados como Mi: para convertir de MiB a MB, multiplica MiB x 1.049&lt;br&gt;
o   Milicores (mc) expresados como m: 1 CPU Core es representado como 1000 milicores. Por ejemplo, 250m es 1/4 de un CPU Core.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;containers:
      - name: applicationName
        image: [aws account id].dkr.ecr.[aws region].amazonaws.com/imageName
        resources:
          requests:
            memory: "256Mi"
            cpu: "250m"
          limits:
            memory: "512Mi"
            cpu: "500m"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ReplicaSet
&lt;/h2&gt;

&lt;p&gt;Los pods están destinadas a replicarse basado en diferentes métricas como CPU o consumo de memoria. También podemos establecer valores estáticos como en el ejemplo a continuación donde configuramos una sola réplica. Al conjunto de réplicas de un pod lo llamamos ReplicaSet.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;spec:
  replicas: 1
  selector:
    matchLabels:
      app: applicationName
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Services
&lt;/h2&gt;

&lt;p&gt;Los pods no deben llamarse directamente, recuerda que son efímeros, lo que también significa que cada vez que actualizas o se crean nuevos, tanto los nombres como las IP varían. Los Services vienen a resolver ese problema directamente y ofrecer un punto único para llamar a una o multiples pods del mismo ReplicaSet. Vamos a enfocarnos en dos tipos de Service:&lt;br&gt;
• LoadBalancer: Este tipo de Service es usado cuando necesitas exponer un ReplicaSet fuera del clúster de Kubernetes, ya sea de forma pública al internet o privada dentro de una red local. En el caso de Amazon EKS, deberías tomar en cuenta dos cosas:&lt;br&gt;
o   Los nombres de Service deben siempre empezar con una letra y contener un guion (“-”) como separador. Por ejemplo: picturesocial-pictures&lt;br&gt;
o   Los LoadBalancer privados deben siempre tener una anotación que especifique que será publicado en una red local únicamente.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kind: Service
apiVersion: v1
metadata:
  name: service-name
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-scheme: "internal"
spec:
  selector:
    app: applicationName
  ports:
  - port: 80
    targetPort: 80
  type: LoadBalancer
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;• ClusterIP: Este tipo de Service es usado cuando necesitas exponer un réplica set para consumidores dentro del clúster de Kubernetes. Este es el enfoque más común debido a que los pods están más seguros si se mantienen dentro de los límites del clúster, de esta forma puedes agregar capas de seguridad para consumirlos como: ingress controller, mutual authentication, API Gateways, etc. Explicaremos un poco más de estos conceptos en futuros blog posts.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kind: Service
apiVersion: v1
metadata:
  name: service-Name
spec:
  selector:
    app: applicationName
  ports:
  - targetPort: 80
    port: 80
  type: ClusterIP
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Los Services siempre detectan cambios en el backend, de esta forma si un pod se cae o es reemplazado por uno nuevo, el Service detendrá el tráfico hacia ese pod y lo redireccionará a los pods que estén trabajando sin problemas. Es por eso que enfatizo que la comunicación síncrona entre pods debe hacerse siempre usando Services y no llamando pods de forma directa, incluso si tu API está contenida en solo un pod.&lt;/p&gt;

&lt;h2&gt;
  
  
  Namespace
&lt;/h2&gt;

&lt;p&gt;Kubernetes fue concebido como un orquestador de containers multi-tenant. Eso significa que fue diseñado como una solución capaz de gestionar múltiples aplicaciones y ambientes al mismo tiempo. Ahí es donde los Namespaces vienen a la acción. Los Namespaces trabajan como un separador de recursos lógico dentro de Kubernetes, puedes agrupar recursos (pods, services, etc.) en un Namespace específico y establecerle permisos. Por ejemplo, podrías decir que los pods en el Namespace A no pueden llamar a los pods del Namespace B. &lt;/p&gt;

&lt;p&gt;Mi sugerencia es que agrupes los recursos de un dominio de negocio en un namespace, de esa forma será más fácil encontrar los recursos que necesitas mientras que habilitas a equipos mantener dominios de negocio de forma independiente. &lt;/p&gt;

&lt;h2&gt;
  
  
  ¿Para qué tipo de aplicaciones debería usar Kubernetes?
&lt;/h2&gt;

&lt;p&gt;Usar Kubernetes para todo es cómo manejar un auto de Formula 1 para ir al supermercado. No me malinterpretes, definitivamente lo haría, pero al mismo tiempo no tiene sentido, ¿En qué cajuela pondría mis 3 pallets de café para la semana?&lt;/p&gt;

&lt;p&gt;Para determinar si usar o no Kubernetes yo suelo usar los siguientes criterios, esta no es una ciencia exacta y podría no adaptarse a tu escenario, pero me ha ayudado mucho en el pasado.&lt;br&gt;
• Tienes una arquitectura contenerizada con al menos 10 servicios ejecutándose y escalando de forma independiente y en la misma infraestructura.&lt;br&gt;
• Tus servicios tienen dependencias que viven en un ambiente restringido a una red local y necesitas políticas de tráfico y autenticación para invocar a esas dependencias.&lt;br&gt;
• Estás trabajando con diferentes equipos manteniendo y desarrollando diferentes componentes de la misma aplicación, de forma independiente.&lt;br&gt;
• Necesitas control sobre el cómputo, redes, políticas de redes, estrategia de despliegue y versionamiento del orquestador.&lt;br&gt;
• Necesitas una solución que se expanda de on-premises a la nube usando herramientas y procesos consistentes que trabajen bajo una estrategia de despliegue unificada. &lt;br&gt;
Si dos o más de esos criterios son verdaderos entonces Kubernetes es una buena opción.&lt;/p&gt;

&lt;p&gt;Yo sé que ha sido demasiada información para un solo blog post, pero también sé que, a pesar de sentirse abrumador, el propósito de este artículo es que juntos entendamos cómo funciona Kubernetes y familiarizarnos con los términos importantes. A medida que avancemos en la creación de Picturesocial veremos como estos conceptos son aplicados en los paso a paso.&lt;br&gt;
En el siguiente blog post aprenderemos cómo crear un clúster de Amazon EKS usando Terraform. Si te gustó este artículo te sugiero que mires el video de este segundo episodio en Youtube: &lt;a href="https://www.youtube.com/watch?v=VHCnyiWVBR4&amp;amp;feature=emb_title"&gt;https://www.youtube.com/watch?v=VHCnyiWVBR4&amp;amp;feature=emb_title&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>eks</category>
      <category>containers</category>
    </item>
    <item>
      <title>PictureSocial - Cómo contenerizar una aplicación en menos de 15 minutos</title>
      <dc:creator>Jose Yapur</dc:creator>
      <pubDate>Fri, 22 Apr 2022 15:41:52 +0000</pubDate>
      <link>https://dev.to/develozombie/picturesocial-como-contenerizar-una-aplicacion-en-menos-de-15-minutos-2b8h</link>
      <guid>https://dev.to/develozombie/picturesocial-como-contenerizar-una-aplicacion-en-menos-de-15-minutos-2b8h</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/471yiQh_BhE"&gt;
&lt;/iframe&gt;
&lt;br&gt;
Hablar de contenedores o containers en arquitectura de software es hablar de un hot topic. Algunos de nosotros hemos trabajado en esos conceptos por años mientras que otros recién están empezando. De todas formas, me gustaría ser quien te guíe en tu proceso de aprendizaje en containers. Juntos, en esta serie, construiremos Picturesocial, una nueva red social para compartir fotos que nacerá con una arquitectura basada en containers. Mientras la construimos tomaremos decisiones de arquitectura y exploraremos algunos retos y soluciones. &lt;/p&gt;

&lt;p&gt;Pero, ¿Qué es un container?&lt;br&gt;
Imagina la sala de tus sueños, con una pintura del color que te gusta, un sofá súper cómodo para leer o pasar el rato, una mesa de centro para poner la tasa de dos litros de café y ese libro de pinturas famosas de que nunca abriste pero se ve muy cool. Finalmente sientes que es el espacio perfecto, solo para darte cuenta que tienes que mudarte a otro lugar y comenzar todo el proceso desde cero.&lt;/p&gt;

&lt;p&gt;Ahora imagina que estás diseñando exactamente la misma sala pero dentro de uno de esos containers de metal que llevan los barcos de carga. Esa sala ira contigo a donde sea que vayas, puede estar en un barco en el medio del mar, en un avión o en un camión cruzando el país.&lt;br&gt;
Un container es exactamente eso, tu aplicación, runtime y sistema de archivos, todo empaquetado (como tu sala en un container de barco) para ejecutarse en cualquier lugar que soporte containers. A mi particularmente me gustan los container porque me dan la flexibilidad y libertad de correr mis aplicaciones donde quiera, cuando quiera y saber que funcionarán sin hacer cambios.&lt;/p&gt;

&lt;p&gt;Cuando trabajas sobre aplicaciones contenerizadas lo más probable es que tus dependencias como base de datos o manejador de colas, no estén dentro de containers sino como servicios externos, al menos en los ambientes productivos, por eso es súper importante que tengas un lugar donde poner la información de configuración de tu aplicación como cadenas conexión, zonas horarias y otros que puedas necesitar; de esa forma si pasas de un ambiente a otro como de Desarrollo a QA y luego a Producción solo necesitas apuntar a la configuración correcta y evitas errores como el mío, donde desplegué una nueva versión de un sitio web completo de alta concurrencia y en producción con la configuración de desarrollo, apuntando a una base de datos local donde todos los clientes tenían el nombre de mis gatos.&lt;/p&gt;

&lt;p&gt;Para iniciar vamos a aprender sobre algunos conceptos básicos de Docker container que nos ayudarán en nuestra ruta de aprendizaje.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;Image&lt;/em&gt;: Esta es una de las piezas fundamentales de un Container, es donde una aplicación y su estado viven. La imagen de un container está compuesta por la compilación de tu aplicación junto con un Dockerfile usando el demonio de Docker, que viene al instalar Docker en tu ambiente de desarrollo. Siempre pienso en la Imagen como un archivo ISO[1 (&lt;a href="https://es.wikipedia.org/wiki/Imagen_ISO)"&gt;https://es.wikipedia.org/wiki/Imagen_ISO)&lt;/a&gt;], de esos que usaba para capturar el estado de mi sistema operativo con archivos, configuraciones y aplicaciones instaladas, y que podía ser utilizada en casi cualquier otra computadora. Comparado con un ISO, una imagen de container solo tiene una pequeña parte del sistema operativo, algunas librerías que yo indique, el runtime y mi aplicación, por lo que termina siendo mucho más liviana y con menos requerimientos de computo al no tener que cargar un sistema operativo completo.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Container&lt;/em&gt;: Cuando una Imagen se ejecuta pasa a llamarse un Container.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Engine&lt;/em&gt;: Tu container necesita ejecutarse en algún lado donde Docker esté instalado. La forma que usa Docker para comunicarse con el Hardware donde está instalado es por medio de APIs, esas APIs son el Engine. Con el Engine, tu container obtiene acceso a los recursos de hardware como CPU, almacenamiento y redes.&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;Registry&lt;/em&gt;: Es el lugar donde almacenas tus Imagenes de Container. El  registry puede ser público o privado. Un registry no solo almacena la última (latest) imagen, sino también usa tags y metadata como 1/ cuándo fue subida tu imagen, 2/ quién sube la imagen y 3/ cuándo la imagen es usada. Es por eso que no podemos hablar de containers sin un registry, incluso cuando trabajamos localmente, nuestra computadora es el registry.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ahora que tenemos un poco de contexto vamos a dar un vistazo al Dockerfile. Para mi, el Dockerfile es lo que solía hacer cuando estaba iniciando mi carrera como practicante, algunos de nosotros estuvimos a cargo de “Escribir el Manual de Instalación”, si, ese manual que nadie realmente leía y que cuando era necesario nunca servía y que sin embargo el principal problema de ellos siempre ha sido que fue escrito por humanos para humanos, sin embargo, un Dockerfile es un manual creado por humanos para máquinas, por lo que debe ser escrito de forma muy precisa y resuelve la mayoría de problemas de interpretación.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build-env
WORKDIR /app
COPY . ./
RUN dotnet restore
RUN dotnet publish -c Release -o out
FROM mcr.microsoft.com/dotnet/aspnet:6.0
WORKDIR /app
COPY --from=build-env /app/out .
EXPOSE 5111
ENV ASPNETCORE_URLS=http://+:5111
ENTRYPOINT ["dotnet", "HelloWorld.dll"]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Todos los Dockerfile necesitan un FROM  y está usualmente ubicado en la primera línea. Es usado para especificar la imagen base que estás usando para crear tu propia imagen, por ejemplo, imagina que quieres crear una Imagen que necesita escribir un archivo en Ubuntu 20.04, entonces necesitarías un FROM similar a este:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;FROM ubuntu:20.04&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Del ejemplo de arriba podemos deducir cierta información básica sobre tagging. 1/ Ubuntu es el nombre de la imagen, tenemos disponibles millones de imágenes en Docker Hub , que en su mayaría son públicas y podemos usar para crear nuestras aplicaciones derivadas o usarlas tal cual. 2/ 20.04 es la versión de Ubuntu, luego de los dos puntos (“:”) siempre se indica el tag de la imagen, puedes usar tagging para especificar versiones de un app, ambientes, lenguajes, o lo que quieras . Si revisamos la pagina de la imagen de Ubuntu en Docker Hub podremos ver los diferentes tags disponibles y sus descripciones. &lt;a href="https://hub.docker.com/_/ubuntu?tab=description"&gt;https://hub.docker.com/_/ubuntu?tab=description&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Algunos otros comandos importantes de Docker son:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;RUN&lt;/em&gt;: usado para ejecutar múltiples comandos bash para preparar un container. Puedes usar RUN múltiples veces en tu Dockerfile. Por ejemplo el siguiente comando creará un directorio demo en el container.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;RUN mkdir demo&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;CMD&lt;/em&gt;: usado para ejecutar comandos bash que solo pueden ser usados una vez, si tienes más de un CMD  solo se ejecutará el último. CMD se utiliza para proveer valores por defecto a tu container. Por ejemplo, el siguiente comando creará un archivo llamado config e la carpeta .conf con el texto Hello World.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;CMD ["echo", "Hello World"]&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Si quieres conocer más sobre los comandos de Dockerfile, este link &lt;a href="https://docs.docker.com/engine/reference/builder"&gt;https://docs.docker.com/engine/reference/builder&lt;/a&gt; será de mucha ayuda. Además si quieres ver ejemplos de Dockerfile para varios lenguajes de programación y runtimes, puedes revisar este link &lt;a href="https://docs.docker.com/samples/"&gt;https://docs.docker.com/samples/&lt;/a&gt;. Cuando creas tus propios Dockerfile es como cuando escribes un cuaderno de recetas, puedes reusarlo para aplicaciones similares cambiando pocas cosas , en mi caso usaré el mismo template de Dockerfile para todas las APIs .NET 6 que expondré en Picturesocial. &lt;/p&gt;

&lt;p&gt;Ahora que tenemos un poco de contexto sobre containers, quiero contarles sobre Amazon Elastic Container Registry o Amazon ECR para los amigos. Puedes usar ECR para almacenar tus imágenes de container ya sea de forma pública o privada, la ventaja es que el acceso a tus imágenes es manejado por AWS Identity and Access Management (IAM) y es nativo de Docker, por lo que los comandos que ejecutas localmente con el Docker CLI son los mismos que ejecutarías para hacer operaciones ECR, como docker login o docker push&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Pre-requisitos:&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Una cuenta de AWS, si no tienes puedes pedir una aquí: &lt;a href="https://aws.amazon.com/free/"&gt;https://aws.amazon.com/free/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Si estás usando Microsoft Windows te sugiero trabajar usando WSL2: &lt;a href="https://docs.microsoft.com/en-us/windows/wsl/install"&gt;https://docs.microsoft.com/en-us/windows/wsl/install&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Si no tienes Git, desde acá puedes instalarlo: &lt;a href="https://github.com/git-guides/install-git"&gt;https://github.com/git-guides/install-git&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Si no tienes Docker instalado, acá las instrucciones &lt;a href="https://docs.docker.com/engine/install/"&gt;https://docs.docker.com/engine/install/&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Acá los pasos para instalar AWS CLI &lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html"&gt;https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Si esta es tu primera vez trabajando con AWS CLI o necesitas un refresh de como setear tus credenciales en el terminal te sugiero seguir este paso a paso: &lt;a href="https://aws.amazon.com/es/getting-started/guides/setup-environment/"&gt;https://aws.amazon.com/es/getting-started/guides/setup-environment/&lt;/a&gt;. Si no quieres instalar todo desde cero, en este mismo link podrás seguir los pasos para configurar Amazon Cloud9 que es un entorno de desarrollo virtual, que incluye casi todo el toolset que necesitas para este paso a paso.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Paso a paso:&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;En esta oportunidad vamos a aprender sobre cómo contenerizar una API desarrollada en .NET 6 que retorna el texto pasado como parámetro en la URL, este template de API será usado para todas las API’s de Picturesocial. Vamos a contenerizar todo para mantener consistencia entre el ambiente de desarrollo local y los ambientes en nube.&lt;/p&gt;

&lt;p&gt;He creado un repositorio de Github &lt;a href="https://github.com/aws-samples/picture-social-sample"&gt;https://github.com/aws-samples/picture-social-sample&lt;/a&gt; con todo el código necesario para seguir este paso a paso, asegúrate de seleccionar la branch “ep1”.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Primero, vamos a clonar nuestro repo base, así tendremos todos los archivos de esta API así como también el Dockerfile que usaremos para crear la imagen de container.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;git clone https://github.com/aws-samples/picture-social-sample --branch ep1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Una vez clonado, vayamos al directorio creado. Aseguremonos de siempre estar dentro de este directorio por el resto de esta guía, de esa forma todo se ejecutará sin problemas.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;cd picture-social-sample/HelloWorld
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Ahora, antes de iniciar con los siguientes pasos, vamos a revisar si Docker está instalado correctamente y funcionando, probemos el siguiente comando y deberíamos recibir que tenemos al menos la versión 20.10.
&lt;/li&gt;
&lt;/ul&gt;

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

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Si abres el Dockerfile, que está dentro de nuestra carpeta, encontrarás exactamente la misma estructura que el que compartí en este artículo. No tengas miedo, cambia cosas y juega con el, la mejor forma de aprender siempre es experimentando por nuestra cuenta, equivocándonos y descubriendo cómo arreglarlo. Acá te doy algunas sugerencias de qué cosas probar.

&lt;ul&gt;
&lt;li&gt;Añade una línea que imprima Hello World en el proceso de build de nuestra imagen de container.
&lt;code&gt;RUN echo “Hello World”&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Cambia el WORKDIR de app a api, asegúrate de cambiar todas las referencias a app en las lineas 2, 11 y 12 del Dockerfile.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Ahora vamos a construir la imagen de container. Usaremos el comando docker build que será el responsable de crear la imagen, para ello usamos el parámetro -t para especificar el nombre de la imagen, tal como aprendimos antes, la estructura del nombre es nombreDeImagen:nombreDeTag si no especificamos un nombreDeTag se creará uno por defecto con el nombre latest. Finalmente especificamos el path donde nuestro Dockerfile está localizado, si seguimos en la carpeta HelloWorld, entonces nuestro path será un punto (.) debido a que se encuentra en el mismo directorio.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker build -t helloworld:latest .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Algo que aprendí mientras escribía este artículo es que si estás usando una Apple MacBook con Apple Silicon, el comando cambia un poco, de esta forma indicamos que construiremos la imagen para ejecutarse en linux/amd64.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker buildx build —platform=linux/amd64 -t helloworld:latest .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Ahora vamos a ejecutar esta imagen y convertirla en un Container, para ello usaremos el comando docker run , por medio del parametro -d diremos que este container puede ejecutarse en segundo plano y con el parametro  -p le diremos el puerto del container y el puerto que expondremos. Tal como podemos ver en nuestro Dockerfile, el container está usando el puerto 51111 y estamos mapeando el mismo puerto en el siguiente comando:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker run -d -p 5111:5111 helloworld:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Después de ejecutar este comando podremos abrir el navegador y escribir &lt;a href="http://localhost:5111/api/HelloWorld/johndoe"&gt;http://localhost:5111/api/HelloWorld/johndoe&lt;/a&gt; (&lt;a href="http://localhost:5111/api/HelloWorld/jhondoe"&gt;http://localhost:5111/api/HelloWorld/jhondoe&lt;/a&gt;) y si todo salió bien deberíamos recibir de respuesta un “Hello johndoe”, puedes cambiar el valor de la url a cualquier valor y probar que el API contenerizada devuelva el mensaje. Ahora que estamos obteniendo los valores esperados vamos a seguir con los pasos necesarios para subir la imagen a nuestro container registry privado, nuestro propio repositorio de ECR llamado “helloworld”. Para eso ejecutamos el siguiente comando de AWS CLI, donde creamos el respositorio y por medio del parametro —repository-name indicamos el nombre “helloworld”
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws ecr create-repository --repository-name helloworld
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Ahora descubramos cual es el nombre de dominio calificado (FQDN) de nuestro registry, de forma que en los siguientes pasos podamos renombrar nuestras imagenes con el nombre completo, esa es la forma que usa Docker para identificar imagenes locales o remotas. Para este proyecto usaremos la región us-east-1 y asumiremos que nuestro AWS Account Id es 111122223333 por lo que el nombre debería quedar así:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[aws account id].dkr.ecr.[aws region].amazonaws.com
#for example for account id: 111122223333 on region: us-east-1
111122223333.dkr.ecr.us-east-1.amazonaws.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Ya tenemos el nombre de nuestro registry, ahora vamos a iniciar sesión en el CLI de Docker, recuerda reemplazar el  AWS Account Id y la región, tal como lo hicimos en el paso anterior. Cuando iniciamos sesión en Docker le estamos dando acceso a nuestro ambiente local para hacer push de imágenes de containers a un repositorio remoto como ECR.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin [aws account id].dkr.ecr.[aws region].amazonaws.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Ahora ya estamos listos para hacer push de nuestra imagen, pero primero tenemos que cambiarle el nombre de forma que incluya el FQDN, caso contrario no la podremos subir a nuestro repositorio remoto, esto sucede porque Docker no reconoce a donde pertenece sin que se lo digas explícitamente. Al ejecutar este comando obtendrás un id de digest, eso significa que hiciste bien.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker tag helloworld:latest [aws account id].dkr.ecr.[aws region].amazonaws.com/helloworld:latest
docker push [aws account id].dkr.ecr.[aws region].amazonaws.com/helloworld:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Si seguiste los pasos hasta acá, significa que ¡Lo lograste! Felicitaciones, contenerizaste tu primera aplicación. Tambien puedes ver el video para tener más detalles, en este &lt;a href="https://play.vidyard.com/6PA7KCQ3SeN214iyMuvhX5"&gt;Link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;El siguiente post estará enfocado en aprender acerca de Kubernetes, intentaré responder a la pregunta: ¿Qué es Kubernetes y por qué debería importarme?&lt;/p&gt;

</description>
      <category>aws</category>
      <category>containers</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
