Tutorial > Come creare un cluster Kubernetes con Kubeadm e Ansible su Ubuntu 20.04

Come creare un cluster Kubernetes con Kubeadm e Ansible su Ubuntu 20.04

Pubblicato il: 27 ottobre 2020

Kubernetes Ubuntu Web Hosting

Introduzione

Kubernetes è una piattaforma open source, sviluppata attivamente da una comunità in tutto il mondo, che permette la gestione e l'orchestrazione di container di applicazioni su larga scala.

Nel seguente tutorial utilizzeremo la usa ultima versione, configurando un cluster Kubernetes da zero e utilizzando il software Ansible per l'automazione delle procedure e il tool Kubeadm per la creazione dei cluster su un server Ubuntu 20.04.

A condizione che i server nel cluster dispongano delle risorse CPU e RAM sufficienti per le applicazioni da far girare, al termine di questa guida avrai un cluster pronto per eseguire applicazioni containerizzate. Prima di procedere con questo tutorial, assicurati quindi di disporre di almeno due macchine worker, e una macchina master con almeno 2 CPU in grado di lavorare correttamente con le macchine worker.

Per prima cosa dovrai connetterti al tuo server mediante SSH. Se non l’hai ancora fatto, ti consigliamo di seguire la nostra guida per connetterti in sicurezza con il protocollo SSH. In caso di server locale puoi passare al punto successivo e aprire il terminale del tuo server.

Installazione di Ansibile

Per procedere con l’installazione di Ansibile, aggiorna prima i pacchetti di sistema tramite i comandi:

sudo apt update

Quindi procedi installando il software necessario:

sudo apt install software-properties-common -y
sudo apt install ansible -y

Dopo qualche secondo, Ansibile dovrebbe essere pronto per essere utilizzato.

Configurazione accesso SSH

Per permettere ad Ansibile di lavorare correttamente su nodi remoti, è necessario aggiungere sui server di destinazione le chiavi SSH, in modo da garantire l'accesso senza richiesta password.

Genera prima le due chiavi (privata e pubblica) attraverso il comando:

# ssh-keygen -t rsa

Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:

Come mostrato sopra, ti verranno richieste delle password, che puoi lasciare tranquillamente vuote.

Una volta completato, puoi inviare la chiave pubblica sui server remoti utilizzando il comando “ssh-copy-id”:

# ssh-copy-id root@IP_WORKER_1

# ssh-copy-id root@IP_WORKER_2

# ssh-copy-id root@IP_MASTER

Per ogni macchina configurata, inserisci le credenziali di accesso quando richieste.

Configurazione del nodo master

Crea una directory chiamata “kube-cluster” nella directory home della tua macchina master:

mkdir ~/kube-cluster
cd ~/kube-cluster

Per tutto il tutorial sarà questa la directory per il tuo spazio di lavoro e conterrà tutti i tuoi playbook Ansible. Sarà anche la directory all'interno della quale eseguirai tutti i comandi locali.

Crea un file di “inventario”, chiamato hosts, usando nano oppure l’editor di testo che preferisci:

nano ~/kube-cluster/hosts

Aggiungi il seguente testo al file, che specificherà le informazioni sulle macchine remote del tuo cluster:

[masters]
master ansible_host=[IP_MASTER] ansible_user=root

[workers]
worker1 ansible_host=[IP_WORKER_1] ansible_user=root
worker2 ansible_host=[IP_WORKER_2] ansible_user=root

[all:vars]
ansible_python_interpreter=/usr/bin/python3

I file di inventario in Ansible sono utilizzati per specificare le informazioni sul server: indirizzi IP, utenti remoti e raggruppamenti di server da utilizzare come singola unità per l'esecuzione dei comandi. In questo tutorial abbiamo aggiunto due gruppi Ansible (master e worker) specificando la struttura logica del tuo cluster.

Nel gruppo master, è presente una voce del server denominata "master" che elenca l'IP del nodo master (IP_MASTER) e specifica che Ansible deve eseguire comandi remoti come amministratore di sistema (utente root). Nel gruppo di lavoro, ci sono due voci per i server di lavoro (worker1 e worker2) che specificano anche ansible_user come root.

L'ultima riga del file dice ad Ansible di utilizzare gli interpreti Python 3 dei server remoti per le sue operazioni di gestione.

Salva e chiudi il file dopo aver aggiunto il testo.

Configurazione dell’utente principale

