Soluciona problemas del operador de Kubernetes de AlloyDB Omni

Selecciona una versión de la documentación:

En esta página, se muestra cómo resolver problemas con el operador de Kubernetes de AlloyDB Omni.

Recopila información de depuración

En estas secciones, se describe cómo recopilar registros y configuraciones para la depuración.

Recupera registros de los pods del operador

Para recuperar los registros de los pods del operador, ejecuta los siguientes 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

Cómo recuperar los registros del Pod de la base de datos

Para recuperar los registros del pod de la base de datos, ejecuta los siguientes comandos:

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

Los siguientes registros son ejemplos de verificaciones de estado de la base de datos exitosas:

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"

Recupera el archivo postgresql.log

Para recuperar el postgresql.log, ejecuta el siguiente comando:

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

Recupera el archivo YAML de DBInstance

Para recuperar el archivo YAML de DBInstance, ejecuta el siguiente comando:

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

Recupera registros y configuraciones para situaciones de HA

Para recuperar los registros y la configuración específicos de situaciones de alta disponibilidad (HA), ejecuta los siguientes 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

Recupera los estados del pod y del STS

Para recuperar los estados de los pods y los StatefulSets (STS), ejecuta los siguientes comandos:

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

Cómo identificar errores

En estas secciones, se describe cómo identificar errores.

Busca el estado y los códigos de error

Para identificar el código de error, consulta el archivo YAML de DBCluster en el estado. Consulta la documentación de los códigos de error para obtener más información.

Para recuperar el archivo YAML de DBCluster, ejecuta el siguiente comando:

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

Busca criticalIncidents. Esta sección contiene el código de error y un seguimiento de pila.

A continuación, se muestran ejemplos 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'

También puedes recuperar el estado extrayendo campos específicos en formato JSON:

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

El resultado es similar a este:

[
  {
    "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"
      }
    ]
  }
]

Si el mensaje de error hace referencia al pod de la base de datos, verifica las instancias y los recursos del pod en el mismo espacio de nombres:

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

Cómo depurar problemas de memoria

En estas secciones, se describe cómo depurar problemas de memoria.

Ejecuta y toma un volcado de montón

Activa esta función solo para solucionar problemas. Recuerda apagarlo después.

Para tomar un heapdump, completa los siguientes pasos:

  1. Modifica la implementación del operador en el espacio de nombres alloydb-omni-system con el nombre fleet-controller-manager y local-controller-manager.
  2. Agrega el siguiente argumento al pod --pprof-address=:8642 o a cualquier otro puerto disponible.
  3. Espera a que se reinicie el Pod del controlador.
  4. Redirecciona el puerto anterior. Por ejemplo:

    kubectl port-forward -n alloydb-omni-system fleet-controller-manager-pod-name 8642:8642
    
  5. En otra terminal, ejecuta go tool pprof http://localhost:8642/debug/pprof/heap. Si no usas 8642, cambia el puerto para que coincida con el puerto anterior.

  6. Conéctate a la dirección y ejecuta comandos de solución de problemas. Por ejemplo: top.

  7. Después de finalizar la solución de problemas, deshaz el paso 1 quitando el argumento y esperando a que se reinicie el Pod.

Determina la cantidad de recursos que supervisa el operador

Para comprender los recursos que están en uso, ejecuta los siguientes 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 ejemplo, si la cantidad de secretos es alta, se puede producir un error de memoria insuficiente (OOM).

kubectl get secrets -A | wc -l

Depuración avanzada de HA

En esta sección, se hace referencia a recursos que son implementaciones internas. Están sujetos a cambios en cualquier momento y no tienen compromisos de retrocompatibilidad. Solo aplica correcciones manuales a los problemas en bases de datos que no sean de producción. Estos pasos pueden hacer que la base de datos sea irrecuperable.

La configuración de HA de AlloyDB Omni tiene tres fases:

  1. Configura la instancia principal para que reciba una conexión de la instancia en espera.
  2. Inicializa la instancia en espera y conéctala a la instancia principal.
  3. Establece la configuración principal para que la conexión sea síncrona.

El paso 2 suele ser el más lento. Según el tamaño de la base de datos, el proceso puede tardar varias horas.

Cada instancia de replicación debe tener un replicationconfig adjunto. Por ejemplo: 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

En este ejemplo:

  • La instancia 9f47-dbcluster-sample se configura como un upstream físico.
  • La instancia 7576-dbcluster-sample está configurada como una instancia física de nivel inferior.

La especificación de Replication Config indica la configuración prevista, mientras que el estado refleja el estado real tal como se lee de la base de datos. Si hay una discrepancia entre la especificación y el estado, el controlador aún intenta aplicar el cambio o hay algún error que impide que se aplique el cambio. Esto se reflejaría en los campos de estado.

Trabajos en espera

Debe haber dos conjuntos de trabajos internos que realicen un seguimiento del flujo de trabajo de un suplente:

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

Si la configuración parece estar atascada, consulta los trabajos relacionados con el clúster de la base de datos (DBC). Es posible que el trabajo tenga mensajes de error que expliquen en qué estado se encuentra la configuración. Los trabajos se limpian automáticamente un tiempo después de que se completan, por lo que es posible que no veas ninguno si no hay trabajos en curso.

k get createstandbyjob

El resultado es similar a este:

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"

Verificación principal

Lo primero que debes verificar es que la instancia principal esté configurada correctamente. Debe haber un perfil de replicación para cada instancia en espera. Si isSynchronous es verdadero en la especificación y el estado, la configuración debería estar completa. Si isSynchronous es falso en la especificación y el estado, aún no se llegó al paso 3. Consulta los trabajos en espera para ver si hay trabajos en ejecución y si tienen mensajes de error.

  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

Verifica que la anotación disableHealthcheck sea falsa. Solo se debe inhabilitar durante una conmutación por error o un cambio.

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 que los recursos del pod de la BD estén configurados correctamente, accede a la base de datos como el usuario administrador alloydbadmin. Luego, ejecuta las siguientes consultas:

Ranura de replicación

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

Un buen estado es la presencia de una ranura de replicación con el mismo nombre que la instancia en espera. La ausencia de una ranura de replicación indica que el primer paso de configuración no se completó correctamente.

Si active == t no es verdadero, significa que el dispositivo en espera no se está conectando por algún motivo (problemas de red, el dispositivo en espera no finaliza la configuración, etc.), y es probable que la depuración deba continuar del lado del dispositivo en espera.

Estadísticas de replicación

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

Si no existe, significa que no hay una conexión activa. El sync_state debe ser sync. Si no es sync, significa que no se completó el paso final de la configuración. Consultar los registros o los trabajos debería proporcionar más detalles.

Verificación en espera

La instancia en espera debe tener un perfil de replicación que coincida con el mismo perfil de la instancia 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

Si no hay conexión de la instancia en espera a la principal, hay dos posibilidades comunes:

  1. El dispositivo en espera aún se está configurando.
  2. El dispositivo en espera recibe un error cuando se configura o se intenta conectar.

Para verificar si se está produciendo la opción 1, obtén los registros del Pod de la base de datos y busca las instrucciones de registro llamadas dbdaemon/setupPhysicalReplicationDownstream. A continuación, se muestran ejemplos de registros de configuración exitosos:

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"

Si hay un error de conexión, verifica los registros del pod de la base de datos y el archivo de registro en la base de datos en /obs/diagnostic/postgresql.log para ver cuál es el error cuando se intenta conectar. Un error común es que no hay conectividad de red entre el nodo en espera y el principal.

Correcciones manuales

La forma más sencilla de solucionar los problemas de HA es inhabilitar y, luego, volver a habilitar la HA. Para ello, establece numberOfStandbys en 0 y, luego, restablece el número que desees. Si las copias de seguridad en espera no se habilitan, sigue estos pasos para restablecer manualmente la configuración de HA y dejarla vacía:

  1. Borra manualmente las instancias en espera.
  2. Conéctate a la base de datos principal. Consulta las ranuras de replicación actuales y borra las ranuras de replicación de los servidores en espera que quieras borrar:

    select pg_drop_replication_slot('<replication_slot_name_here>');
    
  3. Borra los perfiles de replicación de la instancia principal que desees borrar.

Si una instancia no se reconcilió recientemente, puedes editar el valor de la anotación forceReconcile. Establece ese valor en cualquier valor numérico, que es la marca de tiempo de la última vez que se actualizó la anotación. El único propósito de esa anotación es proporcionar un campo que podamos actualizar para forzar una nueva conciliación.

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"

Recopila registros de auditoría y del motor de base de datos

Los registros del motor de base de datos y los registros de auditoría están disponibles como archivos dentro del pod de la base de datos (se requiere acceso de administrador):

  • 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

Recopila métricas de la base de datos y del pod de la base de datos

El operador de AlloyDB Omni proporciona un conjunto de métricas básicas para el motor de AlloyDB Omni y el pod que lo aloja. Las métricas están disponibles como extremos de Prometheus en el puerto 9187. Para acceder a los extremos, debes identificar los nombres de los Pods del Pod de la base de datos y del Pod de supervisión de la base de datos, con las etiquetas DBCluster y task-type de la siguiente manera.

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}'`

Accede a las métricas de la base de datos de AlloyDB Omni

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

Accede a las métricas de los Pods de la base de datos

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

También puedes configurar Prometheus para recopilar las métricas de tu clúster de Kubernetes. Consulta la configuración del descubrimiento de servicios de Prometheus Kubernetes para obtener más detalles.