Crear una aplicación web multinivel con Redis y PHP

En este tutorial se muestra cómo crear una aplicación web multinivel con Google Kubernetes Engine (GKE).

En este tutorial, harás lo siguiente:

  • Configura una aplicación web con una dirección IP externa y un balanceador de carga.
  • Crea un clúster de Redis con un solo maestro (líder) y varias réplicas (seguidores).

En el ejemplo se describen los siguientes conceptos de Kubernetes:

Objetivos

Para desplegar y ejecutar la aplicación en GKE, sigue estos pasos:

  1. Configurar el líder de Redis
  2. Configurar dos seguidores de Redis
  3. Configurar el frontend web
  4. Visitar el sitio web
  5. Escalar el frontend web

En el siguiente diagrama se muestra un resumen de la arquitectura del clúster que crearás al completar estos objetivos:

Arquitectura de clúster de GKE

Costes

En este documento, se utilizan los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costes basada en el uso previsto, utiliza la calculadora de precios.

Los usuarios nuevos Google Cloud pueden disfrutar de una prueba gratuita.

Cuando termines las tareas que se describen en este documento, puedes evitar que se te siga facturando eliminando los recursos que has creado. Para obtener más información, consulta la sección Limpiar.

Antes de empezar

Cloud Shell tiene preinstalado el software que necesitas para este tutorial, como kubectl y la CLI de gcloud. Si no usas Cloud Shell, debes instalar la CLI de gcloud.

  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. Preparar el entorno

    Para configurar tu entorno, sigue estos pasos:

    1. Define las variables de entorno:

      export PROJECT_ID=PROJECT_ID
      export COMPUTE_LOCATION=COMPUTE_LOCATION
      

      Haz los cambios siguientes:

    2. Clona el repositorio de GitHub:

      git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
      
    3. Cambia al directorio de trabajo:

      cd kubernetes-engine-samples/quickstarts/guestbook/
      

    Crear un clúster de GKE

    Crea un clúster de GKE Autopilot o Estándar:

    Autopilot

    gcloud container clusters create-auto guestbook \
        --location=${COMPUTE_LOCATION} \
    

    Estándar

    gcloud container clusters create guestbook \
        --location=${COMPUTE_LOCATION} \
        --num-nodes=4
    

    Conéctate al clúster

    Configura kubectl para que se comunique con el clúster:

    gcloud container clusters get-credentials guestbook \
        --location=${COMPUTE_LOCATION}
    

    Configurar el líder de Redis

    La aplicación usa Redis para almacenar sus datos. La aplicación escribe sus datos en una instancia principal de Redis y lee datos de varias instancias secundarias de Redis.

    1. El siguiente manifiesto describe un Deployment de Kubernetes que ejecuta un pod de líder de Redis de una sola réplica:

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: redis-leader
        labels:
          app: redis
          role: leader
          tier: backend
      spec:
        replicas: 1
        selector:
          matchLabels:
            app: redis
        template:
          metadata:
            labels:
              app: redis
              role: leader
              tier: backend
          spec:
            containers:
            - name: leader
              image: "docker.io/redis:6.0.5"
              resources:
                requests:
                  cpu: 100m
                  memory: 100Mi
              ports:
              - containerPort: 6379

      Aplica el manifiesto a tu clúster:

      kubectl apply -f redis-leader-deployment.yaml
      
    2. Comprueba que el pod del líder de Redis se está ejecutando:

      kubectl get pods
      

      El resultado debería ser similar al siguiente:

      NAME                           READY     STATUS    RESTARTS   AGE
      redis-leader-343230949-qfvrq   1/1       Running   0          43s
      

      STATUS puede tardar varios minutos en cambiar de Pending a Running.

    Crear el servicio de líder de Redis

    La aplicación web necesita comunicarse con el líder de Redis para escribir sus datos. Puedes crear un servicio para dirigir el tráfico al pod líder de Redis.

    Un servicio es una abstracción de Kubernetes que define un conjunto lógico de pods y una política para habilitar el acceso a los pods. Cuando creas un servicio, describes qué pods se deben proxyizar en función de las etiquetas de los pods.

    1. El siguiente manifiesto describe un servicio para el líder de Redis:

      apiVersion: v1
      kind: Service
      metadata:
        name: redis-leader
        labels:
          app: redis
          role: leader
          tier: backend
      spec:
        ports:
        - port: 6379
          targetPort: 6379
        selector:
          app: redis
          role: leader
          tier: backend

      Este manifiesto incluye un conjunto de selectores de etiquetas. que coinciden con el conjunto de etiquetas que se desplegaron en el paso anterior. Por lo tanto, este servicio dirige el tráfico de red al pod líder de Redis que has creado en un paso anterior.

      La sección ports del manifiesto declara una sola asignación de puertos. El servicio dirige el tráfico de port: 6379 a targetPort: 6379 de los contenedores que coincidan con las etiquetas selector especificadas. El containerPort usado en el Deployment debe coincidir con el targetPort para enrutar el tráfico al Deployment.

      Aplica el manifiesto a tu clúster:

      kubectl apply -f redis-leader-service.yaml
      
    2. Verifica que GKE haya creado el servicio:

      kubectl get service
      

      El resultado debería ser similar al siguiente:

      NAME           CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
      kubernetes     10.51.240.1     <none>        443/TCP    42s
      redis-leader   10.51.242.233   <none>        6379/TCP   12s
      

    Configurar seguidores de Redis

    Aunque el líder de Redis consta de un solo pod, se pueden añadir algunos seguidores o réplicas de Redis para aumentar en gran medida su disponibilidad y satisfacer las demandas de tráfico.

    1. El siguiente manifiesto describe una implementación de los pods de réplica de Redis:

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: redis-follower
        labels:
          app: redis
          role: follower
          tier: backend
      spec:
        replicas: 2
        selector:
          matchLabels:
            app: redis
        template:
          metadata:
            labels:
              app: redis
              role: follower
              tier: backend
          spec:
            containers:
            - name: follower
              image: us-docker.pkg.dev/google-samples/containers/gke/gb-redis-follower:v2
              resources:
                requests:
                  cpu: 100m
                  memory: 100Mi
              ports:
              - containerPort: 6379
    2. Aplica el manifiesto a tu clúster:

      kubectl apply -f redis-follower-deployment.yaml
      
    3. Comprueba que las dos réplicas de seguidores de Redis se están ejecutando:

      kubectl get pods
      

      El resultado debería ser similar al siguiente:

      NAME                              READY   STATUS    RESTARTS   AGE
      redis-follower-76588f55b7-bnsq6   1/1     Running   0          27s
      redis-follower-76588f55b7-qvtws   1/1     Running   0          27s
      redis-leader-dd446dc55-kl7nl      1/1     Running   0          119s
      

      STATUS puede tardar varios minutos en cambiar de Pending a Running.

    Crear el servicio de seguidor de Redis

    La aplicación web debe comunicarse con los seguidores de Redis para leer datos. Para que los seguidores de Redis se puedan detectar, debes configurar un servicio.

    1. El siguiente manifiesto describe un servicio para los seguidores de Redis:

      apiVersion: v1
      kind: Service
      metadata:
        name: redis-follower
        labels:
          app: redis
          role: follower
          tier: backend
      spec:
        ports:
          # the port that this service should serve on
        - port: 6379
        selector:
          app: redis
          role: follower
          tier: backend

      Este manifiesto especifica que el servicio se ejecuta en el puerto 6379. El campo selector del servicio coincide con los pods de seguidores de Redis que has creado en el paso anterior.

      Aplica el manifiesto a tu clúster:

      kubectl apply -f redis-follower-service.yaml
      
    2. Verifica que GKE haya creado el servicio:

      kubectl get service
      

      El resultado debería ser similar al siguiente:

      NAME           CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
      kubernetes     10.51.240.1     <none>        443/TCP    1m
      redis-leader   10.51.242.233   <none>        6379/TCP   49s
      redis-follower 10.51.247.238   <none>        6379/TCP   3s
      

    Configurar el frontend web de la aplicación

    Ahora que tienes el almacenamiento de Redis para tu aplicación, inicia los servidores web. Al igual que los seguidores de Redis, el frontend se despliega mediante un Deployment de Kubernetes.

    La aplicación web usa un frontend PHP, que está configurado para comunicarse con los servicios de seguidor o líder de Redis, en función de si la solicitud es de lectura o de escritura. El frontend expone una interfaz JSON y ofrece una interfaz de usuario basada en jQuery Ajax.

    1. El siguiente manifiesto describe un Deployment para el servidor web:

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: frontend
      spec:
        replicas: 3
        selector:
          matchLabels:
              app: guestbook
              tier: frontend
        template:
          metadata:
            labels:
              app: guestbook
              tier: frontend
          spec:
            containers:
            - name: php-redis
              image: us-docker.pkg.dev/google-samples/containers/gke/gb-frontend:v5
              env:
              - name: GET_HOSTS_FROM
                value: "dns"
              resources:
                requests:
                  cpu: 100m
                  memory: 100Mi
              ports:
              - containerPort: 80

      El archivo de manifiesto especifica la variable de entorno GET_HOSTS_FROM=dns. Cuando proporcionas la configuración a la aplicación web frontend, esta usa los nombres de host redis-follower y redis-leader para realizar una búsqueda de DNS. La petición de DNS busca las direcciones IP de los servicios que has creado en los pasos anteriores. Este concepto se denomina descubrimiento de servicios DNS.

      Aplica el manifiesto a tu clúster:

      kubectl apply -f frontend-deployment.yaml
      
    2. Comprueba que las réplicas se estén ejecutando:

      kubectl get pods -l app=guestbook -l tier=frontend
      

      El resultado debería ser similar al siguiente:

      NAME                        READY   STATUS    RESTARTS   AGE
      frontend-7b78458576-8kp8s   1/1     Running   0          37s
      frontend-7b78458576-gg86q   1/1     Running   0          37s
      frontend-7b78458576-hz87g   1/1     Running   0          37s
      

    Muestra el frontend en una dirección IP externa

    Con la configuración actual, solo se puede acceder a los servicios redis-follower y redis-leader que has creado en los pasos anteriores desde dentro del clúster de GKE, ya que el tipo predeterminado de un servicio es ClusterIP.

    Un ClusterIP servicio proporciona una sola dirección IP para el conjunto de pods al que apunta el servicio. A esta dirección IP solo se puede acceder desde dentro del clúster.

    Para que se pueda acceder al servicio del frontend web desde el exterior, puedes especificar type: LoadBalancer o type: NodePort en la configuración del servicio, en función de tus requisitos.

    El siguiente manifiesto describe un servicio de tipo LoadBalancer:

    apiVersion: v1
    kind: Service
    metadata:
      name: frontend
      labels:
        app: guestbook
        tier: frontend
    spec:
      type: LoadBalancer
      ports:
        # the port that this service should serve on
      - port: 80
      selector:
        app: guestbook
        tier: frontend

    La declaración de puerto de la sección ports especifica port: 80 y no se especifica targetPort. Si omite la propiedad targetPort, se usará el valor predeterminado del campo port. En este caso, este servicio dirige el tráfico externo del puerto 80 al puerto 80 de los contenedores de la implementación frontend.

    Aplica el manifiesto a tu clúster:

    kubectl apply -f frontend-service.yaml
    

    Cuando se crea el frontend Service, GKE crea un balanceador de carga y una dirección IP externa. Estos recursos están sujetos a facturación.

    Visitar el sitio web de la aplicación

    Para acceder al sitio web de la aplicación, obtén la dirección IP externa del servicio frontend:

    kubectl get service frontend
    

    El resultado debería ser similar al siguiente:

    NAME       CLUSTER-IP      EXTERNAL-IP        PORT(S)        AGE
    frontend   10.51.242.136   109.197.92.229     80:32372/TCP   1m
    

    La columna EXTERNAL-IP puede mostrar <pending> mientras se crea el balanceador de carga. Este proceso puede tardar varios minutos. Si ves errores como Does not have minimum availability, espera unos minutos. Este error temporal se produce porque GKE vuelve a crear los nodos para aplicar los cambios.

    Copia la dirección IP y abre la página en el navegador:

    Aplicación web que se ejecuta en GKE

    Prueba a añadir algunas entradas escribiendo un mensaje y haciendo clic en Enviar. El mensaje que has escrito aparece en el frontend. Este mensaje indica que los datos se han añadido correctamente a Redis a través de los servicios que has creado.

    Escalar el frontend web

    Supongamos que tu aplicación lleva un tiempo en funcionamiento y, de repente, recibe una gran publicidad. Crees que sería una buena idea añadir más servidores web a la interfaz. Para ello, aumenta el número de pods.

    1. Aumenta el número de pods frontend:

      kubectl scale deployment frontend --replicas=5
      

      El resultado debería ser similar al siguiente:

      deployment.extensions/frontend scaled
      
    2. Verifica el número de réplicas que se están ejecutando:

      kubectl get pods
      

      El resultado debería ser similar al siguiente:

      NAME                             READY     STATUS    RESTARTS   AGE
      frontend-88237173-3s3sc          1/1       Running   0          1s
      frontend-88237173-twgvn          1/1       Running   0          1s
      frontend-88237173-5p257          1/1       Running   0          23m
      frontend-88237173-84036          1/1       Running   0          23m
      frontend-88237173-j3rvr          1/1       Running   0          23m
      redis-leader-343230949-qfvrq     1/1       Running   0          54m
      redis-follower-132015689-dp23k   1/1       Running   0          37m
      redis-follower-132015689-xq9v0   1/1       Running   0          37m
      

      Puedes reducir el número de frontend pods con el mismo comando, pero sustituyendo 5 por 1.

    Limpieza

    Para evitar que los recursos utilizados en este tutorial se cobren en tu cuenta de Google Cloud, elimina el proyecto que contiene los recursos o conserva el proyecto y elimina los recursos.

    Eliminar el proyecto

      Delete a Google Cloud project:

      gcloud projects delete PROJECT_ID

    Eliminar los recursos concretos

    Si has usado un proyecto que ya existía y no quieres eliminarlo, elimina los recursos concretos.

    1. Elimina el servicio frontend:

      kubectl delete service frontend
      
    2. Elimina el clúster de GKE:

      gcloud container clusters delete guestbook
      

    Siguientes pasos