Introdução
Pods são temporários. Um Deployment pode substituir Pods durante atualizações (rollout), reinicializações ou escalonamentos, portanto, os clientes não devem se conectar diretamente aos IPs individuais dos Pods. Um Service fornece aos clientes um nome estável e um IP virtual, utilizando labels (rótulos) para rotear o tráfego para os Pods correspondentes atuais.
Neste laboratório, você criará um pequeno Deployment web, irá expô-lo com um Service do tipo ClusterIP, inspecionará como o Service seleciona os Pods de backend, testará o Service a partir de um Pod cliente e escalará o Deployment para observar a atualização dos endpoints do Service.
Criar um Deployment Web
Nesta etapa, você preparará um namespace e criará um Deployment que poderá ser exposto posteriormente com um Service.
Comece em /home/labex/project:
mkdir -p /home/labex/project
cd /home/labex/project
Verifique se o servidor da API do Kubernetes está acessível. Se a VM acabou de iniciar e o nó ainda não está pronto, aguarde alguns segundos e execute o comando novamente.
kubectl get nodes --request-timeout=5s
A saída esperada inclui:
NAME STATUS ROLES AGE VERSION
labex-v135 Ready control-plane ... v1.35...
Aguarde até que o Pod de rede do cluster esteja pronto (Ready). Este laboratório envia tráfego entre Pods através de um Service, portanto, a rede do cluster precisa estar saudável antes de testar o acesso.
kubectl wait --namespace kube-system --for=condition=Ready pod -l k8s-app=calico-node --timeout=120s
Saída esperada:
pod/calico-node-... condition met
Crie um namespace chamado ckad-prep-service e defina-o como o namespace atual:
kubectl create namespace ckad-prep-service
kubectl config set-context --current --namespace=ckad-prep-service
Crie um Deployment chamado web-front com um Pod NGINX. A flag --port=80 registra a porta do container no template do Pod. Ela não cria um Service por si só.
kubectl create deployment web-front --image=nginx:1.25 --port=80
Aguarde até que o Deployment esteja disponível e, em seguida, inspecione o label do Pod. O label app=web-front é importante, pois o Service o utilizará para encontrar os Pods de backend.
kubectl rollout status deployment/web-front --timeout=120s
kubectl get pods -l app=web-front --show-labels
A saída esperada inclui:
deployment "web-front" successfully rolled out
NAME READY STATUS RESTARTS AGE LABELS
web-front-... 1/1 Running 0 ... app=web-front,...
Expor o Deployment com um Service do tipo ClusterIP
Nesta etapa, você criará um Service para o Deployment e inspecionará os campos que conectam o Service aos Pods.
Use kubectl expose deployment para criar um Service do tipo ClusterIP. A porta do Service é 80, e --target-port=80 instrui o Service a encaminhar o tráfego para a porta 80 nos Pods correspondentes.
kubectl expose deployment web-front --name=web-front --port=80 --target-port=80
Saída esperada:
service/web-front exposed
Inspecione o Service:
kubectl get service web-front
A saída esperada inclui:
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
web-front ClusterIP ... <none> 80/TCP ...
Agora, inspecione o seletor do Service e o mapeamento de portas. O seletor é como o Service encontra os Pods; o mapeamento de porta é como o tráfego do cliente chega ao container.
kubectl get service web-front -o jsonpath='{.spec.selector.app}{" "}{.spec.ports[0].port}{":"}{.spec.ports[0].targetPort}{"\n"}'
Saída esperada:
web-front 80:80
O Kubernetes armazena os endereços de backend selecionados em EndpointSlices. Liste o EndpointSlice criado para este Service:
kubectl get endpointslice -l kubernetes.io/service-name=web-front
A saída esperada inclui:
NAME ADDRESSTYPE PORTS ENDPOINTS AGE
web-front-... IPv4 80 ... ...
Testar o Service a partir de dentro do cluster
Nesta etapa, você criará um Pod cliente temporário e enviará uma requisição HTTP para o Service. Um Service do tipo ClusterIP destina-se ao acesso interno ao cluster, portanto, testar a partir de outro Pod é a maneira mais direta de verificá-lo.
Crie um Pod cliente que permaneça em execução:
kubectl run service-client --image=busybox:1.36 --restart=Never --command -- sleep 3600
Aguarde até que o Pod cliente esteja pronto:
kubectl wait --for=condition=Ready pod/service-client --timeout=120s
Saída esperada:
pod/service-client condition met
Use wget dentro do Pod cliente para solicitar http://web-front. O nome web-front é resolvido para o Service dentro do namespace.
kubectl exec service-client -- wget -qO- http://web-front | head -n 5
A saída esperada inclui o início da página padrão do NGINX:
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
Isso prova que o cliente alcançou o nome estável do Service e que o Service encaminhou o tráfego para o Pod de backend atual.
Escalar o Backend e verificar novamente os Endpoints
Nesta etapa, você escalará o Deployment e confirmará que o Service mantém o mesmo ponto de entrada estável enquanto seus endpoints de backend mudam.
Escale o Deployment para duas réplicas:
kubectl scale deployment web-front --replicas=2
kubectl rollout status deployment/web-front --timeout=120s
A saída esperada inclui:
deployment.apps/web-front scaled
deployment "web-front" successfully rolled out
Liste os Pods. Agora deve haver dois Pods de backend em execução com o mesmo label app=web-front.
kubectl get pods -l app=web-front
A saída esperada inclui dois Pods:
NAME READY STATUS RESTARTS AGE
web-front-... 1/1 Running 0 ...
web-front-... 1/1 Running 0 ...
Conte os endpoints por trás do Service. O comando imprime uma linha para cada endereço de endpoint e, em seguida, conta as linhas.
kubectl get endpointslice -l kubernetes.io/service-name=web-front -o jsonpath='{range .items[*].endpoints[*]}{.addresses[0]}{"\n"}{end}' | wc -l
Saída esperada:
2
Solicite o Service novamente a partir do mesmo Pod cliente:
kubectl exec service-client -- wget -qO- http://web-front | grep '<title>Welcome to nginx'
Saída esperada:
<title>Welcome to nginx!</title>
Resumo
Você expôs um Deployment com um Service do tipo ClusterIP e verificou o caminho completo de acesso dentro do cluster. Você criou um Deployment de backend, criou um Service com um seletor e mapeamento de porta, inspecionou o EndpointSlice gerado para o Service, testou o acesso a partir de um Pod cliente, escalou o Deployment e confirmou que o Service continuou roteando para o conjunto de backend atualizado.


