Visão geral da implantação de carga de trabalho de VM

Este guia aborda o contexto conceitual necessário para implantar uma carga de trabalho baseada em máquina virtual (VM) em um cluster com isolamento físico do Google Distributed Cloud (GDC) em bare metal usando um ambiente de execução de VM. A carga de trabalho neste guia é uma plataforma de sistema de emissão de tíquetes de amostra disponível em hardware no local.

Arquitetura

Hierarquia de recursos

No GDC, você implanta os componentes que compõem o sistema de emissão de tíquetes em uma organização de locatário dedicada para a equipe de operações, idêntica a qualquer organização de cliente. Uma organização é um conjunto de clusters, recursos de infraestrutura e cargas de trabalho de aplicativos administrados em conjunto. Cada organização em uma instância do GDC usa um conjunto dedicado de servidores, o que garante um isolamento forte entre os locatários. Para mais informações sobre infraestrutura, consulte Projetar limites de acesso.

Hierarquia de recursos do GDC com isolamento físico

Além disso, você implanta e gerencia os recursos do sistema de tíquetes juntos em um projeto, o que fornece isolamento lógico em uma organização usando políticas e aplicação de software. Os recursos em um projeto servem para acoplar componentes que precisam permanecer juntos durante o ciclo de vida.

O sistema de tíquetes segue uma arquitetura de três camadas que usa um balanceador de carga para direcionar o tráfego entre os servidores de aplicativos que se conectam a um servidor de banco de dados que armazena dados persistentes.

diagrama de uma arquitetura de três camadas

Essa arquitetura permite escalonabilidade e manutenção, já que cada camada pode ser desenvolvida e mantida de forma independente. Ele também oferece uma separação clara de preocupações, o que simplifica a depuração e a solução de problemas. Ao encapsular esses níveis em um projeto do GDC, é possível implantar e gerenciar componentes juntos, por exemplo, os servidores de aplicativos e de banco de dados.

Rede

A execução do sistema de emissão de tíquetes em um ambiente de produção requer a implantação de dois ou mais servidores de aplicativos para alcançar alta disponibilidade em caso de falha de nó. Combinada com um balanceador de carga, essa topologia também permite distribuir a carga entre várias máquinas para escalonar o aplicativo horizontalmente. A plataforma nativa do Kubernetes do GDC usa o Cloud Service Mesh para rotear o tráfego com segurança para os servidores de aplicativos que compõem o sistema de emissão de ingressos.

O Cloud Service Mesh é uma implementação do Google baseada no projeto de código aberto que gerencia, observa e protege serviços. Os seguintes recursos do Cloud Service Mesh são usados para hospedar o sistema de emissão de tíquetes no GDC:

  • Balanceamento de carga: o Cloud Service Mesh separa o fluxo de tráfego do escalonamento da infraestrutura, abrindo muitos recursos de gerenciamento de tráfego, incluindo o roteamento dinâmico de solicitações. O sistema de emissão de ingressos exige conexões de cliente persistentes. Por isso, ativamos as sessões fixas usando DestinationRules para configurar o comportamento de roteamento de tráfego.
  • Término de TLS: o Cloud Service Mesh expõe gateways de entrada usando certificados TLS e fornece autenticação de transporte no cluster por meio de mTLS (Mutual Transport Layer Security) sem precisar alterar nenhum código do aplicativo.

  • Recuperação de falhas: o Cloud Service Mesh oferece vários recursos essenciais de recuperação de falhas, incluindo tempos limite, disjuntores, verificações de integridade ativas e novas tentativas vinculadas.

No cluster do Kubernetes, usamos objetos Service padrão como uma maneira abstrata de expor os servidores de aplicativos e de banco de dados à rede. Os serviços oferecem uma maneira conveniente de segmentar instâncias de destino usando um seletor e fornecem resolução de nome no cluster usando um servidor DNS que reconhece o cluster.

apiVersion: v1
kind: Service
metadata:
  name: http-ingress
spec:
  selector:
    app.kubernetes.io/component: application-server
  ports:
  - name: http
    port: 80
---
apiVersion: v1
kind: Service
metadata:
  name: database-ingress
spec:
  selector:
    app.kubernetes.io/component: database-server
  ports:
  - name: mysql
    port: 3306

Computação

O sistema de emissão de ingressos recomenda o uso de bare metal ou máquinas virtuais para hospedar instalações no local, e usamos o gerenciamento de máquinas virtuais (VMs) do GDC Virtual para implantar os servidores de aplicativos e de banco de dados como cargas de trabalho de VM. A definição de recursos do Kubernetes nos permitiu especificar VirtualMachine e VirtualMachineDisk para adaptar os recursos às nossas necessidades para os diferentes tipos de servidores. VirtualMachineExternalAccess permite configurar a transferência de dados de entrada e saída da VM.

apiVersion: virtualmachine.gdc.goog/v1
kind: VirtualMachineDisk
metadata:
  name: vm1-boot-disk
spec:
  size: 100G
  source:
    image:
      name: ts-ticketing-system-app-server-2023-08-18-203258
      namespace: vm-system
---
apiVersion: virtualmachine.gdc.goog/v1
kind: VirtualMachine
metadata:
  labels:
    app.kubernetes.io/component: application-server
  name: vm1
  namespace: support
spec:
  compute:
    vcpus: 8
    memory: 12G
  disks:
  - boot: true
    virtualMachineDiskRef:
      name: vm1-boot-disk

---
apiVersion: virtualmachine.gdc.goog/v1
kind: VirtualMachineExternalAccess
metadata:
  name: vm1
  namespace: support
spec:
  enabled: true
  ports:
   - name: ssh
     protocol: TCP
     port: 22

Para a imagem do SO convidado, criamos uma imagem personalizada para atender aos nossos requisitos de conformidade e segurança. É possível se conectar a instâncias de VM em execução por SSH usando o VirtualMachineAccessRequest, que permite limitar a capacidade de se conectar a VMs pelo RBAC do Kubernetes e evitar a necessidade de criar contas de usuário locais nas imagens personalizadas. A solicitação de acesso também define um time to live (TTL) que permite que as solicitações de acesso baseadas em tempo gerenciem as VMs que expiram automaticamente.

Automação

Como um resultado importante para este projeto, criamos uma abordagem para instalar instâncias do sistema de emissão de tíquetes de maneira repetível, que pode oferecer suporte a uma automação extensiva e reduzir o desvio de configuração entre as implantações.

Fluxo de lançamentos

A personalização das imagens do servidor de banco de dados e do aplicativo começa com uma imagem base do sistema operacional, modificando-a conforme necessário para instalar as dependências necessárias para cada imagem do servidor. Selecionamos uma imagem do SO de base para a adoção generalizada de sistemas de emissão de tíquetes de hospedagem em instalações no local. Essa imagem do SO de base também oferece recursos de proteção de segurança necessários para atender aos Guias de implementação técnica de segurança (STIGs, na sigla em inglês) necessários para fornecer uma imagem em conformidade com os controles NIST-800-53.

Nosso pipeline de integração contínua (CI) usou o seguinte fluxo de trabalho para personalizar imagens de servidor de aplicativos e de banco de dados:

Fluxo de trabalho de integração contínua

Quando os desenvolvedores fazem mudanças nos scripts de personalização ou nas dependências de imagem, acionamos um fluxo de trabalho automatizado nas nossas ferramentas de CI para gerar um novo conjunto de imagens que são agrupadas com as versões do GDC. Como parte da criação de imagens, também atualizamos as dependências do SO (yum update) e reduzimos a densidade da imagem com compactação para diminuir o tamanho necessário para transferir imagens para ambientes de clientes.

Ciclo de vida do desenvolvimento de software

O ciclo de vida de desenvolvimento de software (SDLC, na sigla em inglês) é um processo que ajuda as organizações a planejar, criar, testar e implantar software. Ao seguir um SDLC bem definido, as organizações garantem que o software seja desenvolvido de maneira consistente e repetível e identificam possíveis problemas logo no início. Além de criar imagens no pipeline de integração contínua (CI), também definimos ambientes para desenvolver e preparar versões de pré-lançamento do sistema de emissão de passagens para testes e controle de qualidade.

A implantação de uma instância separada do sistema de tíquetes por projeto do GDC permitiu testar as mudanças de forma isolada, sem afetar as instâncias atuais na mesma instância do GDC. Usamos a API ResourceManager para criar e remover projetos de forma declarativa usando recursos do Kubernetes.

apiVersion: resourcemanager.gdc.goog/v1
kind: Project
metadata:
  name: ticketing-system-dev
---
apiVersion: resourcemanager.gdc.goog/v1
kind: Project
metadata:
  name: ticketing-system-qa
---
apiVersion: resourcemanager.gdc.goog/v1
kind: Project
metadata:
  name: ticketing-system-staging

Combinado com o empacotamento de gráficos e o gerenciamento de infraestrutura, como máquinas virtuais como código, os desenvolvedores podem iterar rapidamente fazendo alterações e testando novos recursos junto com as instâncias de produção. A API declarativa também permite que frameworks de execução de testes automatizados realizem testes de regressão regulares e verifiquem os recursos atuais.

Operabilidade

Operabilidade é a facilidade com que um sistema pode ser operado e mantido. É uma consideração importante no design de qualquer aplicativo de software. O monitoramento eficaz contribui para a operabilidade porque permite que os problemas sejam identificados e resolvidos antes de terem um impacto significativo no sistema. O monitoramento também pode ser usado para identificar oportunidades de melhoria e estabelecer um valor de referência para os objetivos de nível de serviço (SLO).

Monitoramento

Integramos o sistema de tíquetes à infraestrutura de observabilidade do GDC, incluindo geração de registros e métricas. Para métricas, expomos endpoints HTTP de cada VM que permitem que o aplicativo extraia pontos de dados produzidos pelos servidores de aplicativos e de banco de dados. Esses endpoints incluem métricas do sistema coletadas usando o exportador de nós do aplicativo e métricas específicas do aplicativo.

Com os endpoints expostos em cada VM, configuramos o comportamento de sondagem do aplicativo usando o recurso personalizado MonitoringTarget para definir o intervalo de raspagem e anotar as métricas.

apiVersion: monitoring.gdc.goog/v1
kind: MonitoringTarget
metadata:
  name: database-monitor
spec:
  podMetricsEndpoints:
    path:
      value: /metrics
    port:
      annotation: application.io/dbMetrics
    scrapeInterval: 60s

Para a geração de registros, instalamos e configuramos um processador de registros e métricas em cada VM para acompanhar os registros relevantes e enviar dados de registro para a ferramenta de geração de registros, em que os dados são indexados e consultados pela instância de monitoramento. Os registros de auditoria são encaminhados para um endpoint especial configurado com retenção estendida para conformidade. Os aplicativos baseados em contêiner podem usar o recurso personalizado LoggingTarget e AuditLoggingTarget para instruir o pipeline de geração de registros a coletar registros de serviços específicos no projeto.

Com base nos dados disponíveis nos processadores de geração de registros e monitoramento, criamos alertas usando o recurso personalizado MonitoringRule, que nos permite gerenciar essa configuração como código no nosso pacote de gráficos. O uso de uma API declarativa para definir alertas e painéis também permite armazenar essa configuração no repositório de código e seguir os mesmos processos de revisão de código e integração contínua que usamos para qualquer outra alteração de código.

Modos de falha

