Configurar la red de un clúster de producción básico

Este tutorial está dirigido a arquitectos de la nube y administradores de operaciones que quieran desplegar una aplicación web en un clúster de Google Kubernetes Engine (GKE) y exponerla con un balanceador de carga HTTPS.

Crear un clúster de GKE

El siguiente archivo de Terraform crea un clúster de GKE:


terraform {
  required_version = "~> 1.3"
}

provider "google" {}

variable "region" {
  type        = string
  description = "Region where the cluster will be created."
  default     = "us-central1"
}

variable "cluster_name" {
  type        = string
  description = "Name of the cluster"
  default     = "networking-cluster"
}

resource "google_container_cluster" "default" {
  name             = var.cluster_name
  description      = "Cluster for sample web application"
  location         = var.region
  enable_autopilot = true

  ip_allocation_policy {}
}

output "region" {
  value       = var.region
  description = "Compute region"
}

output "cluster_name" {
  value       = google_container_cluster.default.name
  description = "Cluster name"
}

El siguiente archivo de Terraform crea una dirección IP global y una zona de Cloud DNS:


terraform {
  required_version = "~> 1.3"
}

variable "base_domain" {
  type        = string
  description = "Your base domain"
}

variable "name" {
  type        = string
  description = "Name of resources"
  default     = "networking-tutorial"
}

data "google_client_config" "current" {}

resource "google_compute_global_address" "default" {
  name = var.name
}

resource "google_dns_managed_zone" "default" {
  name        = var.name
  dns_name    = "${var.name}.${var.base_domain}."
  description = "DNS Zone for web application"
}

resource "google_dns_record_set" "a" {
  name         = google_dns_managed_zone.default.dns_name
  type         = "A"
  ttl          = 300
  managed_zone = google_dns_managed_zone.default.name

  rrdatas = [google_compute_global_address.default.address]
}

resource "google_dns_record_set" "cname" {
  name         = join(".", compact(["www", google_dns_record_set.a.name]))
  type         = "CNAME"
  ttl          = 300
  managed_zone = google_dns_managed_zone.default.name

  rrdatas = [google_dns_record_set.a.name]
}

output "dns_zone_name_servers" {
  value       = google_dns_managed_zone.default.name_servers
  description = "Write these virtual name servers in your base domain."
}

output "domain" {
  value = trim(google_dns_record_set.a.name, ".")
}
  1. Inicializa Terraform:

    terraform init
    
  2. Para ver los cambios en la infraestructura, sigue estos pasos:

    terraform plan
    

    Cuando se te solicite, introduce tu dominio, como my-domain.net.

  3. Aplica la configuración de Terraform:

    terraform apply --auto-approve
    

    Cuando se te solicite, introduce tu dominio, como my-domain.net.

    El resultado debería ser similar al siguiente:

    Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
    
    Outputs:
    
    cluster_name = "networking-cluster"
    region = "us-central1"
    

Crear un balanceador de carga de aplicación externo

  1. El siguiente manifiesto describe un ManagedCertificate, un FrontendConfig, un Deployment, un Service y un Ingress:

    ---
    apiVersion: networking.gke.io/v1
    kind: ManagedCertificate
    metadata:
      name: networking-managed-cert
    spec:
      domains:
        - DOMAIN_NAME
        - www.DOMAIN_NAME
    ---
    apiVersion: networking.gke.io/v1beta1
    kind: FrontendConfig
    metadata:
      name: networking-fc
    spec:
      redirectToHttps:
        enabled: true
        responseCodeName: MOVED_PERMANENTLY_DEFAULT
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: frontend
    spec:
      selector:
        matchLabels:
          app: frontend
      replicas: 2
      template:
        metadata:
          labels:
            app: frontend
        spec:
          containers:
          - name: echo-amd64
            image: us-docker.pkg.dev/google-samples/containers/gke/hello-app-cdn:1.0
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: frontend
    spec:
      type: LoadBalancer
      selector:
        app: frontend
      ports:
      - name: http
        port: 80
        targetPort: 8080
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: frontend
      annotations:
        networking.gke.io/managed-certificates: networking-managed-cert
        networking.gke.io/v1beta1.FrontendConfig: networking-fc
        kubernetes.io/ingress.global-static-ip-name: networking-tutorial
        kubernetes.io/ingress.class: gce
      labels:
        app: frontend
    spec:
      defaultBackend:
        service:
          name: frontend
          port:
            number: 80

    Sustituye DOMAIN_NAME por el nombre de tu dominio, como my-domain.net.

    Este manifiesto tiene las siguientes propiedades:

    • networking.gke.io/managed-certificates: nombre del ManagedCertificate.
    • networking.gke.io/v1beta1.FrontendConfig: nombre del recurso FrontendConfig.
    • kubernetes.io/ingress.global-static-ip-name: el nombre de la dirección IP.
    • kubernetes.io/ingress.class: indica al controlador de Ingress de GKE que cree un balanceador de carga de aplicaciones externo.
  2. Aplica el manifiesto a tu clúster:

    kubectl apply -f kubernetes-manifests.yaml
    
  3. Verifica que se ha creado el Ingress:

    kubectl describe ingress frontend
    

    El resultado debería ser similar al siguiente:

    ...
      Events:
        Type    Reason  Age   From                     Message
        ----    ------  ----  ----                     -------
        Normal  ADD     2m    loadbalancer-controller  default/frontend
        Normal  CREATE  1m    loadbalancer-controller  ip: 203.0.113.2
    ...
    

    El aprovisionamiento de Ingress puede tardar varios minutos.

Aplicación de prueba

  1. Comprueba el estado del certificado SSL:

    kubectl get managedcertificates.networking.gke.io networking-managed-cert
    

    El certificado SSL puede tardar hasta 30 minutos en aprovisionarse. El siguiente resultado indica que el certificado SSL está listo:

    NAME                      AGE   STATUS
    networking-managed-cert   28m   Active
    
  2. Ejecuta un comando curl:

    curl -Lv https://DOMAIN_NAME
    

    El resultado debería ser similar al siguiente:

    *   Trying 34.160.115.33:443...
    * Connected to DOMAIN_NAME (34.160.115.33) port 443 (#0)
    ...
    * TLSv1.3 (IN), TLS handshake, Certificate (11):
    ...
    * Server certificate:
    *  subject: CN=DOMAIN_NAME
    ...
    > Host: DOMAIN_NAME