DevOps Admin

Boas Práticas de Services, Ingress e Exposição de Aplicações em Kubernetes para Times Ágeis Já leu

Services: A Base da Comunicação em Kubernetes Um Service em Kubernetes é um recurso abstrato que define como acessar um conjunto de Pods. Diferentemente de Pods, que são efêmeros e podem ser recriados a qualquer momento, um Service fornece um ponto de acesso estável com um DNS duradouro e um IP de cluster consistente. Sem Services, seria impossível acessar suas aplicações de forma previsível, já que os Pods mudam constantemente. Existem quatro tipos principais de Services: ClusterIP (acesso interno apenas), NodePort (expõe em uma porta de cada node), LoadBalancer (provisiona um balanceador externo) e ExternalName (mapeia um nome DNS externo). A escolha do tipo depende de como você quer que a aplicação seja acessada. ClusterIP: Comunicação Interna O ClusterIP é o tipo padrão e mais comum. Ele aloca um IP virtual do cluster que é roteável apenas dentro do cluster Kubernetes. Use-o quando seus Pods precisam se comunicar entre si ou com outras aplicações no mesmo cluster. Neste exemplo, o

Services: A Base da Comunicação em Kubernetes

Um Service em Kubernetes é um recurso abstrato que define como acessar um conjunto de Pods. Diferentemente de Pods, que são efêmeros e podem ser recriados a qualquer momento, um Service fornece um ponto de acesso estável com um DNS duradouro e um IP de cluster consistente. Sem Services, seria impossível acessar suas aplicações de forma previsível, já que os Pods mudam constantemente.

Existem quatro tipos principais de Services: ClusterIP (acesso interno apenas), NodePort (expõe em uma porta de cada node), LoadBalancer (provisiona um balanceador externo) e ExternalName (mapeia um nome DNS externo). A escolha do tipo depende de como você quer que a aplicação seja acessada.

ClusterIP: Comunicação Interna

O ClusterIP é o tipo padrão e mais comum. Ele aloca um IP virtual do cluster que é roteável apenas dentro do cluster Kubernetes. Use-o quando seus Pods precisam se comunicar entre si ou com outras aplicações no mesmo cluster.

apiVersion: v1
kind: Service
metadata:
  name: backend-service
  namespace: default
spec:
  type: ClusterIP
  selector:
    app: backend
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080

Neste exemplo, o Service backend-service roteia o tráfego na porta 80 para os Pods com rótulo app: backend na porta 8080. Outros Pods podem acessar este serviço através de backend-service.default.svc.cluster.local:80.

NodePort: Acesso Externo Simples

NodePort expõe o Service em uma porta específica em cada node do cluster. É útil para ambiente de desenvolvimento ou quando você não tem um balanceador de carga disponível. O Kubernetes aloca automaticamente uma porta entre 30000 e 32767, mas você pode especificá-la.

apiVersion: v1
kind: Service
metadata:
  name: frontend-service
spec:
  type: NodePort
  selector:
    app: frontend
  ports:
    - protocol: TCP
      port: 80
      targetPort: 3000
      nodePort: 30080

Com esta configuração, sua aplicação estará acessível em http://<qualquer-ip-do-node>:30080. O tráfego entra na porta 30080 do node e é roteado para a porta 3000 do Pod.

LoadBalancer: Integração com Provedores Cloud

LoadBalancer provisiona um balanceador de carga externo (se você estiver em um cloud provider como AWS, GCP ou Azure). É a forma mais direta de expor sua aplicação para o mundo exterior, mas tem custo adicional e funciona apenas em clusters gerenciados.

apiVersion: v1
kind: Service
metadata:
  name: api-service
spec:
  type: LoadBalancer
  selector:
    app: api
  ports:
    - protocol: TCP
      port: 443
      targetPort: 8443
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800

Aqui, o Kubernetes provisiona um Load Balancer que distribui tráfego HTTPS para seus Pods. A opção sessionAffinity: ClientIP garante que requisições do mesmo cliente sempre cheguem no mesmo Pod, útil para aplicações que mantêm estado na sessão.

Ingress: Roteamento Inteligente de Requisições HTTP/HTTPS

Ingress é um recurso que gerencia acesso HTTP/HTTPS externo a serviços dentro de um cluster. Enquanto Services trabalham em camadas mais baixas, Ingress opera na camada de aplicação (Layer 7), permitindo roteamento baseado em hostname, caminho da URL e outras regras sofisticadas. Você precisa de um Ingress Controller rodando no cluster (como NGINX, Traefik ou Istio) para que Ingress realmente funcione.

A grande vantagem do Ingress é usar um único IP público com múltiplos domínios e caminhos, ao invés de um LoadBalancer por serviço. Em um ambiente de produção, é quase sempre a escolha correta.

Configuração Básica de Ingress

O recurso Ingress define as regras de roteamento. Ele não faz nada sozinho — precisa de um controller para interpretar essas regras e configurar um proxy (geralmente NGINX).

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: app-ingress
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - example.com
          - api.example.com
      secretName: example-tls-cert
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: frontend-service
                port:
                  number: 80
    - host: api.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 8080
          - path: /admin
            pathType: Prefix
            backend:
              service:
                name: admin-service
                port:
                  number: 9090

Este Ingress faz o seguinte: direciona example.com para o frontend, api.example.com para a API principal, e api.example.com/admin para o serviço de administração. As anotações indicam que um certificado TLS será provisionado automaticamente via cert-manager com Let's Encrypt.

Roteamento Avançado

O Ingress pode fazer muito mais que roteamento simples. Você pode usar expressões regulares, reescrever URLs, adicionar headers customizados e até dividir tráfego entre múltiplos serviços.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: advanced-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/rate-limit: "100"
    nginx.ingress.kubernetes.io/cors-allow-origin: "*"
spec:
  ingressClassName: nginx
  rules:
    - host: api.example.com
      http:
        paths:
          - path: /v1(/|$)(.*)
            pathType: ImplementationSpecific
            backend:
              service:
                name: api-v1-service
                port:
                  number: 8080
          - path: /v2(/|$)(.*)
            pathType: ImplementationSpecific
            backend:
              service:
                name: api-v2-service
                port:
                  number: 8080

Neste exemplo, requisições para /v1/users são reescritas para /users antes de chegar no api-v1-service, mantendo APIs versionadas separadas. A anotação rate-limit protege contra abuso com limite de 100 requisições por segundo.

Instalando um Ingress Controller

O Ingress Controller é quem realmente faz o trabalho. Aqui está como instalar o NGINX Ingress Controller usando Helm:

# Adicionar repositório Helm
helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
helm repo update

# Instalar o controller
helm install nginx-ingress ingress-nginx/ingress-nginx \
  --namespace ingress-nginx \
  --create-namespace \
  --set controller.service.type=LoadBalancer

Após a instalação, o controller monitora todos os recursos Ingress no cluster e configura um proxy NGINX automaticamente. Quando você cria ou modifica um Ingress, a configuração do NGINX é atualizada em segundos.

Exposição de Aplicações: Estratégias Práticas

Expor uma aplicação Kubernetes não é apenas criar um Service ou Ingress — é entender qual estratégia faz sentido para seu caso. Em desenvolvimento, NodePort é rápido. Em produção, Ingress com certificados TLS é o padrão. Cada escolha tem implicações em segurança, custo e performance.

Estratégia de Desenvolvimento Local

Para trabalhar rapidamente em desenvolvimento, use port-forward ou NodePort. Port-forward permite acessar um Pod ou Service diretamente do seu computador sem expor globalmente.

# Acessar um serviço localmente
kubectl port-forward svc/backend-service 8080:80 -n default

# Acessar um Pod específico
kubectl port-forward pod/nginx-abc123 3000:80 -n default

Após executar um desses comandos, acesse localhost:8080 no seu navegador. É perfeito para debug, mas não use em produção — as conexões não são balanceadas ou resilientes.

Estratégia de Produção com Ingress e TLS

Em produção, combine Ingress com certificados TLS automáticos. Use cert-manager para provisionar certificados do Let's Encrypt sem intervenção manual.

# Primeiro, instale cert-manager
# helm repo add jetstack https://charts.jetstack.io
# helm install cert-manager jetstack/cert-manager \
#   --namespace cert-manager \
#   --create-namespace \
#   --set installCRDs=true

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: admin@example.com
    privateKeySecretRef:
      name: letsencrypt-prod-key
    solvers:
      - http01:
          ingress:
            class: nginx
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: production-ingress
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  ingressClassName: nginx
  tls:
    - hosts:
        - app.example.com
      secretName: app-tls-secret
  rules:
    - host: app.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: app-service
                port:
                  number: 80

O ClusterIssuer define como obter certificados. O Ingress com a anotação cert-manager.io/cluster-issuer faz cert-manager provisionar um certificado automaticamente. O certificado é renovado automaticamente 30 dias antes do vencimento.

Monitorar Exposição e Acesso

Verifique se suas aplicações estão sendo acessadas corretamente:

# Ver todos os Services
kubectl get svc -A

# Ver detalhes de um Ingress
kubectl describe ingress app-ingress

# Ver logs do Ingress Controller
kubectl logs -n ingress-nginx -l app.kubernetes.io/name=ingress-nginx --tail=50

# Testar conectividade dentro do cluster
kubectl run -it --rm debug --image=curlimages/curl --restart=Never -- \
  curl http://backend-service.default.svc.cluster.local:80

# Ver IP externo do LoadBalancer
kubectl get svc frontend-service -o wide

Estes comandos ajudam a diagnosticar problemas de conectividade. Se um serviço não é acessível, verifique se o Ingress Controller está rodando, se o DNS está resolvendo corretamente e se o certificado TLS é válido.

Conclusão

Primeiro aprendizado: Services são a base invisível de qualquer aplicação Kubernetes — sem eles, os Pods seriam acessíveis apenas por IP efêmero. Use ClusterIP para comunicação interna, NodePort para desenvolvimento, e LoadBalancer quando integrado com cloud providers.

Segundo aprendizado: Ingress é seu caminho para exposição em produção, especialmente quando você tem múltiplos serviços acessados pelo mesmo domínio. Combinar Ingress com cert-manager oferece HTTPS automático e roteamento inteligente sem necessidade de múltiplos load balancers caros.

Terceiro aprendizado: A escolha entre Service, NodePort e Ingress não é técnica apenas — é arquitetural. Comece com o mais simples (ClusterIP), evolua conforme suas necessidades crescem, e sempre teste conectividade com logs e comandos de diagnóstico antes de levar para produção.

Referências


Artigos relacionados