Google Cloud Apigee 支持案例最佳做法

您正在查看 ApigeeApigee Hybrid 文档。
查看 Apigee Edge 文档。

在支持案例中提供详细信息和必填信息,以便 Google Cloud 支持团队能够快速而高效地回复您。如果您的支持请求缺少关键细节,我们会要求您提供更多信息,而这可能会反复多次出现。这将花费更长时间,并且可能会导致问题解决的延迟。本最佳实践指南帮助您了解我们需要哪些信息来解决技术支持案例,以便更快地加以解决。

描述问题

问题应包含有关问题发生原因与预期结果、发生时间和方式的详细信息。一个出色的支持请求应包含每个 Apigee 产品的以下关键信息:

关键信息 说明 Google Cloud 上的 Apigee Apigee Hybrid
产品 发现问题的具体 Apigee 产品,包括适用的版本信息。
  • Hybrid 版本
问题详情 清晰而详细的问题描述可勾勒出问题框架,包括完整的错误消息(如果有)
  • 错误消息
  • 调试工具输出
  • 重现问题的步骤
  • 完整的 API 请求/命令
  • 错误消息
  • 调试工具输出
  • 重现问题的步骤
  • 完整的 API 请求/命令
  • 组件诊断日志
  • Cloud Monitoring 指标
时间 问题出现的具体时间戳及其持续时长。
  • 问题出现的日期、时间和时区
  • 问题持续的时长
  • 问题出现的日期、时间和时区
  • 问题持续的时长
设置 被发现问题的详细信息。
  • 组织名称
  • 环境名称
  • API 代理名称
  • 修订版本

以下各个部分详细介绍了这些概念。

产品

Apigee 包括 Google Cloud 上的 ApigeeApigee Hybrid 这两种不同的产品,因此我们需要您提供出现问题的产品的具体信息。

下表给出了一些示例,这些示例展示了 DOs 列中的完整信息,以及 DON'Ts 列中不完整的信息:

DOs DON'Ts
API 代理 OAuth2Google Cloud 上的 Apigee 组织部署失败…

API 代理部署失败

(我们需要知道您在哪个 Apigee 产品发现的该问题。)

我们在 Apigee Hybrid 1.3 版上使用 cqlsh 访问 Cassandra 时,收到以下错误…

我们无法通过 cqlsh 访问 Cassandra。

(缺少混合版本信息)

问题详情

提供有关所遇问题的确切信息,包括错误消息(如果有)以及观察到的预期行为和实际行为。

下表给出了一些示例,这些示例展示了 DOs 列中的完整信息,以及 DON'Ts 列中不完整的信息:

DOs DON'Ts

新的 edgemicro 代理 edgemicro_auth 失败,并显示以下错误:

{"error":"missing_authorization","error_description":"Missing Authorization header"}

今天新创建的 edgemicro 代理无法运行

(代理名称未知。不清楚代理会返回错误还是意外响应。)

在向 API 代理发送请求时,我们的客户端收到 500 错误,并显示以下错误消息:

{"fault":{"faultstring":"Execution of JSReadResponse failed with error: Javascript runtime error: \"TypeError: Cannot read property \"content\" from undefined. (JSReadResponse.js:23)","detail":{"errorcode":"steps.javascript.ScriptExecutionFailed"}}}

在向 API 代理发送请求时,我们的客户端收到 500 错误。

(仅传达 500 错误并不足以为我们调查该问题提供足够的信息。我们需要了解所观察到的实际错误消息和错误代码。)

时间

时间是一条非常重要的信息。请务必为支持工程师提供以下信息:您首次发现此问题的时间、问题持续时长以及该问题是否仍然存在。

负责解决该问题的支持工程师可能与您不在同一个时区,因此有关时间的相对表述会使问题更难诊断。因此,建议使用 ISO 8601 格式来表示日期和时间戳,以提供问题出现时的确切时间信息。

下表给出了一些示例,这些示例展示了 DOs 列出现该问题的准确时间和持续时长,以及 DON'Ts 列中关于问题出现时间的一些模糊或不确定消息:

DOs DON'Ts
昨天在 2020-11-06 17:30 PDT2020-11-06 17:35 PDT 期间发现了大量的 503s

昨天下午 5:30 发现了大量 503s,时长持续了 5 分钟。

(我们不得不使用隐含日期,且未明确说明此问题发生在哪个时区。)

