Ir para o conteúdo principal

service.yml

Descrição: este arquivo cria um Service no Kubernetes.

Um Service é usado para expor uma aplicação que está rodando em Pods, criando um ponto de acesso estável para esses Pods.

Pods podem ser recriados, trocar de IP e mudar de nó. O Service resolve isso criando uma abstração fixa, com nome e porta, e encaminhando as requisições para os Pods selecionados por labels.

No arquivo de referência do cluster, o recurso aparece como:

Recurso: services
Tipo: Service
Versão: v1

TIPO:       Service
VERSÃO:    v1

DESCRIÇÃO:
    Service é uma abstração nomeada de um serviço de software, por exemplo mysql, composta
    por uma porta local, por exemplo 3306, na qual o proxy escuta, e pelo selector que
    determina quais pods responderão às requisições enviadas pelo proxy.

Quando usar Service

Use Service quando a aplicação:

  • precisa ser acessada por outros Pods dentro do cluster;
  • precisa de um nome DNS estável;
  • precisa de uma porta estável;
  • é criada por um Deployment, StatefulSet ou outro controlador;
  • tem Pods que podem ser recriados e mudar de IP;
  • precisa ser publicada por um Ingress;
  • precisa balancear tráfego entre múltiplas réplicas;
  • precisa expor uma aplicação por ClusterIP, NodePort, LoadBalancer ou ExternalName;
  • precisa apontar para Pods usando labels;
  • precisa expor uma ou mais portas TCP, UDP ou SCTP.

Exemplos comuns:

  • backend acessado por um frontend;
  • API acessada por um Ingress;
  • banco interno acessado por uma aplicação;
  • Redis interno;
  • serviço de autenticação interno;
  • aplicação de laboratório;
  • sistema administrativo;
  • painel web;
  • frontend publicado por domínio;
  • serviço de métricas;
  • aplicação de disciplina ou projeto.

Quando Service não é o recurso indicado

Service não é o melhor recurso quando o problema exige outro tipo de controle.

Necessidade Recurso mais indicado Motivo
Executar aplicação e controlar réplicas Deployment Service não cria Pods; ele apenas expõe Pods existentes.
Publicar aplicação por domínio HTTP/HTTPS Ingress Ingress define hostname, path e roteamento HTTP/HTTPS.
Isolar tráfego entre aplicações NetworkPolicy Service não bloqueia tráfego; ele cria acesso estável.
Guardar senha/token Secret Service não armazena credenciais.
Guardar configuração ConfigMap Service não armazena configuração de aplicação.
Persistir dados PersistentVolumeClaim Service não fornece armazenamento.
Controlar CPU/memória ResourceQuota, LimitRange ou resources Service não controla consumo de recursos.
Rodar tarefa pontual Job Service é para rede, não execução de tarefa.
Rodar tarefa agendada CronJob Service não agenda execução.
Ter identidade fixa por réplica StatefulSet + Service adequado StatefulSet controla identidade dos Pods.
Criar permissão de acesso à API Kubernetes ServiceAccount, Role, RoleBinding Service não é recurso de RBAC.

Uso em cenário de universidade

Em uma universidade, um Service pode ser usado para organizar o acesso interno a aplicações institucionais, acadêmicas, administrativas, laboratoriais e de pesquisa.

Exemplos:

  • expor internamente um backend de sistema acadêmico;
  • conectar um frontend a uma API;
  • permitir que um Ingress publique uma aplicação por domínio;
  • criar endereço estável para aplicação de disciplina;
  • criar endereço interno para serviço de laboratório;
  • expor uma API de projeto de pesquisa para outras aplicações do mesmo namespace;
  • padronizar acesso a sistemas dentro de namespaces separados;
  • manter o acesso estável mesmo quando os Pods são recriados.

Uso recomendado em ambiente universitário:

  • um Namespace por projeto, sistema, disciplina, laboratório ou ambiente;
  • um Deployment para executar a aplicação;
  • um Service para expor os Pods internamente;
  • um Ingress para publicar por domínio quando for HTTP/HTTPS;
  • ResourceQuota e LimitRange para controlar uso de CPU/memória;
  • NetworkPolicy para isolar projetos diferentes;
  • ServiceAccount, Role e RoleBinding para permissões mínimas;
  • preferir ClusterIP para aplicações internas ou publicadas por Ingress;
  • evitar NodePort indiscriminado em ambiente compartilhado;
  • usar LoadBalancer somente quando o cluster tiver suporte a balanceador externo;
  • usar ExternalName somente quando a intenção for criar alias DNS para serviço externo.

Exemplo completo: service.yml

apiVersion: v1
kind: Service

metadata:
  name: minha-aplicacao
  namespace: meu-projeto
  labels:
    app: minha-aplicacao
    ambiente: homologacao
    componente: backend
  annotations:
    descricao: "Service exemplo para expor a aplicação internamente"

spec:
  type: ClusterIP

  selector:
    app: minha-aplicacao

  ports:
    - name: http
      appProtocol: http
      protocol: TCP
      port: 80
      targetPort: 8080

  sessionAffinity: None
  internalTrafficPolicy: Cluster
  ipFamilyPolicy: SingleStack
  ipFamilies:
    - IPv4
  publishNotReadyAddresses: false

Explicação linha por linha

apiVersion: v1

Define a versão da API usada pelo manifesto.

Para Service, normalmente é:

apiVersion: v1

Significado:

  • v1: versão estável da API core do Kubernetes.

Use exatamente v1 para Service.


kind: Service

Define o tipo de recurso que será criado.

kind: Service

Significado:

  • Service: recurso que expõe Pods por meio de uma abstração de rede estável.

Não confundir com:

  • Deployment: cria e atualiza Pods;
  • Ingress: publica HTTP/HTTPS por domínio;
  • NetworkPolicy: controla isolamento de tráfego;
  • EndpointSlice: representa endpoints usados pelo Service;
  • ServiceAccount: identidade para Pods acessarem a API Kubernetes.

metadata

metadata identifica e organiza o Service.

metadata:
  name: minha-aplicacao
  namespace: meu-projeto
  labels:
    app: minha-aplicacao
  annotations:
    descricao: "Service exemplo"

metadata.name

Nome do Service.

name: minha-aplicacao

Uso:

  • identifica o recurso dentro do namespace;
  • aparece em kubectl get services;
  • deve ser único dentro do namespace;
  • é usado como nome DNS interno do Service.

Exemplos bons:

name: portal-academico
name: api-pesquisa
name: backend-laboratorio

Regras práticas:

  • use letras minúsculas;
  • use hífen;
  • evite acentos;
  • evite espaços;
  • escolha nome curto e claro.

metadata.namespace

Namespace onde o Service será criado.

namespace: meu-projeto

Uso:

  • separa aplicações;
  • evita mistura entre projetos;
  • permite ter Services com o mesmo nome em namespaces diferentes;
  • ajuda em RBAC, quotas, isolamento e organização.

Se omitir:

  • Kubernetes usa o namespace atual do contexto;
  • em produção isso pode causar Service no namespace errado.

Recomendação:

  • sempre declarar namespace.

metadata.labels

Labels são pares chave/valor usados para organização e filtros.

labels:
  app: minha-aplicacao
  ambiente: homologacao
  componente: backend

Uso:

  • filtrar Services com kubectl;
  • organizar recursos;
  • permitir automações;
  • associar recursos ao mesmo sistema;
  • ajudar ferramentas de observabilidade e GitOps.

Exemplo:

kubectl get services -l app=minha-aplicacao

Boas labels:

app: minha-aplicacao
ambiente: producao
componente: backend

Evite usar label com dado sensível.


metadata.annotations

Annotations são metadados livres.

annotations:
  descricao: "Service da aplicação"

Uso:

  • documentação;
  • configuração de ferramentas;
  • configuração de controladores;
  • integração com balanceadores, Ingress Controllers ou automações.

Diferença entre labels e annotations:

Campo Uso
labels seleção, filtro e organização
annotations informação extra e configuração de ferramentas

Campos de metadata normalmente gerenciados pelo Kubernetes

O kubectl explain mostra vários campos de metadata, mas muitos são preenchidos pelo próprio cluster.

Normalmente você não escreve manualmente:

creationTimestamp:
deletionTimestamp:
resourceVersion:
uid:
generation:
managedFields:
selfLink:

Eles servem para controle interno do Kubernetes.


spec

spec descreve o estado desejado do Service.

spec:
  type: ClusterIP
  selector:
    app: minha-aplicacao
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 8080

Campos principais:

spec:
  allocateLoadBalancerNodePorts
  clusterIP
  clusterIPs
  externalIPs
  externalName
  externalTrafficPolicy
  healthCheckNodePort
  internalTrafficPolicy
  ipFamilies
  ipFamilyPolicy
  loadBalancerClass
  loadBalancerIP
  loadBalancerSourceRanges
  ports
  publishNotReadyAddresses
  selector
  sessionAffinity
  sessionAffinityConfig
  trafficDistribution
  type

spec.type

Define como o Service será exposto.

type: ClusterIP

Valores aceitos:

type: ClusterIP
type: NodePort
type: LoadBalancer
type: ExternalName

ClusterIP

Expõe o Service em um IP interno do cluster.

type: ClusterIP

Uso:

  • comunicação interna entre aplicações;
  • backend para Ingress;
  • APIs internas;
  • banco/cache interno;
  • padrão para a maioria dos Services.

Comportamento:

  • acessível apenas dentro do cluster;
  • Kubernetes atribui um IP virtual interno;
  • outros Pods podem acessar pelo nome do Service.

Exemplo de acesso interno:

http://minha-aplicacao.meu-projeto.svc.cluster.local

NodePort

Expõe o Service em uma porta de cada nó do cluster.

type: NodePort

Uso:

  • testes;
  • diagnóstico;
  • ambientes simples;
  • exposição direta por IP_DO_NO:nodePort.

Comportamento:

  • cria também um ClusterIP;
  • abre uma porta em cada nó;
  • permite acesso externo usando IP do nó e porta alocada.

Cuidado:

  • pode expor serviços de forma ampla;
  • não é a melhor opção para muitos serviços em ambiente compartilhado;
  • normalmente é melhor usar Ingress para HTTP/HTTPS.

LoadBalancer

Expõe o Service por um balanceador externo, quando a infraestrutura oferece suporte.

type: LoadBalancer

Uso:

  • clusters integrados a cloud provider;
  • clusters com controlador de LoadBalancer;
  • serviços que precisam de IP externo próprio;
  • alguns serviços TCP/UDP que não passam por Ingress HTTP.

Comportamento:

  • cria também comportamento de NodePort, salvo configuração específica;
  • depende de integração externa;
  • o IP ou hostname aparece em status.loadBalancer.

Cuidado:

  • se não houver suporte a LoadBalancer, o campo EXTERNAL-IP pode ficar pendente;
  • nem todo cluster próprio possui esse recurso configurado.

ExternalName

Mapeia o Service para um nome DNS externo.

type: ExternalName
externalName: api.exemplo.edu.br

Uso:

  • criar alias DNS interno para serviço externo;
  • padronizar nomes usados pelas aplicações;
  • evitar hardcode de domínio externo dentro da aplicação.

Comportamento:

  • retorna um CNAME para o nome definido em externalName;
  • não cria proxy;
  • não seleciona Pods;
  • não usa selector.

Cuidado:

  • não faz balanceamento interno;
  • não cria endpoints para Pods;
  • não substitui um Service normal para aplicação interna.

spec.selector

Define quais Pods receberão tráfego do Service.

selector:
  app: minha-aplicacao

O Service seleciona Pods que tenham labels compatíveis.

Exemplo de Pod selecionado:

metadata:
  labels:
    app: minha-aplicacao

Regra importante:

  • spec.selector do Service precisa combinar com metadata.labels dos Pods.

Exemplo correto:

# Service
selector:
  app: minha-aplicacao

# Pod criado pelo Deployment
metadata:
  labels:
    app: minha-aplicacao

Se não bater:

  • o Service será criado;
  • mas não terá endpoints úteis;
  • o tráfego não chegará aos Pods esperados.

Verificar endpoints:

kubectl get endpoints minha-aplicacao -n meu-projeto
kubectl get endpointslice -n meu-projeto -l kubernetes.io/service-name=minha-aplicacao

spec.ports

Lista as portas expostas pelo Service.

ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 8080

Um Service pode ter uma ou mais portas.

Quando houver mais de uma porta, o nome da porta deve ser usado para diferenciar.


spec.ports[].name

Nome da porta.

name: http

Uso:

  • identificar a porta;
  • facilitar integração com Ingress;
  • facilitar leitura do manifesto;
  • diferenciar múltiplas portas.

Exemplos:

name: http
name: https
name: metrics
name: postgres
name: redis

spec.ports[].appProtocol

Indica o protocolo de aplicação.

appProtocol: http

Uso:

  • informar protocolo de camada de aplicação;
  • permitir que ferramentas e controladores entendam melhor o tráfego.

Exemplos comuns:

appProtocol: http
appProtocol: https

Este campo é opcional.


spec.ports[].protocol

Define o protocolo de transporte.

protocol: TCP

Valores aceitos:

protocol: TCP
protocol: UDP
protocol: SCTP

Uso comum:

Protocolo Uso comum
TCP HTTP, HTTPS, PostgreSQL, MySQL, Redis, SSH
UDP DNS, syslog, alguns serviços de mídia ou descoberta
SCTP cenários específicos de rede/telecomunicações

Se omitido, o uso comum é TCP.


spec.ports[].port

Porta exposta pelo Service.

port: 80

Este campo é obrigatório.

Significado:

  • é a porta usada por clientes para acessar o Service;
  • não precisa ser igual à porta do container.

Exemplo:

Cliente acessa: Service porta 80
Pod recebe em: container porta 8080

spec.ports[].targetPort

Porta de destino no Pod.

targetPort: 8080

Pode ser:

número
nome

Exemplo com número:

targetPort: 8080

Exemplo com nome:

targetPort: http

Quando usar nome, o container deve declarar a porta com esse nome:

ports:
  - name: http
    containerPort: 8080

Se omitido, o Kubernetes usa o mesmo valor de port.


spec.ports[].nodePort

Porta aberta nos nós.

nodePort: 30080

Uso:

  • Services do tipo NodePort;
  • Services do tipo LoadBalancer quando há alocação de NodePort.

Se omitido:

  • Kubernetes escolhe uma porta disponível dentro da faixa configurada.

Cuidado:

  • use apenas quando necessário;
  • escolha porta dentro da faixa permitida do cluster;
  • evite expor muitos NodePorts em ambiente compartilhado.

spec.clusterIP

IP interno virtual do Service.

clusterIP: 10.43.10.20

Normalmente você não define manualmente.

O Kubernetes aloca automaticamente.

Uso manual só faz sentido em casos específicos, como compatibilidade com sistemas que exigem IP fixo dentro da faixa de Services.


clusterIP: None

Cria um Service sem IP virtual, conhecido como Headless Service.

clusterIP: None

Uso:

  • aplicações com descoberta direta de Pods;
  • StatefulSet;
  • casos em que cada Pod precisa ser resolvido individualmente.

Exemplo:

apiVersion: v1
kind: Service
metadata:
  name: banco
  namespace: meu-projeto
spec:
  clusterIP: None
  selector:
    app: banco
  ports:
    - name: postgres
      port: 5432
      targetPort: 5432

Cuidado:

  • não é o padrão para aplicação web comum;
  • para APIs simples, normalmente use ClusterIP.

spec.clusterIPs

Lista de IPs internos do Service.

clusterIPs:
  - 10.43.10.20

Uso:

  • cenários com mais de uma família IP;
  • ambientes dual-stack IPv4/IPv6.

