Crear un libro de visitas con Redis y PHP

En este instructivo, se explica cómo compilar una aplicación web simple de varios niveles con GKE. La aplicación del instructivo es un libro de visitas que les permite a los visitantes ingresar texto en un registro y ver las entradas de registro más recientes.

En el instructivo, se indica cómo configurar un servicio web de libro de visitas en una IP externa mediante un balanceador de cargas y cómo ejecutar un clúster de Redis con una sola instancia principal y varios trabajadores.

En este ejemplo, se destacan varios conceptos importantes sobre GKE, como los siguientes:

Objetivos

Sigue estos pasos para implementar y ejecutar la aplicación de libro de visitas en GKE:

  1. Configura una instancia principal de Redis
  2. Configura trabajadores de Redis.
  3. Configura el frontend web del libro de visitas.
  4. Visita el sitio web del libro de visitas.
  5. Escala el frontend web del libro de visitas.

Antes de comenzar

Sigue los pasos que se indican a continuación para habilitar la API de Kubernetes Engine:
  1. Consulta la página de Kubernetes Engine en Google Cloud Console.
  2. Crea o selecciona un proyecto.
  3. Espera a que la API y los servicios relacionados se habiliten. Esto puede tardar varios minutos.
  4. Asegúrate de tener habilitada la facturación para tu proyecto de Google Cloud Platform. Obtén información sobre cómo confirmar que tienes habilitada la facturación para tu proyecto.

Instala las siguientes herramientas de línea de comandos de este instructivo:

  • gcloud se usa para crear y borrar clústeres de Kubernetes Engine. gcloud se incluye en el SDK de Google Cloud.
  • kubectl se usa para administrar Kubernetes, el sistema de organización de clústeres que emplea Kubernetes Engine. Puedes instalar kubectl con gcloud:
    gcloud components install kubectl

Establecer valores predeterminados para la herramienta de línea de comandos de gcloud

Para ahorrar tiempo cuando escribes las opciones del ID del proyecto y la zona de Compute Engine en la herramienta de línea de comandos de gcloud, puedes establecer los valores predeterminados:
gcloud config set project [PROJECT_ID]
gcloud config set compute/zone [COMPUTE_ENGINE_ZONE]

Descargar los archivos de configuración

Visita el repositorio de GitHub de ejemplos de Kubernetes para descargar los archivos de configuración que se usan en este instructivo:

Crear un clúster de GKE

El primer paso es crear un clúster de GKE en el que deberás ejecutar la aplicación de libro de visitas y el servicio de Redis.

Crea un clúster de contenedores llamado guestbook con 2 nodos:

gcloud container clusters create guestbook --num-nodes=2

Puedes usar los siguientes comandos para generar una lista de todos los clústeres de tu proyecto o solicitar los detalles de uno de ellos:

gcloud container clusters list
gcloud container clusters describe guestbook

Paso 1: Configurar una instancia principal de Redis

La aplicación de libro de visita usa Redis para almacenar sus datos. Escribe sus datos en una instancia principal de Redis y lee datos de varias instancias trabajadoras (esclavas). El primer paso es implementar la instancia principal de Redis.

Usa el archivo de manifiesto llamado redis-master-deployment para implementar la instancia principal de Redis. En el archivo de manifiesto, se especifica un controlador de implementaciones que ejecuta el pod de instancia principal de Redis de una sola replica:

apiVersion: apps/v1 #  for k8s versions before 1.9.0 use apps/v1beta2  and before 1.8.0 use extensions/v1beta1
kind: Deployment
metadata:
  name: redis-master
spec:
  selector:
    matchLabels:
      app: redis
      role: master
      tier: backend
  replicas: 1
  template:
    metadata:
      labels:
        app: redis
        role: master
        tier: backend
    spec:
      containers:
      - name: master
        image: k8s.gcr.io/redis:e2e  # or just image: redis
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        ports:
        - containerPort: 6379

Ejecuta el siguiente comando para implementar la instancia principal de Redis:

kubectl create -f redis-master-deployment.yaml

Verifica que el pod de instancia principal de Redis ejecute el comando kubectl get pods:

kubectl get pods
Resultado:
NAME                           READY     STATUS    RESTARTS   AGE
redis-master-343230949-qfvrq   1/1       Running   0          43s

Copia el nombre del pod de los resultados del comando anterior y ejecuta el siguiente para revisar los registros del pod principal de Redis:

kubectl logs -f [POD_NAME]

Crear el servicio redis-master

La aplicación de libro de visitas necesita comunicarse con la instancia principal de Redis para escribir sus datos. Debes crear un servicio para poder usar un proxy en el tráfico hacia el pod de instancia principal de Redis.

Un servicio es una abstracción de Kubernetes que define un conjunto lógico de pods y una política para acceder a ellos. En efecto, es un balanceador de cargas con nombre que actúa como proxy para el tráfico a uno o varios pods. Cuando configuras un servicio, debes usar las etiquetas de los pods para indicarle cuáles actuarán como proxies.

Revisa el archivo de manifiesto redis-master-service.yaml, en el que se describe un recurso de servicio para la instancia principal de Redis:

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

Con este archivo de manifiesto, se crea un servicio llamado redis-master con un conjunto de selectores de etiquetas. Estas coinciden con el conjunto de etiquetas implementado en el paso anterior. Por lo tanto, este servicio enruta el tráfico de la red al pod de instancia principal de Redis que creaste en el paso 1.

En la sección ports del manifiesto, se declara la asignación de un solo puerto. En este caso, el servicio enrutará el tráfico del port: 6379 al targetPort: 6379 de los contenedores que coincidan con las etiquetas selector especificadas. Ten en cuenta que el containerPort de la implementación debe coincidir con el targetPort a fin de enrutar el tráfico a la implementación.

Para iniciar el servicio de instancia principal de Redis, ejecuta el siguiente comando:

kubectl create -f redis-master-service.yaml

Verifica que se haya creado el servicio con el siguiente comando:

kubectl get service
Resultado:
NAME           CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes     10.51.240.1     <none>        443/TCP    42s
redis-master   10.51.242.233   <none>        6379/TCP   12s

Paso 2: Configura trabajadores de Redis

A pesar de que la instancia principal de Redis consta de un solo pod, puedes hacer que tenga una disponibilidad alta y satisfaga las exigencias de tráfico. Para ello, agrega algunas réplicas de trabajadores de Redis.

Revisa el archivo de manifiesto redis-slave-deployment.yaml, en el que se describe una implementación para los pods de los trabajadores de Redis:

apiVersion: apps/v1 #  for k8s versions before 1.9.0 use apps/v1beta2  and before 1.8.0 use extensions/v1beta1
kind: Deployment
metadata:
  name: redis-slave
spec:
  selector:
    matchLabels:
      app: redis
      role: slave
      tier: backend
  replicas: 2
  template:
    metadata:
      labels:
        app: redis
        role: slave
        tier: backend
    spec:
      containers:
      - name: slave
        image: gcr.io/google_samples/gb-redisslave:v1
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        env:
        - name: GET_HOSTS_FROM
          value: dns
          # If your cluster config does not include a dns service, then to
          # instead access an environment variable to find the master
          # service's host, comment out the 'value: dns' line above, and
          # uncomment the line below:
          # value: env
        ports:
        - containerPort: 6379

La implementación debe obtener la configuración declarada en el archivo de manifiesto. Por ejemplo, este archivo de manifiesto permite definir dos réplicas para los trabajadores de Redis. Si no hay réplicas en ejecución, la implementación iniciará las dos que se encuentran en el clúster de tu contenedor. Si hay más de dos réplicas en ejecución, debe cerrar una de ellas para cumplir con la configuración.

En este caso, se especifican dos replicas. Para crear la implementación de trabajadores de Redis, ejecuta el siguiente comando:

kubectl create -f redis-slave-deployment.yaml

Consulta la lista de pods para verificar que se están ejecutando las dos réplicas de trabajadores de Redis:

kubectl get pods
Resultado:
NAME                           READY     STATUS    RESTARTS   AGE
redis-master-343230949-qfvrq   1/1       Running   0          17m
redis-slave-132015689-dp23k    1/1       Running   0          2s
redis-slave-132015689-xq9v0    1/1       Running   0          2s

Crear el servicio redis-slave

La aplicación de libro de visitas debe comunicarse con los trabajadores de Redis a fin de poder leer datos. Para detectar los trabajadores de Redis, debes configurar un servicio. Este proporcionará un balanceo de cargas transparente a un conjunto de pods.

Con redis-slave-service.yaml, se define la configuración del servicio para los trabajadores de Redis:

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

Con este archivo, se define un servicio llamado redis-slave que se ejecuta en el puerto 6379. Ten en cuenta que el campo selector del servicio coincide con los pods de los trabajadores de Redis que se crearon en el paso anterior.

Para crear el servicio redis-slave, ejecuta el siguiente comando:

kubectl create -f redis-slave-service.yaml

Verifica que se haya creado el servicio con el siguiente comando:

kubectl get service
Resultado:
NAME           CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
kubernetes     10.51.240.1     <none>        443/TCP    1m
redis-master   10.51.242.233   <none>        6379/TCP   49s
redis-slave    10.51.247.238   <none>        6379/TCP   3s

Paso 3: Configura el frontend web del libro de visitas

Ahora que el almacenamiento de Redis del libro de visitas está listo para usarlo, inicia sus servidores web. Del mismo modo que los trabajadores de Redis, esta es una aplicación replicada que se administra mediante una implementación.

En este instructivo, se usa un frontend de PHP simple, que se configura para que pueda comunicarse con los servicios principal o trabajador de Redis. Esto depende de si la solicitud es de lectura o escritura. Asimismo, expone una interfaz JSON sencilla y entrega una UX basada en jQuery-Ajax.

Revisa el archivo de manifiesto frontend-deployment.yaml, en el que se describe la implementación para el servidor web del libro de visitas:

apiVersion: apps/v1 #  for k8s versions before 1.9.0 use apps/v1beta2  and before 1.8.0 use extensions/v1beta1
kind: Deployment
metadata:
  name: frontend
spec:
  selector:
    matchLabels:
      app: guestbook
      tier: frontend
  replicas: 3
  template:
    metadata:
      labels:
        app: guestbook
        tier: frontend
    spec:
      containers:
      - name: php-redis
        image: gcr.io/google-samples/gb-frontend:v4
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
        env:
        - name: GET_HOSTS_FROM
          value: dns
          # If your cluster config does not include a dns service, then to
          # instead access environment variables to find service host
          # info, comment out the 'value: dns' line above, and uncomment the
          # line below:
          # value: env
        ports:
        - containerPort: 80

Para crear la implementación del frontend web del libro de visitas, ejecuta el comando:

kubectl create -f frontend-deployment.yaml

Consulta la lista de etiquetas que identifican el frontend web para verificar que se están ejecutando las tres réplicas:

kubectl get pods -l app=guestbook -l tier=frontend
Resultado:
NAME                      READY     STATUS    RESTARTS   AGE
frontend-88237173-5p257   1/1       Running   0          40s
frontend-88237173-84036   1/1       Running   0          40s
frontend-88237173-j3rvr   1/1       Running   0          40s

En este archivo de manifiesto, se especifica la variable de entorno GET_HOSTS_FROM=dns. Cuando se asigna esta configuración a la aplicación del frontend web del libro de visitas, esta usa los nombres de host redis-slave y redis-master, y ejecuta una búsqueda de DNS para obtener las direcciones IP de los servicios respectivos que creaste en los pasos anteriores. Este concepto se llama descubrimiento del servicio de DNS.

Exponer el frontend en una dirección IP externa

Los servicios redis-slave y redis-master que creaste en los pasos anteriores solo son accesibles en el clúster del contenedor, ya que ClusterIP es el tipo predeterminado para un servicio. Con ClusterIP, se proporciona una sola dirección IP para el conjunto de pods al que se direcciona el servicio. Solo se puede acceder a esta dirección IP en el clúster.

Sin embargo, el servicio del frontend web del libro de visitas debe ser visible de manera externa. Es decir, los clientes deben poder solicitar el servicio desde fuera del clúster del contenedor. Para lograr esto, debes especificar type: LoadBalancer en la configuración del servicio. El archivo de manifiesto frontend-service.yaml en el que se especifica esta configuración tiene el siguiente aspecto:

apiVersion: v1
kind: Service
metadata:
  name: frontend
  labels:
    app: guestbook
    tier: frontend
spec:
  # comment or delete the following line if you want to use a LoadBalancer
  type: NodePort
  # if your cluster supports it, uncomment the following to automatically create
  # an external load-balanced IP for the frontend service.
  # type: LoadBalancer
  ports:
  - port: 80
  selector:
    app: guestbook
    tier: frontend

Cuando se crea el servicio frontend, GKE crea un balanceador de cargas y una dirección IP externa. Ten en cuenta que estos recursos están sujetos a facturación. En la declaración del puerto en la sección ports, se especifica port: 80, pero no se especifica targetPort. Cuando omites la propiedad targetPort, su valor predeterminado es el valor del campo port. En este caso, con este servicio, se enrutará el tráfico externo del puerto 80 al puerto 80 de los contenedores de la implementación frontend.

Para crear el servicio, primero debes quitar el comentario de la siguiente línea en el archivo frontend-service.yaml:

type: LoadBalancer

Luego, ejecuta el siguiente comando para crear el servicio:

kubectl create -f frontend-service.yaml

Paso 4: Visita el sitio web del libro de visitas

Para acceder al servicio del libro de visitas, debes ejecutar el siguiente comando a fin de buscar la IP externa correspondiente al servicio:

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

Copia la dirección IP en la columna EXTERNAL-IP y carga la página del navegador.

Libro de visitas en ejecución en GKE

Felicitaciones. Intenta agregar entradas al libro de visitas.

Paso 5: Escala el frontend web

Supongamos que tu aplicación de libro de visitas lleva un tiempo en ejecución y, de un momento a otro, se llena de publicidad. Entonces, decides que sería una buena idea agregar más servidores web a tu frontend. Esto es fácil de hacer, ya que tus servidores están definidos como un servicio que usa un controlador de implementación.

Para escalar verticalmente tus pods de frontend a 5, ejecuta el siguiente comando:

kubectl scale deployment frontend --replicas=5

La configuración de la implementación se actualizará para indicar que debería haber 5 réplicas en ejecución. La implementación ajusta la cantidad de pods para que coincidan. Para verificar, ejecuta el siguiente comando:

kubectl get pods
Resultado:
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-master-343230949-qfvrq   1/1       Running   0          54m
redis-slave-132015689-dp23k    1/1       Running   0          37m
redis-slave-132015689-xq9v0    1/1       Running   0          37m

Cuando tu sitio vuelva a la oscuridad, puedes seguir los mismos pasos para reducir la cantidad de pods del servidor web.

Limpiar

Sigue estos pasos para evitar que se apliquen cargos a tu cuenta de Google Cloud Platform por los recursos que usaste en este instructivo:

Paso 6: Limpieza

Después de completar este instructivo, sigue estos pasos para quitar los siguientes recursos y evitar que se apliquen cargos no deseados en tu cuenta:

  1. Borra el servicio: en este paso, se designa el balanceador de cargas de Cloud creado para el servicio de frontend:

    kubectl delete service frontend

  2. Espera a que se borre el balanceador de cargas aprovisionado para el servicio de frontend: el balanceador de cargas se borra de forma asíncrona en segundo plano cuando ejecutas kubectl delete. Espera hasta que el balanceador de cargas se haya borrado. Para ello, mira el resultado del siguiente comando:

    gcloud compute forwarding-rules list

  3. Borra el clúster del contenedor: este paso borrará los recursos que conforman clústeres del contenedor, como las instancias de procesamiento, los discos y los recursos de red.

    gcloud container clusters delete guestbook

Próximos pasos