2020-11-09 15:30 IST2020-11-09 18:10 IST 在以下 API 代理上出现长延迟时间现象…

某些 API 代理上周出现了高延迟现象。

(目前尚不清楚在上周观察到该问题的具体日期和问题持续时长。)

设置

我们需要知道该问题出现的确切位置。 根据您使用的产品,我们需要以下信息:

  • 如果您使用的是 Google Cloud 上的 Apigee,则可能拥有多个组织,因此我们需要知道问题出现的具体组织和其他详细信息:
    • 组织和环境名称
    • API 代理名称和修订版本号(用于 API 请求失败)
  • 如果您使用的是 Hybrid,那么您可能正在使用多个受支持的 Hybrid 平台和安装拓扑之一。因此,我们需要了解您正在使用的 Hybrid 平台和拓扑,包括数据中心数量和节点等详细信息。

下表给出了一些示例,这些示例展示了 DOs 列中的完整信息,以及 DON'Ts 列中不完整的信息:

DOs DON'Ts

2020-11-06 09:30 CST 以来,Google Cloud 上的 Apigee 中的 401 错误有所增加。

Apigee 设置详情

失效 API 的详细信息如下所示:
  组织名称:myorg
  环境名称:test
  API 代理名称:myproxy
  修订版本号:3

错误

{"fault":{"faultstring":"Failed to resolve API Key variable request.header.X-APP-API_KEY","detail":{"errorcode":"steps.oauth.v2.FailedToResolveAPIKey"}}}

401 错误增多。

(其不会提供有关所用产品的任何信息,因为当时正在查看问题或任何设置详情。)

Apigee Hybrid 1.3 版上调试失败并显示以下错误:

错误

Error while Creating trace session for corp-apigwy-discovery, revision 3, environment dev.

Failed to create DebugSession {apigee-hybrid-123456 dev corp-apigwy-discovery 3 ca37384e-d3f4-4971-9adb-dcc36c392bb1}

Apigee Hybrid 设置详情

  • Apigee Hybrid 平台
      Anthos GKE On-Prem 1.4.0 版本
  • Google Cloud 项目、Hybrid 组织和环境
      Google Cloud 项目 ID:apigee-hybrid-123456
      Apigee Hybrid 组织:apigee-hybrid-123456
      Apigee Hybrid 环境:dev
  • Kubernetes 集群名称详细信息
      k8sCluster:
      名称:user-cluster-1
      区域:us-east1
  • 网络拓扑
    附加文件 network-topology.png
Apigee Hybrid 上调试失败。

有用的文件

向我们提供与问题相关的工件可加快解决速度,因为这样能帮助我们了解您观察到的确切行为,从而深入了解此问题。

本部分介绍了一些适用于所有 Apigee 产品的实用工件:

适用于所有 Apigee 产品的通用工件

以下工件适用于所有 Apigee 产品:Google Cloud 上的 ApigeeApigee Hybrid

工件 说明
调试工具输出 调试工具输出包含有关流经 Apigee 产品的 API 请求的详细信息。这适用于所有运行时错误,例如 4XX5XX 和延迟问题。
屏幕截图 屏幕截图有助于传达观察到的实际行为或错误的上下文。这对观察到的所有错误或问题(例如在界面或 Analytics 中)都非常有用。
HAR (Http ARchive) HAR 是一个由 HTTP 会话工具捕获的文件,用于调试与界面相关的问题。该文件可通过 Chrome、Firefox 或 Internet Explorer 等浏览器捕获。
tcpdumps tcpdump 工具会捕获通过网络传输或接收的 TCP/IP 数据包。这对任何网络相关的问题(例如 TLS 握手失败、502 错误和延迟问题等)都非常有用。

Hybrid 的额外工件

对于 Hybrid,我们还可能需要一些额外的工件,以便更快地诊断问题。

工件 说明
Apigee Hybrid 平台 指定使用以下任何受支持的 Hybrid 平台
  • GKE
  • GKE On-Prem
  • AKS(Azure Kubernetes Service)
  • Amazon EKS
  • GKE on AWS
Apigee Hybrid 和依赖项组件版本
  • Apigee hybrid CLI 版本
    apigeectl 版本
  • Apigee Connect Agent 版本
    kubectl -n=apigee get pods -l app=apigee-connect-agent -o=json | jq '.items[].spec.containers[].image'
  • Apigee MART 版本
    kubectl -n=apigee get pods -l app=apigee-mart -o=json | jq '.items[].spec.containers[].image'
  • Apigee Synchronizer 版本
    kubectl -n=apigee get pods -l app=apigee-synchronizer -o=json | jq '.items[].spec.containers[].image'
  • Apigee Cassandra 版本
    kubectl -n=apigee get pods -l app=apigee-cassandra -o=json | jq '.items[].spec.containers[].image'
  • Apigee 运行时版本
    kubectl -n=apigee get pods -l app=apigee-runtime -o=json | jq '.items[].spec.containers[].image'
  • Kubernetes CLI 和服务器版本
    kubectl 版本
  • Istio CLI 和服务器版本
    istioctl 版本
网络拓扑 介绍 Hybrid 设置的 Apigee 安装拓扑图,包括所有数据中心、Kubernetes 集群、命名空间和 pod。
替换 YAML 文件 每个数据中心中用于安装 Apigee Hybrid 运行时平面的 overrides.yaml 文件。
Apigee Hybrid 部署的状态

每个数据中心/ Kubernetes集群中以下命令的输出:

kubectl get pods -A
kubectl get services -A

Apigee Hybrid 组件日志

为 Hybrid 组件提供到 StackDriver 日志的链接,或

您可在每个数据中心/Kubernetes 集群中使用以下命令提取 Apigee Hybrid 组件日志:

kubectl -n {namespace} get pods
kubectl -n {namespace} logs {pod-name}

  • Apigee Connect Agent 日志
    kubectl -n {namespace} get pods
    kubectl -n {namespace} logs {apigee-connect-agent-pod-name}
  • MART 日志
    kubectl -n {namespace} get pods
    kubectl -n {namespace} logs {apigee-mart-pod-name}
  • 同步器日志
    kubectl -n {namespace} get pods
    kubectl -n {namespace} logs {synchronizer-pod-name}
  • Apigee Cassandra 日志
    kubectl -n {namespace} get pods
    kubectl -n {namespace} logs {apigee-cassandra-pod-name}
  • MP/Apigee 运行时日志(所有 apigee-runtime pod)
    kubectl -n {namespace} get pods
    kubectl -n {namespace} logs {apigee-runtime-pod-name}
说明日志

关于 pod 的详细信息。

此方法对于 pod 处于 CrashLoopBackoff 状态等问题尤其有用。

kubectl -n apigee describe pod {pod-name}

Cloud Monitoring
  • 链接到指标信息中心
  • 与 Cloud Monitoring 指标相关的所有信息中心的快照。

Apigee Hybrid Must-Gather

您还可以根据下列命令执行 Must-Gather 脚本;

###--- "kubectl config" commands to get the config details of the whole Apigee Hybrid cluster ---####

kubectl config get-clusters 2>&1 | tee /tmp/k_config_get_clusters_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl config get-contexts 2>&1 | tee /tmp/k_config_get_contexts_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl config get-users 2>&1 | tee /tmp/k_config_get_users_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl config view 2>&1 | tee /tmp/k_config_view_$(date +%Y.%m.%d_%H.%M.%S).txt

### --- Collect all details of all nodes in the Kubernetes cluster.---###

kubectl describe node 2>&1 |  tee /tmp/k_describe_node_$(date +%Y.%m.%d_%H.%M.%S).txt

###--- "kubectl get -A " commands to get CRD details for the whole Apigee Hybrid setup ---####

kubectl get clusterissuers -A -o wide 2>&1 | tee /tmp/k_get_clusterissuers_all$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get certificate -A -o wide 2>&1 | tee /tmp/k_get_certificate_all_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get certificaterequest -A -o wide 2>&1 | tee /tmp/k_get_certificaterequest_all_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get crd -A 2>&1 | tee /tmp/k_get_crd_all_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get ConfigMap -A 2>&1 | tee /tmp/k_get_ConfigMap_all_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get ClusterRole -A -o wide 2>&1 | tee /tmp/k_get_clusterrole_all_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get ClusterRoleBinding -A -o wide 2>&1 | tee /tmp/k_get_clusterrole_binding_all_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get Deployments -A -o wide >&1 | tee /tmp/k_get_deployments_all_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get events -A -o wide 2>&1 | tee /tmp/k_get_events_all_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get endpoints -A  2>&1 | tee /tmp/k_get_endpoints_all_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get issuers -A -o wide 2>&1 | tee /tmp/k_get_issuers_all_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get mutatingwebhookconfigurations  2>&1 | tee /tmp/k_get_mutatingwebhookconfigurations_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get nodes -o wide --show-labels 2>&1 | tee /tmp/k_get_nodes_labels_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get ns 2>&1 | tee /tmp/k_get_namespace_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get PriorityClass -A -o wide 2>&1 | tee /tmp/k_get_PriorityClass_all_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get pv -A -o wide 2>&1 | tee /tmp/k_get_pv_all_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get pvc -A -o wide 2>&1 | tee /tmp/k_get_pvc_all_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get Role -A -o wide 2>&1 | tee /tmp/k_get_role_all_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get RoleBinding -A -o wide 2>&1 | tee /tmp/k_get_Role_Binding_all_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get replicaset -A -o wide 2>&1 | tee /tmp/k_get_replicaset_all_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get sa -A -o wide 2>&1 | tee /tmp/k_get_service_accounts_all_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get services -A -o wide 2>&1 | tee /tmp/k_get_services_all_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get svc -A 2>&1 | tee /tmp/k_get_svc_all$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get secrets -A 2>&1 | tee /tmp/k_get_secrets_all_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get validatingwebhookconfigurations -A  2>&1  | tee /tmp/k_get_validatingwebhookconfigurations_all$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get validatingwebhookconfigurations apigee-validating-webhook-configuration 2>&1  | tee /tmp/k_get_apigee-validating-webhook-configuration_$(date +%Y.%m.%d_%H.%M.%S).txt

### --- List top resource consuming nodes and pods ---####

kubectl top nodes 2>&1 | tee /tmp/k_top_nodes_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl top pod -A --containers 2>&1 | tee /tmp/k_top_pod_all_containers_$(date +%Y.%m.%d_%H.%M.%S).txt

###----- "kubectl get" commands to fetch list of all CRD for "apigee" namespace ----- #####

kubectl get all -n apigee -o wide 2>&1 | tee /tmp/k_get_all_n_apigee_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get ad -n apigee 2>&1 | tee /tmp/k_get_ad_n_apigee_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get apigeeorganization -n apigee 2>&1 | tee /tmp/k_get_apigeeorganization_n_apigee_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get apigeeenv -n apigee  2>&1 | tee /tmp/k_get_apigeeenv_n_apigee_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get apigeeds -n apigee  2>&1 | tee /tmp/k_get_apigeeds_n_apigee_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get apigeedatastore -n apigee 2>&1 | tee /tmp/k_get_apigeedatastore_n_apigee_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get ApigeeDeployment -n apigee 2>&1 | tee /tmp/k_get_apigeedeployment_n_apigee_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get ApigeeRedis -n apigee 2>&1 | tee /tmp/k_get_ApigeeRedis_n_apigee_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get ApigeeRoute -n apigee 2>&1 | tee /tmp/k_get_ApigeeRoute_n_apigee_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get ApigeeRouteConfig -n apigee 2>&1 | tee /tmp/k_get_ApigeeRoutesconfig_n_apigee_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get Apigeetelemetry -n apigee 2>&1 | tee /tmp/k_get_Apigeetelemetry_n_apigee_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get apigeeissues -n apigee 2>&1 | tee /tmp/k_get_apigeeissues_n_apigee_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get ControllerRevision -n apigee -o wide 2>&1 | tee /tmp/k_get_ControllerRevision_n_apigee_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get cronjob -n apigee -o wide 2>&1 | tee /tmp/k_get_cronjob_n_apigee_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get gateway -n apigee 2>&1 | tee /tmp/k_get_gateway_n_apigee_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get PodDisruptionBudget -n apigee -o wide 2>&1 | tee /tmp/k_get_PodDisruptionBudget_n_apigee_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get sc -n apigee -o wide 2>&1 | tee /tmp/k_get_storageclass_n_apigee_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get sts -n apigee 2>&1 | tee /tmp/k_get_sts_n_apigee_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get volumesnapshot -n apigee -o wide 2>&1 | tee /tmp/k_get_volumesnapshot_n_apigee_$(date +%Y.%m.%d_%H.%M.%S).txt

###----- "kubectl describe" commands to fetch details of all CRD for "apigee" namespace ----- #####

for p in $(kubectl -n apigee get apigeeorganization --no-headers -o custom-columns=":metadata.name") ; do kubectl describe apigeeorganization ${p} -n apigee 2>&1 | tee /tmp/k_desc_apigeeorganization_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get apigeeenv --no-headers -o custom-columns=":metadata.name") ; do kubectl describe apigeeenv ${p} -n apigee 2>&1 | tee /tmp/k_desc_apigeeenv_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get apigeeds --no-headers -o custom-columns=":metadata.name") ; do kubectl describe apigeeds ${p} -n apigee 2>&1 | tee /tmp/k_desc_apigeeds_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get apigeedatastore --no-headers -o custom-columns=":metadata.name") ; do kubectl describe apigeedatastore ${p} -n apigee 2>&1 | tee /tmp/k_desc_apigeedatastore_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get ApigeeDeployment --no-headers -o custom-columns=":metadata.name") ; do kubectl describe ApigeeDeployment ${p} -n apigee 2>&1 | tee /tmp/k_desc_ApigeeDeployment_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get ApigeeRedis --no-headers -o custom-columns=":metadata.name") ; do kubectl describe ApigeeRedis ${p} -n apigee 2>&1 | tee /tmp/k_desc_ApigeeRedis_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get ApigeeRoute --no-headers -o custom-columns=":metadata.name") ; do kubectl describe ApigeeRoute ${p} -n apigee 2>&1 | tee /tmp/k_desc_ApigeeRoute_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get ApigeeRouteConfig --no-headers -o custom-columns=":metadata.name") ; do kubectl describe ApigeeRouteConfig ${p} -n apigee 2>&1 | tee /tmp/k_desc_ApigeeRouteConfig_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get Apigeetelemetry --no-headers -o custom-columns=":metadata.name") ; do kubectl describe Apigeetelemetry ${p} -n apigee 2>&1 | tee /tmp/k_desc_Apigeetelemetry_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get apigeeissues --no-headers -o custom-columns=":metadata.name") ; do kubectl describe apigeeissues ${p} -n apigee 2>&1 | tee /tmp/k_desc_apigeeissues_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get ControllerRevision --no-headers -o custom-columns=":metadata.name") ; do kubectl -n apigee describe ControllerRevision ${p} 2>&1 | tee /tmp/k_desc_ControllerRevision_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get certificate --no-headers -o custom-columns=":metadata.name") ; do kubectl describe certificate ${p} -n apigee 2>&1 | tee /tmp/k_desc_certificate_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get cronjob --no-headers -o custom-columns=":metadata.name") ; do kubectl describe cronjob ${p} -n apigee 2>&1 | tee /tmp/k_desc_cronjob_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get daemonset --no-headers -o custom-columns=":metadata.name") ; do kubectl -n apigee describe daemonset ${p} 2>&1 | tee /tmp/k_desc_daemonset_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get deployments --no-headers -o custom-columns=":metadata.name") ; do kubectl -n apigee describe deployments ${p} 2>&1 | tee /tmp/k_desc_deployment_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get hpa --no-headers -o custom-columns=":metadata.name") ; do kubectl describe hpa ${p} -n apigee 2>&1 | tee /tmp/k_desc_hpa_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get jobs --no-headers -o custom-columns=":metadata.name") ; do kubectl describe jobs ${p} -n apigee 2>&1 | tee /tmp/k_desc_jobs_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get po --no-headers -o custom-columns=":metadata.name") ; do kubectl -n apigee describe po ${p} 2>&1 | tee /tmp/k_desc_pod_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get PodDisruptionBudget --no-headers -o custom-columns=":metadata.name") ; do kubectl -n apigee describe PodDisruptionBudget ${p} 2>&1 | tee /tmp/k_desc_PodDisruptionBudget_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get pv --no-headers -o custom-columns=":metadata.name") ; do kubectl -n apigee describe pv ${p} 2>&1 | tee /tmp/k_desc_pv_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt; done
for p in $(kubectl -n apigee get pvc --no-headers -o custom-columns=":metadata.name") ; do kubectl -n apigee describe pvc ${p} 2>&1 | tee /tmp/k_desc_pvc_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt; done
for p in $(kubectl -n apigee get rs --no-headers -o custom-columns=":metadata.name") ; do kubectl describe rs ${p} -n apigee 2>&1 | tee /tmp/k_desc_replicaset_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get sc --no-headers -o custom-columns=":metadata.name") ; do kubectl -n apigee describe sc ${p} 2>&1 | tee /tmp/k_desc_storageclass_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt; done
for p in $(kubectl -n apigee get sts --no-headers -o custom-columns=":metadata.name") ; do kubectl describe sts ${p} -n apigee 2>&1 | tee /tmp/k_desc_sts_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get secrets --no-headers -o custom-columns=":metadata.name") ; do kubectl -n apigee describe secrets ${p} 2>&1 | tee /tmp/k_desc_secrets_n_apigee${p}_$(date +%Y.%m.%d_%H.%M.%S).txt; done
for p in $(kubectl -n apigee get services --no-headers -o custom-columns=":metadata.name") ; do kubectl describe service ${p} -n apigee 2>&1 | tee /tmp/k_desc_services_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get sa --no-headers -o custom-columns=":metadata.name") ; do kubectl describe sa ${p} -n apigee 2>&1 | tee /tmp/k_desc_service_account_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee get svc --no-headers -o custom-columns=":metadata.name") ; do kubectl describe svc ${p} -n apigee 2>&1 | tee /tmp/k_desc_svc_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done

###----- "kubectl logs" command to fetch logs of all containers in the "apigee" namespace ----- #####

for p in $(kubectl -n apigee get po --no-headers -o custom-columns=":metadata.name") ; do kubectl -n apigee logs ${p} --all-containers 2>&1 | tee /tmp/k_logs_n_apigee_${p}_$(date +%Y.%m.%d_%H.%M.%S).log ; done

###----- "kubectl get" commands for "apigee-system" namespace ----- #####

kubectl get all -n apigee-system -o wide 2>&1 | tee /tmp/k_get_all_n_apigee_system_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get jobs -o wide -n apigee-system 2>&1 | tee /tmp/k_get_jobs_n_apigee_system_$(date +%Y.%m.%d_%H.%M.%S).txt

###----- "kubectl describe" commands for "apigee-system" namespace ----- #####

for p in $(kubectl -n apigee-system get certificate --no-headers -o custom-columns=":metadata.name") ; do kubectl describe certificate ${p} -n apigee-system 2>&1 | tee /tmp/k_desc_certificate_n_apigee_system_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee-system get deployment --no-headers -o custom-columns=":metadata.name") ; do kubectl describe deployment ${p} -n apigee-system 2>&1 | tee /tmp/k_desc_deployment_n_apigee_system_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee-system get jobs --no-headers -o custom-columns=":metadata.name") ; do kubectl describe jobs ${p} -n apigee-system 2>&1 | tee /tmp/k_desc_jobs_n_apigee_system_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee-system get po --no-headers -o custom-columns=":metadata.name") ; do kubectl -n apigee-system describe po ${p} 2>&1 | tee /tmp/k_desc_pod_n_apigee_system_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee-system get rs --no-headers -o custom-columns=":metadata.name") ; do kubectl describe rs ${p} -n apigee-system 2>&1 | tee /tmp/k_desc_replicaset_n_apigee_system_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee-system get rolebinding --no-headers -o custom-columns=":metadata.name") ; do kubectl describe rolebinding ${p} -n apigee-system 2>&1 | tee /tmp/k_desc_rolebinding_n_apigee_system_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee-system get services --no-headers -o custom-columns=":metadata.name") ; do kubectl describe service ${p} -n apigee-system 2>&1 | tee /tmp/k_desc_services_n_apigee_system_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee-system get sa --no-headers -o custom-columns=":metadata.name") ; do kubectl describe sa ${p} -n apigee-system 2>&1 | tee /tmp/k_desc_serviceaccount_n_apigee_system_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n apigee-system get secrets --no-headers -o custom-columns=":metadata.name") ; do kubectl describe secrets ${p} -n apigee-system 2>&1 | tee /tmp/k_desc_secrets_n_apigee_system_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done

###----- "kubectl logs" command for "apigee-system" namespace ----- #####

for p in $(kubectl -n apigee-system get po --no-headers -o custom-columns=":metadata.name") ; do kubectl -n apigee-system logs ${p} --all-containers 2>&1 | tee /tmp/k_logs_n_apigee_system_${p}_$(date +%Y.%m.%d_%H.%M.%S).log ; done

###----- "kubectl get" command for "cert-manager" namespace ----- #####

kubectl get all -n cert-manager -o wide 2>&1 | tee /tmp/k_get_all_n_cert_manager_$(date +%Y.%m.%d_%H.%M.%S).txt
kubectl get crd -n cert-manager 2>&1 | tee /tmp/k_get_crd_n_cert_manager_$(date +%Y.%m.%d_%H.%M.%S).txt

###----- "kubectl describe" command for "cert-manager" namespace ----- #####

for p in $(kubectl -n cert-manager get deployment  --no-headers -o custom-columns=":metadata.name") ; do kubectl -n cert-manager describe deployment $(p) 2>&1 | tee /tmp/k_desc_deployment_n_cert_manager_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n cert-manager get endpoints --no-headers -o custom-columns=":metadata.name") ; do kubectl describe endpoints ${p} -n cert-manager 2>&1 | tee /tmp/k_desc_endpoints_n_cert_manager_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n cert-manager get po --no-headers -o custom-columns=":metadata.name") ; do kubectl -n cert-manager describe po ${p} 2>&1 | tee /tmp/k_desc_po_n_cert_manager_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n cert-manager get rs --no-headers -o custom-columns=":metadata.name") ; do kubectl describe rs ${p} -n cert-manager 2>&1 | tee /tmp/k_desc_replicaset_n_cert_manager_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n cert-manager get sa --no-headers -o custom-columns=":metadata.name") ; do kubectl describe sa ${p} -n cert-manager 2>&1 | tee /tmp/k_desc_serviceaccount_n_cert_manager_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n cert-manager get secrets --no-headers -o custom-columns=":metadata.name") ; do kubectl describe secrets ${p} -n cert-manager 2>&1 | tee /tmp/k_desc_secrets_n_cert_manager_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n cert-manager get services --no-headers -o custom-columns=":metadata.name") ; do kubectl describe service ${p} -n cert-manager 2>&1 | tee /tmp/k_desc_service_n_cert_manager_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done
for p in $(kubectl -n cert-manager get svc --no-headers -o custom-columns=":metadata.name") ; do kubectl describe svc ${p} -n cert-manager 2>&1 | tee /tmp/k_desc_svc_n_cert_manager_${p}_$(date +%Y.%m.%d_%H.%M.%S).txt ; done

###----- "kubectl logs" command for "cert-manager" namespace ----- #####

for p in $(kubectl -n cert-manager get po --no-headers -o custom-columns=":metadata.name") ; do kubectl -n cert-manager logs ${p} --all-containers 2>&1 | tee /tmp/k_logs_n_cert_manager_${p}_$(date +%Y.%m.%d_%H.%M.%S).log ; done

生成日志后,使用以下命令将所有输出文件压缩到一个 tar 归档文件中;

	# tar -cvzf /tmp/apigee_hybrid_logs_$(date +%Y.%m.%d_%H.%M).tar.gz /tmp/k_*

如果 tar 文件的大小超过 25MB,您可以将其上传到 Google 云端硬盘,并与我们分享链接。或者,您也可以使用 split 命令将大型文件拆分为能够上传到支持门户的 25MB 数据块。

	# split -b 25M diagnostic.tar.gz "diagnostic.tar.gz.part"

案例模板和示例案例

本部分根据本文档中介绍的最佳做法为不同产品提供了案例模板和示例案例:

Apigee Cloud

模板

本部分提供了 Apigee on Google Cloud 的示例模板。

问题

<请详细描述您发现的问题或行为。请添加适用的产品名称和版本。>

错误消息

<包括发现的完整错误消息(如果有)>

问题开始时间(ISO 8601 格式):

问题结束时间 (ISO 8601 格式):

Apigee 设置详情
组织名称:
环境名称:
API 代理名称:
修订版本号:

重现步骤

<尽可能重现问题的步骤>

诊断信息:

<已附加文件列表>

示例案例

本部分提供了 Apigee on Google Cloud 的示例案例。

问题

我们在 Public Cloud 组织中看到大量 503 服务不可用错误。您能否调查并解决该问题,或者给出解决方法?

错误消息

{"fault":{"faultstring":"The Service is temporarily available", "detail":{"errorcode":"messaging.adaptors.http.flow.ServiceUnavailable"}}}

问题开始时间 (ISO 8601 格式):2020-10-04 06:30 IST

问题结束时间 (ISO 8601 格式):问题仍然存在。

