Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 65

Exposing Deployments with Kubernetes Services

Recommended resources

Olá! Bem-vindo de volta ao nosso módulo de Fundamentos do Kubernetes.

Na lição anterior, você aprendeu a criar e gerenciar um Deployment de forma declarativa, usando um manifesto YAML. Agora temos dois Pods Nginx em execução, mas eles estão isolados, acessíveis apenas pela sua rede interna e efêmera do cluster. Isso nos leva a uma questão fundamental: como nos comunicamos com eles de forma confiável? Os IPs dos Pods mudam toda vez que são recriados, então não podemos depender deles.

É aqui que entra o objeto Service do Kubernetes. Um Service atua como um ponto de acesso de rede estável para um conjunto de Pods. Nesta lição, você aprenderá como expor seu Deployment usando dois tipos de Service: ClusterIP para comunicação interna e NodePort para acesso externo básico.

Seu objetivo hoje é: Autenticar e aplicar um manifesto de Service do Kubernetes (ClusterIP, NodePort) para expor um Deployment.

Por que Precisamos de Services? O Problema dos Pods Efêmeros

Como você viu, um Deployment gerencia Pods para corresponder a um estado desejado. Se um Pod falhar, o Deployment o substitui por um novo. Esse novo Pod terá um novo endereço IP. Isso cria um problema: como outros componentes (sejam outros Pods "frontend" ou usuários externos) podem encontrar e se comunicar com os Pods "backend" se seus IPs estão em constante mudança?

A resposta é o Service. Um Service fornece uma abstração que resolve esse problema.

Service

Para entender o papel fundamental dos Services, leia a introdução da documentação oficial do Kubernetes. Ela explica exatamente o problema que os Services resolvem.

Leia as seções introdutórias até "Defining a Service". Concentre-se em entender por que os Pods são considerados efêmeros e como o objeto Service permite o desacoplamento entre clientes e os Pods que eles precisam acessar.

Em essência, um Service:

  1. Recebe um endereço IP virtual estável (chamado de ClusterIP) e um nome DNS dentro do cluster.
  2. Usa labels e selectors (o mesmo mecanismo que você usou no Deployment) para encontrar dinamicamente os Pods saudáveis que deve direcionar.
  3. Funciona como um balanceador de carga básico, distribuindo o tráfego entre os Pods selecionados.

Isso significa que seus clientes se conectam ao Service, e o Service se encarrega de encaminhar a solicitação para um dos Pods de destino, não importa quais sejam seus IPs atuais.


Anatomia de um Manifesto de Service

Assim como um Deployment, um Service é definido em um arquivo YAML. A estrutura é familiar, mas os campos no spec são diferentes.

Kubernetes YAML File Explained - Deployment and Service | Kubernetes Tutorial 19

O vídeo a seguir, do canal TechWorld with Nana, oferece uma excelente comparação visual entre os manifestos de Deployment e Service. Preste atenção em como o selector do Service se conecta aos labels dos Pods.

Assista do timestamp 04:43 a 08:42. O foco aqui é entender a relação entre os labels e selectors, e a configuração de ports e targetPort no manifesto do Service.

Os campos chave no spec de um Service são:

  • selector: Define quais Pods pertencem a este Service. Deve corresponder aos labels dos Pods que você deseja expor (em nosso caso, os Pods criados pelo nginx-deployment).
  • ports: Uma lista de definições de portas.
    • port: A porta na qual o próprio Service (seu ClusterIP) exporá. Outros Pods no cluster se conectarão a esta porta.
    • targetPort: A porta nos Pods de destino para a qual o tráfego deve ser encaminhado. Isso deve corresponder ao containerPort que sua aplicação está escutando.
  • type: Especifica o tipo de Service. Vamos explorar ClusterIP e NodePort.


Mão na Massa: Expondo nosso Deployment

Vamos aplicar esses conceitos. Certifique-se de que o nginx-deployment da lição anterior ainda esteja em execução. Se não estiver, aplique-o novamente:
kubectl apply -f nginx-deployment.yaml

