Cassandra 복원 문제 해결

ApigeeApigee Hybrid 문서입니다.
이 주제에 해당하는 Apigee Edge 문서가 없습니다.

증상

Apigee Hybrid에서 Cassandra 복원을 수행하는 동안 복원 로그에 오류가 표시될 수 있습니다.

오류 메시지

로그에 다음 중 하나가 표시됩니다.

java.net.ConnectException: Connection timed out (Connection timed out)
/tmp/tmp/schema.cql:662:OperationTimedOut: errors={'10.0.0.1': 'Client request timeout. See Session.execute[_async](timeout)'}, last_host=10.0.0.1
/tmp/tmp/schema.cql:6409:AlreadyExists: Table 'kvm_myorg.kvm_map_keys_descriptor' already exists

가능한 원인

원인 설명 다음에 관한 문제 해결 안내
연결 시간 초과 이 오류는 apigee-cassandra-restore 포드와 apigee-cassandra-default-* 포드 간의 연결 오류입니다. Apigee Hybrid
작업 시간을 초과했습니다. 15분 후 복원이 타임아웃되면 이 오류가 발생합니다. Apigee Hybrid
이미 존재함 이 오류 메시지는 문제의 원인과 관련이 없으며 복원 작업 재시도 작업의 결과입니다. Apigee Hybrid

원인: 연결 타임아웃

다음 오류는 apigee-cassandra-restore 포드와 apigee-cassandra-default-* 포드 간의 연결 오류입니다.

java.net.ConnectException: Connection timed out (Connection timed out)

진단

  1. 포드 네트워크에서 호스트 네트워크에 연결할 수 없는 경우 백업에서 리전 복원에 나와 있는 것처럼 overrides.yamlcassandra 아래에서 hostNetworkfalse로 설정되어 있는지 확인합니다.
  2. 연결을 테스트하려면 apigee-cassandra-restore 작업과 동일한 네트워크에 있는 apigee-mart 또는 apigee-runtime 포드에 로그인합니다. 포드 네트워크에서 다른 포드를 사용할 수도 있습니다.
    1. apigee-mart 포드의 이름을 가져옵니다.
      kubectl -n apigee get po --selector=app=apigee-mart --no-headers -o custom-columns=":metadata.name"
    2. mart 포드 내에서 bash 세션을 실행합니다.
      kubectl exec -it MART_POD_NAME -n apigee -- bash

      MART_POD_NAME을 MART 포드의 이름으로 바꿉니다. 예를 들면 apigee-mart-myorg--9a8228a-191-t0xh1-qz5fl입니다.

    3. Cassandra 포트에 대해 연결 테스트를 실행합니다.
      curl -v -m 5 telnet://apigee-cassandra-default-0.apigee-cassandra-default.apigee.svc.cluster.local:9042
      curl -v -m 5 telnet://apigee-cassandra-default-0.apigee-cassandra-default.apigee.svc.cluster.local:7001

    출력에 Connection timed out 오류가 표시되면 연결 문제가 있는 것입니다. 하지만 Connected to 메시지가 표시되면 연결에 성공한 것입니다. Ctrl+C를 눌러 연결을 닫고 계속 진행해야 합니다.

해결 방법

복원에 사용되는 overrides.yaml 파일에서 HostNetwork 설정이 false로 설정되어 있는지 확인하고 복원 프로세스를 반복합니다. 설정이 이미 false로 설정되어 있지만 연결 오류가 표시되면 다음 명령어를 사용하여 Cassandra 포드가 작동되어 실행되는지 확인합니다.

kubectl get pods -n apigee -l app=apigee-cassandra

다음 예시와 같은 출력이 표시됩니다.

NAME                         READY   STATUS    RESTARTS   AGE
apigee-cassandra-default-0   1/1     Running   0          14m
apigee-cassandra-default-1   1/1     Running   0          13m
apigee-cassandra-default-2   1/1     Running   0          11m
exampleuser@example hybrid-files %

원인: 작업 타임아웃

15분 후 복원이 타임아웃되면 다음 오류가 발생합니다. 이 오류는 스토리지 및 네트워크가 압축되지 않은 백업 내용을 제시간에 전송할 수 없는 등의 I/O 문제를 나타냅니다.

/tmp/tmp/schema.cql:662:OperationTimedOut: errors={'10.0.0.1': 'Client
request timeout. See Session.execute[_async](timeout)'}, last_host=10.0.0.1

진단

  1. apigee-cassandra-default-0 로그에서 복원 시작의 타임스탬프를 확인합니다.

    kubectl logs apigee-cassandra-default-0 -n apigee | grep 'MigrationManager.java' | head -n 1
  2. 타임스탬프를 최신 테이블 생성 로그와 비교합니다.

    kubectl logs apigee-cassandra-default-0 -n apigee | grep 'Create new table' | tail -n 1

    이 비교 결과는 Cassandra 포드가 제한 시간을 초과한 후에도 테이블을 만드는 중임을 보여줍니다.

  3. 다음 명령어를 사용하여 스토리지 대역폭을 테스트합니다.

    kubectl -n apigee exec -it apigee-cassandra-default-0 -- bash -c 'dd if=/dev/zero of=/opt/apigee/data/test.img bs=200M count=1 ; rm /opt/apigee/data/test.img'
    kubectl -n apigee exec -it apigee-cassandra-default-1 -- bash -c 'dd if=/dev/zero of=/opt/apigee/data/test.img bs=200M count=1 ; rm /opt/apigee/data/test.img'
    kubectl -n apigee exec -it apigee-cassandra-default-2 -- bash -c 'dd if=/dev/zero of=/opt/apigee/data/test.img bs=200M count=1 ; rm /opt/apigee/data/test.img'

    쓰기 속도가 100M/s 미만이면 사용된 적절한 StorageClass(SSD)가 부족하다는 의미일 수 있습니다.

  4. 네트워킹 대역폭을 테스트합니다.

    1. Cassandra 포드에서 netcat을 실행하여 포트에서 리슨합니다.

      kubectl -n apigee exec -it apigee-cassandra-default-0 -- bash -c 'nc -l -p 3456 > /dev/null'
    2. 별도의 셸 세션에서 apigee-mart 포드 이름을 가져옵니다.

      kubectl -n apigee get po --selector=app=apigee-mart --no-headers -o custom-columns=":metadata.name"
    3. apigee-mart 포드 내에서 bash 세션을 실행합니다. 포드 네트워크에서 다른 포드를 사용할 수도 있습니다.

      kubectl exec -it MART_POD_NAME -n apigee -- bash

      MART_POD_NAME을 MART 포드의 이름으로 바꿉니다. 예를 들면 apigee-mart-myorg--9a8228a-191-t0xh1-qz5fl입니다.

    4. 아직 netcat을 실행 중인 Cassandra 포드에 대해 네트워크 대역폭 테스트를 실행합니다.

      dd if=/dev/zero bs=50M count=1 | nc apigee-cassandra-default-0.apigee-cassandra-default.apigee.svc.cluster.local 3456

    다른 Cassandra 포드에 대해 이 프로세스를 반복할 수 있습니다. 결과 속도가 10M/s 미만이면 네트워크 대역폭이 문제 원인일 가능성이 가장 높습니다.

해결 방법

위 단계를 통해 느린 I/O 속도가 확인되면 클러스터가 최소 네트워크스토리지 요구사항을 충족하는지 확인합니다. 그런 다음 대역폭을 다시 테스트합니다.

원인: 이미 존재함

진단

다음과 비슷한 오류가 표시됩니다.

/tmp/tmp/schema.cql:6409:AlreadyExists: Table 'kvm_myorg.kvm_map_keys_descriptor' already exists

해결 방법

이 오류 메시지는 문제의 원인과 관련이 없으며 복원 작업 재시도 작업의 결과입니다. 실제 오류 메시지는 실패한 첫 번째 포드 로그에 표시됩니다.

문제를 진단하려면 초기 실패에서 로그를 가져옵니다.

문제가 계속되면 진단 정보를 수집해야 함으로 이동합니다.

알려진 문제 391861216 해결 방법

진단

복원 후 번호가 가장 높은 Cassandra 포드가 CrashLoopBackoff 상태입니다. 이는 알려진 문제 391861216으로 인해 발생할 수 있습니다. Cassandra 포드 로그에 다음과 유사한 오류가 표시됩니다.

Cannot change the number of tokens from 512 to 256

해결 방법

다음 단계를 수행하여 근본 문제를 해결합니다. 이렇게 하면 데이터를 보존하면서 Cassandra를 정상적으로 시작할 수 있습니다.

  1. CrashLoopBackoff 상태로 멈춰 있는 Cassandra 포드의 PVC를 삭제합니다. POD_NAMECrashLoopBackoff 상태의 포드 이름으로 설정합니다. APIGEE_NAMESPACE를 Apigee가 설치된 클러스터의 네임스페이스로 설정합니다.

    kubectl delete pvc cassandra-data-POD_NAME -n APIGEE_NAMESPACE --wait=false
  2. CrashLoopBackoff 상태의 포드를 삭제합니다.

    kubectl delete pod POD_NAME -n APIGEE_NAMESPACE
  3. 수동으로 Cassandra의 시드 호스트를 번호가 가장 높은 포드로 변경합니다. 예를 들어 복제본이 3개 있으면 SEED_POD_NAMEapigee-cassandra-default-2이어야 합니다. 이 작업은 한 번만 필요하며 후속 포드에서는 건너뛸 수 있습니다.

    kubectl patch apigeeds/default -n APIGEE_NAMESPACE --type='merge' -p '{"spec": {"components": {"cassandra": {"properties": {"externalSeedHost":"SEED_POD_NAME.apigee-cassandra-default.APIGEE_NAMESPACE.svc.cluster.local"}}}}}'
  4. Cassandra 링에서 토큰 512개가 있는 노드를 삭제합니다.

    kubectl exec -n APIGEE_NAMESPACE -t sts/apigee-cassandra-default -c apigee-cassandra -- bash -c 'nodetool -u $APIGEE_JMX_USER -pw $APIGEE_JMX_PASSWORD status' | awk '/^DN .*\?.* 512 / {print $6; exit}; /^DN .* [KMG]iB.* 512 / {print $7; exit}' | xargs -I {} kubectl exec -n APIGEE_NAMESPACE -t sts/apigee-cassandra-default -c apigee-cassandra -- bash -c 'nodetool -u $APIGEE_JMX_USER -pw $APIGEE_JMX_PASSWORD removenode {}'
  5. Cassandra 포드가 복구되고 2회 이상 다시 시작되고 2/2Ready 상태에 도달할 때까지 기다립니다. 그러면 다음으로 높은 포드가 CrashLoopBackoff 상태로 전환됩니다.

    kubectl get pods -n APIGEE_NAMESPACE -l app=apigee-cassandra -w
  6. POD_NAME을 업데이트하고 잔여 포드가 CrashLoopBackoff 상태로 전환될 때마다 한 번에 하나씩 잔여 포드에 앞선 이전 단계를 반복합니다. 모든 포드가 2/2Ready 상태이고 Running 상태가 전환될 때까지 계속합니다.

  7. 모든 포드가 Cassandra 링에 성공적으로 조인했는지 확인합니다.

    kubectl exec -n APIGEE_NAMESPACE -t sts/apigee-cassandra-default -c apigee-cassandra -- bash -c 'nodetool -u $APIGEE_JMX_USER -pw $APIGEE_JMX_PASSWORD status'

    모든 Cassandra 노드는 UN 상태이고 토큰은 256개여야 합니다.

  8. Cassandra의 시드 호스트 변경사항을 되돌립니다.

    kubectl patch apigeeds/default -n APIGEE_NAMESPACE --type='merge' -p '{"spec": {"components": {"cassandra": {"properties": {"externalSeedHost":""}}}}}'

    Apigee Datastore 컨트롤러에서 시드 호스트 변경사항을 되돌리면서 Cassandra 포드를 다시 시작합니다.

진단 정보 수집 필요

위 안내를 따른 후에도 문제가 지속되면 다음 진단 정보를 수집한 후 Google Cloud Customer Care에 문의하세요.

  1. 요청 받은 일반적인 데이터 외에도 다음 명령어를 사용하여 모든 Cassandra Pod에서 진단 데이터를 수집합니다.

    for p in $(kubectl -n apigee get pods -l app=apigee-cassandra --no-headers -o custom-columns=":metadata.name") ; do \
            for com in info describecluster failuredetector version status ring info gossipinfo compactionstats tpstats netstats cfstats proxyhistograms gcstats ; do kubectl \
            -n apigee exec ${p} -- bash -c 'nodetool -u $APIGEE_JMX_USER -pw $APIGEE_JMX_PASSWORD '"$com"' 2>&1 '\
            | tee /tmp/k_cassandra_nodetool_${com}_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt | head -n 40 ; echo '...' ; done; done
          
  2. 압축하고 지원 케이스에 제공합니다.

    tar -cvzf /tmp/cassandra_data_$(date +%Y.%m.%d_%H.%M.%S).tar.gz /tmp/k_cassandra_nodetool*
  3. 복원 포드에서 로그를 수집하고 제공합니다. 로그는 단기 지속되므로 실패 직후에 수집해야 합니다.
  4. 위의 진단 단계를 수행한 경우 모든 콘솔 출력을 수집하여 파일로 복사하고 지원 케이스에 첨부합니다.