Implementación continua en Google Kubernetes Engine (GKE) con Cloud Build

1. Descripción general

En este lab, aprenderás a configurar una canalización de entrega continua para GKE con Cloud Build. En este lab, se destaca cómo activar trabajos de Cloud Build para diferentes eventos de Git, así como un patrón simple para lanzamientos Canary automatizados en GKE.

Completarás los siguientes pasos:

  • Crea la aplicación de GKE
  • Automatiza las implementaciones para ramas de git
  • Automatiza las implementaciones para la rama principal de Git
  • Automatiza las implementaciones para etiquetas git

2. Antes de comenzar

Para esta guía de referencia, necesitas un proyecto de Google Cloud. Puedes crear uno nuevo o seleccionar uno que ya hayas creado:

  1. Selecciona o crea un proyecto de Google Cloud.

IR A LA PÁGINA DEL SELECTOR DE PROYECTOS

  1. Habilita la facturación para tu proyecto.

HABILITAR FACTURACIÓN

3. Prepara tu entorno

  1. Crea variables de entorno para usarlas en este instructivo:
    export PROJECT_ID=$(gcloud config get-value project)
    export PROJECT_NUMBER=$(gcloud projects describe $PROJECT_ID --format='value(projectNumber)')
    
    export ZONE=us-central1-b
    export CLUSTER=gke-progression-cluster
    export APP_NAME=myapp
    
  2. Habilita las siguientes APIs:
    • Resource Manager
    • GKE
    • Cloud Source Repositories
    • Cloud Build
    • Container Registry
    gcloud services enable \
        cloudresourcemanager.googleapis.com \
        container.googleapis.com \
        sourcerepo.googleapis.com \
        cloudbuild.googleapis.com \
        containerregistry.googleapis.com \
        --async
    
  3. Clona la fuente de muestra y cambia al directorio del lab:
    git clone https://github.com/GoogleCloudPlatform/software-delivery-workshop.git gke-progression
    
    cd gke-progression/labs/gke-progression
    rm -rf ../../.git
    
  4. Reemplaza los valores de marcador de posición en el repositorio de muestra por tu PROJECT_ID. En este paso, crearás instancias de los distintos archivos de configuración únicos para tu entorno actual. Para revisar un ejemplo de las plantillas que se están actualizando, ejecuta el siguiente comando.
    cat k8s/deployments/dev/frontend-dev.yaml.tmpl
    
    Realiza la sustitución de variables mediante la ejecución del comando de seguimiento.
    for template in $(find . -name '*.tmpl'); do envsubst '${PROJECT_ID} ${ZONE} ${CLUSTER} ${APP_NAME}' < ${template} > ${template%.*}; done
    
    Para revisar un ejemplo del archivo después de la sustitución, ejecuta el siguiente comando.
    cat k8s/deployments/dev/frontend-dev.yaml
    
  5. Si nunca usaste Git en Cloud Shell, configura los valores user.name y user.email que deseas usar:
    git config --global user.email "YOUR_EMAIL_ADDRESS"
    git config --global user.name "YOUR_USERNAME"
    
  6. Almacena el código del repositorio de muestra en Cloud Source Repositories:
    gcloud source repos create gke-progression
    git init
    git config credential.helper gcloud.sh
    git remote add gcp https://source.developers.google.com/p/$PROJECT_ID/r/gke-progression
    git branch -m main
    git add . && git commit -m "initial commit"
    git push gcp main
    
  7. Crea tu clúster de GKE.
    gcloud container clusters create ${CLUSTER} \
        --project=${PROJECT_ID} \
        --zone=${ZONE}
    
  8. Otorga a Cloud Build derechos para tu clúster.Cloud Build implementará la aplicación en tu clúster de GKE y necesitará derechos para hacerlo.
    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
        --member=serviceAccount:${PROJECT_NUMBER}@cloudbuild.gserviceaccount.com \
        --role=roles/container.developer
    

Su entorno está listo

4. Crea tu aplicación de GKE

En esta sección, compilarás y también implementarás la aplicación de producción inicial que usarás en este instructivo.

  1. Compila la aplicación con Cloud Build:
    gcloud builds submit --tag gcr.io/$PROJECT_ID/$APP_NAME:1.0.0 src/
    
  2. Implementa manualmente en entornos de versiones canary y de producción:Crea las implementaciones y los servicios de producción y de versiones canary con los comandos de kubectl apply.
    kubectl create ns production
    kubectl apply -f k8s/deployments/prod -n production
    kubectl apply -f k8s/deployments/canary -n production
    kubectl apply -f k8s/services -n production
    
    El servicio implementado aquí enrutará el tráfico a las implementaciones de producción y de versiones canary.
  3. Revisa la cantidad de Pods en ejecución. Confirma que tienes cuatro Pods en ejecución para el frontend, incluidos tres para el tráfico de producción y uno para los lanzamientos Canary. Esto significa que los cambios en el lanzamiento Canary solo afectarán a 1 de cada 4 usuarios (el 25%).
    kubectl get pods -n production -l app=$APP_NAME -l role=frontend
    
  4. Recupera la dirección IP externa para los servicios de producción.
    kubectl get service $APP_NAME -n production
    
    Una vez que el balanceador de cargas muestre la dirección IP, continúa con el siguiente paso.
  5. Almacena la IP externa para usarla más tarde.
    export PRODUCTION_IP=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].ip}"  --namespace=production services $APP_NAME)
    
  6. Revisa la aplicación. Verifica el resultado de la versión del servicio. Debería decir Hello World v1.0
    curl http://$PRODUCTION_IP
    

¡Felicitaciones! Implementaste la app de ejemplo. A continuación, configurarás un activador para implementar continuamente los cambios.

5. Automatiza implementaciones para ramas de git

En esta sección, configurarás un activador que ejecutará un trabajo de Cloudbuild cuando se confirme cualquier rama que no sea main. El archivo de Cloud Build que se use aquí creará automáticamente un espacio de nombres y una implementación para cualquier rama existente o nueva, lo que permitirá a los desarrolladores obtener una vista previa de su código antes de la integración con la rama principal.

  1. Configura el activador:El componente clave de este activador es el uso del parámetro branchName para hacer coincidir main y el parámetro invertRegex, que se establece como verdadero y altera el patrón branchName para que coincida con cualquier elemento que no sea main. Como referencia, puedes encontrar las siguientes líneas en build/branch-trigger.json.
      "branchName": "main",
      "invertRegex": true
    
    Además, las últimas líneas del archivo de Cloud Build que se usan con este activador crean un espacio de nombres con el nombre de la rama que activó el trabajo y, luego, implementa la aplicación y el servicio dentro del espacio de nombres nuevo. Como referencia, puedes encontrar las siguientes líneas en build/branch-cloudbuild.yaml
      kubectl get ns ${BRANCH_NAME} || kubectl create ns ${BRANCH_NAME}
      kubectl apply --namespace ${BRANCH_NAME} --recursive -f k8s/deployments/dev
      kubectl apply --namespace ${BRANCH_NAME} --recursive -f k8s/services
    
    Ahora que conoces los mecanismos en uso, crea el activador con el comando de gcloud que aparece a continuación.
    gcloud beta builds triggers create cloud-source-repositories \
      --trigger-config build/branch-trigger.json
    
  2. Para revisar el activador, ve a la página Activadores de Cloud Build en la consola.Ir a Activadores
  3. Crea una rama nueva:
    git checkout -b new-feature-1
    
  4. Modifica el código para indicar v1.1Edita src/app.py y cambia la respuesta de 1.0 a 1.1.
    @app.route('/')
    def hello_world():
        return 'Hello World v1.1'
    
  5. Confirma el cambio y envíalo al repositorio remoto:
    git add . && git commit -m "updated" && git push gcp new-feature-1
    
  6. Para revisar la compilación en curso, ve a la página Historial de Cloud Build en la consola. Ve a Compilaciones Una vez que se complete la compilación, continúa con el siguiente paso.
  7. Recupera la dirección IP externa para el servicio de rama recién implementado.
    kubectl get service $APP_NAME -n new-feature-1
    
    Una vez que el balanceador de cargas muestre la dirección IP, continúa con el siguiente paso.
  8. Almacena la IP externa para usarla más tarde.
    export BRANCH_IP=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].ip}"  --namespace=new-feature-1 services $APP_NAME)
    
  9. Revisa el resultado de la versión del servicio applicationCheck. Debería decir Hello World v1.0
    curl http://$BRANCH_IP
    

6. Automatiza las implementaciones para la rama principal de Git

Antes de lanzar el código a producción, es común lanzar el código a un pequeño subconjunto de tráfico en vivo antes de migrar todo el tráfico a la nueva base de código.

En esta sección, implementarás un activador que se activa cuando se confirma el código en la rama principal. El activador implementa la implementación de versiones canary, que recibe el 25% de todo el tráfico activo en la revisión nueva.

  1. Configura el activador de la rama principal:
    gcloud beta builds triggers create cloud-source-repositories \
      --trigger-config build/main-trigger.json
    
  2. Para revisar el activador nuevo, ve a la página Activadores de Cloud Build en la consola.Ir a Activadores
  3. Combina la rama con la línea principal y envíala al repositorio remoto:
    git checkout main
    git merge new-feature-1
    git push gcp main
    
  4. Para revisar la compilación en curso, ve a la página Historial de Cloud Build en la consola. Ve a Compilaciones Una vez que se complete la compilación, continúa con el siguiente paso.
  5. Revisa varias respuestas del servidorEjecuta el siguiente comando y observa que aproximadamente el 25% de las respuestas muestran la nueva respuesta de Hello World v1.1
    while true; do curl -w "\n" http://$PRODUCTION_IP; sleep 1;  done
    
    Cuando quieras continuar, presiona Ctrl+c para salir del bucle.

7. Automatiza implementaciones para etiquetas de Git

Una vez que la implementación de versiones canary se valida con un pequeño subconjunto de tráfico, libera la implementación en el resto del tráfico en vivo.

En esta sección, configurarás un activador que se activa cuando creas una etiqueta en el repositorio. El activador etiqueta la imagen con la etiqueta adecuada y, luego, implementa las actualizaciones para la producción y se asegura de que el 100% del tráfico acceda a la imagen etiquetada.

  1. Configura el activador de etiquetas:
    gcloud beta builds triggers create cloud-source-repositories \
      --trigger-config build/tag-trigger.json
    
  2. Para revisar el activador nuevo, ve a la página Activadores de Cloud Build en la consola.Ir a Activadores
  3. Crea una etiqueta nueva y envíala al repositorio remoto:
    git tag 1.1
    git push gcp 1.1
    
  4. Para revisar la compilación en curso, ve a la página Historial de Cloud Build en la consola.Ir a Compilaciones
  5. Revisa varias respuestas del servidor. Ejecuta el siguiente comando y observa que el 100% de las respuestas muestran la nueva respuesta de Hello World v1.1. Esto puede tardar un momento, ya que se implementan los nuevos Pods y se verifica su estado en GKE.
    while true; do curl -w "\n" http://$PRODUCTION_IP; sleep 1;  done
    
    Cuando quieras continuar, presiona Ctrl+c para salir del bucle. ¡Felicitaciones! Creaste activadores de CI/CD en Cloud Build para ramas y etiquetas a fin de implementar tus apps en GKE.

8. Limpieza

Borra el proyecto

  1. En la consola de Cloud, ve a la página Administrar recursos.
  2. En la lista de proyectos, elige el proyecto que deseas borrar y haz clic en Borrar.
  3. En el diálogo, escribe el ID del proyecto y, luego, haz clic en Cerrar para borrarlo.