Abordagens de arquitetura para computação em soluções multi-inquilino

A maioria das soluções baseadas na cloud são compostas por recursos de computação de algum tipo, como camadas Web e de aplicações, processadores de lotes, tarefas agendadas e até recursos especializados, como GPUs e computação de alto desempenho (HPC). Muitas vezes, as soluções multi-inquilino beneficiam de recursos de computação partilhados, uma vez que uma maior densidade de inquilinos para a infraestrutura reduz o custo operacional e a gestão. Deve considerar os requisitos de isolamento e as implicações da infraestrutura partilhada.

Este artigo fornece orientações sobre as considerações e requisitos que são essenciais para os arquitetos de soluções considerarem ao planear um escalão de computação multi-inquilino. Isto inclui alguns padrões comuns para aplicar multi-inquilino a serviços de computação, juntamente com alguns anti-padrões a evitar.

Principais considerações e requisitos

A multitenancy e o modelo de isolamento que selecionar afetam o dimensionamento, o desempenho, a gestão de estado e a segurança dos seus recursos de computação. Nesta secção, vamos rever algumas das principais decisões que tem de tomar quando planeia uma solução de computação multi-inquilino.

Escala

Os sistemas têm de ter um desempenho adequado sob a procura em constante mudança. À medida que o número de inquilinos e a quantidade de tráfego aumentam, poderá ter de aumentar a capacidade dos seus recursos, acompanhar o número crescente de inquilinos e manter uma taxa de desempenho aceitável. Da mesma forma, quando o número de utilizadores ativos ou a quantidade de tráfego diminui, deve reduzir automaticamente a capacidade de computação para reduzir os custos, mas deve reduzir a capacidade com um impacto mínimo para os utilizadores.

Se implementar recursos dedicados para cada inquilino, terá a flexibilidade de dimensionar os recursos de cada inquilino de forma independente. Numa solução em que os recursos de computação são partilhados entre vários inquilinos, se dimensionar esses recursos, todos esses inquilinos podem utilizar a nova escala. No entanto, também sofrerão todos quando a escala for insuficiente para lidar com a carga global. Para obter mais informações, veja o problema ruidoso vizinho.

Quando cria soluções na cloud, pode optar por dimensionar horizontal ou verticalmente. Numa solução multi-inquilino com um número crescente de inquilinos, o dimensionamento horizontal proporciona normalmente uma maior flexibilidade e um limite de dimensionamento global mais elevado.

Os problemas de desempenho permanecem, muitas vezes, indetectados até que uma aplicação esteja sob carga. Pode utilizar um serviço totalmente gerido, como o Teste de Carga do Azure, para saber como a sua aplicação se comporta sob stress.

Acionadores de dimensionamento

Independentemente da abordagem que utiliza para dimensionar, normalmente tem de planear os acionadores que fazem com que os componentes sejam dimensionados. Quando tiver componentes partilhados, considere os padrões de carga de trabalho de cada inquilino que utiliza os recursos, de modo a garantir que a capacidade aprovisionada pode satisfazer a capacidade total necessária e minimizar a probabilidade de um inquilino ter o problema ruidoso vizinho. Também poderá planear a sua capacidade de dimensionamento ao considerar o número de inquilinos. Por exemplo, se medir os recursos que utiliza para servir 100 inquilinos, à medida que integra mais inquilinos, pode planear dimensionar de forma a que os seus recursos dupliquem para cada 100 inquilinos adicionais.

Estado

Os recursos de computação podem não ter estado ou podem ter monitorização de estado. Os componentes sem estado não mantêm quaisquer dados entre pedidos. Do ponto de vista da escalabilidade, os componentes sem estado são muitas vezes fáceis de aumentar horizontalmente porque pode adicionar rapidamente novos trabalhadores, instâncias ou nós e podem começar imediatamente a processar pedidos. Se a sua arquitetura o permitir, também pode reutilizar instâncias atribuídas a um inquilino e alocá-las a outro inquilino.

Os recursos com monitorização de estado podem ser ainda mais subdivididos, com base no tipo de estado que mantêm. O estado persistente são os dados que têm de ser armazenados permanentemente. Nas soluções na cloud, deve evitar armazenar um estado persistente no escalão de computação. Em vez disso, utilize serviços de armazenamento, como bases de dados ou contas de armazenamento. O estado transitório são dados armazenados temporariamente e inclui caches só de leitura na memória e o armazenamento de ficheiros temporários em discos locais.

O estado transitório é muitas vezes útil para melhorar o desempenho da camada de aplicação, ao reduzir o número de pedidos para serviços de armazenamento de back-end. Por exemplo, quando utiliza uma cache dentro da memória, poderá servir pedidos de leitura, sem ligar a uma base de dados e sem efetuar uma consulta intensiva que realizou recentemente quando serviu outro pedido.

Em aplicações sensíveis à latência, o custo da hidratação da cache pode tornar-se significativo. Uma solução multi-inquilino pode exacerbar este problema, se cada inquilino exigir a colocação em cache de dados diferentes. Para mitigar este problema, algumas soluções utilizam a afinidade de sessão para garantir que todos os pedidos para um utilizador ou inquilino específico são processados pelo mesmo nó de trabalho de computação. Embora a afinidade de sessão possa melhorar a capacidade da camada de aplicação de utilizar a respetiva cache de forma eficaz, também dificulta o dimensionamento e o balanceamento da carga de tráfego entre as funções de trabalho. Esta desvantagem tem de ser cuidadosamente considerada. Para muitas aplicações, a afinidade de sessão não é necessária.

Também é possível armazenar dados em caches externas, como Cache do Azure para Redis. As caches externas são otimizadas para a obtenção de dados de baixa latência, mantendo o estado isolado dos recursos de computação, para que possam ser dimensionadas e geridas separadamente. Em muitas soluções, as caches externas permitem-lhe melhorar o desempenho da aplicação, enquanto mantém o escalão de computação sem estado.

Importante

Evite a fuga de dados entre inquilinos, sempre que utilizar caches dentro da memória ou outros componentes que mantêm o estado. Por exemplo, considere pré-anexar um identificador de inquilino a todas as chaves de cache, para garantir que os dados são separados para cada inquilino.

Isolamento

Quando cria um escalão de computação multi-inquilino, muitas vezes tem muitas opções a considerar para o nível de isolamento entre inquilinos, incluindo a implementação de recursos de computação partilhados, para serem utilizados por todos os inquilinos, recursos de computação dedicados para cada inquilino ou algo entre estes extremos. Cada opção inclui compromissos. Para o ajudar a decidir qual a opção que melhor se adequa à sua solução, considere os seus requisitos de isolamento.

Poderá estar preocupado com o isolamento lógico dos inquilinos e com a forma de separar as responsabilidades de gestão ou as políticas que são aplicadas a cada inquilino. Em alternativa, poderá ter de implementar configurações de recursos distintas para inquilinos específicos, como implementar um SKU de máquina virtual específico para se adequar à carga de trabalho de um inquilino.

Independentemente do modelo de isolamento que selecionar, certifique-se de que verifica se os dados do inquilino permanecem devidamente isolados, mesmo quando os componentes estão indisponíveis ou com mau funcionamento. Considere utilizar o Azure Chaos Studio como parte do seu processo de teste automatizado regular para introduzir deliberadamente falhas que simulam falhas no mundo real e verificar se a sua solução não vaza dados entre inquilinos e está a funcionar corretamente, mesmo sob pressão.

Abordagens e padrões a considerar

Dimensionamento Automático

Os serviços de computação do Azure fornecem diferentes capacidades para dimensionar as cargas de trabalho. Muitos serviços de computação suportam o dimensionamento automático, o que requer que considere quando deve dimensionar e os níveis mínimos e máximos de dimensionamento. As opções específicas disponíveis para dimensionamento dependem dos serviços de computação que utiliza. Veja os seguintes serviços de exemplo:

Padrão de Selos de Implementação

Para obter mais informações sobre como o padrão de Selos de Implementação pode ser utilizado para suportar uma solução multi-inquilino, veja Descrição geral.

Padrão de Consolidação de Recursos de Computação

O padrão de Consolidação de Recursos de Computação ajuda-o a obter uma maior densidade de inquilinos para a infraestrutura de computação, ao partilhar os recursos de computação subjacentes. Ao partilhar recursos de computação, muitas vezes consegue reduzir o custo direto desses recursos. Além disso, os custos de gestão são muitas vezes mais baixos porque há menos componentes para gerir.

No entanto, a consolidação de recursos de computação aumenta a probabilidade do problema ruidoso vizinho. A carga de trabalho de qualquer inquilino pode consumir uma quantidade desproporcional da capacidade de computação disponível. Muitas vezes, pode mitigar este risco ao garantir que dimensiona a sua solução adequadamente e ao aplicar controlos como quotas e limites de API, para evitar inquilinos que consomem mais do que a sua quota justa da capacidade.

Este padrão é alcançado de diferentes formas, consoante o serviço de computação que utilizar. Veja os seguintes serviços de exemplo:

  • Serviço de Aplicações do Azure e Funções do Azure: implemente planos de Serviço de Aplicações partilhados, que representam a infraestrutura do servidor de alojamento.
  • Azure Container Apps: implementar ambientes partilhados.
  • Azure Kubernetes Service (AKS): implemente pods partilhados com uma aplicação com suporte para multi-inquilinos.
  • Máquinas virtuais: implemente um único conjunto de máquinas virtuais para todos os inquilinos utilizarem.

Recursos de computação dedicados por inquilino

Também pode implementar recursos de computação dedicados para cada inquilino. Os recursos dedicados mitigam o risco do problema ruidoso vizinho, garantindo que os recursos de computação para cada inquilino estão isolados dos outros. Também lhe permite implementar uma configuração distinta para os recursos de cada inquilino, com base nos respetivos requisitos. No entanto, os recursos dedicados normalmente têm um custo mais elevado, porque tem uma menor densidade de inquilinos para recursos.

Consoante os serviços de computação do Azure que utiliza, tem de implementar diferentes recursos dedicados da seguinte forma:

  • Serviço de Aplicações do Azure e Funções do Azure: implemente planos de Serviço de Aplicações separados para cada inquilino.
  • Azure Container Apps: implemente ambientes separados para cada inquilino.
  • Azure Kubernetes Service (AKS): implementar clusters dedicados para cada inquilino.
  • Máquinas virtuais: implemente máquinas virtuais dedicadas para cada inquilino.

Recursos de computação semi-isolados

As abordagens semi-isoladas exigem que implemente aspetos da solução numa configuração isolada, enquanto partilha os outros componentes.

Quando trabalha com Serviço de Aplicações e Funções do Azure, pode implementar aplicações distintas para cada inquilino e pode alojar as aplicações em planos de Serviço de Aplicações partilhados. Esta abordagem reduz o custo do escalão de computação, porque Serviço de Aplicações planos representam a unidade de faturação. Também lhe permite aplicar configurações e políticas distintas a cada aplicação. No entanto, esta abordagem introduz o risco do problema ruidoso vizinho.

O Azure Container Apps permite-lhe implementar várias aplicações num ambiente partilhado e, em seguida, utilizar o Dapr e outras ferramentas para configurar cada aplicação separadamente.

Azure Kubernetes Service (AKS) e Kubernetes mais amplamente, fornecem uma variedade de opções para multi-inquilino, incluindo o seguinte:

  • Espaços de nomes específicos do inquilino, para isolamento lógico de recursos específicos do inquilino, que são implementados em clusters partilhados e conjuntos de nós.
  • Nós específicos do inquilino ou conjuntos de nós num cluster partilhado.
  • Pods específicos do inquilino que podem utilizar o mesmo conjunto de nós.

O AKS também lhe permite aplicar governação ao nível do pod para mitigar o problema do Ruidoso Vizinho. Para obter mais informações, veja Melhores práticas para os programadores de aplicações gerirem recursos no Azure Kubernetes Service (AKS).

Também é importante ter em atenção os componentes partilhados num cluster do Kubernetes e como estes componentes podem ser afetados pela multi-inquilino. Por exemplo, o servidor da API do Kubernetes é um serviço partilhado que é utilizado em todo o cluster. Mesmo que forneça conjuntos de nós específicos do inquilino para isolar as cargas de trabalho da aplicação dos inquilinos, o servidor de API poderá deparar-se com a contenção de um grande número de pedidos nos inquilinos.

Antipadrões a evitar

Anti-padrão ruidoso vizinho

