Estima los costos de GKE al principio del ciclo de desarrollo con GitLab


En este instructivo se muestra la práctica recomendada para cambiar la visibilidad de costos de Google Kubernetes Engine (GKE) a tu equipo de desarrollo mediante GitLab. Crear conocimiento de los costos al comienzo del proceso de desarrollo te ayuda a evitar sorpresas en tu factura de Google Cloud. Trasladar una tarea o información a una parte anterior de un proceso se conoce como desplazamiento a la izquierda.

Este instructivo está dirigido a desarrolladores, operadores y profesionales de FinOps que deseen optimizar los costos de los clústeres de GKE y que usen GitLab en producción. En cambio, si usas GitHub, consulta Calcula tus costos de GKE al principio del ciclo de desarrollo mediante GitHub.

En este instructivo, suponemos que estás familiarizado con las siguientes tecnologías:

Descripción general

Muchos equipos que adoptan la nube pública no están acostumbrados al estilo de facturación prepago. Por lo general, no comprenden por completo el entorno en el que se ejecutan las apps, en este caso, GKE. El modelo operativo de FinOps fomenta la cultura de responsabilidad financiera. Una práctica recomendada de FinOps es proporcionar a los equipos información en tiempo real sobre sus gastos para que los problemas de costos se puedan abordar cuando se presenten.

En este documento, se muestra cómo ir un paso más allá mediante la estimación de costos antes de que se convierta en un gasto en tu factura. Como se destaca en el sitio web de GitLab, “La revisión de código es una práctica esencial en todos los proyectos exitosos, y darle la aprobación cuando una solicitud de combinación esté en buen estado es una parte importante del “proceso de revisión”. El mejor momento para estimar los costos es al comienzo del proceso durante el desarrollo y en el momento de la revisión de código. De esta manera, los profesionales pueden comprender y analizar alternativas para el costo de las nuevas funciones y correcciones de errores antes de que se conviertan en un problema. En el siguiente diagrama, se resume esta práctica.

Práctica recomendada para estimar el costo con anticipación.

Como se muestra en el diagrama, los desarrolladores pueden estimar los costos de GKE en su entorno local, lo ideal sería en el tiempo de compilación. Esta estimación les brinda una buena comprensión del costo de la carga de trabajo de producción mensual. Cuando la función o la corrección de errores está completa, se puede proponer una solicitud de combinación que activa una canalización de CI/CD de GitLab. para comprobar la diferencia entre el costo anterior y el nuevo. Si hay aumentos superiores a un límite predefinido, la canalización solicita de forma automática una revisión de código nueva. Esta práctica ayuda a los desarrolladores a conocer más su capacidad de carga de trabajo y solucionar de forma proactiva los problemas de la aplicación en lugar de agregar más recursos cada vez que se encuentra una inestabilidad en producción.

Objetivos

  • Compilar y enviar la imagen del estimador de costos de Kubernetes
  • Crear un proyecto nuevo de GitLab
  • Configurar el ejecutor de GitLab para que se ejecute en un clúster de GKE
  • Enviar el código de ejemplo a tu repositorio de GitHub.
  • Cambiar el código y propón una solicitud de extracción para ver la estimación de costos en acción.

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

  1. En la consola de Google Cloud, ve a la página del selector de proyectos.

    Ir al selector de proyectos

  2. Selecciona o crea un proyecto de Google Cloud.

  3. Comprueba que la facturación esté habilitada en tu proyecto.

    Descubre cómo puedes habilitar la facturación

  4. En la consola de Google Cloud, activa Cloud Shell.

    Activar Cloud Shell

    En la parte inferior de la consola de Google Cloud, se inicia una sesión de Cloud Shell en la que se muestra una ventana de línea de comandos. Cloud Shell es un entorno de shell con Google Cloud CLI ya instalada y con valores ya establecidos para el proyecto actual. La sesión puede tardar unos segundos en inicializarse.

Prepara tu entorno

  1. En Cloud Shell, clona el repositorio gke-shift-left-cost de GitHub.

    git clone https://github.com/GoogleCloudPlatform/gke-shift-left-cost
    cd gke-shift-left-cost
    

    El código de este repositorio se organiza en las siguientes carpetas:

    • Raíz: contiene un archivo Dockerfile que se usa para compilar la imagen del estimador de costos y el archivo main.go que implementa la lógica de la línea de comandos del estimador de costos.
    • api/: contiene la API de Go para manipular los objetos de Kubernetes y realizar la estimación de costos.
    • samples/: contiene ejemplos de manifiestos de Kubernetes para que puedas experimentar con el proceso antes de implementarlo en tu organización.
  2. Configura el ID del proyecto de Cloud, la cuenta de usuario de GitLab y la dirección de correo electrónico:

    export GCP_PROJECT_ID=YOUR_PROJECT_ID
    export GITLAB_USER=YOUR_GITLAB_USER
    export GITLAB_EMAIL=YOUR_GITLAB_EMAIL_ADDRESS
    
    gcloud config set project $GCP_PROJECT_ID
    
    gcloud services enable cloudbilling.googleapis.com \
        compute.googleapis.com \
        container.googleapis.com \
        iamcredentials.googleapis.com \
        artifactregistry.googleapis.com
    
    gcloud config set compute/region us-central1
    gcloud config set compute/zone us-central1-f
    

    Reemplaza lo siguiente:

  • YOUR_PROJECT_ID : Es el ID del proyecto de Cloud para el proyecto que usas en este instructivo.
  • YOUR_GITLAB_USER : Es la cuenta de usuario que usas para acceder a tu cuenta de GitLab.
  • YOUR_GITLAB_EMAIL_ADDRESS: Es el correo electrónico que usas en tu cuenta de GitHub.

De forma opcional, puedes usar una región y una zona diferentes para este instructivo.

Compila y envía la imagen del estimador de costos de Kubernetes

La herramienta de estimación de costos de Kubernetes que se incluye en este instructivo es solo un ejemplo de lo que se puede hacer. Ofrece la capacidad de estimar el costo de los objetos de Kubernetes de DaemonSet, Deployment, StatefulSet, ReplicaSet, HorizontalPodAutoScaler y PersistentVolumeClaim. También puedes implementar tu propia herramienta de estimación de costos o proponer solicitudes de extracción con las mejoras que desees.

  1. En Cloud Shell, permite que application-default use tus credenciales:

    gcloud auth application-default login
    
  2. Compila el objeto binario del estimador de costos de Kubernetes:

    mkdir ./bin
    go test ./api
    go build -v -o ./bin/k8s-cost-estimator .
    
  3. Prueba el objeto binario mediante la ejecución de la estimación de costos en una carpeta de muestra:

    ./bin/k8s-cost-estimator \
        --k8s ./samples/k8s-cost-estimator-local/app-v1  \
        --config ./samples/k8s-cost-estimator-local/example-conf.yaml \
        --v trace
    

    En el resultado, verás una tabla de Markdown que detalla los costos mensuales estimados de la carpeta ./samples/k8s-cost-estimator-local/app-v1/. Para comprender mejor el costo de producción mensual de sus aplicaciones, los desarrolladores pueden ejecutar este paso antes de enviar el código al repositorio remoto.

    INFO[0000] Starting cost estimation (version v0.0.1)...
    ...
    
    |         KIND          | MIN REQUESTED (USD) | MIN REQ + HPA CPU BUFFER (USD) | MAX REQUESTED (USD) | MIN LIMITED (USD) | MAX LIMITED (USD) |
    |-----------------------|---------------------|--------------------------------|---------------------|-------------------|-------------------|
    | Deployment            |             $133.31 |                        $198.71 |             $266.54 |           $312.83 |           $579.29 |
    | StatefulSet           |              $36.33 |                         $36.33 |              $36.33 |            $72.67 |            $72.67 |
    | DaemonSet             |              $29.68 |                         $29.68 |              $29.68 |            $53.19 |            $53.19 |
    | PersistentVolumeClaim |              $28.88 |                         $28.88 |              $28.88 |            $33.68 |            $33.68 |
    | **TOTAL**             |         **$228.20** |                    **$293.60** |         **$361.43** |       **$472.38** |       **$738.83** |
    
    INFO[0002] Finished cost estimation!
    
  4. Compila la imagen de contenedor del estimador de costos de Kubernetes:

    docker build . -t \
    us-central1-docker.pkg.dev/$GCP_PROJECT_ID/docker-repo/k8s-cost-estimator:v0.0.1
    
  5. Crea el repositorio de Docker de Artifact Registry para almacenar la imagen:

    gcloud artifacts repositories create docker-repo \
            --repository-format=docker \
            --location=us-central1 \
            --description="Docker repository"
    
  6. Registra gcloud como auxiliar de credenciales para el archivo de configuración de Docker.

    gcloud auth configure-docker us-central1-docker.pkg.dev
    

    Si se te solicita, confirma la actualización del archivo.

  7. Envía la imagen a Artifact Registry:

    docker push us-central1-docker.pkg.dev/$GCP_PROJECT_ID/docker-repo/k8s-cost-estimator:v0.0.1
    

Crea un proyecto de GitLab nuevo

  1. En Cloud Shell, cambia el directorio al ejemplo de GitLab:

    cd samples/k8s-cost-estimator-gitlab
    
  2. En la página Tokens de acceso personal de GitLab, crea un token de acceso:

    Navega a la página Personal access tokens de GitHub.

    1. En el campo Nombre, ingresa el nombre del token que crearás.
    2. En el campo Alcance, selecciona API y, luego, haz clic en Crear token de acceso personal.
    3. Copia el valor de Tu nuevo token de acceso personal.
  3. En Cloud Shell, guarda el token de acceso personal en una variable:

    GITLAB_API_TOKEN=YOUR_NEW_PERSONAL_ACCESS_TOKEN
    

    Reemplaza lo siguiente:

    • YOUR_NEW_PERSONAL_ACCESS_TOKEN: Es el token de acceso personal de GitHub que creaste.
  4. Crea un proyecto de GitLab nuevo:

    GITLAB_PROJECT_OUTPUT=$(curl -X POST -H "content-type:application/json" -H "PRIVATE-TOKEN:$GITLAB_API_TOKEN" -d '{"name":"k8s-cost-estimator-gitlab","visibility":"public"}'        https://gitlab.com/api/v4/projects)
    GITLAB_PROJECT_ID=$(echo $GITLAB_PROJECT_OUTPUT | jq ".id")
    GITLAB_FINOPS_REVIEWER_ID=$(echo $GITLAB_PROJECT_OUTPUT | jq ".owner.id")
    
  5. Configura las variables que se usarán en la herramienta de estimador de costos cuando se cree una solicitud de combinación:

    curl -X POST -H "content-type:application/json" -H "PRIVATE-TOKEN:$GITLAB_API_TOKEN" -d "{\"key\": \"GITLAB_API_TOKEN\",\"value\": \"$GITLAB_API_TOKEN\", \"masked\":\"true\"}" https://gitlab.com/api/v4/projects/$GITLAB_PROJECT_ID/variables
    
    curl -X POST -H "content-type:application/json" -H "PRIVATE-TOKEN:$GITLAB_API_TOKEN" -d "{\"key\": \"GITLAB_FINOPS_REVIEWER_ID\",\"value\": \"$GITLAB_FINOPS_REVIEWER_ID\"}" https://gitlab.com/api/v4/projects/$GITLAB_PROJECT_ID/variables
    
    curl -X POST -H "content-type:application/json" -H "PRIVATE-TOKEN:$GITLAB_API_TOKEN" -d "{\"key\": \"GITLAB_FINOPS_COST_USD_THRESHOLD\",\"value\": \"10\"}" https://gitlab.com/api/v4/projects/$GITLAB_PROJECT_ID/variables
    
  6. Verifica que se hayan creado el proyecto y las variables:

    curl -s --header "PRIVATE-TOKEN:$GITLAB_API_TOKEN" \
    https://gitlab.com/api/v4/projects/$GITLAB_PROJECT_ID/variables | jq
    

    El resultado se parece al siguiente:

    [
      {
        "variable_type": "env_var",
        "key": "GITLAB_API_TOKEN",
        "value": "Ex...n1",
        "protected": false,
        "masked": true,
        "environment_scope": "*"
      },
      {
        "variable_type": "env_var",
        "key": "GITLAB_FINOPS_REVIEWER_ID",
        "value": "88..87",
        "protected": false,
        "masked": false,
        "environment_scope": "*"
      },
      {
        "variable_type": "env_var",
        "key": "GITLAB_FINOPS_COST_USD_THRESHOLD",
        "value": "10",
        "protected": false,
        "masked": false,
        "environment_scope": "*"
      }
    ]
    

    El archivo ./samples/k8s-cost-estimator-gitlab/templates/.gitlab-ci.yml.tpl usa las variables configuradas en el proyecto de GitLab para actualizar las solicitudes de combinación y son las siguientes:

    • GITLAB_API_TOKEN: Tu token de acceso personal de GitLab.
    • GITLAB_FINOPS_REVIEWER_ID: El revisor de código requerido cada vez que el costo aumenta por encima de un límite determinado. Para simplificar, en este instructivo se establece tu propio ID de usuario como revisor. Sin embargo, en un entorno de producción, recomendamos que configures un equipo en lugar de una persona individual.
    • GITLAB_FINOPS_COST_USD_THRESHOLD: el límite en USD, en este caso, $10. Cuando la diferencia entre los costos antiguos y los nuevos supera este umbral, se aplica una aprobación extraordinaria. También puedes establecer umbrales para otros valores. Para explorar esta función, puedes agregar el parámetro --output cuando ejecutes el comando ./bin/k8s-cost-estimator en Compila y envía la imagen del estimador de costos de Kubernetes. Este parámetro genera un archivo con una extensión .diff que te permite ver las opciones disponibles.

Configura el ejecutor de GitLab para que se ejecute en un clúster de GKE

En esta sección, instalarás el ejecutor de GitLab en tu propio clúster de GKE con Workload Identity para permitir que la herramienta de estimador de Kubernetes consulte el catálogo de precios de Google Cloud. El estimador usa precios brutos y no tiene en cuenta las VM interrumpibles ni los descuentos.

  1. En Cloud Shell, crea un clúster de GKE:

    gcloud beta container clusters create gitlab-runners \
        --enable-ip-alias \
        --release-channel=stable \
        --workload-pool=$GCP_PROJECT_ID.svc.id.goog \
        --enable-autoprovisioning --min-cpu 1 --min-memory 1 --max-cpu 4 --max-memory 16 \
        --autoscaling-profile=optimize-utilization \
        --preemptible
    
  2. Obtén el token de registro del ejecutor de GitLab del proyecto que creaste:

    export GITLAB_RUNNER_TOKEN=$(curl -s --header "PRIVATE-TOKEN:$GITLAB_API_TOKEN" https://gitlab.com/api/v4/projects/$GITLAB_PROJECT_ID | jq -r '.runners_token')
    [ -z "$GITLAB_RUNNER_TOKEN" ] && echo "GITLAB_RUNNER_TOKEN is not exported" || echo "GITLAB_RUNNER_TOKEN is $GITLAB_RUNNER_TOKEN"
    
  3. Instala el ejecutor de GitLab en tu clúster de GKE:

    kubectl create namespace gitlab
    
    helm repo add gitlab https://charts.gitlab.io
    
    sed "s/GCP_PROJECT_ID/$GCP_PROJECT_ID/g; s/GITLAB_RUNNER_TOKEN/$GITLAB_RUNNER_TOKEN/g" templates/gitlab-runner-values.yaml.tpl > gitlab-runner-values.yaml
    
    helm install --namespace gitlab --version 0.24.0 gitlab-runner -f gitlab-runner-values.yaml gitlab/gitlab-runner
    
    kubectl -n gitlab wait --for=condition=available deployment gitlab-runner --timeout=5m
    
    gcloud iam service-accounts create gitlab-runner --display-name=gitlab-runner
    gcloud iam service-accounts add-iam-policy-binding \
        --role roles/iam.workloadIdentityUser \
        --member "serviceAccount:$GCP_PROJECT_ID.svc.id.goog[gitlab/gitlab-runner]" \
        gitlab-runner@$GCP_PROJECT_ID.iam.gserviceaccount.com
    
  4. Inhabilita los ejecutores compartidos en tu proyecto de GitLab:

    curl -s --header "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" -X PUT "https://gitlab.com/api/v4/projects/$GITLAB_PROJECT_ID" --form "shared_runners_enabled=false"
    
  5. Verifica que el ejecutor que implementaste esté habilitado en tu proyecto de GitLab:

    curl -s --header "PRIVATE-TOKEN: ${GITLAB_API_TOKEN}" "https://gitlab.com/api/v4/projects/$GITLAB_PROJECT_ID/runners?status=active" | jq '.[] | select(.is_shared==false)'
    

    El resultado se parece al siguiente:

    {
        "id": 49345561,
        "description": "gitlab-runner-gitlab-runner-788459d488-jlscn",
        "ip_address": "35.178.223.199",
        "active": true,
        "is_shared": false,
        "name": "gitlab-runner",
        "online": true,
        "status": "online"
    }
    

Envía el código de ejemplo a tu repositorio de GitHub

  1. Crea un par de claves SSH para enviar el código de muestra a tu repositorio de GitLab:

    mkdir -p ssh && cd ssh
    ssh-keygen -t rsa -b 4096 -N '' -f gitlab-key
    eval `ssh-agent` && ssh-add $(pwd)/gitlab-key
    curl -s --request POST --header "PRIVATE-TOKEN:$GITLAB_API_TOKEN" https://gitlab.com/api/v4/user/keys --form "title=k8s-cost-estimator-key" --form "key=$(cat gitlab-key.pub)"
    cd ..
    
  2. Envía el contenido a tu repositorio de GitLab nuevo.

    sed "s/GCP_PROJECT_ID/$GCP_PROJECT_ID/g; s/GITLAB_USER/$GITLAB_USER/g; s/GITLAB_EMAIL/$GITLAB_EMAIL/g;" templates/.gitlab-ci.yml.tpl > .gitlab-ci.yml
    
    GITLAB_SSH_URL_REPO=$(curl -s --header "PRIVATE-TOKEN:$GITLAB_API_TOKEN" https://gitlab.com/api/v4/users/$GITLAB_FINOPS_REVIEWER_ID/projects | jq '.[] | select(.name=="k8s-cost-estimator-gitlab")' | jq -r '.ssh_url_to_repo')
    [ -z "$GITLAB_SSH_URL_REPO" ] && echo "GITLAB_PROJECT_SSH_URL is not exported" || echo "GITLAB_PROJECT_SSH_URL is $GITLAB_SSH_URL_REPO"
    
    git init
    git remote add origin $GITLAB_SSH_URL_REPO
    git add -A .
    git commit -m "Initial commit"
    git checkout -b main
    git push -u origin main
    

Cambia el código y propone una solicitud de combinación para ver la estimación de costos en acción

  1. En Cloud Shell, obtén la URL del entorno de desarrollo integrado (IDE) de GitLab:

    echo "https://gitlab.com/-/ide/project/$GITLAB_USER/k8s-cost-estimator-gitlab/tree/main/-/wordpress/wordpress_hpa.yaml"
    
  2. Ctrl + clic (Cmd + clic en macOS) en la URL de salida para navegar al IDE web de GitLab.

  3. En el IDE web de GitLab, edita el archivo ./wordpress/wordpress_hpa.yaml de la siguiente manera:

    1. Cambia el valor minReplicas de 2 a 5.
    2. Haz clic en Confirmar.
  4. Como se muestra en la siguiente captura de pantalla, selecciona Create a new branch y Start a new merge request. Luego, haz clic en Commit.

    Inicia una solicitud de combinación.

  5. En la pantalla Nueva solicitud de combinación, haz clic en Crear solicitud de combinación en la parte inferior de la página.

    Además de crear una nueva solicitud de combinación, este paso activa una canalización de estimación de costos en función del archivo .gitlab-ci.yml. Esta canalización usa la imagen de contenedor que creaste en una sección anterior. Esta canalización también determina cuándo se requiere una aprobación de FinOps. Para simplificar, .gitlab-ci.yml agrega aprobaciones para cada base de solicitud de combinación, pero puedes definir y reutilizar reglas de aprobación definidas a nivel de proyecto de GitLab.

  6. Espera un minuto para que finalice la canalización. Cuando termine, se agregará un comentario con los detalles de los costos a la solicitud de combinación. Debido a que el aumento del costo del código que propones supera el límite de $10, también se solicita un revisor de FinOps.

    El resultado se parece al siguiente:

    Comenta con el detalle del costo en la solicitud de combinación.

    En este instructivo, se usa la configuración predeterminada para las aprobaciones de solicitudes de combinación. Es posible seleccionar diferentes parámetros de configuración para tus solicitudes de combinación en Gitlab. Por ejemplo, para evitar que el autor apruebe solicitudes de combinación, ve a Configuración > General > Aprobaciones de solicitud de combinación (MR) > Configuración de aprobación.

Limpia

Puedes borrar tu proyecto para evitar que se apliquen cargos a tu cuenta de Google Cloud por los recursos usados en este instructivo.

Borra el proyecto

  1. En la consola de Google Cloud, ve a la página Administrar recursos.

    Ir a Administrar recursos

  2. En la lista de proyectos, elige el proyecto que quieres borrar y haz clic en Borrar.
  3. En el diálogo, escribe el ID del proyecto y, luego, haz clic en Cerrar para borrar el proyecto.

Borra el proyecto de GitLab

Si no deseas conservar tu proyecto de GitLab, haz lo siguiente:

  1. En Cloud Shell, borra tu proyecto de GitLab:

     curl -X DELETE -H "content-type:application/json" -H "PRIVATE-TOKEN:$GITLAB_API_TOKEN" https://gitlab.com/api/v4/projects/$GITLAB_PROJECT_ID
    

    El resultado se parece al siguiente: {"message":"202 Accepted"}

    Si pierdes la conexión con Cloud Shell, debes volver a configurar las siguientes variables:

    • GITLAB_API_TOKEN
    • GITLAB_PROJECT_ID

¿Qué sigue?