Deploy usando Kubernetes

Kubernetes

Você pode realizar deploy do projeto usando Kubernetes. Nos passos a seguir, será mostrado como realizar deploy em um ambiente Kubernetes.

É importante salientar também que o deploy do Minerva System geralmente é feito em um ambiente K3s, o que pode impactar em algumas formas de configuração.

Introdução

Kubernetes é uma ferramenta sofisticada de orquestração de contêineres. O Minerva System é planejado para que seu deploy seja feito utilizando o Kubernetes.

Objetivo

O deploy usando Kubernetes é planejado desde o início do projeto, sendo uma das formas de estado da arte de deploy de aplicações web. Para simular este cenário, utilizamos uma instalação em um cluster local com K3s, em computadores cuja arquitetura seja x86_64 ou ARM64.

Dependências

As configurações de deploy são preparadas de forma a utilizar o próprio registry do DockerHub como fonte para as imagens previamente geradas. Assim, é necessário apenas ter acesso a um cluster com Kubernetes instalado, algo que pode ser simulado através da ferramenta K3s.

Para monitoramento e configuração, use as ferramentas a seguir:

  • Kubectl v 1.23.3 ou superior, de acordo com o compatível com seu cluster;
  • k9s versão 0.25.18 ou superior, para monitoramento (opcional);
  • kubernetes-el, pacote do editor de texto Emacs que permite monitorar um cluster Kubernetes.

A instalação local do K3s é opcional, e poderia ser substituída pelo Minikube, porém essa substituição pode ser impactante na configuração de alguns recursos, especialmente em Ingresses.

Realizando deploy de serviços

Nos passos a seguir, será mostrado como realizar deploy de cada um dos serviços e objetos k8s que fazem parte do Minerva System. Recomenda-se seguir os tópicos em ordem.

Os passos também assumem que a ferramenta kubectl esteja configurada localmente e que tenha acesso ao cluster.

Geralmente, o kubectl lê a configuração em ~/.kube/config por padrão; caso sua máquina não possua esse arquivo, verifique se consegue obter a configuração do Kubernetes para substituí-lo. No caso do K3s, esse arquivo está em /etc/rancher/k3s/k3s.yaml, e pode ser copiado, de forma paliativa, para uma outra máquina, desde que o host do cluster seja adequado na chave server.

Dependências iniciais

Para realizar o deploy do Minerva System, primeiramente precisaremos provisionar as dependências iniciais, software externos que são utilizados pelo resto do sistema.

Namespace do sistema

O namespace deve ser aplicado para que todos os objetos do sistema existam dentro do mesmo. Assim, temos uma forma de encapsular o sistema inteiro com a maior parte de suas dependências.

kubectl apply -f minerva-namespace.yml

PostgreSQL

O próximo passo é realizar o deploy do banco de dados relacional. O Minerva System usa PostgreSQL para tanto. A configuração envolve um Secret, um PersistentVolumeClaim, um Deployment, e um Service de tipo ClusterIP para garantir que o mesmo só possa ser acessado dentro do cluster.

kubectl apply -f postgresql.yml

MongoDB

Para banco de dados não-relacional, utilizaremos o MongoDB. O Minerva System usa o MongoDB principalmente para armazenamento de dados de seção do usuário. A configuração envolve um Secret, um PersistentVolumeClaim, um Deployment, e um Service de tipo ClusterIP, para que o MongoDB só possa ser acessado dentro do cluster.

kubectl apply -f mongodb.yml

Redis

Como serviço de cache, usamos um cluster Redis configurado manualmente. Esse cluster levanta um mínimo de duas instâncias do Redis, de forma que uma instância seja mestre e as demais sejam instâncias que operam como meras réplicas.

O Redis possui um ConfigMap que define um arquivo de configuração para o cluster. Além disso, temos um PersistentVolumeClaim, e o cluster definido através de um StatefulSet Temos também um Service de tipo ClusterIP para que ele possa ser acessado, e um HorizontalPodAutoscaler que adiciona ou remove réplicas sob demanda.

