Cassandra 问题排查指南

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

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 正在等待创建永久性卷。

诊断

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

kubectl -n namespace describe pods pod_name

例如:

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

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

  • 如果问题是资源不足,您将看到一条警告消息,指示 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

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 并重新创建,则可能会出现此问题。
找不到 Truststore 目录 此错误表示 Cassandra pod 无法创建 TLS 连接。如果提供的密钥和证书无效、缺失或存在其他问题,通常会发生这种情况。

诊断

检查 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

找不到 Truststore 目录

如果您看到此日志消息:

Caused by: java.io.FileNotFoundException: /apigee/cassandra/ssl/truststore.p12
(No such file or directory)

请验证替换文件中提供的密钥和证书是否正确且有效。例如:

cassandra:
  sslRootCAPath: path_to_root_ca-file
  sslCertPath: path-to-tls-cert-file
  sslKeyPath: path-to-tls-key-file

节点故障

症状

启动时,Cassandra pod 将保持“待处理”状态。此问题可能表示底层节点故障。

诊断

  1. 确定哪些 Cassandra pod 没有运行:
    $ kubectl get pods -n your_namespace
        NAME                  READY   STATUS    RESTARTS   AGE
        cassandra-default-0   0/1     Pending   0          13s
        cassandra-default-1   1/1     Running   0          8d
        cassandra-default-2   1/1     Running   0          8d
  2. 检查工作器节点。如果一个节点处于 NotReady 状态,则表示该节点发生故障:
    kubectl get nodes -n your_namespace
    NAME                          STATUS   ROLES          AGE   VERSION
    ip-10-30-1-190.ec2.internal   Ready    <none>   8d    v1.13.2
    ip-10-30-1-22.ec2.internal    Ready    master   8d    v1.13.2
    ip-10-30-1-36.ec2.internal    NotReady <none>   8d    v1.13.2
    ip-10-30-2-214.ec2.internal   Ready    <none>   8d    v1.13.2
    ip-10-30-2-252.ec2.internal   Ready    <none>   8d    v1.13.2
    ip-10-30-2-47.ec2.internal    Ready    <none>   8d    v1.13.2
    ip-10-30-3-11.ec2.internal    Ready    <none>   8d    v1.13.2
    ip-10-30-3-152.ec2.internal   Ready    <none>   8d    v1.13.2
    ip-10-30-3-5.ec2.internal     Ready    <none>   8d    v1.13.2

解决方法

  1. 从集群中移除失效 Cassandra pod。
    $ kubectl exec -it apigee-cassandra-default-0 -- nodetool status
    $ kubectl exec -it apigee-cassandra-default-0 -- nodetool removenode deadnode_hostID
  2. 从失效节点中移除 VolumeClaim,以防止 Cassandra pod 因亲和性而尝试登录到失效节点上:
    kubectl get pvc -n your_namespace
    kubectl delete pvc volumeClaim_name -n your_namespace
  3. 更新卷模板并为新添加的节点创建 PersistentVolume。以下是一个卷模板示例:
    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: cassandra-data-3
    spec:
      capacity:
        storage: 100Gi
      accessModes:
      - ReadWriteOnce
      persistentVolumeReclaimPolicy: Retain
      storageClassName: local-storage
      local:
        path: /apigee/data
      nodeAffinity:
        "required":
          "nodeSelectorTerms":
          - "matchExpressions":
            - "key": "kubernetes.io/hostname"
              "operator": "In"
              "values": ["ip-10-30-1-36.ec2.internal"]
  4. 将值替换为新的主机名/IP,并应用模板:
    kubectl apply -f volume-template.yaml

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

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

创建客户端容器

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

  1. 容器使用 apigee-cassandra-user-setup pod 中的 TLS 证书。第一步是提取此证书名称:
    kubectl get secrets -n apigee |grep "kubernetes.io/tls"|grep apigee-cassandra-user-setup|awk '{print $1}'

    此命令返回证书名称。例如:apigee-cassandra-user-setup-rg-hybrid-b7d3b9c-tls

  2. 接下来,提取数据存储区密钥名称:
    kubectl get secrets -n apigee | grep "datastore.*-creds" | awk '{print $1}' 
  3. 打开一个新文件,并将以下 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: "google/apigee-hybrid-cassandra-client:1.5.0"
        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: default-datastore-creds  # The datastore secret name fetched previously.
        - name: APIGEE_DML_PASSWORD
          valueFrom:
            secretKeyRef:
              key: dml.password
              name: default-datastore-creds  # The datastore secret name fetched previously.
        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
  4. 使用 .yaml 扩展名保存文件。例如:my-spec.yaml
  5. 将规范应用到您的集群:
    kubectl apply -f your-spec-file.yaml -n apigee
  6. 登录容器:
    kubectl exec -n apigee cassandra-client -it -- bash
  7. 使用以下命令连接到 Cassandra cqlsh 接口。输入如下所示的命令:
    cqlsh ${CASSANDRA_SEEDS} -u ${APIGEE_DML_USER} -p ${APIGEE_DML_PASSWORD} --ssl

删除客户端 pod

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

kubectl delete pods -n apigee cassandra-client