Passo 1: Exposição Interna com ClusterIP

O ClusterIP é o tipo de Service padrão. Ele cria um IP virtual acessível apenas de dentro do cluster. É ideal para comunicação entre microserviços (por exemplo, sua API Web se comunicando com um banco de dados).

Day 9/40 - Kubernetes Services Explained - ClusterIP vs NodePort vs Loadbalancer vs External

Este vídeo explica em detalhes o conceito de ClusterIP e por que ele é necessário para a comunicação interna, abordando o problema dos IPs de Pods efêmeros que mencionamos.

Assista da marca de 30:20 a 37:32. O vídeo demonstra como criar um Service ClusterIP e explica o conceito de Endpoints, que são os IPs reais dos Pods para os quais o Service está direcionando o tráfego.

Agora, vamos criar nosso próprio Service ClusterIP.

  1. Crie o manifesto do Service:
    Crie um novo arquivo chamado nginx-service-clusterip.yaml:

    # nginx-service-clusterip.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-service
    spec:
      # type: ClusterIP é o padrão, então podemos omiti-lo.
      selector:
        app: nginx  # Encontre Pods com o label 'app: nginx'
      ports:
        - protocol: TCP
          port: 80         # A porta deste Service
          targetPort: 80   # Encaminhe para a porta 80 nos Pods
    

    Note que o selector (app: nginx) corresponde exatamente ao label que definimos no template do nosso nginx-deployment.yaml. É assim que a conexão é feita.

  2. Aplique o manifesto:

    kubectl apply -f nginx-service-clusterip.yaml
    

    Você verá service/nginx-service created.

  3. Verifique o Service:

    kubectl get service nginx-service
    

    A saída mostrará o nome do serviço, o tipo ClusterIP, o IP do cluster que foi alocado e a porta (80).

  4. Inspecione os Endpoints:
    Para confirmar que o Service encontrou nossos Pods, use o comando describe:

    kubectl describe service nginx-service
    

    Procure pela linha Endpoints. Você verá os endereços IP e portas dos dois Pods Nginx que nosso Deployment está gerenciando. O Service manterá essa lista atualizada automaticamente.

  5. Teste a conectividade (de dentro do cluster):
    Como o ClusterIP é interno, não podemos acessá-lo do nosso computador. Para testar, vamos executar um Pod temporário dentro do cluster e tentar nos conectar ao Service.

    kubectl run busybox --image=busybox:1.28 --rm -it --restart=Never -- wget -qO- http://nginx-service
    
    • Este comando cria um Pod busybox temporário (--rm -it).
    • Dentro dele, executa wget para fazer uma requisição HTTP para http://nginx-service. O Kubernetes fornece resolução DNS interna, então podemos usar o nome do Service como hostname.
    • Você deverá ver a página de boas-vindas do Nginx! Isso confirma que nosso Service está funcionando e roteando o tráfego corretamente.

Passo 2: Exposição Externa com NodePort

E se quisermos acessar nossa aplicação de fora do cluster, por exemplo, durante o desenvolvimento? O tipo NodePort é uma maneira simples de fazer isso.

Um Service do tipo NodePort faz duas coisas:

  1. Cria um ClusterIP (como antes).
  2. Expõe o Service em uma porta estática (o NodePort) no endereço IP de cada nó do cluster. O NodePort deve estar em um intervalo padrão, geralmente 30000-32767.

O tráfego flui assim: Requisição Externa → IP_DO_NÓ:NodePort → ClusterIP_DO_SERVICE:Port → IP_DO_POD:TargetPort.

Este diagrama ilustra como o tráfego externo entra através de uma porta em um nó (NodePort), é roteado internamente pelo Service e finalmente chega a um dos Pods de destino.

Vamos modificar nosso Service para usar NodePort.

CKA Full Course 2024: Day 9/40 Kubernetes Services ...

Este artigo prático mostra como modificar um Service de ClusterIP para NodePort e testar o acesso externo. Siga os passos para aplicar o conceito na prática.

