Implementazioni sicure con Config Sync

Questo documento mostra agli operatori di cluster e agli amministratori della piattaforma come implementare in modo sicuro le modifiche in più ambienti utilizzando Config Sync. Questo approccio può aiutarti a evitare errori che interessano tutti i tuoi ambienti contemporaneamente.

Config Sync ti consente di gestire singoli cluster, cluster multi-tenant e configurazioni Kubernetes multi-cluster utilizzando i file archiviati in un repository Git.

Le configurazioni possono rappresentare diverse cose, tra cui:

Config Sync è particolarmente adatto per eseguire il deployment di configurazioni, criteri e carichi di lavoro necessari per eseguire la piattaforma creata su Google Kubernetes Engine (GKE) Enterprise Edition, ad esempio agenti di sicurezza, agenti di monitoraggio e gestori dei certificati.

Sebbene sia possibile eseguire il deployment di applicazioni rivolte agli utenti con Config Sync, sconsigliamo di collegare il loro ciclo di vita delle release al ciclo di vita delle release dei carichi di lavoro amministrativi menzionati in precedenza. Ti consigliamo invece di utilizzare uno strumento dedicato al deployment delle applicazioni, ad esempio uno strumento di deployment continuo, in modo che i team di applicazioni possano essere responsabili della pianificazione del rilascio.

Config Sync è un prodotto potente che può gestire molti elementi, quindi hai bisogno di guardrail per evitare errori con un impatto significativo. Questo documento descrive diversi metodi per creare guardrail. La prima sezione riguarda le implementazioni graduali, mentre la seconda si concentra su test e convalide. La terza sezione mostra come monitorare i deployment.

Implementazione di implementazioni graduali con Config Sync

In un ambiente multi-cluster, una situazione comune per gli utenti di GKE Enterprise, non è consigliabile applicare una modifica di configurazione a tutti i cluster contemporaneamente. Un'implementazione graduale, cluster per cluster, è molto più sicura perché riduce l'impatto potenziale di eventuali errori.

Esistono diversi modi per implementare le implementazioni graduali con Config Sync:

  • Utilizza i commit o i tag Git per applicare manualmente le modifiche che vuoi ai cluster.
  • Utilizza i rami Git per applicare automaticamente le modifiche al momento della loro unione. Puoi utilizzare rami diversi per gruppi diversi di cluster.
  • Utilizza gli oggetti ClusterSelector e NamespaceSelector per applicare in modo selettivo le modifiche a sottogruppi di cluster o spazi dei nomi.

Tutti i metodi per l'implementazione graduale presentano vantaggi e svantaggi. La tabella seguente mostra quali di questi metodi puoi utilizzare contemporaneamente:

Compatibilità Commit o tag Git Rami Git Selettori di cluster Selettori di spazi dei nomi
Commit o tag Git Non compatibile Compatibile Compatibile
Rami Git Non compatibile Compatibile Compatibile
Selettori di cluster Compatibile Compatibile Compatibile
Selettori di spazi dei nomi Compatibile Compatibile Compatibile

La seguente struttura decisionale può aiutarti a decidere quando utilizzare uno dei metodi di implementazione graduale.

Albero decisionale per i metodi di implementazione.

Utilizzare commit o tag Git

Rispetto agli altri metodi di implementazione graduale, l'utilizzo di commit o tag Git offre il massimo controllo ed è il più sicuro. Puoi utilizzare la pagina Config Sync nella console Google Cloud per aggiornare più cluster contemporaneamente. Utilizza questo metodo se vuoi applicare le modifiche ai cluster una alla volta e controllare esattamente quando ciò accade.

In questo metodo, "blocchi" ogni cluster a una versione specifica (un commit o un tag) del tuo repository. Questo metodo è simile all'utilizzo del commit Git come tag dell'immagine del container. Implementa questo metodo specificando il commit, il tag o l'hash nel spec.git.revision campo della RootSync o della RepoSync risorsa personalizzata.

Se gestisci le risorse personalizzate RootSync o RepoSync con uno strumento come Kustomize, puoi ridurre la quantità di lavoro manuale richiesta per gli implementamenti. Con questo strumento, devi solo modificare il parametro revision in un punto e poi applicare in modo selettivo la nuova risorsa personalizzata RootSync o RepoSync ai tuoi cluster nell'ordine e con la frequenza che preferisci.

Inoltre, puoi utilizzare la console Google Cloud per aggiornare contemporaneamente il parametro revision per più cluster appartenenti allo stesso parco risorse. Tuttavia, se disponi di un sistema automatico per aggiornare le configurazioni, ti sconsigliamo di utilizzare la console Google Cloud per apportare modifiche alla configurazione.

Ad esempio, la seguente definizione RootSync configura Config Sync per utilizzare il tag 1.2.3:

apiVersion: configsync.gke.io/v1
kind: RootSync
metadata:
  name: root-sync
  namespace: config-sync-system
spec:
  sourceType: git
  sourceFormat: unstructured
  git:
    repo: git@example.com:gke/config-sync.git
    revision: 1.2.3
    auth: ssh

Se applichi questa configurazione al tuo cluster, Config Sync utilizzerà il tag 1.2.3 del repository example.com:gke/config-sync.git.

Per aggiornare un cluster, modifica il campo spec.git.revision con il nuovo valore per il cluster. In questo modo puoi definire quali cluster vengono aggiornati e quando. Se devi rollback una modifica, ripristina il valore precedente del campo spec.git.revision.

Il seguente diagramma illustra la procedura di implementazione di questo metodo. Innanzitutto, committa le modifiche al repository Config Sync, quindi aggiorna le definizioni di RootSync su tutti i cluster:

Procedura di implementazione per i commit e i tag Git.

Consigliamo di eseguire queste operazioni:

  • Utilizza gli ID commit Git anziché i tag. Grazie al funzionamento di Git, hai la garanzia che non cambieranno mai. Ad esempio, un git push --force non può modificare il commit utilizzato da Config Sync. Questo approccio è utile per scopi di controllo e per monitorare il commit che utilizzi nei log. Inoltre, a differenza dei tag, non è necessario alcun passaggio aggiuntivo per eseguire il commit degli ID.
  • Se preferisci utilizzare i tag Git anziché gli ID commit Git, puoi proteggere i tuoi tag se utilizzi una soluzione Git che supporta la protezione.
  • Se vuoi aggiornare più cluster contemporaneamente, puoi farlo nella console Google Cloud. Per aggiornare più cluster contemporaneamente, questi devono far parte dello stesso parco risorse (e dello stesso progetto).

Utilizzare i rami Git

Se vuoi che le modifiche vengano applicate ai cluster non appena vengono unite nel tuo repository Git, configura Config Sync in modo che utilizzi i branch Git anziché i commit o i tag. In questo metodo, crei più rami di lunga durata nel tuo repository Git e configuri Config Sync in cluster diversi per leggere la relativa configurazione da rami diversi.

Ad esempio, un pattern semplice ha due rami:

  • Un ramo staging per i cluster non di produzione.
  • Un ramo main per i cluster di produzione.

Per i cluster non di produzione, crea l'oggetto RootSync o RepoSync con il campo spec.git.branch impostato su staging. Per i cluster di produzione, crea l'oggetto RootSync o RepoSync con il parametro spec.git.branch impostato su main.

Ad esempio, la seguente definizione RootSync configura Config Sync per utilizzare il ramo main:

apiVersion: configsync.gke.io/v1
kind: RootSync
metadata:
  name: root-sync
  namespace: config-sync-system
spec:
  git:
    repo: git@example.com:gke/config-sync.git
    branch: main
    auth: ssh

Il seguente diagramma illustra la procedura di implementazione di questo metodo:

Procedura di implementazione per i rami Git.

Puoi adattare questo pattern a esigenze specifiche, utilizzando più di due branch o branch mappati a qualcosa di diverso dagli ambienti. Se devi eseguire il rollback di una modifica, utilizza il comando git revert per creare un nuovo commit nello stesso ramo che ripristina le modifiche del commit precedente.

Consigliamo di eseguire queste operazioni:

  • Quando hai a che fare con più cluster, utilizza almeno due branch Git per contribuire a distinguere i cluster di produzione da quelli non di produzione.
  • La maggior parte delle soluzioni Git ti consente di utilizzare la funzionalità dei rami protetti per impedire la cancellazione o le modifiche non esaminate di questi rami. Per ulteriori informazioni, consulta la documentazione di GitHub, GitLab e Bitbucket.

Utilizza gli oggetti ClusterSelector e NamespaceSelector

I rami Git sono un buon modo per eseguire l'implementazione graduale delle modifiche su più cluster che alla fine avranno tutti gli stessi criteri. Tuttavia, se vuoi implementare una modifica solo in un sottoinsieme di cluster o di spazi dei nomi, utilizza gli oggetti ClusterSelector e NamespaceSelector. Questi oggetti hanno un obiettivo simile: ti consentono di applicare oggetti solo a cluster o spazi dei nomi con etichette specifiche.

Ad esempio:

  • Utilizzando gli oggetti ClusterSelector, puoi applicare criteri diversi ai cluster, a seconda del paese in cui si trovano, per vari regimi di conformità.
  • Utilizzando gli oggetti NamespaceSelector, puoi applicare criteri diversi ai namespace utilizzati da un team interno e da un appaltatore esterno.

Gli oggetti ClusterSelector e NamespaceSelector ti consentono inoltre di implementare metodi di test e rilascio avanzati, ad esempio:

  • Release Canary dei criteri, in cui viene implementato un nuovo criterio in un piccolo insieme di cluster e spazi dei nomi per un lungo periodo di tempo per studiarne l'impatto.
  • Test A/B, in cui implementi versioni diverse dello stesso criterio in cluster diversi per studiare la differenza dell'impatto delle versioni dei criteri e poi scegliere la migliore da implementare ovunque.

Ad esempio, immagina un'organizzazione con diversi cluster di produzione. Il team della piattaforma ha già creato due categorie di cluster di produzione, chiamate canary-prod e prod, utilizzando gli oggetti Cluster e ClusterSelector (consulta Utilizzare ClusterSelectors).

Il team della piattaforma vuole implementare un criterio con Policy Controller per applicare la presenza di un'etichetta del team agli spazi dei nomi al fine di identificare a quale team appartiene ogni spazio dei nomi. Ha già implementato una versione di questo criterio in modalità dry run e ora vuole applicarlo a un numero limitato di cluster. Utilizzando gli oggetti ClusterSelector, creano due diverse risorse K8sRequiredLabels che vengono applicate a cluster diversi.

  • La risorsa K8sRequiredLabels viene applicata ai cluster di tipo prod, con un parametro enforcementAction impostato su dryrun:

    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: K8sRequiredLabels
    metadata:
      name: ns-must-have-team
      annotations:
        configmanagement.gke.io/cluster-selector: prod
    Spec:
      enforcementAction: dryrun
      match:
        kinds:
          - apiGroups: [""]
            kinds: ["Namespace"]
      parameters:
        labels:
          - key: "team"
    
  • La risorsa K8sRequiredLabels viene applicata ai cluster di tipo canary-prod, senza il parametro enforcementAction, il che significa che il criterio viene effettivamente applicato:

    apiVersion: constraints.gatekeeper.sh/v1beta1
    kind: K8sRequiredLabels
    metadata:
      name: ns-must-have-team
      annotations:
        configmanagement.gke.io/cluster-selector: canary-prod
    spec:
      match:
        kinds:
          - apiGroups: [""]
        kinds: ["Namespace"]
      parameters:
        labels:
          - key: "team"
    

L'annotazione configmanagement.gke.io/cluster-selector consente al team di applicare il criterio solo ai cluster di tipo canary-prod, impedendo che eventuali effetti collaterali indesiderati si diffondano nell'intero parco produttivo. Per ulteriori informazioni sulla funzionalità di prova simulata di Policy Controller, consulta la sezione sulla creazione dei vincoli.

Consigliamo di eseguire queste operazioni:

  • Utilizza gli oggetti ClusterSelector e NamespaceSelector se devi applicare una modifica alla configurazione solo a un sottoinsieme di cluster o spazi dei nomi indefinitamente o per un lungo periodo di tempo.
  • Se implementi una modifica utilizzando i selettori, fai molta attenzione. Se utilizzi i commit Git, qualsiasi errore interessa un solo cluster alla volta, perché l'implementazione avviene cluster per cluster. Tuttavia, se utilizzi i rami Git, qualsiasi errore può colpire tutti i cluster che li utilizzano. Se utilizzi i selettori, l'errore può interessare tutti i cluster contemporaneamente.