Sempre que implementar componentes que são partilhados entre inquilinos, o problema do Ruidoso Vizinho é um risco potencial. Confirme que inclui a governação e monitorização de recursos para mitigar o risco de a carga de trabalho de computação de um inquilino ser afetada pela atividade de outros inquilinos.

Fuga de dados entre inquilinos

As camadas de computação podem estar sujeitas a fugas de dados entre inquilinos, se não forem processadas corretamente. Geralmente, isto não é algo que tenha em consideração quando está a utilizar um serviço multi-inquilino no Azure, uma vez que a Microsoft fornece proteções na camada de plataforma. No entanto, quando desenvolver a sua própria aplicação multi-inquilino, considere se quaisquer recursos partilhados (como caches de discos locais, RAM e caches externas) podem conter dados que outro inquilino possa ver ou modificar inadvertidamente.

Antipadrão Front-end ocupado

Para evitar o antipadrão Do Front-End Ocupado, evite que o seu escalão de front-end faça muito do trabalho que pode ser processado por outros componentes ou camadas da sua arquitetura. Este antipadrão é particularmente importante quando cria front-ends partilhados para uma solução multi-inquilino, porque um front-end ocupado irá degradar a experiência para todos os inquilinos.

Em vez disso, considere utilizar o processamento assíncrono ao utilizar filas ou outros serviços de mensagens. Esta abordagem também lhe permite aplicar controlos de qualidade de serviço (QoS) para diferentes inquilinos, com base nos respetivos requisitos. Por exemplo, todos os inquilinos podem partilhar um escalão de front-end comum, mas os inquilinos que pagam por um nível de serviço superior podem ter um conjunto mais elevado de recursos dedicados para processar o trabalho a partir das respetivas mensagens de fila.

Dimensionamento inelastico ou insuficiente

As soluções multi-inquilino estão frequentemente sujeitas a padrões de escala de expansão. Os componentes partilhados são particularmente suscetíveis a este problema, porque o âmbito de expansão é maior e o impacto é maior quando tem mais inquilinos com padrões de utilização distintos.

Certifique-se de que utiliza bem a elasticidade e a escala da cloud. Considere se deve utilizar o dimensionamento horizontal ou vertical e utilizar o dimensionamento automático para processar automaticamente picos de carga. Teste a sua solução para compreender como se comporta em diferentes níveis de carga. Confirme que inclui os volumes de carga esperados na produção e o crescimento esperado. Pode utilizar um serviço totalmente gerido, como o Teste de Carga do Azure, para saber como a sua aplicação se comporta sob stress.

Antipadrão Sem Colocação em Cache

O antipadrão Sem Colocação em Cache é quando o desempenho da sua solução sofre porque a camada da aplicação solicita ou recompila repetidamente informações que podem ser reutilizadas entre pedidos. Se tiver dados que podem ser partilhados, entre inquilinos ou entre utilizadores num único inquilino, é provável que valha a pena colocar em cache para reduzir a carga na camada de back-end/base de dados.

Estado desnecessário

O corolário do antipadrão Sem Colocação em Cache é que também deve evitar armazenar um estado desnecessário no escalão de computação. Seja explícito sobre onde mantém o estado e porquê. As camadas de front-end ou aplicações com monitorização de estado podem reduzir a sua capacidade de dimensionamento. Normalmente, os escalões de computação com monitorização de estado também requerem afinidade de sessão, o que pode reduzir a sua capacidade de balancear efetivamente o tráfego, entre trabalhadores ou nós.

Considere as desvantagens de cada elemento de estado que mantém no escalão de computação e se afeta a sua capacidade de dimensionamento ou crescimento à medida que os padrões de carga de trabalho dos inquilinos mudam. Também pode armazenar o estado numa cache externa, como Cache do Azure para Redis.

Contribuidores

Este artigo é mantido pela Microsoft. Foi originalmente escrito pelos seguintes contribuidores.

Principais autores:

  • Dixit Arora | Engenheiro Sénior de Clientes, FastTrack para o Azure
  • John Downs | Engenheiro Principal de Clientes, FastTrack para o Azure

Outros contribuidores:

Passos seguintes

Reveja as orientações específicas do serviço para os seus serviços de computação: