Stima i costi di GKE nelle prime fasi del ciclo di sviluppo utilizzando GitLab


Questo tutorial illustra la best practice per spostare la visibilità dei costi di Google Kubernetes Engine (GKE) al team di sviluppo utilizzando GitHub. Essere consapevoli dei costi nelle prime fasi del processo di sviluppo ti aiuta a evitare sorprese nella fattura di Google Cloud. Lo spostamento di un'attività o di informazioni in una parte precedente di un processo a volte è definito spostamento a sinistra.

Questo tutorial è destinato a sviluppatori, operatori e professionisti FinOps che vogliono ottimizzare i costi nei cluster GKE e che utilizzano GitLab in produzione. Se utilizzi GitHub, consulta l'articolo Stimare i costi di GKE nelle prime fasi del ciclo di sviluppo utilizzando GitHub.

Il tutorial presuppone la conoscenza delle seguenti tecnologie:

Panoramica

Molti team che adottano il cloud pubblico non sono abituati allo stile di fatturazione con pagamento a consumo. Spesso, non comprendono appieno l'ambiente in cui vengono eseguite le loro app, in questo caso GKE. Il modello operativo FinOps promuove la cultura della responsabilità finanziaria. Una best practice di FinOps è fornire ai team informazioni in tempo reale sulle spese, in modo da risolvere eventuali problemi relativi ai costi.

Questo documento mostra come fare un passo in più facendo una stima dei costi prima che diventino spese in fattura. Il momento migliore per stimare i costi è nelle fasi iniziali del processo, sia in fase di sviluppo che di revisione del codice. In questo modo, i professionisti possono comprendere e discutere le alternative per l'impatto sui costi delle nuove funzionalità e delle correzioni di bug prima che diventi un problema. Il seguente diagramma riassume questa pratica.

Best practice per una stima anticipata dei costi.

Come mostra il diagramma, gli sviluppatori possono stimare i costi di GKE nel loro ambiente locale, idealmente in fase di creazione. Questa stima consente loro di avere un'idea chiara del costo mensile del carico di lavoro di produzione. Quando la funzionalità o la correzione del bug è completa, il cliente può proporre una richiesta di unione che attivi una pipeline CI/CD di GitHub per verificare la differenza tra il costo precedente e quello nuovo. In caso di aumenti superiori a una soglia predefinita, la pipeline richiede automaticamente una nuova revisione del codice. Questa pratica aiuta gli sviluppatori a diventare più consapevoli della capacità dei loro carichi di lavoro e a risolvere in modo proattivo i problemi delle applicazioni anziché aggiungere altre risorse ogni volta che si rileva instabilità in produzione.

Obiettivi

  • Crea ed esegui il push di un'immagine dello strumento per la stima dei costi di Kubernetes.
  • Creare un nuovo progetto GitLab.
  • Configura il runner GitLab in modo che venga eseguito su un cluster GKE.
  • Esegui il push del codice di esempio nel tuo repository GitLab.
  • Modifica il codice e proponi una richiesta di unione per vedere la stima dei costi in azione.

Costi

In questo documento vengono utilizzati i seguenti componenti fatturabili di Google Cloud:

Per generare una stima dei costi in base all'utilizzo previsto, utilizza il Calcolatore prezzi. I nuovi utenti di Google Cloud possono essere idonei a una prova senza costi aggiuntivi.

Una volta completate le attività descritte in questo documento, puoi evitare la fatturazione continua eliminando le risorse che hai creato. Per ulteriori informazioni, consulta la pagina Pulizia.

Prima di iniziare

  1. Nella console Google Cloud, vai alla pagina del selettore progetto.

    Vai al selettore progetti

  2. Seleziona o crea un progetto Google Cloud.

  3. Assicurati che la fatturazione sia attivata per il tuo progetto Google Cloud.

  4. Nella console Google Cloud, attiva Cloud Shell.

    Attiva Cloud Shell

    Nella parte inferiore della console Google Cloud viene avviata una sessione di Cloud Shell che mostra un prompt della riga di comando. Cloud Shell è un ambiente shell con Google Cloud CLI già installato e con valori già impostati per il progetto attuale. L'inizializzazione della sessione può richiedere alcuni secondi.

prepara l'ambiente

  1. In Cloud Shell, clona il repository GitHub di gke-shift-left-cost:

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

    Il codice in questo repository è strutturato nelle seguenti cartelle:

    • Root: contiene un file Dockerfile utilizzato per creare l'immagine dello strumento per la stima dei costi e il file main.go che implementa la logica a riga di comando per lo strumento per la stima dei costi.
    • api/: contiene l'API Go per manipolare gli oggetti Kubernetes e effettuare una stima dei costi.
    • samples/: contiene esempi di manifest Kubernetes per consentirti di sperimentare il processo prima di implementarlo nella tua organizzazione.
  2. Imposta l'ID progetto Google Cloud, l'account utente e l'indirizzo email GitLab:

    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
    

    Sostituisci quanto segue:

  • YOUR_PROJECT_ID : l'ID del progetto Google Cloud che stai utilizzando in questo tutorial.
  • YOUR_GITLAB_USER : l'account utente che utilizzi per accedere al tuo account GitLab.
  • YOUR_GITLAB_EMAIL_ADDRESS: l'email che utilizzi nel tuo account GitLab.

