Resolver problemas do operador AlloyDB Omni no Kubernetes

Selecione uma versão da documentação:

Nesta página, mostramos como resolver problemas com o operador do AlloyDB Omni no Kubernetes.

Coletar informações de depuração

Estas seções descrevem como coletar registros e configurações para depuração.

Extrair registros de pods de operador

Para buscar registros dos pods do operador, execute os seguintes comandos:

kubectl logs deployments/fleet-controller-manager -c manager -n alloydb-omni-system
kubectl logs deployments/local-controller-manager -c manager -n alloydb-omni-system

Extrair registros do pod do banco de dados

Para buscar os registros do pod de banco de dados, execute os seguintes comandos:

kubectl logs al-<id-instance-name>-0 -n db
kubectl logs -l alloydbomni.internal.dbadmin.goog/dbcluster=dbcluster-name -c database -n db

Os registros a seguir são exemplos de verificações de integridade de banco de dados bem-sucedidas:

I1106 16:17:28.826188      30 gateway.go:166] "DatabaseHealthCheck: handling request" log_name="agent" project_ns="dbc-bugbash" dbcluster="dbcluster-sample"
I1106 16:17:28.826295      30 gateway.go:184] "DatabaseHealthCheck: request handled successfully" log_name="agent" project_ns="dbc-bugbash" dbcluster="dbcluster-s
ample"
I1106 16:17:34.810447      30 gateway.go:166] "DatabaseHealthCheck: handling request" log_name="agent" project_ns="dbc-bugbash" dbcluster="dbcluster-sample"
I1106 16:17:34.834844      30 gateway.go:184] "DatabaseHealthCheck: request handled successfully" log_name="agent" project_ns="dbc-bugbash" dbcluster="dbcluster-s
ample"
I1106 16:17:38.825843      30 gateway.go:166] "DatabaseHealthCheck: handling request" log_name="agent" project_ns="dbc-bugbash" dbcluster="dbcluster-sample"
I1106 16:17:38.825959      30 gateway.go:184] "DatabaseHealthCheck: request handled successfully" log_name="agent" project_ns="dbc-bugbash" dbcluster="dbcluster-s
ample"

Extraia o postgresql.log

Para buscar o postgresql.log, execute o seguinte comando:

kubectl exec -it al-id-instance-name-0 -n db -c database -- cat /obs/diagnostic/postgresql.log

Extrair o arquivo YAML DBInstance

Para buscar o arquivo YAML DBInstance, execute o seguinte comando:

kubectl get dbclusters.a <dbcluster-name> -n db -o yaml

Buscar configurações e registros para cenários de alta disponibilidade

Para buscar configurações e registros específicos de cenários de alta disponibilidade (HA), execute os seguintes comandos:

kubectl get replicationconfig -n <namespace>
kubectl get deletestandbyjobs.alloydbomni.internal -n <namespace> -o yaml
kubectl get createstandbyjobs.alloydbomni.internal -n <namespace> -o yaml
kubectl get failovers.alloydbomni.dbadmin.goog -n <namespace> -o yaml

Buscar status do pod e do STS

Para buscar os status do pod e do StatefulSet (STS), execute os seguintes comandos:

kubectl describe pod -n <namespace> <pod-name>
kubectl describe statefulset -n <namespace> al-<id-instance-name>

Identificar erros

Essas seções descrevem como identificar erros.

Procurar status e códigos de erro

Para identificar o código de erro, verifique o arquivo YAML do DBCluster em "status". Consulte a documentação de códigos de erro para mais informações.

Para buscar o arquivo YAML do DBCluster, execute o seguinte comando:

kubectl get dbclusters.a <dbcluster-name> -n <dbcluster-namespace> -o yaml

Procure por criticalIncidents. Esta seção contém o código do erro e um stack trace.

Confira alguns exemplos de criticalIncidents:

