25 MetalLB no K3s (usando o modo de camada 2) #
O MetalLB é uma implementação de balanceador de carga para clusters Kubernetes bare metal, usando protocolos de roteamento padrão.
Neste guia, demonstramos como implantar o MetalLB no modo de camada 2 (L2).
25.1 Por que usar este método #
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.
Compatível com vários protocolos: o MetalLB é compatível com os modos de camada 2 e BGP (Border Gateway Protocol), proporcionando flexibilidade de acordo com as 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.
25.2 MetalLB no K3s (usando L2) #
Neste início rápido, o modo L2 será usado. Isso significa que não precisamos de nenhum equipamento de rede especial, mas de três IPs livres no intervalo de rede.
25.3 Pré-requisitos #
Um cluster K3s no qual o MetalLB será implantado.
O K3S vem com o próprio balanceador de carga de serviço chamado
Klipper. Você precisa
desabilitá-lo para executar o MetalLB. Para desabilitar o Klipper, o
K3s precisa ser instalado com o sinalizador
--disable=servicelb
.
Helm
Três endereços IP livres dentro do intervalo de rede. Neste exemplo,
192.168.122.10-192.168.122.12
Garanta que esses endereços IP não estejam atribuídos. Em um ambiente DHCP, esses endereços não devem fazer parte do pool DHCP para evitar atribuições duplas.
25.4 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
done
25.5 Configuração #
Neste ponto, a instalação foi concluída. Agora é hora de configurar usando nossos valores de exemplo:
cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
name: ip-pool
namespace: metallb-system
spec:
addresses:
- 192.168.122.10/32
- 192.168.122.11/32
- 192.168.122.12/32
EOF
cat <<-EOF | kubectl apply -f -
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
name: ip-pool-l2-adv
namespace: metallb-system
spec:
ipAddressPools:
- ip-pool
EOF
Agora ele está pronto para uso. É possível personalizar vários componentes no modo L2, por exemplo:
E muito mais para BGP.
25.5.1 Traefik e MetalLB #
O Traefik é implantado por padrão com o K3s (ele pode
ser desabilitado com --disable=traefik
) e exposto
como LoadBalancer
(para uso com o Klipper). No entanto,
como o Klipper precisa ser desabilitado, o serviço Traefik para entrada
ainda é um tipo de LoadBalancer
. Sendo assim, no momento
da implantação do MetalLB, o primeiro IP será automaticamente atribuído à
entrada do Traefik.
# Before deploying MetalLB
kubectl get svc -n kube-system traefik
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
traefik LoadBalancer 10.43.44.113 <pending> 80:31093/TCP,443:32095/TCP 28s
# After deploying MetalLB
kubectl get svc -n kube-system traefik
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
traefik LoadBalancer 10.43.44.113 192.168.122.10 80:31093/TCP,443:32095/TCP 3m10s
Isso será aplicado mais adiante (Seção 25.6.1, “Ingress com MetalLB”) no processo.
25.6 Uso #
Vamos criar uma implantação de exemplo:
cat <<- EOF | kubectl apply -f -
---
apiVersion: v1
kind: Namespace
metadata:
name: hello-kubernetes
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: hello-kubernetes
namespace: hello-kubernetes
labels:
app.kubernetes.io/name: hello-kubernetes
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: hello-kubernetes
namespace: hello-kubernetes
labels:
app.kubernetes.io/name: hello-kubernetes
spec:
replicas: 2
selector:
matchLabels:
app.kubernetes.io/name: hello-kubernetes
template:
metadata:
labels:
app.kubernetes.io/name: hello-kubernetes
spec:
serviceAccountName: hello-kubernetes
containers:
- name: hello-kubernetes
image: "paulbouwer/hello-kubernetes:1.10"
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 8080
protocol: TCP
livenessProbe:
httpGet:
path: /
port: http
readinessProbe:
httpGet:
path: /
port: http
env:
- name: HANDLER_PATH_PREFIX
value: ""
- name: RENDER_PATH_PREFIX
value: ""
- name: KUBERNETES_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: KUBERNETES_POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: KUBERNETES_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: CONTAINER_IMAGE
value: "paulbouwer/hello-kubernetes:1.10"
EOF
E, por fim, o serviço:
cat <<- EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: hello-kubernetes
namespace: hello-kubernetes
labels:
app.kubernetes.io/name: hello-kubernetes
spec:
type: LoadBalancer
ports:
- port: 80
targetPort: http
protocol: TCP
name: http
selector:
app.kubernetes.io/name: hello-kubernetes
EOF
Vamos vê-lo em ação:
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 8s
curl http://192.168.122.11
<!DOCTYPE html>
<html>
<head>
<title>Hello Kubernetes!</title>
<link rel="stylesheet" type="text/css" href="/css/main.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Ubuntu:300" >
</head>
<body>
<div class="main">
<img src="/images/kubernetes.png"/>
<div class="content">
<div id="message">
Hello world!
</div>
<div id="info">
<table>
<tr>
<th>namespace:</th>
<td>hello-kubernetes</td>
</tr>
<tr>
<th>pod:</th>
<td>hello-kubernetes-7c8575c848-2c6ps</td>
</tr>
<tr>
<th>node:</th>
<td>allinone (Linux 5.14.21-150400.24.46-default)</td>
</tr>
</table>
</div>
<div id="footer">
paulbouwer/hello-kubernetes:1.10 (linux/amd64)
</div>
</div>
</div>
</body>
</html>
25.6.1 Ingress com MetalLB #
Como o Traefik já atua como controlador de entrada, podemos expor o tráfego
HTTP/HTTPS por um objeto Ingress
, por exemplo:
IP=$(kubectl get svc -n kube-system traefik -o jsonpath="{.status.loadBalancer.ingress[0].ip}")
cat <<- EOF | kubectl apply -f -
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hello-kubernetes-ingress
namespace: hello-kubernetes
spec:
rules:
- host: hellok3s.${IP}.sslip.io
http:
paths:
- path: "/"
pathType: Prefix
backend:
service:
name: hello-kubernetes
port:
name: http
EOF
E depois:
curl http://hellok3s.${IP}.sslip.io
<!DOCTYPE html>
<html>
<head>
<title>Hello Kubernetes!</title>
<link rel="stylesheet" type="text/css" href="/css/main.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Ubuntu:300" >
</head>
<body>
<div class="main">
<img src="/images/kubernetes.png"/>
<div class="content">
<div id="message">
Hello world!
</div>
<div id="info">
<table>
<tr>
<th>namespace:</th>
<td>hello-kubernetes</td>
</tr>
<tr>
<th>pod:</th>
<td>hello-kubernetes-7c8575c848-fvqm2</td>
</tr>
<tr>
<th>node:</th>
<td>allinone (Linux 5.14.21-150400.24.46-default)</td>
</tr>
</table>
</div>
<div id="footer">
paulbouwer/hello-kubernetes:1.10 (linux/amd64)
</div>
</div>
</div>
</body>
</html>
Verifique se o MetalLB funciona corretamente:
% arping hellok3s.${IP}.sslip.io
ARPING 192.168.64.210
60 bytes from 92:12:36:00:d3:58 (192.168.64.210): index=0 time=1.169 msec
60 bytes from 92:12:36:00:d3:58 (192.168.64.210): index=1 time=2.992 msec
60 bytes from 92:12:36:00:d3:58 (192.168.64.210): index=2 time=2.884 msec
No exemplo acima, o tráfego flui da seguinte maneira:
hellok3s.${IP}.sslip.io
é resolvido para o IP atual.Em seguida, o tráfego é processado pelo pod
metallb-speaker
.metallb-speaker
redireciona o tráfego para o controladortraefik
.Por fim, o Traefik encaminha a solicitação para o serviço
hello-kubernetes
.