Aula 07 – Kubernetes – Services

Aula 07 – Kubernetes – Services

Voltar para página principal do blog

Todas as aulas desse curso

Aula 06                                                 Aula 08

Redes Sociais:

facebook              

 

Site das bibliotecas

Tensorflow

Keras

Cursos Gratuitos

Digital Innovation

Quer aprender python3 de graça e com certificado? Acesse então:

workover

Empresas de Cloud:

Hostinger

Digital Ocean

One.com

Canais do Youtube

Toti

Lofi Music Zone Beats

Backing Track / Play-Along

Código Fluente

Putz!

Vocal Techniques and Exercises

Fiquem a vontade para me adicionar ao linkedin.

PIX para doações

PIX Nubank

PIX Nubank


Aula 07 – Kubernetes – Services

Documentação do Minikube: https://minikube.sigs.k8s.io/docs
Documentação do Kubernetes: https://kubernetes.io/docs/home/
Github do Kubernetes: https://github.com/kubernetes/kubernetes
Playground: https://killercoda.com/kubecon

Introdução

Bem-vindos à sétima aula do curso de Kubernetes!

Hoje, vamos aprender sobre os Services, um componente fundamental para a comunicação e exposição de aplicações no Kubernetes.

Services – Visão Geral

O que é um Service?

Um Service no Kubernetes é um recurso abstrato que define um conjunto lógico de Pods e uma política pela qual podemos acessá-los.

Os Services permitem a comunicação entre diferentes Pods ou entre Pods e o mundo externo.

Por que usar Services?

  1. Descoberta de Serviços: Em um cluster Kubernetes, os Services permitem que os Pods se comuniquem entre si sem precisar saber a localização exata de cada um.
  2. Balanceamento de Carga: Os Services distribuem automaticamente o tráfego de rede entre os Pods, permitindo balanceamento de carga e alta disponibilidade.
  3. Exposição de Aplicações: Os Services podem expor aplicações rodando em Pods tanto internamente, isto é, dentro do cluster, quanto para o mundo externo.

Tipos de Services

  1. ClusterIP: Exposição do serviço dentro do cluster.
  2. NodePort: Exposição do serviço em um endereço IP estático do nó.
  3. LoadBalancer: Integração com Load Balancers externos providos por servidores na nuvem.
  4. ExternalName: Mapeia um serviço para um nome DNS externo.
  5. Headless: Serviço Kubernetes sem IP fixo, permite acesso direto a cada Pod individualmente.

Cluster IP

Service Cluster IP

Service Cluster IP

Nodeport

Nodeport

Nodeport

LoadBalancer

LoadBalancer

LoadBalancer

ExternalName

ExternalName

ExternalName

Antes de tudo, inicie o minikube!

minikube start

Veja o status

minikube status

Veja se já existe um Deployment  existente:

kubectl get deployments

No meu caso a saída foi:

NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deployment 3/3 3 3 46d

kubectl delete deployment nginx-deployment

Criar um Deployment

Antes de criar o Service, você precisa de um Deployment com Pods que o Service possa direcionar.

Supondo que você já tenha um Deployment com o label app: nginx, e você não deletou, como eu fiz com o comando acima, você pode pular este passo, caso contrário, crie um com o seguinte arquivo YAML, ajuste conforme necessário.

Se quiser deletar o deployment

nginx-deployment.yaml


apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3  # Número de réplicas
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx-container
          image: nginx:latest
          ports:
            - containerPort: 80

Aplique o yaml

kubectl apply -f nginx-deployment.yaml

Tipos de Services no Kubernetes e Seus Usos

ClusterIP

  • Descrição: Este é o tipo de Service padrão. Ele expõe o Service dentro do cluster em um endereço IP interno. Isso significa que o Service só é acessível dentro do cluster.
  • Uso Prático: Utilizado para comunicação interna entre aplicações dentro do mesmo cluster. Por exemplo, um front-end em execução dentro do cluster que precisa se comunicar com um back-end também no cluster.

Isso é útil para comunicação entre serviços dentro do cluster, mas não para acesso externo.

clusterIP-service.yaml


apiVersion: v1
kind: Service
metadata:
  name: my-cluster-ip-service
spec:
  type: ClusterIP
  ports:
    - port: 80
  selector:
    app: nginx

Aplique o yaml

kubectl apply -f clusterIP-service.yaml

Alguns comandos exploratórios:

kubectl get services

kubectl describe service my-cluster-ip-service

kubectl get endpoints my-cluster-ip-service

kubectl get pods

kubectl logs [nome-do-pod]

kubectl exec -it [nome-do-pod] -- [comando]

kubectl exec -it [nome-do-pod] -- curl http://localhost:80

kubectl exec -it [nome-do-pod] -- /bin/bash

kubectl get service my-cluster-ip-service -o yaml

Explicação:

  • apiVersion: v1: A versão da API para definir Services.
  • kind: Service: O tipo do recurso que estamos criando.
  • metadata:
    • name: my-cluster-ip-service: O nome do Service.
  • spec:
    • type: ClusterIP: Define que este é um Service do tipo ClusterIP, acessível apenas dentro do cluster.
    • ports:
      • port: 80: A porta que o Service irá expor.
    • selector:
      • app: nginx: Seleciona os Pods com o label app: nginx. Isso deve corresponder aos labels dos Pods criados pelo seu Deployment nginx-deployment.

Certifique-se de que o label app: nginx está correto e corresponde aos labels dos Pods no seu Deployment nginx-deployment. Se os labels forem diferentes, ajuste o selector no YAML do Service para corresponder aos labels corretos dos Pods.

NodePort

  • Descrição: Este tipo de Service expõe o Service em cada Node do cluster usando uma porta estática (o NodePort). Um ClusterIP é automaticamente criado, e o Service é acessível no <NodeIP>:<NodePort>.
  • Uso Prático: Útil quando você quer acesso externo ao Service de fora do cluster. Por exemplo, para acessar uma aplicação web de um navegador.

node-port-service.yaml


apiVersion: v1
kind: Service
metadata:
  name: my-nodeport-service
spec:
  type: NodePort
  ports:
    - port: 80
      nodePort: 30007
  selector:
    app: nginx

Aplique o yaml

kubectl apply -f node-port-service.yaml

Alguns comandos exploratórios:

kubectl get services

kubectl get service my-nodeport-service

kubectl get nodes -o wide

http://<Endereço-IP-do-Nó>:<NodePort>

No meu caso, no navegador eu coloco: http://192.168.59.104:30007

Ou é só digitar:
minikube service my-nodeport-service

Explicação:

  • apiVersion: v1: A versão da API Kubernetes utilizada para criar o Service.
  • kind: Service: O tipo do recurso sendo criado.
  • metadata:
    • name: my-nodeport-service: O nome atribuído ao seu Service.
  • spec:
    • type: NodePort: Define o tipo do Service como NodePort.
    • ports:
      • port: 80: A porta interna do cluster que o Service escuta.
      • nodePort: 30007: A porta externa no nó do cluster onde o Service estará acessível. Esse valor deve estar dentro do range padrão permitido (geralmente 30000-32767).
    • selector:
      • app: nginx: Seleciona os Pods baseados no label. Neste caso, selecionará os Pods que fazem parte do Deployment nginx-deployment.

LoadBalancer

  • Descrição: Esse tipo de Service expõe o Service externamente usando o Load Balancer de um provedor de nuvem. Ele atribui um IP externo ao Service.
  • Uso Prático: Ideal para distribuir o tráfego de internet para os Pods. Comum em ambientes de produção para aplicações web.

Obs: O tipo LoadBalancer no Minikube difere de um ambiente de produção em nuvem, onde um IP externo seria fornecido pelo provedor de nuvem e o tráfego seria distribuído entre os nós do cluster.

Como Funciona:

  • O Service LoadBalancer cria automaticamente um Load Balancer externo, se estiver rodando em um provedor de nuvem que suporta Load Balancers e direciona o tráfego para o seu Service.
  • Quando você cria este Service em um ambiente como o Minikube, o Minikube simula um Load Balancer fornecendo um IP externo acessível.

Nota: Em um ambiente de desenvolvimento local como o Minikube, o tipo LoadBalancer funciona um pouco diferente, pois o Minikube não pode provisionar um Load Balancer real. Em vez disso, ele irá atribuir um IP acessível para simular um Load Balancer. Você pode acessar este serviço no Minikube usando o comando minikube service my-loadbalancer-service.

