AWS EKS Fargate with Terraform (2)
En la segunda parte de este tutorial veremos como desplegar nuestras aplicaciones al cluster
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
:
resource "aws_ecr_repository" "frontend" {name = "frontend"}resource "aws_ecr_repository" "backend" {name = "backend"}
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.
docker
FROM gradle:7.2.0-jdk16 as builderUSER rootARG COMMIT_SHAADD . .RUN printf %s ".${COMMIT_SHA}" >> VERSIONRUN gradle --parallel --build-cache -Dorg.gradle.console=plain -Dorg.gradle.daemon=false :shadowJar###########################################################################FROM openjdk:16-alpineENV PORT 6060WORKDIR /appCOPY --from=builder /home/gradle/build/libs/backend_api.jar backend_api.jarEXPOSE $PORTCMD java -Xms256m -Xmx256m -Xss512k -jar backend_api.jar
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.
yaml
on:push:branches:- mainpaths:- backend/*- .github/workflows/backend.ymljobs:backend-push-image:runs-on: ubuntu-latestenv:AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}steps:- name: Checkout repositoryuses: actions/checkout@v2- name: Deploy apirun: |cd backendecho "Build docker image"docker build --tag backend:latest --build-arg COMMIT_SHA=${GITHUB_SHA} .echo "Push image to ECR"docker run --rm -e AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} -e AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} amazon/aws-cli ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 186990837788.dkr.ecr.us-east-1.amazonaws.com/backenddocker tag backend:latest 186990837788.dkr.ecr.us-east-1.amazonaws.com/backend:latestdocker push 186990837788.dkr.ecr.us-east-1.amazonaws.com/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.
docker
# Install dependencies only when neededFROM node:16-alpine AS deps# Check https://github.com/nodejs/docker-node/tree/b4117f9333da4138b03a546ec926ef50a31506c3#nodealpine to understand why libc6-compat might be needed.RUN apk add --no-cache libc6-compatWORKDIR /app# Install dependencies based on the preferred package managerCOPY package.json yarn.lock* package-lock.json* pnpm-lock.yaml* ./RUN \if [ -f yarn.lock ]; then yarn --frozen-lockfile; \elif [ -f package-lock.json ]; then npm ci; \elif [ -f pnpm-lock.yaml ]; then yarn global add pnpm && pnpm i; \else echo "Lockfile not found." && exit 1; \fi# Rebuild the source code only when neededFROM node:16-alpine AS builderWORKDIR /appCOPY --from=deps /app/node_modules ./node_modulesCOPY . .# Next.js collects completely anonymous telemetry data about general usage.# Learn more here: https://nextjs.org/telemetry# Uncomment the following line in case you want to disable telemetry during the build.# ENV NEXT_TELEMETRY_DISABLED 1RUN yarn build# If using npm comment out above and use below instead# RUN npm run build# Production image, copy all the files and run nextFROM node:16-alpine AS runnerWORKDIR /appENV NODE_ENV production# Uncomment the following line in case you want to disable telemetry during runtime.# ENV NEXT_TELEMETRY_DISABLED 1RUN addgroup --system --gid 1001 nodejsRUN adduser --system --uid 1001 nextjs# You only need to copy next.config.js if you are NOT using the default configuration# COPY --from=builder /app/next.config.js ./COPY --from=builder /app/public ./publicCOPY --from=builder /app/package.json ./package.json# Automatically leverage output traces to reduce image size# https://nextjs.org/docs/advanced-features/output-file-tracingCOPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/staticUSER nextjsEXPOSE 3000ENV PORT 3000CMD ["node", "server.js"]
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.
yaml
on:push:branches:- mainpaths:- frontend/*- .github/workflows/frontend.ymljobs:frontend-push-image:runs-on: ubuntu-latestenv:AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}steps:- name: Checkout repositoryuses: actions/checkout@v2- name: Push frontend imagerun: |cd frontendecho "Build docker image"docker build --tag frontend:latest --build-arg COMMIT_SHA=${GITHUB_SHA} .echo "Push image to ECR"docker run --rm -e AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} -e AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} amazon/aws-cli ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 186990837788.dkr.ecr.us-east-1.amazonaws.com/frontenddocker tag frontend:latest 186990837788.dkr.ecr.us-east-1.amazonaws.com/frontend:latestdocker push 186990837788.dkr.ecr.us-east-1.amazonaws.com/frontend
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:
resource "aws_eks_fargate_profile" "staging" {cluster_name = aws_eks_cluster.cluster.namefargate_profile_name = "staging"pod_execution_role_arn = aws_iam_role.eks-fargate-profile.arn# These subnets must have the following resource tag:# kubernetes.io/cluster/<CLUSTER_NAME>.subnet_ids = [aws_subnet.private-us-east-1a.id,aws_subnet.private-us-east-1b.id]selector {namespace = "staging"}}
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
:
yaml
---apiVersion: v1kind: Namespacemetadata:name: staging
El frontend en k8s/rontend-deployent.yaml
:
yaml
---apiVersion: apps/v1kind: Deploymentmetadata:name: frontendnamespace: stagingspec:selector:matchLabels:run: frontend# remove replica if using gitopsreplicas: 1template:metadata:labels:run: frontendspec:containers:- name: frontendimage: 186990837788.dkr.ecr.us-east-1.amazonaws.com/frontend # Es importante colocar la direccion de su registryports:- containerPort: 3000resources:limits:cpu: 200mmemory: 256Mirequests:cpu: 200mmemory: 256Mi
Y el backend en backend-deployment.yaml
:
yaml
---apiVersion: apps/v1kind: Deploymentmetadata:name: backendnamespace: stagingspec:selector:matchLabels:run: backend# remove replica if using gitopsreplicas: 1template:metadata:labels:run: backendspec:containers:- name: backendimage: 186990837788.dkr.ecr.us-east-1.amazonaws.com/backend # Es importante colocar la direccion de su registryports:- containerPort: 6060resources:limits:cpu: 200mmemory: 256Mirequests:cpu: 200mmemory: 256Mi
Para probar que nuestros archivos esten correctos, podemos aplicarlos con kubectl antes de automatizar este proceso. Para eso debemos correr los siguientes comandos.
bash
ldamore@Desktop/aws-eks-fargate:~ kubectl apply -f k8s/namespace.yamlldamore@Desktop/aws-eks-fargate:~ kubectl apply -f k8s/frontend-deployment.yamlldamore@Desktop/aws-eks-fargate:~ kubectl apply -f k8s/backend-deployment.yaml
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
:
yaml
on:push:branches:- mainpaths:- frontend/*- .github/workflows/frontend.ymljobs:frontend-push-image:runs-on: ubuntu-latestenv:AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}steps:- name: Checkout repositoryuses: actions/checkout@v2- name: Install kubectluses: azure/setup-kubectl@v1with:version: 'v1.21.3'id: install- name: Configure AWS credentialsuses: aws-actions/configure-aws-credentials@v1with:aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}aws-region: us-east-1- name: Push frontend imagerun: |cd frontendecho "Build docker image"docker build --tag frontend:latest --build-arg COMMIT_SHA=${GITHUB_SHA} .echo "Push image to ECR"docker run --rm -e AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} -e AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} amazon/aws-cli ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 186990837788.dkr.ecr.us-east-1.amazonaws.com/frontenddocker tag frontend:latest 186990837788.dkr.ecr.us-east-1.amazonaws.com/frontend:latestdocker push 186990837788.dkr.ecr.us-east-1.amazonaws.com/frontend- name: Update kube configrun: aws eks update-kubeconfig --name demo --region us-east-1- name: Deploy image to Amazon EKSrun: |kubectl apply -f k8s/frontend-deployment.yaml
Dentro de .github/workflows/backend.yml
:
yaml
on:push:branches:- mainpaths:- backend/*- .github/workflows/backend.ymljobs:backend-push-image:runs-on: ubuntu-latestenv:AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}steps:- name: Checkout repositoryuses: actions/checkout@v2- name: Install kubectluses: azure/setup-kubectl@v1with:version: 'v1.21.3'id: install- name: Configure AWS credentialsuses: aws-actions/configure-aws-credentials@v1with:aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}aws-region: us-east-1- name: Push backend imagerun: |cd backendecho "Build docker image"docker build --tag backend:latest --build-arg COMMIT_SHA=${GITHUB_SHA} .echo "Push image to ECR"docker run --rm -e AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} -e AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} amazon/aws-cli ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 186990837788.dkr.ecr.us-east-1.amazonaws.com/backenddocker tag backend:latest 186990837788.dkr.ecr.us-east-1.amazonaws.com/backend:latestdocker push 186990837788.dkr.ecr.us-east-1.amazonaws.com/backend- name: Update kube configrun: aws eks update-kubeconfig --name demo --region us-east-1- name: Deploy image to Amazon EKSrun: |kubectl apply -f k8s/backend-deployment.yaml
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
yaml
apiVersion: v1kind: Servicemetadata:name: frontendnamespace: staginglabels:app: frontendspec:type: NodePortselector:app: frontendports:- port: 80targetPort: 3000
Y en k8s/backend-service.yaml
yaml
apiVersion: v1kind: Servicemetadata:name: backendnamespace: staginglabels:app: backendspec:type: NodePortselector:app: backendports:- port: 80targetPort: 6060
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
:
yaml
---apiVersion: policy/v1kind: PodDisruptionBudgetmetadata:name: frontendnamespace: stagingspec:maxUnavailable: 1selector:matchLabels:run: frontend
k8s/ackend-pdb.yaml
:
yaml
---apiVersion: policy/v1kind: PodDisruptionBudgetmetadata:name: backendnamespace: stagingspec:maxUnavailable: 1selector:matchLabels:run: backend
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
:
data "tls_certificate" "eks" {url = aws_eks_cluster.cluster.identity[0].oidc[0].issuer}resource "aws_iam_openid_connect_provider" "eks" {client_id_list = ["sts.amazonaws.com"]thumbprint_list = [data.tls_certificate.eks.certificates[0].sha1_fingerprint]url = aws_eks_cluster.cluster.identity[0].oidc[0].issuer}
Una vez que pusheamos podemos corroborrar que se se creo el IAM OIDC provider con el siguiente comando
bash
aws iam list-open-id-connect-providers
Desplegat AWS Load Balancer Controller usando Terraform
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
:
data "aws_iam_policy_document" "aws_load_balancer_controller_assume_role_policy" {statement {actions = ["sts:AssumeRoleWithWebIdentity"]effect = "Allow"condition {test = "StringEquals"variable = "${replace(aws_iam_openid_connect_provider.eks.url, "https://", "")}:sub"values = ["system:serviceaccount:kube-system:aws-load-balancer-controller"]}principals {identifiers = [aws_iam_openid_connect_provider.eks.arn]type = "Federated"}}}resource "aws_iam_role" "aws_load_balancer_controller" {assume_role_policy = data.aws_iam_policy_document.aws_load_balancer_controller_assume_role_policy.jsonname = "aws-load-balancer-controller"}resource "aws_iam_policy" "aws_load_balancer_controller" {policy = file("./AWSLoadBalancerController.json")name = "AWSLoadBalancerController"}resource "aws_iam_role_policy_attachment" "aws_load_balancer_controller_attach" {role = aws_iam_role.aws_load_balancer_controller.namepolicy_arn = aws_iam_policy.aws_load_balancer_controller.arn}output "aws_load_balancer_controller_role_arn" {value = aws_iam_role.aws_load_balancer_controller.arn}
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
:
json
{"Version": "2012-10-17","Statement": [{"Effect": "Allow","Action": ["iam:CreateServiceLinkedRole"],"Resource": "*","Condition": {"StringEquals": {"iam:AWSServiceName": "elasticloadbalancing.amazonaws.com"}}},{"Effect": "Allow","Action": ["ec2:DescribeAccountAttributes","ec2:DescribeAddresses","ec2:DescribeAvailabilityZones","ec2:DescribeInternetGateways","ec2:DescribeVpcs","ec2:DescribeVpcPeeringConnections","ec2:DescribeSubnets","ec2:DescribeSecurityGroups","ec2:DescribeInstances","ec2:DescribeNetworkInterfaces","ec2:DescribeTags","ec2:GetCoipPoolUsage","ec2:DescribeCoipPools","elasticloadbalancing:DescribeLoadBalancers","elasticloadbalancing:DescribeLoadBalancerAttributes","elasticloadbalancing:DescribeListeners","elasticloadbalancing:DescribeListenerCertificates","elasticloadbalancing:DescribeSSLPolicies","elasticloadbalancing:DescribeRules","elasticloadbalancing:DescribeTargetGroups","elasticloadbalancing:DescribeTargetGroupAttributes","elasticloadbalancing:DescribeTargetHealth","elasticloadbalancing:DescribeTags"],"Resource": "*"},{"Effect": "Allow","Action": ["cognito-idp:DescribeUserPoolClient","acm:ListCertificates","acm:DescribeCertificate","iam:ListServerCertificates","iam:GetServerCertificate","waf-regional:GetWebACL","waf-regional:GetWebACLForResource","waf-regional:AssociateWebACL","waf-regional:DisassociateWebACL","wafv2:GetWebACL","wafv2:GetWebACLForResource","wafv2:AssociateWebACL","wafv2:DisassociateWebACL","shield:GetSubscriptionState","shield:DescribeProtection","shield:CreateProtection","shield:DeleteProtection"],"Resource": "*"},{"Effect": "Allow","Action": ["ec2:AuthorizeSecurityGroupIngress","ec2:RevokeSecurityGroupIngress"],"Resource": "*"},{"Effect": "Allow","Action": ["ec2:CreateSecurityGroup"],"Resource": "*"},{"Effect": "Allow","Action": ["ec2:CreateTags"],"Resource": "arn:aws:ec2:*:*:security-group/*","Condition": {"StringEquals": {"ec2:CreateAction": "CreateSecurityGroup"},"Null": {"aws:RequestTag/elbv2.k8s.aws/cluster": "false"}}},{"Effect": "Allow","Action": ["ec2:CreateTags","ec2:DeleteTags"],"Resource": "arn:aws:ec2:*:*:security-group/*","Condition": {"Null": {"aws:RequestTag/elbv2.k8s.aws/cluster": "true","aws:ResourceTag/elbv2.k8s.aws/cluster": "false"}}},{"Effect": "Allow","Action": ["ec2:AuthorizeSecurityGroupIngress","ec2:RevokeSecurityGroupIngress","ec2:DeleteSecurityGroup"],"Resource": "*","Condition": {"Null": {"aws:ResourceTag/elbv2.k8s.aws/cluster": "false"}}},{"Effect": "Allow","Action": ["elasticloadbalancing:CreateLoadBalancer","elasticloadbalancing:CreateTargetGroup"],"Resource": "*","Condition": {"Null": {"aws:RequestTag/elbv2.k8s.aws/cluster": "false"}}},{"Effect": "Allow","Action": ["elasticloadbalancing:CreateListener","elasticloadbalancing:DeleteListener","elasticloadbalancing:CreateRule","elasticloadbalancing:DeleteRule"],"Resource": "*"},{"Effect": "Allow","Action": ["elasticloadbalancing:AddTags","elasticloadbalancing:RemoveTags"],"Resource": ["arn:aws:elasticloadbalancing:*:*:targetgroup/*/*","arn:aws:elasticloadbalancing:*:*:loadbalancer/net/*/*","arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*/*"],"Condition": {"Null": {"aws:RequestTag/elbv2.k8s.aws/cluster": "true","aws:ResourceTag/elbv2.k8s.aws/cluster": "false"}}},{"Effect": "Allow","Action": ["elasticloadbalancing:AddTags","elasticloadbalancing:RemoveTags"],"Resource": ["arn:aws:elasticloadbalancing:*:*:listener/net/*/*/*","arn:aws:elasticloadbalancing:*:*:listener/app/*/*/*","arn:aws:elasticloadbalancing:*:*:listener-rule/net/*/*/*","arn:aws:elasticloadbalancing:*:*:listener-rule/app/*/*/*"]},{"Effect": "Allow","Action": ["elasticloadbalancing:ModifyLoadBalancerAttributes","elasticloadbalancing:SetIpAddressType","elasticloadbalancing:SetSecurityGroups","elasticloadbalancing:SetSubnets","elasticloadbalancing:DeleteLoadBalancer","elasticloadbalancing:ModifyTargetGroup","elasticloadbalancing:ModifyTargetGroupAttributes","elasticloadbalancing:DeleteTargetGroup"],"Resource": "*","Condition": {"Null": {"aws:ResourceTag/elbv2.k8s.aws/cluster": "false"}}},{"Effect": "Allow","Action": ["elasticloadbalancing:RegisterTargets","elasticloadbalancing:DeregisterTargets"],"Resource": "arn:aws:elasticloadbalancing:*:*:targetgroup/*/*"},{"Effect": "Allow","Action": ["elasticloadbalancing:SetWebAcl","elasticloadbalancing:ModifyListener","elasticloadbalancing:AddListenerCertificates","elasticloadbalancing:RemoveListenerCertificates","elasticloadbalancing:ModifyRule"],"Resource": "*"}]}
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
provider "helm" {kubernetes {host = aws_eks_cluster.cluster.endpointcluster_ca_certificate = base64decode(aws_eks_cluster.cluster.certificate_authority[0].data)exec {api_version = "client.authentication.k8s.io/v1beta1"args = ["eks", "get-token", "--cluster-name", aws_eks_cluster.cluster.id]command = "aws"}}}resource "helm_release" "aws-load-balancer-controller" {name = "aws-load-balancer-controller"repository = "https://aws.github.io/eks-charts"chart = "aws-load-balancer-controller"namespace = "kube-system"version = "1.4.1"set {name = "clusterName"value = aws_eks_cluster.cluster.id}set {name = "image.tag"value = "v2.4.2"}set {name = "replicaCount"value = 1}set {name = "serviceAccount.name"value = "aws-load-balancer-controller"}set {name = "serviceAccount.annotations.eks\\.amazonaws\\.com/role-arn"value = aws_iam_role.aws_load_balancer_controller.arn}# EKS Fargate specificset {name = "region"value = "us-east-1"}set {name = "vpcId"value = aws_vpc.main.id}depends_on = [aws_eks_fargate_profile.kube-system]}
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: