Kubeadm Instalação
Vamos fazer uma instalação do cluster usando o kubeadm.
A ferramenta kubeadm nos ajuda a montar um cluster de vários nós usando as melhores práticas do Kubernetes.
Só para relembrar, o cluster Kubernetes consiste em vários componentes, incluindo o kube-apiserver, etcd, os controladores, etc.

Vimos algumas das exigências em torno da segurança e certificados para permitir a comunicação entre todos os componentes. Instalar todos esses vários componentes individualmente em diferentes nós e modificar todos os arquivos de configuração necessários para garantir que todos os componentes apontem uns para os outros e estabelecer certificados para que funcionem é uma tarefa entediante.
A ferramenta kubeadm nos ajuda, cuidando de todas estas tarefas.
Primeiro, você precisa ter vários sistemas ou VMs provisionados. Portanto, vamos precisar de um par de nós para formar o nosso cluster Kubernetes. Estas podem ser máquinas físicas ou virtuais. Como é um lab vamos criar máquinas virtuais usando o VirtualBox e Vagrant.
Com o Vagrant podemos criar um bootstrap após a máquina subir, colocando os comandos necessários em um script.
Os comandos para os nodes que serão os master são diferentes dos que serão workers, mas o kubeadm nos ajudará também nessa tarefa.
Todos os nodes precisam de um container runtime em execução. O kubeadm subirá os controllers como pods estáticos dentro do nosso cluster.
Procedimento para implantação do Kubernetes Cluster
-
Provisionamento de Máquinas (ALL): 1.1. Garantir que as máquinas atendam aos requisitos mínimos, incluindo:
- Update do sistema operacional
- Desabilitar o uso de swap.
- Desativar o firewall ou configurá-lo corretamente para permitir o tráfego necessário.
-
Instalação do Container Runtime (ALL):
- Instalar o containerd em todas as máquinas conforme as instruções do fabricante.
-
Instalação do kubeadm (ALL):
- Instalar o kubeadm em todas as máquinas, seguindo as instruções da documentação oficial do Kubernetes.
- https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
-
Configuração do Master (MASTER1):
- Em uma das máquinas master vamos inicializar o cluster usando o kubeadm como se fosse single node.
-
Deploy do CNI para criar a rede do cluster (MASTER1):
- Vamos implantar uma solução de CNI para conseguir ter a rede do nosso cluster.
-
Adicionar outros masters:
- Nas máquinas designadas como master, executar os comandos específicos do kubeadm para que se juntem ao cluster com função de master.
-
Adição de Workers ao Cluster:
- Nas máquinas designadas como workers, executar os comandos específicos do kubeadm para que se juntem ao cluster.
Requisitos
Vamos precisar do Vagrant instalado e do VirtualBox. É bom dar uma olhada no link https://github.com/kodekloudhub/certified-kubernetes-administrator-course
Crie uma pasta para o projeto.
mkdir kubeadm-env
cd kubeadm-env
E vamos criar um arquivo chamado Vagrantfile
com esse conteúdo:
NUM_EXTRA_MASTER_NODE = 2
NUM_WORKER_NODE = 2
IP_NW = "192.168.56."
MASTER_IP_START = 11
NODE_IP_START = 20
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/jammy64"
config.vm.boot_timeout = 900
config.vm.box_check_update = false
# Provision Master Nodes
config.vm.define "kubemaster" do |node|
node.vm.provider "virtualbox" do |vb|
vb.name = "kubemaster01"
vb.memory = 2048
vb.cpus = 2
end
node.vm.hostname = "kubemaster01"
node.vm.network :private_network, ip: IP_NW + "#{MASTER_IP_START}"
node.vm.network "forwarded_port", guest: 22, host: "#{2710}"
end
# Provision Extra Masters
(1..NUM_EXTRA_MASTER_NODE).each do |i|
config.vm.define "kubemaster0#{i+1}" do |node|
node.vm.provider "virtualbox" do |vb|
vb.name = "kubemaster0#{i+1}"
vb.memory = 2048
vb.cpus = 2
end
node.vm.hostname = "kubemaster0#{i+1}"
node.vm.network :private_network, ip: IP_NW + "#{MASTER_IP_START + i + 1}"
node.vm.network "forwarded_port", guest: 22, host: "#{2710 + i + 1}"
end
end
# Provision Worker Nodes
(1..NUM_WORKER_NODE).each do |i|
config.vm.define "kubenode0#{i}" do |node|
node.vm.provider "virtualbox" do |vb|
vb.name = "kubenode0#{i}"
vb.memory = 1024
vb.cpus = 1
end
node.vm.hostname = "kubenode0#{i}"
node.vm.network :private_network, ip: IP_NW + "#{NODE_IP_START + i}"
node.vm.network "forwarded_port", guest: 22, host: "#{2720 + i}"
end
end
end
Este arquivo apenas subirá 5 VMs, e não executará nada dentro delas como o bootstrap. Os passos 1, 2 e 3 servem para todos os nodes, então vamos montar um script para fazer um bootstrap geral.
#!/bin/bash
echo "##### Update System #####"
sudo apt-get update
sudo apt-get upgrade -y
## Seguindo a documentação https://kubernetes.io/docs/setup/production-environment/
## https://docs.docker.com/engine/install/ubuntu/container-runtimes/
echo "##### Desativando o swap #####"
sed -i '/swap/d' /etc/fstab
swapoff -a
echo "##### Desativando o firewall #####"
systemctl disable --now ufw >/dev/null 2>&1
echo "##### Ativando módulos do kernel necessários para o containerd #####"
cat >>/etc/modules-load.d/containerd.conf<<EOF
overlay
br_netfilter
EOF
modprobe overlay
modprobe br_netfilter
echo "##### Correção de Módulos #####"
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# sysctl params required by setup, params persist across reboots
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
EOF
# Apply sysctl params without reboot
sudo sysctl --system
# Verifying
sysctl net.bridge.bridge-nf-call-iptables net.bridge.bridge-nf-call-ip6tables net.ipv4.ip_forward
echo "##### Install Containerd #####"
sudo apt-get update
sudo apt-get install ca-certificates curl
echo "##### Install Containerd: Add Docker's official GPG key #####"
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "##### Install Containerd: Add the repository to Apt sources #####"
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
echo "##### Install Containerd: Install Packages #####"
sudo apt-get update
sudo apt-get install containerd.io -y
echo "##### Install Containerd: Verifying Service #####"
systemctl status containerd.service
echo "##### Install Containerd: Fix Cgroups Driver for systemd #####"
sudo mv /etc/containerd/config.toml /etc/containerd/config.toml.default
sudo tee /etc/containerd/config.toml > /dev/null <<EOF
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc]
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
SystemdCgroup = true
EOF
sudo systemctl restart containerd.service
systemctl status containerd.service
#https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm/
echo "##### Install Kubeadm kubelet and kubectl #####"
sudo apt-get install -y apt-transport-https ca-certificates curl gpg
echo "##### Install Kubeadm kubelet and kubectl: Add Kubernetes's official GPG key"
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.29/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo "##### Install Kubeadm kubelet and kubectl: Add the repository to Apt sources"
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.29/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
echo "##### Install Kubeadm kubelet and kubectl: Install Packages #####"
sudo apt-get install -y kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
Fiz todos os comentários necessários nesse script para que entenda o que vamos fazer, agora vamos adicionar esse script em todas as VMs.
Salve esse script na mesma pasta onde está o Vagrantfile com o nome de bootstrap.sh
ls -lha
total 20K
drwxrwxr-x 3 david-prata david-prata 4,0K fev 25 02:12 .
drwxrwxr-x 3 david-prata david-prata 4,0K fev 24 21:02 ..
-rw-rw-r-- 1 david-prata david-prata 3,0K fev 25 02:15 bootstrap.sh
-rw-rw-r-- 1 david-prata david-prata 1,7K fev 25 02:17 Vagrantfile
Vamos adicionar as linhas abaixo comentadas.
NUM_EXTRA_MASTER_NODE = 2
NUM_WORKER_NODE = 2
IP_NW = "192.168.56."
MASTER_IP_START = 11
NODE_IP_START = 20
Vagrant.configure("2") do |config|
config.vm.box = "ubuntu/jammy64"
config.vm.boot_timeout = 900
config.vm.box_check_update = false
# Provision Master Nodes
config.vm.define "kubemaster" do |node|
# Nome mostrado na interface gráfica
node.vm.provider "virtualbox" do |vb|
vb.name = "kubemaster01"
vb.memory = 2048
vb.cpus = 2
end
node.vm.hostname = "kubemaster01"
node.vm.network :private_network, ip: IP_NW + "#{MASTER_IP_START}"
node.vm.network "forwarded_port", guest: 22, host: "#{2710}"
node.vm.provision "shell", path: "bootstrap.sh" ## ADICIONADO
end
# Provision Extra Masters
(1..NUM_EXTRA_MASTER_NODE).each do |i|
config.vm.define "kubemaster0#{i+1}" do |node|
node.vm.provider "virtualbox" do |vb|
vb.name = "kubemaster0#{i+1}"
vb.memory = 2048
vb.cpus = 2
end
node.vm.hostname = "kubemaster0#{i+1}"
node.vm.network :private_network, ip: IP_NW + "#{MASTER_IP_START + i + 1}"
node.vm.network "forwarded_port", guest: 22, host: "#{2710 + i + 1}"
node.vm.provision "shell", path: "bootstrap.sh" ## ADICIONADO
end
end
# Provision Worker Nodes
(1..NUM_WORKER_NODE).each do |i|
config.vm.define "kubenode0#{i}" do |node|
node.vm.provider "virtualbox" do |vb|
vb.name = "kubenode0#{i}"
vb.memory = 1024
vb.cpus = 1
end
node.vm.hostname = "kubenode0#{i}"
node.vm.network :private_network, ip: IP_NW + "#{NODE_IP_START + i}"
node.vm.network "forwarded_port", guest: 22, host: "#{2720 + i}"
node.vm.provision "shell", path: "bootstrap.sh" ## ADICIONADO
end
end
end
Em cada nó então estaremos preparados para montar o cluster.
No primeiro nó master precisamos inicializar o cluster.
kubeadm init --apiserver-advertise-address=<IP DO MASTER> --pod-network-cidr=<REDE QUE OS PODS TERÃO>
Nós já sabemos qual é o IP dos masters. Definimos no Vagrantfile os IPs de forma automática.
IPS | NODE |
---|---|
kubemaster01 | 192.168.56.11 |
kubemaster02 | 192.168.56.12 |
kubemaster03 | 192.168.56.13 |
kubemaster01 | 192.168.56.21 |
kubemaster01 | 192.168.56.22 |
Vamos definir a rede que será usada pelos pods para 10.244.0.0/16, poderia ser outra, claro.
Então o comando seria:
kubeadm init --apiserver-advertise-address=192.168.56.11 --pod-network-cidr=10.244.0.0/16
Podemos automatizar isso.
IP_ADDR=`ip -4 address show enp0s8 | grep inet | awk '{print $2}' | cut -d/ -f1`
POD_CIDR="10.244.0.0/16"
echo "##### Inicializando o cluster #####"
sudo kubeadm init --apiserver-advertise-address=$IP_ADDR --pod-network-cidr=$POD_CIDR
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Vamos falar um pouco sobre esse comando. Não temos aqui um load balancer na frente do nosso cluster. Se tivéssemos deveríamos passar alguns parâmetros a mais nesse comando --control-plane-endpoint=<IP_LB:6443> --upload-certs
.
O comando init faz pull de algumas imagens que serão usadas automaticamente. Se quiser fazer o pull dessas imagens antes de rodar o comando init para ser mais rápido é possível, mas não é obrigatório.
kubeadm config images pull
.
Executando o script acima temos o cluster com um único node master. No console ele mostra os comandos necessários que demos continuar executando, veja a saída.
###
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 192.168.56.11:6443 --token 9n1vty.afan7eb99kaxltcj \
--discovery-token-ca-cert-hash sha256:6ebd7fd44972113263b6e85e8bdddd841774a39db9a48bd04d575c034c188247
O kubeconfig gerado fica em /etc/kubernetes/admin.conf. Precisamos dele para que o kubectl funcione, logo vamos colocar os comandos acima dentro do nosso script. Outra coisa que precisamos fazer é instalar um CNI no cluster. Já vamos também aplicá-lo no cluster usando o kubectl que acabamos de fazer funcionar. Poderíamos usar outras opções de CNI, mas vamos escolher o Weavenet.
IP_ADDR=`ip -4 address show enp0s8 | grep inet | awk '{print $2}' | cut -d/ -f1`
POD_CIDR="10.244.0.0/16"
echo "##### Init Cluster #####"
sudo kubeadm init --apiserver-advertise-address=$IP_ADDR --pod-network-cidr=$POD_CIDR
echo "##### Copy kubeconfig #####"
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
##https://github.com/weaveworks/weave?tab=readme-ov-file
echo "##### Deploy CNI weavenet #####"
kubectl apply -f https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n') >/dev/null 2>&1
kubeadm token create --certificate-key $(kubeadm init phase upload-certs --upload-certs | tail -1 ) --print-join-command > /join_masters.sh