Ora dovrai creare un utente non root con privilegi sudo su tutti i server in modo che tu possa accedere manualmente tramite SSH come utente non privilegiato.

L'utilizzo di un utente che non sia privilegiato per attività tipiche che avvengono durante la manutenzione di un cluster, riduce al minimo il rischio di eseguire involontariamente operazioni pericolose o di modificare o eliminare file importanti.

Crea un file chiamato initial.yml nell'area di lavoro:

nano initial.yml

Aggiungi quindi il seguente contenuto:

- hosts: all
  become: yes
  tasks:
    - name: create the 'ubuntu' user
      user: name=ubuntu append=yes state=present createhome=yes shell=/bin/bash

    - name: allow 'ubuntu' to have passwordless sudo
      lineinfile:
        dest: /etc/sudoers
        line: 'ubuntu ALL=(ALL) NOPASSWD: ALL'
        validate: 'visudo -cf %s'

    - name: set up authorized keys for the ubuntu user
      authorized_key: user=ubuntu key="{{item}}"
      with_file:
        - ~/.ssh/id_rsa.pub

Questo playbook ha il compito di creare l'utente non root "ubuntu", configurare il file "sudoers" per consentire all'utente "ubuntu" di eseguire i comandi sudo senza una richiesta di password.

Inoltre si occupa di aggiungere la chiave pubblica nella tua macchina locale (di solito ~/.ssh/id_rsa.pub) all'elenco delle chiavi autorizzate dell'utente "ubuntu" remoto. Ciò ti consentirà di accedere tramite SSH a ciascun server come utente "ubuntu".

Salva e chiudi il file dopo aver aggiunto il testo.

Successivamente, esegui il playbook eseguendo localmente:

ansible-playbook -i hosts initial.yml

Il comando verrà completato entro pochissimi minuti. Al termine, vedrai un output di questo tipo:

Output
PLAY [all] ****

TASK [Gathering Facts] ****
ok: [master]
ok: [worker1]
ok: [worker2]

TASK [create the 'ubuntu' user] ****
changed: [master]
changed: [worker1]
changed: [worker2]

TASK [allow 'ubuntu' user to have passwordless sudo] ****
changed: [master]
changed: [worker1]
changed: [worker2]

TASK [set up authorized keys for the ubuntu user] ****
changed: [worker1] => (item=ssh-rsa AAAAB3...)
changed: [worker2] => (item=ssh-rsa AAAAB3...)
changed: [master] => (item=ssh-rsa AAAAB3...)

PLAY RECAP ****
master                     : ok=5    changed=4    unreachable=0    failed=0   
worker1                    : ok=5    changed=4    unreachable=0    failed=0   
worker2                    : ok=5    changed=4    unreachable=0    failed=0   

La configurazione preliminare è completa.

Creazione del cluser Kubernetes

Ora dovrai installare i pacchetti richiesti da Kubernetes a livello di sistema operativo  con il gestore di pacchetti di Ubuntu.

Crea un file chiamato kube-dependencies.yml nell'area di lavoro:

nano ~/kube-cluster/kube-dependencies.yml

Aggiungi le seguenti istruzioni al file per installare questi pacchetti sui tuoi server:

- hosts: all
  become: yes
  tasks:
   - name: install Docker
     apt:
       name: docker.io
       state: present
       update_cache: true

   - name: install APT Transport HTTPS
     apt:
       name: apt-transport-https
       state: present

   - name: add Kubernetes apt-key
     apt_key:
       url: https://packages.cloud.google.com/apt/doc/apt-key.gpg
       state: present

   - name: add Kubernetes' APT repository
     apt_repository:
      repo: deb http://apt.kubernetes.io/ kubernetes-xenial main
      state: present
      filename: 'kubernetes'

   - name: install kubelet
     apt:
       name: kubelet
       state: present
       update_cache: true

   - name: install kubeadm
     apt:
       name: kubeadm
       state: present

- hosts: master
  become: yes
  tasks:
   - name: install kubectl
     apt:
       name: kubectl
       state: present

Il playbook appena incollato ha il compito di:

  • Installare Docker, il runtime del contenitore;
  • Installare apt-transport-https, permettendoti di aggiungere fonti HTTPS esterne all'elenco delle fonti di APT;
  • Aggiungere la chiave apt del repository APT di Kubernetes per la verifica della chiave;
  • Aggiungere il repository APT di Kubernetes all'elenco delle origini APT dei server remoti;
  • Installare Kubelet e Kubeadm.

Salva e chiudi il file quando hai finito.

Successivamente, esegui il playbook eseguendo localmente:

ansible-playbook -i hosts kube-dependencies.yml

Al termine, vedrai un output di questo tipo:

Output
PLAY [all] ****

TASK [Gathering Facts] ****
ok: [worker1]
ok: [worker2]
ok: [master]

TASK [install Docker] ****
changed: [master]
changed: [worker1]
changed: [worker2]

TASK [install APT Transport HTTPS] *****
ok: [master]
ok: [worker1]
changed: [worker2]

TASK [add Kubernetes apt-key] *****
changed: [master]
changed: [worker1]
changed: [worker2]

TASK [add Kubernetes' APT repository] *****
changed: [master]
changed: [worker1]
changed: [worker2]

TASK [install kubelet] *****
changed: [master]
changed: [worker1]
changed: [worker2]

TASK [install kubeadm] *****
changed: [master]
changed: [worker1]
changed: [worker2]

PLAY [master] *****

TASK [Gathering Facts] *****
ok: [master]

TASK [install kubectl] ******
ok: [master]

PLAY RECAP ****
master                     : ok=9    changed=5    unreachable=0    failed=0   
worker1                    : ok=7    changed=5    unreachable=0    failed=0  
worker2                    : ok=7    changed=5    unreachable=0    failed=0  

Dopo l'esecuzione, Docker, Kubeadm e Kubelet saranno installati su tutti i server remoti.

Kubectl non è un componente richiesto ed è necessario solo per eseguire i comandi del cluster. Installarlo solo sul nodo master ha senso in questo contesto, poiché eseguirai i comandi Kubectl solo dal master.

Tuttavia i comandi Kubectl possono essere eseguiti da qualsiasi nodo di lavoro o da qualsiasi macchina su cui può essere installato e configurato per puntare a un cluster.

Tutte le dipendenze di sistema sono ora installate.

A questo punto dovrai configurare il nodo master e inizializzare il cluster, prima di creare qualsiasi playbook.

Crea un playbook Ansible denominato master.yml sul tuo computer locale:

nano ~/kube-cluster/master.yml

Aggiungi la seguente riproduzione al file per inizializzare il cluster e installare Flannel:

- hosts: master
  become: yes
  tasks:
    - name: remove swap
      shell: "swapoff -a"

    - name: initialize the cluster
      shell: kubeadm init --pod-network-cidr=10.244.0.0/16 >> cluster_initialized.txt
      args:
        chdir: $HOME
        creates: cluster_initialized.txt

    - name: create .kube directory
      become: yes
      become_user: ubuntu
      file:
        path: $HOME/.kube
        state: directory
        mode: 0755

    - name: copy admin.conf to user's kube config
      copy:
        src: /etc/kubernetes/admin.conf
        dest: /home/ubuntu/.kube/config
        remote_src: yes
        owner: ubuntu

    - name: install Pod network
      become: yes
      become_user: ubuntu
      shell: kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml >> pod_network_setup.txt
      args:
        chdir: $HOME
        creates: pod_network_setup.txt

Nel dettaglio:

  • Con l'esecuzione della prima attività Kubeadm "init" stai inizializzando il cluster, e passando l'argomento --pod-network-cidr = 10.244.0.0 / 16 specifichi la sottorete privata da cui verranno assegnati gli IP del pod. Flannel utilizza la sottorete precedente per impostazione predefinita: stai dicendo a Kubeadm di utilizzare la stessa sottorete.
  • Con la seconda attività stai avviando la creazione di una directory .kube in / home / ubuntu, che conterrà le informazioni di configurazione come i file della chiave amministratore, necessari per connettersi al cluster, e l'indirizzo API del cluster.
  • Con la terza attività stai copiando il file /etc/kubernetes/admin.conf che è stato generato da kubeadm init nella directory home dell'utente non root. Ciò ti consentirà di utilizzare kubectl per accedere al cluster appena creato.
  • Con la quarta attività stai eseguendo Kubectl apply per installare Flannel. kubectl apply -f descriptor. [yml | json] è la sintassi per dire a Kubectl di creare gli oggetti descritti nel file descrittore. [yml | json]. Il file kube-flannel.yml contiene le descrizioni degli oggetti necessari per configurare Flannel nel cluster.

Salva e chiudi il file quando hai finito.

Esegui il playbook localmente, lanciando il seguente comando:

ansible-playbook -i hosts master.yml

Al termine, vedrai un output di questo tipo:

PLAY [master] ****

TASK [Gathering Facts] ****
ok: [master]

TASK [initialize the cluster] ****
changed: [master]

TASK [create .kube directory] ****
changed: [master]

TASK [copy admin.conf to user's kube config] *****
changed: [master]

TASK [install Pod network] *****
changed: [master]

PLAY RECAP ****
master                     : ok=5    changed=4    unreachable=0    failed=0  

Come controllo dello stato del nodo master, utilizza questo comando:

ssh ubuntu@master_ip

Una volta all'interno del nodo master, esegui:

kubectl get nodes

Ora vedrai il seguente output:

NAME STATUS ROLES AGE VERSION master Ready master 1d v1.14.0

L'output indica che tutte le attività di inizializzazione sono state completate dal nodo master, che si trova in uno stato di ready, sicché è pronto per iniziare ad accettare i nodi di lavoro e ad eseguire le attività inviate al server API.

Configurazione dei nodi worker

L'aggiunta di lavoratori al cluster implica l'esecuzione di un singolo comando su ciascuno di essi.

Questo comando include le informazioni necessarie sul cluster, come indirizzo IP, porta dell'API Server del master e un token sicuro. I nodi che passano nel token sicuro potranno unirsi al cluster.

Torna al tuo spazio di lavoro e crea un playbook denominato workers.yml:

nano ~/kube-cluster/workers.yml

Per aggiungere i worker al cluster, aggiungi la seguente configurazione al file:

- hosts: master
  become: yes
  gather_facts: false
  tasks:
    - name: get join command
      shell: kubeadm token create --print-join-command
      register: join_command_raw

    - name: set join command
      set_fact:
        join_command: "{{ join_command_raw.stdout_lines[0] }}"

- hosts: workers
  become: yes
  tasks:
    - name: remove swap
      shell: "swapoff -a"

    - name: join cluster	
      shell: "{{ hostvars['master'].join_command }} >> node_joined.txt"
      args:
        chdir: $HOME
        creates: node_joined.txt

Questo playbook contiene le istruzioni che devono essere eseguite sui nodi worker.

Con la seconda riproduzione hai un'unica attività che esegue il comando join su tutti i nodi di lavoro.

Al termine di questa attività, i due nodi di lavoro faranno parte del cluster.

Salva e chiudi il file quando hai finito ed esegui il playbook eseguendo localmente:

ansible-playbook -i hosts workers.yml

Al termine, vedrai un output di questo tipo:

Output
PLAY [master] ****

TASK [get join command] ****
changed: [master]

TASK [set join command] *****
ok: [master]

PLAY [workers] *****

TASK [Gathering Facts] *****
ok: [worker1]
ok: [worker2]

TASK [join cluster] *****
changed: [worker1]
changed: [worker2]

PLAY RECAP *****
master                     : ok=2    changed=1    unreachable=0    failed=0   
worker1                    : ok=2    changed=1    unreachable=0    failed=0  
worker2                    : ok=2    changed=1    unreachable=0    failed=0  

Con l'aggiunta dei nodi di lavoro, il tuo cluster è ora completamente configurato e funzionale, con i lavoratori pronti per eseguire carichi di lavoro.

Verifica il corretto funzionamento dei cluster appena aggiunti, utilizzando il tool Kubectl, come effettuato in precedenza:

ssh ubuntu master_ip

Esegui il seguente comando per ottenere lo stato del cluster:

kubectl get nodes

Vedrai un output di questo tipo: 

 

Output NAME STATUS ROLES AGE VERSION master Ready master 1d v1.14.0 worker1 Ready  1d v1.14.0 worker2 Ready  1d v1.14.0

Se invece alcuni nodi presentanto lo stato "NotReady", potrebbe significare che i nodi di lavoro non hanno ancora completato la configurazione. Attendi non più di dieci minuti prima di rieseguire il comando"kubectl get" nodes e ispezionare il nuovo output.

Se il cambio di stato da NotReady a Ready continua a non avvenire, verifica di aver eseguito correttamente i comandi nei passaggi precedenti e in caso ripetili.

Ora che il tuo cluster è stato verificato correttamente, potrai pianificare operazione remote all’interno del cluster Kubernetes sul tuo server Ubuntu 20.04.