Partilhar via


Implantar um banco de dados PostgreSQL altamente disponível no Serviço Kubernetes do Azure (AKS)

Neste artigo, você implanta um banco de dados PostgreSQL altamente disponível no AKS.

Important

O software de código aberto é mencionado em toda a documentação e amostras do AKS. O software que você implanta é excluído dos contratos de nível de serviço do AKS, da garantia limitada e do suporte do Azure. Ao usar a tecnologia de código aberto ao lado do AKS, consulte as opções de suporte disponíveis nas respetivas comunidades e mantenedores do projeto para desenvolver um plano.

A Microsoft assume a responsabilidade pela criação dos pacotes de código aberto que implantamos no AKS. Essa responsabilidade inclui ter a propriedade completa do processo de compilação, digitalização, assinatura, validação e correção rápida, juntamente com o controlo dos binários nas imagens de contentor. Para obter mais informações, consulte Gestão de vulnerabilidades para AKS e Cobertura de suporte AKS.

Criar segredo para usuário da aplicação de bootstrap

  1. Gere um segredo para validar a implantação do PostgreSQL por login interativo de um utilizador da aplicação bootstrap usando o comando kubectl create secret.

Important

A Microsoft recomenda que você use o fluxo de autenticação mais seguro disponível. O fluxo de autenticação descrito neste procedimento requer um alto grau de confiança no aplicativo e acarreta riscos que não estão presentes em outros fluxos. Você só deve usar esse fluxo quando outros fluxos mais seguros, como identidades gerenciadas, não forem viáveis.

PG_DATABASE_APPUSER_SECRET=$(echo -n | openssl rand -base64 16)

kubectl create secret generic db-user-pass \
    --from-literal=username=app \
     --from-literal=password="${PG_DATABASE_APPUSER_SECRET}" \
     --namespace $PG_NAMESPACE \
     --context $AKS_PRIMARY_CLUSTER_NAME
  1. Valide se o segredo foi criado com êxito usando o kubectl get comando.

    kubectl get secret db-user-pass --namespace $PG_NAMESPACE --context $AKS_PRIMARY_CLUSTER_NAME
    

Definir variáveis de ambiente para o cluster PostgreSQL

  • Implante um ConfigMap para configurar o operador CNPG usando o comando a seguir kubectl apply . Esses valores substituem a alternância herdada ENABLE_AZURE_PVC_UPDATES, que já não é necessária, e ajudam a gerir a atualização e a acelerar as reconexões de réplicas. Antes de colocar essa configuração em produção, valide se todas as configurações existentes DRAIN_TAINTS nas quais você confia permanecem compatíveis com seu ambiente do Azure.

    cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME -n $PG_NAMESPACE -f -
    apiVersion: v1
    kind: ConfigMap
    metadata:
        name: cnpg-controller-manager-config
    data:
        CLUSTERS_ROLLOUT_DELAY: '120'
        STANDBY_TCP_USER_TIMEOUT: '10'
    EOF
    

Instalar o PodMonitors do Prometheus

Prometheus coleta dados do CNPG usando as regras de gravação armazenadas no repositório de amostras do GitHub CNPG. Como o PodMonitor gerido pelo operador está a ser preterido, crie e gerencie o recurso do PodMonitor você mesmo para poder adaptá-lo à sua pilha de monitorização.

  1. Adicione o repositório Prometheus Community Helm usando o helm repo add comando.

    helm repo add prometheus-community \
        https://prometheus-community.github.io/helm-charts
    
  2. Atualize o repositório Helm da comunidade Prometheus e instale-o no cluster primário utilizando o comando helm upgrade com o parâmetro --install.

    helm upgrade --install \
        --namespace $PG_NAMESPACE \
        -f https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/main/docs/src/samples/monitoring/kube-stack-config.yaml \
        prometheus-community \
        prometheus-community/kube-prometheus-stack \
        --kube-context=$AKS_PRIMARY_CLUSTER_NAME
    
  3. Crie um PodMonitor para o cluster. A equipe do CNPG está substituindo o PodMonitor gerenciado pelo operador, então agora você o gerencia diretamente:

    cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACE -f -
    apiVersion: monitoring.coreos.com/v1
    kind: PodMonitor
    metadata:
      name: $PG_PRIMARY_CLUSTER_NAME
      namespace: ${PG_NAMESPACE}
      labels:
        cnpg.io/cluster: ${PG_PRIMARY_CLUSTER_NAME}
    spec:
      selector:
        matchLabels:
          cnpg.io/cluster: ${PG_PRIMARY_CLUSTER_NAME}
      podMetricsEndpoints:
        - port: metrics
    EOF
    

Criar uma credencial federada

Nesta seção, você cria uma credencial de identidade federada para backup do PostgreSQL para permitir que o CNPG use a identidade de carga de trabalho AKS para autenticar no destino da conta de armazenamento para backups. O operador CNPG cria uma conta de serviço Kubernetes com o mesmo nome do cluster usado no manifesto de implantação do cluster CNPG.

  1. Obtenha a URL do emissor OIDC do cluster usando o az aks show comando.

    export AKS_PRIMARY_CLUSTER_OIDC_ISSUER="$(az aks show \
        --name $AKS_PRIMARY_CLUSTER_NAME \
        --resource-group $RESOURCE_GROUP_NAME \
        --query "oidcIssuerProfile.issuerUrl" \
        --output tsv)"
    
  2. Crie uma credencial de identidade federada usando o az identity federated-credential create comando.

    az identity federated-credential create \
        --name $AKS_PRIMARY_CLUSTER_FED_CREDENTIAL_NAME \
        --identity-name $AKS_UAMI_CLUSTER_IDENTITY_NAME \
        --resource-group $RESOURCE_GROUP_NAME \
        --issuer "${AKS_PRIMARY_CLUSTER_OIDC_ISSUER}" \
        --subject system:serviceaccount:"${PG_NAMESPACE}":"${PG_PRIMARY_CLUSTER_NAME}" \
        --audience api://AzureADTokenExchange
    

Implantar um cluster PostgreSQL altamente disponível

Nesta seção, você implanta um cluster PostgreSQL altamente disponível usando a definição de recurso personalizada (CRD) do Cluster CNPG.

Parâmetros CRD do cluster

A tabela a seguir descreve as principais propriedades definidas no manifesto de implantação do YAML para o CRD do Cluster:

Property Definition
imageName Aponta para a imagem do contêiner do operando CloudNativePG. Use ghcr.io/cloudnative-pg/postgresql:18-system-trixie com a integração de backup in-core mostrada neste guia, ou mude para 18-standard-trixie ao adotar o plug-in Barman Cloud.
inheritedMetadata Específico para o operador CNPG. O operador CNPG aplica os metadados a todos os objetos relacionados ao cluster.
annotations Inclui o rótulo DNS necessário ao expor os pontos de extremidade do cluster e habilita alpha.cnpg.io/failoverQuorum para failover baseado em quorum.
labels: azure.workload.identity/use: "true" Indica que o AKS deve injetar dependências de identidade de carga de trabalho nos pods que hospedam as instâncias de cluster do PostgreSQL.
topologySpreadConstraints Requer zonas diferentes e nós diferentes com rótulo "workload=postgres".
resources Configura uma classe de Qualidade de Serviço (QoS) de Garantido. Em um ambiente de produção, esses valores são fundamentais para maximizar o uso da VM do nó subjacente e variam com base na SKU da VM do Azure usada.
probes Substitui a configuração herdada startDelay . As sondas de inicialização e preparação de streaming ajudam a garantir que as réplicas estejam íntegras antes de atender ao tráfego.
smartShutdownTimeout Permite que transações de longa duração sejam concluídas de forma suave durante as atualizações, em vez de usar atrasos de interrupção agressivos.
bootstrap Específico para o operador CNPG. Inicializa com um banco de dados de aplicativo vazio.
storage Define as configurações de PersistentVolume para o banco de dados. Com os discos gerenciados do Azure, a sintaxe simplificada mantém os dados e a WAL no mesmo volume de 64 GiB, o que oferece melhores camadas de taxa de transferência em discos gerenciados. Ajuste caso precise de volumes WAL separados.
postgresql.synchronous Substitui minSyncReplicas/maxSyncReplicas e permite especificar o comportamento de replicação síncrona usando o esquema mais recente.
postgresql.parameters Específico para o operador CNPG. Mapeia as configurações de postgresql.conf, pg_hba.confe pg_ident.conf. O exemplo enfatiza a capacidade de observação e os padrões de retenção do WAL que se adequam ao cenário de identidade de carga de trabalho do AKS, mas devem ser ajustados conforme a carga de trabalho.
serviceAccountTemplate Contém o modelo necessário para gerar as contas de serviço e mapeia a credencial de identidade federada do AKS para o UAMI para habilitar a autenticação de identidade de carga de trabalho do AKS dos pods que hospedam as instâncias do PostgreSQL para recursos externos do Azure.
barmanObjectStore Específico para o operador CNPG. Configura o conjunto de ferramentas barman-cloud usando a identidade de carga de trabalho AKS para autenticação no repositório de objetos do Armazenamento de Blobs do Azure.

Para isolar ainda mais as cargas de trabalho do PostgreSQL, você pode adicionar uma mancha (por exemplo, node-role.kubernetes.io/postgres=:NoSchedule) aos nós do plano de dados e substituir a amostra nodeSelector/tolerations pelos valores recomendados pelo CloudNativePG. Se você adotar essa abordagem, rotule os nós de acordo e confirme se as políticas do autoscaler do AKS estão alinhadas com sua topologia.

Parâmetros de desempenho do PostgreSQL

O desempenho do PostgreSQL depende muito dos recursos subjacentes e da carga de trabalho do cluster. A tabela a seguir fornece orientações básicas para um cluster de três nós utilizando nós D4s v3 padrão, com 16 GiB de memória. Trate esses valores como um ponto de partida e ajuste-os assim que entender seu perfil de carga de trabalho:

Property Valor recomendado Definition
wal_compression lz4 Compacta gravações de página inteira gravadas em arquivo WAL com o método especificado
max_wal_size 6 GB Define o tamanho da WAL que aciona um ponto de verificação
checkpoint_timeout 15 minutos Define o tempo máximo entre os pontos de verificação WAL automáticos
checkpoint_completion_target 0,9 Equilibra o trabalho do ponto de verificação na janela de verificação
checkpoint_flush_after 2 MB Número de páginas após as quais as gravações executadas anteriormente são liberadas no disco
wal_writer_flush_after 2 MB Quantidade de WAL escrita pelo gravador WAL que dispara um flush
min_wal_size 2 GB Define o tamanho mínimo para reduzir a WAL para
max_slot_wal_keep_size 10 GB Limite superior para WAL remanescente para slots de replicação
shared_buffers 4 GB Define o número de buffers de memória partilhada usados pelo servidor (25% da memória do nó neste exemplo)
effective_cache_size 12 GB Define a suposição do planejador sobre o tamanho total dos caches de dados
work_mem 1/256 da memória do nó Define a memória máxima a ser usada para espaços de trabalho de consulta
maintenance_work_mem 6,25% de memória de nó Define a memória máxima a ser usada para operações de manutenção
autovacuum_vacuum_cost_limit 2400 Montante do custo de vácuo disponível antes de suspender temporariamente, para autovácuo
random_page_cost 1.1 Define a estimativa do planejador do custo de uma página de disco não obtida sequencialmente
effective_io_concurrency 64 Define quantas solicitações simultâneas o subsistema de disco pode lidar com eficiência
maintenance_io_concurrency 64 Uma variação de "effective_io_concurrency" que é utilizada para tarefas de manutenção

Implantando o PostgreSQL

  1. Desdobre o cluster PostgreSQL com o Cluster CRD usando o comando kubectl apply.

    cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME -n $PG_NAMESPACE -v 9 -f -
    apiVersion: postgresql.cnpg.io/v1
    kind: Cluster
    metadata:
      name: $PG_PRIMARY_CLUSTER_NAME
      annotations:
        alpha.cnpg.io/failoverQuorum: "true"
    spec:
      imageName: ghcr.io/cloudnative-pg/postgresql:18-system-trixie
      inheritedMetadata:
        annotations:
          service.beta.kubernetes.io/azure-dns-label-name: $AKS_PRIMARY_CLUSTER_PG_DNSPREFIX
        labels:
          azure.workload.identity/use: "true"
    
      instances: 3
      smartShutdownTimeout: 30
    
      probes:
        startup:
          type: streaming
          maximumLag: 32Mi
          periodSeconds: 5
          timeoutSeconds: 3
          failureThreshold: 120
        readiness:
          type: streaming
          maximumLag: 0
          periodSeconds: 10
          failureThreshold: 6
    
      topologySpreadConstraints:
      - maxSkew: 1
        topologyKey: topology.kubernetes.io/zone
        whenUnsatisfiable: DoNotSchedule
        labelSelector:
          matchLabels:
            cnpg.io/cluster: $PG_PRIMARY_CLUSTER_NAME
    
      affinity:
        nodeSelector:
          workload: postgres
    
      resources:
        requests:
          memory: '8Gi'
          cpu: 2
        limits:
          memory: '8Gi'
          cpu: 2
    
      bootstrap:
        initdb:
          database: appdb
          owner: app
          secret:
            name: db-user-pass
          dataChecksums: true
    
      storage:
        storageClass: $POSTGRES_STORAGE_CLASS
        size: 64Gi
    
      postgresql:
        synchronous:
          method: any
          number: 1
        parameters:
          wal_compression: lz4
          max_wal_size: 6GB
          max_slot_wal_keep_size: 10GB
          checkpoint_timeout: 15min
          checkpoint_completion_target: '0.9'
          checkpoint_flush_after: 2MB
          wal_writer_flush_after: 2MB
          min_wal_size: 2GB
          shared_buffers: 4GB
          effective_cache_size: 12GB
          work_mem: 62MB
          maintenance_work_mem: 1GB
          autovacuum_vacuum_cost_limit: "2400"
          random_page_cost: "1.1"
          effective_io_concurrency: "64"
          maintenance_io_concurrency: "64"
          log_checkpoints: 'on'
          log_lock_waits: 'on'
          log_min_duration_statement: '1000'
          log_statement: 'ddl'
          log_temp_files: '1024'
          log_autovacuum_min_duration: '1s'
          pg_stat_statements.max: '10000'
          pg_stat_statements.track: 'all'
          hot_standby_feedback: 'on'
        pg_hba:
          - host all all all scram-sha-256
    
      serviceAccountTemplate:
        metadata:
          annotations:
            azure.workload.identity/client-id: "$AKS_UAMI_WORKLOAD_CLIENTID"
          labels:
            azure.workload.identity/use: "true"
    
      backup:
        barmanObjectStore:
          destinationPath: "https://${PG_PRIMARY_STORAGE_ACCOUNT_NAME}.blob.core.windows.net/backups"
          azureCredentials:
            inheritFromAzureAD: true
        retentionPolicy: '7d'
    EOF
    

Observação

O manifesto de amostra usa a imagem ghcr.io/cloudnative-pg/postgresql:18-system-trixie porque funciona com a integração incorporada do Barman Cloud mostrada mais adiante. Quando estiver pronto para mudar para o plug-in Barman Cloud, atualize spec.imageNameghcr.io/cloudnative-pg/postgresql:18-standard-trixie e siga as orientações de configuração do plug-in antes de reimplantar o cluster.

Important

A entrada de exemplo pg_hba permite acesso não-TLS. Se você mantiver essa configuração, documente as implicações de segurança para sua equipe e prefira conexões criptografadas sempre que possível.

  1. Valide se o cluster PostgreSQL primário foi criado com êxito usando o kubectl get comando. O CRD do Cluster CNPG especificou três instâncias, que podem ser validadas exibindo pods em execução assim que cada instância é criada e unida para replicação. Seja paciente, pois pode levar algum tempo para que as três instâncias fiquem online e se juntem ao cluster.

    kubectl get pods --context $AKS_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACE -l cnpg.io/cluster=$PG_PRIMARY_CLUSTER_NAME
    

    Exemplo de saída

    NAME                         READY   STATUS    RESTARTS   AGE
    pg-primary-cnpg-r8c7unrw-1   1/1     Running   0          4m25s
    pg-primary-cnpg-r8c7unrw-2   1/1     Running   0          3m33s
    pg-primary-cnpg-r8c7unrw-3   1/1     Running   0          2m49s
    

Important

Se utilizar o NVMe local com o Armazenamento de Contentores do Azure e um pod permanecer no estado de inicialização com um erro de multi-anexação, o pod ainda estará à procura do volume em um nó perdido. Depois de o pod começar a ser executado, ele entra num CrashLoopBackOff estado porque o CNPG cria uma nova réplica num novo nó, sem dados, e não consegue encontrar o pgdata diretório. Para resolver esse problema, destrua a instância afetada e abra uma nova. Execute o seguinte comando:

kubectl cnpg destroy [cnpg-cluster-name] [instance-number]  

Validar se o Prometheus PodMonitor está em execução

O PodMonitor criado manualmente vincula a configuração de scrape do kube-prometheus-stack aos pods CNPG implantados anteriormente.

Valide se o PodMonitor está em execução usando o kubectl get comando.

kubectl --namespace $PG_NAMESPACE \
    --context $AKS_PRIMARY_CLUSTER_NAME \
    get podmonitors.monitoring.coreos.com \
    $PG_PRIMARY_CLUSTER_NAME \
    --output yaml

Exemplo de saída

kind: PodMonitor
metadata:
  labels:
    cnpg.io/cluster: pg-primary-cnpg-r8c7unrw
  name: pg-primary-cnpg-r8c7unrw
  namespace: cnpg-database
spec:
  podMetricsEndpoints:
  - port: metrics
  selector:
    matchLabels:
      cnpg.io/cluster: pg-primary-cnpg-r8c7unrw

Se estiveres a usar o Azure Monitor for Managed Prometheus, precisarás de adicionar outro monitor de pod usando o nome personalizado do grupo. O Managed Prometheus não pega as definições de recursos personalizados (CRDs) da comunidade Prometheus. Além do nome do grupo, os CRDs são os mesmos. Esse design permite que os monitores de pod para o Managed Prometheus funcionem ao lado dos monitores de pod que utilizam o CRD da comunidade. Se não estiver a utilizar o Managed Prometheus, pode ignorar esta secção. Crie um novo pod de monitorização:

cat <<EOF | kubectl apply --context $AKS_PRIMARY_CLUSTER_NAME --namespace $PG_NAMESPACE -f -
apiVersion: azmonitoring.coreos.com/v1
kind: PodMonitor
metadata:
  name: cnpg-cluster-metrics-managed-prometheus
  namespace: ${PG_NAMESPACE}
  labels:
    azure.workload.identity/use: "true"
    cnpg.io/cluster: ${PG_PRIMARY_CLUSTER_NAME}
spec:
  selector:
    matchLabels:
      azure.workload.identity/use: "true"
      cnpg.io/cluster: ${PG_PRIMARY_CLUSTER_NAME}
  podMetricsEndpoints:
    - port: metrics
EOF

Verifique se o monitor pod foi criado (observe a diferença no nome do grupo).

kubectl --namespace $PG_NAMESPACE \
    --context $AKS_PRIMARY_CLUSTER_NAME \
    get podmonitors.azmonitoring.coreos.com \
    -l cnpg.io/cluster=$PG_PRIMARY_CLUSTER_NAME \
    -o yaml

Opção A - Espaço de trabalho do Azure Monitor

Depois de implantar o cluster Postgres e o monitor de pod, você pode exibir as métricas usando o portal do Azure em um espaço de trabalho do Azure Monitor.

Captura de tela mostrando métricas de cluster do Postgres em um espaço de trabalho do Azure Monitor no portal do Azure.

Opção B - Grafana Gerenciado

Como alternativa, depois de implantar o cluster Postgres e os monitores pod, você pode criar um painel de métricas na instância do Grafana Gerenciado criada pelo script de implantação para visualizar as métricas exportadas para o espaço de trabalho do Azure Monitor. Você pode acessar o Managed Grafana por meio do portal do Azure. Navegue até a instância do Managed Grafana criada pelo script de implantação e selecione o link Endpoint conforme mostrado aqui:

Captura de tela Métricas de cluster do Postgres em uma instância do Azure Managed Grafana no portal do Azure.

Selecionar o link Endpoint abre uma nova janela do navegador onde você pode criar painéis na instância do Managed Grafana. Seguindo as instruções para configurar uma fonte de dados do Azure Monitor, você pode adicionar visualizações para criar um painel de métricas do cluster Postgres. Depois de configurar a conexão da fonte de dados, no menu principal, selecione a opção Fontes de dados. Você deverá ver um conjunto de opções de fonte de dados para a conexão, conforme mostrado aqui:

Captura de tela mostrando as opções de fonte de dados do Azure Monitor no portal do Azure.

Na opção Managed Prometheus, selecione a opção para criar um painel para abrir o editor de painel. Depois que a janela do editor abrir, selecione a opção Adicionar visualização e, em seguida, selecione a opção Managed Prometheus para procurar as métricas do cluster Postgres. Depois de selecionar a métrica que deseja visualizar, selecione o botão Executar consultas para buscar os dados para a visualização, conforme mostrado aqui:

Captura de tela mostrando um painel do Managed Prometheus com métricas de cluster do Postgres.

Selecione o ícone Salvar para adicionar o painel ao seu painel. Você pode adicionar outros painéis selecionando o botão Adicionar no editor de painel e repetindo esse processo para visualizar outras métricas. Adicionando as visualizações de métricas, você deve ter algo parecido com isto:

Captura de ecrã a mostrar um dashboard do Managed Prometheus guardado no portal do Azure.

Selecione o ícone Salvar para salvar seu painel.


Próximos passos

Contributors

A Microsoft mantém este artigo. Os seguintes colaboradores escreveram-no originalmente:

  • Ken Kilty - Brasil | Principal TPM
  • Russell de Pina - Brasil | Principal TPM
  • Adrian Joian | Engenheiro de Clientes Senior
  • Jenny Hayes | Desenvolvedora de Conteúdo Sénior
  • Carol Smith | Desenvolvedora Sénior de Conteúdos
  • Erin Schaffer | Desenvolvedora de Conteúdo 2
  • Adam Sharif | Engenheiro de Clientes 2

Agradecimento

Esta documentação foi desenvolvida em conjunto com o EnterpriseDB, os mantenedores do operador CloudNativePG. Agradecemos a Gabriele Bartolini por ter revisado rascunhos anteriores deste documento e oferecido melhorias técnicas.