kubectl apply -f redis.yml

RabbitMQ

O Minerva System usa o RabbitMQ para serviços de mensageria.

O RabbitMQ é utilizado majoritariamente para abrigar mensagens de operações que possam ser despachadas de forma assíncrona, sem uma interferência direta do usuário, ou que sejam efeito colateral de outras operações no sistema.

Para provisionar o RabbitMQ, precisamos provisionar um operador de cluster para RabbitMQ, e então criar uma instância de cluster do RabbitMQ, que criará réplicas do serviço de forma eficiente.

Operador de cluster

Para realizarmos o deploy de um operador de cluster, utilizaremos o projeto RabbitMQ Cluster Operator. O arquivo para deploy do cluster está reproduzido no repositório; igualmente, sua licença pode ser encontrada em rabbitmq-cluster-operator.LICENSE.

kubectl apply -f rabbitmq-cluster-operator.yml
Instância do cluster

Agora, para criarmos uma instância do cluster RabbitMQ com três réplicas, podemos aplicar a configuração criada para o Minerva System. Isso criará um StatefulSet e um Service de tipo ClusterIP para o nosso cluster RabbitMQ.

kubectl apply -f broker-rabbitmqcluster

Configuração das dependências

Uma vez que as dependências iniciais estejam preparadas, poderemos configurar os bancos de dados, criar filas de mensagens e preparar tenants.

Configuração geral de Servers e Portas

Inicialmente, precisaremos criar dois ConfigMaps, que registram os hosts e portas dos serviços que serão criados. Essas configurações são compartilhadas pela maioria dos serviços.

kubectl apply -f servers-configmap.yml
kubectl apply -f ports-configmap.yml

Serviço de preparação

Isso pode ser feito através do módulo RUNONCE, composto de um ConfigMap, um Secret e um Job. Ao aplicar sua configuração, o Job será executado e preparará as dependências.

kubectl apply -f minerva-runonce.yml

Módulos do Minerva System

A partir desse momento, podemos começar o deploy dos módulos do Minerva System. Cada um dos módulos é basicamente uma aplicação stateless, sendo geralmente composto de um Deployment, um Service de tipo ClusterIP, e um HorizontalPodAutoscaler que criará ou destruirá réplicas dos Pods sob demanda. Alguns módulos também possuem o próprio ConfigMap para definir algumas variáveis de ambiente necessárias.

USER

O serviço gRPC de gerenciamento de usuários.

kubectl apply -f minerva-user.yml

SESSION

O serviço gRPC de gerenciamento de sessões de usuários.

kubectl apply -f minerva-session.yml

DISPATCH

O serviço de despacho de mensagens vindas do RabbitMQ.

Esse serviço não possui um Service, já que não pode ser acessado diretamente; seu único objetivo é despachar mensagens para outros serviços, de acordo com o que for requisitado através de mensagens via filas no RabbitMQ.

kubectl apply -f minerva-dispatch.yml

REST (Gateway)

O serviço REST funciona como um gateway para o back-end do Minerva System. Através desse serviço, a API poderá ser acessada, e as operações serão redirecionadas para outros serviços, de acordo com o domínio da regra de negócio em questão.

REST é o único módulo cujo Service possui um tipo diferente, sendo um tipo LoadBalancer, que fornece acesso direto à API através da porta 30000.

kubectl apply -f minerva-rest.yml

Utilitários de monitoramento

Com o deploy do sistema feito, poderemos também provisionar algumas ferramentas para ajudar no monitoramento do mesmo.

Prometheus

O Prometheus é um serviço que realiza scraping de informações expostas em endpoints de métricas. Através dele, é possível recuperar dados que podem ser posteriormente trabalhados para analisar a saúde de serviços ou até mesmo do cluster Kubernetes.

Configurando o k3s

Primeiramente, configure a sua instância do K3s, como orienta esse link; basta apenas, no seu nó master do cluster, criar o arquivo /etc/rancher/k3s/config.yaml com o conteúdo:

etcd-expose-metrics: true

Em seguida, reinicie o serviço do K3s.

