documentation.suse.com / Documentação do SUSE Edge / Guias de Procedimentos / MetalLB na frente do servidor da API Kubernetes

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

Nota
Nota

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 -
Nota
Nota

Verifique se o sinalizador --disable=servicelb foi inserido no comando k3s server.

Importante
Importante

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/config

27.3 Configurando um cluster existente

Nota
Nota

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
EOF
cat <<-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
EOF

27.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-namespace

O 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
EOF

Para 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
EOF

Verifique 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 kubernetes

Se 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/config

A 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 nodes

Segundo terminal:

watch kubectl get endpointslices

Agora 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.service

Para 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 -