Cassandra 问题排查指南

您正在查看 ApigeeApigee Hybrid 文档。
此主题没有等效的 Apigee Edge 文档。

本主题讨论您可以采取哪些措施来排查和解决 Cassandra 数据存储区的问题。Cassandra 是一种永久性数据存储区,在 Hybrid 运行时架构cassandra 组件中运行。另请参阅运行时服务配置概览

Cassandra pod 卡在“正在发布”状态

症状

尝试对 Cassandra pod 进行更新后,数据存储区报告其卡在“正在发布”状态。

错误消息

使用 kubectl 查看 pod 状态时,您会看到一个或多个 Cassandra pod 卡在“正在发布”状态:

Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Ack 57s (x7 over 24h) apigee-datastore release started

可能的原因

Pod 卡在“正在发布”状态可能是由以下原因造成的:

原因 说明
存储空间容量更改 override.yaml 文件中更改了存储空间容量。
其他配置更改 override.yaml 文件中的 cassandra 属性进行了更新;但是,更改没有生效。

存储空间容量更改

诊断

  1. 使用 kubectl 查看 apigee 数据存储区 pod 的当前状态:
    kubectl get apigeeds -n apigee
    NAME STATE AGE
    default releasing 122d
  2. 检查 override.yaml 文件是否有任何更改:
    1. 使用您的版本控制系统,将 override.yaml 文件的先前版本与当前版本进行比较:
      diff OVERRIDES_BEFORE.yaml OVERRIDES_AFTER.yaml
    2. 如果 override.yaml 输出有差异,则表示存储空间容量大小可能存在问题。例如:
      # Overrides.yaml  before:
      cassandra:
         storage:
            capacity: 500Gi
      
      # Overrides.yaml after:
      cassandra:
         storage:
            capacity: 100Gi

      如果有一个操作会更改存储空间容量(跳过了步骤),并且直接应用了新的 override.yaml,则可能会导致数据存储区处于“正在发布”状态。

  3. 检查 statefulset,确保有 apigee-cassandra-default 的对应项:
    kubectl describe sts -n apigee

    输出如下所示:

    Name:               apigee-cassandra-default
    Namespace:          apigee
    CreationTimestamp:  Tue, 18 Jul 2023 00:40:57 +0000
    Selector:           app=apigee-cassandra,name=default
    Labels:             apigee.cloud.google.com.revision=v1-2cc098050836c6b4
                        apigee.cloud.google.com.version=v1
                        apigee.cloud.google.com/platform=apigee
                        app=apigee-cassandra
                        name=default
    Annotations:        <none>
    Replicas:           3 desired | 3 total
    Update Strategy:    RollingUpdate
      Partition:        0
    Pods Status:        3 Running / 0 Waiting / 0 Succeeded / 0 Failed
    Pod Template:
      Labels:       apigee.cloud.google.com/apigee_servicename=production
                    apigee.cloud.google.com/billing_type=subscription
                    apigee.cloud.google.com/platform=apigee
                    app=apigee-cassandra
                    name=default
                    revision=v1
                    runtime_type=hybrid
      Annotations:  apigee.cloud.google.com/pod-template-spec-hash: 2cc098050836c6b4
                    prometheus.io/path: /metrics
                    prometheus.io/port: 7070
                    prometheus.io/scheme: https
                    prometheus.io/scrape: true
      Containers:
       apigee-cassandra:
        Image:       gcr.io/apigee-release/hybrid/apigee-hybrid-cassandra:1.10.1
        Ports:       7000/TCP, 7001/TCP, 7199/TCP, 9042/TCP, 8778/TCP
        Host Ports:  7000/TCP, 7001/TCP, 7199/TCP, 9042/TCP, 8778/TCP
        Requests:
          cpu:      500m
          memory:   1Gi
        Readiness:  exec [/bin/bash -c /opt/apigee/ready-probe.sh] delay=0s timeout=5s period=10s #success=1 #failure=2
        Environment:
          POD_NAME:                  (v1:metadata.name)
          POD_IP:                    (v1:status.podIP)
          MAX_HEAP_SIZE:            512M
          HEAP_NEWSIZE:             100M
          CASSANDRA_SEEDS:          apigee-cassandra-default-0.apigee-cassandra-default.apigee.svc.cluster.local
          CASSANDRA_CLUSTER_NAME:   apigeecluster
          CASSANDRA_DC:             dc-1
          CASSANDRA_RACK:           ra-1
          CASSANDRA_OPEN_JMX:       true
          CPS_ADMIN_USER:           <set to the key 'admin.user' in secret 'apigee-datastore-default-creds'>        Optional: false
          CPS_ADMIN_PASSWORD:       <set to the key 'admin.password' in secret 'apigee-datastore-default-creds'>    Optional: false
          APIGEE_JMX_USER:          <set to the key 'jmx.user' in secret 'apigee-datastore-default-creds'>          Optional: false
          APIGEE_JMX_PASSWORD:      <set to the key 'jmx.password' in secret 'apigee-datastore-default-creds'>      Optional: false
          CASS_PASSWORD:            <set to the key 'default.password' in secret 'apigee-datastore-default-creds'>  Optional: false
          APIGEE_JOLOKIA_USER:      <set to the key 'jolokia.user' in secret 'apigee-datastore-default-creds'>      Optional: false
          APIGEE_JOLOKIA_PASSWORD:  <set to the key 'jolokia.password' in secret 'apigee-datastore-default-creds'>  Optional: false
        Mounts:
          /opt/apigee/apigee-cassandra/conf from appsfs (rw)
          /opt/apigee/customer from cwc-volume (ro)
          /opt/apigee/data from cassandra-data (rw)
          /opt/apigee/ssl from tls-volume (ro)
          /var/secrets/google from apigee-cassandra-backup (rw)
          /var/secrets/keys from apigee-cassandra-backup-key-file (rw)
      Volumes:
       cwc-volume:
        Type:        Secret (a volume populated by a Secret)
        SecretName:  config-cassandra-default
        Optional:    false
       tls-volume:
        Type:        Secret (a volume populated by a Secret)
        SecretName:  apigee-cassandra-default-tls
        Optional:    false
       appsfs:
        Type:       EmptyDir (a temporary directory that shares a pod's lifetime)
        Medium:
        SizeLimit:  <unset>
       apigee-cassandra-backup:
        Type:        Secret (a volume populated by a Secret)
        SecretName:  apigee-cassandra-backup-svc-account
        Optional:    true
       apigee-cassandra-backup-key-file:
        Type:        Secret (a volume populated by a Secret)
        SecretName:  apigee-cassandra-backup-key-file
        Optional:    true
    Volume Claims:
      Name:          cassandra-data
      StorageClass:
      Labels:        <none>
      Annotations:   <none>
      Capacity:      10Gi
      Access Modes:  [ReadWriteOnce]
    Events:
      Type    Reason            Age   From                    Message
      ----    ------            ----  ----                    -------
      Normal  SuccessfulCreate  47m   statefulset-controller  create Pod apigee-cassandra-default-2 in StatefulSet apigee-cassandra-default successful
  4. 检查 Apigee 控制器中的错误消息:
    kubectl logs -f apigee-controller-manager-59cf595c77-wtwnr -n apigee-system -c manager | grep apigeedatastore
    

    结果:

    "error creating
    apigee-cassandra object: failed to update resource
    apigee/apigee-cassandra-default: StatefulSet.apps \"apigee-cassandra-default\"
    is invalid: spec: Forbidden: updates to statefulset spec for fields other than
    'replicas', 'template', 'updateStrategy', 'persistentVolumeClaimRetentionPolicy'
    and 'minReadySeconds' are forbiddenerror creating apigee-cassandra object:
    failed to update resource apigee/apigee-cassandra-default: StatefulSet.apps
    \"apigee-cassandra-default\" is invalid: spec: Forbidden: updates to statefulset
    spec for fields other than 'replicas', 'template', 'updateStrategy',
    'persistentVolumeClaimRetentionPolicy' and 'minReadySeconds' are forbidden"

解决方法

您可以使用以下步骤重置 Cassandra 的状态,使其恢复运行状态:

  1. 停用 apigee-controller
    kubectl -n apigee-system edit deployments and set --enable-controllers=true to --enable-controllers=false
    
  2. 使用 PATCH 命令将数据存储区恢复到运行状态:
    curl -XPATCH \-H "Accept: application/json" -H "Content-Type: application/json-patch+json" --data '[{"op": "replace", "path": "/status/nestedState", "value": ""},{"op": "replace", "path": "/status/state", "value": "running"}]' 'http://127.0.0.1:8001/apis/apigee.cloud.google.com/v1alpha1/namespaces/apigee/apigeedatastores/default/status'
    
  3. 重新应用原始 override.yaml 文件:
    ./apigeectl apply --datastore -f overrides.yaml
    
  4. 启用 apigee-controller
    kubectl -n apigee-system edit deployments and set --enable-controllers=false to --enable-controllers=true
    
  5. 等待数据存储区恢复运行并使用以下命令进行验证:
    kubectl get apigeeds --namespace apigee
    
  6. 验证 Apigee 部署和 pod 是否处于运行状态;并且 apigeeds 不再处于“正在发布”状态:
    kubectl get ad -n apigee
    
    kubectl get pods -n apigee
    
    kubectl get apigeeds -n apigee
    
    NAME      STATE     AGE
    default   running   24d

其他配置更改

override.yaml 中的 cassandra 属性进行了的更新,但更改未生效。可能是在 override.yaml 中更改了密码或对资源进行了更改。也可能是错误地将不正确的 override.yaml 应用到了集群。

诊断

请参阅诊断中的相关步骤。

解决方法

请参阅解决方法中的相关步骤。

必须收集的诊断信息

如果按照上述说明操作后问题仍然存在,请收集以下诊断信息,然后与 Google Cloud Customer Care 联系:

  • 安装中每个集群的 Overrides.yaml
  • Hybrid 安装中的 kubernetes 集群信息转储:

    生成 kubernetes cluster-info dump

    kubectl cluster-info dump -A --output-directory=/tmp/kubectl-cluster-info-dump
    

    使用 zip 对 kubernetes cluster-info dump 进行压缩:

    zip -r kubectl-cluster-info-dump`date +%Y.%m.%d_%H.%M.%S`.zip /tmp/kubectl-cluster-info-dump/*
    

Cassandra pod 卡在“待处理”状态

症状

启动时,Cassandra pod 将保持待处理状态。

错误消息

使用 kubectl 查看 pod 状态时,您会看到一个或多个 Cassandra pod 卡在 Pending 状态。Pending 状态表示 Kubernetes 无法调度节点上的 pod:无法创建 pod。例如:

kubectl get pods -n NAMESPACE

NAME                                     READY   STATUS      RESTARTS   AGE
adah-resources-install-4762w             0/4     Completed   0          10m
apigee-cassandra-default-0               0/1     Pending     0          10m
...

可能的原因

Pod 卡在“待处理”状态可能有多种原因。例如:

原因 说明
资源不足 没有足够的 CPU 或内存来创建 pod。
未创建卷 pod 正在等待创建永久性卷。
缺少 Amazon EBS CSI 驱动程序 对于 EKS 安装,未安装所需的 Amazon EBS CSI 驱动程序。

诊断

使用 kubectl 描述 pod 以确定错误来源。例如:

kubectl -n NAMESPACE describe pods POD_NAME

例如:

kubectl describe pods apigee-cassandra-default-0 -n apigee

输出可能显示以下可能的问题之一:

  • 如果问题是资源不足,您将看到一条警告消息,指示 CPU 或内存不足。
  • 如果错误消息指出 pod 存在未绑定的即时 PersistentVolumeClaim (PVC),则表示 pod 无法创建其永久性卷

解决方法

资源不足

修改 Cassandra 节点池,使其具有足够的 CPU 和内存资源。如需了解详情,请参阅调整节点池的大小

未创建永久性卷

如果您确定是永久性卷问题,请描述 PersistentVolumeClaim (PVC) 以确定为什么不创建它:

  1. 列出集群中的 PVC:
    kubectl -n NAMESPACE get pvc
    
    NAME                                        STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
    cassandra-data-apigee-cassandra-default-0   Bound    pvc-b247faae-0a2b-11ea-867b-42010a80006e   10Gi       RWO            standard       15m
    ...
  2. 描述失败的 pod 的 PVC。例如,以下命令描述了绑定到 pod apigee-cassandra-default-0 的 PVC:
    kubectl apigee describe pvc cassandra-data-apigee-cassandra-default-0
    
    Events:
      Type     Reason              Age                From                         Message
      ----     ------              ----               ----                         -------
      Warning  ProvisioningFailed  3m (x143 over 5h)  persistentvolume-controller  storageclass.storage.k8s.io "apigee-sc" not found

    请注意,在此示例中,名为 apigee-sc 的 StorageClass 不存在。要解决此问题,请在集群中创建缺失的 StorageClass,如更改默认 StorageClass 中所述。

另请参阅调试 pod

缺少 Amazon EBS CSI 驱动程序

如果 Hybrid 实例在 EKS 集群上运行,请确保 EKS 集群使用 Amazon EBS 容器存储接口 (CSI) 驱动程序。如需了解详情,请参阅 Amazon EBS CSI 迁移常见问题解答

Cassandra pod 卡在 CrashLoopBackoff 状态

症状

启动时,Cassandra pod 保持 CrashLoopBackoff 状态。

错误消息

使用 kubectl 查看 pod 状态时,您会看到一个或多个 Cassandra pod 处于 CrashLoopBackoff 状态。此状态表示 Kubernetes 无法创建 pod。例如:

kubectl get pods -n NAMESPACE

NAME                                     READY   STATUS            RESTARTS   AGE
adah-resources-install-4762w             0/4     Completed         0          10m
apigee-cassandra-default-0               0/1     CrashLoopBackoff  0          10m
...

可能的原因

pod 卡在 CrashLoopBackoff 状态可能有多种原因。例如:

原因 说明
数据中心与之前的数据中心不同 此错误表示 Cassandra pod 具有永久性卷,该卷包含来自上一个集群的数据,并且新 pod 无法加入旧集群。如果过时的永久性卷来自同一 Kubernetes 节点上之前的 Cassandra 集群,通常会发生这种情况。如果您在集群中删除 Cassandra 并重新创建,则可能会出现此问题。
Kubernetes 升级 Kubernetes 升级可能会影响 Cassandra 集群。当托管 Cassandra pod 的 Anthos 工作器节点升级到新的操作系统版本时,可能会发生这种情况。

诊断

检查 Cassandra 错误日志以确定问题的原因。

  1. 列出 pod 以获取失败的 Cassandra pod 的 ID:
    kubectl get pods -n NAMESPACE
  2. 检查失败的 pod 的日志:
    kubectl logs POD_ID -n NAMESPACE

解决方法

在 pod 的日志中查找以下线索:

数据中心与之前的数据中心不同

如果您看到此日志消息:

Cannot start node if snitch's data center (us-east1) differs from previous data center
  • 检查集群中是否有任何过时的或旧的 PVC,然后删除它们。
  • 如果是全新安装,请删除所有 PVC,然后重试设置。例如:
    kubectl -n NAMESPACE get pvc
    kubectl -n NAMESPACE delete pvc cassandra-data-apigee-cassandra-default-0

Anthos 升级更改安全设置

检查 Cassandra 日志中是否存在此错误消息:

/opt/apigee/run.sh: line 68: ulimit: max locked memory:
  cannot modify limit: Operation not permitted

创建用于调试的客户端容器

本部分介绍如何创建可从中访问 Cassandra 调试实用程序(如 cqlsh)的客户端容器。这些实用程序可让您查询 Cassandra 表,并且可用于调试。

创建客户端容器

如需创建客户端容器,请按以下步骤操作:

  1. 容器必须使用 apigee-cassandra-user-setup Pod 中的 TLS 证书。此证书以 Kubernetes Secret 的形式存储。提取存储此证书的 Secret 的名称:
    kubectl get secrets -n apigee --field-selector type=kubernetes.io/tls | grep apigee-cassandra-user-setup | awk '{print $1}'

    此命令会返回 Secret 的名称。例如:apigee-cassandra-user-setup-rg-hybrid-b7d3b9c-tls。您将在 YAML 文件的 secretName 字段中使用该名称。

  2. 打开一个新文件,并将以下 pod 规范粘贴到其中:
    apiVersion: v1
    kind: Pod
    metadata:
      labels:
      name: CASSANDRA_CLIENT_NAME   # For example: my-cassandra-client
      namespace: apigee
    spec:
      containers:
      - name: CASSANDRA_CLIENT_NAME
        image: "gcr.io/apigee-release/hybrid/apigee-hybrid-cassandra-client:YOUR_APIGEE_HYBRID_VERSION" # For example, 1.10.5.
        imagePullPolicy: Always
        command:
        - sleep
        - "3600"
        env:
        - name: CASSANDRA_SEEDS
          value: apigee-cassandra-default.apigee.svc.cluster.local
        - name: APIGEE_DML_USER
          valueFrom:
            secretKeyRef:
              key: dml.user
              name: apigee-datastore-default-creds
        - name: APIGEE_DML_PASSWORD
          valueFrom:
            secretKeyRef:
              key: dml.password
              name: apigee-datastore-default-creds
        volumeMounts:
        - mountPath: /opt/apigee/ssl
          name: tls-volume
          readOnly: true
      volumes:
      - name: tls-volume
        secret:
          defaultMode: 420
          secretName: YOUR_SECRET_NAME    # For example: apigee-cassandra-user-setup-rg-hybrid-b7d3b9c-tls
      restartPolicy: Never
  3. 使用 .yaml 扩展名保存文件。例如:my-spec.yaml
  4. 将规范应用到您的集群:
    kubectl apply -f YOUR_SPEC_FILE.yaml -n apigee
  5. 登录容器:
    kubectl exec -n apigee CASSANDRA_CLIENT_NAME -it -- bash
  6. 使用以下命令连接到 Cassandra cqlsh 接口。输入如下所示的命令:
    cqlsh ${CASSANDRA_SEEDS} -u ${APIGEE_DML_USER} -p ${APIGEE_DML_PASSWORD} --ssl

删除客户端 pod

使用以下命令删除 Cassandra 客户端 pod:

kubectl delete pods -n apigee cassandra-client

配置有误的区域扩展:所有 Cassandra 节点在一个数据中心内

此情况发生在 GKE 和 GKE On-Prem (Anthos) 平台上的多区域扩展中。请尽量避免尝试在同一数据中心内创建所有 Cassandra 节点。

症状

无法在第二个区域的数据中心内创建 Cassandra 节点。

错误消息

failed to rebuild from dc-1: java.lang.RuntimeException : Error while rebuilding node: Stream failed

解决方法

请按照以下步骤修复配置有误的区域扩展:

  1. 在第二个数据中心的 overrides.yaml 文件中,将 Cassandra replicaCount 更新为 1。例如:
    cassandra:
      . . .
      replicaCount: 1

    使用 apigeectl apply 应用此设置:

    $APIGEECTL_HOME/apigeectl apply -f 2ND_DATACENTER_OVERRIDES.yaml
  2. 使用 kubectl exec 通过以下命令访问其余的 Cassandra Pod:
    kubectl exec -it -n apigee apigee-cassandra-default-0 -- /bin/bash
  3. 使用以下命令停用其余的 Cassandra Pod:
    nodetool -u CASSANDRA_DB_USER -pw CASSANDRA_DB_PASSWORD decommission
  4. 使用带有 --datastore 参数的 apigeectl delete 从第二个数据中心删除 Cassandra Pod。例如:
    $APIGEECTL_HOME/apigeectl delete -f 2ND_DATACENTER_OVERRIDES.yaml --datastore
  5. 将 Kubernetes 上下文更改为第一个数据中心的集群:
    kubectl config use-context FIRST_DATACENTER_CLUSTER
  6. 验证第一个数据中心内没有处于停止运行状态的 Cassandra 节点。
    nodetool -u CASSANDRA_DB_USER -pw CASSANDRA_DB_PASSWORD status
  7. 验证配置有误的 Cassandra 节点(要用于第二个数据中心)已从第一个数据中心移除。确保 nodetool 状态输出中显示的 IP 地址只有用于第一个数据中心的 Cassandra Pod 的 IP 地址。例如,在以下输出中,IP 地址 10.100.0.39 应该对应于第一个数据中心中的 Pod。
    kubectl exec -it -n apigee apigee-cassandra-default-0 -- /bin/bash
    nodetool -u CASSANDRA_DB_USER -pw CASSANDRA_DB_PASSWORD status
    
      Datacenter: dc-1
      ================
      Status=U/D (Up/Down) | State=N/L/J/M (Normal/Leaving/Joining/Moving)
      --  Address      Load      Tokens  Owns (effective)  Host ID                               Rack
      UN  10.100.0.39  4.21 MiB  256     100.0%            a0b1c2d3-e4f5-6a7b-8c9d-0e1f2a3b4c5d  ra-1
  8. 验证第二个数据中心的 overrides.yaml 文件在 cassandra 部分下包含数据中心名称设置。例如:
    cassandra:
      datacenter: DATA_CENTER_2
      rack: "RACK_NAME" # "ra-1" is the default value.
      . . .
  9. 将第二个数据中心的 overrides.yaml 文件中的 cassandra:replicaCount 设置更新为所需的数字。例如:
    cassandra:
      datacenter: DATA_CENTER_2
      . . .
      replicaCount: 3
  10. 使用 --datastore 参数应用第二个数据中心的 overrides.yaml 文件。例如:
    $APIGEECTL_HOME/apigeectl apply -f 2ND_DATACENTER_OVERRIDES.yaml --datastore
  11. 使用 kubectl exec 访问第二个数据中心内的新 Cassandra Pod,并验证有两个数据中心:
     "nodetool -u CASSANDRA_DB_USER -pw CASSANDRA_DB_PASSWORD status"

其他资源

请参阅 Apigee X 和 Apigee Hybrid playbook 简介