Os testes iniciais revelaram vários modos de falha relacionados a recursos que nos ajudaram a priorizar quais métricas e alertas adicionar primeiro. Começamos monitorando o uso elevado de memória e disco, já que a configuração incorreta do banco de dados inicialmente levou as tabelas de buffer a consumir toda a memória disponível, e o excesso de registros preencheu o disco de volume permanente anexado. Depois de ajustar o tamanho do buffer de armazenamento e implementar uma estratégia de rotação de registros, introduzimos alertas que são executados se as VMs se aproximarem do uso de memória ou disco alto.

apiVersion: monitoring.gdc.goog/v1
kind: MonitoringRule
metadata:
  name: monitoring-rule
spec:
  interval: 60s
  limit: 0
  alertRules:
  - alert: vm1_disk_usage
    expr:
      (node_filesystem_size_bytes{container_name="compute"} -
      node_filesystem_avail_bytes{container_name="compute"}) * 100 /
      node_filesystem_size_bytes{container_name="compute"} > 90
    labels:
      severity: error
      code: TS-R0001
      resource: vm1
    annotations:
      message: "vm1 disk usage above 90% utilization"

Depois de verificar a estabilidade do sistema, mudamos o foco para os modos de falha do aplicativo no sistema de tíquetes. Como a depuração de problemas no aplicativo geralmente exigia o uso do Secure Shell (SSH) em cada VM do servidor de aplicativos para verificar os registros do sistema de emissão de tíquetes, configuramos um aplicativo para encaminhar esses registros à ferramenta de geração de registros para criar na pilha de observabilidade do GDC e consultar todos os registros operacionais do sistema de emissão de tíquetes na instância de monitoramento.

A geração de registros centralizada também nos permitiu consultar registros de várias VMs ao mesmo tempo, consolidando nossa visualização de cada componente do sistema.

Backups

Os backups são importantes para a operabilidade de um sistema de software porque permitem que ele seja restaurado em caso de falha. O GDC oferece backup e restauração de VMs por meio de recursos do Kubernetes. Criar um recurso personalizado VirtualMachineBackupRequest com um recurso personalizado VirtualMachineBackupPlanTemplate permite fazer backup do volume permanente anexado a cada VM no repositório de objetos, em que os backups podem ser retidos de acordo com um conjunto de políticas de retenção.

apiVersion: virtualmachine.gdc.goog/v1
kind: VirtualMachineBackupPlanTemplate
metadata:
  name: vm-backup-plan
spec:
  backupRepository: "backup-repository"
---
apiVersion: virtualmachine.gdc.goog/v1
kind: VirtualMachineBackupRequest
metadata:
  name: "db-vm-backup"
spec:
  virtualMachineBackupPlanTemplate: vm-backup-plan
  virtualMachine: db1
  virtualMachineBackupName: db-vm-backup

Da mesma forma, restaurar o estado de uma VM usando um backup envolve criar um recurso personalizado VirtualMachineRestoreRequest para restaurar os servidores de aplicativos e de banco de dados sem modificar o código ou a configuração de nenhum dos serviços.

apiVersion: virtualmachine.gdc.goog/v1
kind: VirtualMachineRestoreRequest
metadata:
  name: vm-restore-1
spec:
  virtualMachineBackup: db-vm-backup
  restoreName: restore1
  restoredResourceName: db1

Upgrades

Para dar suporte ao ciclo de vida do software do sistema de emissão de tíquetes e às dependências dele, identificamos três tipos de upgrades de software, cada um tratado individualmente para minimizar o tempo de inatividade e a interrupção do serviço:

  1. Upgrades do SO.
  2. Upgrades de plataforma, como patches e versões principais.
  3. Atualizações de configuração.

Para upgrades de SO, criamos e lançamos continuamente novas imagens de VM para servidores de aplicativos e de banco de dados que são distribuídos com cada versão do GDC. Essas imagens contêm correções para vulnerabilidades de segurança e atualizações para o sistema operacional subjacente.