Implementazione di revisioni, test e convalide

Un vantaggio di Config Sync è che gestisce tutto in modo dichiarativo: risorse Kubernetes, risorse cloud e criteri. Ciò significa che i file in un sistema di gestione del controllo dei file sorgente rappresentano le risorse (file Git, nel caso di Config Sync). Questa caratteristica consente di implementare i flussi di lavoro di sviluppo che utilizzi già per il codice sorgente di un'applicazione: revisioni e test automatici.

Implementare le recensioni

Poiché Config Sync si basa su Git, puoi utilizzare la tua soluzione Git preferita per ospitare il repository Config Sync. La tua soluzione Git probabilmente dispone di una funzionalità di revisione del codice che puoi utilizzare per esaminare le modifiche apportate al repository Config Sync.

Le best practice per esaminare le modifiche al tuo repository sono le stesse di una normale revisione del codice, come segue:

A causa della sensibilità del codice di Config Sync, ti consigliamo inoltre di eseguire le seguenti configurazioni, se possibile con la tua soluzione Git:

Utilizzando queste diverse funzionalità, puoi applicare le approvazioni per ogni richiesta di modifica al codice base. Ad esempio, puoi assicurarti che ogni modifica venga approvata almeno da un membro del team della piattaforma (che gestisce il parco di cluster) e da un membro del team di sicurezza (che si occupa di definire e implementare i criteri di sicurezza).

Ti consigliamo di procedere nel seguente modo:

  • Applica le revisioni tra pari al tuo repository e proteggi i rami Git utilizzati dai tuoi cluster.

Implementare i test automatici

Una best practice comune quando si lavora su una base di codice è implementare l'integrazione continua. Ciò significa che configuri i test automatici in modo che vengano eseguiti quando viene creata o aggiornata una richiesta di modifica. I test automatici possono rilevare molti errori prima che una persona esamini la richiesta di modifica. In questo modo, il ciclo di feedback per lo sviluppatore viene stretto. Puoi implementare la stessa idea, utilizzando gli stessi strumenti, per il repository Config Sync.

Ad esempio, un buon punto di partenza è eseguire automaticamente il comando nomos vet per le nuove modifiche. Questo comando convalida la sintassi del repository Config Sync. Puoi implementare questo test utilizzando Cloud Build seguendo il tutorial sulla convalida delle configurazioni. Puoi integrare Cloud Build con le seguenti opzioni:

  • Bitbucket, utilizzando trigger di build.
  • GitHub, utilizzando l'app GitHub Google Cloud Build. Gli trigger di compilazione sono disponibili anche per GitHub, ma l'applicazione GitHub è il metodo di integrazione preferito.

Come puoi vedere nel tutorial sulla convalida delle configurazioni, il test viene eseguito utilizzando un'immagine container. Di conseguenza, puoi implementare il test in qualsiasi soluzione di integrazione continua che esegue i contenitori, non solo Cloud Build.

Per stringere ulteriormente il loop di feedback, puoi chiedere agli utenti di eseguire il comando nomos vet come hook pre-commit di Git. Un'avvertenza è che alcuni utenti potrebbero non avere accesso ai cluster Kubernetes gestiti da Config Sync e potrebbero non essere in grado di eseguire la convalida completa dalla propria workstation. Esegui il comando nomos vet --clusters "" per limitare la convalida ai controlli semantici e sintattici.

Ti consigliamo di procedere nel seguente modo:

  • Implementa i test in una pipeline di integrazione continua.
  • Esegui almeno il comando nomos vet su tutte le modifiche suggerite.

Monitoraggio delle implementazioni

Anche se implementi tutte le misure di salvaguardia descritte in questo documento, possono verificarsi comunque errori. Di seguito sono riportati due tipi comuni di errori:

  • Errori che non causano problemi a Config Sync stesso, ma impediscono il corretto funzionamento dei carichi di lavoro, ad esempio un criterio NetworkPolicy eccessivamente restrittivo che impedisce la comunicazione dei componenti del carico di lavoro.
  • Errori che impediscono a Config Sync di applicare modifiche a un cluster, ad esempio un manifest Kubernetes non valido o un oggetto rifiutato da un controller di ammissione. I metodi spiegati in precedenza dovrebbero rilevare la maggior parte di questi errori.

