Introdução
Os Services fornecem pontos de acesso estáveis para as aplicações dentro de um cluster. O Ingress adiciona regras de roteamento HTTP na frente dos Services, permitindo que várias aplicações compartilhem um único ponto de entrada por nome de host ou caminho da URL.
Você vai inspecionar o controlador ingress-nginx já preparado, implantar dois backends, adicionar roteamento por host e por caminho e acompanhar uma requisição passando pelo Ingress, pelo Service e pelo Pod.
Durante todo o laboratório, mantenha em mente o caminho da requisição: cliente → ponto de entrada do ingress-nginx → regra do Ingress → Service → Pod pronto. Quando uma requisição falhar, verificar esses elementos nessa ordem é muito mais simples do que tratar o Ingress como uma caixa-preta única.
Inspecionar o controlador do Ingress
Nesta etapa, inspecione o controlador já fornecido pelo ambiente CKA, em vez de instalar uma segunda cópia.
Um objeto Ingress é uma configuração, não um processo de proxy. Ele só produz efeito quando um controlador compatível o observa. Comece comprovando que os dois componentes da infraestrutura existem: uma IngressClass chamada nginx e um Deployment do ingress-nginx disponível.
cd /home/labex/project/ingress-routing
kubectl get ingressclasses
kubectl get deployments,pods,services -n ingress-nginx
kubectl wait --for=condition=Available deployment/ingress-nginx-controller -n ingress-nginx --timeout=60s
Um recurso Ingress armazena a intenção de roteamento. O controlador ingress-nginx observa os recursos cujo ingressClassName é nginx e configura o proxy real.
O Service do controlador expõe o proxy por meio de um NodePort neste cluster local. Você descobrirá essa porta mais adiante, em vez de fixá-la diretamente.
O ambiente preparado informa uma classe nginx, um controlador disponível e um Service NodePort:
NAME CONTROLLER
nginx k8s.io/ingress-nginx
deployment.apps/ingress-nginx-controller 1/1 ...
service/ingress-nginx-controller NodePort ... 80:.../TCP,443:.../TCP
Os dois Pods de admissão com status Completed que você também pode ver são Jobs de instalação já concluídos; eles não representam réplicas do controlador que falharam.
Implantar dois backends de Service
Nesta etapa, crie duas cargas de trabalho web com uma réplica cada e os respectivos Services ClusterIP a partir de um único arquivo com vários documentos.
Esses backends usam conceitos apresentados em Kubernetes para iniciantes, portanto o foco aqui é a relação de roteamento, e não a sintaxe do Deployment. O arquivo contém cinco documentos YAML separados por ---: primeiro um namespace e, em seguida, um Deployment e um Service para cada aplicação. Observe o Service.spec.selector ao lado do rótulo correspondente do Pod; eles precisam coincidir para que o Ingress consiga alcançar qualquer backend.
cd /home/labex/project/ingress-routing
cat <<'EOF' > backends.yaml
apiVersion: v1
kind: Namespace
metadata: {name: practice-ingress}
---
apiVersion: apps/v1
kind: Deployment
metadata: {name: storefront, namespace: practice-ingress}
spec:
replicas: 1
selector: {matchLabels: {app: storefront}}
template:
metadata: {labels: {app: storefront}}
spec:
containers: [{name: web, image: nginx:1.27-alpine, imagePullPolicy: IfNotPresent, ports: [{name: http, containerPort: 80}]}]
---
apiVersion: v1
kind: Service
metadata: {name: storefront, namespace: practice-ingress}
spec: {selector: {app: storefront}, ports: [{name: http, port: 80, targetPort: http}]}
---
apiVersion: apps/v1
kind: Deployment
metadata: {name: reports, namespace: practice-ingress}
spec:
replicas: 1
selector: {matchLabels: {app: reports}}
template:
metadata: {labels: {app: reports}}
spec:
containers: [{name: web, image: httpd:2.4-alpine, imagePullPolicy: IfNotPresent, ports: [{name: http, containerPort: 80}]}]
---
apiVersion: v1
kind: Service
metadata: {name: reports, namespace: practice-ingress}
spec: {selector: {app: reports}, ports: [{name: http, port: 80, targetPort: http}]}
EOF
Aplique os cinco documentos de uma só vez e, em seguida, aguarde os dois Deployments. Esperar por cada um separadamente deixa claro qual backend falhou caso haja algum problema com a imagem ou com o seletor:
kubectl apply -f backends.yaml
kubectl rollout status deployment/storefront -n practice-ingress --timeout=60s
kubectl rollout status deployment/reports -n practice-ingress --timeout=60s
O Ingress encaminha requisições apenas para Services, portanto cada backend já precisa ter endpoints prontos.
Confirme explicitamente esse pré-requisito antes de criar as regras de roteamento:
kubectl get services,endpointslices -n practice-ingress
Cada Service deve ter um EndpointSlice correspondente com um endereço pronto.
service/reports ClusterIP ... 80/TCP
service/storefront ClusterIP ... 80/TCP
endpointslice.../reports-... IPv4 80 10.244.104...
endpointslice.../storefront-... IPv4 80 10.244.104...
Os sufixos gerados e os endereços variam, mas cada nome de Service deve ter um EndpointSlice não vazio. O Ingress não consegue corrigir um Service sem backend; esta verificação comprova deliberadamente primeiro a camada inferior.
Adicionar roteamento baseado em host
Nesta etapa, encaminhe store.practice.test para o Service storefront.
Uma regra de Ingress toma três decisões de roteamento: host, path e a porta do Service de backend. ingressClassName: nginx seleciona o controlador. A anotação de reescrita é específica do controlador; ela altera o caminho da requisição enviada ao backend para /, que pode ser atendido pelos dois servidores de demonstração.
cd /home/labex/project/ingress-routing
cat <<'EOF' > ingress.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: practice-routing
namespace: practice-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
rules:
- host: store.practice.test
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: storefront
port: {name: http}
EOF
Aplique a regra e use describe para consultar como o controlador a interpretou, incluindo o endpoint de backend resolvido:
kubectl apply -f ingress.yaml
kubectl describe ingress practice-routing -n practice-ingress
pathType: Prefix corresponde a / e aos caminhos abaixo dele. A anotação de reescrita envia a requisição selecionada para / no backend, onde o servidor web de demonstração possui uma página. O host é uma chave de roteamento HTTP; ele não precisa de DNS público para este teste local.
O describe deve resolver a regra até chegar ao endereço de um Pod:
Rules:
Host Path Backends
store.practice.test
/ storefront:http (10.244.104...:80)
Um campo Address de nível superior vazio logo após a criação não indica uma falha neste ambiente local. O backend storefront:http resolvido e o endereço do Pod são as evidências importantes.
Adicionar roteamento por caminho e testar as requisições
Nesta etapa, adicione o roteamento para /reports e teste as duas regras por meio do ponto de entrada do nó.
O caminho do patch JSON termina em /-. Para um array, - significa adicionar um novo item ao final, em vez de substituir a rota / existente. O novo backend aponta para o Service reports por meio de sua porta nomeada http.
Execute este patch de adição uma única vez. Diferentemente de kubectl apply, adicionar em /- não é idempotente: repeti-lo acrescenta outro item /reports idêntico, em vez de reconhecer o item anterior.
As duas atribuições seguintes descobrem o endpoint em vez de fixar seu valor. minikube ip -p labex-v135 retorna o IP do nó para o perfil nomeado do Minikube, e a substituição de comando $(...) armazena a saída de cada comando em uma variável do shell. A consulta JSONPath seleciona a porta do Service chamada http e extrai seu NodePort.
kubectl patch ingress practice-routing -n practice-ingress --type='json' -p='[{"op":"add","path":"/spec/rules/0/http/paths/-","value":{"path":"/reports","pathType":"Prefix","backend":{"service":{"name":"reports","port":{"name":"http"}}}}}]'
NODE_IP=$(minikube ip -p labex-v135)
HTTP_NODE_PORT=$(kubectl get service ingress-nginx-controller -n ingress-nginx -o jsonpath='{.spec.ports[?(@.name=="http")].nodePort}')
echo "Ingress endpoint: ${NODE_IP}:${HTTP_NODE_PORT}"
As duas variáveis evitam inserir endereços específicos do ambiente diretamente nas instruções. Agora envie requisições com o cabeçalho de host exigido pela regra. Em cada comando curl, -s oculta o indicador de progresso, --retry 5 repete a tentativa em caso de falhas transitórias, --retry-connrefused também repete quando a conexão é recusada inicialmente e --retry-delay 2 aguarda dois segundos entre as tentativas. -H fornece o cabeçalho HTTP Host, e o pipe envia a resposta para grep, exibindo apenas o texto identificador da página.
curl -s --retry 5 --retry-connrefused --retry-delay 2 -H 'Host: store.practice.test' "http://${NODE_IP}:${HTTP_NODE_PORT}/" | grep 'Welcome to nginx'
curl -s --retry 5 --retry-connrefused --retry-delay 2 -H 'Host: store.practice.test' "http://${NODE_IP}:${HTTP_NODE_PORT}/reports" | grep 'It works'
As duas respostas comprovam que um único ponto de entrada encaminha requisições para Services diferentes.
A primeira resposta vem do NGINX e a segunda do Apache httpd. O texto distinto das páginas é uma evidência deliberada de que a regra de caminho selecionou outro backend, e não apenas de que o proxy retornou HTTP 200.
As linhas esperadas são:
<title>Welcome to nginx!</title>
<h1>Welcome to nginx!</h1>
<title>It works! Apache httpd</title>
<p>It works!</p>
Esse resultado também explica por que o cabeçalho Host personalizado é importante: as duas requisições chegam ao mesmo IP do nó e ao mesmo NodePort; são o host e o caminho que selecionam a regra e o backend.
Resumo
Você reutilizou o controlador ingress-nginx preparado, conectou regras de Ingress a Services prontos e testou o roteamento baseado em host e caminho por meio de um único ponto de entrada.


