Services: expondo aplicações no cluster
1. Por que Precisamos de Services?
1.1. A natureza efêmera dos Pods: IPs voláteis e a necessidade de descoberta
No Kubernetes, Pods são criados e destruídos constantemente — seja por escalonamento automático, atualizações rolling update ou falhas. Cada Pod recebe um endereço IP interno único, mas esse IP desaparece quando o Pod é recriado. Se um componente A precisa se comunicar com um componente B, não podemos depender de IPs fixos. Services resolvem esse problema fornecendo um ponto de acesso estável.
1.2. Balanceamento de carga interno: distribuindo tráfego entre réplicas
Quando executamos múltiplas réplicas de um Deployment, precisamos distribuir as requisições uniformemente entre elas. Um Service atua como um balanceador de carga interno, roteando tráfego automaticamente para todos os Pods saudáveis que correspondem ao seletor definido.
1.3. Abstração de acesso: separando consumidores da implementação dos Pods
Services criam uma camada de abstração entre consumidores (outros Pods, serviços externos) e a implementação real dos Pods. Podemos alterar versões, escalar ou substituir Pods sem que os consumidores precisem ser atualizados — eles continuam apontando para o mesmo Service.
2. Tipos de Service no Kubernetes
2.1. ClusterIP: comunicação interna entre componentes do cluster
ClusterIP é o tipo padrão. O Service recebe um IP virtual acessível apenas dentro do cluster. Ideal para comunicação entre microsserviços internos.
apiVersion: v1
kind: Service
metadata:
name: api-backend
spec:
selector:
app: backend
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: ClusterIP
2.2. NodePort: expondo aplicações para fora via porta do nó
NodePort expõe o Service em uma porta estática (30000-32767) em todos os nós do cluster. Útil para testes locais ou ambientes on-premise.
apiVersion: v1
kind: Service
metadata:
name: web-frontend
spec:
selector:
app: frontend
ports:
- port: 80
targetPort: 3000
nodePort: 30080
type: NodePort
2.3. LoadBalancer: integração com balanceadores de carga cloud-native
Em clusters cloud (EKS, AKS, GKE), o tipo LoadBalancer provisiona automaticamente um balanceador de carga externo. Ideal para produção.
apiVersion: v1
kind: Service
metadata:
name: app-external
spec:
selector:
app: minha-app
ports:
- port: 443
targetPort: 8443
type: LoadBalancer
3. Criando e Configurando um Service
3.1. Estrutura do manifesto YAML: selector, ports e type
O manifesto de um Service possui três elementos críticos:
- selector: define quais Pods serão alvo (baseado em labels)
- ports: mapeia portas entre Service e Pod
- type: define o tipo de exposição
3.2. Mapeamento de portas: targetPort, port e nodePort
spec:
ports:
- name: http
protocol: TCP
port: 80 # Porta do Service
targetPort: 8080 # Porta do container
nodePort: 30080 # Porta do nó (apenas NodePort)
- port: porta que o Service escuta
- targetPort: porta do container que recebe o tráfego
- nodePort: porta no nó (opcional, apenas para NodePort)
3.3. Aplicando e verificando: kubectl apply, kubectl get svc e kubectl describe svc
# Aplicar o manifesto
kubectl apply -f service.yaml
# Listar Services
kubectl get svc
# Obter detalhes completos
kubectl describe svc api-backend
# Verificar endpoints (Pods associados)
kubectl get endpoints api-backend
4. Descoberta de Serviços e DNS Interno
4.1. Como o CoreDNS resolve nomes de Service dentro do cluster
O Kubernetes possui o CoreDNS como DNS interno padrão. Quando um Service é criado, o CoreDNS registra automaticamente um registro DNS para ele. Qualquer Pod pode resolver o nome do Service e obter seu IP ClusterIP.
4.2. Padrão de nomenclatura: ..svc.cluster.local
# Formato completo
<service-name>.<namespace>.svc.cluster.local
# Exemplo prático
api-backend.default.svc.cluster.local
# Formato abreviado (dentro do mesmo namespace)
api-backend
4.3. Variáveis de ambiente vs DNS: diferenças e boas práticas
O Kubernetes também injeta variáveis de ambiente (como API_BACKEND_SERVICE_HOST), mas o DNS é mais flexível e recomendado:
- DNS: funciona mesmo se o Service for recriado com IP diferente
- Variáveis de ambiente: podem conter IPs obsoletos se o Service for recriado após o Pod iniciar
Boas práticas: prefira DNS para descoberta de serviços entre namespaces diferentes e variáveis de ambiente apenas para configurações estáticas.
5. Services Headless e Casos Especiais
5.1. Quando usar ClusterIP: None para descoberta direta de Pods
Um Service headless (ClusterIP: None) não cria um IP virtual nem faz balanceamento. Em vez disso, o DNS retorna os IPs individuais de todos os Pods selecionados. Útil quando o cliente precisa se conectar diretamente a cada Pod específico.
apiVersion: v1
kind: Service
metadata:
name: db-headless
spec:
clusterIP: None
selector:
app: database
ports:
- port: 5432
targetPort: 5432
5.2. Integração com StatefulSets e bancos de dados distribuídos
Services headless são essenciais para StatefulSets, onde cada Pod precisa de uma identidade estável (nome de host único). Bancos de dados como Cassandra, Elasticsearch e MongoDB usam esse padrão para descoberta de nós.
5.3. ExternalName: apontando Services para recursos fora do cluster
apiVersion: v1
kind: Service
metadata:
name: db-externo
spec:
type: ExternalName
externalName: meu-banco.exemplo.com
Esse tipo cria um alias DNS dentro do cluster para um serviço externo, sem proxy ou balanceamento.
6. Roteamento Avançado e Ingress
6.1. Limitações do Service Layer 4 e a necessidade de Layer 7
Services operam na camada de transporte (TCP/UDP). Eles não entendem HTTP, não podem rotear baseado em hostname ou path, nem realizar terminação SSL. Para isso, precisamos de um Ingress Controller.
6.2. Ingress Controller: como expor múltiplos serviços com um único IP
O Ingress é um recurso que define regras de roteamento HTTP/HTTPS. O Ingress Controller (como NGINX Ingress, Traefik, AWS ALB Ingress) implementa essas regras.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: meu-ingress
spec:
rules:
- host: app1.exemplo.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: api-backend
port:
number: 80
6.3. Regras de roteamento baseadas em hostname e path
spec:
rules:
- host: loja.exemplo.com
http:
paths:
- path: /api
backend:
service:
name: api-loja
port: 8080
- path: /web
backend:
service:
name: web-loja
port: 80
7. Monitoramento e Troubleshooting de Services
7.1. Verificando conectividade com kubectl port-forward e curl
# Encaminhar porta local para o Service
kubectl port-forward svc/api-backend 8080:80
# Testar conectividade
curl http://localhost:8080/health
# Verificar resolução DNS dentro de um Pod
kubectl exec -it pod-teste -- nslookup api-backend
7.2. Logs e eventos: identificando falhas de selector ou porta
# Verificar eventos recentes do Service
kubectl describe svc api-backend
# Verificar logs do CoreDNS
kubectl logs -n kube-system -l k8s-app=kube-dns
# Verificar endpoints ativos
kubectl get endpoints api-backend
Se kubectl get endpoints mostrar vazio, o selector não está encontrando Pods — verifique as labels.
7.3. Ferramentas de diagnóstico: kubectl exec, nslookup e tcpdump
# Testar conectividade TCP de dentro de um Pod
kubectl exec -it pod-teste -- curl -v http://api-backend:80
# Verificar resolução DNS
kubectl exec -it pod-teste -- nslookup api-backend.default.svc.cluster.local
# Instalar tcpdump em um Pod para debug avançado
kubectl exec -it pod-teste -- tcpdump -i any port 80
Referências
- Kubernetes Documentation: Services — Documentação oficial completa sobre Services, tipos, portas e exemplos de manifesto.
- Kubernetes: DNS for Services and Pods — Guia oficial sobre resolução DNS interna, CoreDNS e padrões de nomenclatura.
- Kubernetes: Ingress Controllers — Documentação sobre Ingress, roteamento Layer 7 e controllers disponíveis.
- Kubernetes: Headless Services — Especificação detalhada de Services headless e casos de uso com StatefulSets.
- Kubernetes: Debugging Services — Tutorial oficial de troubleshooting para Services, incluindo comandos kubectl e técnicas de diagnóstico.