Instalando o Kube-State-Metrics

O serviço kube-state-metrics provê algumas métricas coletadas através dos serviços no cluster Kubernetes. Voce pôderá instalar uma configuração padrão, como colocado neste link, clonando o repositório do projeto e aplicando essa configuração:

git clone https://github.com/kubernetes/kube-state-metrics
kubectl apply -f kube-state-metrics/examples/standard/
Provisionando o Prometheus

Como o Prometheus realiza scraping de dados nos serviços do Kubernetes e até mesmo em outros serviços, ele necessita de configurações de RBAC, o que implica na criação de objetos como ClusterRoles, ClusterRoleBindings e ServiceAccounts. Além disso, o Prometheus possui arquivos de configuração em um ConfigMap, um Deployment e um Service.

kubectl apply -f util/prometheus.yml

Mongo Express

O Mongo Express é uma ferramenta para explorar e editar o conteúdo do banco de dados não-relacional MongoDB. Esse serviço é exposto através de um Service de tipo NodePort, na porta 31085.

O Mongo Express do Minerva já vem configurado com configuração de acesso ao MongoDB. Caso sejam requisitadas credenciais para abrir o aplicativo, utilize o usuário mongo e a senha mongo.

ATENÇÃO: Caso seja necessário usar uma ferramenta mais específica, como MongoDB Compass, você poderá realizar port-forward do Deployment do MongoDB e conectar-se à porta via localhost.

kubectl apply -f util/mongoexpress.yml

PgAdmin4

O PgAdmin4 é uma ferramenta para explorar e editar o conteúdo do banco de dados relacional PostgreSQL. Esse serviço é exposto através de um Service de tipo NodePort, na porta 31084.

O PgAdmin4 do Minerva já vem configurado com dados de acesso ao PostgreSQL. Para efetuar login, use o usuário admin@admin.com e a senha admin. Para acessar o PostgreSQL, você precisará do usuário e senha padrão do mesmo também (postgres para ambos, por padrão).

ATENÇÃO: Caso seja necessário usar uma ferramenta mais específica, como DBeaver, você poderá realizar port-forward do Deployment do PostgreSQL e conectar-se à porta via localhost.

kubectl apply -f util/pgadmin.yml

Grafana

O Grafana é um serviço para criação e mostra de dashboards que operam a partir de métricas coletadas em serviços variados. No caso do Minerva, esses dados vêm principalmente do serviço Prometheus, previamente configurado.

Para o Grafana, provisionaremos alguns ConfigMaps com configuração inicial e alguns dashboards padrão para o cluster RabbitMQ. Como essa configuração inicial produz um arquivo relativamente grande, é necessário forçá-lo a ser processado de forma server-side.

As credenciais padrão do Grafana são o usuário admin e senha admin. Durante o primeiro login, você poderá alterar a senha inicial.

kubectl apply -f --server-side=true util/grafana-data.yml
kubectl apply -f util/grafana.yml

Para mais detalhes da configuração do Grafana, veja a página de Ferramentas para monitoramento externo.

Ingresses (via Traefik)

Os Ingresses são formas mais explícitas de acesso a alguns serviços do cluster, pois abrem rotas propriamente ditas que "camuflam" requisições nas mesmas e realizam forwarding para serviços específicos.

Os Ingresses atualmente preparados são compatíveis com a infraestrutura padrão do K3s, que utiliza Traefik como proxy reverso de Ingresses padrão.

Atualmente, os ingresses exportam as seguintes rotas:

  • /api, para a API do Minerva System;
  • /pgadmin, para o PgAdmin4;
  • /mongoexpress, para o Mongo Express;
  • /grafana, para o Grafana.
kubectl apply -f minerva-ingress.yml

Acessando serviços externamente

Pode ser necessário acessar, de forma externa, algum serviço que esteja no cluster, especialmente se o mesmo possuir um Service do tipo ClusterIP, que não permite acesso externo diretamente.

O Kubernetes provê algumas formas de realizar este acesso.

Acessando com Port Forward