Facoltativamente, puoi utilizzare una regione e una zona diverse per questo tutorial.

Crea ed esegui il push dell'immagine dello strumento di stima dei costi di Kubernetes

Lo strumento per la stima dei costi di Kubernetes fornito in questo tutorial è un esempio di cosa si può fare. Offre la possibilità di stimare i costi per gli oggetti DaemonSet, Deployment, StatefulSet, ReplicaSet, HorizontalPodAutoScaler e PersistentVolumeClaim Kubernetes. Puoi anche implementare il tuo strumento di stima dei costi o proporre richieste pull con i miglioramenti che preferisci.

  1. In Cloud Shell, consenti a application-default di utilizzare le tue credenziali:

    gcloud auth application-default login
    
  2. Crea il programma binario dello strumento per la stima dei costi di Kubernetes:

    mkdir ./bin
    go test ./api
    go build -v -o ./bin/k8s-cost-estimator .
    
  3. Testa il programma binario eseguendo una stima dei costi in una cartella di esempio:

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

    Nell'output, vedi una tabella Markdown che descrive in dettaglio i costi mensili stimati per la cartella ./samples/k8s-cost-estimator-local/app-v1/. Per comprendere meglio il costo mensile di produzione delle loro applicazioni, gli sviluppatori possono eseguire questo passaggio prima di eseguire il push del codice nel repository 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. Crea l'immagine del container dello strumento per la stima dei costi di Kubernetes:

    docker build . -t \
    us-central1-docker.pkg.dev/$GCP_PROJECT_ID/docker-repo/k8s-cost-estimator:v0.0.1
    
  5. Crea il repository Docker Artifact Registry per archiviare l'immagine:

    gcloud artifacts repositories create docker-repo \
            --repository-format=docker \
            --location=us-central1 \
            --description="Docker repository"
    
  6. Registra gcloud come helper delle credenziali per il file di configurazione Docker.

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

    Se richiesto, conferma l'aggiornamento del file.

  7. Esegui il push dell'immagine in Artifact Registry:

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

Crea un nuovo progetto GitLab

  1. In Cloud Shell, cambia la directory sull'esempio GitLab:

    cd samples/k8s-cost-estimator-gitlab
    
  2. Nella pagina Token di accesso personale di GitLab, crea un token di accesso:

    Vai alla pagina dei token di accesso personale di GitLab

    1. Nel campo Nome, inserisci il nome del token che stai creando.
    2. Nel campo Ambito, seleziona api e fai clic su Crea token di accesso personale.
    3. Copia il valore in Il tuo nuovo token di accesso personale.
  3. In Cloud Shell, salva il token di accesso personale in una variabile:

    GITLAB_API_TOKEN=YOUR_NEW_PERSONAL_ACCESS_TOKEN
    

    Sostituisci YOUR_NEW_PERSONAL_ACCESS_TOKEN con il token di accesso personale GitHub che hai creato.

  4. Crea un nuovo progetto GitLab:

    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. Imposta le variabili da utilizzare per lo strumento per la stima dei costi quando viene creata una richiesta di unione:

    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 che il progetto e le variabili siano stati creati:

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

    L'output è simile al seguente:

    [
        {
        "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": "*"
        }
    ]
    

    Le variabili configurate nel progetto GitLab vengono utilizzate dal file ./samples/k8s-cost-estimator-gitlab/templates/.gitlab-ci.yml.tpl per aggiornare le richieste di unione e sono le seguenti:

    • GITLAB_API_TOKEN: il tuo token di accesso personale GitLab.
    • GITLAB_FINOPS_REVIEWER_ID: il revisore del codice richiesto ogni volta che il costo supera una determinata soglia. Per semplicità, questo tutorial imposta il tuo ID utente come revisore. Tuttavia, in un ambiente di produzione, ti consigliamo di configurare un team anziché una singola persona.
    • GITLAB_FINOPS_COST_USD_THRESHOLD: la soglia in USD, in questo caso 10 $. Quando la differenza tra i costi precedenti e quelli nuovi supera questa soglia, viene applicata un'approvazione straordinaria. Puoi anche impostare soglie per altri valori. Per esplorare questa funzionalità, puoi aggiungere il parametro --output quando esegui il comando ./bin/k8s-cost-estimator in Creazione ed esecuzione dell'immagine dello strumento per la stima dei costi di Kubernetes. Questo parametro genera un file con un'estensione .diff che consente di visualizzare le opzioni disponibili.

