La nostra implementazione del Continuous Deployment sulla piattaforma del cliente

Noi di True Engineering abbiamo impostato un processo per la fornitura continua di aggiornamenti ai server dei clienti e desideriamo condividere questa esperienza.

Per cominciare, abbiamo sviluppato un sistema online per il cliente e lo abbiamo implementato nel nostro cluster Kubernetes. Ora la nostra soluzione ad alto carico è stata spostata sulla piattaforma del cliente, per la quale abbiamo impostato un processo di distribuzione continua completamente automatico. Grazie a ciò, abbiamo accelerato il time-to-market, ovvero l'introduzione delle modifiche nell'ambiente del prodotto.

In questo articolo parleremo di tutte le fasi del processo di Continuous Deployment (CD) ovvero di consegna degli aggiornamenti alla piattaforma del cliente:

  1. Come inizia questo processo?
  2. sincronizzazione con il repository Git del cliente,
  3. assemblaggio di backend e frontend,
  4. distribuzione automatica dell'applicazione in un ambiente di test,
  5. distribuzione automatica a Prod.

Condivideremo i dettagli di configurazione lungo il percorso.

La nostra implementazione del Continuous Deployment sulla piattaforma del cliente

1. Avviare il CD

La distribuzione continua inizia con lo sviluppatore che invia le modifiche al ramo di rilascio del nostro repository Git.

La nostra applicazione funziona su un'architettura a microservizi e tutti i suoi componenti sono archiviati in un unico repository. Grazie a questo, tutti i microservizi vengono raccolti e installati, anche se uno di essi è cambiato.

Abbiamo organizzato il lavoro attraverso un repository per diversi motivi:

  • Facilità di sviluppo: l'applicazione si sta sviluppando attivamente, quindi puoi lavorare con tutto il codice contemporaneamente.
  • Un’unica pipeline CI/CD che garantisce che l’applicazione come sistema unico superi tutti i test e venga consegnata all’ambiente di produzione del cliente.
  • Eliminiamo la confusione nelle versioni: non dobbiamo archiviare una mappa delle versioni dei microservizi e descriverne la configurazione per ciascun microservizio negli script Helm.

2. Sincronizzazione con il repository Git del codice sorgente del cliente

Le modifiche apportate vengono automaticamente sincronizzate con il repository Git del cliente. Lì viene configurato l'assemblaggio dell'applicazione, che viene avviato dopo l'aggiornamento del ramo e la distribuzione nella continuazione. Entrambi i processi hanno origine nel loro ambiente da un repository Git.

Non possiamo lavorare direttamente con il repository del cliente perché abbiamo bisogno dei nostri ambienti per lo sviluppo e il test. Utilizziamo il nostro repository Git per questi scopi: è sincronizzato con il loro repository Git. Non appena uno sviluppatore pubblica le modifiche nel ramo appropriato del nostro repository, GitLab invia immediatamente queste modifiche al cliente.

La nostra implementazione del Continuous Deployment sulla piattaforma del cliente

Dopodiché è necessario eseguire l'assemblaggio. Si compone di diverse fasi: assemblaggio backend e frontend, test e consegna alla produzione.

3. Assemblare il backend e il frontend

La creazione del backend e del frontend sono due attività parallele eseguite nel sistema GitLab Runner. La sua configurazione dell'assembly originale si trova nello stesso repository.

Tutorial per scrivere uno script YAML da costruire in GitLab.

GitLab Runner prende il codice dal repository richiesto, lo assembla con il comando Java application build e lo invia al registro Docker. Qui assembliamo il backend e il frontend, otteniamo le immagini Docker, che inseriamo in un repository dal lato del cliente. Per gestire le immagini Docker utilizziamo Plug-in Gradle.

Sincronizziamo le versioni delle nostre immagini con la versione release che verrà pubblicata in Docker. Per un funzionamento regolare abbiamo apportato diverse modifiche:

1. I contenitori non vengono ricostruiti tra l'ambiente di test e l'ambiente di produzione. Abbiamo effettuato delle parametrizzazioni in modo che lo stesso contenitore potesse funzionare con tutte le impostazioni, variabili d'ambiente e servizi sia nell'ambiente di test che in produzione senza ricompilazione.

2. Per aggiornare un'applicazione tramite Helm, è necessario specificarne la versione. Costruiamo il backend, il frontend e aggiorniamo l'applicazione: si tratta di tre attività diverse, quindi è importante utilizzare la stessa versione dell'applicazione ovunque. Per questa attività, utilizziamo i dati della cronologia Git, poiché la configurazione e le applicazioni del nostro cluster K8S si trovano nello stesso repository Git.

Otteniamo la versione dell'applicazione dai risultati dell'esecuzione del comando
git describe --tags --abbrev=7.

4. Distribuzione automatica di tutte le modifiche all'ambiente di test (UAT)

Il passaggio successivo in questo script di build consiste nell'aggiornare automaticamente il cluster K8S. Ciò si verifica a condizione che l'intera applicazione sia stata creata e tutti gli artefatti siano stati pubblicati nel registro Docker. Successivamente, viene avviato l'aggiornamento dell'ambiente di test.

L'aggiornamento del cluster viene avviato utilizzando Aggiornamento del timone. Se, di conseguenza, qualcosa non è andato secondo i piani, Helm ripristinerà automaticamente e in modo indipendente tutte le modifiche apportate. Il suo lavoro non ha bisogno di essere controllato.

Forniamo la configurazione del cluster K8S insieme all'assemblaggio. Pertanto, il passaggio successivo è aggiornarlo: configMap, distribuzioni, servizi, segreti e qualsiasi altra configurazione di K8S che abbiamo modificato.

Helm esegue quindi un aggiornamento RollOut dell'applicazione stessa nell'ambiente di test. Prima che l'applicazione venga distribuita in produzione. Questo viene fatto in modo che gli utenti possano testare manualmente le funzionalità aziendali che inseriamo nell'ambiente di test.

5. Distribuzione automatica di tutte le modifiche a Prod

Per distribuire un aggiornamento nell'ambiente di produzione, devi solo fare clic su un pulsante in GitLab e i contenitori verranno immediatamente consegnati all'ambiente di produzione.

La stessa applicazione può funzionare in ambienti diversi, di test e di produzione, senza necessità di ricompilazione. Utilizziamo gli stessi artefatti senza modificare nulla nell'applicazione e impostiamo i parametri esternamente.

La parametrizzazione flessibile delle impostazioni dell'applicazione dipende dall'ambiente in cui verrà eseguita l'applicazione. Abbiamo spostato all'esterno tutte le impostazioni dell'ambiente: tutto è parametrizzato attraverso la configurazione di K8S e i parametri Helm. Quando Helm distribuisce un assembly nell'ambiente di test, le impostazioni di test vengono applicate ad esso e le impostazioni del prodotto vengono applicate all'ambiente di produzione.

La cosa più difficile è stata parametrizzare tutti i servizi utilizzati e le variabili che dipendono dall'ambiente e tradurli in variabili di ambiente e descrizioni-configurazioni dei parametri di ambiente per Helm.

Le impostazioni dell'applicazione utilizzano variabili di ambiente. I loro valori sono impostati in contenitori utilizzando la mappa di configurazione di K8S, modellata utilizzando i modelli Go. Ad esempio, l'impostazione di una variabile di ambiente sul nome di dominio può essere eseguita in questo modo:

APP_EXTERNAL_DOMAIN: {{ (pluck .Values.global.env .Values.app.properties.app_external_domain | first) }}

.Values.global.env – questa variabile memorizza il nome dell'ambiente (prod, stage, UAT).
.Values.app.properties.app_external_domain – in questa variabile impostiamo il dominio desiderato nel file .Values.yaml

Quando si aggiorna un'applicazione, Helm crea un file configmap.yaml dai modelli e riempie il valore APP_EXTERNAL_DOMAIN con il valore desiderato a seconda dell'ambiente in cui viene avviato l'aggiornamento dell'applicazione. Questa variabile è già impostata nel contenitore. È possibile accedervi dall'applicazione, quindi ogni ambiente applicativo avrà un valore diverso per questa variabile.

Relativamente di recente, il supporto K8S è apparso in Spring Cloud, incluso il lavoro con configMaps: Spring Cloud Kubernetes. Sebbene il progetto si stia sviluppando attivamente e cambiando radicalmente, non possiamo utilizzarlo nella produzione. Ma monitoriamo attivamente le sue condizioni e lo utilizziamo nelle configurazioni DEV. Non appena si sarà stabilizzato, passeremo dall'utilizzo delle variabili di ambiente ad esso.

In totale

Quindi, la distribuzione continua è configurata e funzionante. Tutti gli aggiornamenti avvengono premendo un solo tasto. La consegna delle modifiche all'ambiente del prodotto è automatica. E, cosa più importante, gli aggiornamenti non fermano il sistema.

La nostra implementazione del Continuous Deployment sulla piattaforma del cliente

Piani futuri: migrazione automatica del database

Abbiamo pensato all'aggiornamento del database e alla possibilità di annullare queste modifiche. Dopotutto, due diverse versioni dell'applicazione sono in esecuzione contemporaneamente: quella vecchia è in esecuzione e quella nuova è attiva. E spegneremo quella vecchia solo quando saremo sicuri che la nuova versione funzioni. La migrazione del database dovrebbe consentire di lavorare con entrambe le versioni dell'applicazione.

Pertanto, non possiamo semplicemente modificare il nome della colonna o altri dati. Ma possiamo creare una nuova colonna, copiare i dati dalla vecchia colonna al suo interno e scrivere trigger che, durante l'aggiornamento dei dati, li copieranno e aggiorneranno contemporaneamente in un'altra colonna. E dopo il successo dell'implementazione della nuova versione dell'applicazione, dopo il periodo di supporto post lancio, saremo in grado di eliminare la vecchia colonna e il trigger che non è più necessario.

Se la nuova versione dell'applicazione non funziona correttamente, possiamo ripristinare la versione precedente, inclusa la versione precedente del database. In breve, le nostre modifiche ti permetteranno di lavorare contemporaneamente con diverse versioni dell'applicazione.

Prevediamo di automatizzare la migrazione del database tramite il lavoro K8S, integrandolo nel processo CD. E condivideremo sicuramente questa esperienza su Habré.

Fonte: habr.com

Aggiungi un commento