Rilevare gli errori descritti nel primo punto precedente è quasi impossibile a livello di Config Sync perché richiede la comprensione dello stato di ciascun carico di lavoro. Per questo motivo, è meglio rilevare questi errori tramite il sistema di monitoraggio esistente che ti avvisa quando un'applicazione non funziona correttamente.

Il rilevamento degli errori descritti nel secondo punto precedente, che dovrebbe essere raro se hai implementato tutti i guardrail, richiede una configurazione specifica. Per impostazione predefinita, Config Sync scrive gli errori nei propri log (che per impostazione predefinita troverai in Cloud Logging). Gli errori vengono visualizzati anche nella pagina della console Google Cloud di Config Sync. In genere né i log né la console sono sufficienti per rilevare gli errori, perché probabilmente non li monitori sempre. Il modo più semplice per automatizzare il rilevamento degli errori è eseguire il nomos status comando, che indica se è presente un errore in un cluster.

Puoi anche configurare una soluzione più avanzata con avvisi automatici per gli errori. Config Sync espone le metriche nel formato Prometheus. Per ulteriori informazioni, consulta la sezione relativa al monitoraggio di Config Sync.

Dopo aver inserito le metriche di Config Sync nel sistema di monitoraggio, crea un avviso che ti invii una notifica quando la metrica gkeconfig_monitor_errors è maggiore di 0. Per ulteriori informazioni, consulta la sezione relativa alla gestione dei criteri di avviso per Cloud Monitoring o le regole di avviso per Prometheus.

Riepilogo dei meccanismi per implementazioni sicure con Config Sync

La tabella seguente riassume i vari meccanismi descritti in precedenza in questo documento. Nessuno di questi meccanismi è esclusivo. Puoi scegliere di utilizzarne alcune o tutte per scopi diversi.

Meccanismo A cosa serve Che cosa non è adatto Caso d'uso di esempio
ID e tag dei commit Git Utilizza ID o tag di commit Git specifici per controllare con precisione a quali modifiche del cluster vengono applicate. Non utilizzare ID commit o tag Git per differenze di lunga durata tra i cluster. Utilizza i selettori di cluster. Tutti i tuoi cluster sono configurati per applicare il commit 12345 Git. Apporta una modifica con un nuovo commit, abcdef, che vuoi testare. Modifica la configurazione di un singolo cluster per utilizzare questo nuovo commit per convalidare la modifica.
Rami Git Utilizza più branch di Git quando vuoi implementare la stessa modifica in più ambienti, uno dopo l'altro. Non utilizzare più branch di Git per differenze di lunga durata tra i cluster. I rami divergono notevolmente e sarà difficile riunirli nuovamente. Prima unisci la modifica nel ramo di staging, dove verrà rilevata dai cluster di staging.
Quindi unisci la modifica nel ramo principale, dove verrà rilevata dai cluster di produzione.
Selettori di cluster e spazi dei nomi Utilizza i selettori per le differenze permanenti tra cluster e spazi dei nomi. Non utilizzare i selettori per un'implementazione graduale in più ambienti. Se vuoi testare prima una modifica in fase di staging e poi eseguirne il deployment in produzione, utilizza branch Git distinti. Se i team di applicazioni hanno bisogno di accesso completo ai cluster di sviluppo, ma accesso in sola lettura ai cluster di produzione, utilizza l'oggetto ClusterSelector per applicare i criteri RBAC corretti solo ai cluster pertinenti.
Revisioni tra pari Utilizza le revisioni tra pari per assicurarti che i team competenti approvino le modifiche. I revisori non rilevano tutti gli errori, in particolare elementi come gli errori di sintassi. La tua organizzazione impone che il team di sicurezza debba esaminare le modifiche alla configurazione che interessano più sistemi. Chiedi a un membro del team di sicurezza di esaminare le modifiche.
Test automatici nella pipeline di integrazione continua Utilizza i test automatici per rilevare gli errori nelle modifiche suggerite. I test automatici non possono sostituire completamente un revisore umano. Utilizza entrambe. L'esecuzione di un comando nomos vet su tutte le modifiche suggerite conferma che il repository è una configurazione Config Sync valida.
Monitorare gli errori di sincronizzazione Assicurati che Config Sync applichi effettivamente le modifiche ai tuoi cluster. Gli errori di sincronizzazione si verificano solo se Config Sync tenta di applicare un repository non valido o se il server API Kubernetes rifiuta alcuni degli oggetti. Un utente aggira tutti i test e le revisioni e commette una modifica non valida al repository Config Sync. Questa modifica non può essere applicata ai cluster. Se monitori gli errori di sincronizzazione, riceverai un avviso in caso di errore.

