问题排查

本页面介绍问题排查策略以及一些常见错误的解决方案。

对 Cloud Run for Anthos 进行问题排查时,请先确认您可以在本地运行容器映像

如果您的应用未在本地运行,您将需要对其进行诊断和修复。 您应该使用 Cloud Logging 来帮助调试已部署的项目。

对 Cloud Run for Anthos 进行问题排查时,请参阅以下部分,了解可能的问题解决方案。

此外,请参阅已知问题页面,详细了解 Cloud Run for Anthos 中的已知问题以及如何解决这些问题。

检查命令行输出

如果您使用 Google Cloud CLI,请检查命令输出以确定该命令是否运行成功。例如,如果您的部署未成功终止,则您应该会看到一条错误消息,其中描述了失败的原因。

导致部署失败的最可能原因是清单配置错误或命令不正确。例如,以下输出表明路由流量百分比的总和必须配置为 100。

Error from server (InternalError): error when applying patch:</p><pre>{"metadata":{"annotations":{"kubectl.kubernetes.io/last-applied-configuration":"{\"apiVersion\":\"serving.knative.dev/v11\",\"kind\":\"Route\",\"metadata\":{\"annotations\":{},\"name\":\"route-example\",\"namespace\":\"default\"},\"spec\":{\"traffic\":[{\"configurationName\":\"configuration-example\",\"percent\":50}]}}\n"}},"spec":{"traffic":[{"configurationName":"configuration-example","percent":50}]}}
to:
&{0xc421d98240 0xc421e77490 default route-example STDIN 0xc421db0488 264682 false}
for: "STDIN": Internal error occurred: admission webhook "webhook.knative.dev" denied the request: mutation failed: The route must have traffic percent sum equal to 100.
ERROR: Non-zero return code '1' from command: Process exited with status 1

检查服务的日志

您可以使用 Cloud Logging 或 Google Cloud 控制台中的 Cloud Run for Anthos 页面来检查请求日志和容器日志。如需查看完整的详细信息,请阅读记录和查看日志

如果您使用 Cloud Logging,则需要过滤的资源是 Kubernetes 容器

检查 Service 状态

运行以下命令以获取已部署的 Cloud Run for Anthos 服务的状态:

gcloud run services describe SERVICE

您可以添加 --format yaml(status)--format json(status) 以获取完整状态,例如:

gcloud run services describe SERVICE --format 'yaml(status)'

status 中的条件可帮助您找到失败的原因。条件可能包括 TrueFalseUnknown

  • ReadyTrue 表示服务已配置,可以开始接收流量。
  • ConfigurationReadyTrue 表示底层配置已准备就绪。对于 False 或“Unknown”,您应查看最新修订版本的状态
  • RoutesReadyTrue 表示底层路由已准备就绪。对于 False 或“Unknown”,您应查看路由状态

如需详细了解状态条件,请参阅 Knative 错误信令

检查 Route 状态

每项 Cloud Run for Anthos 服务都会管理一个路由,它表示针对服务的修订版本的当前路由状态。

您可以通过查看服务状态来检查 Route 的整体状态:

gcloud run services describe SERVICE --format 'yaml(status)'

status 中的 RoutesReady 条件提供 Route 的状态。

您可以通过运行以下命令进一步诊断 Route 状态:

kubectl get route SERVICE -o yaml

status 中的条件提供失败的原因。具体包括以下这些照片和视频:

  • Ready 表示服务是否已配置以及是否具有可用的后端。如果此值为 true,则表示已正确配置路由。

  • AllTrafficAssigned 表示服务是否已正确配置以及是否具有可用的后端。如果此条件的 status 不是 True

  • IngressReady 指示 Ingress 是否已准备就绪。如果此条件的 status 不是 True,请尝试检查 Ingress 状态

  • CertificateProvisioned 表示 Knative 证书是否已预配。如果此条件的 status 不是 True,请尝试排查代管式 TLS 问题

如需状态条件的更多详情,请参阅 Knative 错误条件和报告

检查 Ingress 状态

Cloud Run for Anthos 使用一个名为 istio-ingress 的 Kubernetes 负载均衡器服务,该服务负责处理从集群外部传入的流量。

如需获取 Ingress 的外部 IP 地址,请使用

kubectl get svc istio-ingress -n gke-system

如果 EXTERNAL-IPpending,请参阅下面的 EXTERNAL-IP 长时间处于 pending 状态

检查 Revision 状态

如需获取 Cloud Run for Anthos 服务的最新修订版本,请运行以下命令:

gcloud run services describe SERVICE --format='value(status.latestCreatedRevisionName)'

运行以下命令以获取特定 Cloud Run for Anthos 修订版本的状态:

gcloud run revisions describe REVISION

您可以添加 --format yaml(status)--format json(status) 以获取完整状态:

gcloud run revisions describe REVISION --format yaml(status)

status 中的条件提供失败的原因。具体包括以下这些照片和视频:

  • Ready 表示运行时资源是否已准备就绪。如果此值为 true,则表示已正确配置修订版本。
  • ResourcesAvailable 指示是否已预配底层 Kubernetes 资源。如果此条件的 status 不是 True,请尝试检查 Pod 状态
  • ContainerHealthy 指示修订版本就绪检查是否已完成。 如果此条件的 status 不是 True,请尝试检查 Pod 状态
  • Active 表示修订版本是否正在接收流量。

如果这些条件中任何一个条件的 status 不是 True,请尝试检查 Pod 状态

检查 Pod 状态

要获取所有部署的 Pod,请使用以下命令:

kubectl get pods

此命令应列出所有 Pod 的简要状态。例如:

NAME                                                      READY     STATUS             RESTARTS   AGE
configuration-example-00001-deployment-659747ff99-9bvr4   2/2       Running            0          3h
configuration-example-00002-deployment-5f475b7849-gxcht   1/2       CrashLoopBackOff   2          36s

选择一个集群,然后使用以下命令查看其 status 的详细信息。一些有用的字段是 conditionscontainerStatuses

kubectl get pod POD-NAME -o yaml

EXTERNAL-IP 长时间处于 <pending> 状态

有时,您可能无法在创建集群后立即获得外部 IP 地址,从而将外部 IP 地址视为 pending 状态。例如,您可以通过调用以下命令来确认这一点:

要获取 Istio 入站网关的外部 IP 地址,请执行以下操作:

kubectl get svc istio-ingress -n gke-system

生成的输出类似如下所示:

NAME            TYPE           CLUSTER-IP     EXTERNAL-IP  PORT(S)
istio-ingress   LoadBalancer   XX.XX.XXX.XX   pending      80:32380/TCP,443:32390/TCP,32400:32400/TCP

负载平衡器的 EXTERNAL-IP 是您必须使用的 IP 地址。

这可能意味着 Google Cloud 中的外部 IP 地址配额已经用完。您可以通过调用以下命令来检查可能的原因:

kubectl describe svc istio-ingress -n gke-system

这将产生如下所示的输出:

Name:                     istio-ingress
Namespace:                gke-system
Labels:                   addonmanager.kubernetes.io/mode=Reconcile
                          app=istio-ingress
                          chart=gateways-1.0.3
                          heritage=Tiller
                          istio=ingress-gke-system
                          k8s-app=istio
                          kubernetes.io/cluster-service=true
                          release=istio