Os upgrades da plataforma do sistema de tíquetes exigem a aplicação de atualizações às imagens de VM atuais. Portanto, não podemos contar com uma infraestrutura imutável para realizar correções e atualizações de versões de lançamento principais. Para upgrades de plataforma, testamos e verificamos a versão de patch ou principal nos nossos ambientes de desenvolvimento e de preparo antes de lançar um pacote de upgrade independente com a versão do GDC.

Por fim, as atualizações de configuração são aplicadas sem inatividade usando as APIs do sistema de tíquetes para conjuntos de atualização e outros dados do usuário. Desenvolvemos e testamos atualizações de configuração nos nossos ambientes de desenvolvimento e de preparo antes de empacotar vários conjuntos de atualização durante o processo de lançamento do GDC.

Integrações

Provedores de identidade

Para oferecer aos clientes uma jornada integrada e permitir que as organizações integrem os usuários, integramos o sistema de tíquetes a vários provedores de identidade disponíveis no GDC. Normalmente, os clientes corporativos e do setor público têm os próprios provedores de identidade bem gerenciados para conceder e revogar direitos aos funcionários. Devido aos requisitos de conformidade e à facilidade de governança de identidade e governança de acesso, esses clientes querem usar os provedores de identidade atuais como a fonte de verdade para gerenciar o acesso dos funcionários ao sistema de tíquetes.

O sistema de tíquetes é compatível com os provedores SAML 2.0 e OIDC por meio do módulo de provedor de várias identidades, que pré-ativamos na imagem de VM do servidor de aplicativos. Os clientes se autenticam pelo provedor de identidade da organização, que cria usuários e atribui papéis automaticamente no sistema de tíquetes.

A saída para servidores de provedores de identidade é permitida pelo recurso personalizado ProjectNetworkPolicy, que limita se os serviços externos podem ser acessados por uma organização no GDC. Essas políticas permitem controlar de forma declarativa quais endpoints o sistema de emissão de tíquetes pode acessar na rede.

Ingestão de alertas

Além de permitir que os usuários façam login para criar casos de suporte manualmente, também criamos incidentes no sistema de tíquetes em resposta a alertas do sistema.

Para conseguir essa integração, personalizamos um webhook de código aberto do Kubernetes para receber alertas do aplicativo e gerenciar o ciclo de vida dos incidentes usando o endpoint de API do sistema de tíquetes exposto pelo Cloud Service Mesh.

As chaves de API são armazenadas usando o armazenamento de secrets do GDC, apoiado por secrets do Kubernetes controlados pelo controle de acesso baseado em função (RBAC). Outras configurações, como endpoints de API e campos de personalização de incidentes, são gerenciadas pelo armazenamento de chave-valor do ConfigMap do Kubernetes.

E-mail

O sistema de tíquetes oferece integrações de servidor de e-mail para que os clientes recebam suporte por e-mail. Os fluxos de trabalho automatizados convertem os e-mails recebidos de clientes em casos de suporte e enviam respostas automáticas com links para os casos. Assim, nossa equipe de suporte pode gerenciar melhor a caixa de entrada, rastrear e resolver sistematicamente as solicitações por e-mail e oferecer um melhor atendimento ao cliente.

apiVersion: networking.gdc.goog/v1
kind: ProjectNetworkPolicy
metadata:
  name: allow-ingress-traffic-from-ticketing-system
spec:
  subject:
    subjectType: UserWorkload
  ingress:
  - from:
    - projects:
        matchNames:
        - ticketing-system

Expor o e-mail como um serviço do Kubernetes também fornece descoberta de serviços e resolução de nomes de domínio, além de separar ainda mais o back-end do servidor de e-mail de clientes como o sistema de tíquetes.

Compliance

Registro de auditoria

Os registros de auditoria contribuem para a postura de compliance, fornecendo uma maneira de rastrear e monitorar o uso do software e fornecer um registro da atividade do sistema. Os registros de auditoria registram tentativas de acesso de usuários não autorizados, rastreiam o uso da API e identificam possíveis riscos de segurança. Os registros de auditoria atendem aos requisitos de conformidade, como os impostos pela Lei de Portabilidade e Responsabilidade de Seguros de Saúde (HIPAA), pelo Padrão de Segurança de Dados do Setor de Cartões de Pagamento (PCI DSS) e pela Lei Sarbanes-Oxley (SOX).

