Vai al contenuto

Principi architetturali e operativi

Infrastruttura come codice (IaC)

Quando possibile gestiamo l'infrastruttura attraverso un approccio dichiarativo.

Ciò significa che l'infrastruttura desiderata è descrivibile e descritta attraverso collezioni di files strutturati (.yaml, .json, etc..) sottoposti a versionamento in repositories appartenenti a github.com/qntweb.

Infrastruttura immutabile

Una infrastruttura si definisce immutabile quando l'aggiornamento dei suoi componenti non avviene attraverso modifiche e patches agli stessi, ma attraverso la loro sostituzione.

Esempio: aggiornamento di un Deployment in K8s

Quando Kubernetes procede al rolling update di un Deployment i vecchi Pods non vengono aggiornati, bensì dismessi, mentre ne vengono creati di nuovi.

Ambienti Kubernetes

Tutto ciò che distribuiamo nei clusters Kubernetes e la distribuzione dei clusters stessi (1) seguono questo principio by design.

  1. Se, ad esempio, esce una nuova patch di Kubernetes o occorre aggiornare il kernel linux questo significa dover aggiornare i nodi dei clusters.

    Il processo di riconciliazione di Cluster API crea nuove VM che si agganciano al cluster per sostituire quelle vecchie, che vengono prima drenate dai loro carichi di lavoro e poi eliminate.

Altri ambienti

Quando possibile seguiamo lo stesso approccio anche relativamente allo strato di computing in cui distribuiamo i nostri applicativi, ossia le Virtual Machines.

GitOps

Si parla di GitOps quando sviluppatori e sistemisti non sottopongono direttamente i files di definizione dell'infrastruttura ai controllers che li rendono operativi.

Il team si limita al mantenimento delle definizioni nei repositories, operando attraverso modifiche dirette (push), proposte di modifica (pull request) e approvazione delle medesime (merge pull request).(1)

  1. Autorizzazione di A a ricevere traffico da B
    gitGraph LR:
        commit id: "..."
        branch firewalling/allow-a-from-b
        checkout firewalling/allow-a-from-b
        commit id: "Allow ingress in A from B"
        checkout main
        commit id: "direct update xy"
        merge firewalling/allow-a-from-b id: "Sysadmin Merge pr #"

La trasmissione delle definizioni ai sistemi di distribuzione/riconciliazione di più basso livello (vSphere, Kubernetes API, etc...) è demandata a software di distribuzione continua che consumano i repositories git, come ad esempio ArgoCD.

I software di distribuzione continua offrono al team visibilità e controllo sulla sincronizzazione dell'infrastruttura con ciò che è definito nei repositories git.

GitOps Flow

Procedure amministrative

Esistono procedure amministrative che vengono eseguite one-shot nelle operazioni aziendali, ossia non si prestano al ciclo di riconciliazione continua tipico di un controller.

Operators

Nel ciclo di vita di una distribuzione applicativa si usa distinguere tra due tipi di operazioni

  • Day 1: sono le operazioni di configurazione e rilascio iniziale
  • Day 2: le operazioni di mantenimento
    • rilasci di aggionamenti
    • scaling
    • monitoraggio
    • healing e recovery
    • operazioni di failover in sistemi di HA che presentano topologie master/slave
    • ...

Quando possibile cerchiamo di automatizzare l'intero ciclo vita (Day1+2).

In Kubernetes questo significa generalmente utilizzare operatori.

Esempio: Zalando Postgres Operator

Supponiamo di dover distribuire un cluster Postgres, con una topologia composta da un master e due repliche sincrone.

Le operazioni Day1 consistono nel fare in modo che le tre istanze siano operative e opportunamente configurate per formare il cluster, nel configurare due servizi di networking (servizio master, servizio repliche bilanciato), etc...

Le operazioni Day2 consistono nelle operazioni di backup, aggiornamento, scaling, monitoraggio, healing, failover, etc...

Postgres Operator incapsula le operazioni Day1+2 estendendo il control plane di Kubernetes con le sue CRD.

Postgres Operator Flow

Firewalling

Zero Trust Networks

L'approccio Zero Trust consiste nell'immaginare e cercare di implementare una rete di connettività tra dispositivi e applicazioni in cui non esiste l'idea di perimetro sicuro.
L'obiettivo è quello di ottenere pieno controllo e piena capacità di enforcement su tutte le direzioni di traffico, sia verticale che orizzontale e minimizzare la capacità di movimeto laterale in caso di penetrazione dei sistemi.

In uno scenario ideale il traffico di rete in uscita ed entrata di ogni applicazione o dispositivo è oggetto di policies che stabiliscono, a partire da una condizione di default pari a deny all, quale tipo di traffico sia autorizzato e da/verso chi.

Perimetri

Nella realtà un approccio pienamente Zero Trust a tutti i livelli non è così semplice da implementare, soprattutto laddove la mancanza di controllers che possano procedere autonomamente all'applicazione distribuita delle regole di traffico renderebbe molto onerosa l'attività sistemistica e aumenterebbe le probabilittà di vulnerabilità dovute ad errore umano.

Spesso è necessario ricorrere ad un architettura basata su perimetri considerati "sicuri" (1), il cui traffico N/S transita attraverso uno o più firewalls.

  1. Perimetro "sicuro"

    Un perimetro sicuro è uno spazio di connettività di rete in cui il traffico tra i partecipanti, altrimenti detto "orizzontale" o "E/W", è potenzialmente non oggetto di policies di firewalling, poiché considerato "affidabile".

    Questo espone gli applicativi ad attacchi laterali mossi a partire da partecipanti al perimetro che sono stati "bucati".

Perimetri di simplebooking.local

Ambiente Kubernetes

In ogni sito geografico i nodi dei clusters dell'ambiente Kubernetes sono distribuiti all'interno del perimetro kubernetes.cmp/24, che vede il firewall perimetrale del sito come ponte N/S.

Il traffico di rete E/W e N/S degli applicativi distribuiti nei clusters Kubernetes è gestito secondo un approccio Zero Trust.
La segmentazione del traffico autorizzato avviene per mezzo di network policies gestite Cilium.