Como instalar um Cluster Multi-Node Kubernetes
Kubernetes - The hard way será uma série mão na massa, com linguagem simples e no estilo de faça você mesmo.
Para provar o que estou dizendo, vamos começar a meter a mão na massa e instalar o nosso cluster Kubernetes de Lab o qual usaremos por toda essa jornada.
Antes de começar...
Para acompanhar essa série sobre Kubernetes você vai precisar de:
- No mínimo 2 hosts com 2GB de RAM e 10GB de disco **.
- Sistema operacional CentOS 7 instalado (pode ser a versão minimal) *.
- Todos os hosts devem estar na mesma rede e com acesso à internet.
Configurações iniciais do CentOS
Antes de mais nada precisamos configurar o nosso Sistema Operacional CentOS para atender os requisitos necessários para instalação do cluster Kubernetes.
Desabilitando o SELinux
O Kubernetes não tem compatibilidade com o SELinux em modo "enforcing", geralmente o padrão do CentOS. Então, devemos desabilita-lo.
Para desativar o SELinux, execute:
sudo setenforce 0 && sed -i 's/^SELINUX=enforcing$/SELINUX=disabled/' /etc/selinux/config
Carregando os módulos necessários
É necessário que o módulo br_filter esteja ativo no S.O, então vamos checar se módulo já está carregado.
Execute:
sudo lsmod | grep br_netfilter
Se o comando não teve resultado, o módulo não está ativo, então, vamos ativa-lo. Execute:
sudo modprobe br_netfilter
Vamos checar novamente com o lsmod.
Desta
vez o resultado deve ser similar a este:
$ sudo lsmod | grep br_netfilter
br_netfilter 22248 0
bridge 107106 1 br_netfilter
Desabilitando o firewall
A instalação do Kubernetes irá configurar as regras de firewall para nós, então, neste momento, vamos desativar o firewall para que não ocorram problemas com as regras que já estão ativas.
Para desabilitar o Iptables, execute:
sudo systemctl disable firewalld --now
Vamos aproveitar e garantir que algumas flags do nosso Iptables estejam devidamente configuradas para quando ele for reativado na instalação do Kubernetes.
Execute:
sudo echo 1 > /proc/sys/net/bridge/bridge-nf-call-iptables &&
sudo echo 1 > /proc/sys/net/bridge/bridge-nf-call-ip6tables &&
sudo echo 1 > /proc/sys/net/ipv4/ip_forward
Desabilitando SWAP
O Kubernetes não pode ser inicializado se o SWAP estiver ativo. Então, precisamos desativa-lo.
Para desativar o SWAP execute:
sudo swapoff -a && sed -i '/ swap / s/^/#/' /etc/fstab
Para verificar se o SWAP foi desativado com sucesso
vamos checar o arquivo /proc/swaps
. Execute:
cat /proc/swaps
O comando não deve retornar resultado, assim como no exemplo a seguir:
$ cat /proc/swaps
Filename Type Size Used Priority
Configurando a rede
Agora chegou a hora de configurar a interface de rede do host e para garantir que não tenhamos problemas em nosso cluster devemos seguir estes passos com atenção.
Primeiro, vamos configurar o endereço IP do host como estático, isso vai garantir que o DHCP não tenha ação sobre nossa interface de rede e não irá alterar o endereço IP. Podemos fazer assim:
Vamos identificar qual interface de rede está conectada em nossa rede local, execute:
nmcli c show --active
O resultado deve ser algo parecido com esse:
$ nmcli c show --active
NAME UUID TYPE DEVICE
ens33 6a62f935-8cdd-4f51-890e-98f3dc64b0dc ethernet ens33
No meu host a interface se chama ens33. Agora vamos consultar algumas informações desta interface.
Execute (não se esqueça de alterar o nome interface):
nmcli c show ens33 |grep -E "ipv4.method|IP4.ADDRESS|IP4.DNS|IP4.GATEWAY"
Com o comando anterior conseguimos confirmar que a nossa interface está usando DHCP, o endereço IP, o endereço IP do gateway e o endereço IP do DNS da nossa interface, como no exemplo a seguir:
nmcli c show ens33 |grep -E "ipv4.method|IP4.ADDRESS|IP4.DNS|IP4.GATEWAY"
ipv4.method: auto
IP4.ADDRESS[1]: 192.168.130.138/24
IP4.GATEWAY: 192.168.130.2
IP4.DNS[1]: 192.168.130.2
Agora vamos alterar nossa interface para o modo estático, mas vamos usar as mesmas configurações de endereço IP.
Para o meu host o comando a ser executado fica assim (não esqueça de mudar o nome da interface):
sudo nmcli c mod ens33 connection.autoconnect yes \
ipv4.method "manual" \
ipv4.addresses $(nmcli c show ens33 |grep -E "IP4.ADDRESS" | awk '{print $2}') \
ipv4.gateway $(nmcli c show ens33 |grep -E "IP4.GATEWAY" | awk '{print $2}') \
ipv4.dns $(nmcli c show ens33 |grep -E "IP4.DNS" | awk '{print $2}') \
ipv4.dns-search "k8scluster"
Os campos desse comando representam o seguinte:
- connection.autoconnect: Configura a interface para iniciar automaticamente com o S.O.
- ipv4.method: Configura a interface para endereço IP manual (estático).
- ipv4.addresses: O endereço IP da interface.
- ipv4.dns: Endereço IP para consulta DNS.
- ipv4.dns-search: O nome do domínio local do nosso cluster.
Agora, se consultarmos nossa interface novamente, teremos um resultado similar a esse:
$ nmcli c show ens33 |grep -E "ipv4.method|IP4.ADDRESS|IP4.DNS|IP4.GATEWAY"
ipv4.method: manual
IP4.ADDRESS[1]: 192.168.130.138/24
IP4.GATEWAY: 192.168.130.2
IP4.DNS[1]: 192.168.130.2
Configurando os repositórios
Vamos configurar o CentOS para ter os repositórios de instalação e os pacotes necessários.
Primeiro vamos atualizar nosso CentOS. Execute:
sudo yum update -y && sudo yum install -y yum-utils
Agora vamos configurar o repositório do Docker. Execute:
yum-config-manager --add-repo \
https://download.docker.com/linux/centos/docker-ce.repo
E por fim o repositório do Kubernetes. Execute:
cat << EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kube*
EOF
Pronto, agora já temos nosso host com o CentOS configurado para seguirmos com a instalação do Kubernetes e a configuração do nosso cluster.
Instalando o Kubernetes
Depois que todas as configurações do CentOS foram realizadas, está na hora de iniciar a instalação do Kubernetes.
Para iniciar, precisamos instalar alguns pré-requisitos para o nosso CentOS. Execute:
sudo yum install -y device-mapper-persistent-data lvm2
Agora podemos seguir com a instalação de um serviço de containers. Em nosso cluster vamos usar o Docker. Execute:
sudo yum install -y docker-ce-19.03.13-3.el7
Por último podemos instalar o Kubernetes.
sudo yum install -y kubelet-1.19.4-0 kubeadm-1.19.4-0 kubectl-1.19.4-0 --disableexcludes=kubernetes
Iniciando os serviços do Kubernetes
Vamos inicializar o Docker e o Kubernetes e também habilitá-los para iniciar automaticamente no boot do S.O.
sudo systemctl enable docker kubelet --now
Se tudo ocorreu bem até aqui, agora temos nossos hosts devidamente configurados e prontos para seguir com a instalação do nosso cluster Kubernetes.
A seguir vamos iniciar o nosso cluster configurando o host Master e o nodes Workers.
Iniciando um Cluster Kubernetes
Um cluster Kubernetes deve ter no mínimo um host Master e outro Worker, em nosso cluster Lab vamos iniciar com esses dois hosts.
Master
O host master é o principal componente do nosso cluster Kubernetes, então ele deve ser configurado primeiro.
Configurando o hostname
Para mantermos um padrão daqui em diante vamos dar o nome aos nossos hosts seguindo o modelo k8s-ROLE, onde ROLE será a função do host em nosso cluster Kubernetes.
Para o host master vamos nomea-lo de k8s-master. Para isso, execute:
sudo hostnamectl set-hostname k8s-master
Configurando a resolução de nomes
Precisamos garantir que os hosts do nosso cluster
possam resolver seus nomes na rede, e como não temos uma infraestrutura de DNS para a rede local, vamos
configurar o arquivo /etc/hosts
em todos os hosts para conseguirmos resolver os nomes em
nosso cluster.
No arquivo hosts vamos adicionar o endereço IP e o nome que demos ao nosso host.
Execute (não se esqueça de alterar o endereço IP para o endereço da sua interface):
echo "192.168.130.138 k8s-master k8s-master.k8scluster" >> /etc/hosts
Inicializando o Cluster Kubernetes
Agora já podemos começar a instalação do nosso cluster Kubernetes, vamos inicializar o nosso host Master.
Já sabemos o endereço IP do nosso host Master, mas vamos confirmar novamente:
$ nmcli c show ens33 |grep -E "IP4.ADDRESS"
IP4.ADDRESS[1]: 192.168.130.138/24
Aqui podemos confirmar que o endereço IP da minha interface ens33 é 192.168.130.138 e a minha rede local é 192.168.130.0/24 (máscara 255.255.255.0).
Agora vamos ajudar os parâmetros de inicialização do cluster Kubernetes. Usaremos dois parâmetros.
- apiserver-advertise-address: Será endereço IP do host.
- pod-network-cid: Deve ser uma rede que não conflite com bloco de da interface local do host. No meu caso tem que ser diferente de 192.168.130.0/24.
Com os parâmetros ajustados. Execute:
kubeadm init --apiserver-advertise-address=192.168.130.138 --pod-network-cidr=172.20.0.0/16
Após a conclusão da instalação, copie o comando com o Token, iremos utilizar esse comando para ingressar os nossos nodes Worker posteriormente.
kubeadm join 192.168.130.138:6443 --token 6krn26.htncib0efp5qwcuv \
--discovery-token-ca-cert-hash sha256:e9e8a0e93f6f3a4be78644bd2b6e49561281e0fcc737f239791474981abaf26c
Configurando a console
Para que possamos executar comandos em nosso cluster Kubernetes sem problemas, devemos configurar a nossa console. Execute:
export KUBECONFIG=/etc/kubernetes/admin.conf
echo "export KUBECONFIG=/etc/kubernetes/admin.conf" >> ~/.bash_profile
Agora tudo pronto! Vamos executar o nosso primeiro comando no cluster para ver seu status, execute:
kubectl cluster-info
Se tudo estiver OK o resultado deve ser algo assim:
$ kubectl cluster-info
Kubernetes master is running at https://192.168.130.138:6443
KubeDNS is running at https://192.168.130.138:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
Adicionando nodes Worker ao cluster
Sem Workers nosso cluster ainda não está completo e para isso, primeiro vamos configurar nossos hosts e depois vamos adicioná-los ao cluster com a função Worker.
Configurando o hostname
Seguindo o padrão de nomenclatura que já definimos, vamos nomear nossos hosts Workers como k8s-worker1, k8s-worker2 etc...
Para nosso primeiro Worker, execute:
sudo hostnamectl set-hostname k8s-worker1
Configurando a resolução de nomes
Quando configuramos o host Master adicionamos ao
arquivo /etc/hosts
apenas o endereço IP e o nome do host Master. Agora estamos configurando
a resolução de nomes em nosso Worker, então, precisamos adicionar além das informações do Worker as
informações do Master também.
Vamos seguir basicamente os mesmos passos que fizemos
no Master, vamos descobrir o endereço IP do Worker e configurar o arquivo /etc/hosts
Para confirmar o IP do host Worker, execute:
nmcli c show ens33 |grep -E "IP4.ADDRESS"
Meu Worker tem o IP 192.168.130.139:
$ nmcli c show ens33 |grep -E "IP4.ADDRESS"
IP4.ADDRESS[1]: 192.168.130.139/24
Agora vamos adicionar as informações do Worker e
também do Master no arquivo /etc/hosts
do nosso host Worker.
Execute (não esqueça de alterar os endereços IPs):
cat << EOF >> /etc/hosts
192.168.130.138 k8s-master k8s-master.k8scluster
192.168.130.139 k8s-worker1 k8s-worker1.k8scluster
EOF
Para finalizar também temos que atualizar o arquivo
/etc/hosts
do host Master com as informações do nosso Worker.
No host Master, execute (altere o endereço IP para o endereço do seu host Worker):
echo "192.168.130.139 k8s-worker1 k8s-worker1.k8scluster" >> /etc/hosts
Incluindo o Worker no cluster
No host Worker vamos executar o
kubeadm join
com as informações de Token (o Token, assim como o comando completo foram
informados após a instalação do Master).
Execute (execute o comando que pegamos após a instalação do Master):
kubeadm join 192.168.130.138:6443 --token 6krn26.htncib0efp5qwcuv \
--discovery-token-ca-cert-hash sha256:e9e8a0e93f6f3a4be78644bd2b6e49561281e0fcc737f239791474981abaf26c
Ao concluir você deve receber a mensagem que o node foi incluído ao cluster, com no exemplo:
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Configurando a rede do Cluster Kubernetes
Agora temos um cluster Kubernetes completo, Master e Workers rodando e tudo pronto. Nem tudo...
Anteriormente executamos o comando o
kubectl cluster-info
para verificar o status do nosso cluster, agora vamos ver como estão
os nodes do nosso cluster. No host Master, execute:
kubectl get node
Repare o status, nossos hosts ainda não estão Ready.
$ kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master NotReady master 44m v1.19.4
k8s-worker1 NotReady 2m47s v1.19.4
Vamos dar uma olhada nos Pods do nosso cluster. Execute:
kubectl get pod --all-namespaces
Repare que alguns Pods coredns-* estão com o status Pending. Isso não é bom.
kubectl get pod --all-namespaces
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-system coredns-f9fd979d6-7p46w 0/1 Pending 0 4m37s
kube-system coredns-f9fd979d6-sjlcz 0/1 Pending 0 4m37s
kube-system etcd-k8s-master 1/1 Running 0 4m37s
kube-system kube-apiserver-k8s-master 1/1 Running 0 4m37s
kube-system kube-controller-manager-k8s-master 1/1 Running 0 4m37s
kube-system kube-proxy-dxvtn 1/1 Running 0 4m37s
kube-system kube-scheduler-k8s-master 1/1 Running 0 4m37s
O que está acontecendo é devido a ainda não termos um componente de rede configurado em nosso cluster.
Precisamos instalar um Cluster Network Interface ou CNI. Este componente é responsável por gerenciar a comunicação entre os nodes, os pods e containers do nosso cluster Kubernetes.
Existem diversas alternativas de CNI compatíveis com o Kubernetes que podem ser instalados, em nosso cluster vamos utilizar o Calico.
Instalando o Calico no Cluster Kubernetes
Instalar um CNI no Kubernetes geralmente é uma tarefa simples, em nosso cluster, para instalar o Calico, vamos apenas baixar os arquivos YAML.
No host Master, execute:
curl https://docs.projectcalico.org/manifests/tigera-operator.yaml -o tigera-operator.yaml &&
curl https://docs.projectcalico.org/manifests/custom-resources.yaml -o custom-resources.yaml
Vamos conferir o arquivo de instalação do Calico e confirmar se as configurações do Calico estão de acordo com as configurações do nosso cluster. Se não, vamos fazer os ajustes se necessários:
cat custom-resources.yaml
Repare o item de configuração cidr, o endereço no arquivo é 192.168.0.0/16.
$ cat custom-resources.yaml
# This section includes base Calico installation configuration.
# For more information, see: https://docs.projectcalico.org/v3.18/reference/installation/api#operator.tigera.io/v1.Installation
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
name: default
spec:
# Configures Calico networking.
calicoNetwork:
# Note: The ipPools section cannot be modified post-install.
ipPools:
- blockSize: 26
cidr: 192.168.0.0/16
encapsulation: VXLANCrossSubnet
natOutgoing: Enabled
nodeSelector: all()
Na instalação do Master customizamos a configuração do nosso endereço de rede de Pods para 172.20.0.0/16 usando o parâmetro --pod-network-cidr. Devemos alterar a configuração do Calico para corresponder ao mesmo endereço que estamos usando em nosso cluster.
Vamos alterar o cidr do nosso arquivo. Execute:
sed -i 's/192.168.0.0/172.20.0.0/' custom-resources.yaml
Com o endereço da rede de Pods configurado, podemos seguir com a instalação do Calico. Execute:
kubectl create -f tigera-operator.yaml &&
kubectl create -f custom-resources.yaml
Agora vamos observar se os Pods do coredns alteram o status de Pending para Running. Execute:
watch kubectl get pods -n kube-system
Pode levar alguns segundos (ou minutos) para que os Pods fiquem Running.
Every 2.0s: kubectl get pod -n kube-system Sat Feb 6 17:35:11 2021
NAME READY STATUS RESTARTS AGE
coredns-f9fd979d6-79vq7 1/1 Running 0 6m57s
coredns-f9fd979d6-q9ms5 1/1 Running 0 6m57s
etcd-k8s-master 1/1 Running 0 7m6s
kube-apiserver-k8s-master 1/1 Running 0 7m6s
kube-controller-manager-k8s-master 1/1 Running 0 7m6s
kube-proxy-lct2l 1/1 Running 0 6m57s
kube-scheduler-k8s-master 1/1 Running 0 7m6s
Com todos os Pods Running, vamos checar novamente como estão nossos nodes. Execute:
kubectl get node
Desta vez o status deve ser Ready.
$ kubectl get node
NAME STATUS ROLES AGE VERSION
k8s-master Ready master 72m v1.19.4
k8s-worker1 Ready 31m v1.19.4
Agora sim! Tudo pronto com nosso cluster Kubernetes de lab.
Que tal já começarmos a fazer algumas coisinhas?
Primeiros passos no Kubernetes
Agora que já temos nosso cluster Kubernetes rodando perfeitamente, está na hora de começarmos a soltar as asinhas e explorar nosso Lab.
Para começar, vamos criar nosso primeiro Pod, um servidor Web com uma página Web.
No host Master, execute:
kubectl apply -f - <<EOF
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-hello
data:
index.html: |
<h1>Hello World! o/</h1>
---
apiVersion: v1
kind: Pod
metadata:
name: nginx-demo
labels:
env: demo
spec:
containers:
- name: nginx-demo
image: nginx
volumeMounts:
- mountPath: /usr/share/nginx/html
name: nginx-hello
volumes:
- name: nginx-hello
configMap:
name: nginx-hello
EOF
Vamos ver como está o nosso primeiro Pod:
kubectl get pod
Parece que temos nossa primeira aplicação rodando em nosso cluster Kubernetes.
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-demo 1/1 Running 0 66s
Mas agora você deve estar se perguntando. Legal, tá rodando, mas como acesso a página Web do meu Pod?
Para isso precisamos "expor" nosso Pod para que as conexões de fora do nosso cluster cheguem até ele.
Para expor o Pod, execute:
kubectl expose pod nginx-demo --port=80 --type=NodePort
Nosso Pod já está acessível, mas em qual endereço?
Vamos ver qual a URL para acessar nossa página. Execute:
echo http://$(kubectl get pod nginx-demo -o jsonpath='{.status.hostIP}'):$(kubectl get service nginx-demo -o jsonpath='{.spec.ports[].nodePort}')
Agora é só acessar a URL pelo navegador!
Conclusão
Chegamos ao fim do primeiro artigo da série que irá lhe ajudar a entender melhor o Kubernetes e como ele funciona.
Sem muito blá blá blá, hoje colocamos a mão na massa e instalamos o nosso Cluster Kubernetes de Lab. Se você ficou com dúvidas, não se preocupe, o objetivo do primeiro artigo era apenas preparar o terreno e não detalhar as configurações. Os detalhes veremos a partir daqui.
No próximo artigo vamos entrar na arquitetura do Kubernetes e ver alguns dos principais componentes do nosso cluster, vamos entender o que são os Pods e como podemos planejar melhor nossas aplicações usando Deployments. Também vamos aprender como escalar nossas aplicações e publicar "expor" as aplicações para acesso externo de forma muito mais eficiente. Por fim, também instalar uma interface Web para gerenciamento do Kubernetes, o Kubernetes Dashboard.
Espero que você tenha gostado deste primeiro artigo. Se achou legal ou não, deixe um comentário, a sua mensagem pode me ajudar a trazer um conteúdo cada vez melhor!
Comentários
Postar um comentário