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 comandocat
.
[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/hosts
impostando 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.