O GDC fornece um sistema para registrar atividades administrativas e acessos na plataforma e reter esses registros por um período configurável. A implantação do recurso personalizado AuditLoggingTarget configura o pipeline de geração de registros para coletar registros de auditoria do aplicativo.

Para o sistema de tíquetes, configuramos destinos de registro de auditoria para os eventos de auditoria do sistema coletados e os eventos específicos do aplicativo gerados pelo registro de auditoria de segurança do sistema de tíquetes. Os dois tipos de registros são enviados para uma instância centralizada do Loki, em que podemos escrever consultas e visualizar painéis na instância de monitoramento.

Controle de acesso

O controle de acesso é o processo de conceder ou negar acesso a recursos com base na identidade do usuário ou do processo que solicita o acesso. Isso ajuda a proteger os dados contra acesso não autorizado e garante que apenas usuários autorizados possam fazer mudanças no sistema. No GDC, usamos o RBAC do Kubernetes para declarar políticas e aplicar autorização aos recursos do sistema que consistem no aplicativo do sistema de emissão de tíquetes.

Definir um ProjectRole no GDC permite conceder acesso granular aos recursos do Kubernetes usando um papel de autorização predefinido.

apiVersion: resourcemanager.gdc.goog/v1
kind: ProjectRole
metadata:
  name: ticketing-system-admin
  labels:
    resourcemanager.gdc.goog/rbac-selector: system
spec:
  rules:
  - apiGroups:
    - ""
    resources:
    - configmaps
    - events
    - pods/log
    - services
    verbs:
    - get
    - list

Recuperação de desastres

Réplica do banco de dados

Para atender aos requisitos de recuperação de desastres (DR), implantamos o sistema de emissão de tíquetes em uma configuração primária-secundária em várias instâncias do GDC. Nesse modo, as solicitações para o sistema de emissão de tíquetes normalmente são roteadas para o site principal, enquanto o site secundário replica continuamente o registro binário do banco de dados. No caso de um evento de failover, o site secundário é promovido para se tornar o novo site principal, e as solicitações são roteadas para o novo site principal.

Usamos os recursos de replicação de banco de dados para configurar os servidores de banco de dados principal e de réplica por instância do GDC com base nos parâmetros definidos.

Para ativar a replicação em uma instância que está em execução há mais tempo do que o período de armazenamento do registro binário, podemos restaurar o banco de dados de réplica usando o backup do banco de dados para iniciar a replicação do banco de dados principal.

No modo principal, os servidores de aplicativos e o banco de dados funcionam da mesma forma que hoje, mas o banco de dados principal é configurado para permitir a replicação. Exemplo:

  1. Ative o registro binário.

  2. Defina o ID do servidor.

  3. Criar uma conta de usuário de replicação.

  4. criar um backup.

No modo de réplica, os servidores de aplicativos vão desativar o serviço da Web de emissão de bilhetes para evitar a conexão direta com o banco de dados de réplica. O banco de dados de réplica precisa ser configurado para iniciar a replicação do banco de dados principal, por exemplo:

  1. Defina o ID do servidor.

  2. Configure as credenciais do usuário de replicação e os detalhes da conexão principal, como o host e a porta.

  3. A restauração do backup retoma a posição do registro binário.

A replicação de banco de dados requer conectividade de rede para que a réplica se conecte ao banco de dados principal para iniciar a replicação. Para expor o endpoint do banco de dados principal para replicação, usamos o Cloud Service Mesh para criar uma malha de serviço de entrada que oferece suporte ao término de TLS na malha de serviço, de maneira semelhante à forma como lidamos com a transferência de dados HTTPS para o aplicativo da Web do sistema de emissão de ingressos.