DevOps & CI/CD

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

11 min de leitura

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

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

<h2>Services: A Base da Comunicação em Kubernetes</h2>

<p>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.</p>

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

<h3>ClusterIP: Comunicação Interna</h3>

<p>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.</p>

<pre><code class="language-yaml">apiVersion: v1

kind: Service

metadata:

name: backend-service

namespace: default

spec:

type: ClusterIP

selector:

app: backend

ports:

  • protocol: TCP

port: 80

targetPort: 8080</code></pre>

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

<h3>NodePort: Acesso Externo Simples</h3>

<p>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.</p>

<pre><code class="language-yaml">apiVersion: v1

kind: Service

metadata:

name: frontend-service

spec:

type: NodePort

selector:

app: frontend

ports:

  • protocol: TCP

port: 80

targetPort: 3000

nodePort: 30080</code></pre>

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

<h3>LoadBalancer: Integração com Provedores Cloud</h3>

<p>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.</p>

<pre><code class="language-yaml">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</code></pre>

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

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

<p>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 <strong>Ingress Controller</strong> rodando no cluster (como NGINX, Traefik ou Istio) para que Ingress realmente funcione.</p>

<p>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.</p>

<h3>Configuração Básica de Ingress</h3>

<p>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).</p>

<pre><code class="language-yaml">apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

name: app-ingress

annotations:

cert-manager.io/cluster-issuer: &quot;letsencrypt-prod&quot;

nginx.ingress.kubernetes.io/ssl-redirect: &quot;true&quot;

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</code></pre>

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

<h3>Roteamento Avançado</h3>

<p>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.</p>

<pre><code class="language-yaml">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: &quot;100&quot;

nginx.ingress.kubernetes.io/cors-allow-origin: &quot;*&quot;

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</code></pre>

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

<h3>Instalando um Ingress Controller</h3>

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

<pre><code class="language-bash"># 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</code></pre>

<p>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.</p>

<h2>Exposição de Aplicações: Estratégias Práticas</h2>

<p>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.</p>

<h3>Estratégia de Desenvolvimento Local</h3>

<p>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.</p>

<pre><code class="language-bash"># 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</code></pre>

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

<h3>Estratégia de Produção com Ingress e TLS</h3>

<p>Em produção, combine Ingress com certificados TLS automáticos. Use cert-manager para provisionar certificados do Let&#039;s Encrypt sem intervenção manual.</p>

<pre><code class="language-yaml"># 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: &quot;letsencrypt-prod&quot;

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</code></pre>

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

<h3>Monitorar Exposição e Acesso</h3>

<p>Verifique se suas aplicações estão sendo acessadas corretamente:</p>

<pre><code class="language-bash"># 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</code></pre>

<p>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.</p>

<h2>Conclusão</h2>

<p><strong>Primeiro aprendizado:</strong> 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.</p>

<p><strong>Segundo aprendizado:</strong> 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.</p>

<p><strong>Terceiro aprendizado:</strong> 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.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://kubernetes.io/docs/concepts/services-networking/service/" target="_blank" rel="noopener noreferrer">Documentação Oficial de Services - Kubernetes</a></li>

<li><a href="https://kubernetes.io/docs/concepts/services-networking/ingress/" target="_blank" rel="noopener noreferrer">Documentação Oficial de Ingress - Kubernetes</a></li>

<li><a href="https://kubernetes.github.io/ingress-nginx/" target="_blank" rel="noopener noreferrer">NGINX Ingress Controller - Helm Chart</a></li>

<li><a href="https://cert-manager.io/docs/" target="_blank" rel="noopener noreferrer">cert-manager Documentation</a></li>

<li><a href="https://www.manning.com/books/kubernetes-in-action" target="_blank" rel="noopener noreferrer">Kubernetes in Action - Marko Lukša</a></li>

</ul>

<p>&lt;!-- FIM --&gt;</p>

Comentários

Mais em DevOps & CI/CD

O que Todo Dev Deve Saber sobre ArgoCD: GitOps Contínuo para Kubernetes na Prática
O que Todo Dev Deve Saber sobre ArgoCD: GitOps Contínuo para Kubernetes na Prática

O que é ArgoCD e Por que GitOps? ArgoCD é uma ferramenta declarativa de entre...

Guia Completo de Podman e Alternativas ao Docker: Daemonless Containers na Prática
Guia Completo de Podman e Alternativas ao Docker: Daemonless Containers na Prática

Entendendo Containers Tradicionais vs. Daemonless A história dos containers c...

Dominando Os Três Pilares da Observabilidade: Métricas, Logs e Traces em Projetos Reais
Dominando Os Três Pilares da Observabilidade: Métricas, Logs e Traces em Projetos Reais

Os Três Pilares da Observabilidade: Métricas, Logs e Traces A observabilidade...