Creando una arquitectura robusta en AWS con Terraform

Hello World 🙂

Continuando con nuestra serie de ejercicios sobre Terraform y la creación de recursos en AWS, les presento otro ejercicio completamente práctico. En esta ocasión, nos adentraremos en la creación de una VPC, que como siempre, servirá como base para el despliegue de nuestros servicios. Sin embargo, en este caso, daremos un paso más al desplegar un clúster de EKS (Amazon Elastic Kubernetes Service), la distribución de Kubernetes soportada por AWS.

Una de las ventajas clave de desplegar Kubernetes en AWS es su integración con una amplia gama de servicios de la plataforma. En este ejercicio, mostraremos cómo integrar EKS con EFS (Amazon Elastic File System), una opción de almacenamiento altamente distribuido, escalable y de alto rendimiento.

Además, crearemos una instancia EC2 que fungirá como Jumpbox, desde la cual nos conectaremos a nuestro clúster de EKS, para finalizar desplegaremos un breve ejemplo para verificar la integración y el correcto funcionamiento de estos servicios.

Para este ejemplo, seguiremos las mejores prácticas. Crearemos nuestro clúster EKS y nuestro EFS en subredes privadas, y configuraremos los Security Groups con los accesos mínimos necesarios. Nuestra instancia EC2 será creada en subredes públicas. Asimismo, configuraremos nuestro clúster de EKS con su API privada, un requisito crucial si nuestro entorno será auditado por PCI(Payment Card Industry).

Esta arquitectura desplegada hoy representa un escenario común que se puede implementar en entornos reales, ofreciendo una sólida base para infraestructuras seguras y eficientes.

¡Prepárate para adentrarte en el mundo de la automatización de infraestructura con Terraform!

Requisitos:

En esta ocasión el proyecto va a estar formado por 3 carpetas;

  • La primera carpeta es 1-iam-role-eks, donde definiremos los archivos necesarios para crear el Rol IAM que Terraform utilizará posteriormente para aprovisionar el clúster EKS. Este rol proporcionará los permisos necesarios para la creación y gestión de los recursos del clúster de manera segura y controlada.
  • La segunda carpeta es 2-eks-cluster, en esta carpeta vamos a definir todos los archivos necesarios para crear el clúster de EKS, el EFS y la instancia EC2.
  • La tercera carpeta es 3-k8s, aquí vamos a tener los ficheros necesarios para validar el funcionamiento y la integración de nuestro clúster EKS con el EFS.

1- Primero necesitamos exporta nuestras credenciales de AWS en nuestra consola;

  • export AWS_ACCESS_KEY_ID="XXXXXXXXXX"
    export AWS_SECRET_ACCESS_KEY="XXXXXXXXXX"
  • Comprobamos que estemos conectados de forma correcta
    •  aws sts get-caller-identity

