Crear un registry en AWS ECR para nuestras imagenes de frontend y backend
Necesitaremos deployar las imagenes de nuestro frontend y backend al registry de amazon (ECR) para que nuestros pods puedan tomar pullear esas imagenes.
Para crear el recurso ECR debemos crear el siguiente archivo terraform/9-ecr.tf:
Pusheamos para correr el pipeline y si vamos a nuestro ECR deberiamos ver lo siguiente:
Pushear nuestras imagenes del frontend y backend
Para el frontend crearemos una aplicacion simple de NextJS y para nuestro backend un servidor HTTP simple con Kotlin. El codigo del frontend y backend pueden copiarlo del repositorio de este tutorial, lo que veremos aqui es como crear los Dockerfile y como pushear las imagenes al registry con GitHub Actions.
Backend
Una vez que ya tengamos el codigo de nuestro backend (tomar de referencia el del repositorio), debemos crear el siguiente Dockerfile para construir la imagen de nuestro back.
Y dentro de la carpeta .github/workflows crearemos el archivo backend.yml para pushear nuestra imagen al registry de amazon previamente creado para nuestro backend.
La funcion de este archivo es que cada vez que se modifique el backend, se active el pipeline para pushear la nueva imagen del backend al registry de amazon. Una vez que pusheemos podemos corroborrar que en repositorio de nuestra imagen en ECR esta la imagen buildeada.
Frontend
Una vez que ya tengamos el codigo de nuestro frontend (tomar de referencia el del repositorio), debemos crear el siguiente Dockerfile para construir la imagen de nuestro front.
Y dentro de la carpeta .github/workflows crearemos el archivo frontend.yml para pushear nuestra imagen al registry de amazon previamente creado para nuestro backend.
La funcion de este archivo es que cada vez que se modifique el frontend, se active el pipeline para pushear la nueva imagen del frontend al registry de amazon. Una vez que pusheemos podemos corroborrar que en repositorio de nuestra imagen en ECR esta la imagen buildeada.
Desplegar nuestros pods
El proximo paso es desplegar nuestro backend y frontend a nuestro cluster. Para eso debemos crear otro Fargate profile, ya que nuestro pods estaran en un namespace diferente al de kube-system. Recordemos que por cada namespace necesitamos un Fargate profile para otorgarle privilegios a Fargate para que pueda crear nodos y asignarlos a nuestros pods.
Para crear el Fargate profile crearemos el archivo terraform/8-staging-profile.tf con lo siguiente:
En la raiz del proyecto crearemos una carpeta llamada k8s y ahi escribiremos nuestros archivos de Kubernetes.
Primero el namespace de staging en k8s/amespace.yaml:
El frontend en k8s/rontend-deployent.yaml:
Y el backend en backend-deployment.yaml:
Para probar que nuestros archivos esten correctos, podemos aplicarlos con kubectl antes de automatizar este proceso. Para eso debemos correr los siguientes comandos.
Luego de unos minutos si ejecutamos el comando kubectl get pods -n staging podemos ver que nuestros pods ya estan deployados.
Ahora para automatizar este proceso debemos modificar nuestros archivos .github/workflows/backend.yml y .github/workflows/frontend.yml lo que se agrega a estos archivos es la configuracion de aws-cli, la instalacion de kubectl, actualizar kube config para que kubectl este apuntando a nuestro cluster y por ultimo aplicar los archivos correspondientes de kubernetes.
Dentro de .github/workflows/frontend.yml:
Dentro de .github/workflows/backend.yml:
Crear servicios para nuestros pods
Es tiempo de crear servicios a nuestros pods para que proximamente esten expuestos a internet a traves de un ingress.
Dentro de la carpeta k8s crearemos un archivo frontend-service.yaml y otro backend-service.yaml
En k8s/frontend-service.yaml
Y en k8s/backend-service.yaml
Para crear los servicios deberemos agregar
en: .github/workflows/backend.yml
luego de la linea para aplicar el deployment, la siguiente linea kubectl apply -f k8s/backend-service.yaml
y en: .github/workflows/frontend.yml
luego de la linea para aplicar el deployment, la siguiente linea kubectl apply -f k8s/frontend-service.yaml
Para poder ver los servicios que creamos podemos ejecutar kubectl get services -n staging
Mejorar la estabilidad de nuestros pods con Pod Disruption Budget
Amazon EKS debe periodicamente patchear los pods que corren en nodos de AWS Fargate para mantenerlos seguros. A veces esto significa que los pods necesitan ser recreados. Para limitar el impacto en nuestra aplicacion debemos crear un pod disruption budget apropiado para controlar el numero de pods que estan caidos al mismo tiempo.
Para eso dentro de la carpeta k8s crearemos los siguientes archivos:
k8s/frontend-pdb.yaml:
k8s/ackend-pdb.yaml:
Para crear los pod disruption badgets deberemos agregar
en: .github/workflows/backend.yml
luego de la linea para aplicar el service, la siguiente linea kubectl apply -f k8s/backend-pdb.yaml
y en: .github/workflows/frontend.yml
luego de la linea para aplicar el service, la siguiente linea kubectl apply -f k8s/frontend-pdb.yaml
Para poder ver los servicios que creamos podemos ejecutar kubectl get pdb -n staging
Crear IAM OIDC provider usando Terraform
Podemos asociar un IAM role a una Kubernetes service account. Esta service account puede proveer AWS permissions a los container en cualquier pod que este usando esa service account.
Con este feature no es mas necesario configurar a mano los permisos de los nodos para que los pods puedan hacer llamadas a AWS APIs.
Esta service account la necesitaremos para un pod que va a necesitar tener permisos para crear load balancers.
Para eso dentro de la carpeta k8s crearemos el archivo 10-iam-oidc.tf :
Una vez que pusheamos podemos corroborrar que se se creo el IAM OIDC provider con el siguiente comando
El proximo paso es deployar un AWS Load Balancer controller, pero primero, necesitamos un IAM role y establecer confianza con la Kubernetes service account.
Tendremos un pod con este AWS Load Balancer controller que estara viendo cuando se crea un ingress, en el momento que se crea un ingress, el pod creara un Application Load Balancer basandose en la definicion del ingress. Es por eso que necesitamos establecer confianza con la Kubernetes service account, para que permita a este pod crear recursos como el Application Load Balancer.
Crearemos el archivo terraform/11-iam-lb-controller.tf:
Ademas debemos crear el archivo AWSLoadBalancerController.json que tendra la policy con los permisos necesarios para el IAM role.
Dentro de la carpeta terraform crear terraform/AWSLoadBalancerController.json:
Por ultimo creamos la controller usando Helm, ya que la definicion para el pod ya esta hecha por AWS.
Creamos el archivo terraform/12-lb-controller.tf
Pusheamos para que se apliquen los cambios en terraform.
Si corremos el comando kubectl get pods -n kube-system, veremos que ya tenemos nuestro pod con la AWS Load Balancer Controller: