Crear un clúster y desplegar una carga de trabajo con Terraform


Un clúster de Kubernetes proporciona computación, almacenamiento, redes y otros servicios para aplicaciones, de forma similar a un centro de datos virtual. Las aplicaciones y los servicios asociados que se ejecutan en Kubernetes se denominan cargas de trabajo.

En este tutorial se muestra cómo ver rápidamente un clúster de Google Kubernetes Engine y una carga de trabajo de ejemplo en funcionamiento, todo configurado con Terraform. Después, puedes explorar la carga de trabajo en la Google Cloud consola antes de seguir nuestro curso más detallado o empezar a planificar y crear tu propio clúster listo para producción. En este tutorial se da por hecho que ya conoces Terraform.

Si prefieres configurar tu clúster y tu carga de trabajo de ejemplo en la Google Cloud consola, consulta Crear un clúster en la consola Google Cloud .

Antes de empezar

Sigue estos pasos para habilitar la API de Kubernetes Engine:

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. Install the Google Cloud CLI.

  3. Si utilizas un proveedor de identidades (IdP) externo, primero debes iniciar sesión en la CLI de gcloud con tu identidad federada.

  4. Para inicializar gcloud CLI, ejecuta el siguiente comando:

    gcloud init
  5. Create or select a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.
    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  6. Verify that billing is enabled for your Google Cloud project.

  7. Enable the GKE API:

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    gcloud services enable container.googleapis.com
  8. Install the Google Cloud CLI.

  9. Si utilizas un proveedor de identidades (IdP) externo, primero debes iniciar sesión en la CLI de gcloud con tu identidad federada.

  10. Para inicializar gcloud CLI, ejecuta el siguiente comando:

    gcloud init
  11. Create or select a Google Cloud project.

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.
    • Create a Google Cloud project:

      gcloud projects create PROJECT_ID

      Replace PROJECT_ID with a name for the Google Cloud project you are creating.

    • Select the Google Cloud project that you created:

      gcloud config set project PROJECT_ID

      Replace PROJECT_ID with your Google Cloud project name.

  12. Verify that billing is enabled for your Google Cloud project.

  13. Enable the GKE API:

    Roles required to enable APIs

    To enable APIs, you need the Service Usage Admin IAM role (roles/serviceusage.serviceUsageAdmin), which contains the serviceusage.services.enable permission. Learn how to grant roles.

    gcloud services enable container.googleapis.com
  14. Grant roles to your user account. Run the following command once for each of the following IAM roles: roles/container.admin, roles/compute.networkAdmin, roles/iam.serviceAccountUser

    gcloud projects add-iam-policy-binding PROJECT_ID --member="user:USER_IDENTIFIER" --role=ROLE

    Replace the following:

    • PROJECT_ID: your project ID.
    • USER_IDENTIFIER: the identifier for your user account—for example, myemail@example.com.
    • ROLE: the IAM role that you grant to your user account.
  15. Preparar el entorno

    En este tutorial, usarás Cloud Shell para gestionar los recursos alojados enGoogle Cloud. Cloud Shell tiene preinstalado el software que necesitas para este tutorial, como Terraform, kubectl y Google Cloud CLI.

    1. Inicia una sesión de Cloud Shell desde la consola Google Cloud haciendo clic en el icono de activación de Cloud Shell Activar Cloud Shell Activar botón Shell. De esta forma, se inicia una sesión en el panel inferior de la consola Google Cloud .

      Las credenciales de servicio asociadas a esta máquina virtual son automáticas, por lo que no tienes que configurar ni descargar una clave de cuenta de servicio.

    2. Antes de ejecutar comandos, define tu proyecto predeterminado en la CLI de gcloud con el siguiente comando:

      gcloud config set project PROJECT_ID
      

      Sustituye PROJECT_ID por el ID de tu proyecto.

    3. Clona el repositorio de GitHub:

      git clone https://github.com/terraform-google-modules/terraform-docs-samples.git --single-branch
      
    4. Cambia al directorio de trabajo:

      cd terraform-docs-samples/gke/quickstart/autopilot
      

    Revisar los archivos de Terraform

    El Google Cloud proveedor es un complemento que te permite gestionar y aprovisionar Google Cloud recursos con Terraform. Actúa como puente entre las configuraciones de Terraform y las APIs de Google Cloud , lo que te permite definir de forma declarativa recursos de infraestructura, como máquinas virtuales y redes.

    El clúster y la aplicación de ejemplo de este tutorial se especifican en dos archivos de Terraform que usan los proveedores Google Cloud y Kubernetes.

    1. Revisa el archivo cluster.tf:

      cat cluster.tf
      

      La salida es similar a la siguiente:

      resource "google_compute_network" "default" {
        name = "example-network"
      
        auto_create_subnetworks  = false
        enable_ula_internal_ipv6 = true
      }
      
      resource "google_compute_subnetwork" "default" {
        name = "example-subnetwork"
      
        ip_cidr_range = "10.0.0.0/16"
        region        = "us-central1"
      
        stack_type       = "IPV4_IPV6"
        ipv6_access_type = "INTERNAL" # Change to "EXTERNAL" if creating an external loadbalancer
      
        network = google_compute_network.default.id
        secondary_ip_range {
          range_name    = "services-range"
          ip_cidr_range = "192.168.0.0/24"
        }
      
        secondary_ip_range {
          range_name    = "pod-ranges"
          ip_cidr_range = "192.168.1.0/24"
        }
      }
      
      resource "google_container_cluster" "default" {
        name = "example-autopilot-cluster"
      
        location                 = "us-central1"
        enable_autopilot         = true
        enable_l4_ilb_subsetting = true
      
        network    = google_compute_network.default.id
        subnetwork = google_compute_subnetwork.default.id
      
        ip_allocation_policy {
          stack_type                    = "IPV4_IPV6"
          services_secondary_range_name = google_compute_subnetwork.default.secondary_ip_range[0].range_name
          cluster_secondary_range_name  = google_compute_subnetwork.default.secondary_ip_range[1].range_name
        }
      
        # Set `deletion_protection` to `true` will ensure that one cannot
        # accidentally delete this instance by use of Terraform.
        deletion_protection = false
      }

      En este archivo se describen los siguientes recursos:

      • google_compute_network: una red de VPC con IPv6 interno habilitado.
      • google_compute_subnetwork: una subred de doble pila.
      • google_container_cluster: un clúster de modo Autopilot de pila dual ubicado en us-central1. El ajuste deletion_protection controla si puedes usar Terraform para eliminar este clúster. Si asignas el valor false al campo deletion_protection, Terraform puede eliminar el clúster. Para obtener más información, consulta la referencia de google_container_cluster.
    2. Revisa el archivo app.tf:

      cat app.tf
      

      El resultado debería ser similar al siguiente:

      data "google_client_config" "default" {}
      
      provider "kubernetes" {
        host                   = "https://${google_container_cluster.default.endpoint}"
        token                  = data.google_client_config.default.access_token
        cluster_ca_certificate = base64decode(google_container_cluster.default.master_auth[0].cluster_ca_certificate)
      
        ignore_annotations = [
          "^autopilot\\.gke\\.io\\/.*",
          "^cloud\\.google\\.com\\/.*"
        ]
      }
      
      resource "kubernetes_deployment_v1" "default" {
        metadata {
          name = "example-hello-app-deployment"
        }
      
        spec {
          selector {
            match_labels = {
              app = "hello-app"
            }
          }
      
          template {
            metadata {
              labels = {
                app = "hello-app"
              }
            }
      
            spec {
              container {
                image = "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
                name  = "hello-app-container"
      
                port {
                  container_port = 8080
                  name           = "hello-app-svc"
                }
      
                security_context {
                  allow_privilege_escalation = false
                  privileged                 = false
                  read_only_root_filesystem  = false
      
                  capabilities {
                    add  = []
                    drop = ["NET_RAW"]
                  }
                }
      
                liveness_probe {
                  http_get {
                    path = "/"
                    port = "hello-app-svc"
      
                    http_header {
                      name  = "X-Custom-Header"
                      value = "Awesome"
                    }
                  }
      
                  initial_delay_seconds = 3
                  period_seconds        = 3
                }
              }
      
              security_context {
                run_as_non_root = true
      
                seccomp_profile {
                  type = "RuntimeDefault"
                }
              }
      
              # Toleration is currently required to prevent perpetual diff:
              # https://github.com/hashicorp/terraform-provider-kubernetes/pull/2380
              toleration {
                effect   = "NoSchedule"
                key      = "kubernetes.io/arch"
                operator = "Equal"
                value    = "amd64"
              }
            }
          }
        }
      }
      
      resource "kubernetes_service_v1" "default" {
        metadata {
          name = "example-hello-app-loadbalancer"
          annotations = {
            "networking.gke.io/load-balancer-type" = "Internal" # Remove to create an external loadbalancer
          }
        }
      
        spec {
          selector = {
            app = kubernetes_deployment_v1.default.spec[0].selector[0].match_labels.app
          }
      
          ip_family_policy = "RequireDualStack"
      
          port {
            port        = 80
            target_port = kubernetes_deployment_v1.default.spec[0].template[0].spec[0].container[0].port[0].name
          }
      
          type = "LoadBalancer"
        }
      
        depends_on = [time_sleep.wait_service_cleanup]
      }
      
      # Provide time for Service cleanup
      resource "time_sleep" "wait_service_cleanup" {
        depends_on = [google_container_cluster.default]
      
        destroy_duration = "180s"
      }

      En este archivo se describen los siguientes recursos:

    (Opcional) Exponer la aplicación en Internet

    Los archivos de Terraform del ejemplo describen una aplicación con una dirección IP interna, a la que solo se puede acceder desde la misma nube privada virtual (VPC) que la aplicación de ejemplo. Si quieres acceder a la interfaz web de la aplicación de demostración en ejecución desde Internet (por ejemplo, desde tu portátil), modifica los archivos de Terraform para crear una dirección IP pública antes de crear el clúster. Puedes hacerlo con un editor de texto directamente en Cloud Shell o con el editor de Cloud Shell.

    Para exponer la aplicación de demostración en Internet, haz lo siguiente:

    1. En cluster.tf, cambia ipv6_access_type de INTERNAL a EXTERNAL.

      ipv6_access_type = "EXTERNAL"
      
    2. En app.tf, configura un balanceador de carga externo quitando la anotación networking.gke.io/load-balancer-type.

       annotations = {
         "networking.gke.io/load-balancer-type" = "Internal" # Remove this line
       }
      

    Crear un clúster y desplegar una aplicación

    1. En Cloud Shell, ejecuta este comando para verificar que Terraform está disponible:

      terraform
      

      La salida debería ser similar a la siguiente:

      Usage: terraform [global options] <subcommand> [args]
      
      The available commands for execution are listed below.
      The primary workflow commands are given first, followed by
      less common or more advanced commands.
      
      Main commands:
        init          Prepare your working directory for other commands
        validate      Check whether the configuration is valid
        plan          Show changes required by the current configuration
        apply         Create or update infrastructure
        destroy       Destroy previously-created infrastructure
      
    2. Inicializa Terraform:

      terraform init
      
    3. Planifica la configuración de Terraform:

      terraform plan
      
    4. Aplica la configuración de Terraform

      terraform apply
      

      Cuando se te solicite, introduce yes para confirmar las acciones. Este comando puede tardar varios minutos en completarse. El resultado debería ser similar al siguiente:

      Apply complete! Resources: 6 added, 0 changed, 0 destroyed.
      

    Verificar que el clúster funciona

    Para confirmar que el clúster se está ejecutando correctamente, haz lo siguiente:

    1. Ve a la página Cargas de trabajo de la Google Cloud consola:

      Ve a Cargas de trabajo.

    2. Haz clic en la carga de trabajo example-hello-app-deployment. Se muestra la página Detalles del pod. En esta página se muestra información sobre el pod, como las anotaciones, los contenedores que se ejecutan en el pod, los servicios que exponen el pod y las métricas, incluido el uso de CPU, memoria y disco.

    3. Ve a la página Servicios y entrada de la consola de Google Cloud :

      Ir a Servicios e Ingress

    4. Haz clic en el example-hello-app-loadbalancer servicio LoadBalancer. Se mostrará la página de detalles del servicio. En esta página se muestra información sobre el servicio, como los pods asociados al servicio y los puertos que utiliza.

    5. En la sección Endpoints externos, haz clic en el enlace IPv4 o en el enlace IPv6 para ver tu servicio en el navegador. La salida es similar a la siguiente:

      Hello, world!
      Version: 2.0.0
      Hostname: example-hello-app-deployment-5df979c4fb-kdwgr
      

    Limpieza

    Para evitar que se apliquen cargos en tu Google Cloud cuenta por los recursos utilizados en esta página, elimina el Google Cloud proyecto con los recursos.

    Si tienes previsto seguir otros tutoriales o explorar más a fondo la muestra, espera a terminar para realizar este paso.

    • En Cloud Shell, ejecuta el siguiente comando para eliminar los recursos de Terraform:

      terraform destroy --auto-approve
      

    Solucionar errores de limpieza

    Si aparece un mensaje de error similar a The network resource 'projects/PROJECT_ID/global/networks/example-network' is already being used by 'projects/PROJECT_ID/global/firewalls/example-network-yqjlfql57iydmsuzd4ot6n5v', haz lo siguiente:

    1. Elimina las reglas de cortafuegos:

      gcloud compute firewall-rules list --filter="NETWORK:example-network" --format="table[no-heading](name)" | xargs gcloud --quiet compute firewall-rules delete
      
    2. Vuelve a ejecutar el comando de Terraform:

      terraform destroy --auto-approve
      

    Siguientes pasos