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
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.
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.
Comments