26 MetalLB em K3s (usando o modo de camada 3) #
O MetalLB é uma implementação de balanceador de carga para clusters Kubernetes bare metal, usando protocolos de roteamento padrão.
Neste guia, vamos demonstrar como implantar o MetalLB no modo de camada 3 (L3) do BGP.
26.1 Por que usar o MetalLB? #
O MetalLB é uma opção atrativa para balanceamento de carga em clusters Kubernetes bare metal por vários motivos:
Integração nativa com o Kubernetes: o MetalLB se integra perfeitamente ao Kubernetes, o que facilita a implantação e o gerenciamento usando as ferramentas e práticas conhecidas do Kubernetes.
Compatibilidade com bare metal: ao contrário dos balanceadores de carga com base na nuvem, o MetalLB foi especificamente projetado para implantações no local, em que os balanceadores de carga tradicionais podem não estar disponíveis ou ser viáveis.
Suporte a vários protocolos: o MetalLB oferece suporte aos modos de camada 2 e 3 do BGP (Border Gateway Protocol), proporcionando flexibilidade para diferentes arquiteturas e requisitos de rede.
Alta disponibilidade: ao distribuir as responsabilidades de balanceamento de carga por vários nós, o MetalLB garante alta disponibilidade e confiabilidade aos seus serviços.
Escalabilidade: o MetalLB processa implantações de grande escala, ajustando a escala no cluster Kubernetes para atender à crescente demanda.
No modo de camada 2, um nó assume a responsabilidade de anunciar um serviço para a rede local. Da perspectiva da rede, simplesmente parece que a máquina tem vários endereços IP atribuídos à interface de rede.
A maior vantagem do modo de camada 2 é a sua universalidade: ele funciona em qualquer rede Ethernet, sem a necessidade de hardware especial nem de roteadores sofisticados.
26.2 MetalLB em K3s (usando L3) #
Neste início rápido, o modo de L3 é usado. Por essa razão, precisamos ter os roteadores vizinhos com recursos de BGP dentro do intervalo de rede.
26.3 Pré-requisitos #
Um cluster K3s no qual o MetalLB será implantado.
Roteadores na rede com suporte ao protocolo BGP.
Um endereço IP livre no intervalo de rede para o serviço. Neste exemplo,
192.168.10.100
Você deve garantir que esse endereço IP não esteja atribuído. Em um ambiente DHCP, esse endereço não deve fazer parte do pool DHCP para evitar atribuições duplas.
26.4 Configuração para anunciar endereços IP de serviços #
O BGP anuncia imediatamente o endereço IP de um serviço a todos os pares configurados. Esses pares, que normalmente são roteadores, receberão a rota para o endereço IP de cada serviço com uma máscara de rede de 32 bits. Neste exemplo, usaremos um roteador com base em FRR que está na mesma rede que o nosso cluster. Em seguida, usaremos o recurso BGP do MetalLB para anunciar um serviço a esse roteador com base em FRR.
26.5 Implantação #
Vamos usar o gráfico Helm do MetalLB publicado como parte da solução SUSE Edge:
helm install \
metallb oci://registry.suse.com/edge/charts/metallb \
--namespace metallb-system \
--create-namespace
while ! kubectl wait --for condition=ready -n metallb-system $(kubectl get\
pods -n metallb-system -l app.kubernetes.io/component=controller -o name)\
--timeout=10s; do
sleep 2
done26.6 Configuração #
Neste ponto, a instalação é concluída. Crie um
IPAddressPool:
cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: bgp-pool
namespace: metallb-system
labels:
app: httpd
spec:
addresses:
- 192.168.10.100/32
autoAssign: true
avoidBuggyIPs: false
serviceAllocation:
namespaces:
- metallb-system
priority: 100
serviceSelectors:
- matchExpressions:
- key: serviceType
operator: In
values:
- httpd
EOFConfigure um
BGPPeer.
O roteador FRR tem ASN 1000, enquanto o nosso BGPPeer
terá 1001. Podemos ver também que o roteador FRR tem o endereço IP
192.168.3.140.
cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta2
kind: BGPPeer
metadata:
namespace: metallb-system
name: mypeertest
spec:
peerAddress: 192.168.3.140
peerASN: 1000
myASN: 1001
routerID: 4.4.4.4
EOFCrie o BGPAdvertisement (L3):
cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: BGPAdvertisement
metadata:
name: bgpadvertisement-test
namespace: metallb-system
spec:
ipAddressPools:
- bgp-pool
EOF26.7 Utilização #
Crie um aplicativo de exemplo com um serviço. Neste caso, o endereço IP do
IPAddressPoolé192.168.10.100para o serviço.
cat <<- EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: httpd-deployment
namespace: metallb-system
labels:
app: httpd
spec:
replicas: 3
selector:
matchLabels:
pod-label: httpd
template:
metadata:
labels:
pod-label: httpd
spec:
containers:
- name: httpdcontainer
image: image: docker.io/library/httpd:2.4
ports:
- containerPort: 80
protocol: TCP
restartPolicy: Always
---
apiVersion: v1
kind: Service
metadata:
name: http-service
namespace: metallb-system
labels:
serviceType: httpd
spec:
selector:
pod-label: httpd
type: LoadBalancer
ports:
- protocol: TCP
port: 8080
name: 8080-tcp
targetPort: 80
EOFPara verificar, faça login no roteador FRR para ver as rotas criadas com base no anúncio feito por BGP.
42178089cba5# show ip bgp all
For address family: IPv4 Unicast
BGP table version is 3, local router ID is 2.2.2.2, vrf id 0
Default local pref 100, local AS 1000
Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
Network Next Hop Metric LocPrf Weight Path
* i172.16.0.0/24 1.1.1.1 0 100 0 i
*> 0.0.0.0 0 32768 i
* i172.17.0.0/24 3.3.3.3 0 100 0 i
*> 0.0.0.0 0 32768 i
*= 192.168.10.100/32
192.168.3.162 0 1001 i
*= 192.168.3.163 0 1001 i
*> 192.168.3.161 0 1001 i
Displayed 3 routes and 7 total paths
kubectl get svc -n hello-kubernetes
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hello-kubernetes LoadBalancer 10.43.127.75 192.168.122.11 80:31461/TCP 8sSe esse roteador é o gateway padrão da sua rede, você pode executar o comando
curlde uma caixa nessa rede para verificar se ele pode acessar o aplicativo de amostra httpd.
# curl http://192.168.10.100:8080
<html><body><h1>It works!</h1></body></html>
#