Configura il runner GitLab per l'esecuzione su un cluster GKE

In questa sezione installerai il runner GitLab nel tuo cluster GKE con Workload Identity per consentire allo strumento per la stima di Kubernetes di eseguire query sul Catalogo prezzi di Google Cloud. Lo strumento per la stima utilizza prezzi lordi e non tiene conto delle VM prerilasciabili o di eventuali sconti.

  1. In Cloud Shell, crea un cluster 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. Recupera il token di registrazione del runner GitLab dal progetto che hai creato:

    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. Installa il runner GitLab nel tuo cluster 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. Disabilita i runner condivisi nel tuo progetto 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 che il runner di cui hai eseguito il deployment sia abilitato nel tuo progetto 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)'
    

    L'output è simile al seguente:

    {
        "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"
    }
    

Esegui il push del codice di esempio al tuo repository GitLab

  1. Crea una coppia di chiavi SSH per eseguire il push del codice campione nel tuo repository 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. Esegui il push dei contenuti nel nuovo repository GitLab:

    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 config --global user.email $GITLAB_EMAIL
    git config --global user.name $GITLAB_USER
    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
    

Modifica il codice e proponi una richiesta di unione per vedere la stima dei costi in azione

  1. In Cloud Shell, recupera l'URL dell'ambiente di sviluppo integrato web (IDE) GitHub:

    echo "https://gitlab.com/-/ide/project/$GITLAB_USER/k8s-cost-estimator-gitlab/tree/main/-/wordpress/wordpress_hpa.yaml"
    
  2. Ctrl + fai clic (Cmd + fai clic su macOS) sull'URL di output per accedere all'IDE web GitLab.

  3. Nell'IDE web GitLab, modifica il file ./wordpress/wordpress_hpa.yaml come segue:

    1. Modifica il valore di minReplicas da 2 a 5.
    2. Fai clic su Esegui il commit.
  4. Come mostrato nello screenshot seguente, seleziona Crea un nuovo ramo e Avvia una nuova richiesta di unione, quindi fai clic su Esegui il commit.

    Avvia una richiesta di unione.

  5. Nella schermata Nuova richiesta di unione, fai clic su Crea richiesta di unione nella parte inferiore della pagina.

    Oltre a creare una nuova richiesta di unione, questo passaggio attiva una pipeline di stima dei costi basata sul file .gitlab-ci.yml. Questa pipeline utilizza l'immagine container che hai creato in una sezione precedente. Questa pipeline determina anche quando è richiesta l'approvazione di FinOps. Per semplicità, .gitlab-ci.yml aggiunge approvazioni per ogni base di richieste di unione, ma puoi definire e riutilizzare le regole di approvazione definite a livello di progetto GitLab.

  6. Attendi circa un minuto per il completamento della pipeline. Al termine, nella richiesta di unione viene aggiunto un commento con i dettagli dei costi. Poiché l'aumento del costo del codice che proponi supera la soglia di $10, viene richiesto anche un revisore di FinOps.

    L'output è simile al seguente:

    Commento con i dettagli dei costi nella richiesta di unione.

    In questo tutorial viene utilizzata la configurazione predefinita per le approvazioni delle richieste di unione. È possibile selezionare configurazioni diverse per le richieste di unione in Gitlab. Ad esempio, per impedire all'autore di approvare le richieste di unione, vai a Impostazioni > Generali > Approvazioni richieste di unione (MR) > Impostazioni di approvazione.

Esegui la pulizia

Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo tutorial, puoi eliminare il tuo progetto.

Elimina il progetto

  1. Nella console Google Cloud, vai alla pagina Gestisci risorse.

    Vai a Gestisci risorse

  2. Nell'elenco dei progetti, seleziona il progetto che vuoi eliminare, quindi fai clic su Elimina.
  3. Nella finestra di dialogo, digita l'ID del progetto e fai clic su Chiudi per eliminare il progetto.

Elimina il progetto GitLab

Se non vuoi conservare il progetto GitLab, segui questi passaggi:

  1. In Cloud Shell, elimina il tuo progetto GitLab:

     curl -X DELETE -H "content-type:application/json" -H "PRIVATE-TOKEN:$GITLAB_API_TOKEN" https://gitlab.com/api/v4/projects/$GITLAB_PROJECT_ID
    ```
    
     The output is similar to the following:
    
     ```none {:.devsite-disable-click-to-copy}
     {"message":"202 Accepted"}
    

    Se perdi la connessione con Cloud Shell, devi impostare di nuovo le seguenti variabili:

    • GITLAB_API_TOKEN
    • GITLAB_PROJECT_ID

Passaggi successivi