Apigee Cloud 设置详情
组织名称:myorg
环境名称:dev
API 代理名称:myproxy
修订版本号:3

重现步骤

运行以下 curl 命令以重现该问题:

curl -X GET 'https://myorg-dev.apigee.net/v1/myproxy'

诊断信息:

调试工具输出 (trace-503.xml)

Hybrid

模板

本部分提供了 Apigee Hybrid 的示例模板。

问题

<请详细描述您发现的问题或行为。请添加适用的产品名称和版本。>

错误消息

<包括发现的完整错误消息(如果有)>

问题开始时间(ISO 8601 格式):

问题结束时间 (ISO 8601 格式):

Apigee Hybrid 设置详情

  • Apigee Hybrid 平台

    <提供安装 Hybrid 及其版本的平台信息。>

  • Google Cloud 项目、Hybrid 组织和环境
      Google Cloud 项目 ID:
      <如果您使用的是 Google Kubernetes Engine (GKE),则必须提供集群所在的项目 ID。如果您使用的是 GKE On-Prem、Azure Kubernetes Service 或 Amazon EKS,请提供要在其中发送日志的项目 ID。>
      Apigee Hybrid 组织:
      Apigee Hybrid 环境:
  • Apigee Hybrid 和其他 CLI 版本
      Apigee Hybrid CLI (apigeectl) 版本:
      Kubectl 版本:
  • Kubernetes 集群名称详细信息
      k8sCluster:
      名称:
      区域:
  • 网络拓扑
    <附加介绍 Apigee Hybrid 设置的网络拓扑,包括数据中心、Kubernetes 集群、命名空间和 pod。>
  • 替换 YAML 文件
    <附加替换 YAML 文件。>

重现步骤

<尽可能重现问题的步骤>

诊断信息:

<已附加文件列表>

示例案例

本部分介绍了 Apigee Hybrid 的示例案例。

问题

我们在 Apigee Hybrid 1.3 版本 上执行管理 API 时出现错误。

错误消息

[ERROR] 400 Bad Request
{
"error": {
"code": 400,
"message": "Error processing MART request: INTERNAL_ERROR",
"errors": [
{
"message": "Error processing MART request: INTERNAL_ERROR",
"domain": "global",
"reason": "failedPrecondition"
}
],
"status": "FAILED_PRECONDITION"
}
}

问题开始时间 (ISO 8601 格式):自 2020-10-24 10:30 PDT 开始

问题结束时间 (ISO 8601 格式):继续观察该问题。

Apigee Hybrid 设置详情

  • Apigee Hybrid 平台
    GKE 1.15.1 版
  • Google Cloud 项目、Hybrid 组织和环境
      Google Cloud 项目 ID:apigee-hybrid-123456
      注意:这是集群所在的项目 ID。
      Apigee Hybrid 组织:apigee-hybrid-123456
      Apigee Hybrid 环境:dev
  • Apigee Hybrid 和其他 CLI 版本
      Apigee Hybrid CLI (apigeectl) 版本:
        版本:1.2.0
        提交:ac09109
        构建 ID:214
        构建时间:2020-03-30T20:23:36Z
        Go 版本:go1.12

      Kubectl 版本:
        客户端版本:
    version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.0", GitCommit:"e8462b5b5dc2584fdcd18e6bcfe9f1e4d970a529", GitTreeState:"clean", BuildDate:"2019-06-19T16:40:16Z", GoVersion:"go1.12.5", Compiler:"gc", Platform:"darwin/amd64"}

        服务器版本:
    version.Info{Major:"1", Minor:"14+", GitVersion:"v1.14.10-gke.36", GitCommit:"34a615f32e9a0c9e97cdb9f749adb392758349a6", GitTreeState:"clean",
  • Kubernetes 集群名称详细信息
      k8sCluster:
      名称:user-cluster-1
      区域:us-east1
  • 网络拓扑
    附加文件 network-topology.png
  • 替换 YAML 文件
    附加 overrides.yaml 文件

重现步骤

运行以下管理 API 以发现错误:

curl -X GET --header "Authorization: Bearer <TOKEN>" "https://apigee.googleapis.com/v1/organizations/apigee-hybrid-123456/environments/dev/keyvaluemaps"

诊断信息:

已附加以下文件:

  • network-topology.png
  • overrides.yaml file
  • MART 日志
  • 同步器日志