Normalmente é preenchido pelo Kubernetes.


spec.ipFamilies

Define as famílias de IP usadas pelo Service.

ipFamilies:
  - IPv4

Valores comuns:

ipFamilies:
  - IPv4
ipFamilies:
  - IPv4
  - IPv6

Uso:

  • clusters IPv4;
  • clusters IPv6;
  • clusters dual-stack.

Normalmente pode ser omitido em ambientes simples.


spec.ipFamilyPolicy

Define a política de família IP.

ipFamilyPolicy: SingleStack

Valores aceitos:

ipFamilyPolicy: SingleStack
ipFamilyPolicy: PreferDualStack
ipFamilyPolicy: RequireDualStack

Significado:

Valor Uso
SingleStack usa uma família de IP
PreferDualStack prefere dual-stack quando disponível
RequireDualStack exige dual-stack

spec.externalIPs

Lista IPs externos pelos quais o Service também pode ser acessado.

externalIPs:
  - 192.0.2.10

Uso:

  • cenários avançados de rede;
  • IP externo já roteado para nós do cluster;
  • integração manual com rede institucional.

Cuidado:

  • requer roteamento externo adequado;
  • pode expor serviço indevidamente se usado sem controle;
  • normalmente não é necessário para aplicação comum com Ingress.

spec.externalName

Nome DNS externo usado por Service do tipo ExternalName.

externalName: api.exemplo.edu.br

Uso obrigatório quando:

type: ExternalName

Exemplo completo:

apiVersion: v1
kind: Service
metadata:
  name: api-externa
  namespace: meu-projeto
spec:
  type: ExternalName
  externalName: api.exemplo.edu.br

spec.externalTrafficPolicy

Controla como tráfego externo é roteado.

externalTrafficPolicy: Cluster

Valores aceitos:

externalTrafficPolicy: Cluster
externalTrafficPolicy: Local

Cluster

Permite encaminhar tráfego para endpoints em qualquer nó.

Uso:

  • distribuição normal;
  • maior chance de encontrar Pod disponível;
  • comportamento padrão na maioria dos cenários.

Local

Encaminha apenas para endpoints locais do nó que recebeu tráfego.

Uso:

  • preservar IP de origem em alguns cenários;
  • integração com balanceadores externos;
  • cenários em que tráfego precisa ficar local ao nó.

Cuidado:

  • se o nó não tiver endpoint local, pode não encaminhar tráfego;
  • exige planejamento de réplicas e distribuição dos Pods.

spec.healthCheckNodePort

Porta usada para health check em alguns Services do tipo LoadBalancer.

healthCheckNodePort: 32080

Uso:

  • associado a LoadBalancer;
  • especialmente relevante com externalTrafficPolicy: Local.

Normalmente é alocado automaticamente.


spec.internalTrafficPolicy

Controla como tráfego interno do cluster é roteado.

internalTrafficPolicy: Cluster

Valores aceitos:

internalTrafficPolicy: Cluster
internalTrafficPolicy: Local

Cluster

Permite encaminhar tráfego interno para endpoints em qualquer nó.

Local

Encaminha tráfego interno apenas para endpoints no mesmo nó.

Uso de Local:

  • reduzir tráfego entre nós;
  • otimizar latência em casos específicos;
  • manter tráfego local quando possível.

Cuidado:

  • se não houver endpoint local, o Service se comporta como se não houvesse endpoint para aquele nó.

spec.loadBalancerClass

Define qual implementação de LoadBalancer deve atender o Service.

loadBalancerClass: exemplo.io/loadbalancer

Uso:

  • clusters com mais de uma implementação de LoadBalancer;
  • escolha explícita de controlador;
  • ambientes com controladores específicos.

Cuidado:

  • só faz sentido para type: LoadBalancer;
  • depende de controlador compatível no cluster.

spec.loadBalancerIP

Solicita um IP específico para Service do tipo LoadBalancer.

loadBalancerIP: 192.0.2.50

Uso:

  • quando o provedor ou controlador suporta escolher IP;
  • integração específica com infraestrutura.

Cuidado:

  • depende da implementação;
  • pode ser ignorado se o provedor não suportar;
  • a documentação oficial informa que esse campo está depreciado desde Kubernetes v1.24.

spec.loadBalancerSourceRanges

Define faixas de origem permitidas para acessar o LoadBalancer.

loadBalancerSourceRanges:
  - 10.0.0.0/8
  - 192.168.0.0/16

Uso:

  • restringir acesso a redes específicas;
  • permitir acesso apenas por rede institucional;
  • permitir acesso apenas por VPN ou redes internas.

Cuidado:

  • depende de suporte do controlador de LoadBalancer;
  • não substitui políticas de segurança em outros níveis.

spec.allocateLoadBalancerNodePorts

Controla se um Service LoadBalancer deve alocar NodePorts.

allocateLoadBalancerNodePorts: true

Valores:

allocateLoadBalancerNodePorts: true
allocateLoadBalancerNodePorts: false

Uso:

  • true: comportamento tradicional;
  • false: para implementações de LoadBalancer que encaminham tráfego diretamente para Pods e não precisam de NodePort.

Cuidado:

  • só faz sentido para type: LoadBalancer;
  • se alterar para false em Service já existente, NodePorts antigos podem precisar ser removidos explicitamente.

spec.publishNotReadyAddresses

Controla se Pods ainda não prontos devem ser publicados como endpoints.

publishNotReadyAddresses: false

Valores:

publishNotReadyAddresses: true
publishNotReadyAddresses: false

Uso comum:

publishNotReadyAddresses: false

Use true quando:

  • a aplicação precisa descobrir peers antes de estarem prontos;
  • alguns cenários de StatefulSet;
  • sistemas distribuídos que precisam formar cluster.

Evite true quando:

  • aplicação web comum;
  • API comum;
  • Pod não pronto não deve receber tráfego.

spec.sessionAffinity

Controla afinidade de sessão.

sessionAffinity: None

Valores aceitos:

sessionAffinity: None
sessionAffinity: ClientIP

None

Sem afinidade.

O tráfego pode ser distribuído entre diferentes Pods.

ClientIP

Tenta manter requisições do mesmo IP cliente no mesmo backend.

Uso:

  • aplicações legadas;
  • aplicações que mantêm sessão em memória;
  • casos em que o mesmo cliente deve continuar indo para o mesmo Pod.

Cuidado:

  • pode reduzir distribuição equilibrada;
  • prefira aplicações stateless quando possível.

spec.sessionAffinityConfig

Configura detalhes da afinidade de sessão.

sessionAffinityConfig:
  clientIP:
    timeoutSeconds: 10800

Uso:

  • só faz sentido com sessionAffinity: ClientIP.

spec.sessionAffinityConfig.clientIP.timeoutSeconds

Tempo da afinidade por IP do cliente.

timeoutSeconds: 10800

Significado:

  • valor em segundos;
  • define por quanto tempo o cliente permanece associado ao mesmo backend.

spec.trafficDistribution

Indica preferência de distribuição de tráfego.

trafficDistribution: PreferClose

Uso:

  • preferência por endpoints mais próximos;
  • cenários em que o cluster suporta essa funcionalidade;
  • otimização de tráfego em topologias específicas.

Cuidado:

  • depende da versão e recursos habilitados no cluster;
  • pode ser omitido na maioria dos Services comuns.

status

status mostra o estado atual observado pelo Kubernetes.

Você normalmente não escreve status no YAML.

O Kubernetes e os controladores preenchem automaticamente.

No arquivo de referência aparecem campos como:

status:
  conditions
  loadBalancer

Use para diagnóstico:

kubectl get service minha-aplicacao -n meu-projeto
kubectl describe service minha-aplicacao -n meu-projeto
kubectl get service minha-aplicacao -n meu-projeto -o yaml

status.conditions

Lista condições atuais do Service.

conditions:
  lastTransitionTime
  message
  observedGeneration
  reason
  status
  type

