Installazione di un Load Balancer

Deployment

File di manifest ~/scripts/deploy.yml:

vim ~/scripts/deploy.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      app: hello-world
  template:            
    metadata:          
      labels:    
        app: hello-world
    spec:               
      containers:       
      - name: hello-pod 
        image: localhost:5000/myhello
        imagePullPolicy: IfNotPresent
        ports:                       
        - containerPort: 8888

Yl parametro imagePullPolicy specifica se compiere il pull dell'immagine specificata. Ha tre possibili valori:

  • IfNotPresent - se non è già stato compiuto un pull in precedenza (default)
  • Always - sempre, anche se l'immagine è già presente
  • Never - mai. Naturalmente può causare dei problemi

Creare il deployment:

kubectl apply -f ~/scripts/deploy.yml

Inspezionare il deployment:

kubectl get deploy hello-deploy
kubectl describe deploy hello-deploy

Mostrare il ReplicaSet associato:

kubectl get rs

Service

Scrivere il manifest ~/scripts/svc.yml:

vim ~/scripts/svc.yml
apiVersion: v1
kind: Service
metadata:
  name: hello-svc
  labels:
    app: hello-world
spec:
  type: NodePort
  ports:
  - port: 8888
    nodePort: 30001
    protocol: TCP
  selector:
    app: hello-world

Applicare il servizio:

kubectl apply -f ~/scripts/svc.yml

Tipi di Servizio

ClusterIP - default

  • Indirizzo IP interno al cluster, effimero
  • Tipico per i pods e i service interni

NodePort

  • Indirizzo IP interno al cluster, a livello nodi, statico

LoadBalancer

  • Indirizzo IP esterno al cluster, statico
  • Tipico per i service esterni
  • Fornito dall’implementazione del cluster, non da kubernetes (add-on)

Uso del Service

Listare i servizi:

kubectl get services
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)          AGE
hello-svc    NodePort       10.96.125.102   <none>           8888:30001/TCP   50m
kubernetes   ClusterIP      10.96.0.1       <none>           443/TCP          55m

Un servizio NodePort è visibile su tutti i nodi del cluster alla porta configurata dal settaggio nodePort.

Trovare l’indirizzo IP di un nodo:

kubectl describe node kind-worker | grep InternalIP
InternalIP:  172.19.0.3

Naturalmente il risultato può variare da questo esempio.

Connettersi al servizio su quel nodo:

curl 172.19.0.3:30001
Hello, 世界

Metallb

Per vedere un servizio da fuori del cluster serve un Load Balancer.

KinD fornisce il Metallb load balancer.

Scarichiamo i due manifest di Metallb:

cd ~/scripts

wget https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/namespace.yaml
mv namespace.yaml metallb-ns.yml

wget https://raw.githubusercontent.com/metallb/metallb/v0.12.1/manifests/metallb.yaml
mv metallb.yaml metallb-svc.yml

cd

Il primo manifest crea un namespace:

kubectl apply -f ~/scripts/metallb-ns.yml

Il secondo manifest è complesso, e istanzia tutti gli oggetti di Metallb:

kubectl apply -f ~/scripts/metallb-svc.yml 

Verificare il progresso:

kubectl get pods -n metallb-system
  • Due immagini docker vengono scaricate
  • Attendere che i pod metallb abbiano lo status di Running

ConfigMap per Metallb

Ci serve un range si indirizzi IP per metallb, e lo scopriamo col comando:

docker network inspect -f '{{.IPAM.Config}}' kind

Ritorna:

[{172.18.0.0/16  172.18.0.1 map[]} {fc00:f853:ccd:e793::/64   map[]}]

Poichè la rete 172.18.0.0/16 è visibile, decidiamo di usare il range di indirizzi 172.18.255.200-172.19.255.250

In altre occasioni può ritornare indirizzi diversi. Occorre usare quelli specifici ritornati.

Scriviamo un manifest per il ConfigMap, chiamandolo ~/scripts/metallb-configmap.yml:

vim ~/scripts/metallb-configmap.yml
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 172.18.255.200-172.18.255.250

Creare il configmap:

kubectl apply -f ~/scripts/metallb-configmap.yml

Nota

Può darsi in futuro che la rete a cui appartiene kind cambi.

In tal caso occorre editare e riapplicare il file metallb-configmap.yml

Lo si può fare in modo batch tramite la seguente procedura shell:

ipnet=$(docker network inspect -f '{{.IPAM.Config}}' kind | \
        cut -d{ -f2 | cut -d. -f1,2)
newaddr="      - ${ipnet}.255.200-${ipnet}.255.250"
sed -i "/^.*172.*/s//$newaddr/" ~/scripts/metallb-configmap.yml

Load Balancer service

Scriviamo un manifest ~/scripts/lb.yml che configura il servizio di tipo Load Balancer:

vim ~/scripts/lb.yml
apiVersion: v1
kind: Service
metadata:
  name: lb-svc
  labels:
    app: hello-world
spec:
  type: LoadBalancer
  ports:
  - port: 8888
    protocol: TCP
  selector:
    app: hello-world

Creiamo il servizio:

kubectl apply -f ~/scripts/lb.yml

Verificare la creazione del servizio:

kubectl get services
NAME         TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)          AGE
hello-svc    NodePort       10.96.125.102   <none>           8888:30001/TCP   74m
kubernetes   ClusterIP      10.96.0.1       <none>           443/TCP          79m
lb-svc       LoadBalancer   10.96.109.230   172.19.255.200   8888:31740/TCP   55m

Provare a connettersi da qualsiasi macchina sul Docker cluster:

curl 172.18.255.200:8888
Hello, 世界

Proviamo a vedere il servizio da una macchina esterna al cluster.

Lanciare un alpine, esterno ma sulla stessa rete del cluster:

docker run -ti --rm --privileged --net kind alpine sh

Aggiungere curl e provare:

apk add curl
curl 172.18.255.200:8888
``