Anteriormente, expliquei como criar o seu próprio cluster Kubernetes na nuvem. Agora, chegou o momento de executar a nossa primeira aplicação nesse cluster e entendermos como isso funciona no Kubernetes.

Antes, vamos entender…

Antes de tudo, vamos entender como nossa aplicação é executada no Kubernetes. Para isso, precisamos entender elementos muito importantes para esse processo: Pod, Services, Labels, Selectors e Deployment

Pods

O pod é a menor unidade do Kubernetes. É nele que são executados os containeres. Cada pod pode ter 1 ou mais containeres e cada pod possui os seus próprios recursos (rede, processamento, memória, rede, etc…). O mais comum é termos um container em cada pod, mas veremos futuramente alguns casos onde teremos mais de 1.

Os pods possuem um ciclo de vida, eles nascem e morrem com muita frequência. Por isso, não é uma prática conectarmos um pod diretamente a outro pod. Então, você me pergunta:
Ok, mas como eu faço para comunicar a minha aplicação com um banco de dados ou outro serviço ?
Utilizaremos nesse caso o service.

Services

Conforme falei anteriormente, os pods nascem e morrem com
frequência e precisamos ter um meio de comunicar os serviços entre si. Para isso, existe o service, ele cria uma abstração de comunicação entre os containeres.

Existem 4 tipos diferentes de services:

  • ClusterIP – Expõe o serviço apenas internamente no cluster.
  • NodePort – Expõe o serviço externamente do cluster utilizando qualquer ip dos nodes, porém, é mapeado através de uma porta estática (normalmente algo entre 30000 e 32767).
  • LoadBalancer – Expõe o serviço utilizando um load balance provido pelo serviço de cloud.
  • ExternalName – Mapeia o serviço para o conteúdo do campo externalName (por exemplo, xpto.fabricioveronez.net), retornando um registro CNAME com seu valor. Nenhum proxy de qualquer tipo é criado.

Utilizando o services, é possível me comunicar com um ou mais pods sem precisar saber o IP dele e sem me preocupar qual instância vou me comunicar.

Labels e Selectors

Já vimos que os services nos fornecem comunicação entre um conjunto de pods e que isso permite não nos preocupar com o nascimento e a morte dos pods. Porém, como o services identifica os pods que irá expor ? Para isso existem os labels e selectors, eles agrupam os pods para que sejam mapeados pelos services. Basicamente, são chaves e valores que são inseridos para gerar uma identificação. Por exemplo, ambiente, número da versão, etc…

Deployments

Já sabemos que precisamos do pod para executar os containeres e do service para criar um ponto de conexão com os pods. Entretanto, como faço para especificar isso tudo e fazer o Kubernetes criar isso pra mim ? Para uma aplicação ser executada, eu preciso criar um deployment.

O deployment nada mais é do que uma configuração de quais elementos minha aplicação terá e como eu espero que a minha aplicação se comporte. Ou seja, eu especifico quais imagens vou utilizar para criar os meus pods, quais pods vou utlilizar e consigo criar os meus serviços.

Assim que efetuo um deploy, o Kubernetes Master cria instâncias entre os Nodes do cluster e ao mesmo tempo, o Kubernetes Deployment Controller monitora para que a aplicação esteja sempre conforme solicitado. Isso quer dizer que, caso eu solicite 4 instâncias de conteiner e por algum motivo algum deixe de funcionar, outro é criado para substituir o mesmo.

Hora da mão na massa

Depois de toda explicação teória, vamos visualizar isso tudo na prática. Visando facilitar o entendimento, vou criar o arquivo de manifesto, que nada mais do que um arquivo YAML com os dados do deployment.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: primeiro-deployment
  labels:
    app: primeiro-deployment
spec:
  selector:
    matchLabels:
      app: primeiro-deploy
  template:
    metadata:
      labels:
        app: primeiro-deploy
    spec:
      containers:
      - name: primeiro-deploy-api
        image: fabricioveronez/cadastroprodutossimplesapi 
        ports:
        - containerPort: 80

---

kind: Service
apiVersion: v1
metadata:
  name: primeiro-service
spec:
  selector:
    app: primeiro-deploy
  ports:
  - protocol: TCP
    port: 80
  type: NodePort

No YAML de exemplo, estou criando um Deployment com o nome primeiro-deployment e uma label “app:primeiro-deployment”. Logo em seguinda, especifico que ele é formado por um pod que possui um container da imagem “fabricioveronez/cadastroprodutossimplesapi” e exponho a porta 80. Você pode encontrar mais detalhes na documentação do Kubernetes.

Na declaração do service, temos o nome “primeiro-service” e o seletor para que o service exponha todos os pods com a label “app:primeiro-deploy”. Logo em seguida, tem os dados de protocolo, acesso e o service type. Também é possível encontrar mais detalhes na documentação.

Como nosso cluster não possui um serviço de load balance como os serviços de cloud (GCP, AKS e EKS por exemplo) não é possível trabalhar com o type LoadBalancer.

Então, executo o comando para criar o meu deployment:

kubectl apply -f primeirodeploy.yaml

Agora, podemos listar os pods e os services que estão sendo executados nesse momento:

kubectl get pods -o wide
kubectl get services 

Como podemos ver, o NodePort mapeou a porta 80 do service para a porta 31754. Então, é possível acessar a nossa api utilizando o ip externo do master ou de algum node.


Caso eu execute o mesmo YAML com o service type LoadBalancer, o resultado é esse:

Como podem ver, o serviço de cloud me fornece um IP externo para acessar o service criado.

Como escalar meus pods ?

Já conseguimos criar deployment, pods e services. Porém, como escalo a quantidade de pods que o meu terá ? Muito simples, preciso configurar a quantidade de réplicas e posso fazer pelo arquivo YAML ou por linha de comando.

Segue abaixo o arquivo YAML alterado para criar 10 réplicas do meu pod:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: primeiro-deployment
  labels:
    app: primeiro-deployment
spec:
  replicas: 10
  selector:
    matchLabels:
      app: primeiro-deploy
  template:
    metadata:
      labels:
        app: primeiro-deploy
    spec:
      containers:
      - name: primeiro-deploy-api
        image: fabricioveronez/cadastroprodutossimplesapi 
        ports:
        - containerPort: 80

---

kind: Service
apiVersion: v1
metadata:
  name: primeiro-service
spec:
  selector:
    app: primeiro-deploy
  ports:
  - protocol: TCP
    port: 80
  type: NodePort

Como podem ver, basta adicionar a linha “replicas: 10” no meu arquivo e executar novamente o kubectl apply

Para alterar por linha de comando, executo o comando abaixo:

kubectl scale --replicas=10 deployment.v1.apps/primeiro-deployment

Como podem ver, foram criados os novos pods e distribuídos entre os nodes.

Com isso, conseguimos executar a nossa primeira aplicação no cluster kubernetes. No meu próximo artigo vamos entender como inserir o nginx para configurarmos domínios no nosso cluster.
Lembrando que para dúvidas ou sugestões, basta entrar em contato. Até breve !