Exemplo Prático de Balanceamento de Carga com Kubernetes Service

Cenário: Suponha que você tenha uma aplicação web que está recebendo um volume crescente de tráfego. Para lidar com essa demanda, você decide escalar horizontalmente a aplicação, adicionando mais instâncias (Pods) para distribuir a carga.

Passo 1: Implementar Múltiplos Pods

Primeiro, você implementa múltiplos Pods da sua aplicação.

Cada Pod é rotulado de forma adequada para ser identificado pelo Service.

Deployment

nginx-deployment.yaml


apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3  # Número de réplicas
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx-container
          image: nginx:latest
          ports:
            - containerPort: 80

Passo 2: Criar um Service para Balanceamento de Carga

Em seguida, você cria um Service do tipo LoadBalancer ou ClusterIP, dependendo se você está exposto externamente ou apenas internamente no cluster.

Service LoadBalancer

load-balancer-service.yaml


apiVersion: v1
kind: Service
metadata:
  name: my-loadbalancer-service
spec:
  type: LoadBalancer
  ports:
    - port: 80
  selector:
    app: nginx

Aplique o yaml

kubectl apply -f load-balancer-service.yaml

Alguns comandos exploratórios:

kubectl get services

kubectl describe service my-loadbalancer-service

kubectl get endpoints my-loadbalancer-service

No Minikube, você pode usar o comando minikube service para acessar facilmente o Service do tipo LoadBalancer:

minikube service my-loadbalancer-service

Explicação:

  • apiVersion: v1: A versão da API do Kubernetes que estamos usando para definir o Service.
  • kind: Service: Indica que estamos criando um recurso do tipo Service.
  • metadata:
    • name: my-loadbalancer-service: O nome do seu Service.
  • spec:
    • type: LoadBalancer: Define o tipo do Service como LoadBalancer.
    • ports:
      • port: 80: A porta pela qual o Service será acessível. Esta porta será exposta externamente através do Load Balancer.
    • selector:
      • app: nginx: Determina que o Service irá direcionar tráfego para os Pods que têm o label app: nginx, que são gerenciados pelo seu Deployment nginx-deployment.

Como Funciona o Balanceamento de Carga:

  • Quando um Service do tipo LoadBalancer ou ClusterIP é criado e configurado com um selector que corresponde aos Pods da sua aplicação, o Kubernetes automaticamente distribui as requisições de entrada entre os Pods.
  • O Service tem um IP estável que permanece constante, enquanto os Pods podem ser adicionados ou removidos, ou podem mudar devido a atualizações e reimplantações.
  • Quando uma requisição chega ao Service, ele utiliza algoritmos de balanceamento de carga (como round-robin) para direcionar a requisição a um dos Pods disponíveis.
  • Isso garante que nenhum único Pod receba uma carga desproporcional de requisições, otimizando a utilização dos recursos e mantendo a alta disponibilidade da aplicação.
  • Em geral, são usados serviços de empresas como Google Cloud, AWS, IBM, etc. Para o gerenciamento do balanceamento de carga, e o endereço IP do cluster em produção, é atribuído pelo provedor.

Usando esse método, você pode eficientemente balancear a carga entre múltiplos Pods, garantindo que sua aplicação web possa lidar com um tráfego crescente de forma eficaz e resiliente.

ExternalName

O Service do tipo ExternalName no Kubernetes é um pouco diferente dos tipos ClusterIP, NodePort e LoadBalancer.

Em vez de direcionar tráfego para um IP interno ou expor um serviço diretamente, um Service ExternalName mapeia um nome de serviço para um nome DNS externo.

Isso é útil quando você quer referenciar um serviço que está fora do cluster Kubernetes, mas deseja acessá-lo usando um nome de serviço interno.


apiVersion: v1
kind: Service
metadata:
  name: my-external-service
spec:
  type: ExternalName
  externalName: my-external-service.exemplo.com