Uso:

  • diagnóstico;
  • verificar estado observado por controladores;
  • entender mensagens relacionadas ao recurso.

Normalmente é somente leitura.


status.loadBalancer

Mostra status do balanceador, quando existe.

loadBalancer:
  ingress:
    hostname
    ip
    ipMode
    ports

Uso:

  • verificar IP externo;
  • verificar hostname externo;
  • diagnosticar Service LoadBalancer.

Exemplo de consulta:

kubectl get service minha-aplicacao -n meu-projeto

Manifesto mínimo funcional

apiVersion: v1
kind: Service
metadata:
  name: nginx-exemplo
  namespace: meu-projeto
spec:
  selector:
    app: nginx-exemplo
  ports:
    - port: 80
      targetPort: 80

Aplicar:

kubectl apply -f service.yml

Verificar:

kubectl get services -n meu-projeto
kubectl get endpoints nginx-exemplo -n meu-projeto

Manifesto recomendado para aplicação web simples

apiVersion: v1
kind: Service
metadata:
  name: app-web
  namespace: meu-projeto
  labels:
    app: app-web
spec:
  type: ClusterIP
  selector:
    app: app-web
  ports:
    - name: http
      appProtocol: http
      protocol: TCP
      port: 80
      targetPort: 8080
  sessionAffinity: None
  internalTrafficPolicy: Cluster

Este modelo é adequado para uma aplicação web/API que será acessada por outro Pod ou publicada por Ingress.


Manifesto para Service do tipo NodePort

apiVersion: v1
kind: Service
metadata:
  name: app-nodeport
  namespace: meu-projeto
spec:
  type: NodePort
  selector:
    app: app-nodeport
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 8080
      nodePort: 30080

Acesso:

http://IP-DO-NO:30080

Use com cuidado em ambiente compartilhado.


Manifesto para Service do tipo LoadBalancer

apiVersion: v1
kind: Service
metadata:
  name: app-loadbalancer
  namespace: meu-projeto
spec:
  type: LoadBalancer
  selector:
    app: app-loadbalancer
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 8080

Verificar IP externo:

kubectl get service app-loadbalancer -n meu-projeto

Se o cluster não tiver suporte a LoadBalancer, o IP externo pode ficar pendente.


Manifesto para Service do tipo ExternalName

apiVersion: v1
kind: Service
metadata:
  name: api-externa
  namespace: meu-projeto
spec:
  type: ExternalName
  externalName: api.exemplo.edu.br

Uso:

api-externa.meu-projeto.svc.cluster.local

Esse nome passa a resolver para:

api.exemplo.edu.br

Manifesto para Headless Service

apiVersion: v1
kind: Service
metadata:
  name: banco
  namespace: meu-projeto
spec:
  clusterIP: None
  selector:
    app: banco
  ports:
    - name: postgres
      protocol: TCP
      port: 5432
      targetPort: 5432

Uso comum:

  • StatefulSet;
  • sistemas distribuídos;
  • aplicações que precisam descobrir Pods individualmente.

Comandos úteis

Aplicar

kubectl apply -f service.yml

Ver Services

kubectl get services -n meu-projeto

Ver Service específico

kubectl get service minha-aplicacao -n meu-projeto

Ver detalhes

kubectl describe service minha-aplicacao -n meu-projeto

Ver endpoints

kubectl get endpoints minha-aplicacao -n meu-projeto

Ver EndpointSlices

kubectl get endpointslice -n meu-projeto -l kubernetes.io/service-name=minha-aplicacao

Ver YAML real aplicado

kubectl get service minha-aplicacao -n meu-projeto -o yaml

Testar DNS interno com Pod temporário

kubectl run teste-dns -n meu-projeto --rm -it --image=busybox:1.36 --restart=Never -- sh

Dentro do Pod:

nslookup minha-aplicacao

Testar HTTP com Pod temporário

kubectl run teste-curl -n meu-projeto --rm -it --image=curlimages/curl --restart=Never -- sh

Dentro do Pod:

curl -v http://minha-aplicacao:80

Relação com outros manifestos

