Nell’articolo precedente abbiamo installato e configurato un cluster kubernetes su Ubuntu, formato da un master e due workers.

In questo articolo invece elenco i comandi per iniziare a prendere dimestichezza con kubernetes e qualche esempio pratico.

Comandi utili sul master

kubectl cluster-info
kubectl config view
kubectl get componentstatuses
kubectl get nodes
kubectl get namespace

kubectl get events
kubectl top nodes
kubectl top pods

# -A sta per --all-namespaces
kubectl get deployments -A 
kubectl get pods -A
kubectl get services -A
kubectl get pvc -A # persistent volume claims
kubectl get pv # persistent volume

# a qualsiasi comando è possibile aggiungere alla fine "-o wide" per avere maggiori informazioni. con "-o json" oppure "-o yaml" vengono stampate le informazioni complete nel formato specificato.

# al posto di get è utile utilizzare anche describe o delete o explain

# aggiungendo watch davanti si può vedere in tempo reale
watch kubectl get pods -A

# restart deployment
kubectl rollout restart deployment deplyment-name -n namespace-name

# si può filtrare per namespace con --namespace=namespace_name (o -n ns-name)

# creazione ed eliminazione namespaces
kubectl create namespace <insert-namespace-name-here>
kubectl delete namespaces <insert-some-namespace-name>

# riporto anche qui per comodità il comando per generare il token per la dashboard
kubectl -n kubernetes-dashboard create token admin-user

# context: cambiare il namespace di default:

# creare il nuovo context assegnandogli un nome ed il namespace di riferimento (viene aggiunto al file di configurazione utilizzato es: ~/.kube/config)

kubectl config set-context new-context --namespace=my-namespace

# attivare il nuovo context
kuvectl config use-context new-context

# aggiungere label al pod 
kubectl label pods <pod-name> color=red

# rimuovere label
kubectl labep pods <pod-name> color-

# logs
kubectl logs <pod-name>

# per entrare nella shell di un pod (prendere il nome da get pods)
kubectl exec -it <podName> -n test-namespace -- bash

# in assenza di shell ci si può attaccare al processo in esecuzione:
kubectl attach -it <podName>

Link utili per approfondimenti sui comandi di kubectl:

Creazione di un deployment da riga di comando

# creo il namespace
kubectl create namespace test-namespace
# oppure 
kubectl create ns test-namespace


# avvio un deployment con due repliche nel namespace appena creato dall'immagine nginx da dockerhub
kubectl create deployment nginx --image=nginx -n=test-namespace --replicas=2

# controllo se i due pods vengono avviati
watch kubectl get pods --all-namespaces

# descrizione del deployment
kubectl describe deployments nginx --namespace=test-namespace

# attivo un servizio nodeport che espone le porte dei nodi
kubectl create service nodeport nginx --tcp=80:80 --namespace=test-namespace

# verifico il servizio appena creato per ottenere la porta
kubectl get services --namespace=test-namespace

# posso accedere al servizio dalla porta appena ottenuta di ogni nodo
curl <nodeIP>:<port>

# elimino il deployment (posso evitare questo comando se voglio eliminare tutto il namespace con il comando successivo)
kubectl delete deployment nginx --namespace=test-namespace

# elimino l'intero namespace e tutto il contenuto
kubectl delete namespaces test-namepsace

Stesso esempio di prima, ma con file yaml di deployment.

Crea un file nginx.yaml con questo contenuto:

---
apiVersion: v1
kind: Namespace
metadata:
  name: test-namespace
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: test-namespace
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx
        ports:
        - containerPort: 80
---
kind: Service
apiVersion: v1
metadata:
  labels:
    name: node-server-nodeport
  name: node-server-nodeport
  namespace: test-namespace
spec:
  type: NodePort
  selector:
    app: nginx
  ports:
    - protocol: TCP
      nodePort: 32555
      port: 80
      targetPort: 80

Il file appena creato è suddiviso in 3 sezioni e si occuperà di creare:

  • il namespace test-namespace
  • due repliche dell’immagine di nginx
  • il servizio NodePort che espone la porta 32555 (se omessa, viene aperta una porta random)

Applicare il deployment con:

kubectl apply -f ./nginx.yaml

# NB: passando una directory invece del file, vengono applicati tutti i manifest nella directory
# NB: è possibile passare anche un url invece di un file

Replicas & Scaling

Nell’esempio con manifest yaml, abbiamo già settato per la nostra app 2 repliche, ed abbiamo avviato pertanto 2 pods nginx. Possiamo modificare questo valore (o qualsiasi altro parametro del nostro manifesto ed applicarlo semplicemente rilanciando il comando kubectl apply, oppure direttamente dalla shell con il comando kubectl scale:

# modifica il file yaml e poi applica:
kubectl apply -f ./nginx.yaml

# scala l'applicazione direttamente da shell
kubectl scale --replicas=4 deployment/nginx -n test-namespace

# NB: Scalando l'applicazione con il secondo metodo, applicando nuovamente il file yaml senza modificarlo, si torna alla situazione precedente.

Rollout & revert updates

Con lo stesso sistema delle repliche, è possibile aggiornare (ma anche fare il revert) le immagini dei pods in produzione, semplicemente modificando il manifesto yaml, ad esempio passando dall’immagine nginx:1.0 alla nginx:1.1

Applicando il manifesto, verranno sostituiti tutti i pods con la nuova versione senza mandare l’applicazione offline. Se qualcosa è andato storto, si può revertare ripristinando l’immagine precedente.

La history dei rollout può essere ottenuta con:

kubectl rollout history deployment/nginx -n test-namespace

deployment.apps/nginx
REVISION  CHANGE-CAUSE
1         <none>
4         <none>
5         <none>

# per vedere il dettaglio di una revisione:

kubectl rollout history deployment/nginx -n test-namespace --revision=4

deployment.apps/nginx with revision #4
Pod Template:
  Labels:       app=nginx
        pod-template-hash=7b6857d997
  Containers:
   nginx:
    Image:      sampozzo/nginx:1.0
    Port:       80/TCP
    Host Port:  0/TCP
    Environment:        <none>
    Mounts:     <none>
  Volumes:      <none>

LoadBalancer Service

kubectl expose deployment nginx --type=LoadBalancer --port=80 --target-port=80 --name=nginx-load-balancer -n test-namespace

kubectl describe services nginx-load-balancer -n test-namespace

Name:                     nginx-load-balancer
Namespace:                test-namespace
Labels:                   <none>
Annotations:              <none>
Selector:                 app=nginx
Type:                     LoadBalancer
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.105.45.38
IPs:                      10.105.45.38
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  32488/TCP
Endpoints:                10.244.205.207:80,10.244.35.79:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

kubectl delete services nginx-load-balancer -n test-namespace

TO BE CONTINUED…