Para garantir o funcionamento estável das aplicações e distribuir o tráfego de forma uniforme entre os pods no Kubernetes, usamos um load balancer. Ele ajuda a evitar sobrecarga em pods individuais, mantendo alta disponibilidade e estabilidade dos serviços.
Para criar um load balancer no Kubernetes, definimos um recurso Service do tipo LoadBalancer. Exemplo de manifesto básico:
apiVersion: v1
kind: Service
metadata:
name: example-balancer
namespace: kubernetes-dashboard
spec:
selector:
app.kubernetes.io/name: nginx
ports:
- port: 80 # External port for accessing the application
targetPort: 80 # Pod port to which traffic is redirected
type: LoadBalancer
Neste exemplo, o load balancer redireciona o tráfego da porta 80 para a porta 80 dentro dos pods que correspondem ao selector app.kubernetes.io/name: nginx.
Se precisar adicionar múltiplas regras de balanceamento, especifique o atributo name para cada porta:
apiVersion: v1
kind: Service
metadata:
name: example-balancer
namespace: kubernetes-dashboard
spec:
selector:
app.kubernetes.io/name: nginx
ports:
- port: 80
targetPort: 80
name: http
- port: 443
targetPort: 443
name: https
type: LoadBalancer
O valor do atributo name pode ser arbitrário.
Para cada porta, é possível definir o protocolo de tráfego usando o atributo appProtocol. Isso define explicitamente como o load balancer irá tratar o tráfego. Por padrão, o valor é proto-tcp.
Valores suportados:
k8s.hostman.com/proto-http: tráfego HTTP padrãok8s.hostman.com/proto-https: tráfego HTTPSk8s.hostman.com/proto-tcp: tráfego TCPk8s.hostman.com/proto-tcp-ssl: tráfego TCP com suporte TLSk8s.hostman.com/proto-http2: tráfego HTTP/2Após a criação, o load balancer ficará visível no painel de controle na seção Balanceadores de carga, com o label k8s.
Um load balancer criado via Kubernetes só pode ser modificado pelo
kubectl, não pelo painel de controle ou API.
Para maior flexibilidade, é possível usar parâmetros adicionais, definidos como labels ou annotations no manifesto do Service.
Exemplo com labels:
apiVersion: v1
kind: Service
metadata:
name: example-balancer
namespace: kubernetes-dashboard
labels:
k8s.hostman.com/attached-loadbalancer-algo: "leastconn"
k8s.hostman.com/attached-loadbalancer-ddos-guard-external-ip: "true"
spec:
selector:
app.kubernetes.io/name: nginx
ports:
- port: 80
appProtocol: k8s.hostman.com/proto-http
targetPort: 80
type: LoadBalancer
Exemplo com annotations:
apiVersion: v1
kind: Service
metadata:
name: example-balancer
namespace: kubernetes-dashboard
labels:
app: nginx
annotations:
k8s.hostman.com/attached-loadbalancer-algo: "leastconn"
k8s.hostman.com/attached-loadbalancer-ddos-guard-external-ip: "true"
spec:
selector:
app.kubernetes.io/name: nginx
ports:
- port: 80
appProtocol: k8s.hostman.com/proto-http
targetPort: 80
type: LoadBalancer
Nestes exemplos, dois parâmetros adicionais são definidos:
k8s.hostman.com/attached-loadbalancer-algo: algoritmo de balanceamento (ex.: leastconn, seleciona o servidor com menos conexões ativas).k8s.hostman.com/attached-loadbalancer-ddos-guard-external-ip: atribui IP externo ao load balancer com proteção DDoS.|
Parâmetro |
Finalidade |
|
|
Define a configuração do load balancer. O padrão é a configuração mínima da zona. IDs de presets via API. |
|
|
Algoritmo de balanceamento: |
|
|
Intervalo entre health checks (segundos). |
|
|
Timeout de health check (segundos). |
|
|
Número de falhas antes de marcar upstream como indisponível. |
|
|
Número de checks bem-sucedidos necessários para recuperar upstream. |
|
|
Desativa IP externo público do load balancer. |
|
|
Exclui serviço do balanceamento Hostman, útil ao usar outro LoadBalancer (ex.: |
|
|
Atribui IP externo com proteção DDoS. |
|
|
Habilita modo proxy no load balancer. |
|
|
Timeout de conexão TCP com upstream (ms). |
|
|
Timeout para receber novos segmentos TCP do cliente (ms). |
|
|
Timeout aguardando resposta do backend (ms). |
|
|
Timeout de execução de requisição HTTP (ms). |
|
|
Máximo de conexões simultâneas no frontend. |
|
|
Habilita emissão automática de certificado SSL. Se false, certificado é deletado. |
|
|
Domínio para emissão do certificado SSL. |
Vamos criar dois deployments Nginx, cada um mostrando sua própria página HTML. O load balancer distribuirá as requisições aleatoriamente entre os pods.
Para facilitar gerenciamento e remoção rápida de recursos:
kubectl create namespace test-namespace
Use este namespace em todos os recursos, incluindo load balancer, deployments e ConfigMap, adicionando namespace: test-namespace em cada manifesto.
Começaremos criando um ConfigMap para armazenar duas páginas HTML. O Pod 1 exibirá uma página com o título "Pod 1" e o Pod 2 exibirá uma página com o título "Pod 2". Essas páginas estarão conectadas ao Nginx dentro dos pods.
Arquivo nginx-pages-configmap.yaml:
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-pages
namespace: test-namespace
data:
index-page1.html: |
<html>
<body>
<h1>Pod 1</h1>
<p>This is page served by Pod 1.</p>
</body>
</html>
index-page2.html: |
<html>
<body>
<h1>Pod 2</h1>
<p>This is page served by Pod 2.</p>
</body>
</html>
Aqui criamos um ConfigMap com dois arquivos HTML: index-page1.html e index-page2.html. Esses arquivos serão montados nos pods do Nginx, permitindo que cada pod exiba sua página específica.
Aplicar ConfigMap:
kubectl apply -f nginx-pages-configmap.yaml
Em seguida, criamos dois deployments, cada um usando páginas HTML diferentes do ConfigMap. Os deployments usam o selector app: nginx, que o load balancer utilizará para identificar os pods que participam da distribuição de tráfego.
nginx-deployment-pod1.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-pod1
namespace: test-namespace
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
volumeMounts:
- name: nginx-pages
mountPath: /usr/share/nginx/html/index.html
subPath: index-page1.html
ports:
- containerPort: 80
volumes:
- name: nginx-pages
configMap:
name: nginx-pages
Este deployment cria um único pod (replica 1) com a imagem Nginx, que monta o arquivo index-page1.html do ConfigMap no diretório /usr/share/nginx/html/index.html. A porta 80 está aberta para acessar a página.
Aplica deployment:
kubectl apply -f nginx-deployment-pod1.yaml
nginx-deployment-pod2.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-pod2
namespace: test-namespace
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:latest
volumeMounts:
- name: nginx-pages
mountPath: /usr/share/nginx/html/index.html
subPath: index-page2.html
ports:
- containerPort: 80
volumes:
- name: nginx-pages
configMap:
name: nginx-pages
Este deployment também cria um pod Nginx, mas monta o arquivo index-page2.html, que contém conteúdo diferente.
Aplicar o segundo deployment:
kubectl apply -f nginx-deployment-pod2.yaml
Agora, crie um load balancer que direcionará as requisições para os pods com o label app: nginx.
Arquivo nginx-loadbalancer.yaml:
apiVersion: v1
kind: Service
metadata:
name: nginx-loadbalancer
namespace: test-namespace
spec:
selector:
app: nginx
ports:
- port: 80
targetPort: 80
appProtocol: k8s.hostman.com/proto-http
type: LoadBalancer
Neste Service, definimos type: LoadBalancer e selector: app: nginx. O tráfego será distribuído usando o algoritmo roundrobin.
Aplicar load balancer:
kubectl apply -f nginx-loadbalancer.yaml
Após criar, verifique o IP público no painel ou via:
kubectl get services -n test-namespace
Acessando o IP, você verá uma das páginas. Cada refresh pode redirecionar para pods diferentes.
Depois de verificar o funcionamento do load balancer, você pode deletar todos os pods e recursos criados. Use os seguintes comandos:
kubectl delete service nginx-loadbalancer -n test-namespace
kubectl delete deployment nginx-pod1 -n test-namespace
kubectl delete deployment nginx-pod2 -n test-namespace
kubectl delete configmap nginx-pages -n test-namespace
Ou deletar o namespace inteiro:
kubectl delete namespace test-namespace
Se o load balancer não conseguir IP externo, aparecerá a annotation:
k8s.hostman.com/attached-loadbalancer-ensuring-error: true
Isso indica erro ao vincular IP externo. Neste caso, recrie o load balancer ou contate suporte.
kubectl get svc --all-namespaces --field-selector spec.type=LoadBalancer
kubectl describe svc <service-name> -n <namespace>
kubectl describe svc <service-name> -n <namespace>