Annotations:              kubectl.kubernetes.io/last-applied-configuration={"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"addonmanager.kubernetes.io/mode":"Reconcile","app":"istio-ingressgateway","...
Selector:                 app=ingressgateway,istio=ingress-gke-system,release=istio
Type:                     LoadBalancer
IP:                       10.XX.XXX.XXX
LoadBalancer Ingress:     35.XXX.XXX.188
Port:                     http2  80/TCP
TargetPort:               80/TCP
NodePort:                 http2  31380/TCP
Endpoints:                XX.XX.1.6:80
Port:                     https  443/TCP
TargetPort:               443/TCP
NodePort:                 https  3XXX0/TCP
Endpoints:                XX.XX.1.6:XXX
Port:                     tcp  31400/TCP
TargetPort:               3XX00/TCP
NodePort:                 tcp  3XX00/TCP
Endpoints:                XX.XX.1.6:XXXXX
Port:                     tcp-pilot-grpc-tls  15011/TCP
TargetPort:               15011/TCP
NodePort:                 tcp-pilot-grpc-tls  32201/TCP
Endpoints:                XX.XX.1.6:XXXXX
Port:                     tcp-citadel-grpc-tls  8060/TCP
TargetPort:               8060/TCP
NodePort:                 tcp-citadel-grpc-tls  31187/TCP
Endpoints:                XX.XX.1.6:XXXX
Port:                     tcp-dns-tls  853/TCP
TargetPort:               XXX/TCP
NodePort:                 tcp-dns-tls  31219/TCP
Endpoints:                10.52.1.6:853
Port:                     http2-prometheus  15030/TCP
TargetPort:               XXXXX/TCP
NodePort:                 http2-prometheus  30944/TCP
Endpoints:                10.52.1.6:15030
Port:                     http2-grafana  15031/TCP
TargetPort:               XXXXX/TCP
NodePort:                 http2-grafana  31497/TCP
Endpoints:                XX.XX.1.6:XXXXX
Session Affinity:         None
External Traffic Policy:  Cluster
Events:
  Type    Reason                Age                  From                Message
  ----    ------                ----                 ----                -------
  Normal  EnsuringLoadBalancer  7s (x4318 over 15d)  service-controller  Ensuring load balancer

如果您的输出指示超出了 IN_USE_ADDRESSES 配额,您可以申请更多配额,方法是导航到 Google Cloud Console 中的“IAM 和管理”页面来申请增加配额。

网关将继续重试,直到分配外部 IP 地址。 这可能需要几分钟的时间。

排查代管式传输层安全协议 (TLS) 问题

使用下列问题排查步骤解决有关代管式 TLS 证书功能的常见问题。

检查特定网域映射的状态

如需检查特定网域映射的状态,请执行以下操作:

  1. 运行以下命令:

    gcloud run domain-mappings describe --domain DOMAIN --namespace NAMESPACE

    替换

    • DOMAIN 替换为您使用的域名。
    • NAMESPACE 替换为您用于网域映射的命名空间。
  2. 在此命令的 yaml 结果中,检查 CertificateProvisioned 字段的条件以确定错误的性质。

  3. 如果显示错误,则该错误应与下表中的某个错误相匹配。请按照表格中的建议解决问题。

用户配置错误

错误代码 详细消息 问题排查说明
DNSErrored DNS record is not configured correctly. Need to map domain [XXX] to IP XX.XX.XX.XX 请按照提供的说明正确配置 DNS 记录。
RateLimitExceeded acme: urn:ietf:params:acme:error:rateLimited: Error creating new order

:: too many certificates already issued for exact set of domains:

test.example.com:

see https://letsencrypt.org/docs/rate-limits/

请与 Let's Encrypt 联系以增加该主机的证书配额。
InvalidDomainMappingName DomainMapping name %s cannot be the same as Route URL host %s. DomainMapping 名称不能与其映射到的路由的主机名完全相同。请使用其他域名来作为 DomainMapping 名称。
ChallengeServingErrored 系统无法处理 HTTP01 请求。 如果 istio-ingress 服务无法处理来自 Let's Encrypt 的请求来验证网域所有权,则可能会发生此错误。
  1. 确保可以在不使用 Virtual Private Cloud 的情况下通过公共互联网访问 istio-ingress 服务。
  2. 确定您的 istio-ingress 服务接受来自网址 http://DOMAIN/.well-known/acme-challenge/... 的请求,其中 DOMAIN 是待验证的网域。

系统错误

错误代码 详细消息 问题排查说明
OrderErrored

AuthzErrored

ChallengeErrored

如果 Let's Encrypt 对网域所有权的验证失败,则会出现这三种类型的错误。

这些错误通常是暂时性错误,Cloud Run for Anthos 将重新尝试解决错误。

重新尝试的延迟时间以指数增加,最短为 8 秒,最长为 8 小时。

如果您要手动重新尝试解决错误,可以手动删除失败的订单。

kubectl delete order DOMAIN -n NAMESPACE

ACMEAPIFailed 如果 Cloud Run for Anthos 无法调用 Let's Encrypt,则会出现这种类型的错误。此错误通常是暂时性错误,Cloud Run for Anthos 将重新尝试解决错误。

如果您要手动重新尝试解决错误,请手动删除失败的订单。

kubectl delete order DOMAIN -n NAMESPACE

UnknownErrored 此错误表示 GKE 集群中极少出现的未知系统错误。如果您看到此错误,请与 Cloud 支持团队联系以获得调试帮助。

检查订单状态

订单状态记录了与 Let's Encrypt 交互的过程,因此可用于调试与 Let's Encrypt 相关的问题。如果需要,请通过运行以下命令检查订单的状态:

kubectl get order DOMAIN -n NAMESPACE -oyaml

替换

  • DOMAIN 替换为您使用的域名。
  • NAMESPACE 替换为您用于网域映射的命名空间。

如果订单成功,则结果将包含已发放的证书以及其他信息。

超出 Let's Encrypt 配额

检查 DomainMapping 状态。如果您超出了 Let's Encrypt 配额,则会在 DomainMapping 中看到如下错误消息:

acme: urn:ietf:params:acme:error:rateLimited: Error creating new order
:: too many certificates already issued for exact set of domains:
test.example.com:
see https://letsencrypt.org/docs/rate-limits/'

如需增加证书配额,请参阅有关速率限制的 Let's Encrypt 文档

订单超时

如果订单对象仍然无法获取证书,则会在 20 分钟后超时。

  1. 检查网域映射状态。对于超时,请在状态输出中查找如下错误消息:

    order (test.example.com) timed out (20.0 minutes)
  2. 超时问题的一个常见原因是您的 DNS 记录未正确配置,无法将您使用的网域映射到 gke-system 下的 istio-ingress 服务的 IP 地址。请运行以下命令来检查 DNS 记录:

    host DOMAIN
  3. 运行以下命令以检查 gke-systemistio-ingress 服务的外部 IP 地址:

    kubectl get svc istio-ingress -n gke-system

    如果网域的外部 IP 地址与入站 IP 地址不匹配,请重新配置您的 DNS 记录以映射到正确的 IP 地址。

  4. (更新的)DNS 记录生效后,运行以下命令删除订单对象,以重新触发请求 TLS 证书的过程:

    kubectl delete order DOMAIN -n NAMESPACE

    替换

    • DOMAIN 替换为您使用的域名。
    • NAMESPACE 替换为您使用的命名空间。

授权失败

如果 DNS 记录未及时传播到全球范围,则可能会出现授权失败的问题。在这种情况下,Let's Encrypt 无法验证网域的所有权。

  1. 检查订单状态。请在状态的 acmeAuthorizations 字段下找到 authz 链接。网址应如下所示:

    https://acme-v02.api.letsencrypt.org/acme/authz-v3/1717011827
  2. 打开链接。如果您看到类似如下消息:

    urn:ietf:params:acme:error:dns

    则问题就在于 DNS 传播不完整。

  3. 如需解决 DNS 传播错误,请执行以下操作:

    1. 通过运行以下命令获取 gke-systemistio-ingress 服务的外部 IP 地址:
      kubectl get svc istio-ingress -n gke-system
    2. 通过运行以下命令检查网域的 DNS 记录:

      host DOMAIN

      如果 DNS 记录的 IP 地址与 gke-systemistio-ingress 服务的外部 IP 地址不匹配,请配置 DNS 记录以将用户的网域映射到外部 IP 地址。

    3. (更新的)DNS 记录生效后,运行以下命令删除订单对象,以重新触发请求 TLS 证书的过程:

      kubectl delete order DOMAIN -n NAMESPACE

    替换

    • DOMAIN 替换为您使用的域名。
    • NAMESPACE 替换为您用于网域映射的命名空间。

专用集群部署失败:“调用 webhook 失败”错误

如果您对专用集群的部署失败并显示以下消息,则您的防火墙可能未正确设置:

Error: failed calling webhook "webhook.serving.knative.dev": Post
https://webhook.knative-serving.svc:443/?timeout=30s: context deadline exceeded (Client.Timeout
exceeded while awaiting headers)

如需了解支持部署到专用集群所需的防火墙更改,请参阅在专用集群上启用部署

IngressNotConfigured 的服务报告状态

如果您的服务状态中出现 IngressNotConfigured,则您可能需要在 gke-system 命名空间中重启 istio-pilot 部署。此错误在 kubernetes 1.14 上更加常见;如果服务是在 istio_pilot 准备开始协调 VirtualServices 并将 Envoy 配置推送到入站网关之前创建的,则可能会出现此错误。

如需解决此问题,请缩减部署规模,然后使用类似如下的命令再次扩大部署规模:

kubectl scale deployment istio-pilot -n gke-system --replicas=0
kubectl scale deployment istio-pilot -n gke-system --replicas=1

缺失请求数和请求延迟时间指标

如果您启用了 Workload Identity,并且未向您的服务使用的服务帐号授予某些权限,则您的服务可能不会报告修订版本请求计数和请求延迟时间指标。

您可以按照使用 Workload Identity 启用集群上的指标部分中的步骤来解决此问题。

将 WebSocket 用于自定义网域

默认情况下,会针对自定义网域映射停用 WebSocket。

如需为自定义网域启用 WebSocket,请运行以下命令,使用 allow_connect: true 创建 Istio EnvoyFilter 对象:

cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: EnvoyFilter
metadata:
  name: allowconnect-cluster-local-gateway-tb
  namespace: gke-system
spec:
  workloadSelector:
    labels:
      istio: ingress-gke-system
  configPatches:
  - applyTo: NETWORK_FILTER
    match:
      listener:
        portNumber: 8081
        filterChain:
          filter:
            name: "envoy.http_connection_manager"
    patch:
      operation: MERGE
      value:
        typed_config:
          "@type": "type.googleapis.com/envoy.config.filter.network.http_connection_manager.v2.HttpConnectionManager"
          http2_protocol_options:
            allow_connect: true
EOF