Esempio di strategia di implementazione

Questa sezione utilizza i concetti introdotti nel resto dell'articolo per aiutarti a creare una strategia di implementazione end-to-end in tutti i cluster della tua organizzazione. Questa strategia presuppone che tu abbia parchi risorse distinti per lo sviluppo, la gestione temporanea e la produzione (come mostrato nell'esempio di parco risorse 1 - Approccio 1).

In questo scenario, configuri ogni cluster in modo che si sincronizzi con il tuo repository Git utilizzando un commit Git specifico. Il deployment di una modifica in un determinato parco risorse è un processo in quattro passaggi:

  1. Aggiorna un singolo cluster ("canary") nel parco per utilizzare per primo il nuovo commit.
  2. Convalida che tutto funzioni come previsto eseguendo test e monitorando l'implementazione.
  3. Aggiorna il resto dei cluster nel parco risorse.
  4. Confermi di nuovo che tutto funziona come previsto.

Per implementare una modifica in tutti i cluster, ripeti questa procedura per ogni parco risorse. Tecnicamente, puoi applicare questo metodo a qualsiasi commit Git, da qualsiasi ramo. Tuttavia, ti consigliamo di adottare la seguente procedura per identificare i problemi all'inizio della procedura di revisione:

  1. Quando un utente apre una richiesta di modifica nel repository Git di Config Sync, esegui il deployment della modifica in uno dei cluster di sviluppo.
  2. Se la richiesta di modifica viene accettata e unita al tuo ramo principale, esegui il deployment completo in tutti i parchi come descritto in precedenza.

Sebbene alcune modifiche possano avere come target solo un parco specifico, ti consigliamo di implementare tutte le modifiche su tutti i parchi. Questa strategia elimina il problema di monitorare quale parco deve essere sincronizzato con quale commit. Presta particolare attenzione alle modifiche che hanno come target solo il fleet di produzione, perché non sarà stato possibile eseguire test adeguati nei fleet precedenti. Ad esempio, significa attendere più a lungo prima che si verifichino problemi tra il deployment nei cluster canary e nel resto dei cluster.

In sintesi, un deployment end-to-end completo è il seguente:

  1. Qualcuno apre una richiesta di modifica.
  2. Vengono eseguiti test e convalide automatici e viene eseguita una revisione manuale.
  3. Attiva un job manualmente per eseguire il deployment della modifica nel cluster canary nel parco risorse di sviluppo. I test end-to-end automatici vengono eseguiti in questo cluster.
  4. Se è tutto a posto, unisci la richiesta di modifica al ramo principale.
  5. L'unione attiva un job automatico per eseguire il deployment del nuovo commit della punta del ramo principale nel cluster canary nel parco risorse di sviluppo. I test end-to-end automatici vengono eseguiti in questo cluster (per rilevare potenziali incompatibilità tra due richieste di modifica che sono state create e unite approssimativamente nello stesso momento).
  6. I seguenti job vengono eseguiti uno dopo l'altro (li attivi manualmente o dopo un orario predefinito per consentire agli utenti di segnalare le regressioni):
    1. Esegui il deployment in tutti i cluster del parco risorse di sviluppo.
    2. Esegui test e convalide nei cluster del parco risorse di sviluppo.
    3. Esegui il deployment nel cluster canary del parco risorse di staging.
    4. Esegui test e convalide nel cluster canary del parco risorse di gestione temporanea.
    5. Esegui il deployment in tutti i cluster del parco risorse di staging.
    6. Esegui test e convalide nei cluster del parco risorse di gestione temporanea.
    7. Esegui il deployment nel cluster canary del parco risorse di produzione.
    8. Esegui test e convalide nel cluster canary del parco risorse di produzione.
    9. Esegui il deployment in tutti i cluster del parco risorse di produzione.
    10. Esegui test e convalide nei cluster del parco risorse di produzione.

Procedura di implementazione completa.

Passaggi successivi