Uma forma muito útil de acesso externo é o port forwarding, que realiza bind de uma porta da máquina local a uma porta específica de um pod específico. Também é possível referenciar um conjunto inteiro de réplicas através de um Deployment, ReplicaSet ou StatefulSet.

Para tanto, basta ter o kubectl instalado na sua máquina e a configuração correta de acesso ao cluster.

O exemplo a seguir realiza port forwarding do MongoDB para a máquina local, de forma que a porta 27017 do pod esteja acessível localmente através da porta 9050. Esse tipo de manobra será útil especialmente para acesso externo, por exemplo, au usar o MongoDB Compass.

kubectl port-forward deployment/mongodb-deployment 9050:27017

Acesso via NodePort

Esse tipo de acesso envolve acessar alguns Services que possuam um tipo NodePort ou LoadBalancer, estando expostos sob uma porta em qualquer IP do cluster. A tabela a seguir mostra uma relação dessas portas.

ServiçoPorta
API30000
PgAdmin 431084
Mongo Express31085
Redis Commander31086
Grafana31087

Monitoramento e testes

A seguir, estão listadas algumas configurações relacionadas a utilitários de monitoramento e testes do Minerva no cluster.

k9s

k9s

Uma das ferramentas possíveis de se utilizar para monitorar o cluster é o k9s.

A ferramenta utiliza uma edição modal, muito parecida com o editor Vim. Os comandos possuem um sistema de autocompletar e são também mostrados na tela. Alguns comandos interessantes de serem utilizados são:

  • :q: Sair da aplicação.
  • :po: Lista de Pods.
  • :svc: Lista de Services.
  • :dp: Lista de Deployments.
  • :ing: Lista de Ingresses.
  • :hpa: Lista de HorizontalPodAutoscalers.
  • :pvc: Lista de PersistentVolumeClaims.
  • :pv: Lista de PersistentVolumes.

Você poderá usar o k9s para visualizar logs e também para modificar algumas propriedades mais avançadas também. É possível até mesmo acessar diretamente o console dos contêineres.

kubernetes-el

kubernetes-el

O kubernetes-el é um pacote para o editor de texto Emacs que permite inspecionar um cluster Kubernetes.

Para mais informações, veja o site oficial do pacote.

Dashboard do Kubernetes

É possível acessar o Dashboard padrão do Kubernetes para realizar gerenciamento e monitoramento, porém o K3s exige configuração extra.

Para ter acesso ao Dashboard, siga as orientações no site oficial da Rancher.

Testes de Stress

Há alguns testes de stress para o Minerva System. Estes testes servem principalmente para testar os limites e o comportamento do sistema quando o mesmo estiver sob uma grande carga de operações.

Testes de spike com K6

Os testes padrão são realizados através da ferramenta K6, porém essa ferramenta demanda a extensão Faker para que funcione adequadamente. Você poderá encontrar as instruções de instalação dessa extensão no repositório da mesma.

No diretório deploy/tests/k6, você poderá executar o k6 compilado com a extensão referida. O host do cluster deverá ser informado através da variável de ambiente MINERVA_HOST. Note que o k6 assume que o host informado possua uma rota /api, então você deverá garantir que o Ingress do cluster esteja funcionando.

O exemplo a seguir mostra como executar os spike tests para stress de operações de sessão e de usuários.

# Testes de sessão
MINERVA_HOST=http://$IP_DO_CLUSTER k6 run session_spike.js

# Testes de usuários
MINERVA_HOST=http://$IP_DO_CLUSTER k6 run users_spike.js

A execução dos testes gerará um arquivo html ao final, que mostra um formato interativo para inspeção dos resultados de testes.

Testes de stress legados (via Bash)

Para realizar testes de stress com o formato legado, use o script deploy/tests/legacy/stress_test.sh.

Você poderá testar cada sistema crucial usando um comando como este:

./deploy/tests/legacy/stress_test.sh $IP_DO_CLUSTER/api user

Para maiores informações, execute o script sem argumentos e veja instruções rápidas de utilização.