Ricerca nel sito web

Come installare Kubernetes su Rocky Linux 9/AlmaLinux 9


La distribuzione Linux Rocky Linux 9/AlmaLinux 9 è disponibile al pubblico da luglio 2022. Entrambe saranno supportate fino al 31 maggio 2032 (durata del supporto di 10 anni), rendendola una piattaforma ideale per eseguire il cluster Kubernetes. In questo articolo condividiamo i passaggi da seguire quando si configura un cluster Kubernetes a 3 nodi su sistema Rocky Linux 9/AlmaLinux 9.

  • 1 piano di controllonodo Kubernetes
  • 2 nodi di lavoroKubernetes

La configurazione del mio server è come mostrata di seguito.

Server IP Server Hostname Role
37.27.37.63 k8smaster.mylab.io Master Node (Control Plane)
37.27.6.95 k8snode01.mylab.io Worker Node 01
135.181.195.155 k8snode02.mylab.io Worker Node 02

L'infrastruttura utilizzata in questa guida è fornita da Hetzner Cloud.

$ hcloud server list
ID         NAME                 STATUS    IPV4              IPV6                      PRIVATE NET   DATACENTER
41815406   k8snode01.mylab.io   running   37.27.6.95        2a01:4f9:c011:bf23::/64   -             hel1-dc2
41815407   k8snode02.mylab.io   running   135.181.195.155   2a01:4f9:c011:b7d7::/64   -             hel1-dc2
41815408   k8smaster.mylab.io   running   37.27.37.63       2a01:4f9:c012:c08a::/64   -             hel1-dc2

Questa configurazione è semi-automatica utilizzando Ansible Playbook che eseguirà una serie di attività per configurare cose come;

  • Aggiorna il sistema e installa i pacchetti di dipendenze
  • Disabilita scambio (deve essere disattivato durante l'installazione del cluster Kubernetes)
  • Imposta il fuso orario e configura la sincronizzazione dell'ora NTP
  • Carica i moduli del kernel richiesti e configura altre configurazioni sysctl
  • Configura il file /etc/hosts su ciascun nodo
  • Installare e configurare il runtime del contenitore; Containerd, CRI-O o Docker con Mirantis cri-dockerd
  • Configura firewalld se attivato

1. Prepara la tua macchina workstation

La workstation è il luogo in cui verranno eseguiti i comandi ansible. Può anche essere uno dei nodi del cluster.

Installa gli strumenti CLI di base sulla macchina.

### Ubuntu / Debian ###
sudo apt update
sudo apt install git wget curl vim bash-completion tmux

### CentOS / RHEL / Fedora / Rocky Linux ###
sudo yum -y install git wget curl vim bash-completion tmux

Successivamente installiamo ansible se non già disponibile.

### Python3 ###
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python3 get-pip.py --user
python3 -m pip install ansible --user

### Python2 ###
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python get-pip.py --user
python -m pip install ansible --user

Controlla la versione di Ansible dopo l'installazione:

$ ansible --version
ansible [core 2.15.8]
  config file = None
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /root/.local/lib/python3.9/site-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /root/.local/bin/ansible
  python version = 3.9.18 (main, Sep  7 2023, 00:00:00) [GCC 11.4.1 20230605 (Red Hat 11.4.1-2)] (/usr/bin/python3)
  jinja version = 3.1.3
  libyaml = True

Aggiorna il file /etc/hosts nella tua macchina workstation:

$ sudo vim /etc/hosts
37.27.37.63      k8smaster.mylab.io  k8smaster
37.27.6.95       k8snode01.mylab.io  k8snode01
135.181.195.155  k8snode02.mylab.io  k8snode02

Genera chiavi SSH:

$ ssh-keygen -t rsa -b 4096 -N ''
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:wAufyZb3Zn/aEjo2Ds9/wnJrTTM2L3LsTlvtFXMiZcw [email 
The key's randomart image is:
+---[RSA 4096]----+
|OOo              |
|B**.             |
|EBBo. .          |
|===+ . .         |
|=*+++ . S        |
|*=++.o . .       |
|=.o. .. . .      |
| o. .    .       |
|   .             |
+----[SHA256]-----+

Crea un file di configurazione del client SSH con i seguenti parametri.

$ vim ~/.ssh/config
Host *
    UserKnownHostsFile /dev/null
    StrictHostKeyChecking no
    IdentitiesOnly yes
    ConnectTimeout 0
    ServerAliveInterval 30

Copia le chiavi SSH su tutti i nodi del cluster Kubernetes

ssh-copy-id username@ServerIP #Loop for all nodes.

# Example
ssh-copy-id  root@k8smaster
ssh-copy-id  root@k8snode01
ssh-copy-id  root@k8snode02

2. Impostare il nome host corretto su tutti i nodi

Accedi a ciascun nodo nel cluster e configura il nome host corretto:

# Examples
# Master Node 01
sudo hostnamectl set-hostname k8smaster.mylab.io

# Worker Node 01
sudo hostnamectl set-hostname k8snode01.mylab.io

Esci e poi accedi nuovamente per confermare che il nome host è impostato correttamente:

$ hostnamectl
 Static hostname: k8smaster.mylab.io
       Icon name: computer-vm
         Chassis: vm 🖴
      Machine ID: b4c55e2d211141d786f56d387aafff8e
         Boot ID: 190eaf2401b14942bef3c55920f4c6de
  Virtualization: kvm
Operating System: Rocky Linux 9.3 (Blue Onyx)
     CPE OS Name: cpe:/o:rocky:rocky:9::baseos
          Kernel: Linux 5.14.0-362.13.1.el9_3.x86_64
    Architecture: x86-64
 Hardware Vendor: Hetzner
  Hardware Model: vServer
Firmware Version: 20171111

Per un'istanza cloud che utilizza cloud-init, consulta la guida di seguito:

  • Imposta il nome host del server in EC2|OpenStack|DigitalOcean|Istanza di Azure

3. Prepara i nodi del cluster per l'installazione di k8s

Ho creato un playbook Ansible nel mio repository github che aiuta a semplificare queste operazioni standard.

  • Installa i pacchetti standard richiesti per gestire i nodi
  • Imposta i requisiti di sistema standard: Disabilita Swap, Modifica sysctl, Disabilita SELinux
  • Installa e configura un runtime di container di tua scelta: cri-o, Docker, Containerd
  • Installa i pacchetti Kubernetes: kubelet, kubeadm e kubectl
  • Configura Firewalld sui nodi Kubernetes Master e Worker: apri tutte le porte richieste

Clona il repository git sul tuo computer workstation:

git clone https://github.com/jmutai/k8s-pre-bootstrap.git

Passare alla directory k8s-pre-bootstrap

cd k8s-pre-bootstrap

Aggiorna il file di inventario con i nodi del cluster Kubernetes. Esempio;

$ vim hosts
[k8snodes]
k8smaster
k8snode01
k8snode02

Dobbiamo anche aggiornare le variabili nel file playbook. L'essere più importante;

  • Versione Kubernetes: k8s_version
  • Il tuo fuso orario: fuso orario
  • Kubernetes CNI da utilizzare: k8s_cni
  • Runtime del contenitore: container_runtime
$ vim  k8s-prep.yml
- name: Prepare Kubernetes Nodes for Cluster bootstrapping
  hosts: k8snodes
  remote_user: root
  become: yes
  become_method: sudo
  #gather_facts: no
  vars:
    k8s_version: "1.29"                                  # Kubernetes version to be installed
    selinux_state: permissive                            # SELinux state to be set on k8s nodes
    timezone: "Africa/Nairobi"                           # Timezone to set on all nodes
    k8s_cni: calico                                      # calico, flannel
    container_runtime: cri-o                             # docker, cri-o, containerd
    pod_network_cidr: "172.18.0.0/16"                    # pod subnet if using cri-o runtime
    configure_firewalld: false                           # true / false (keep it false, k8s>1.19 have issues with firewalld)
    # Docker proxy support
    setup_proxy: false                                   # Set to true to configure proxy
    proxy_server: "proxy.example.com:8080"               # Proxy server address and port
    docker_proxy_exclude: "localhost,127.0.0.1"          # Adresses to exclude from proxy
  roles:
    - kubernetes-bootstrap

Convalida la sintassi del tuo Ansible Playbook:

$ ansible-playbook  --syntax-check -i hosts k8s-prep.yml
playbook: k8s-prep.yml

Per le chiavi private SSH con una passphrase, salvala per evitare richieste al momento dell'esecuzione del playbook:

eval `ssh-agent -s` && ssh-add

Ora possiamo eseguire il playbook per preparare i nostri nodi del cluster.

ansible-playbook -i hosts k8s-prep.yml

L'estratto della mia esecuzione ansible è mostrato di seguito.

PLAY [Prepare Kubernetes Nodes for Cluster bootstrapping] ********************************************************************************************************************************************

TASK [Gathering Facts] *******************************************************************************************************************************************************************************
ok: [k8snode02]
ok: [k8smaster]
ok: [k8snode01]

TASK [kubernetes-bootstrap : Add the OS specific variables] ******************************************************************************************************************************************
ok: [k8smaster] => (item=/private/tmp/k8s-pre-bootstrap/roles/kubernetes-bootstrap/vars/RedHat9.yml)
ok: [k8snode01] => (item=/private/tmp/k8s-pre-bootstrap/roles/kubernetes-bootstrap/vars/RedHat9.yml)
ok: [k8snode02] => (item=/private/tmp/k8s-pre-bootstrap/roles/kubernetes-bootstrap/vars/RedHat9.yml)

TASK [kubernetes-bootstrap : Include Pre-reqs setup task] ********************************************************************************************************************************************
included: /private/tmp/k8s-pre-bootstrap/roles/kubernetes-bootstrap/tasks/pre_setup.yml for k8smaster, k8snode01, k8snode02

TASK [kubernetes-bootstrap : Put SELinux in permissive mode] *****************************************************************************************************************************************
ok: [k8smaster]
ok: [k8snode02]
ok: [k8snode01]

TASK [kubernetes-bootstrap : Update system packages] *************************************************************************************************************************************************
ok: [k8smaster]
ok: [k8snode02]
ok: [k8snode01]

TASK [kubernetes-bootstrap : Install some packages needed to configure the nodes] ********************************************************************************************************************
changed: [k8smaster] => (item=['vim', 'bash-completion', 'wget', 'curl', 'firewalld', 'python3-firewall', 'yum-utils', 'lvm2', 'device-mapper-persistent-data', 'iproute-tc'])
changed: [k8snode02] => (item=['vim', 'bash-completion', 'wget', 'curl', 'firewalld', 'python3-firewall', 'yum-utils', 'lvm2', 'device-mapper-persistent-data', 'iproute-tc'])
changed: [k8snode01] => (item=['vim', 'bash-completion', 'wget', 'curl', 'firewalld', 'python3-firewall', 'yum-utils', 'lvm2', 'device-mapper-persistent-data', 'iproute-tc'])

TASK [kubernetes-bootstrap : Disable firewalld service] **********************************************************************************************************************************************
changed: [k8snode02]
changed: [k8smaster]
changed: [k8snode01]

TASK [kubernetes-bootstrap : Include task to disable swap] *******************************************************************************************************************************************
included: /private/tmp/k8s-pre-bootstrap/roles/kubernetes-bootstrap/tasks/disable_swap.yml for k8smaster, k8snode01, k8snode02

TASK [kubernetes-bootstrap : Disable SWAP since kubernetes can't work with swap enabled (1/2)] *******************************************************************************************************
changed: [k8smaster]
changed: [k8snode02]
changed: [k8snode01]

TASK [kubernetes-bootstrap : Disable SWAP in fstab since kubernetes can't work with swap enabled (2/2)] **********************************************************************************************
ok: [k8smaster]
ok: [k8snode02]
ok: [k8snode01]

TASK [kubernetes-bootstrap : Include task to configure timezone and ntp] *****************************************************************************************************************************
included: /private/tmp/k8s-pre-bootstrap/roles/kubernetes-bootstrap/tasks/configure_timezone_ntp.yml for k8smaster, k8snode01, k8snode02

TASK [kubernetes-bootstrap : Configure timezone on all nodes] ****************************************************************************************************************************************
changed: [k8smaster]
changed: [k8snode02]
changed: [k8snode01]

TASK [kubernetes-bootstrap : Ensure chrony package is installed] *************************************************************************************************************************************
ok: [k8smaster]
ok: [k8snode01]
ok: [k8snode02]

TASK [kubernetes-bootstrap : Enable and start chronyd service] ***************************************************************************************************************************************
ok: [k8smaster]
ok: [k8snode02]
ok: [k8snode01]

TASK [kubernetes-bootstrap : Synchronize time manually] **********************************************************************************************************************************************
changed: [k8smaster]
changed: [k8snode02]
changed: [k8snode01]

TASK [kubernetes-bootstrap : Include task to load required kernel modules and sysctl configs] ********************************************************************************************************
included: /private/tmp/k8s-pre-bootstrap/roles/kubernetes-bootstrap/tasks/load_kernel_modules_sysctl.yml for k8smaster, k8snode01, k8snode02

TASK [kubernetes-bootstrap : Load required modules] **************************************************************************************************************************************************
changed: [k8snode02] => (item=br_netfilter)
changed: [k8smaster] => (item=br_netfilter)
changed: [k8snode01] => (item=br_netfilter)
changed: [k8snode02] => (item=overlay)
changed: [k8smaster] => (item=overlay)
changed: [k8snode01] => (item=overlay)
changed: [k8smaster] => (item=ip_vs)
changed: [k8snode02] => (item=ip_vs)
changed: [k8snode01] => (item=ip_vs)
changed: [k8smaster] => (item=ip_vs_rr)
changed: [k8snode02] => (item=ip_vs_rr)
changed: [k8snode01] => (item=ip_vs_rr)
changed: [k8smaster] => (item=ip_vs_wrr)
changed: [k8snode02] => (item=ip_vs_wrr)
changed: [k8snode01] => (item=ip_vs_wrr)
changed: [k8smaster] => (item=ip_vs_sh)
changed: [k8snode02] => (item=ip_vs_sh)
changed: [k8snode01] => (item=ip_vs_sh)
ok: [k8smaster] => (item=nf_conntrack)
ok: [k8snode02] => (item=nf_conntrack)
ok: [k8snode01] => (item=nf_conntrack)

TASK [kubernetes-bootstrap : Create the .conf file to load the modules at bootup] ********************************************************************************************************************
changed: [k8smaster]
changed: [k8snode02]
changed: [k8snode01]

TASK [kubernetes-bootstrap : Modify sysctl entries] **************************************************************************************************************************************************
changed: [k8smaster] => (item={'key': 'net.bridge.bridge-nf-call-ip6tables', 'value': 1})
changed: [k8snode02] => (item={'key': 'net.bridge.bridge-nf-call-ip6tables', 'value': 1})
changed: [k8snode01] => (item={'key': 'net.bridge.bridge-nf-call-ip6tables', 'value': 1})
changed: [k8snode02] => (item={'key': 'net.bridge.bridge-nf-call-iptables', 'value': 1})
changed: [k8smaster] => (item={'key': 'net.bridge.bridge-nf-call-iptables', 'value': 1})
changed: [k8snode01] => (item={'key': 'net.bridge.bridge-nf-call-iptables', 'value': 1})
changed: [k8smaster] => (item={'key': 'net.ipv4.ip_forward', 'value': 1})
changed: [k8snode02] => (item={'key': 'net.ipv4.ip_forward', 'value': 1})
changed: [k8snode01] => (item={'key': 'net.ipv4.ip_forward', 'value': 1})

TASK [kubernetes-bootstrap : Include task to configure /etc/hosts file on each node] *****************************************************************************************************************
included: /private/tmp/k8s-pre-bootstrap/roles/kubernetes-bootstrap/tasks/configure_etc_host_file.yml for k8smaster, k8snode01, k8snode02

TASK [kubernetes-bootstrap : Generate /etc/hosts file] ***********************************************************************************************************************************************
changed: [k8smaster]
changed: [k8snode02]
changed: [k8snode01]

TASK [kubernetes-bootstrap : Include task to configure docker] ***************************************************************************************************************************************
skipping: [k8smaster]
skipping: [k8snode01]
skipping: [k8snode02]

TASK [kubernetes-bootstrap : Include task to configure cri-o container runtime] **********************************************************************************************************************
included: /private/tmp/k8s-pre-bootstrap/roles/kubernetes-bootstrap/tasks/setup_crio.yml for k8smaster, k8snode01, k8snode02

TASK [kubernetes-bootstrap : Configure Cri-o YUM repository] *****************************************************************************************************************************************
changed: [k8smaster]
changed: [k8snode01]
changed: [k8snode02]

TASK [kubernetes-bootstrap : Setup required sysctl params] *******************************************************************************************************************************************
ok: [k8smaster] => (item={'key': 'net.bridge.bridge-nf-call-ip6tables', 'value': 1})
ok: [k8snode02] => (item={'key': 'net.bridge.bridge-nf-call-ip6tables', 'value': 1})
ok: [k8snode01] => (item={'key': 'net.bridge.bridge-nf-call-ip6tables', 'value': 1})
ok: [k8smaster] => (item={'key': 'net.bridge.bridge-nf-call-iptables', 'value': 1})
ok: [k8snode02] => (item={'key': 'net.bridge.bridge-nf-call-iptables', 'value': 1})
ok: [k8snode01] => (item={'key': 'net.bridge.bridge-nf-call-iptables', 'value': 1})
ok: [k8smaster] => (item={'key': 'net.ipv4.ip_forward', 'value': 1})
ok: [k8snode02] => (item={'key': 'net.ipv4.ip_forward', 'value': 1})
ok: [k8snode01] => (item={'key': 'net.ipv4.ip_forward', 'value': 1})

Screenshot che mostra l'esecuzione corretta del playbook. Conferma che non ci siano errori nell'output:

Accedi a uno dei nodi e convalida le impostazioni di seguito:

  • Il contenuto del file /etc/hosts configurato può essere controllato utilizzando il comando cat.
[root@k8smaster ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

37.27.37.63 k8smaster.mylab.io k8smaster
37.27.6.95 k8snode01.mylab.io k8snode01
135.181.195.155 k8snode02.mylab.io k8snode02
  • Stato del servizio cri-o:
[root@k8smaster ~]# systemctl status crio
 crio.service - Container Runtime Interface for OCI (CRI-O)
     Loaded: loaded (/usr/lib/systemd/system/crio.service; enabled; preset: disabled)
     Active: active (running) since Thu 2024-01-11 12:13:14 EAT; 17min ago
       Docs: https://github.com/cri-o/cri-o
   Main PID: 13950 (crio)
      Tasks: 8
     Memory: 21.2M
        CPU: 977ms
     CGroup: /system.slice/crio.service
             └─13950 /usr/bin/crio

Jan 11 12:13:41 k8smaster.mylab.io crio[13950]: time="2024-01-11 12:13:41.364003994+03:00" level=info msg="Updated default CNI network name to crio"
Jan 11 12:13:41 k8smaster.mylab.io crio[13950]: time="2024-01-11 12:13:41.364030052+03:00" level=info msg="CNI monitoring event CHMOD         \"/usr/libexec/cni/vrf;659fb144\""
Jan 11 12:13:41 k8smaster.mylab.io crio[13950]: time="2024-01-11 12:13:41.364049032+03:00" level=info msg="CNI monitoring event RENAME        \"/usr/libexec/cni/vrf;659fb144\""
Jan 11 12:13:41 k8smaster.mylab.io crio[13950]: time="2024-01-11 12:13:41.370310945+03:00" level=info msg="Found CNI network crio (type=bridge) at /etc/cni/net.d/100-crio-bridge.conflist"
Jan 11 12:13:41 k8smaster.mylab.io crio[13950]: time="2024-01-11 12:13:41.374147282+03:00" level=info msg="Found CNI network loopback (type=loopback) at /etc/cni/net.d/200-loopback.conflist"
Jan 11 12:13:41 k8smaster.mylab.io crio[13950]: time="2024-01-11 12:13:41.374193281+03:00" level=info msg="Updated default CNI network name to crio"
Jan 11 12:13:41 k8smaster.mylab.io crio[13950]: time="2024-01-11 12:13:41.374220253+03:00" level=info msg="CNI monitoring event CREATE        \"/usr/libexec/cni/vrf\""
Jan 11 12:13:41 k8smaster.mylab.io crio[13950]: time="2024-01-11 12:13:41.380391706+03:00" level=info msg="Found CNI network crio (type=bridge) at /etc/cni/net.d/100-crio-bridge.conflist"
Jan 11 12:13:41 k8smaster.mylab.io crio[13950]: time="2024-01-11 12:13:41.384774768+03:00" level=info msg="Found CNI network loopback (type=loopback) at /etc/cni/net.d/200-loopback.conflist"
Jan 11 12:13:41 k8smaster.mylab.io crio[13950]: time="2024-01-11 12:13:41.384832716+03:00" level=info msg="Updated default CNI network name to crio"
  • Parametri del kernel sysctl configurati
[root@k8smaster ~]# sysctl -p
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1
  • Porte aperte da Firewalld:
[root@k8smaster ~]# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: enp1s0
  sources:
  services: cockpit dhcpv6-client ssh
  ports: 22/tcp 80/tcp 443/tcp 6443/tcp 2379-2380/tcp 10250/tcp 10251/tcp 10252/tcp 30000-32767/tcp 4789/udp 5473/tcp 179/tcp
  protocols:
  masquerade: no
  forward-ports:
  source-ports:
  icmp-blocks:
  rich rules:

4. Bootstrap del piano di controllo Kubernetes

Il comando kubeadm init viene utilizzato per inizializzare il piano di controllo Kubernetes. Esegue una serie di controlli pre-volo per convalidare lo stato del sistema prima di apportare modifiche

Di seguito sono elencate le opzioni chiave di cui dovresti essere a conoscenza:

  • –apiserver-advertise-address: l'indirizzo IP su cui il server API pubblicizzerà il suo ascolto. Se non viene impostata, verrà utilizzata l'interfaccia di rete predefinita.
  • –apiserver-bind-port: porta a cui collegarsi il server API; il valore predefinito è 6443
  • –control-plane-endpoint: specifica un indirizzo IP stabile o un nome DNS per il piano di controllo.
  • –cri-socket: percorso della presa CRI per la connessione.
  • –dry-run: non applica alcuna modifica; emetti semplicemente ciò che verrebbe fatto
  • –image-repository: scegli un registro contenitori da cui estrarre le immagini del piano di controllo; Impostazione predefinita: "k8s.gcr.io"
  • –kubernetes-version: scegli una versione Kubernetes specifica per il piano di controllo.
  • –pod-network-cidr: specifica l'intervallo di indirizzi IP per la rete pod. Se impostato, il piano di controllo assegnerà automaticamente i CIDR per ogni nodo.
  • –service-cidr: utilizza un intervallo alternativo di indirizzi IP per i VIP del servizio. Impostazione predefinita: "10.96.0.0/12"

La tabella seguente elenca i runtime del contenitore e i relativi percorsi socket associati:

Controllo delle note sulla versione della versione Kubernetes

Puoi trovare le note sulla versione leggendo il registro delle modifiche che corrisponde alla tua versione di Kubernetes

Opzione 1: bootstrap del cluster di nodi del piano di controllo singolo

Se hai intenzione di aggiornare un singolo cluster kubeadm del piano di controllo alla disponibilità elevata, devi specificare --control-plane-endpoint per impostare l'endpoint condiviso per tutti i nodi del piano di controllo.

Ma se questo è pensato per un ambiente di test con piano di controllo a nodo singolo, puoi ignorare l'opzione –control-plane-endpoint.

Accedi al nodo principale:

ssh root@k8smaster

Quindi inizializzare il piano di controllo eseguendo i seguenti comandi.

sudo kubeadm init --pod-network-cidr=172.18.0.0/16

Prendi nota dei comandi kubeconfig e dei comandi di unione al cluster per i nodi di lavoro.

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 37.27.37.63:6443 --token h1q8cy.8tkc1fb6yrmtroxs \
	--discovery-token-ca-cert-hash sha256:0a8b2738df4d9116f698c68a85afafc7ac82677736cc2cef934cf5e93daeb7c4

Configura kubectl

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Conferma che funziona.

[root@k8smaster ~]# kubectl get nodes
NAME                 STATUS   ROLES           AGE   VERSION
k8smaster.mylab.io   Ready    control-plane   14m   v1.29.4

Distribuisci il plugin di rete Calico al cluster

Installa l'operatore Tigera Calico e le definizioni delle risorse personalizzate.

VER=$(curl --silent "https://api.github.com/repos/projectcalico/calico/releases/latest"|grep '"tag_name"'|sed -E 's/.*"([^"]+)".*/\1/'|sed 's/v//')
echo $VER
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v$VER/manifests/tigera-operator.yaml

Output dell'esecuzione del comando:

namespace/tigera-operator created
customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgpfilters.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/blockaffinities.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/caliconodestatuses.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamblocks.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamconfigs.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamhandles.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipreservations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/kubecontrollersconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/apiservers.operator.tigera.io created
customresourcedefinition.apiextensions.k8s.io/imagesets.operator.tigera.io created
customresourcedefinition.apiextensions.k8s.io/installations.operator.tigera.io created
customresourcedefinition.apiextensions.k8s.io/tigerastatuses.operator.tigera.io created
serviceaccount/tigera-operator created
clusterrole.rbac.authorization.k8s.io/tigera-operator created
clusterrolebinding.rbac.authorization.k8s.io/tigera-operator created
deployment.apps/tigera-operator created

Successivamente installa Calico creando la risorsa personalizzata necessaria. Per ulteriori informazioni sulle opzioni di configurazione disponibili in questo manifest, consulta il riferimento all'installazione.

wget https://raw.githubusercontent.com/projectcalico/calico/v$VER/manifests/custom-resources.yaml
sed -ie 's/192.168.0.0/172.18.0.0/g' custom-resources.yaml
kubectl apply -f custom-resources.yaml

Rimuovi le incompatibilità sul piano di controllo in modo da poter programmare i pod su di esso.

kubectl taint nodes --all node-role.kubernetes.io/control-plane-
kubectl taint nodes --all node-role.kubernetes.io/master-

Attendi che i pod vengano eseguiti con il comando seguente.

[root@k8smaster ~]# watch kubectl get pods -n calico-system
NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-85fdd68cb8-t68b9   1/1     Running   0          67s
calico-node-xp4j5                          1/1     Running   0          68s
calico-typha-79db89578b-9478m              1/1     Running   0          68s
csi-node-driver-2b4wg                      2/2     Running   0          68s

Opzione 2: bootstrap del cluster del piano di controllo multinodo

Utilizza l'opzione --control-plane-endpoint per impostare l'endpoint condiviso per tutti i nodi del piano di controllo. Questa opzione consente sia indirizzi IP che nomi DNS che possono essere mappati a indirizzi IP

Esempio di record A nel collegamento del server DNS

; Create entries for the master nodes
k8s-master-01		IN	A	192.168.200.10
k8s-master-02		IN	A	192.168.200.11
k8s-master-03		IN	A	192.168.200.12

;
; The Kubernetes cluster ControlPlaneEndpoint point these to the IP of the masters
k8s-endpoint	IN	A	192.168.200.10
k8s-endpoint	IN	A	192.168.200.11
k8s-endpoint	IN	A	192.168.200.12

Esempio di un file /etc/hosts

$ sudo vim /etc/hosts
192.168.200.10 k8s-master-01.example.com k8s-master-01
192.168.200.11 k8s-master-02.example.com k8s-master-02
192.168.200.12 k8s-master-03.example.com k8s-master-03
##  Kubernetes cluster ControlPlaneEndpoint Entries ###
192.168.200.10 k8s-endpoint.example.com  k8s-endpoint
#192.168.200.11 k8s-endpoint.example.com  k8s-endpoint
#192.168.200.12 k8s-endpoint.example.com  k8s-endpoint

Utilizzo dell'IP del bilanciatore del carico per ControlPlaneEndpoint

L'approccio ideale per le configurazioni HA è la mappatura dell'endpoint ControlPlane su un IP del sistema di bilanciamento del carico. Il LB punterà quindi ai nodi del piano di controllo con una qualche forma di controllo dello stato.

# Entry in Bind DNS Server
k8s-endpoint	IN	A	192.168.200.8

# Entry in /etc/hosts file
192.168.200.8 k8s-endpoint.example.com  k8s-endpoint

Cluster Kubernetes del piano di controllo multinodo Bootstrap

Accedi al Master Node 01 dal server bastion o dalla tua workstation:

[root@k8s-bastion ~]# ssh k8s-master-01
Warning: Permanently added 'k8s-master-01' (ED25519) to the list of known hosts.
Last login: Fri Sep 24 18:07:55 2021 from 192.168.200.9
[root@k8s-master-01 ~]#

Aggiorna il file /etc/hosts con questo indirizzo IP del nodo e un nome DNS personalizzato mappato a questo IP:

[root@k8s-master-01 ~]# vim /etc/hosts
192.168.200.10 k8s-endpoint.example.com  k8s-endpoint

Per inizializzare l'esecuzione del nodo del piano di controllo:

[root@k8s-master-01 ~]# kubeadm init \
  --pod-network-cidr=172.18.0.0/16 \
  --control-plane-endpoint=k8s-endpoint.example.com \
  --cri-socket=unix://var/run/crio/crio.sock \
  --upload-certs

Dove :

  • k8s-endpoint.example.com è un nome DNS valido configurato per ControlPlane Endpoint
  • /var/run/crio/crio.sock è il file socket runtime Cri-o
  • 172.18.0.0/16 è la tua rete Pod da utilizzare in Kubernetes
  • –upload-certs Flag utilizzato per caricare i certificati che dovrebbero essere condivisi tra tutte le istanze del piano di controllo nel cluster

In caso di successo otterrai un output con contenuti simili a questo:

...output omitted...
[mark-control-plane] Marking the node k8s-master-01.example.com as control-plane by adding the taints [node-role.kubernetes.io/master:NoSchedule]
[bootstrap-token] Using token: p11op9.eq9vr8gq9te195b9
[bootstrap-token] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to get nodes
[bootstrap-token] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstrap-token] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstrap-token] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstrap-token] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[kubelet-finalize] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key
[addons] Applied essential addon: CoreDNS
[addons] Applied essential addon: kube-proxy

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Alternatively, if you are the root user, you can run:

  export KUBECONFIG=/etc/kubernetes/admin.conf

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

You can now join any number of the control-plane node running the following command on each as root:

  kubeadm join k8s-endpoint.example.com:6443 --token 78oyk4.ds1hpo2vnwg3yykt \
	--discovery-token-ca-cert-hash sha256:4fbb0d45a1989cf63624736a005dc00ce6068eb7543ca4ae720c7b99a0e86aca \
	--control-plane --certificate-key 999110f4a07d3c430d19ca0019242f392e160216f3b91f421da1a91f1a863bba

Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use
"kubeadm init phase upload-certs --upload-certs" to reload certs afterward.

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join k8s-endpoint.example.com:6443 --token 78oyk4.ds1hpo2vnwg3yykt \
	--discovery-token-ca-cert-hash sha256:4fbb0d45a1989cf63624736a005dc00ce6068eb7543ca4ae720c7b99a0e86aca

Configura Kubectl come mostrato nell'output:

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Test controllando i nodi attivi:

[root@k8smaster ~]# kubectl get nodes
NAME                 STATUS   ROLES           AGE   VERSION
k8smaster.mylab.io   Ready    control-plane   14m   v1.29.4

Distribuisci il plugin di rete Calico al cluster

Installa l'operatore Tigera Calico e le definizioni delle risorse personalizzate.

VER=$(curl --silent "https://api.github.com/repos/projectcalico/calico/releases/latest"|grep '"tag_name"'|sed -E 's/.*"([^"]+)".*/\1/'|sed 's/v//')
echo $VER
kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v$VER/manifests/tigera-operator.yaml

Output dell'esecuzione del comando:

namespace/tigera-operator created
customresourcedefinition.apiextensions.k8s.io/bgpconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgpfilters.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/bgppeers.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/blockaffinities.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/caliconodestatuses.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/clusterinformations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/felixconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/globalnetworksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/hostendpoints.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamblocks.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamconfigs.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipamhandles.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ippools.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/ipreservations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/kubecontrollersconfigurations.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networkpolicies.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/networksets.crd.projectcalico.org created
customresourcedefinition.apiextensions.k8s.io/apiservers.operator.tigera.io created
customresourcedefinition.apiextensions.k8s.io/imagesets.operator.tigera.io created
customresourcedefinition.apiextensions.k8s.io/installations.operator.tigera.io created
customresourcedefinition.apiextensions.k8s.io/tigerastatuses.operator.tigera.io created
serviceaccount/tigera-operator created
clusterrole.rbac.authorization.k8s.io/tigera-operator created
clusterrolebinding.rbac.authorization.k8s.io/tigera-operator created
deployment.apps/tigera-operator created

Successivamente installa Calico creando la risorsa personalizzata necessaria. Per ulteriori informazioni sulle opzioni di configurazione disponibili in questo manifest, consulta il riferimento all'installazione.

wget https://raw.githubusercontent.com/projectcalico/calico/v$VER/manifests/custom-resources.yaml
sed -ie 's/192.168.0.0/172.18.0.0/g' custom-resources.yaml
kubectl apply -f custom-resources.yaml

Rimuovi le incompatibilità sul piano di controllo in modo da poter programmare i pod su di esso.

kubectl taint nodes --all node-role.kubernetes.io/control-plane-
kubectl taint nodes --all node-role.kubernetes.io/master-

Attendi che i pod vengano eseguiti con il comando seguente.

[root@k8smaster ~]# watch kubectl get pods -n calico-system
NAME                                       READY   STATUS    RESTARTS   AGE
calico-kube-controllers-85fdd68cb8-t68b9   1/1     Running   0          67s
calico-node-xp4j5                          1/1     Running   0          68s
calico-typha-79db89578b-9478m              1/1     Running   0          68s
csi-node-driver-2b4wg                      2/2     Running   0          68s

Aggiungi altri nodi del piano di controllo

Questo è applicabile solo per più nodi del piano di controllo (nodi master)

Aggiorna il file /etc/hostsimpostando ControlPlaneEndpoint sul primo nodo di controllo da cui è stato avviato il processo di bootstrap:

192.168.200.10 k8s-endpoint.example.com   k8s-endpoint
#192.168.200.11 k8s-endpoint.example.com  k8s-endpoint
#192.168.200.12 k8s-endpoint.example.com  k8s-endpoint

Quindi utilizzare il comando stampato dopo un'inizializzazione riuscita:

kubeadm join k8s-endpoint.example.com:6443 --token <token> \
  --discovery-token-ca-cert-hash <hash> \
  --control-plane --certificate-key <certkey>

Controlla l'elenco dei nodi del piano di controllo

Da uno dei nodi master con Kubectl configurato controlla l'elenco dei nodi:

[root@k8s-master-03 ~]# kubectl get nodes
NAME                                  STATUS   ROLES                  AGE   VERSION
k8s-master-01.example.com             Ready    control-plane,master   11m   v1.29.4
k8s-master-02.example.com             Ready    control-plane,master   5m    v1.29.4
k8s-master-03.example.com             Ready    control-plane,master   32s   v1.29.4

Ora puoi rimuovere il commento da altre righe nel file /etc/hosts su ciascun nodo di controllo se non utilizzi l'IP del bilanciatore di carico:

# Perform on all control plane nodes
[root@k8s-master-03 ~]# vim /etc/hosts
###  Kubernetes cluster ControlPlaneEndpoint Entries ###
192.168.200.10 k8s-endpoint.example.com  k8s-endpoint
192.168.200.11 k8s-endpoint.example.com  k8s-endpoint
192.168.200.12 k8s-endpoint.example.com  k8s-endpoint

5. Aggiunta di nodi di lavoro al cluster

Accedi a ciascuna delle macchine lavoratore utilizzando ssh:

ssh username@nodeip

Aggiorna il file /etc/hosts su ciascun nodo con i nomi host/indirizzo IP dei nodi master e di lavoro se non è presente alcun DNS (solo per l'utilizzo del DNS API)

### Also add Kubernetes cluster ControlPlaneEndpoint Entries for multiple control plane nodes(masters) ###
192.168.200.10 k8s-endpoint.example.com  k8s-endpoint
192.168.200.11 k8s-endpoint.example.com  k8s-endpoint
1192.168.200.12 k8s-endpoint.example.com  k8s-endpoint

Unisci le tue macchine lavoratore al cluster utilizzando i comandi forniti in precedenza:

kubeadm join k8s-endpoint.example.com:6443 \
  --token <tonek> \
  --discovery-token-ca-cert-hash <hash>

Una volta terminato, esegui kubectl get nodes sul piano di controllo per vedere i nodi unirsi al cluster:

[root@k8smaster ~]#  kubectl get nodes
NAME                 STATUS   ROLES           AGE   VERSION
k8smaster.mylab.io   Ready    control-plane   21m   v1.29.4
k8snode01.mylab.io   Ready    <none>          2s    v1.29.4
k8snode02.mylab.io   Ready    <none>          21s   v1.29.4

Puoi anche creare e utilizzare un nuovo comando di unione.

[root@k8smaster ~]# kubeadm token create --print-join-command

6. Distribuire l'applicazione di test sul cluster

Dobbiamo verificare che il nostro cluster funzioni distribuendo un'applicazione. Lavoreremo con l'applicazione Guestbook.

Per i cluster a nodo singolo consulta la nostra guida su come eseguire i pod sui nodi del piano di controllo:

  • Pianificazione dei pod sui nodi del piano di controllo Kubernetes (master).

Crea uno spazio dei nomi temporaneo:

$ kubectl create namespace temp
namespace/temp created

Distribuisci l'applicazione guestbook nello spazio dei nomi temporaneo creato.

kubectl -n temp apply -f https://k8s.io/examples/application/guestbook/redis-leader-deployment.yaml
kubectl -n temp apply -f https://k8s.io/examples/application/guestbook/redis-leader-service.yaml
kubectl -n temp apply -f https://k8s.io/examples/application/guestbook/redis-follower-deployment.yaml
kubectl -n temp apply -f https://k8s.io/examples/application/guestbook/redis-follower-service.yaml
kubectl -n temp apply -f https://k8s.io/examples/application/guestbook/frontend-deployment.yaml
kubectl -n temp apply -f https://k8s.io/examples/application/guestbook/frontend-service.yaml

Interroga l'elenco dei pod per verificare che siano in esecuzione dopo pochi minuti:

kubectl get all -n temp

Esegui il comando seguente per inoltrare la porta 8080 sul tuo computer locale alla porta 80 sul servizio.

$ kubectl -n temp port-forward svc/frontend 8080:80
Forwarding from 127.0.0.1:8080 -> 80
Forwarding from [::1]:8080 -> 80

Ora carica la pagina http://localhost:8080 nel tuo browser per visualizzare il tuo libro degli ospiti.

7. Installazione di altri componenti aggiuntivi/strumenti di terze parti

Qui condividiamo i collegamenti a diverse guide sull'installazione di altri componenti che migliorano l'utilizzo di Kubernetes.

#1. Server delle metriche

Metrics Server recupererà le metriche delle risorse dai kubelet e le esporrà nel server API Kubernetes tramite l'API Metrics per l'utilizzo da parte di HPA e VPA.

Consulta la guida di seguito su come distribuirlo.

  • Come distribuire Metrics Server nel cluster Kubernetes

#2. Installa il controller di ingresso

Un controller Ingress viene utilizzato per fornire un accesso pubblico sicuro ai servizi K8. Abbiamo guide all'installazione di Nginx e Traefik nel nostro sito web.

  • Distribuisci Nginx Ingress Controller su Kubernetes utilizzando Helm Chart
  • Installa e configura il controller di ingresso Traefik sul cluster Kubernetes

#3. Distribuisci il monitoraggio Prometheus/Grafana

Utilizza la guida qui sotto per installare e configurare Prometheus e Grafana.

  • Configura Prometheus e Grafana su Kubernetes utilizzando prometheus-operator

#4. Distribuisci la dashboard Kubernetes (facoltativo)

Il dashboard Kubernetes può essere utilizzato durante la risoluzione dei problemi delle applicazioni containerizzate e nell'amministrazione generale delle risorse del cluster.

  • Come installare la dashboard Kubernetes con NodePort

#5. Archiviazione persistente (facoltativo)

Abbiamo molte guide sull'archiviazione persistente, vedi sotto.

  • Configura NFS come archivio di volumi persistenti Kubernetes
  • Come distribuire Rook Ceph Storage sul cluster Kubernetes
  • Archiviazione persistente Ceph per Kubernetes con Cephfs
  • Archiviazione persistente per Kubernetes con Ceph RBD
  • Come configurare il provisioning del volume dinamico di Kubernetes con Heketi e GlusterFS

#6. Distribuisci MetalLB su Kubernetes

Per l'installazione del bilanciatore di carico MetalLB fare riferimento al seguente articolo.

  • Come distribuire il bilanciatore del carico MetalLB sul cluster Kubernetes

I migliori libri sull'amministrazione Kubernetes da leggere:

  • I migliori libri di studio su Kubernetes

Conclusione

In questo articolo siamo stati in grado di installare e configurare un cluster Kubernetes a tre nodi con un singolo piano di controllo e due nodi di lavoro. L'infrastruttura Kubernetes può essere facilmente scalata per garantire un'elevata disponibilità. Ci auguriamo che questo tutorial ti sia stato di grande aiuto. Grazie e ci vediamo in altri articoli.

Articoli correlati: