Implementa un clúster de Redis en GKE


En este instructivo, se proporcionan prácticas recomendadas para crear una aplicación con estado y actualizar el clúster de Google Kubernetes Engine (GKE) que ejecuta la aplicación. En este instructivo, se usa Redis como ejemplo para implementar una aplicación con estado, pero los mismos conceptos se aplican a otros tipos de aplicaciones con estado implementadas en GKE.

Objetivos

En este instructivo, se abarcan los siguientes pasos:

  1. Crea un clúster de GKE inscrito en un canal de versiones.
  2. Crea un Clúster de Redis en GKE
  3. Implementa la aplicación cliente de Redis en GKE
  4. Realiza estas prácticas recomendadas para las actualizaciones de grupos de nodos:
    1. Configura el presupuesto de interrupción de Pods (PDB).
    2. Configura el período de mantenimiento y las exclusiones.
    3. Configura la estrategia de actualización de nodos como actualización de aumento o actualización azul-verde.
  5. Probar la aplicación
  6. Actualiza el clúster.
  7. Prueba la interrupción de la carga de trabajo.

En el siguiente diagrama, se muestra una vista de alto nivel de la arquitectura del clúster para este instructivo:

Diagrama de arquitectura

Costos

En este documento, usarás los siguientes componentes facturables de Google Cloud:

Para generar una estimación de costos en función del uso previsto, usa la calculadora de precios. Es posible que los usuarios nuevos de Google Cloud califiquen para obtener una prueba gratuita.

Cuando finalices las tareas que se describen en este documento, puedes borrar los recursos que creaste para evitar que continúe la facturación. Para obtener más información, consulta Cómo realizar una limpieza.

Antes de comenzar

Configura tu proyecto

  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. In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the GKE API.

    Enable the API

  5. In the Google Cloud console, on the project selector page, click Create project to begin creating a new Google Cloud project.

    Go to project selector

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Enable the GKE API.

    Enable the API

Establece valores predeterminados para Google Cloud CLI

  1. En la consola de Google Cloud, inicia una instancia de Cloud Shell:
    Abrir Cloud Shell

  2. Descarga el código fuente para esta app de ejemplo:

     git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
     cd kubernetes-engine-samples/quickstarts/hello-app-redis/manifests
    
  3. Configura las variables de entorno predeterminadas:

     gcloud config set project PROJECT-ID
     gcloud config set compute/zone COMPUTE-ZONE
    

    Reemplaza los siguientes valores:

Crea un clúster de GKE inscrito en un canal de versiones

Para crear un clúster de GKE, completa los siguientes pasos:

  1. Crea un clúster llamado redis-test con tres nodos:

    gcloud container clusters create redis-test \
        --num-nodes=3 \
        --release-channel regular
    

    Una vez que se cree el clúster, deberías ver un resultado similar al siguiente:

      NAME: redis-test
      LOCATION: us-central1-c
      MASTER_VERSION: 1.22.10-gke.600
      MASTER_IP: 34.69.67.7
      MACHINE_TYPE: e2-medium
      NODE_VERSION: 1.22.10-gke.600
      NUM_NODES: 3
      STATUS: RUNNING
    
  2. Configura kubectl para comunicarse con el clúster:

    gcloud container clusters get-credentials redis-test
    

Crea un Clúster de Redis en GKE

En esta sección, agregarás un clúster de Redis sobre el clúster de GKE que creaste antes mediante la implementación de un ConfigMap, un StatefulSety un Service sin interfaz gráfica.

Para crear un clúster de Redis, completa estos pasos:

  1. Consulta el archivo ConfigMap (redis-configmap.yaml) que almacena la configuración de Redis. En el siguiente fragmento, se muestra el sondeo de preparación y las secuencias de comandos del sondeo de funcionamiento.

    readiness.sh: |-
      #!/bin/sh
    
      pingResponse="$(redis-cli -h localhost ping)"
      if [ "$?" -eq "124" ]; then
        echo "PING timed out"
        exit 1
      fi
    
      if [ "$pingResponse" != "PONG"]; then
        echo "$pingResponse"
        exit 1
      fi
    liveness.sh: |-
      #!/bin/sh
    
      pingResponse="$(redis-cli -h localhost ping | head -n1 | awk '{print $1;}')"
      if [ "$?" -eq "124" ]; then
        echo "PING timed out"
        exit 1
      fi
    
      if [ "$pingResponse" != "PONG"] && [ "$pingResponse" != "LOADING" ] && [ "$pingResponse" != "MASTERDOWN" ]; then
        echo "$pingResponse"
        exit 1
      fi

    Las secuencias de comandos readiness.sh y liveness.sh usan redis-cli ping para verificar si el servidor de redis se está ejecutando o no. Si muestra PONG, significa que el servidor de Redis está en funcionamiento. Estas secuencias de comandos se usarán en redis-cluster.yaml.

    Para obtener más información sobre los parámetros de Redis en este ConfigMap, consulta la sección de parámetros de configuración del clúster de Redis en el Instructivo del clúster de Redis.

  2. Implementa el ConfigMap:

    kubectl apply -f redis-configmap.yaml
    
  3. Consulta el fragmento de StatefulSet (redis-cluster.yaml) que aparece a continuación, en el que se muestra el uso del sondeo de preparación y el de funcionamiento.

    Para obtener más información sobre cómo configurar sondeos en Kubernetes, consulta Configura sondeos.

    startupProbe:
      periodSeconds: 5
      timeoutSeconds: 5
      successThreshold: 1
      failureThreshold: 20
      tcpSocket:
        port: redis
    livenessProbe:
      periodSeconds: 5
      timeoutSeconds: 5
      successThreshold: 1
      failureThreshold: 5
      exec:
        command: ["sh", "-c", "/probes/liveness.sh"]
    readinessProbe:
      periodSeconds: 5
      timeoutSeconds: 1
      successThreshold: 1
      failureThreshold: 5
      exec:
        command: ["sh", "-c", "/probes/readiness.sh"]

    Recomendamos que uses sondeos de preparación y capacidad de respuesta cuando actualices los grupos de nodos; esto garantiza que tus Pods estén listos durante una actualización.

  4. Implementa StatefulSet:

    kubectl apply -f redis-cluster.yaml
    
  5. El Service sin interfaz gráfica llamado redis-service.yaml es para la conexión de nodos de Redis. El campo clusterIP se establece en None para crear un Service sin interfaz gráfica.

    Implementa el Service:

    kubectl apply -f redis-service.yaml
    
  6. Espera aproximadamente dos minutos y verifica que todos los Pods estén en ejecución mediante el siguiente comando:

    kubectl get pods
    

    Deberías ver un resultado similar al siguiente:

    NAME      READY   STATUS              RESTARTS   AGE
    redis-0   1/1     Running             0          2m29s
    redis-1   1/1     Running             0          2m8s
    redis-2   1/1     Running             0          107s
    redis-3   1/1     Running             0          85s
    redis-4   1/1     Running             0          54s
    redis-5   1/1     Running             0          23s
    
  7. Ejecuta el siguiente comando para verificar que se crearon los volúmenes persistentes:

    kubectl get pv
    

    Deberías ver un resultado similar al siguiente:

    NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                  STORAGECLASS   REASON   AGE
    pvc-HASH   1Gi        RWO            Delete           Bound    default/data-redis-5   standard                75s
    pvc-HASH   1Gi        RWO            Delete           Bound    default/data-redis-1   standard                2m59s
    pvc-HASH   1Gi        RWO            Delete           Bound    default/data-redis-3   standard                2m16s
    pvc-HASH   1Gi        RWO            Delete           Bound    default/data-redis-2   standard                2m38s
    pvc-HASH   1Gi        RWO            Delete           Bound    default/data-redis-0   standard                3m20s
    pvc-HASH   1Gi        RWO            Delete           Bound    default/data-redis-4   standard                104s
    

    En este resultado, HASH representa un hash adjunto a cada nombre de volumen persistente.

Asigna roles al clúster de Redis

Una vez que completes la configuración, asigna roles al clúster de Redis.

La siguiente secuencia de comandos obtiene las direcciones IP del Pod y, luego, asigna los roles de líder y de seguidor mediante el paso de cada una de las direcciones IP del Pod al comando:

#!/bin/bash
# Usage: ./roles.sh

urls=$(kubectl get pods -l app=redis -o jsonpath='{range.items[*]}{.status.podIP} ')
command="kubectl exec -it redis-0 -- redis-cli --cluster create --cluster-replicas 1 "

for url in $urls
do
    command+=$url":6379 "
done

echo "Executing command: " $command
$command

Para asignar roles a tu clúster de Redis, completa estos pasos:

  1. Ejecute la secuencia de comandos:

    chmod +x ./roles.sh
    ./roles.sh
    
  2. Escribe yes cuando se te solicite.

  3. Accede a un nodo de Redis para verificar su rol. Por ejemplo, para verificar que redis-0 tenga una función líder, ejecuta el siguiente comando:

    kubectl exec -it redis-0 -- redis-cli role
    

    Deberías ver un resultado similar al siguiente:

    1) "master"
    2) (integer) 574
    3) 1) 1) "10.28.2.3"
           2) "6379"
           3) "574"
    

Implementa la aplicación cliente de Redis

Para implementar la aplicación en el clúster de GKE que creaste, define una implementación para la aplicación. El archivo llamado app-deployment.yaml contiene la definición de la implementación de la aplicación.

Para obtener más información sobre los sondeos y las reglas de afinidad de Pods que se usan en esta implementación, consulta Prácticas recomendadas de GKE: Diseña y compila clústeres con alta disponibilidad.

Para crear el Deployment, sigue estos pasos:

  1. Aplica la implementación:

    kubectl apply -f app-deployment.yaml
    
  2. Expón la aplicación a través de un balanceador de cargas:

    kubectl expose deployment hello-web \
        --type=LoadBalancer \
        --port 80 \
        --target-port 8080
    
  3. Espera aproximadamente un minuto y recupera la dirección IP externa de la aplicación mediante la ejecución del siguiente comando:

    kubectl get service
    

    En el resultado, copia el valor que aparece en la columna EXTERNAL-IP de hello-web's:

    NAME             TYPE           CLUSTER-IP    EXTERNAL-IP    PORT(S)              AGE
    hello-web        LoadBalancer   10.13.10.55   EXTERNAL_IP   80:30703/TCP         166m
    
  4. Verifica que la aplicación funcione. Para ello, pega EXTERNAL_IP en el navegador web. Deberías ver un resultado similar al siguiente:

    I have been hit [1] times since deployment!
    

    Anota el número de visita. Debes usarlo en la sección Prueba la interrupción de la aplicación.

  5. Establece una variable para la EXTERNAL_IP que acabas de copiar. Este valor se usa cuando creas secuencias de comandos para probar la aplicación en la siguiente sección:

    export IP=EXTERNAL_IP
    

Configura las prácticas recomendadas para las actualizaciones de grupos de nodos

Realiza estas prácticas recomendadas para las aplicaciones con estado a fin de optimizar la mejor disponibilidad durante las actualizaciones del grupo de nodos.

Configura el presupuesto de interrupción de Pods (PDB)

Crea un presupuesto de interrupción de Pods para limitar la cantidad de Pods replicados que se encuentran inactivos de forma simultánea durante una interrupción voluntaria. Esto es útil para aplicaciones con estado en las que debe haber un quórum para que la cantidad de réplicas estén disponibles durante una actualización.

apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
  name: redis-pdb
spec:
  minAvailable: 3
  selector:
    matchLabels:
      app: redis

En una definición de PDB:

  • app especifica a qué aplicación se aplica este PDB.
  • minAvailable establece la cantidad mínima de Pods que estarán disponibles durante una interrupción. Puede ser un valor o un porcentaje (p. ej., 30%).
  • maxUnavailable establece la cantidad máxima de Pods que pueden no estar disponibles durante una interrupción. También puede ser un valor o un porcentaje.

Para configurar el PDB, completa estos pasos:

  1. Implementa el PDB:

    kubectl apply -f pdb-minavailable.yaml
    
  2. Verifica que se haya creado el PDB:

    kubectl get pdb
    

Configura las exclusiones y los períodos de mantenimiento

Las actualizaciones automáticas de nodos optimizan el proceso y mantienen los nodos en el clúster actualizados cuando el plano de control se actualiza en tu nombre. Esta función está habilitada de forma predeterminada. Para obtener más información, consulta Actualización automática de nodos.

Usa períodos de mantenimiento y exclusiones de mantenimiento para configurar períodos y controlar cuándo puede o no puede ocurrir el mantenimiento en los clústeres de GKE:

  1. Configura un período de mantenimiento que comience a las 2:00 a.m. UTC del 19 de agosto de 2022 y finalice cuatro horas después. Este período de mantenimiento se ejecuta a diario. Durante este tiempo, se permite el mantenimiento automático.

    gcloud container clusters update redis-test \
       --maintenance-window-start 2022-08-19T02:00:00Z \
       --maintenance-window-end 2022-08-19T06:00:00Z \
       --maintenance-window-recurrence FREQ=DAILY
    
  2. Configura un período de exclusión que evite el mantenimiento durante las festividades de Año Nuevo. Esta exclusión de mantenimiento usa el permiso no_upgrades. Durante este tiempo, no se permite el mantenimiento automático de ningún tipo. Para obtener más información, consulta Alcance del mantenimiento que se excluirá.

    gcloud container clusters update redis-test \
       --add-maintenance-exclusion-name new-year \
       --add-maintenance-exclusion-start 2022-12-26T00:00:00Z \
       --add-maintenance-exclusion-end 2023-01-02T02:00:00Z \
       --add-maintenance-exclusion-scope no_upgrades
    
  3. Verifica que se apliquen las exclusiones y el período de mantenimiento. Mira en maintenancePolicy:

    gcloud container clusters describe redis-test
    

Para obtener más información, consulta Configura exclusiones y períodos de mantenimiento.

Configura una estrategia de actualización de nodos

Existen dos estrategias de actualización de nodos que puedes usar para los grupos de nodos de tu clúster de GKE: actualizaciones azul-verde y actualizaciones de aumento. Para obtener más información, consulta Estrategias de actualización de nodos.

Actualizaciones azul-verde

Elige actualizaciones azul-verde si las cargas de trabajo son menos tolerantes a las interrupciones. Además, un aumento temporal del costo debido al mayor uso de recursos es aceptable.

Ejecuta el siguiente comando para cambiar los grupos de nodos actuales a la estrategia actualización azul-verde.

gcloud container node-pools update default-pool \
--cluster=redis-test \
--enable-blue-green-upgrade \
--zone COMPUTE-ZONE \
--node-pool-soak-duration=120s

La duración del tiempo de espera del grupo de nodos se establece en dos minutos para ahorrar tiempo durante la fase de tiempo de espera del grupo de nodos para los fines de este instructivo. Esta fase se usa para que verifiques el estado de la carga de trabajo después de que se vacíen los nodos del grupo azul. Recomendamos configurar el tiempo de espera del grupo de nodos en una hora (3,600 segundos) o la duración que mejor se adapte a la aplicación.

Para obtener más información sobre la administración de la asignación de pods, consulta Implementa un pod en un grupo de nodos específico y, también, Implementa servicios en grupos de nodos específicos

Para obtener más información sobre cómo configurar las actualizaciones azul-verde, consulta Configura actualizaciones azul-verde.

Actualizaciones de aumento

Elige actualizaciones de aumento si la optimización de costos es importante y si las cargas de trabajo pueden tolerar un cierre controlado en menos de 60 minutos (GKE respeta los PDB hasta 60 minutos).

Ejecuta el siguiente comando para cambiar los grupos de nodos actuales a la estrategia de actualización de aumento.

gcloud container node-pools update default-pool \
--max-surge-upgrade=1 \
--max-unavailable-upgrade=0 \
--cluster=redis-test

Con esta configuración (maxSurge=1 y maxUnavailable=0), solo se puede agregar un nodo de aumento al grupo de nodos durante una actualización, de modo que solo se puede actualizar un nodo a la vez. Esta configuración acelera el reinicio de los Pods durante las actualizaciones mientras se procesa de forma conservadora.

Para obtener más información sobre cómo configurar las actualizaciones de aumento, consulta Configura las actualizaciones de aumento.

Verifica la configuración actual del grupo de nodos:

   gcloud container node-pools describe default-pool \
   --cluster redis-test \
   --zone COMPUTE-ZONE

Para obtener más información sobre cómo ver grupos de nodos, consulta Visualiza grupos de nodos en un clúster.

Probarla

En esta sección, usarás dos secuencias de comandos, una que envía solicitudes a la aplicación y otra que mide la tasa de éxito de las solicitudes. Usarás estas secuencias de comandos para medir lo que sucede cuando actualizas el clúster.

Para crear las secuencias de comandos, sigue estos pasos:

  1. Cambia al directorio que contiene las secuencias de comandos:

    cd
    cd kubernetes-engine-samples/quickstarts/hello-app-redis/scripts
    
  2. Consulta la secuencia de comandos llamada generate_load.sh, que envía una solicitud de consultas por segundo (QPS) a la aplicación. Esta secuencia de comandos guarda el código de respuesta HTTP en el directorio actual en un archivo llamado output. El valor de output se usa en la secuencia de comandos que creas en el paso siguiente.

    #!/bin/bash
    # Usage: ./generate_load.sh <IP> <QPS>
    
    IP=$1
    QPS=$2
    
    while true
      do for N in $(seq 1 $QPS)
        do curl -I -m 5 -s -w "%{http_code}\n" -o /dev/null http://${IP}/ >> output &
        done
      sleep 1
    done
  3. Consulta la secuencia de comandos llamada print_error_rate.sh, que calcula la tasa de éxito en función del resultado que generó generate_load.sh.

    #!/bin/bash
    # Usage: watch ./print_error_rate.sh
    
    TOTAL=$(cat output | wc -l);
    SUCCESS=$(grep "200" output |  wc -l);
    ERROR1=$(grep "000" output |  wc -l)
    ERROR2=$(grep "503" output |  wc -l)
    ERROR3=$(grep "500" output |  wc -l)
    SUCCESS_RATE=$(($SUCCESS * 100 / TOTAL))
    ERROR_RATE=$(($ERROR1 * 100 / TOTAL))
    ERROR_RATE_2=$(($ERROR2 * 100 / TOTAL))
    ERROR_RATE_3=$(($ERROR3 * 100 / TOTAL))
    echo "Success rate: $SUCCESS/$TOTAL (${SUCCESS_RATE}%)"
    echo "App network Error rate: $ERROR1/$TOTAL (${ERROR_RATE}%)"
    echo "Resource Error rate: $ERROR2/$TOTAL (${ERROR_RATE_2}%)"
    echo "Redis Error rate: $ERROR3/$TOTAL (${ERROR_RATE_3}%)"
  4. Otórgate permiso para ejecutar las secuencias de comandos:

    chmod u+x generate_load.sh print_error_rate.sh
    
  5. Establece una variable para la cantidad de QPS. Este valor se usa en la secuencia de comandos generate_load.sh como la variable que configuraste para la EXTERNAL_IP. Te recomendamos establecer un valor de 40.

    export QPS=40
    
  6. Ejecuta la secuencia de comandos generate_load.sh para comenzar a enviar QPS:

    ./generate_load.sh $IP $QPS 2>&1
    
  7. Deja la secuencia de comandos generate_load.sh en ejecución y abre una terminal nueva. En la terminal nueva, ejecuta la secuencia de comandos print_error_rate.sh para verificar la tasa de error:

    cd
    cd kubernetes-engine-samples/quickstarts/hello-app-redis/scripts
    watch ./print_error_rate.sh
    

    Deberías ver una tasa de éxito del 100% y una tasa de error del 0% a medida que se realizan las QPS.

  8. Deja las secuencias de comandos en ejecución y abre una tercera terminal en preparación para la siguiente sección.

Actualiza el clúster

Para actualizar el clúster, completa estos pasos:

  1. Determina qué versión de GKE usa el clúster redis-test:

    V=$(gcloud container clusters describe redis-test | grep "version:" | sed "s/version: //")
    echo $V
    

    Deberías ver un resultado similar al siguiente ejemplo: 1.22.9-gke.2000.

  2. Recupera una lista de las versiones de Kubernetes disponibles:

    gcloud container get-server-config
    
  3. En la lista de versiones, ubica la sección validMasterVersions: y busca la versión de redis-cluster que recuperaste en el paso anterior. Para evitar el sesgo de versión, copia la versión de la lista que aparece justo sobre la versión de redis-cluster.

  4. Actualiza el plano de control del clúster a la versión que seleccionaste y escribe y cuando se te solicite:

    gcloud container clusters upgrade redis-test \
        --master \
        --cluster-version VERSION
    

    Reemplaza VERSION por la versión que seleccionaste de la lista en el paso anterior.

    La actualización del plano de control lleva varios minutos.

  5. Actualiza los nodos del clúster a la versión que seleccionaste y escribe y cuando se te solicite:

    gcloud container clusters upgrade redis-test \
        --cluster-version=VERSION \
        --node-pool=default-pool
    

    Reemplaza VERSION por la versión que seleccionaste de la lista.

Prueba la interrupción de la carga de trabajo

En esta sección, probarás el estado de la aplicación y observarás la interrupción de la carga de trabajo.

  1. Regresa a la ventana de la terminal que ejecuta ./print_error_rate.sh y observa cómo cambió la tasa de éxito durante la actualización. Deberías notar una leve disminución en la tasa de éxito y un ligero aumento en la tasa de error de red de la app, ya que se quitaron los nodos para actualizarlos.

    En el campo Success rate, verás cuántas visitas al sitio web se realizaron de manera correcta. Toma nota de este valor.

  2. Ingresa CTRL+C en las terminales relevantes para evitar que se ejecuten ambas secuencias de comandos.

  3. Para volver al sitio web de la aplicación, ingresa la dirección IP (es la EXTERNAL_IP que copiaste durante la sección Implementa la aplicación cliente de Redis) en el navegador.

  4. Observa el número de visita de la aplicación. El número que ves debe ser igual a lo siguiente:

    ORIGINAL_VISIT_NUMBER + SUCCESSFUL_VISIT_NUMBER

    En el ejemplo anterior, ORIGINAL_VISIT_NUMBER es el número que registraste en el paso final de Implementa la aplicación cliente de Redis, y SUCCESSFUL_VISIT_NUMBER es el valor que registraste en el primer paso de esta sección.

Limpia

Una vez que completes el instructivo, puedes limpiar los recursos que creaste para que dejen de usar la cuota y generar cargos. En las siguientes secciones, se describe cómo borrar o desactivar estos recursos.

Borra el proyecto

La manera más fácil de eliminar la facturación es borrar el proyecto que creaste para el instructivo.

Para borrar el proyecto, haga lo siguiente:

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

Borre el clúster

Para borrar el clúster que creaste en este instructivo, ejecuta el siguiente comando:

gcloud container clusters delete redis-test

¿Qué sigue?