IBM Cloud: Kubernetes e approccio a container

IBM CLOUD: Come realizzare un cluster Kubernetes

Questo articolo è stato scritto da Raffaele Mandese, Nel Maggio 2019 è diventato CTO della startup Fortunito. In questa realtà ha effettuato un importante lavoro di migrazione in ambiente cloud IBM trasferendo quasi tutti i servizi dall’ infrastruttura classica a Kubernetes.

Questo articolo nasce in collaborazione con Michele Grossi (MICHELE GROSSI) e Massimo Loaldi (Massimo Loaldi), IT Solution Architect di IBM Italia.

IBM Cloud è la piattaforma cloud di IBM che aiuta gli sviluppatori a realizzare e ad eseguire applicazioni e servizi innovativi.

Kubernetes (Conosciuto anche come k8s o “kube”) è uno strumento open source di orchestrazione e gestione di container che permette di automatizzare molte operazioni manuali come il deployment di container, la gestione, la scalabilità e l’eliminazione. Attraverso immagini Docker è possibile realizzare una infrastruttura scalabile e altamente performante. Esso può essere configurato sia on-premise, sia su cloud privato, sia su cloud pubblico e ciò rende Kubernetes una piattaforma ideale per l’hosting di applicazioni cloud native scalabili. IBM è uno dei provider più importanti che offre, fra le tante soluzioni, anche la possibilità di realizzare ambienti o cluster scalabili attraverso le piattaforme “Kubernetes” e “Openshift”.

Nello specifico quest’oggi capiremo come realizzare un cluster kubernetes su IBM Cloud.

Requisito necessario per il proseguo della lettura e per la creazione delle risorse è essere in possesso dell’account IBM Cloud. Se non si disponesse dell’account seguire il tutorial per la creazione di un free account.

Dopo aver fatto accesso ad IBM Cloud (cloud.ibm.com/login) è possibile recarsi nel menù in alto a sinistra, successivamente alla voce Kubernetes e poi su cluster.

Image for post
Image for post

La pagina che si aprirà ci darà la possibilità di creare un Cluster Kubernetes semplicemente cliccando sul pulsante + Create cluster, come indicato nell’immagine sottostante.

Image for post
Image for post

Dopo aver premuto il tasto create cluster si verrà reindirizzati nella pagina di creazione di un cluster Kubernetes oppure di un cluster Openshift. Kubernetes è una soluzione più economica, adatta sia alle piccole che alle grandi imprese, ha una Dashboard chiara, ed è supportata da una community tecnica. Openshift invece è uno strumento enterprise-ready, è economicamente più oneroso, ha un supporto RedHat/IBM dedicato e offre un tool per la gestione della continuos integration e continuos delivery (DevOps CI/CD). Il cluster può essere configurato con Infrastruttura classica oppure infrastruttura VPC. L’infrastruttura classica (Supporta macchine virtuali e server bare metal) e includono tutte le collaudate e solide funzioni di IBM Cloud Kubernetes Service per il calcolo, la rete e l’archiviazione.

Per Infrastruttura VPC si intende Virtual Private cloud (Supporta macchine virtuali) offre la sicurezza di un ambiente cloud privato con la scalabilità dinamica di un cloud pubblico, con la capacità di distribuire i tuoi nodi di lavoro del cluster come server virtuali. Inserire il nome del cluster (Nome identificativo) l’ubicazione (Location) del cluster.

L’ultimo parametro da inserire per ultimare la configurazione sono le istanze, la vera e propria potenza computazionale del nostro cluster. La configurazione meno performante è 2vCPU e 4Gb di RAM la configurazione più performante in assoluto è 64vCPU e 512Gb di RAM. Selezionare la configurazione che meglio si avvicina alle esigenze di business. È possibile in qualsiasi momento aggiungere, eliminare o modificare le istanze.

Dopo aver premuto il pulsante crea partirà il processo di creazione del nostro cluster con la configurazione dei nodi da noi scelti. Al termine la situazione che avremo nella sezione Cluster di Kubernetes in IBM Cloud sarà simile all’immagine seguente:

Image for post
Image for post

Per poter ottenere informazioni sul cluster appena creato basterà semplicemente cliccare sul nome nell’elenco:

Image for post
Image for post

Come si evince dall’immagine qui sopra sono presenti le voci di menù:

  • Accesso: In questa sezione vengono indicate le modalità di accesso al cluster kubernetes direttamente dalla nostra CLI (Command Line Interface).
  • Panoramica: La sezione panoramica è evidenziata nell’immagine qui sopra e contiene le informazioni di base del nostro cluster tra cui l’id, la zona, lo stato e l’endpoint pubblico.
  • Nodi di lavoro: Questa sezione permette di vedere lo stato dei nodi del nostro cluster e ci da la possibilità̀ di eseguire operazioni quali: eliminazione, aggiunta o aggiornamento.
  • Pool di lavoro: Allo stesso modo dei nodi è possibile gestire il pool di lavoro.
  • Componenti aggiuntivi: È possibile aggiungere al cluster dei componenti aggiuntivi come l’autoscaler, il proxy, Istio oppure il Kubernetes terminal
  • DevOps: Configurazione del Continuos Delivery e Continuos Integration

In alto a destra è presente un pulsante blu con il nome Kubernetes Dashboard, esso permette di raggiungere la dashboard del nostro cluster in modo da avere un overview dei PODs, dei deployments, dei Jobs, ecc..

Image for post
Image for post

Docker registry è il registro che memorizza, distribuisce e gestisce le immagini di Docker; è paragonabile a un repository, ma basato sulle immagini Docker e quindi contenente immagini. IBM offre la possibilità di poter creare gratuitamente un nostro docker registry che sia accessibile dal nostro cluster kubernetes e dove poter inserire le immagini docker che preferiamo. Il servizio è denominato IBM Cloud™ Container Registry

Per poter creare un registry possiamo seguire la guida di IBM descritta al link:

Per poter aggiungere una immagine docker, bisognerà anzitutto installare docker sulla propria macchina in locale, successivamente creare un’immagine sempre in locale e sarà necessario taggarla usando la naming convention del nostro registry (informazione reperibile nella dashboard kubernetes) e eseguire una push sul nostro cloud registry.

Un pod è un’istanza kubernetes che incapsula uno o più container docker. In altre parole, un pod è una istanza di un servizio. È possibile creare un pod sulla dashboard kubernetes attraverso un particolare file di configurazione chiamato yaml, che conterrà le informazioni sull’ immagine docker da cui attingere informazioni e risorse.

Questo è un esempio di file yaml per un pod che istanzia un container con un microservizio Java.

apiVersion: v1 kind: Pod metadata:

name: simple-rest-service labels:

app: simple-rest-service namespace: default

spec:
containers:
- name: simple-rest-service

image: uk.icr.io/kubernetes-registry/microservice-java:1

ùAnalizzando questo POD vediamo che ciò che viene richiesto sono le apiVersion, il kind, il nome del pod definito nel name dentro il tag metadata, e la labels. Il tag spec è fondamentale perché al suo interno è possibile specificare i container docker da istanziare attraverso il nome e l’immagine (con la versione). Come si evince dal file Yaml l’immagine docker che si sta prendendo in esame è presente container registry di IBM.

Il file Yaml descritto qui sopra può essere inserito in Kubernetes in due modi differenti:

  • IBM Cloud Kubernetes Dashboard:
Image for post
Image for post

Recandosi sulla dashboard in alto a destra è presente un simbolo “+” di colore Blu, cliccandolo è possibile inserire direttamente il codice java del file YAML. Se l’upload non ha dato errori allora è possibile recarsi dalla dashboard nella sezione PODs e visualizzarne il contenuto dettagliatamente (dal consumo di memoria a quello di cpu ai dettagli sulla rete e sugli eventi).

Image for post
Image for post

È possibile inoltre, tornando nella dashboard e successivamente nella sezione logs, visionare i logs del nostro POD, per monitorare lo stato del nostro servizio.

Image for post
Image for post
  • Linea di comando:

Tornando all’istanza Kubernetes su IBM Cloud, ci si può recare nella tab Accesso e seguire la guida step by step che ci permette, utilizzando il comando kubectl (kubectl apply -f <path del file>), di accedere al cluster. Altri comandi utili sono:

  • kubectl get pods: Restituisce invece l’elenco dei pods attivi sul nostro cluster.
  • kubectl top pods: Evidenzia il consumo di CPU e RAM dei nostri pod.
  • kubectl get nodes: È possibile visionare i nodi del cluster.
  • kubectl top nodes: Evidenzia il consumo di CPU e RAM di ogni singolo nodo del cluster.
  • kubectl describe pod <nome-del-pod>: Esprime il dettaglio dello specifico POD.

Per ulteriori informazioni sui pods ecco la guida di riferimento.

Dopo aver capito che il POD è un’istanza di un servizio, la domanda che sorge spontanea è come accedere e configurare tale servizio?

Un pod vive dentro kubernetes, in un ambiente chiuso e isolato. Per permettere a un pod di essere contattato dall’ esterno è necessario creare una interfaccia, uno strumento che mappi le porte esposte dal nostro pod con i vari nodi del nostro cluster, o con un load balancer, in modo tale da permettere ad un traffico esterno di poterlo raggiungere.

Questo è possibile attraverso la creazione di un Service. I principali tipi di service sono:

  • Cluster IP: Il Cluster Ip è il service kubernetes di default. Mappa le porte dei pod, ma il sistema continua però ad essere isolato. Sarebbe possibile poter contattare il service solo attraverso un proxy, e questo magari può essere il caso d’uso ad esempio per una attività di debugging.
Image for post
Image for post
  • Node Port: Il NodePort è un tipo di configurazione del service che permette di aprire una porta che va da 30000 a 32767 a tutti i nodi del cluster. In questo modo, contattando qualsiasi nodo del cluster su quella porta, viene fatto un reverse proxy sul servizio.
Image for post
Image for post
  • Load Balancer: Il LoadBalancer è un tipo di configurazione invece che permette di contattare un service tramite un loadbalancer.

Il service può essere creato sempre attraverso un file Yaml, come nell’esempio sottostante:

apiVersion: v1 kind: Service metadata:

name: simple-rest-service spec:

selector:
app: simple-rest-service

type: NodePort ports:
- name: http

port: 80 targetPort: 80 nodePort: 30001 protocol: TCP

Come evince nel service qui sopra, è stata mappata la porta 80 del container all’ interno del POD con la porta 80 del service e è stato esposto la nodePort 30001 perché questo service è di tipo NodePort. Molto importante è il selector definito nelle spec. Questo selector indica a quali pod si deve agganciare questo service.

Il service si può creare con lo stesso procedimento utilizzato per il POD, con il tasto “+” in alto a destra, oppure utilizzando la linea di comando, nello specifico il comando:

  • kubectl apply -f <nome-del-service-yaml>

Successivamente per avere informazioni sul service digitare:

  • kubectl describe service <nome- del-service>

Un Deployment è una configurazione del nostro cluster kubernetes per un POD che ci permette di definire alcune caratteristiche dell’ istanza, in particolare modo il numero di replicas della stessa. Una replicas rapprenta il numero di istanze attive del nostro POD. Il deployment ha il compito di monitorare il comportamento delle nostre istanze, e qualora qualcuna di queste dovesse “crashare” oppure non funzionare correttamente, ha il compito di “riportare up l’istanza” secondo i parametri configurati proprio nei replicas.

Anche il deployment deve essere creato tramite un file Yaml, qui di seguito un esempio di deployment:

apiVersion: apps/v1 kind: Deployment metadata:

name: simple-rest-service-deployment

namespace: default spec:

selector: matchLabels:

app: simple-rest-service replicas: 1
template:

metadata: labels:

app: simple-rest-service spec:

containers:
- name: simple-rest-service

image: uk.icr.io/kubernetes-registry/microservice- java:3

resources: requests:

memory: “100Mi”

cpu: “100m” limits:

memory: “200Mi” cpu: “200m”

In questo deployment stato definito un numero di replicas pari a 1. Quindi se quella istanza dovesse “crashare” per qualche motivo, questo deployment ha il compito di reinstanziare il pod.

In questo deployment è stato configurato un pod con delle resources. Le “resources” sono le risorse che servono all’ istanza per funzionare correttamente. Le “resources” sono costituite da 2 elementi principali: le “requests” e i “limits”.

Le “requests” sono le risorse richieste all’ istanza per poter essere eseguita su un nodo. Se il nodo non ha le risorse definite nelle “requests”, quest’ultimo non può istanziare il pod. I “limits” invece rappresenta le risorse limite che l’istanza può richiedere al nodo.

E’ importante specificare questi parametri quando si vuole attivare un sistema di autoscaling dei pod.

Per caricare un deployment si utilizza sempre il comando:

  • kubectl apply -f “<nome-del-file-yaml-di-deployment>

Per poter scalare automaticamente kubernetes offre un servizio che si chiama Horizonal pod autoscaler. Questo servizio permette di scalare automaticamente i deployment in base all’ utilizzo delle risorse. Ad esempio si potrebbe impostare che i pod scalassero automaticamente quando raggiungono il 30% di utilizzo della CPU settata nelle requests resources oppure quando raggiungono il 40% di utilizzo della RAM.

Un horizontal autoscaler si crea sempre attraverso un file yaml di questo tipo:

apiVersion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata:

name: simple-rest-service-autoscale spec:

maxReplicas: 2 minReplicas: 1 scaleTargetRef:

apiVersion: apps/v1
kind: Deployment
name: simple-rest-service-deployment

targetCPUUtilizationPercentage: 30

Come potete vedere in questo HorizontalPodAutoscaler è stato definito un numero minimo di replicas per il deployment “simple-rest-service-deployment” pari a 1 e un numero massimo di replicas pari a 2 che vengono istanziati quando il pod raggiunge il 30% di consumo della CPU “requests”. Allo stesso modo possiamo vedere come si può impostare lo stesso sulla base del consumo della RAM (Superiore al 40%) per lo stesso POD:

apiVersion: autoscaling/v1 kind: HorizontalPodAutoscaler metadata:

name: simple-rest-service-autoscale spec:

maxReplicas: 2 minReplicas: 1 scaleTargetRef:

apiVersion: apps/v1
kind: Deployment
name: simple-rest-service-deployment

metrics:
- type: Resource

resource:
name: memory targetAverageUtilization: 40

È possibile creare un sistema che ci permetta di contattare il nostro cluster kubernetes attraverso un endpoint e mappare dei path su cui rispondano i vari services creati nel cluster. Questa operazione è gestita dalle Ingress, un file Yaml di esempio è il seguente:

apiVersion: extensions/v1beta1 kind: Ingress
metadata:

name: simple-web-ingress spec:

rules:
- host:
www.simple-rest-service.local

http: paths:
- path: /

backend:
serviceName: simple-rest-service servicePort: 80ù

Come si può evince la configurazione qui sopra mappa l’endpoint (www.simple-rest-service.local/) al service simple- rest-service sulla porta 80.

Il file Yaml è da caricarsi sempre con il comando:

  • kubectl apply -f <nome-del-file-yaml-ingress>

Per ulteriori informazioni rimando alla documentazione ufficiale IBM: https://cloud.ibm.com/docs/containers?topic=containers-ingress

IBM Mette a disposizione tantissimi altri servizi applicabili one click sul cluster kubernetes. L’elenco completo dei servizi aggiuntivi è usufruibile al link: https://cloud.ibm.com/kubernetes/helm

La documentazione ufficiale di kubernetes: https://kubernetes.io/docs/concepts/

La documentazione ufficiale IBM Cloud su kubernetes: https://cloud.ibm.com/docs/containers?topic=containers-getting-started

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store