Compartilhar via


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

Neste artigo, você implantará 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 está excluído dos contratos de nível de serviço do AKS, garantia limitada e suporte do Azure. Ao usar tecnologia de código aberto junto com o AKS, consulte as opções de suporte disponíveis nas comunidades e mantenedores de projetos respectivos para desenvolver um plano.

A Microsoft assume a responsabilidade por criar os pacotes de código aberto que implantamos no AKS. Essa responsabilidade inclui ter propriedade completa do processo de criação, verificação, sinalização, validação e hotfix, junto com o controle sobre os binários em imagens de contêiner. Para obter mais informações, confira Gerenciamento de vulnerabilidades para o AKS e Cobertura de suporte do AKS.

Criar segredo para o usuário do aplicativo bootstrap

  1. Gere um segredo para validar a implantação do PostgreSQL por meio de logon interativo para um usuário do aplicativo bootstrap usando o comando kubectl create secret.

Important

A Microsoft recomenda usar 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 traz 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 comando kubectl get.

    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 não é mais necessária, e ajudam a escalonar atualizações e 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 em que você depende 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 Prometheus PodMonitors

O Prometheus coleta dados do CNPG usando as regras de registro armazenadas no repositório de exemplos do GitHub CNPG. Como o PodMonitor gerenciado pelo operador está sendo descontinuado, crie e gerencie o recurso PodMonitor por conta própria, permitindo que você o adapte à sua pilha de monitoramento.

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

    helm repo add prometheus-community \
        https://prometheus-community.github.io/helm-charts
    
  2. Atualize o repositório Prometheus Community Helm e instale-o no cluster primário usando o comando helm upgrade com o sinalizador --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, portanto, 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ê criará uma credencial de identidade federada para backup do PostgreSQL para permitir que o CNPG use a identidade de carga de trabalho do AKS para autenticar no destino da conta de armazenamento para backups. O operador CNPG cria uma conta de serviço do Kubernetes com o mesmo nome do cluster nomeado usado no manifesto de implantação do Cluster CNPG.

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

    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 comando az identity federated-credential create.

    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ê implantará um cluster PostgreSQL altamente disponível usando o CRD (definição de recurso personalizado) do Cluster CNPG.

Parâmetros de CRD do cluster

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

Property Definition
imageName Aponta para a imagem de contêiner do operando CloudNativePG. Use ghcr.io/cloudnative-pg/postgresql:18-system-trixie com a integração de backup no núcleo mostrada neste guia ou alterne para 18-standard-trixie quando você adotar o plug-in do 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 Exigir zonas diferentes e nós diferentes com rótulo "workload=postgres".
resources Configura uma classe QoS (Qualidade de Serviço) de Garantia. Em um ambiente de produção, esses valores são fundamentais para maximizar o uso da VM do nó subjacente e variam de acordo com a SKU da VM do Azure usada.
probes Substitui a configuração herdada startDelay . As investigações de inicialização e preparação de streaming ajudam a garantir que as réplicas estejam íntegras antes de receber tráfego.
smartShutdownTimeout Permite que transações de execução prolongada sejam concluídas de forma suave durante as atualizações, em vez de usar atrasos de parada 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 o WAL no mesmo volume de 64 GiB, que oferece melhores camadas de taxa de transferência em discos gerenciados. Ajuste se precisar de volumes WAL separados.
postgresql.synchronous minSyncReplicas / maxSyncReplicas Substitui 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 para postgresql.conf, pg_hba.conf e pg_ident.conf. A amostra enfatiza a observabilidade e os padrões de retenção 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 a 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 da carga de trabalho do 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 taint (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 adequadamente e confirme se as políticas de dimensionamento automático do AKS estão alinhadas com sua topologia.

Parâmetros de desempenho do PostgreSQL

O desempenho do PostgreSQL depende muito dos recursos subjacentes do cluster e da carga de trabalho. A tabela a seguir fornece diretrizes básicas para um cluster de três nós em execução em nós Standard D4s v3 (memória de 16 GiB). Trate esses valores como um ponto de partida e ajuste-os depois de entender seu perfil de carga de trabalho:

Property Valor recomendado Definition
wal_compression lz4 Compacta gravações de páginas completas escritas no arquivo WAL com o método especificado
max_wal_size 6 GB Define o tamanho do WAL que dispara um ponto de verificação
checkpoint_timeout 15 minutos Define o tempo máximo entre os pontos de verificação automáticos do WAL
checkpoint_completion_target 0,9 Equilibra o trabalho de ponto de verificação na janela de ponto 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 para o disco
wal_writer_flush_after 2 MB Quantidade de WAL escrito pelo gravador WAL que dispara uma liberação
min_wal_size 2 GB Define o tamanho mínimo para reduzir o WAL para
max_slot_wal_keep_size 10 GB Limite superior para WAL à esquerda para slots de replicação de serviço
shared_buffers 4 GB Define o número de buffers de memória compartilhada 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 de memória do nó Define a quantidade máxima de memória a ser utilizada para espaços de trabalho de consultas
maintenance_work_mem 6,25% de memória do nó Define a memória máxima a ser usada para operações de manutenção
autovacuum_vacuum_cost_limit 2400 Valor do custo do vácuo disponível antes do repouso, para vácuo automático
random_page_cost 1.1 Define a estimativa de custo do planejador para uma página de disco acessada não 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 variante de "effective_io_concurrency" usada para o trabalho de manutenção

Implantando o PostgreSQL

  1. Implante o cluster PostgreSQL com o CRD do Cluster 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 do Barman Cloud mostrada posteriormente. Quando estiver pronto para alternar para o plug-in do Barman Cloud, atualize spec.imageNameghcr.io/cloudnative-pg/postgresql:18-standard-trixie e siga as diretrizes 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 comando kubectl get. O CRD do Cluster CNPG especificou três instâncias, que podem ser validadas exibindo pods em execução depois que cada instância é criada e unida para replicação. Seja paciente, pois pode levar algum tempo para as três instâncias ficarem online e ingressarem no cluster.

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

    Saída de exemplo

    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 você usar NVMe local com o Armazenamento de Contêineres do Azure e um pod permanecer no estado de inicialização com um erro de multi-anexação, o pod ainda estará procurando o volume em um nó perdido. Depois que o pod começa a ser executado, ele entra em um estado CrashLoopBackOff porque o CNPG cria uma nova réplica em um novo nó sem dados e não consegue localizar o diretório pgdata. Para resolver esse problema, destrua a instância afetada e crie uma nova. Execute o comando a seguir:

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 extração kube-prometheus-stack aos pods CNPG implantados anteriormente.

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

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

Saída de exemplo

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 você estiver usando o Azure Monitor para o Prometheus Gerenciado, precisará adicionar outro monitor de pod usando o nome do grupo personalizado. O Prometheus gerenciado não adota as CRDs (definições de recursos personalizados) 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 sejam executados ao lado dos monitores de pod que usam a CRD da comunidade. Se você não estiver usando o Managed Prometheus, ignore esta seção. Crie um novo monitor de pod:

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 do 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 – Workspace do Azure Monitor

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

Captura de tela mostrando as métricas de cluster do Postgres em um workspace do Azure Monitor no portal do Azure.

Opção B – Grafana Gerenciado

Como alternativa, após implantar o cluster Postgres e os monitores de pods, você pode criar um painel de métricas na instância do Grafana Gerenciada, criada pelo script de implantação, para visualizar as métricas exportadas para a área de trabalho do Azure Monitor. Você pode acessar o Grafana Gerenciado 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 das métricas de cluster do Postgres em uma instância do Grafana Gerenciado do Azure no portal do Azure.

Selecionar o link do 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ê 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 Prometheus Gerenciado, selecione a opção para criar um painel para abrir o editor do painel. Depois que a janela do editor for aberta, selecione a opção Adicionar visualização e selecione a opção Prometheus Gerenciado para navegar pelas 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 Prometheus Gerenciado com métricas de cluster do Postgres.

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

Captura de tela mostrando um painel do Managed Prometheus salvo no portal do Azure.

Selecione o ícone Salvar para salvar seu painel.


Próximas etapas

Contributors

A Microsoft atualiza este artigo. Os seguintes colaboradores o escreveram originalmente:

  • Ken Kilty | Diretor de TPM
  • Russell de Pina | Diretor de TPM
  • Adrian Joian | Engenheiro sênior de clientes
  • Jenny Hayes | Desenvolvedora sênior de conteúdo
  • Carol Smith | Desenvolvedora sênior de conteúdo
  • Erin Schaffer | Desenvolvedora de Conteúdo 2
  • Adam Sharif | Engenheiro de clientes 2

Reconhecimento

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