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:
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
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?
- 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.
- Balanceamento de Carga: Os Services distribuem automaticamente o tráfego de rede entre os Pods, permitindo balanceamento de carga e alta disponibilidade.
- 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
- ClusterIP: Exposição do serviço dentro do cluster.
- NodePort: Exposição do serviço em um endereço IP estático do nó.
- LoadBalancer: Integração com Load Balancers externos providos por servidores na nuvem.
- ExternalName: Mapeia um serviço para um nome DNS externo.
- Headless: Serviço Kubernetes sem IP fixo, permite acesso direto a cada Pod individualmente.
Cluster IP
Nodeport
LoadBalancer
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 Deploymentnginx-deployment
.
- app: nginx: Seleciona os Pods com o label
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.
- type: NodePort: Define o tipo do Service como
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.
- app: nginx: Determina que o Service irá direcionar tráfego para os Pods que têm o label
- type: LoadBalancer: Define o tipo do Service como
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ó.