status:
    certificateReference:
      certificateKey: ca.crt
      secretRef:
        name: dbs-al-cert-dr-mce
        namespace: dr
    conditions:
    -   lastTransitionTime: "2024-10-07T22:46:03Z"
    ...
    criticalIncidents:
    -   code: DBSE0304
      createTime: "2024-10-03T11:50:54Z"
      message: 'Healthcheck: Health check invalid result.'
      resource:
        component: healthcheck
        location:
          group: alloydbomni.internal.dbadmin.goog
          kind: Instance
          name: bc0f-dr-mce
          namespace: dr
          version: v1
      stackTrace:
      -   component: healthcheck
        message: 'DBSE0304: Healthcheck: Health check invalid result. rpc error: code
          = Code(10304) desc = DBSE0304: Healthcheck: Health check invalid result.
          dbdaemon/healthCheck: invalid timestamp read back from the healthcheck table.
          Lag is 384837.296269 seconds, wanted 35 seconds'

Também é possível extrair campos específicos em formato JSON para conferir o status:

kubectl get dbcluster.${DBTYPE:?} -n "${PROJECT:?}" "${DBCLUSTER:?}" -o json -o jsonpath='{.status.criticalIncidents}' | jq

O resultado será assim:

[
  {
    "code": "DBSE0085",
    "createTime": "2024-03-14T05:41:37Z",
    "message": "Platform: Pod is unschedulable.",
    "resource": {
      "component": "provisioning",
      "location": {
        "group": "alloydb.internal.dbadmin.goog",
        "kind": "Instance",
        "name": "b55f-testdbcluster",
        "namespace": "dbs-system",
        "version": "v1"
      }
    },
    "stackTrace": [
      {
        "component": "provisioning",
        "message": "DBSE0085: Platform: Pod is unschedulable. 0/16 nodes are available: pod has unbound immediate PersistentVolumeClaims. preemption: 0/16 nodes are available: 16 No preemption victims found for incoming pod..: Pod is unschedulable"
      }
    ]
  }
]

Se a mensagem de erro se referir ao pod do banco de dados, verifique as instâncias e os recursos do pod no mesmo namespace:

kubectl get instances.a dbcluster_name -n dbcluster_namespace -o yaml
kubectl get pods -l alloydbomni.internal.dbadmin.goog/dbcluster=dbcluster_name -l alloydbomni.internal.dbadmin.goog/task-type=database -n dbcluster_namespace

Depurar problemas de memória

Essas seções descrevem como depurar problemas de memória.

Executar e fazer um heapdump

Ative esse recurso apenas para resolver problemas. Não se esqueça de desligar depois.

Para fazer um heapdump, siga estas etapas:

  1. Modifique a implantação do operador no namespace alloydb-omni-system com os nomes fleet-controller-manager e local-controller-manager.
  2. Adicione o argumento a seguir ao pod --pprof-address=:8642 ou a qualquer outra porta disponível.
  3. Aguarde a reinicialização do pod do controlador.
  4. Encaminhe a porta anterior. Exemplo:

    kubectl port-forward -n alloydb-omni-system fleet-controller-manager-pod-name 8642:8642
    
  5. Em outro terminal, execute go tool pprof http://localhost:8642/debug/pprof/heap. Mude a porta para corresponder à anterior se você não usar 8642.

  6. Conecte-se ao endereço e execute comandos de solução de problemas. Por exemplo, top.

  7. Depois de concluir a solução de problemas, desfaça a etapa 1 removendo o argumento e aguardando a reinicialização do pod.

Determinar o número de recursos que o operador está monitorando

Para entender os recursos em uso, execute os seguintes comandos:

kubectl get backuprepositories -A  | wc -l
kubectl get failovers -A  | wc -l
kubectl get instancebackupplans -A  | wc -l
kubectl get instancebackups -A  | wc -l
kubectl get instancerestores -A  | wc -l
kubectl get instances -A  | wc -l
kubectl get instanceswitchovers -A  | wc -l
kubectl get lrojobs -A  | wc -l
kubectl get replicationconfigs -A  | wc -l
kubectl get sidecars -A  | wc -l
kubectl get deployments -A  | wc -l
kubectl get statefulsets -A  | wc -l
kubectl get certificates.cert-manager.io -A  | wc -l
kubectl get issuers.cert-manager.io -A  | wc -l
kubectl get configmaps -A  | wc -l
kubectl get persistentvolumeclaims -A  | wc -l
kubectl get persistentvolumes -A  | wc -l
kubectl get pods -A  | wc -l
kubectl get secrets -A  | wc -l
kubectl get services -A  | wc -l
kubectl get storageclasses.storage.k8s.io -A  | wc -l

Por exemplo, se o número de secrets for alto, isso poderá causar um erro de falta de memória (OOM).

kubectl get secrets -A | wc -l

Depuração avançada de HA

Esta seção faz referência a recursos que são implementações internas. Elas estão sujeitas a mudanças a qualquer momento e não têm compromissos de compatibilidade com versões anteriores. Aplique correções manuais apenas a problemas em bancos de dados que não sejam de produção. Essas etapas podem tornar o banco de dados irrecuperável.

A configuração de alta disponibilidade do AlloyDB Omni tem três fases:

  1. Configure o principal para receber uma conexão do modo de espera.
  2. Inicialize o modo de espera e conecte-o ao primário.
  3. Defina as configurações principais para tornar a conexão síncrona.

A etapa 2 geralmente é a mais lenta. Dependendo do tamanho do banco de dados, isso pode levar várias horas.

Cada instância de replicação precisa ter um replicationconfig anexado. Por exemplo: bash ❯ k get replicationconfigs.alloydbomni.internal.dbadmin.goog NAME PARENT TYPE ROLE READY HEALTHY 9f47-dbcluster-sample--7576-dbcluster-sample 9f47-dbcluster-sample Physical Upstream True True ds-7576-dbcluster-sample 7576-dbcluster-sample Physical Downstream True True

Neste exemplo:

  • A instância 9f47-dbcluster-sample está configurada como um upstream físico.
  • A instância 7576-dbcluster-sample está configurada como um downstream físico.

A especificação da configuração de replicação indica as configurações pretendidas, enquanto o status reflete o estado real lido do banco de dados. Se houver uma incompatibilidade entre a especificação e o status, o controlador ainda vai tentar aplicar a mudança ou haverá algum erro que impeça a aplicação. Isso seria refletido nos campos de status.

Jobs em espera

Há dois conjuntos de jobs internos que rastreiam o fluxo de trabalho de um standby:

  • createstandbyjobs.alloydbomni.internal.dbadmin.goog
  • deletestandbyjobs.alloydbomni.internal.dbadmin.goog

Se a configuração parecer travada, confira os jobs relacionados ao cluster de banco de dados (DBC). O job pode ter mensagens de erro que explicam em qual estado a configuração está. Os jobs são limpos automaticamente algum tempo depois de serem concluídos. Portanto, talvez você não veja nenhum job se não houver nenhum em andamento.

k get createstandbyjob

O resultado será assim:

apiVersion: alloydbomni.dbadmin.gdc.goog/v1
  kind: CreateStandbyJob
  metadata:
    creationTimestamp: "2024-11-05T03:34:26Z"
    finalizers:
    -   createstandbyjob.dbadmin.goog/finalizer
    generation: 1804
    labels:
      dbs.internal.dbadmin.goog/dbc: foo-ha-alloydb1-clone1
    name: foo-ha-alloydb1-clone1--ac00-foo-ha-alloydb1-clone1--6036-foo-ha-alloydb1-clone1-1730777666
    namespace: db
    resourceVersion: "11819071"
    uid: 1f24cedf-b326-422f-9405-c96c8720cd90
  spec:
    attempt: 3
    cleanup: false
    currentStep: SetupSynchronous
    currentStepTime: "2024-11-05T03:45:31Z"
    metadata:
      dbc: foo-ha-alloydb1-clone1
      primaryInstance: ac00-foo-ha-alloydb1-clone1
      retryError: 'etcdserver: leader changed'
      standbyInstance: 6036-foo-ha-alloydb1-clone1
    requeueTime: "2024-11-05T18:33:03Z"
    startTime: "2024-11-05T03:36:56Z"

Verificação principal

Primeiro, verifique se a instância principal está configurada corretamente. É necessário ter um perfil de replicação para cada standby. Se isSynchronous for verdadeiro na especificação e no status, a configuração estará concluída. Se isSynchronous for falso na especificação e no status, significa que ainda não chegou à etapa 3. Confira os jobs em espera para saber se há jobs em execução e se eles têm mensagens de erro.

  replication:
    profiles:
    -   isActive: true
      isSynchronous: true
      name: ha:4c82-dbcluster-sample::d85d-dbcluster-sample
      password:
        name: ha-rep-pw-dbcluster-sample
        namespace: default
      passwordResourceVersion: "896080"
      role: Upstream
      type: Physical
      username: alloydbreplica

Verifique se a anotação disableHealthcheck é falsa. Ele deve ser desativado apenas durante um failover ou uma alternância.

apiVersion: alloydbomni.internal.dbadmin.goog/v1
kind: Instance
metadata:
  annotations:
    dbs.internal.dbadmin.goog/consecutiveHealthcheckFailures: "0"
    dbs.internal.dbadmin.goog/disableHealthcheck: "false"
    dr-secondary: "false"
    forceReconcile: "1730414498"

Consultas

Para verificar se os recursos no pod do banco de dados estão configurados corretamente, faça login no banco de dados como o usuário administrador alloydbadmin. Em seguida, execute estas consultas:

Slot de replicação

alloydbadmin=# select * from pg_replication_slots;
-[ RECORD 1 ]-------+---------------------------------------------
slot_name           | d85d_dbcluster_sample
plugin              |
slot_type           | physical
datoid              |
database            |
temporary           | f
active              | t
active_pid          | 250
xmin                | 16318
catalog_xmin        |
restart_lsn         | 0/CA657F0
confirmed_flush_lsn |
wal_status          | reserved
safe_wal_size       |
two_phase           | f

Um bom estado é a presença de um slot de replicação com o mesmo nome da instância standby. A ausência de um slot de replicação indica que a primeira etapa de configuração não foi concluída.

Se active == t não for verdadeiro, isso significa que o dispositivo em espera não está se conectando por algum motivo (rede, configuração não concluída etc.), e a depuração provavelmente precisará continuar no dispositivo em espera.

Estatísticas de replicação

alloydbadmin=# select * from pg_stat_replication;
-[ RECORD 1 ]----+----------------------------------------------------------------
pid              | 250
usesysid         | 16385
usename          | alloydbreplica
application_name | d85d_dbcluster_sample
client_addr      | 10.54.79.196
client_hostname  | gke-samwise-default-pool-afaf152d-8197.us-central1-a.c.foo
client_port      | 24914
backend_start    | 2024-10-30 21:44:26.408261+00
backend_xmin     |
state            | streaming
sent_lsn         | 0/CA64DA8
write_lsn        | 0/CA64DA8
flush_lsn        | 0/CA64DA8
replay_lsn       | 0/CA64DA8
write_lag        |
flush_lag        |
replay_lag       |
sync_priority    | 2
sync_state       | sync
reply_time       | 2024-11-04 22:08:04.370838+00

Se ele não existir, significa que não há uma conexão ativa. O sync_state precisa ser sync. Se não for sync, isso significa que a etapa final da configuração não foi concluída. Confira os registros / jobs para mais detalhes.

Verificação em espera

O standby precisa ter um perfil de replicação que corresponda ao mesmo perfil da instância principal:

  replication:
    profiles:
    -   host: 10.54.79.210
      isActive: true
      isSynchronous: true
      name: ha:4c82-dbcluster-sample::d85d-dbcluster-sample
      passwordResourceVersion: "896080"
      port: 5432
      role: Downstream
      type: Physical
      username: alloydbreplica

Se não houver conexão da espera para a principal, há duas possibilidades comuns:

  1. O standby ainda está sendo configurado.
  2. O standby está recebendo um erro ao configurar ou tentar se conectar.

Para verificar se a opção 1 está acontecendo, extraia os registros do pod do banco de dados e procure instruções de registro chamadas dbdaemon/setupPhysicalReplicationDownstream. Confira a seguir exemplos de registros de configuração bem-sucedida:

I1104 22:42:42.604871     103 replication.go:107] "dbdaemon/setupPhysicalReplicationDownstream: begin setup" log_name="agent" project_ns="default" dbcluster="dbcluster-sample"
2024-11-04 22:42:42,605 INFO waiting for postgres to stop
2024-11-04 22:42:43,566 INFO stopped: postgres (exit status 0)
I1104 22:42:43.567590     103 replication.go:131] "dbdaemon/setupPhysicalReplicationDownstream: about to call pg_basebackup" log_name="agent" project_ns="default" dbcluster="dbcluster-sample" cmd=["-h","10.54.79.210","-D","/mnt/disks/pgsql/pg_basebackup_data","-U","alloydbreplica","-v","-P","-p","5432","-w","-c","fast"]
I1104 22:42:44.206403     103 replication.go:139] "dbdaemon/setupPhysicalReplicationDownstream: pg_basebackup finished" log_name="agent" project_ns="default" dbcluster="dbcluster-sample"
I1104 22:42:44.206440     103 replication.go:141] "dbdaemon/setupPhysicalReplicationDownstream: replacing data directory with pg_basebackup data directory" log_name="agent" project_ns="default" dbcluster="dbcluster-sample"
I1104 22:42:44.244749     103 replication.go:148] "dbdaemon/setupPhysicalReplicationDownstream: replaced data directory with pg_basebackup data directory" log_name="agent" project_ns="default" dbcluster="dbcluster-sample"
I1104 22:42:44.244783     103 replication.go:150] "dbdaemon/setupPhysicalReplicationDownstream: Creating config files" log_name="agent" project_ns="default" dbcluster="dbcluster-sample"
I1104 22:42:44.251565     103 replication.go:155] "dbdaemon/setupPhysicalReplicationDownstream: removing postgresql config file for log archiving" log_name="agent" project_ns="default" dbcluster="dbcluster-sample"
I1104 22:42:44.251621     103 replication.go:160] "dbdaemon/setupPhysicalReplicationDownstream: removing postgresql auto config file" log_name="agent" project_ns="default" dbcluster="dbcluster-sample"
I1104 22:42:44.251689     103 replication.go:165] "dbdaemon/setupPhysicalReplicationDownstream: Successfully wrote to config file" log_name="agent" project_ns="default" dbcluster="dbcluster-sample"
2024-11-04 22:42:44,256 INFO spawned: 'postgres' with pid 271
2024-11-04 22:42:45,469 INFO success: postgres entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
I1104 22:42:45.469838     103 replication.go:174] "dbdaemon/setupPhysicalReplicationDownstream: backup replication configuration after changing replication config" log_name="agent" project_ns="default" dbcluster="dbcluster-sample"
I1104 22:42:45.476732     103 replication.go:179] "dbdaemon/setupPhysicalReplicationDownstream: finished standby setup" log_name="agent" project_ns="default" dbcluster="dbcluster-sample"

Se houver um erro de conexão, verifique os registros do pod do banco de dados e o arquivo de registro no banco de dados em /obs/diagnostic/postgresql.log para saber qual é o erro ao tentar se conectar. Um erro comum é a falta de conectividade de rede entre o standby e o primário.

Correções manuais

A maneira mais fácil de corrigir problemas de HA é desativar e reativar o HA definindo numberOfStandbys como 0 e redefinindo para o número desejado. Se os standbys ficarem presos e desativados, siga estas etapas para redefinir manualmente a configuração de alta disponibilidade para ficar vazia:

  1. Exclua manualmente as instâncias de espera.
  2. Conecte-se ao banco de dados principal. Consulte os slots de replicação atuais e exclua os slots de replicação dos standbys que você quer excluir:

    select pg_drop_replication_slot('<replication_slot_name_here>');
    
  3. Exclua todos os perfis de replicação da instância principal que você quer excluir.

Se uma instância não tiver sido reconciliada recentemente, edite o valor da anotação forceReconcile. Defina como qualquer valor numérico, que é o carimbo de data/hora da última atualização da anotação. O único propósito dessa anotação é fornecer um campo que podemos atualizar para forçar uma nova conciliação.

apiVersion: alloydbomni.internal.dbadmin.goog/v1
kind: Instance
metadata:
  annotations:
    dbs.internal.dbadmin.goog/consecutiveHealthcheckFailures: "0"
    dbs.internal.dbadmin.goog/disableHealthcheck: "false"
    dr-secondary: "false"
    forceReconcile: "1730414498"

Coletar registros de auditoria e do mecanismo de banco de dados

Os registros do mecanismo de banco de dados e de auditoria estão disponíveis como arquivos no pod do banco de dados (exige acesso root):

  • obs/diagnostic/postgresql.log
  • obs/diagnostic/postgresql.audit
export NAMESPACE=dbcluster-namespace
export DBCLUSTER=dbcluster-sample

export DBPOD=`kubectl get pod -n ${NAMESPACE} -l alloydbomni.internal.dbadmin.goog/dbcluster=${DBCLUSTER} -l alloydbomni.internal.dbadmin.goog/task-type=database -o jsonpath='{.items[0].metadata.name}'`
kubectl exec -n ${NAMESPACE} ${DBPOD} -it -- /bin/bash

$ ls -la /obs/diagnostic/
-rw------- 1 postgres postgres    98438 Sep 25 20:15 postgresql.audit
-rw------- 1 postgres postgres 21405058 Sep 25 20:24 postgresql.log

Coletar métricas de banco de dados e pods de banco de dados

O operador do AlloyDB Omni fornece um conjunto de métricas básicas para o mecanismo do AlloyDB Omni e o pod que o hospeda. As métricas estão disponíveis como endpoints do Prometheus na porta 9187. Para acessar os endpoints, identifique os nomes dos pods do banco de dados e do monitoramento do banco de dados usando os rótulos DBCluster e task-type da seguinte maneira.

export NAMESPACE=default
export DBCLUSTER=dbcluster-sample

export DBPOD=`kubectl get pod -n ${NAMESPACE} -l alloydbomni.internal.dbadmin.goog/dbcluster=${DBCLUSTER},alloydbomni.internal.dbadmin.gdc.goog/task-type=database -o jsonpath='{.items[0].metadata.name}'`

export MONITORINGPOD=`kubectl get pod -n ${NAMESPACE} -l alloydbomni.internal.dbadmin.goog/dbcluster=${DBCLUSTER},alloydbomni.internal.dbadmin.gdc.goog/task-type=monitoring -o jsonpath='{.items[0].metadata.name}'`

Acessar métricas do banco de dados do AlloyDB Omni

kubectl port-forward -n ${NAMESPACE} ${MONITORINGPOD} 9187:9187
curl http://localhost:9187/metrics | grep HELP

Acessar métricas de pods de banco de dados

kubectl port-forward -n ${NAMESPACE} ${DBPOD} 9187:9187
curl http://localhost:9187/metrics | grep HELP

Também é possível configurar o Prometheus para extrair as métricas no cluster do Kubernetes. Consulte a configuração de descoberta de serviço do Kubernetes do Prometheus para mais detalhes.