top of page
Foto do escritorRafael Natali

Kubernetes Network na Prática 2/3

Atualizado: 20 de fev.

Este é o segundo de três artigos explicando e detalhando o modelo de rede do Kubernetes com uma abordagem prática. No primeiro artigo, falei sobre a comunicação de Pod para Pod. Este artigo focará na comunicação de Pod para Serviço, e o próximo discutirá Ingress / Ingress Controllers. Estes artigos são baseados em um repositório que criei e que contém mais exemplos e conteúdo. Convido você a revisar o repositório em https://github.com/rafaelmnatali/kubernetes.



Comunicação de Pod para Serviço

Um Serviço serve como um ponto de entrada central que permite que Pods se comuniquem entre si. Por exemplo, quando um grupo de Pods (referidos como "backends") oferece funcionalidade para outros Pods (conhecidos como "frontends") dentro do seu cluster, o Serviço de backend fornecerá ao frontend uma lista de Pods de backend com os quais o frontend pode estabelecer conexões.


Existem quatro tipos de Serviços no Kubernetes:



ClusterIP

ClusterIP é o tipo padrão de Serviço. O Kubernetes atribuirá um endereço IP a partir de um pool de endereços IP que o seu cluster reservou para esse fim.

Implante um servidor web NGINX e veja como o ClusterIP funciona:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
  namespace: default
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      initContainers:
      - name: init
        image: busybox
        command: ['sh', '-c', 'echo "Welcome to the home page of host $(hostname)!" > /usr/share/nginx/html/index.html']
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html
      containers:
      - name: nginx
        image: nginx
        ports:
        - name: http-web-svc
          containerPort: 80
          protocol: TCP
        volumeMounts:
        - name: html
          mountPath: /usr/share/nginx/html
      volumes:
      - name: html
        emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  namespace: default
spec:
  selector:
    app: nginx
  ports:
  - name: http-web-svc
    protocol: TCP
    port: 80
    targetPort: http-web-svc

Liste os Serviços:

NAME            TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   
kubernetes      ClusterIP   10.96.0.1        <none>        443/TCP   
nginx-service   ClusterIP   10.110.110.219   <none>        80/TCP    

Use a imagem nicolaka/netshoot para executar os testes de rede.

kubectl run tmp-shell --rm -i --tty --image nicolaka/netshoot -- /bin/bash

Primeiro, use nslookup para consultar o nome do Serviço pelo DNS:

tmp-shell:~# nslookup nginx-service
Server:         10.96.0.10
Address:        10.96.0.10#53

Name:   nginx-service.default.svc.cluster.local
Address: 10.110.110.219

O DNS retorna o endereço IP do Serviço.


Nós podemos usar o comando curl para enviar uma requisição HTTP usando o nome do Serviço.

tmp-shell:~# curl nginx-service
Welcome to the home page of host nginx-5c7575f557-j2pzq!
tmp-shell:~# curl nginx-service
Welcome to the home page of host nginx-5c7575f557-vbglc!
tmp-shell:~# curl nginx-service
Welcome to the home page of host nginx-5c7575f557-82mx4!

O Serviço do NGINX está associado aos três Pods (como visto na coluna ENDPOINTS). No exemplo acima, o Serviço direcionou uma requisição para cada Pod.

$ kubectl get endpointslices.discovery.k8s.io                               
NAME                  ADDRESSTYPE   PORTS   ENDPOINTS                             
kubernetes            IPv4          8443    192.168.49.2                          
nginx-service-5pf9n   IPv4          80      10.244.3.46,10.244.3.47,10.244.3.48   17m

Usando o Kubeshark, é possível ter uma representação visual do tráfego de rede.

O Pod tmp-shell faz solicitações de DNS para resolver os registros A/AAAA para nginx-service.default.svc.cluster.local. Depois disso, ele envia um GET para o Serviço na porta 80 e então recebe a resposta de 10.244.3.48.


Headless Service


Headless Service é criado definindo explicitamente ClusterIP como None ao criar o Serviço. Com isso um endereço IP não é alocado e nem encaminha o tráfego. Na minha opinião, o principal caso de uso é para aplicações Stateful, onde o headless é responsável pela identidade de rede dos Pods.


Como é diferente a descoberta de IP de ClusterIP para Headless?

Implante um Serviço Headless para o nosso NGINX:

apiVersion: v1
kind: Service
metadata:
  name: nginx-headless-service
  namespace: default
spec:
  clusterIP: None 
  selector:
    app: nginx
  ports:
  - name: http-web-svc
    protocol: TCP
    port: 80
    targetPort: http-web-svc

Liste os Serviços:

NAME                     TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)  
kubernetes               ClusterIP   10.96.0.1        <none>        443/TCP   
nginx-headless-service   ClusterIP   None             <none>        80/TCP    
nginx-service            ClusterIP   10.110.110.219   <none>        80/TCP    

Use a imagem nicolaka/netshoot para executar os testes de rede.

kubectl run tmp-shell --rm -i --tty --image nicolaka/netshoot -- /bin/bash

Execute nslookup para pesquisar os dois Serviços:

tmp-shell:~# nslookup nginx-service
Server:         10.96.0.10
Address:        10.96.0.10#53

Name:   nginx-service.default.svc.cluster.local
Address: 10.110.110.219
tmp-shell:~# nslookup nginx-headless-service
Server:         10.96.0.10
Address:        10.96.0.10#53

Name:   nginx-headless-service.default.svc.cluster.local
Address: 10.244.3.46
Name:   nginx-headless-service.default.svc.cluster.local
Address: 10.244.3.47
Name:   nginx-headless-service.default.svc.cluster.local
Address: 10.244.3.48

No primeiro caso, o ClusterIP retorna seu próprio endereço IP. O Serviço Headless retorna o endereço IP de cada Pod.


Resumo


Neste artigo, experimentei com dois tipos de Kubernetes Services - ClusterIP, que fornece um endereço IP e balanceamento de carga, e headless Service, que não oferece balanceamento de carga e retorna uma lista de todos os Pods associados. O artigo explora como você pode se conectar às suas aplicações usando esses dois Services.

Um Service é o método preferido para expor uma aplicação de rede em execução como um ou mais Pods em seu cluster. Uma das principais vantagens dos Services do Kubernetes é que você não precisa modificar sua aplicação para usufruir de suas vantagens.

Na terceira e última parte desta série, discutirei sobre Ingress e Ingress Controllers.


Referências


10 visualizações0 comentário

Commentaires


bottom of page