Sobre Dimensionamento de Consumidores de Filas do OCI no Kubernetes

Este manual mostra como usar os recursos da Fila do Oracle Cloud Infrastructure (OCI) e fornece uma receita que se ajustará à maioria dos casos de uso que exigem dimensionamento dinâmico, com base na quantidade de demanda do cliente, sem incorrer em problemas de back pressure ou de gargalo no desempenho.

Você pode implantar um microsserviço no Oracle Kubernetes Engine (OKE), que processa mensagens de uma Fila do OCI e, em seguida, aproveita a profundidade da Fila para dimensionar horizontalmente as instâncias de microsserviços em execução em um cluster do OKE. O exemplo inclui um gerador de mensagens que você pode executar de qualquer lugar; por exemplo, da sua máquina local ou como parte de outro contêiner ou VM.

Este playbook também fornece código e instruções de configuração detalhadas, que podem ser encontradas no repositório Oracle-DevRel GitHub, oci-arch-queue-oke-demo (que você pode acessar na seção Explorar Mais deste playbook). Esta solução fornece todos os códigos, scripts e arquivos de configuração Java, além de etapas detalhadas sobre como criar, implantar e executar os blocos de construção. Este documento fornecerá uma visão arquitetônica e examinará os elementos-chave da implementação, incluindo a identificação das partes do código que você precisará modificar para adaptar a solução às suas próprias necessidades.

Saiba mais sobre APIs de Fila do OCI

As soluções raramente abordam processos únicos; a comunicação entre aplicações geralmente deve ser assíncrona para evitar limitar a solução pela parte mais limitante de uma solução (por exemplo, exigindo CPU, latência e assim por diante). Você pode superar essas questões estabelecendo uma comunicação em que o(s) produtor(es) e o(s) consumidor(es) não são dependentes uns dos outros. É isso que a Fila do OCI suporta com desempenho muito alto.

Embora a Fila possa amortecer os aplicativos das flutuações de demanda, quando os usuários estão envolvidos, você não quer muito tempo entre a criação da mensagem e o processamento da mensagem. Portanto, o back end precisa ser capaz de ser dimensionado dinamicamente, com base na demanda. Essa demanda é determinada pelo número de mensagens que estão na fila; mais mensagens significam mais demanda e, portanto, mais esforço de computação é necessário. Por outro lado, uma fila vazia não representa demanda e, portanto, requer recursos de backend mínimos. O escalonamento dinâmico aborda essas variações constantes.

Arquitetura

Essa arquitetura requer uma fila para as mensagens que residem fora de nossos domínios de falha visíveis, pois é um serviço totalmente gerenciado.

No OCI, você pode executar o Kubernetes com nós gerenciados pelo cliente ou com nós gerenciados pela Oracle. Este cenário usa a abordagem mais antiga dos nós clientes; portanto, você precisa de nós do serviço Compute anexados ao cluster. Esses nós são melhor distribuídos pelos domínios de falha, dentro de uma zona de disponibilidade.

Observação:

Neste manual, a geração de demanda vem da sua máquina local e, portanto, fora do ambiente OCI.

Os dois últimos elementos-chave controlam o dimensionamento. Primeiro, uma Função do OCI é chamada periodicamente e recupera detalhes da profundidade da fila. Para abstrair a forma como a profundidade da fila é verificada, um Gateway de API é usado, o que facilita a chamada de Funções do OCI.

Por fim, precisamos de serviços auxiliares, como o Vault, para armazenar credenciais de acesso à Fila, monitoramento para observação geral da saúde, etc.


A descrição de Queue-scaling-oke-arch.png é exibida a seguir
Descrição da ilustração Queue-scaling-oke-arch.png

fila-escalonamento-arranjo-oracle.zip

Os números no diagrama anterior representam esta sequência de eventos:
  1. O produtor hospedado localmente coloca mensagens na Fila do OCI.
  2. Nossa(s) instância(s) do Consumidor do OCI recupera(m) mensagens da fila. No código, a taxa de consumo é restringida usando um atraso. Isso garante que o provedor esteja gerando mais mensagens do que um único consumidor pode remover da fila. Como resultado, os mecanismos de dimensionamento funcionarão.
  3. Periodicamente, um job programado do Kubernetes suportará o KEDA para chamar a API publicada e obter o número de mensagens na fila.
  4. O Gateway de API direciona a solicitação para uma instância da Função do OCI.
  5. A Função do OCI interroga a Fila do OCI.
  6. A resposta é retornada, o que resultará no KEDA acionando um aumento ou diminuição das instâncias do microsserviço.
