kubernetes ingress

in Architetture Software, Informatica

Kubernetes – Ingress

Reading Time: 5 minutes

Un ingress è una regola che definisce come un servizio, presente all’interno di un cluster, possa essere reso disponibile all’esterno del cluster. Pensiamo ad esempio ad una serie di server web nginx che devono essere resi accessibili dalla rete internet. Un Ingress Controller è un proxy che intercetta le richieste verso il cluster e utilizzando le regole mappa ogni servizio in base alla URL o il nome del dominio nella richiesta.

Quando viene definito un deployment in Kubernetes, tramite un file yaml, ci troviamo in una situazione simile alla seguente:

Nel caso specifico vengono create tre repliche del container con etichetta foo generate a partire dall’immagine my-app .

Anzichè accedere direttamente ai container è spesso utile raggrupparli all’interno di un servizio, rendendoli disponibili tramite un unico indirizzo IP del cluster. In questa particolare situazione sono accessibili solo all’interno del cluster stesso.

Partendo da un file yaml con la definizione di un deployment è possibile creare un service, utilizzando anche in questo caso un file yaml :

In questo caso viene creato un service denominato foo-service che espone all’interno del cluster la porta 80, protocollo tcp. In questo modo il servizio è disponibile solo all’interno del cluster.

Per poter rendere disponibile un service all’esterno Kubernetes integra nativamente due tipologie di nodi: NodePort e LoadBalancer. La definizione del tipo di nodo che deve essere utilizzata avviene all’interno del campo type all’interno del manifest del servizio stesso.

Nell’esempio precedente, viene definito un service di tipo NodePort.

NodePort

Il tipo di service NodePort sono quelli più semplici da utilizzare e da implementare. In pratica, richiedono alle API di Kubernetes di assegnargli una porta (nell’esempio una porta TCP) casuale e che venga esposta all’esterno del cluster. La richiesta di un client può essere indirizza verso quella porta e la richiesta verrà indirizzata automaticamente verso il nodo corretto. Facendo un parallelo con il mondo telefonico, è come se facendo una chiamata verso un particolare numero esista la certezza di essere messi in contatto con la persona corretta. Il meccanismo di mappatura viene configurato automaticamente da Kubernetes, e questo lo rende semplice da utilizzare. L’unica particolarità è che Kubernetes mette a disposizione porte “random” solo nel range tra 30000  e 32767, sicuramente porte custom e che normalmente non generano conflitto con altri servizi, ma che sono sicuramente distanti dalle porte 80 e 443 dei servizi web che vogliamo esporre. Inoltre, la casualità della porta rilasciata rende le operazioni di configurazione di servizi come firewal, NAT non sempre facili.

LoadBalancer

L’alternativa ai NodePort è il type LoadBalancer. Questo particolare type è leggermente piu’ complesso rispetto al NodePort e ha bisogno di alcuni prerequisiti, come ad esempio la presenza del cluster all’interno di un ambiente cloud e soprattutto è necessario sottostare alle configurazioni che vengono messe a disposizione da ogni singolo fornitore cloud (es. Google, Aws e Azure). Inoltre, un load balancer viene attivato per ogni service con questo particolare tipo associato, il che si traduce nell’utilizzo di un indirizzo IP che molto spesso viene fornito come servizio a pagamento.

L’assegnazione di una porta casuale (NodePort) oppure utilizzando il type LoadBalancer è necessario impostare una serie di configurazioni e soprattutto comporta una serie di problemi al crescere dei servizi da esporre. Inoltre, l’esposizione dei servizi tramite LoadBalancer comporta problemi di costi legati aggiuntivi al rilascio di ogni nuovo indirizzo ip .

In questo scenario, Kubernetes aveva la necessità di introdurre un meccanismo piu’ snello per l’esposizione dei servizi verso l’esterno. In questo scenario la piattaforma di Kubernetes ha introdotto un nuovo tipo di manifest che prende il nome di Ingress, con il compito di definire le regole che permettono di defnire l’accesso dal client al relativo servizio.

Ma cosa sono gli ingress? Sono dei pod, come qualsiasi altra applicazione, quindi sono posizionati all’interno del cluster e possono vedere altri pods. Sono sviluppati utilizzando proxy, sviluppati ormai da anni e che li rende particolarmente adattati e configurabili. In rete sono disponibili diverse tipologie di Ingress che possono essere scaricati ed installati, utilizzando package manager per Kubernetes, come ad esempio Helm. Un ingress che può essere installato è  NGINX Ingress Controller. Ogni ingress ha particolari caratteristiche che lo differenziano dagli altri, ma soprattutto che possono offrire performance differenti verso i servizi stessi.

Inoltre, essendo posizionati all’interno del cluster ed essendo di fatto dei veri e propri pods, sono soggetti alle stesse restrizioni. Anche in questo caso sarà necessario utlizzare NodePort e/o LoadBalancer, ma a differenza dell’esempio precedente ci troviamo ora ad aver implementato un unico punto di ingresso configurabile ed accessibile dall’esterno. L’utilizzo di un ingressa basato sul protocollo HTTP consente di ispezionare il contenuto della richiesta ed indirizzarla verso il servizio più appropriato, tramite l’analisi dell’URL, il nome del dominio ed header. Consideriamo il manifest dell’ingress seguente:

in questo caso sono state definite due regole che consentono di intercettare /foo e /bar all’interno dell’url e di indirizzarla all’intero dei servizi foo-service e bar-service. Quello che abbiamo definito è un servizio API che in base al path inserito all’interno della URL indirizza e risponda verso un service specifico.

Installazione di Ingress

A questo, dopo aver introdotto il concetto di ingress, vediamo come sia possibile installarlo. Per poter installare nginx-ingress è possibile scaricarlo applicarlo al cluster in running con il comando:

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml

in questo l’ingress verrà scaricato ed eseguito all’interno di un pods. Un altro ingress che può essere installato è HAProxy Controller, che può essere installato utilizzando Helm, un package manager che tratterò in un prossimo post.

Una volta installato helm, è possibile effettuare il download ed il deploy del dell’ingress, tramite i comandi:

$> helm repo add haproxytech https://haproxytech.github.io/helm-charts
$> helm install haproxy-controller haproxytech/kubernetes-ingress

A questo punto è possibile verificare se l’ingress è stato eseguito correttamente, usando il comando :

$> kubectl get services

Se tutto è andato a buon fine verrà visualizzato il servizio dell’ingress running e gli indirizzi ip con il quale è esposto verso l’esterno. Da notare che HaProxy sta funzionando all’interno del cluster come un servizio di tipo NodePort che utilizza la porta 31704 ridiretta verso la porta 80 e la porta 32225 ridiretta verso la 443.

In questo caso è stata utilizzata la configurazione con un servizio di tipo NodePort, che come descritto in precedenza consente di gestire porte in un range limitato (quelle che effettivamente sono collegate all’ingress) anzichè quelle che effettivamente sono associate ai singoli servizi.

In certe situazioni potrebbe essere utile cambiare la tipologia di servizio, utilizzando LoadBalancer. Per poter mandare in esecuzione l’ingress in modalità LoadBalancer è possibile utilizzare la seguenti sintassi:

In questo post abbiamo analizzato l’ingress: un meccanismo che consente di esporre all’esterno un servizio all’interno del cluster. In realtà la configurazione si basa sull’introduzione di regole che consentono di indirizzare le richieste del cliente verso i servizi interni.