Leia as seções 6 ("Change the Service Type for External Access") e 7 ("Access the Service in Your Browser or Using curl"). Elas fornecem o manifesto YAML para um Service NodePort e o comando para testá-lo.

  1. Modifique o manifesto do Service:
    Crie um novo arquivo nginx-service-nodeport.yaml ou modifique o existente.
    # nginx-service-nodeport.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-service
    spec:
      type: NodePort   # Mude o tipo para NodePort
      selector:
        app: nginx
      ports:
        - protocol: TCP
          port: 80         # Porta no ClusterIP
          targetPort: 80   # Porta no Pod
          nodePort: 30007  # Porta estática nos nós (dentro do intervalo 30000-32767)
    
    Aqui, especificamos explicitamente type: NodePort e definimos um nodePort fixo como 30007. Se você omitir o campo nodePort, o Kubernetes escolherá uma porta aleatória do intervalo.
*Este manifesto anotado destaca as partes principais de um Service NodePort, incluindo `type`, `selector` e as três definições de porta.*

2. Aplique a nova configuração:
O kubectl apply é inteligente. Ele detectará a mudança no arquivo e atualizará o objeto Service existente.
bash kubectl apply -f nginx-service-nodeport.yaml
A saída será service/nginx-service configured.

  1. Verifique a mudança:

    kubectl get service nginx-service
    

    Agora você verá que o TYPE é NodePort. Na coluna PORT(S), você verá algo como 80:30007/TCP, indicando que a porta 80 do Service está mapeada para a porta 30007 nos nós.

  2. Teste o acesso externo:
    Como você provavelmente está usando uma configuração local como Docker Desktop ou Minikube, o IP do nó é mapeado para localhost. Abra seu navegador e vá para http://localhost:30007, ou use curl:

    curl http://localhost:30007
    

    Você deve ver a página de boas-vindas do Nginx novamente, mas desta vez, a requisição veio de fora do cluster!

Teste seu entendimento!

Em um manifesto NodePort, você tem port: 8080, targetPort: 80 e nodePort: 31000. Descreva o caminho que um pacote de rede segue desde um cliente externo até a aplicação dentro do contêiner.

Show answer
  1. O cliente externo envia uma requisição para http://<IP_DO_NÓ>:31000.
  2. O Kubernetes no nó recebe o tráfego na porta 31000 (nodePort) e o encaminha para o ClusterIP do Service na porta 8080 (port).
  3. O Service então seleciona um Pod de destino e encaminha o tráfego para a porta 80 (targetPort) desse Pod, onde a aplicação está escutando.

Conclusão

Parabéns! Você agora entende como expor suas aplicações no Kubernetes. Você aprendeu a criar um ponto de acesso de rede estável e desacoplado para seus Pods, que são inerentemente efêmeros.

Principais Pontos:

  • Service é a solução: Ele fornece um IP e DNS estáveis para um conjunto de Pods, resolvendo o problema dos IPs de Pods que mudam.
  • Seletores são a cola: Services usam labels e selectors para descobrir e rotear o tráfego para os Pods corretos.
  • ClusterIP é para comunicação interna: Fornece um IP acessível apenas de dentro do cluster, ideal para a comunicação back-end.
  • NodePort é para acesso externo simples: Expõe o Service em uma porta estática em cada nó, útil para desenvolvimento e cenários onde um balanceador de carga completo não é necessário.

Para limpar os recursos, você pode deletar tanto o Service quanto o Deployment:

kubectl delete -f nginx-service-nodeport.yaml
kubectl delete -f nginx-deployment.yaml

Próxima Lição:
Até agora, nossa imagem de contêiner e configuração estão misturadas. Em um ambiente de produção real, queremos separar a configuração (como strings de conexão de banco de dados ou chaves de API) da imagem do contêiner para torná-la mais portátil e segura. Na próxima lição, "Gerenciar a configuração da aplicação usando ConfigMaps", exploraremos como o Kubernetes nos permite injetar dados de configuração em nossos Pods no momento da execução.