Um Service normalmente faz parte de um conjunto de manifestos.

Uso típico:

Namespace
  ├── ConfigMap
  ├── Secret
  ├── ServiceAccount
  ├── Deployment
  ├── Service
  ├── Ingress
  ├── NetworkPolicy
  ├── ResourceQuota
  └── LimitRange

Service + Deployment

Deployment cria Pods.

Service expõe esses Pods por selector.

Service + Ingress

Ingress publica o Service por domínio HTTP/HTTPS.

Service + StatefulSet

StatefulSet pode usar Service comum ou Headless Service, dependendo do caso.

Service + NetworkPolicy

Service cria ponto de acesso.

NetworkPolicy controla quem pode acessar.

Service + EndpointSlice

EndpointSlice representa os endpoints reais usados pelo Service.

Normalmente é gerenciado automaticamente pelo Kubernetes.


Erros comuns

Selector diferente das labels dos Pods

Errado:

# Service
selector:
  app: app-a

# Pod
labels:
  app: app-b

Correto:

# Service
selector:
  app: app-a

# Pod
labels:
  app: app-a

Sintoma:

kubectl get endpoints app-a -n meu-projeto

Retorna vazio.


targetPort diferente da porta real do container

Errado:

ports:
  - port: 80
    targetPort: 80

Mas o container escuta em:

8080

Correto:

ports:
  - port: 80
    targetPort: 8080

Criar LoadBalancer sem suporte no cluster

Sintoma:

EXTERNAL-IP: <pending>

Possíveis causas:

  • cluster não tem controlador de LoadBalancer;
  • integração de infraestrutura ausente;
  • IP externo indisponível;
  • controlador não configurado.

Usar ExternalName esperando proxy

ExternalName não cria proxy.

Ele cria alias DNS.

Errado esperar que ele:

  • selecione Pods;
  • faça balanceamento interno;
  • crie endpoint;
  • abra porta no cluster.

Expor NodePort sem necessidade

NodePort pode funcionar, mas em ambiente compartilhado pode expor serviços de forma desorganizada.

Prefira:

Ingress + Service ClusterIP

para aplicações HTTP/HTTPS.


Service criado no namespace errado

Sintoma:

  • Deployment está em um namespace;
  • Service está em outro;
  • selector parece correto, mas endpoints ficam vazios.

Verificar:

kubectl get pods -A -l app=minha-aplicacao
kubectl get service -A | grep minha-aplicacao

Checklist para uso em produção

Antes de aplicar um Service em ambiente compartilhado:

  • namespace definido;
  • name claro;
  • labels claras;
  • selector combina com as labels dos Pods;
  • ports[].port definido corretamente;
  • ports[].targetPort aponta para a porta real do container;
  • ports[].protocol definido quando necessário;
  • porta nomeada quando houver múltiplas portas;
  • type adequado ao cenário;
  • ClusterIP usado como padrão para aplicações internas;
  • Ingress usado quando precisar domínio HTTP/HTTPS;
  • NodePort usado apenas quando realmente necessário;
  • LoadBalancer usado somente se o cluster tiver suporte;
  • ExternalName usado apenas para alias DNS externo;
  • endpoints verificados após aplicar;
  • Service testado a partir de outro Pod;
  • exposição externa revisada com cuidado;
  • NetworkPolicy criada se houver necessidade de isolamento.

Resumo

Use Service para criar acesso estável a Pods no Kubernetes.

O Service controla:

  • nome interno estável;
  • porta de acesso;
  • seleção de Pods por labels;
  • tipo de exposição;
  • balanceamento interno entre endpoints;
  • integração com Ingress e LoadBalancer, dependendo do cenário.

Para aplicação web comum, o conjunto mínimo geralmente é:

Namespace + Deployment + Service + Ingress

Para ambiente institucional compartilhado, o conjunto recomendado é:

Namespace + ResourceQuota + LimitRange + ServiceAccount + Role/RoleBinding
+ ConfigMap + Secret + Deployment + Service + Ingress + NetworkPolicy + PDB