27 MetalLB na frente do servidor da API Kubernetes #
Este guia demonstra o uso do serviço MetalLB para expor a API RKE2/K3s
externamente em um cluster HA com três nós de plano de controle. Para isso,
um serviço Kubernetes do tipo LoadBalancer será criado
manualmente. Em seguida, o objeto EndpointSlices será
automaticamente criado para manter os IPs de todos os nós de plano de
controle disponíveis no cluster. Para sempre manter o EndpointSlices
sincronizado com os eventos que ocorrem no cluster (adição/remoção de nó ou
um nó que fica offline), o Endpoint Copier Operator (Capítulo 20, Endpoint Copier Operator) será implantado. O operador monitora os eventos
ocorridos no EndpointSlices padrão do kubernetes e
atualiza o que é gerenciado automaticamente para mantê-los em
sincronia. Como o serviço gerenciado é do tipo
LoadBalancer, o MetalLB atribui a ele um
ExternalIP estático. Esse ExternalIP
será usado para comunicação com o API Server.
27.1 Pré-requisitos #
Três hosts para implantar o RKE2/K3s em cima.
Certifique-se de que os hosts tenham nomes diferentes.
Para teste, eles podem ser máquinas virtuais.
Pelo menos 2 IPs disponíveis na rede (um para o Traefik/Nginx e outro para o serviço gerenciado).
Helm
27.2 Instalando o RKE2/K3s #
Se você não deseja usar um cluster novo, mas um existente, ignore esta etapa e avance para a próxima.
Primeiramente, é necessário reservar um IP livre para usar mais adiante como
ExternalIP do serviço gerenciado.
Acesse o primeiro host por SSH e instale a distribuição desejada no modo de cluster.
Para RKE2:
# Export the free IP mentioned above
export VIP_SERVICE_IP=<ip>
curl -sfL https://get.rke2.io | INSTALL_RKE2_EXEC="server \
--write-kubeconfig-mode=644 --tls-san=${VIP_SERVICE_IP} \
--tls-san=https://${VIP_SERVICE_IP}.sslip.io" sh -
systemctl enable rke2-server.service
systemctl start rke2-server.service
# Fetch the cluster token:
RKE2_TOKEN=$(tr -d '\n' < /var/lib/rancher/rke2/server/node-token)Para K3s:
# Export the free IP mentioned above
export VIP_SERVICE_IP=<ip>
export INSTALL_K3S_SKIP_START=false
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server --cluster-init \
--disable=servicelb --write-kubeconfig-mode=644 --tls-san=${VIP_SERVICE_IP} \
--tls-san=https://${VIP_SERVICE_IP}.sslip.io" K3S_TOKEN=foobar sh -Verifique se o sinalizador --disable=servicelb foi
inserido no comando k3s server.
A partir de agora, os comandos devem ser executados na máquina local.
Para acessar o servidor da API de um ambiente externo, o IP da VM do RKE2/K3s será usado.
# Replace <node-ip> with the actual IP of the machine
export NODE_IP=<node-ip>
export KUBE_DISTRIBUTION=<k3s/rke2>
scp ${NODE_IP}:/etc/rancher/${KUBE_DISTRIBUTION}/${KUBE_DISTRIBUTION}.yaml ~/.kube/config && sed \
-i '' "s/127.0.0.1/${NODE_IP}/g" ~/.kube/config && chmod 600 ~/.kube/config27.3 Configurando um cluster existente #
Esta etapa é válida apenas se você pretende usar um cluster RKE2/K3s existente.
Modifique os sinalizadores tls-san para usar um cluster
existente. Além disso, o LB servicelb deve ser
desabilitado no K3s.
Para alterar os sinalizadores dos servidores RKE2 ou K3s, você precisa
modificar o arquivo /etc/systemd/system/rke2.service ou
/etc/systemd/system/k3s.service em todas as VMs no
cluster, dependendo da distribuição.
Insira os sinalizadores em ExecStart. Por exemplo:
Para RKE2:
# Replace the <vip-service-ip> with the actual ip
ExecStart=/usr/local/bin/rke2 \
server \
'--write-kubeconfig-mode=644' \
'--tls-san=<vip-service-ip>' \
'--tls-san=https://<vip-service-ip>.sslip.io' \Para K3s:
# Replace the <vip-service-ip> with the actual ip
ExecStart=/usr/local/bin/k3s \
server \
'--cluster-init' \
'--write-kubeconfig-mode=644' \
'--disable=servicelb' \
'--tls-san=<vip-service-ip>' \
'--tls-san=https://<vip-service-ip>.sslip.io' \Na sequência, os seguintes comandos devem ser executados para carregar as novas configurações:
systemctl daemon-reload
systemctl restart ${KUBE_DISTRIBUTION}27.4 Instalando o MetalLB #
Para implantar o MetalLB, use o guia do MetalLB no K3s
(Capítulo 25, MetalLB no K3s (usando o modo de camada 2)).
NOTA: Garanta que o endereço IP
VIP_SERVICE_IP não se sobreponha ao
IPAddressPools existente no cluster.
Crie um IpAddressPool separado e um
L2Advertisement para uso apenas com o serviço gerenciado.
NOTA: O IPAddressPool a seguir será
atribuído a um serviço do tipo LoadBalancer no namespace
padrão. Se houver vários serviços
LoadBalancer nele, outros ServiceSelectors
poderão ser configurados para corresponder a esse serviço VIP de maneira
explícita.
# Export the VIP_SERVICE_IP on the local machine
# Replace with the actual IP
export VIP_SERVICE_IP=<ip>
cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: kubernetes-vip-ip-pool
namespace: metallb-system
spec:
addresses:
- ${VIP_SERVICE_IP}/32
serviceAllocation:
priority: 100
namespaces:
- default
EOFcat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: kubernetes-vip-l2-adv
namespace: metallb-system
spec:
ipAddressPools:
- kubernetes-vip-ip-pool
EOF27.5 Instalando o Endpoint Copier Operator #
helm install \
endpoint-copier-operator oci://registry.suse.com/edge/charts/endpoint-copier-operator \
--namespace endpoint-copier-operator \
--create-namespaceO comando acima implanta o operador
endpoint-copier-operator com duas réplicas: uma será a
líder e a outra assumirá a função de líder se necessário.
Agora o serviço kubernetes-vip deve estar implantado, que
será reconciliado pelo operador, e será criado um EndpointSlices com as
portas e o IP configurados.
Para RKE2:
cat <<-EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: kubernetes-vip
namespace: default
spec:
ports:
- name: rke2-api
port: 9345
protocol: TCP
targetPort: 9345
- name: k8s-api
port: 6443
protocol: TCP
targetPort: 6443
type: LoadBalancer
EOFPara K3s:
cat <<-EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: kubernetes-vip
namespace: default
spec:
internalTrafficPolicy: Cluster
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- name: https
port: 6443
protocol: TCP
targetPort: 6443
sessionAffinity: None
type: LoadBalancer
EOFVerifique se o serviço kubernetes-vip tem o endereço IP
correto:
kubectl get service kubernetes-vip -n default \
-o=jsonpath='{.status.loadBalancer.ingress[0].ip}'Verifique se os recursos kubernetes-vip-* e
kubernetes do EndpointSlices no namespace
padrão apontam para os mesmos IPs.
kubectl get endpointslices | grep kubernetesSe tudo estiver correto, a última coisa a se fazer é usar o
VIP_SERVICE_IP no Kubeconfig.
sed -i '' "s/${NODE_IP}/${VIP_SERVICE_IP}/g" ~/.kube/configA partir de agora, o kubectl sempre vai passar pelo
serviço kubernetes-vip.
27.6 Adicionando nós do plano de controle #
Para monitorar o processo inteiro, é possível abrir mais duas guias do terminal.
Primeiro terminal:
watch kubectl get nodesSegundo terminal:
watch kubectl get endpointslicesAgora execute os comandos a seguir no segundo e no terceiro nó.
Para RKE2:
# Export the VIP_SERVICE_IP in the VM
# Replace with the actual IP
export VIP_SERVICE_IP=<ip>
curl -sfL https://get.rke2.io | INSTALL_RKE2_TYPE="server" sh -
systemctl enable rke2-server.service
mkdir -p /etc/rancher/rke2/
cat <<EOF > /etc/rancher/rke2/config.yaml
server: https://${VIP_SERVICE_IP}:9345
token: ${RKE2_TOKEN}
EOF
systemctl start rke2-server.servicePara K3s:
# Export the VIP_SERVICE_IP in the VM
# Replace with the actual IP
export VIP_SERVICE_IP=<ip>
export INSTALL_K3S_SKIP_START=false
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server \
--server https://${VIP_SERVICE_IP}:6443 --disable=servicelb \
--write-kubeconfig-mode=644" K3S_TOKEN=foobar sh -