In Buildo iniziamo sempre ogni progetto dalla comprensione dei bisogni di fondo, anche per i progetti interni. Come team DevOps abbiamo deciso di intervenire per migliorare il flusso di lavoro e l’autonomia del nostro team di sviluppo (puoi leggere come è iniziato lo sviluppo della nostra Clustero Developer Platform nell’articolo precedente, “L’anello mancante per semplificare la complessità dei database”). In sintesi, attraverso interviste e sulla base dell’esperienza passata abbiamo individuato le funzionalità chiave di cui uno sviluppatore avrebbe bisogno:
- Esporre l’app su internet tramite un URL HTTPS
- Autenticazione per la segregazione degli accessi tramite l’utenza Google di Buildo
- La possibilità di iniettare secret da 1Password, che usiamo comunemente in Buildo
Oggi gli sviluppatori che vogliono esplorare una nuova tecnologia hanno bisogno del team DevOps per partire. Il nostro obiettivo è rimuovere le barriere che ostacolano la sperimentazione autonoma. Se lasciata senza controllo, questa situazione porta a un’eccessiva proliferazione di ambienti snowflake unici, difficili da gestire e su cui è difficile condividere conoscenza.
In questo articolo parliamo del nostro approccio per abilitare la sperimentazione autonoma senza il supporto del team DevOps e dei dettagli di implementazione delle nostre soluzioni. Vedremo anche come gli sviluppatori possono interfacciarsi con il nostro sistema tramite semplici file YAML, il ruolo di Argo CD e dell’App Operator e i nostri piani futuri per integrare i database senza attriti.
L’interfaccia per gli sviluppatori
Come può quindi uno sviluppatore sperimentare senza generare ambienti snowflake o richiedere il supporto DevOps?
La risposta è semplice: basta aggiungere un file YAML essenziale a un repository, così che ArgoCD possa installare la tua app nel cluster senza attriti.
apiVersion: applications.buildo.io/v1alpha1
kind: App
metadata:
name: my-app
namespace: my-app
spec:
image: my-app-image:v1.2.3
Argo CD, uno strumento di continuous delivery GitOps dichiarativo per Kubernetes, esamina automaticamente i repository di Buildo alla ricerca di un App CR (la Custom Resource definita dall’Operator) e lo installa nel cluster, attivando l’App Operator per l’installazione principale.
Semplice, no? E per ottenere un indirizzo internet senza esporre il proprio lavoro a tutto il mondo? Bastano poche righe in più e l’App Operator se ne occuperà al posto tuo.
apiVersion: applications.buildo.io/v1alpha1
kind: App
metadata:
name: my-app
namespace: my-app
spec:
image: my-app-image:v1.2.3
env:
MY_ENV_VAR: wow
route:
domain: my-app.buildo.io
port: 3000
path: /custom-path
auth:
enabled: true
secretsFrom: 1password-item
storage:
- /cache
- /data
L’App CR in dettaglio
Avrai notato che il kind App non è una risorsa nativa di Kubernetes. Abbiamo esteso le API di Kubernetes con una custom resource definition per permettere a un operator, l’App Operator di Buildo, di convertire questo semplice YAML in più risorse complesse.
L’App Operator è una parte cruciale della nostra architettura. È stato creato usando l’Operator SDK con Helm. Abbiamo definito la Custom Resource Definition come il nostro contratto con gli sviluppatori. Abbiamo scelto Helm come linguaggio di templating perché è molto diffuso e facile da comprendere. Un limite di Helm, però, è che il client controlla contenuto e versione del pacchetto. Con l’approccio Helm Operator è il team DevOps a occuparsi della manutenzione dell’operator: questo significa che gli sviluppatori non devono cambiare la versione del pacchetto quando un componente dell’infrastruttura viene aggiornato. Per maggiori informazioni puoi leggere il nostro articolo precedente su questo tema.

L’App Operator legge il kind App e lo converte in diversi CR e risorse native.
Ingress, Service e Certificate
Nell’Ingress colleghiamo il dominio specificato dall’utente al Service. Il dominio viene associato all’IP del load balancer tramite ExternalDNS. Se lo sviluppatore opta per l’autenticazione, l’operator include le annotazioni necessarie per integrare Ory Oathkeeper. Il Certificate associato - emesso dall’operator cert-manager tramite Let’s Encrypt - viene generato automaticamente.
...
spec:
route:
domain: my-app.buildo.io
port: 3000
path: /custom-path
auth:
enabled: true
...
Ory Oathkeeper autorizza le richieste HTTP in ingresso. Può funzionare come Policy Enforcement Point all’interno della tua architettura cloud, facendo da reverse proxy per l’API o il web server upstream, rifiutando le richieste non autorizzate e inoltrando quelle autorizzate.
ExternalSecret
ExternalSecret è fondamentale per generare un Secret a partire da un elemento di 1Password, che viene poi associato come variabile d’ambiente nel Deployment. L’operator di ExternalSecret e 1Password Secrets Automation rendono possibile questo processo.
...
spec:
secretsFrom: 1password-item
...
External Secrets Operator è un operator Kubernetes che integra sistemi esterni di gestione dei secret come AWS Secrets Manager, HashiCorp Vault, Google Secrets Manager, Azure Key Vault, IBM Cloud Secrets Manager, CyberArk Conjur e altri. L’operator recupera le informazioni dalle API esterne e le inietta automaticamente in un Kubernetes Secret.
PersistentVolumeClaim
Il PersistentVolumeClaim (PVC) fornisce un volume che viene montato automaticamente sul nostro Deployment. Il PVC crea un PersistenceVolume usando la storage class predefinita di clustero: EBS tramite aws-ebs-csi-driver.
...
spec:
storage:
- /var/lib/cache
- /data
...
Non abbiamo dovuto attendere molto per la prima occasione di mettere alla prova il nostro lavoro: Conto, uno dei nostri strumenti interni, aveva bisogno di qualcosa come la nostra piattaforma per migliorare il proprio flusso di lavoro. Essendo uno strumento interno senza un budget dedicato, era piuttosto semplice: una web app Python con Streamlit. Dopo un po’ di tempo, insieme al team di Conto, ci siamo accorti che usavano un volume per mettere in cache alcuni dati e non volevano perderli ogni volta che l’app veniva riavviata per un aggiornamento. Abbiamo visto l’opportunità di migliorare la nostra Clustero Developer Platform risolvendo il problema di Conto, e abbiamo quindi ampliato le funzionalità della piattaforma aggiungendo la possibilità di rendere persistenti i volumi, così che i dati non andassero perduti durante i riavvii dell’app.
Questa storia di successo ha avuto rapidamente eco negli altri team interni, portando all’adozione della nuova funzionalità di Clustero in diversi piccoli progetti. Quella che era nata come una semplice intuizione si è evoluta in una feature che ha reso più autonomi più team, riducendo la dipendenza dal supporto DevOps.
Sviluppi futuri
Siamo riusciti a eliminare gli ambienti snowflake in favore di applicazioni distribuite rapidamente. Il nostro percorso, però, non finisce qui: vogliamo integrare la nostra soluzione anche nei progetti già esistenti. Per farlo ci serve una nuova funzionalità cruciale: i database. Come forse hai letto nell’articolo di Benedetto, in Clustero forniamo già un metodo semplice e dichiarativo per gestire un database, e integreremo questa funzionalità nell’App CR.