| Bellacosa Mainframe e os kubernetes |
☕ Um Café no Bellacosa Mainframe
Kubernetes Services Muito Além do ClusterIP
O Que Todo Programador COBOL Padawan Precisa Saber Sobre ClusterIP, NodePort, LoadBalancer, ExternalName, DNS, Balanceamento, Alta Disponibilidade e Como os Grandes Bancos Mantêm Milhares de Microsserviços Funcionando Sem Que Ninguém Perceba
"Um bom programador conhece um endereço IP. Um excelente engenheiro cria sistemas onde ninguém precisa conhecer endereço algum."
Introdução
Durante décadas, nós, profissionais de Mainframe, aprendemos que estabilidade era uma virtude.
No IBM Z, dificilmente pensamos no endereço físico de uma aplicação.
Quando um operador acessa uma transação CICS, ele não precisa saber em qual LPAR ela está executando.
Quando um lote conversa com o DB2, ele não sabe onde está o buffer pool.
Quando um terminal 3270 executa uma transação, ele não precisa conhecer qual região AOR irá atendê-lo.
Existe uma camada de abstração.
Essa camada protege o usuário da complexidade.
Curiosamente, quase cinquenta anos depois, o Kubernetes resolveu exatamente o mesmo problema.
Só que agora para milhares de containers distribuídos em centenas de servidores Linux.
Se você é um Programador COBOL Padawan entrando no universo DevOps, Kubernetes pode parecer um mundo completamente diferente.
Mas não é.
Na verdade, muitos dos conceitos já existem no Mainframe há décadas.
Neste artigo vamos descobrir por que os Kubernetes Services talvez sejam um dos recursos mais importantes de toda a plataforma.
Antes de falar de Services...
Precisamos entender um conceito fundamental.
Tudo no Kubernetes é temporário.
Isso assusta quem vem do Mainframe.
No IBM Z pensamos assim:
"Meu programa está naquela máquina."
No Kubernetes pensamos diferente.
"Meu programa está em algum lugar do cluster."
Essa pequena mudança de mentalidade muda tudo.
Imagine uma aplicação simples.
Internet
↓
Frontend
↓
Backend
↓
Banco
Agora imagine que o Backend roda em três Pods.
Pod A
Pod B
Pod C
Cada Pod possui um endereço IP.
10.244.1.3
10.244.8.15
10.244.2.9
Até aqui parece simples.
O problema aparece quando um Pod morre.
Pods nascem e morrem o tempo todo
Ao contrário de um servidor tradicional, Pods são descartáveis.
Podem desaparecer por diversos motivos.
atualização
falha
manutenção
escalabilidade
reinício do Node
Rolling Update
Auto Scaling
Imagine:
Pod B
10.244.8.15
Foi destruído.
Kubernetes cria outro.
Pod D
10.244.19.44
Novo IP.
Novo identificador.
Nova localização.
Se todas as aplicações utilizassem o IP antigo, tudo quebraria.
É exatamente aqui que nasce o Kubernetes Service.
Afinal, o que é um Kubernetes Service?
A definição oficial diz:
Um Service fornece um endpoint de rede estável para acessar um conjunto de Pods.
Na prática podemos traduzir para:
Um Service é um endereço permanente que representa vários Pods temporários.
Observe.
Sem Service.
Cliente
↓
Pod A
10.244.1.7
Quando o Pod muda...
Tudo quebra.
Com Service.
Cliente
↓
backend-service
↓
Pod A
Pod B
Pod C
Agora o cliente nunca mais conversa diretamente com os Pods.
Essa é uma das ideias mais elegantes do Kubernetes.
A analogia perfeita para quem conhece Mainframe
Imagine um ambiente CICS.
Você possui:
TOR
AOR
FOR
WLM
Sysplex
VIPA
Quando um usuário acessa uma aplicação, ele normalmente não conhece qual AOR irá executar sua transação.
Existe uma infraestrutura inteligente fazendo esse trabalho.
No Kubernetes acontece exatamente a mesma coisa.
Cliente
↓
Service
↓
Pod 1
Pod 2
Pod 3
O Service é uma espécie de endereço lógico.
Assim como um VIPA.
Por que Services existem?
Existem cinco motivos principais.
1. Endereço permanente
Mesmo que todos os Pods sejam recriados.
O endereço continua igual.
2. DNS automático
Todo Service recebe automaticamente um nome DNS.
Exemplo.
backend-service
Ou
backend-service.default.svc.cluster.local
Isso elimina IPs fixos no código.
3. Balanceamento
Se existem quatro Pods...
Pod1
Pod2
Pod3
Pod4
O Service distribui as requisições.
Nenhum Pod fica sobrecarregado.
4. Descoberta de serviços
Imagine um cluster com:
PIX
Conta Corrente
Cartão
Investimentos
Fraude
Autenticação
Como um microsserviço encontra o outro?
Através do Service.
5. Desacoplamento
Aplicações deixam de depender da infraestrutura.
Mudamos Pods.
Mudamos Nodes.
Mudamos Cluster.
Nada muda para o cliente.
Como um Service funciona internamente?
Muita gente imagina que existe um processo rodando como um proxy.
Na maioria dos casos não.
O fluxo real é aproximadamente este.
Cliente
↓
DNS
↓
Service
↓
EndpointSlice
↓
kube-proxy
↓
iptables/IPVS/eBPF
↓
Pod
O kube-proxy cria regras dentro do próprio Kernel Linux.
O encaminhamento acontece praticamente sem intervenção de processos em espaço de usuário.
Endpoint e EndpointSlice
Quando criamos um Service, ele precisa descobrir quais Pods pertencem à aplicação.
Isso acontece através dos Labels.
Pod.
labels:
app: backend
Service.
selector:
app: backend
O Kubernetes encontra automaticamente todos os Pods.
Esses Pods são armazenados em objetos chamados EndpointSlices.
Nos clusters antigos existiam apenas Endpoints.
Hoje o EndpointSlice melhora muito a escalabilidade.
Os quatro tipos clássicos de Services
Agora chegamos ao coração do assunto.
ClusterIP
Este é o padrão.
Sempre que você cria um Service sem especificar o tipo, ele será ClusterIP.
type: ClusterIP
Ele cria um IP virtual acessível apenas dentro do cluster.
Arquitetura.
Frontend
↓
ClusterIP
↓
Backend
É o tipo mais utilizado.
Por quê?
Porque a maioria dos microsserviços nunca deve ficar pública.
Imagine um banco.
Você possui.
Serviço PIX
Serviço Cartão
Serviço Conta
Serviço Investimentos
Serviço Fraude
Nenhum deles precisa ser acessado pela Internet.
Todos usam ClusterIP.
Casos de uso
APIs internas
Banco de Dados
Redis
RabbitMQ
Kafka
Elasticsearch
MongoDB
NodePort
Agora a história muda.
NodePort abre uma porta fixa em todos os servidores do cluster.
Exemplo.
Node1
30080
Node2
30080
Node3
30080
Qualquer um responde.
Mesmo que o Pod esteja em outro servidor.
O acesso acontece assim.
192.168.1.50:30080
Muito útil para laboratório.
Pouco utilizado em produção.
Limitações
portas limitadas
pouca segurança
difícil gerenciamento
IP dos Nodes exposto
Por isso normalmente é utilizado apenas para desenvolvimento.
LoadBalancer
Quando trabalhamos em Cloud, LoadBalancer torna-se extremamente importante.
Criamos.
type: LoadBalancer
O Kubernetes conversa automaticamente com o provedor.
AWS cria um ELB.
Azure cria um Azure Load Balancer.
Google cria um Cloud Load Balancer.
IBM Cloud cria um IBM Cloud Load Balancer.
Tudo automaticamente.
Arquitetura.
Internet
↓
Cloud Load Balancer
↓
Service
↓
Pods
Essa automação impressiona quem vem do mundo tradicional.
Em poucos segundos uma infraestrutura completa aparece pronta.
ExternalName
Este tipo é diferente de todos os outros.
Ele não cria IP.
Não cria balanceamento.
Não cria Endpoint.
Não cria Proxy.
Ele apenas responde um nome DNS.
Exemplo.
externalName:
api.bcb.gov.br
Agora qualquer aplicação utiliza.
banco-central
Mesmo que o endereço verdadeiro mude.
Isso facilita migrações.
O quinto tipo que poucos lembram
Embora muitos materiais apresentem apenas quatro tipos, existe outro extremamente importante.
Headless Service.
clusterIP: None
Nesse caso não existe IP virtual.
O DNS devolve diretamente todos os Pods.
Muito utilizado em StatefulSets.
Exemplo.
Kafka
Cassandra
MongoDB
Elasticsearch
ZooKeeper
O papel do DNS
Uma das maiores mágicas do Kubernetes.
Criamos.
name: backend-service
Automaticamente nasce.
backend-service.default.svc.cluster.local
Nenhuma configuração adicional.
Isso é fornecido pelo CoreDNS.
Assim os desenvolvedores nunca precisam decorar IPs.
Como acontece o balanceamento?
Imagine.
Pod1
Pod2
Pod3
Chegam 900 requisições.
O Service distribui.
300
300
300
Na prática depende do mecanismo utilizado.
iptables
IPVS
eBPF
Mas a ideia continua sendo a mesma.
Distribuir carga.
O que acontece quando um Pod morre?
Suponha.
Pod2
Falhou.
Kubernetes percebe.
Remove o Pod do EndpointSlice.
O Service deixa imediatamente de enviar tráfego para ele.
O usuário nem percebe.
Depois um novo Pod nasce.
Automaticamente entra no balanceamento.
Tudo sem intervenção humana.
O papel das Readiness Probes
Outro conceito fundamental.
Um Pod pode estar vivo.
Mas ainda não pronto.
Imagine um sistema Java iniciando.
O processo já está executando.
Mas ainda carregando centenas de classes.
O Kubernetes espera a Readiness Probe informar.
"Agora estou pronto."
Só então o Service começa a enviar requisições.
Ingress não substitui Service
Esse erro aparece frequentemente em entrevistas.
Ingress faz uma função diferente.
Arquitetura correta.
Internet
↓
Load Balancer
↓
Ingress Controller
↓
ClusterIP
↓
Pods
Ingress trabalha na camada HTTP/HTTPS.
Service trabalha na camada de rede interna.
São tecnologias complementares.
Session Affinity
Por padrão.
Cada requisição pode ir para qualquer Pod.
Mas algumas aplicações antigas dependem de sessão.
Nesse caso.
sessionAffinity:
ClientIP
O mesmo cliente tende a conversar sempre com o mesmo Pod.
É semelhante ao conceito de Sticky Session.
Erros clássicos
Selector errado
Service.
selector:
app: api
Pods.
labels:
app: backend
Resultado.
Zero Endpoints.
TargetPort incorreto
Service.
targetPort: 8080
Container.
9090
Nada funciona.
Pod não Ready
Existe.
Está executando.
Mas ainda não recebe requisições.
NetworkPolicy
O Service funciona.
Mas a política de rede bloqueia o acesso.
O paralelo com o IBM Mainframe
Chegamos à parte mais interessante.
Veja esta comparação.
| IBM Mainframe | Kubernetes |
|---|---|
| Região CICS | Pod |
| Sysplex | Cluster |
| VIPA | ClusterIP |
| Sysplex Distributor | Service |
| WLM | Balanceamento |
| VTAM | Rede do Cluster |
| DNS Corporativo | CoreDNS |
| Health Check | Readiness Probe |
| Região AOR | Réplica do Deployment |
| Balanceador F5 | LoadBalancer |
Perceba que o Kubernetes não inventou todos esses conceitos.
Ele apenas os adaptou para um mundo distribuído baseado em Linux e containers.
Como um banco utiliza tudo isso?
Imagine um Internet Banking.
Internet
↓
Load Balancer
↓
Ingress
↓
Gateway
↓
Conta Corrente
↓
PIX
↓
Cartão
↓
Investimentos
↓
DB2
Cada caixa dessa arquitetura possui seu próprio ClusterIP.
Cada aplicação possui diversas réplicas.
Cada réplica pode estar em um servidor diferente.
Se um Node inteiro falhar.
O Kubernetes recria os Pods em outro Node.
Os Services continuam exatamente iguais.
Os clientes continuam utilizando os mesmos nomes DNS.
Nenhum código precisa ser alterado.
Esse é o verdadeiro poder da abstração.
Conclusão
Quando começamos a estudar Kubernetes, é comum dedicar muita atenção aos Pods, Deployments e Containers. Eles são importantes, mas representam apenas parte da história.
O componente que realmente transforma um conjunto de processos efêmeros em uma plataforma corporativa é o Service.
Ele fornece identidade estável para aplicações que mudam constantemente, esconde a complexidade da infraestrutura, distribui carga, integra-se ao DNS do cluster e permite que atualizações, escalabilidade e recuperação de falhas ocorram de forma transparente.
Para quem vem do universo IBM Mainframe, a ideia não é totalmente nova. Há décadas, tecnologias como VIPA, Sysplex Distributor, WLM e CICS já abstraem a localização física das aplicações e distribuem trabalho entre múltiplas instâncias. O Kubernetes segue a mesma filosofia, adaptando-a ao mundo dos containers, dos microsserviços e da computação em nuvem.
O grande aprendizado para o Programador COBOL Padawan é que o endereço de uma aplicação nunca deve depender da máquina onde ela está executando. Assim como um usuário de um sistema bancário não precisa saber qual região CICS processará sua transação, um consumidor de um microsserviço não deve conhecer o IP de um Pod. Ele deve conhecer apenas um nome lógico — o Service.
No fim das contas, Kubernetes Services representam muito mais do que um recurso de rede. Eles materializam princípios clássicos de engenharia de software: abstração, desacoplamento, alta disponibilidade, balanceamento de carga, resiliência e escalabilidade. São esses princípios que permitem que grandes bancos, seguradoras e empresas globais executem milhões de transações por dia, mantendo seus sistemas disponíveis mesmo quando containers são criados, destruídos e recriados continuamente. Entender esse mecanismo é um passo fundamental para qualquer desenvolvedor COBOL que deseje evoluir do mundo do processamento tradicional para a moderna engenharia de software baseada em DevOps, Cloud Native e IBM Z integrado ao ecossistema Kubernetes.