2- Crear la carpeta 1-iam-role-eks y dentro de ella los siguientes ficheros;

  • 1-iam.tf; definiremos el provider, el rol que vamos a crear y las políticas que le vamos a adjuntar.
    • Nota: Si tienes algún Rol creado anteriormente que deseas autorizar para que asuma este Rol en otro momento lo debes definir aquí.
      • terraform {
          required_version = ">= 1.0"
          required_providers {
            aws = {
              source  = "hashicorp/aws"
              version = ">= 4.47"
            }
          }
        }
      • resource "aws_iam_role" "terraform_role" {
          name               = local.role_name
          assume_role_policy = jsonencode({
            "Version" : "2012-10-17",
            "Statement" : [
              {
                "Effect" : "Allow",
                "Principal" : {
                  "AWS" : [
                    "arn:aws:iam::012345678901:role/#########",
                    "arn:aws:iam::012345678901:root"
                  ]
                },
                "Action" : "sts:AssumeRole"
              }
            ]
          })
        }
    • resource "aws_iam_role_policy_attachment" "attachment_policy" {
        role       = aws_iam_role.terraform_role.name
        policy_arn = "arn:aws:iam::aws:policy/AdministratorAccess"
      }
      • En este caso adjuntamos la política AdministratorAccess, pero si queremos podemos ser un poco más específico y adjuntar solo las políticas que necesitemos.
  • 3-output.tf; definiremos la salida del ARN del rol.
    • output "provisioner_role_arn" {
        value = aws_iam_role.terraform_role.arn
      }
  • Después de crear esos ficheros ya estamos en condiciones de ejecutar Terraform
    • terraform init
    • terraform plan
    • terraform apply
        • Copiar el ARN que se imprime en la salida.
    • Una vez que hemos creado el rol, es necesario editarlo para que pueda asumirse a sí mismo. Esto se logra tomando el ARN del rol y añadiendo assumed-role. El formato sería algo como: arn:aws:sts::012345678901:assumed-role/TerraformRole-Eks/demo.Este ajuste puede hacerse desde la consola de AWS. Simplemente navega a IAM, busca el rol, y en la sección Trust relationships agrega una nueva entrada con la información mencionada. Alternativamente, también puedes realizar este cambio directamente desde Terraform.Este procedimiento es una buena práctica de seguridad, ya que permite evitar la creación de recursos mediante un usuario específico. Al usar este rol para la creación de recursos, obtenemos mucho más control y seguridad sobre nuestra infraestructura.

3- Crear la carpeta 2-eks-cluster y dentro de ella los siguientes ficheros;

  • En el archivo 0-provider.tf, definiremos los proveedores y la región que utilizaremos en este proyecto. Estos proveedores son esenciales, ya que permiten a Terraform interactuar con los distintos servicios de infraestructura en la nube necesarios para desplegar los recursos correctamente.
    • En el caso del provider AWS vamos a definirle el rol queremos que utilice. Esto es particularmente útil cuando necesitas ejecutar Terraform con permisos específicos que están otorgados a un rol IAM.
    • provider "aws" {
        region = local.region
        default_tags {
         tags = local.tags
        }
        assume_role {
          role_arn = var.terraformrole
        }
      }
      terraform {
        required_version = ">= 1.0"
        required_providers {
          aws = {
            source  = "hashicorp/aws"
            version = ">= 4.47"
          }
          kubernetes = {
            source  = "hashicorp/kubernetes"
            version = ">= 2.10"
          }
          helm = {
            source  = "hashicorp/helm"
            version = ">= 2.5.0"
          }
          kubectl = {
            source  = "gavinbunney/kubectl"
            version = ">= 1.14"
          }
        }
      }
      provider "kubernetes" {
        host                   = module.eks.cluster_endpoint
        cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data)
        exec {
          api_version = "client.authentication.k8s.io/v1beta1"
          command     = "aws"
          # This requires the awscli to be installed locally where Terraform is executed
          args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name]
        }
      }
  • 1-locals.tf; definiremos las variables locales del proyecto. Estas variables ayudan a centralizar valores que se utilizarán en múltiples recursos, simplificando la configuración y facilitando el mantenimiento del código.
    • locals {
        ng_name     = "demo-eks"
        region      = var.region
        tags        = var.tags
        cluster_name = var.cluster_name
        common_tags = {
          Environment = var.environment
          project_name = var.project_name
          Terraform   = "true"  
        }
      }
  • 2-vpc.tf; en este fichero definiremos todo lo necesario para crear nuestra VPC, que servirá como la base de la infraestructura del proyecto. Aquí, definiremos subredes y demás componentes claves que permitirán una red segura y eficiente para los recursos que desplegaremos más adelante.
    • module "vpc" {
        source  = "terraform-aws-modules/vpc/aws"
        version = "5.2.0"
        name                   = var.vpc_name
        cidr                   = var.vpc_base_cidr
        azs                    = var.availability_zones == [] ? var.availability_zones : data.aws_availability_zones.available.names
        private_subnets        = split(",", var.private_subnets)
        private_subnet_tags    = merge(var.private_subnet_tags, local.common_tags)
        public_subnets         = split(",", var.public_subnets)
        public_subnet_tags     = merge(var.public_subnet_tags, local.common_tags)
        database_subnets       = split(",", var.isolated_subnets)
        database_subnet_tags   = merge(var.isolated_subnet_tags, local.common_tags)
        enable_nat_gateway     = var.enable_nat_gateway
        single_nat_gateway     = var.single_nat_gateway
        enable_vpn_gateway     = var.enable_vpn_gateway
        one_nat_gateway_per_az = var.one_nat_gateway_per_az
        enable_dns_hostnames   = var.enable_dns_hostnames
        enable_dns_support     = var.enable_dns_support
        tags                   = merge(var.vpc_tags, local.common_tags)
      }
      data "aws_availability_zones" "available" {}
  • 3-eks.tf; definiremos todo lo necesario para la creación de nuestro clúster EKS, incluyendo las configuraciones base y los ajustes requeridos para desplegarlo correctamente en AWS.
    • module "eks" {
        source                          = "terraform-aws-modules/eks/aws"
        version                         = "19.12.0"
        cluster_name                    = var.cluster_name
        cluster_version                 = var.cluster_version
        cluster_endpoint_private_access = var.cluster_endpoint_private_access
        cluster_endpoint_public_access  = var.cluster_endpoint_public_access
        vpc_id                          = module.vpc.vpc_id
        subnet_ids                      = module.vpc.private_subnets
        enable_irsa                     = var.enable_irsa
        # Aquí defino los valores predeterminados que van a tener todos los "eks_managed_node_groups"
        eks_managed_node_group_defaults = {
          name             = local.ng_name
          instance_types   = var.instance_types
          ami_id           = data.aws_ami.eks_default.image_id
          min_size         = var.min_size
          max_size         = var.max_size
          desired_size     = var.desired_size
         
          enable_bootstrap_user_data = true
          enable_monitoring       = true
          block_device_mappings = {
            xvda = {
              device_name = "/dev/xvda"
              ebs = {
                volume_size           = 25
                volume_type           = "gp3"
                iops                  = 3000
                throughput            = 150
                delete_on_termination = true
              }
            }
          }
        }
        eks_managed_node_groups         = var.eks_managed_node_groups
        manage_aws_auth_configmap       = var.manage_aws_auth_configmap
        create_aws_auth_configmap       = var.create_aws_auth_configmap
        cluster_enabled_log_types       = var.cluster_enabled_log_types
        tags                            = merge(var.tags, local.common_tags)
      }
    • Aquí vamos a permitir el tráfico proveniente de los puertos 2049 para poder usar el servicio de EFS y 443(HTTS) para poder administrar el clúster desde nuestro Jumbox.
      • resource "aws_security_group_rule" "eks_sg_efs" {
          depends_on = [module.eks]
          description = "Allow EFS traffic"
          type              = "ingress"
          from_port         = 2049
          to_port           = 2049
          protocol          = "tcp"
          cidr_blocks       = [var.vpc_base_cidr]
          security_group_id = module.eks.cluster_primary_security_group_id
        }
        resource "aws_security_group_rule" "eks_sg_https" {
          depends_on = [module.eks]
          description = "Allow https traffic to manage the cluster fromthe Jumbox"
          type              = "ingress"
          from_port         = 443
          to_port           = 443
          protocol          = "tcp"
          cidr_blocks       = [var.vpc_base_cidr]
          security_group_id = module.eks.cluster_primary_security_group_id
        }
    • Aquí vamos a permitir que el tráfico proveniente del EFS llegue a los nodos del clúster.
      • resource "aws_security_group_rule" "node_sg_efs" {
          depends_on = [module.eks]
          description = "Allow EFS traffic"
          type              = "ingress"
          from_port         = 2049
          to_port           = 2049
          protocol          = "tcp"
          cidr_blocks       = [var.vpc_base_cidr]
          security_group_id=module.eks.node_security_group_id
        }
    • Aquí vamos a buscar el AMI que va a hacer usada por los nodos del clúster, si tuviésemos algún Golden AMI también la pudiéramos filtrar.
    • data "aws_ami" "eks_default" {
        most_recent = true
        owners      = ["amazon"]
        filter {
          name   = "name"
          values = ["amazon-eks-node-${var.cluster_version}-v*"]
        }
      }
  • 4-efs.tf; definiremos todo lo necesario para la creación del EFS, permitiendo que esté preparado para integrarse con el clúster EKS.
    • resource "aws_efs_file_system" "demo_efs" {
        creation_token = "demo"
        performance_mode = "generalPurpose"
        throughput_mode  = "bursting"
        encrypted        = true
        tags = {
          Name = "demo"
        }
      }
    • resource "aws_efs_mount_target" "zone" {
        for_each = { for idx, subnet in module.vpc.private_subnets : idx => subnet }
        file_system_id  = aws_efs_file_system.demo_efs.id
        subnet_id       = each.value
        security_groups = [aws_security_group.efs.id]
      }
  • 5-ec2.tf; configuraremos nuestro servidor JumpBox, que nos permitirá acceder al clúster de EKS. A través de user_data, instalaremos las herramientas necesarias para la gestión y administración del clúster, como Git, kubectl, Helm y Terraform. Este servidor funcionará como un punto de control seguro y centralizado para nuestras operaciones en el entorno de Kubernetes.
    • resource "aws_instance" "jumbox" {
          ami = data.aws_ami.amazon_linux.id
          instance_type = "t2.micro"
          iam_instance_profile = "${aws_iam_instance_profile.demo_profile.name}"
          subnet_id = module.vpc.public_subnets[0]
          associate_public_ip_address= true
          vpc_security_group_ids = [aws_security_group.ec2.id]
          tags= {
              Name = "demo"
          }
          user_data = <<-EOF
                      #!/bin/bash
                      sudo yum update
                      sudo yum -y install telnet git
                      # Install Kubectl
                      curl -O https://s3.us-west-2.amazonaws.com/amazon-eks/1.28.8/2024-04-19/bin/linux/amd64/kubectl
                      curl -O https://s3.us-west-2.amazonaws.com/amazon-eks/1.28.8/2024-04-19/bin/linux/amd64/kubectl.sha256
                      openssl sha1 -sha256 kubectl
                      chmod +x ./kubectl
                      mkdir -p $HOME/bin && cp ./kubectl $HOME/bin/kubectl && export PATH=$HOME/bin:$PATH
                      echo 'export PATH=$HOME/bin:$PATH' >> ~/.bashrc
                      kubectl version --client
                      # Install Helm
                      curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 > get_helm.sh
                      chmod 700 get_helm.sh
                      ./get_helm.sh
                      helm version
                      # Install Terraform
                      sudo yum install -y yum-utils
                      sudo yum-config-manager --add-repo https://rpm.releases.hashicorp.com/AmazonLinux/hashicorp.repo
                      sudo yum -y install terraform
                      EOF
      }
    • Filtramos el AMI que va hacer utilizada para la creacion del servidor Jumbox
      • data "aws_ami" "amazon_linux" {
          most_recent = true
          filter {
            name   = "name"
            values = ["al202*-ami-202*"]
          }
          filter {
            name   = "architecture"
            values = ["x86_64"]
          }
          owners = ["amazon"]
        }
  • 6-security.tf; configuraremos los grupos de seguridad necesarios para el correcto funcionamiento del EFS y del servidor JumpBox. Estos grupos de seguridad permitirán gestionar de manera segura el acceso dentro de nuestra infraestructura.
    • resource "aws_security_group" "efs" {
         name = "efs-sg"
         description= "Allow inbound efs traffic from ec2"
         vpc_id = module.vpc.vpc_id
         ingress {
           cidr_blocks = [var.vpc_base_cidr]
           from_port = 2049
           to_port=2049
           protocol = "tcp"
         }
         ingress {
           security_groups = [aws_security_group.ec2.id]
           from_port = 2049
           to_port=2049
           protocol = "tcp"
         }
         egress {
           cidr_blocks = [var.vpc_base_cidr]
           from_port = 0
           to_port = 0
           protocol = "-1"
         }      
             
         egress {
           security_groups = [aws_security_group.ec2.id]
           from_port = 0
           to_port = 0
           protocol = "-1"
         }
         tags = {
          Name = "efs-sg"
        }
       }
    • resource "aws_security_group" "ec2" {
        name        = "ec2-sg"
        description = "Allow efs outbound traffic"
        vpc_id = module.vpc.vpc_id
        ingress {
           cidr_blocks = ["0.0.0.0/0"]
           from_port = 22
           to_port = 22
           protocol = "tcp"
         }
        egress {
          from_port       = 0
          to_port         = 0
          protocol        = "-1"
          cidr_blocks     = ["0.0.0.0/0"]
        }
        tags = {
          Name = "ec2-sg"
        }
      }
  • 7-iam.tf; en este fichero vamos a definir el rol, las políticas y el instance_profile que se asociará al servidor Jumbox. Esto nos permitirá gestionar permisos y conectarnos a la instancia de manera segura desde la consola de AWS, asegurando así un acceso adecuado y controlado al servidor.
    • resource "aws_iam_role" "demo_role" {
        name = "demo_role"
        assume_role_policy = <<EOF
      {
        "Version": "2012-10-17",
        "Statement": [
          {
            "Action": "sts:AssumeRole",
            "Principal": {
              "Service": "ec2.amazonaws.com"
            },
            "Effect": "Allow",
            "Sid": ""
          }
        ]
      }
      EOF
        tags = {
            tag-key = "demo"
        }
      }
    • resource "aws_iam_policy_attachment" "attach_amazon_ssm_full_access-demo_role" {
        name       = "attach-amazon-ssm-full-access-demo_role"
        roles      = [aws_iam_role.demo_role.name]
        policy_arn = "arn:aws:iam::aws:policy/AmazonSSMFullAccess"
      }
      resource "aws_iam_policy_attachment" "attach_amazon_ec2_role_for_ssm-demo_role" {
        name       = "attach-amazon-ec2-role-for-ssm-demo_role"
        roles      = [aws_iam_role.demo_role.name]
        policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonEC2RoleforSSM"
      }
    • resource "aws_iam_instance_profile" "demo_profile" {
        name = "demo_profile"
        role = "${aws_iam_role.demo_role.name}"
      }
  • 8-variables.tf; definiremos todas las variables que necesitaremos para parametrizar el proyecto. Estas variables permitirán una mayor flexibilidad y reutilización del código, facilitando la personalización de los recursos y haciendo que el despliegue sea más adaptable a diferentes entornos y requisitos específicos.
    • Como son muchas variables les dejo el enlace directo a este fichero en el repositorio.
  • 9-demo-eks.auto.tfvars; estableceremos todos los valores necesarios para generar nuestro entorno. Esto nos permite un enfoque más dinámico y flexible, ya que cualquier ajuste de valores en el futuro solo requerirá modificar este archivo, facilitando la administración y personalización de nuestro entorno según sea necesario.
    • ###################
      # General Inputs
      ###################
      region          = "us-west-1"
      environment     = "Demo"
      project_name    = "demo-eks"
      terraformrole   = "arn:aws:iam::012345678901:role/TerraformRole-Eks"

      Nota: Aquí debemos poner el ARN del rol creado anteriormente

      ###################
      # VPC Inputs
      ###################
      vpc_name               = "demo-eks"
      vpc_base_cidr          = "10.1.0.0/16"
      availability_zones     = ["us-west-1a", "us-west-1b"]
      private_subnets        = "10.1.11.0/24,10.1.12.0/24"
      public_subnets         = "10.1.21.0/24,10.1.22.0/24"
      isolated_subnets       = "10.1.31.0/24,10.1.32.0/24"
      public_subnet_tags = {
      "Name"                       = "Public-Subnet"
      "kubernetes.io/role/elb"     = 1
      "kubernetes.io/cluster/demo" = "owned"
      }
      private_subnet_tags = {
      "Name"                       = "Private-Subnet"
      "kubernetes.io/role/internal-elb" = 1
      "kubernetes.io/cluster/demo"      = "owned"
      }
      ###################
      # EKS Inputs
      ###################
      cluster_name                    = "demo-eks"
      cluster_version                 = "1.28"
      cluster_endpoint_private_access = true
      cluster_endpoint_public_access  = false
      instance_types = ["t3.medium"]
      desired_size = 1
      min_size     = 1
      max_size     = 3
      eks_managed_node_groups = {
        on_demand = {
          labels = {
            role = "on_demand"
          }
          capacity_type  = "ON_DEMAND"
        }
        spot = {
          desired_size = 1
          min_size     = 1
          max_size     = 5
          labels = {
            role = "spot"
          }
          instance_types = ["t3.micro"]
          capacity_type  = "SPOT"
        }
      }
      tags = {
        App_Name = "Kubernetes"
        Country  = "UY"
        Region   = "AMERICA"
      }
  • 10-outputs.tf;  definiremos las salidas que Terraform nos mostrará tras ejecutar terraform apply. Estas salidas incluirán detalles de los recursos creados, que nos ayudarán a verificar rápidamente el estado del despliegue y a acceder fácilmente a los recursos configurados en el proyecto.
    • este es un fichero opcional, por lo que les dejo el enlace directo al fichero por si quieren copiar su contenido.
  • Después de crear esos ficheros ya estamos en condiciones de ejecutar Terraform;
    • terraform init
    • terraform plan
    • terraform apply