Além disso, (a) essa implementação também permite que o usuário, a qualquer momento, interrogue o estado da profundidade da Fila.
Essa arquitetura contém estes componentes:
  • Região

    Uma região OCI é uma área geográfica localizada que contém um ou mais data centers, denominada domínios de disponibilidade. As regiões são independentes de outras regiões, e grandes distâncias podem separá-las (entre países ou até mesmo continentes).

  • Domínios de disponibilidade

    Os domínios de disponibilidade são data centers independentes e independentes dentro de uma região. Os recursos físicos em cada domínio de disponibilidade são isolados dos recursos dos outros domínios de disponibilidade, o que oferece tolerância a falhas. Os domínios de disponibilidade não compartilham serviços de infraestrutura, como energia, refrigeração ou a rede interna do domínio de disponibilidade. Portanto, provavelmente uma falha em um domínio de disponibilidade não afetará os outros domínios de disponibilidade da região.

  • Domínio de falha

    Um domínio de falha é um agrupamento de hardware e infraestrutura dentro de um domínio de disponibilidade. Cada domínio de disponibilidade tem três domínios de falha com potência e hardware independentes. Quando você distribui recursos entre diversos domínios de falha, seus aplicativos podem tolerar falhas físicas no servidor, na manutenção do sistema e na alimentação dentro de um domínio de falha.

  • Compartimento

    Os compartimentos são partições lógicas entre regiões em uma tenancy do OCI. Use compartimentos para organizar seus recursos no Oracle Cloud, controlar o acesso aos recursos e definir cotas de uso. Para controlar o acesso aos recursos em cada compartimento, você define políticas que especificam quem pode acessar os recursos e quais ações eles podem executar.

  • Rede virtual na nuvem (VCN) e sub-redes

    Uma VCN é uma rede personalizável e definida por software que você configura em uma região OCI. Como as redes tradicionais de data center, as VCNs oferecem total controle sobre seu ambiente de rede. Uma VCN pode ter vários blocos CIDR não sobrepostos que você pode alterar após criar a VCN. Você pode segmentar uma VCN em sub-redes, que podem ter escopo em uma região ou em um domínio de disponibilidade. Cada sub-rede consiste em um intervalo ininterrupto de endereços que não se sobrepõem às outras sub-redes da VCN. Você pode alterar o tamanho de uma sub-rede após a criação. Uma sub-rede pode ser pública ou privada.

  • Instâncias do Serviço Compute

    O OCI Compute permite provisionar e gerenciar hosts de computação. Você pode iniciar instâncias de computação com configurações que atendam aos seus requisitos de recursos (CPU, memória, largura de banda de rede e armazenamento). Após criar uma instância de computação, você pode acessá-la com segurança, reiniciá-la, anexar e desanexar volumes e encerrá-la quando não precisar.

  • Funções

    O Oracle Functions é uma plataforma totalmente gerenciada, multitenant, altamente escalável, sob demanda, Functions-as-a-Service (FaaS). É alimentado pelo mecanismo de código aberto do Fn Project. As funções permitem que você implante seu código e o chame diretamente ou acione em resposta a eventos. O Oracle Functions usa contêineres Docker hospedados no OCI Registry.

  • Registro de Contêiner

    O OCI Registry é um registro gerenciado pela Oracle que permite simplificar seu workflow de desenvolvimento para produção. O registro facilita o armazenamento, o compartilhamento e o gerenciamento de artefatos de desenvolvimento, como imagens do Docker. A arquitetura altamente disponível e escalável do OCI garante que você possa implantar e gerenciar seus aplicativos de forma confiável.

  • Container Engine for Kubernetes

    O OCI Container Engine for Kubernetes é um serviço totalmente gerenciado, escalável e altamente disponível que você pode usar para implantar seus aplicativos de contêinerização na nuvem. Você especifica os recursos de computação que seus aplicativos exigem, e o Container Engine for Kubernetes os provisiona no OCI em uma tenancy existente. O Container Engine for Kubernetes usa o Kubernetes para automatizar a implantação, o dimensionamento e o gerenciamento de aplicativos de contêineres em clusters de hosts.

  • API Gateway

    O Oracle API Gateway permite que você publique APIs com pontos finais para gerenciar a visibilidade da funcionalidade, como Funções, Microsserviços e outras interfaces de aplicativos. Os pontos finais fornecem controles de segurança refinados para soluções de backend e abstraem como uma API pode ser implementada.

  • Fila

    Fila é um mecanismo de comunicação assíncrona altamente escalável sem servidor. É ideal para permitir a dissociação de serviços e a entrega de mensagens.

Considerações

Ao implantar um microsserviço no Kubernetes para processar mensagens da Fila do OCI, considere o seguinte:

  • Considerações sobre Políticas para Filas

    As políticas para controlar e configurar Filas e políticas do OCI para criar e consumir mensagens são separadas. Isso lhe dá um controle detalhado das operações disponíveis por meio das APIs. Isso significa que você precisa considerar os requisitos e as necessidades de segurança do seu aplicativo. Para produção, são recomendados controles rígidos; essa implementação utiliza definições de configuração relaxadas, o que minimiza a chance de um erro de configuração impedir que a demonstração funcione.

  • Considerações sobre limites de dimensionamento do Kubernetes

    Você precisa considerar a taxa e os limites no dimensionamento do backend. Você precisa abordar fatores, como a profundidade que a fila pode obter antes de iniciar instâncias adicionais do microsserviço. O número máximo de instâncias adicionais de um microsserviço deve estar em execução. Embora seja tentador não vincular isso, no mundo real, termos práticos, se alguém (deliberadamente ou acidentalmente) começar a inundar sua fila com mensagens erradas, você não quer absorver os custos do poder computacional adicional necessário para fugir. Você também precisa considerar a velocidade de rotação das instâncias adicionais do seu microsserviço. Reduza muito rapidamente e você encontrará seu ambiente iniciando e interrompendo constantemente os serviços. Independentemente da eficiência do microsserviço, sempre haverá um custo indireto de iniciar e interromper instâncias de serviço que, em última análise, custa.

  • Considerações para controle de dimensionamento

    O último aspecto de controlar o dimensionamento é se você deseja aplicar o dimensionamento e como controlá-lo. Esse cenário aproveita um projeto CNCF chamado KEDA (Kubernetes Event Driven Autoscaler). Além de como o dimensionamento do backend é executado, você precisa considerar como a API é chamada. Nesse caso, você pode configurar um job programado do Kubernetes (como o job é executado por um nó de trabalho, o diagrama reflete esse fluxo) para chamar a API.

Pré-requisitos

Antes de começar, você precisa preparar o ambiente atendendo aos pré-requisitos descritos aqui.

  • Para a geração de mensagens, você precisa do Java 8 ou de uma versão posterior (Java 8 instalado junto com o Apache Maven).
  • A interação com a Fila do OCI precisará de usuários e credenciais associadas para permitir acesso. Defina estas políticas:
    • Defina esta política para identificar o compartimento que você usará (compartment-name):
      allow any-user to manage queues in compartment compartment-name 
    • Para limitar os usuários a apenas ler ou gravar na Fila do OCI, crie Grupos do OCI chamados MessageConsumers e MessageProducers e aloque os usuários apropriados a esses grupos. Use as seguintes políticas:
      allow group MessageConsumers to use queues in compartment compartment-name 
      allow group MessageProducers to use queues in compartment compartment-name
    • Forneça ao cliente produtor os atributos de configuração padrão do OCI para que ele possa ser autenticado com o OCI e use a API.
    • Você precisa definir políticas para suportar o comportamento dinâmico porque novos recursos virão e vão e precisarão de acesso à Fila. Defina essas políticas criando um Grupo Dinâmico com os recursos necessários para controlar elasticamente. Como esse controle acontece no OCI, use um controlador de instâncias. Chame este grupo queue_dg. Use as seguintes instruções de política:
      ALL {instance.compartment.id='instance Compartment id (OCID)'} 
      allow dynamic-group queue_dg to use queues in compartment queue_parent_compartment 
      Onde instance Compartment id (OCID) é o compartimento que contém os nós de trabalho.

Saiba mais sobre o Java SDK

As três partes do código (produtor, consumidor e função) usam as APIs do OCI. A maneira mais fácil de interagir com as APIs é por meio do Java SDK. Os SDKs fornecidos pelo OCI fornecem uma série de funções de convicção que recuperam as informações necessárias para que você autentique e autorize as chamadas de serviços do OCI. Os SDKs adotam a variante do padrão Builder de Joshua Bloch. Você pode encontrar mais informações sobre o SDK no Java SDK. O repositório DevRel GitHub da Oracle tem mais exemplos dos SDKs usados aqui, por exemplo, em https://github.com/oracle-devrel/oci-arch-queue-demo.