Sempre più aziende portano le proprie applicazioni nel cloud e si trovano davanti a un bivio: optare per un "lift and shift" oppure ripensare le soluzioni in ottica "cloud-native", termine che assume sfumature diverse a seconda dei contesti. Questo articolo si concentra sulla seconda strada e, nello specifico, su una tecnica utile per spostare le applicazioni nei container (ad esempio Docker) e orchestrarle con Kubernetes.

Fonte: iStockPhoto
La sfida del bootstrapping
Una delle promesse di DevOps e delle migrazioni verso il cloud è alleggerire le operations tradizionali automatizzando i processi manuali. La natura dichiarativa di Kubernetes, che garantisce in automatico lo stato desiderato delle applicazioni, è estremamente potente. A volte, però, le applicazioni richiedono fasi di "bootstrapping" prima di poter essere eseguite correttamente, oppure devono partire in un ordine preciso per gestire le dipendenze da altri sistemi come code o database.
Per far girare l'app senza intoppi si potrebbe riscrivere il codice introducendo una logica di retry personalizzata fino al verificarsi delle condizioni ideali, ma questo rischia di rallentare la migrazione. Un'alternativa che evita di mettere mano al codice è creare piccole app, script o comandi e aggiungerli come InitContainers.
Possibili casi d'uso degli Init Container
- Un'app blockchain che deve registrarsi tra i propri peer
- Un'app che deve recuperare un access token da un identity provider
- Dati dinamici letti da un database e messi in cache, così che l'app possa usarli dopo l'avvio
- Recuperare secret cifrati da un vault e scriverli sul file system
- Bloccare l'avvio dell'app finché un altro sistema non è disponibile (ad esempio una coda o un database server)
Un esempio semplice con due immagini Busybox
In questo esempio ipotizziamo che un'app debba essere popolata dinamicamente con alcuni dati prima dell'avvio (come negli scenari visti sopra). Lo stesso risultato si potrebbe ottenere con una ConfigMap, ma a fini illustrativi, e per mostrare la potenza di questa tecnica, vale la pena tenere la mente aperta su cos'altro si potrebbe fare.
- Creare un PersistentVolumeClaim
Per prima cosa serve un volume di storage a cui poter accedere
Persistent Volume Claim
$ kubectl apply -f test-pvc.yamlpersistentvolumeclaim/test-pvc created
2. Generare un file YAML di configurazione del Deployment
$ kubectl create deployment test-app --image=busybox:1.28.0 -o yaml --dry-run > test-app.yaml
3. Modificare il Deployment aggiungendo il volume e l'Init Container come segue
Deployment con Init Container
Notate come in questo file abbiamo aggiunto il volume e poi un'altra immagine Busybox nell'initContainer. Potrebbe essere letteralmente qualsiasi immagine; in questo esempio volevamo semplicemente scrivere del contenuto in un file sul file system montato e, all'avvio dell'app con l'altra immagine Busybox, leggerne il contenuto.
4. Avviare il Deployment e monitorare i log
# deploy app
$ kubectl apply -f test-app.yamldeployment.apps/test-app configured# monitor logs
$ kubectl logs -f deployment/test-appFile content: Hello, World!
Se vedete "File content: Hello, World!", allora ha funzionato. Partendo da questo esempio di base potete personalizzare la vostra app sostituendo l'immagine del container principale e aggiungere tutti gli init container necessari, così che l'app si avvii con tutto ciò che le serve. Il bello di questa tecnica è poter automatizzare il deploy delle app senza dover scrivere logiche di retry complesse o gestire manualmente errori e dipendenze.
Per ulteriori informazioni sugli Init Container, consultate la documentazione ufficiale di Kubernetes: