排查 AlloyDB Omni Kubernetes 操作器问题

选择文档版本:

本页面介绍如何解决 AlloyDB Omni Kubernetes 操作器的问题。

收集调试信息

以下部分介绍如何收集日志和配置以进行调试。

从操作器 Pod 中提取日志

如需从操作器 Pod 中提取日志,请运行以下命令:

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

提取数据库 Pod 日志

如需提取数据库 Pod 日志,请运行以下命令:

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

以下日志是成功的数据库健康检查的示例:

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"

提取 postgresql.log

如需提取 postgresql.log,请运行以下命令:

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

提取 DBInstance YAML 文件

如需提取 DBInstance YAML 文件,请运行以下命令:

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

提取高可用性场景的配置和日志

如需提取特定于高可用性 (HA) 场景的配置和日志,请运行以下命令:

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

提取 Pod 和 STS 状态

如需提取 Pod 和 StatefulSet (STS) 状态,请运行以下命令:

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

找出错误

以下部分介绍如何找出错误。

查找错误状态和错误代码

如需找到错误代码,请查看状态下的 DBCluster YAML 文件。如需了解详情,请参阅错误代码文档。

如需提取 DBCluster YAML 文件,请运行以下命令:

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

查找 criticalIncidents。 此部分包含错误代码和堆栈轨迹。

以下是 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'

您还可以通过提取 JSON 格式的特定字段来检索状态:

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

输出类似于以下内容:

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

如果错误消息涉及数据库 Pod,请检查同一命名空间中的实例和 Pod 资源:

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

调试内存问题

以下部分介绍如何调试内存问题。

运行并获取堆转储

仅在排查问题时开启此功能。请记得在之后将其关闭。

如需获取堆转储,请完成以下步骤:

  1. 修改 alloydb-omni-system 命名空间下名为 fleet-controller-managerlocal-controller-manager 的操作器部署。
  2. 将以下参数添加到 Pod --pprof-address=:8642 或任何其他可用端口。
  3. 等待控制器 Pod 重启。
  4. 转发上述端口。例如:

    kubectl port-forward -n alloydb-omni-system fleet-controller-manager-pod-name 8642:8642
    
  5. 在另一个终端上,运行 go tool pprof http://localhost:8642/debug/pprof/heap。如果您不使用 8642,请将端口更改为与前面的端口匹配。

  6. 连接到该地址并运行问题排查命令。例如:top

  7. 完成问题排查后,通过移除该参数并等待 Pod 重启来撤消第 1 步。

确定操作器正在监控的资源数量

如需了解正在使用的资源,请运行以下命令:

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

例如,如果 Secret 数量较多,可能会导致内存不足 (OOM) 错误。

kubectl get secrets -A | wc -l

高级高可用性调试

本部分引用了内部实现的资源。这些资源可能会随时发生变化,且无法保证向后兼容。仅对非生产数据库中的问题应用手动修复。这些步骤可能会导致数据库不可恢复。

AlloyDB Omni 高可用性设置分为三个阶段:

  1. 将主实例设置为接收来自备用实例的连接。
  2. 初始化备用实例并将其连接到主实例。
  3. 配置主实例设置以使连接同步。

第 2 步通常最慢。根据数据库的大小,可能需要几个小时。

每个进行复制的实例都应附加 replicationconfig。例如: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

在此示例中:

  • 实例 9f47-dbcluster-sample 配置为物理上游。
  • 实例 7576-dbcluster-sample 配置为物理下游。

复制配置的规范表示预期设置,而状态则反映从数据库读取的实际状态。如果规范与状态不匹配,则表示控制器仍在尝试应用更改,或者存在阻止应用更改的错误。这会反映在状态字段中。

备用实例作业

应有两组内部作业来跟踪备用实例的工作流:

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

如果设置似乎卡住了,请查看与数据库集群 (DBC) 相关的作业。作业可能包含错误消息,其中会说明设置所处的状态。作业在完成一段时间后会自动清理,因此如果没有进行中的作业,您可能看不到任何作业。

k get createstandbyjob

输出类似于以下内容:

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"

主实例验证

首先要验证的是主实例是否已正确设置。每个备用实例都应有一个复制配置文件。如果规范和状态中的 isSynchronous 为 true,则表示设置应该已经完成。如果规范和状态中的 isSynchronous 为 false,则表示尚未进行到第 3 步。查看备用实例作业,了解是否有任何正在运行的作业,以及这些作业是否包含任何错误消息。

  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

验证 disableHealthcheck 注解是否为 false。应仅在故障切换或切换期间停用该功能。

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"

查询

如需验证数据库 Pod 上的资源是否已正确设置,请以管理员用户身份 (alloydbadmin) 登录数据库。然后,发出以下查询:

复制槽

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

良好的状态是指存在与备用实例同名的复制槽。如果缺少复制槽,则表示第一个设置步骤未成功完成。

如果 active == t 不为 true,则表示备用实例因某种原因(网络、备用实例未完成设置等)而未连接,可能需要继续在备用实例端进行调试。

复制统计数据

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

如果不存在此值,则表示没有活跃连接。sync_state 应为 sync。如果不是 sync,则表示设置的最后一步未完成。查看日志/作业应该能够获得更多详细信息。

备用实例验证

备用实例应具有与主实例相同的复制配置文件:

  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

如果备用实例与主实例之间没有连接,则通常有以下两种可能:

  1. 备用实例仍在设置中。
  2. 备用实例在设置或尝试连接时出错。

如需检查是否发生了第一种情况,请获取数据库 Pod 日志,并查找名为 dbdaemon/setupPhysicalReplicationDownstream 的日志语句。以下是成功设置日志的示例:

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"

如果发生连接错误,请检查数据库 Pod 日志以及数据库上 /obs/diagnostic/postgresql.log 中的日志文件,了解在尝试连接时发生了什么错误。一个常见错误是备用实例与主实例之间没有网络连接。

手动修复

修复高可用性问题最简单的方法是先将 numberOfStandbys 设置为 0,然后将其重新设置为所需的数量,以停用并重新启用高可用性。如果备用实例一直卡在停用状态,请按照以下步骤操作,手动将高可用性设置重置为空:

  1. 手动删除备用实例。
  2. 连接到主数据库。查询当前的复制槽,并删除您要删除的备用实例的所有复制槽:

    select pg_drop_replication_slot('<replication_slot_name_here>');
    
  3. 从要删除的主实例中删除所有复制配置文件。

如果某个实例近期未进行协调,您可以修改 forceReconcile 注解值。将其设置为任意数值,即相应注解上次更新时的时间戳。该注解的唯一用途是提供一个可更新的字段来强制进行新的协调。

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"

收集数据库引擎日志和审核日志

数据库引擎日志和审核日志以文件形式存在于数据库 Pod 内(需要有根访问权限):

  • 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

收集数据库指标和数据库 Pod 指标

AlloyDB Omni 操作器为 AlloyDB Omni 引擎及其托管 Pod 提供了一组基本指标。这些指标以 Prometheus 端点的形式提供,可在端口 9187 上获取。如需访问这些端点,您需要使用 DBCluster 和任务类型标签来确定数据库 Pod 和数据库监控 Pod 的 Pod 名称,如下所示。

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

访问 AlloyDB Omni 数据库指标

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

访问数据库 Pod 指标

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

您还可以将 Prometheus 配置为爬取 Kubernetes 集群中的指标。如需了解详情,请参阅 Prometheus Kubernetes 服务发现配置