3- Como la API del clúster EKS es privada, debemos ir a nuestro Jumbox, creado en la misma VPC del clúster y que nos va a permitir administrar el mismo sin inconvenientes.

  • Vamos a la consola de AWS y nos conectamos a la instancia
  • Primero necesitamos exporta nuestras credenciales de AWS para poder asumir el rol que creamos anteriormente y que nos permitirá administrar el clúster;
    • export AWS_ACCESS_KEY_ID="XXXXXXXXXX"
      export AWS_SECRET_ACCESS_KEY="XXXXXXXXXX"
  • Comprobamos que estemos conectados de forma correcta
    •  aws sts get-caller-identity
  • Después exportamos el rol de la siguiente manera;

credentials=$(aws sts assume-role --role-arn arn:aws:iam::012345678901:role/TerraformRole-Eks --role-session-name "demo" | jq ".Credentials")
export AWS_ACCESS_KEY_ID=$(echo $credentials | jq -r ".AccessKeyId")
export AWS_SECRET_ACCESS_KEY=$(echo $credentials | jq -r ".SecretAccessKey")
export AWS_SESSION_TOKEN=$(echo $credentials | jq -r ".SessionToken")

  • Actualizar el kubeconfig
    aws eks --region us-west-1 update-kubeconfig --name demo-eks --alias demo-eks

4-Para poder utilizar el EFS desde amazon tenemos que instalar el Amazon EFS CSI driver, en nuestro caso lo vamos hacer usando Helm.

  • helm repo add aws-efs-csi-driver https://kubernetes-sigs.github.io/aws-efs-csi-driver/
  • helm install aws-efs-csi-driver aws-efs-csi-driver/aws-efs-csi-driver -n kube-system
  • Ejecutar el siguiente comando para verificar que todo está bien.
    • kubectl get pod -n kube-system -l "app.kubernetes.io/name=aws-efs-csi-driver,app.kubernetes.io/instance=aws-efs-csi-driver"

4- Crear la carpeta 3-k8s y dentro de ella los siguientes ficheros;

  • sc.yaml; aquí vamos a definir el StorageClass que vamos a utilizar.
    • kind: StorageClass
      apiVersion: storage.k8s.io/v1
      metadata:
        name: efs-sc
      provisioner: efs.csi.aws.com
  • Obtenemos el id del EFS creado y agregarlo en el fichero pv.yaml generado a continuación;
    • aws efs describe-file-systems --query "FileSystems[*].FileSystemId" --output text --region us-west-1
  • pv.yaml, aquí vamos a definir todo lo necesario para generar el PersistentVolume.
    • apiVersion: v1
      kind: PersistentVolume
      metadata:
        name: efs-pv
      spec:
        capacity:
          storage: 5Gi
        volumeMode: Filesystem
        accessModes:
          - ReadWriteMany
        persistentVolumeReclaimPolicy: Retain
        storageClassName: efs-sc
        csi:
          driver: efs.csi.aws.com
          volumeHandle: efs-id
  • pvc.yaml; aquí vamos a definir todo lo necesario para generar el PersistentVolumeClaim.
    • apiVersion: v1
      kind: PersistentVolumeClaim
      metadata:
        name: efs-claim
      spec:
        accessModes:
          - ReadWriteMany
        storageClassName: efs-sc
        resources:
          requests:
            storage: 5Gi
  • Vamos a definir un par de podque van a montar como volumen el PVC creado anteriormente;
    • pod1.yaml;
      • apiVersion: v1
        kind: Pod
        metadata:
          name: app1
        spec:
          containers:
          - name: app1
            image: busybox
            command: ["/bin/sh"]
            args: ["-c", "while true; do echo Printing the date $(date -u) from the pod $(hostname) >> /data/out1.txt; sleep 5; done"]
            volumeMounts:
            - name: persistent-storage
              mountPath: /data
          volumes:
          - name: persistent-storage
            persistentVolumeClaim:
              claimName: efs-claim
    • pod2.yaml;
      • apiVersion: v1
        kind: Pod
        metadata:
          name: app2
        spec:
          containers:
          - name: app2
            image: busybox
            command: ["/bin/sh"]
            args: ["-c", "while true; do echo Printing the date $(date -u) from the pod $(hostname) >> /data/out2.txt; sleep 5; done"]
            volumeMounts:
            - name: persistent-storage
              mountPath: /data
          volumes:
          - name: persistent-storage
            persistentVolumeClaim:
              claimName: efs-claim
  • Ahora ya podemos crear todos estos recursos;
    • kubectl apply -f .
  • Verificamos que los datos estén escritos en el sistema de archivos de Amazon EFS.
    • kubectl exec -ti app1 -- tail /data/out1.txt
    • kubectl exec -ti app2 -- tail /data/out2.txt
    • También podemos hacer un ls desde cualquiera de los 2 pod y veremos lo mismo en ambos volúmenes;

4- Terraform destroy

  • Al finalizar tus pruebas, recuerda eliminar todos los recursos creados. Este paso es crucial para evitar sorpresas desagradables en tu factura al final del mes. No subestimes la importancia de esta tarea, ya que la acumulación de recursos no utilizados puede generar costos innecesarios. Tomate el tiempo para limpiar tu entorno, eso te ahorrará dolores de cabeza en el futuro 🙂

Conclusiones

Hemos llegado al final de esta entrada, donde hemos explorado un ejercicio práctico en su totalidad, aplicable en situaciones reales. Durante este recorrido, hemos construido una arquitectura sólida y bien diseñada. Nuestro clúster se ha configurado con su API privada, un aspecto vital que destacamos al inicio de la entrada. Además, hemos accedido a este clúster desde nuestro servidor Jumbox, permitiéndonos una gestión segura y eficiente.

Durante nuestras pruebas, confirmamos el correcto funcionamiento de nuestro EFS al crear y utilizar recursos en el clúster de EKS. Desplegamos varios pods y presenciamos cómo pueden utilizar almacenamiento compartido de manera efectiva.

Espero que esta entrada haya sido útil y que lo hayan disfrutado tanto como yo, si tienen alguna pregunta o comentario, no duden en compartirlo.

¡Nos vemos en la próxima entrada!

Nota: Todo el código utilizado lo pueden encontrar en este repositorio.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.