Explicação:

  • apiVersion: v1: versão da API Kubernetes que está sendo usada para criar este recurso. Neste caso, é a versão “v1” da API.
  • kind: Service: Isso especifica que estamos criando um recurso do tipo Service no Kubernetes.
  • metadata:
    • name: my-external-service: Aqui, definimos o nome do Service, que é como ele será identificado no Kubernetes. Neste exemplo, o nome é “my-external-service“, mas você pode escolher um nome significativo para o seu caso..
  • spec:
    • type: ExternalName: Define o tipo do Service como ExternalName.
    • ports:
      • port: 80: A porta pela qual o Service será acessível. Esta porta será exposta externamente através do Load Balancer.
    • selector:
      • app: nginx: Determina que o Service irá direcionar tráfego para os Pods que têm o label app: nginx, que são gerenciados pelo seu Deployment nginx-deployment.

Aqui está um exemplo de como você criaria um Service do tipo ExternalName:

  • Descrição: Este tipo de Service permite mapear o Service para um nome DNS externo.
  • Uso Prático: Útil quando você está migrando um serviço para o Kubernetes e esse serviço ainda precisa se comunicar com recursos fora do cluster.

No caso do Service do tipo ExternalName no Kubernetes, o campo selector não é utilizado.

Diferentemente dos tipos de Service como ClusterIP, NodePort e LoadBalancer, que direcionam o tráfego para os Pods dentro do cluster Kubernetes com base em labels (usando o selector), o ExternalName não aponta para Pods internos, em vez disso, ele cria um alias DNS que redireciona para um nome DNS externo.

external-name-service.yaml


apiVersion: v1
kind: Service
metadata:
  name: jsonplaceholder-service
spec:
  type: ExternalName
  externalName: jsonplaceholder.typicode.com

Aplique o yaml

kubectl apply -f external-name-service.yaml

Alguns comandos exploratórios:

kubectl get service jsonplaceholder-service

kubectl describe service jsonplaceholder-service

Testar a Resolução DNS do Service: Embora não seja possível “pingar” diretamente um Service do tipo ExternalName, você pode executar um teste de DNS de um Pod no cluster para confirmar se a resolução do nome está funcionando:

Primeiro, crie um Pod temporário para execução de testes, nesse caso, o Pod busybox):

kubectl run -i --tty --rm debug --image=busybox -- sh

Em seguida, dentro do shell do Pod, execute:

nslookup jsonplaceholder-service

O nslookup é uma ferramenta usada para consultar servidores de nomes de domínio (Domain Name System – DNS) para descobrir o endereço IP associado a um nome de domínio ou vice-versa.

Testar Acesso ao Serviço Externo: Ainda dentro do shell do Pod de debug, você pode usar o curl ou wget para fazer uma requisição de teste ao serviço externo usando o nome do Service ExternalName:

wget -O - http://jsonplaceholder.typicode.com/posts

Headless

Um serviço “Headless” em Kubernetes é usado quando você deseja agrupar um conjunto de Pods, mas não precisa de um único IP estável para o serviço.

Neste tipo de serviço, o DNS é configurado para retornar os endereços IP dos próprios Pods, em vez de um único IP.

Um exemplo clássico do uso de um serviço Headless é com StatefulSets.

StatefulSets são usados quando você precisa manter o estado nos Pods, como em bancos de dados.

Cada instância do banco de dados precisa ser acessível individualmente para operações de replicação, backup ou outras tarefas administrativas.

Imagine que você tenha um cluster Kubernetes com um StatefulSet para um banco de dados como o PostgreSQL. Cada instância do banco de dados (pod) precisa de sua própria identidade e armazenamento persistente.

Com um serviço Headless, cada pod pode ser acessado diretamente, permitindo operações específicas em cada instância do banco de dados.

Aqui está um exemplo de definição de um serviço Headless para Nginx:

headless-service.yaml


apiVersion: v1
kind: Service
metadata:
  name: nginx-headless
spec:
  clusterIP: None  # Define o serviço como Headless
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  • apiVersion: v1: Esta é a versão da API Kubernetes que está sendo usada para criar este recurso. Neste caso, é a versão “v1” da API.
  • kind: Service: Especifica que estamos criando um recurso do tipo Service no Kubernetes.
  • metadata:
    • name: nginx-headless: Aqui, definimos o nome do Service, que é como ele será identificado dentro do Kubernetes. Neste exemplo, o nome é “nginx-headless”.
  • spec:
    • clusterIP: None: Esta linha é crucial porque define o serviço como Headless, significando que ele não terá um IP de cluster único. Em vez disso, permitirá acesso direto aos IPs individuais dos Pods.
    • selector:
      • app: nginx: Especifica o critério de seleção para quais Pods o serviço deve direcionar o tráfego. Neste caso, ele direcionará o tráfego para os Pods que têm o label “app: nginx”.
    • ports:
      • protocol: TCP: Define o protocolo de rede usado pelo serviço. Aqui, é TCP.
      • port: 80: A porta pela qual o Service será acessível dentro do cluster. Neste caso, a porta 80 é usada, que é padrão para tráfego HTTP.
      • targetPort: 80: Especifica a porta do Pod ao qual o tráfego de rede deve ser direcionado. Aqui, também é a porta 80.

Aplique o yaml

kubectl apply -f headless-service.yaml

Alguns comandos exploratórios:

kubectl get svc nginx-headless

kubectl get pods -l app=nginx

Testa a Resolução DNS do Serviço Headless: Para mostrar como o serviço Headless resolve para os endereços IP dos Pods, você pode usar o comando kubectl run para executar um pod temporário e usar nslookup ou dig:

kubectl run -i --tty --rm debug --image=busybox --restart=Never -- nslookup nginx-headless

Deletando um Service

kubectl delete service <service-name>, remove um Service do cluster. Isso é importante para a limpeza e manutenção do cluster.

Redirecionamento de Tráfego

Redirecionar Tráfego para Diferentes Versões de um Aplicativo (Usando Labels e Selectors): Modifique a seção selector no arquivo YAML do Service para apontar para diferentes labels de Pods. Alterando os selectors de um Service, você pode redirecionar o tráfego para diferentes versões ou instâncias de um aplicativo, facilitando estratégias como blue-green deployment ou canary releases.

Antes da modificação:

apiVersion: v1
kind: Service
metadata:
  name: nginx-v1-service
spec:
  selector:
    app: nginx
    version: nginx-1.24.0
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

Esses dois serviços irão selecionar Pods com os rótulos “app: nginx” e “version: nginx-1.24.0” para o “nginx-v1-service” e “version: nginx-1.25.3” para o “nginx-v2-service“.

Modificando o Selector para Apontar para uma Versão Diferente: version: nginx-1.25.3

Depois da modificação:


apiVersion: v1
kind: Service
metadata:
  name: nginx-v2-service
spec:
  selector:
    app: nginx
    version: nginx-1.25.3
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80

Nesta versão modificada, o Service agora direcionará o tráfego para Pods que tenham os labels app: nginx e version: nginx-1.25.3.

Explicação:

  • Ao alterar o valor do label version no selector do Service, você redireciona o tráfego para uma nova versão dos Pods.
  • Isso permite implementar estratégias de atualização como blue-green ou canary, onde você tem múltiplas versões do mesmo aplicativo rodando ao mesmo tempo e controla para qual versão o tráfego é direcionado.
  • Essa abordagem oferece uma maneira segura e controlada de rolar atualizações e testar novas versões em um ambiente de produção.

Lembre-se de que, para que isso funcione, você precisa ter Pods rodando com os labels correspondentes (version: nginx-1.25.3 no exemplo acima).

Concluindo Services

Nesta aula, abordamos o fundamental componente dos Services no Kubernetes, explorando como eles facilitam a comunicação e exposição de aplicações dentro de um cluster.

Vimos como os diferentes tipos de Services – ClusterIP, NodePort, LoadBalancer e ExternalName – e suas aplicações práticas.

Utilizando o Minikube, demonstramos a criação e gestão de Services, além de praticar comandos importantes como kubectl get, describe, exec, e apply.

Vimos como Services são vitais para o balanceamento de carga e como podem ser usados para gerenciar o tráfego em estratégias de atualização de aplicações.

Esta aula foi uma imersão valiosa no uso eficiente dos Services no Kubernetes, um conhecimento essencial para a orquestração eficaz de aplicações em containers.

Por essa aula é só.

Até a próxima! 🚀

Mantenha a curiosidade e continue praticando!

Voltar para página principal do blog

Todas as aulas desse curso

Aula 06                                                 Aula 08

Meu github:

https://github.com/toticavalcanti

Novamente deixo meus link de afiliados:

Hostinger

Digital Ocean

One.com

Obrigado e bons estudos. 😉

Category: DevOps, Kubernates
About The Author
-

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>