问题排查

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

对 Knative 服务进行问题排查时,请先确认您可以在本地运行容器映像

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

在对 Knative 服务进行问题排查时,请参阅以下部分,了解可能的问题解决方案。

检查命令行输出

如果您使用 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 控制台中的 Knative 服务页面来检查请求日志和容器日志。如需查看完整的详细信息,请阅读记录和查看日志

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

检查 Service 状态

运行以下命令,以获取已部署的 Knative 服务服务的状态:

gcloud run services describe SERVICE

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

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

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

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

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

检查 Route 状态

每个 Knative 服务服务都管理一个路由,表示根据服务修订版本的当前路由状态。

您可以通过查看服务状态来检查 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 状态

Knative 服务使用名为 istio-ingressgateway 的负载均衡器服务,该服务负责处理从集群外部传入的流量。

如需获取负载均衡器的外部 IP,请运行以下命令:

kubectl get svc istio-ingressgateway -n ASM-INGRESS-NAMESPACE

ASM-INGRESS-NAMESPACE 替换为 Anthos Service Mesh 入站流量所在的命名空间。如果您使用默认配置安装了 Anthos Service Mesh,请指定 istio-system

输出类似于以下内容:

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

其中 EXTERNAL-IP 值是负载均衡器的外部 IP。

如果 EXTERNAL-IPpending,请参阅下面的 EXTERNAL-IP 长时间为 pending

检查 Revision 状态

如需获取 Knative 服务服务的最新版本,请运行以下命令:

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

运行以下命令,以获取特定 Knative 服务修订版本的状态:

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 状态。例如,您可以通过调用以下命令来确认这一点:

如需获取负载均衡器的外部 IP,请运行以下命令:

kubectl get svc istio-ingressgateway -n ASM-INGRESS-NAMESPACE

ASM-INGRESS-NAMESPACE 替换为 Anthos Service Mesh 入站流量所在的命名空间。如果您使用默认配置安装了 Anthos Service Mesh,请指定 istio-system

输出类似于以下内容:

NAME                   TYPE           CLUSTER-IP     EXTERNAL-IP  PORT(S)
istio-ingressgateway   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-ingressgateway -n INGRESS_NAMESPACE
其中,INGRESS_NAMESPACE 是 ASM Ingress 的命名空间,默认为“istio-system”。这样会生成类似于以下内容的输出:
Name:                     istio-ingressgateway
Namespace:                INGRESS_NAMESPACE
Labels:                   app=istio-ingressgateway
                          istio=ingressgateway
                          istio.io/rev=asm-1102-3
                          operator.istio.io/component=IngressGateways
                          operator.istio.io/managed=Reconcile
                          operator.istio.io/version=1.10.2-asm.3
                          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=istio-ingressgateway,istio=ingressgateway
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 控制台中的“IAM 和管理”页面来申请增加配额。

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

排查自定义网域和代管式 TLS 问题

使用下面列出的问题排查步骤解决有关自定义网域代管式 TLS 证书功能的常见问题。

用于专用内部网络的自定义网域

如果您将自定义网域映射到专用内部网络中的 Knative 服务集群或服务,则必须停用代管式 TLS 证书,否则您的网域配置将无法实现 ready 状态。默认情况下,内部负载均衡器无法与证书授权机构进行外部通信。

检查特定网域映射的状态

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

  1. 运行以下命令:

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

    替换

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

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

用户配置错误

错误代码 详细信息
DNSErrored 消息DNS 记录配置不正确。需要将网域 [XXX] 映射到 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.your-domain.com:
see https://letsencrypt.org/docs/rate-limits/

超出了 Let's Encrypt 配额。您必须增加该主机的 Let's Encrypt 证书配额。

InvalidDomainMappingName 消息: DomainMapping name %s cannot be the same as Route URL host %s.

DomainMapping 名称不能与其映射到的路由的主机名完全相同。请使用其他域名来作为 DomainMapping 名称。

ChallengeServingErrored 消息:System failed to serve HTTP01 request.

如果 istio-ingressgateway 服务无法处理来自 Let's Encrypt 的请求来验证网域所有权,则可能会发生此错误。

  1. 确保可以在不使用 Virtual Private Cloud 的情况下通过公共互联网访问 istio-ingressgateway 服务。
  2. 确保 istio-ingressgateway 服务接受来自网址 http://DOMAIN/.well-known/acme-challenge/... 的请求,其中 DOMAIN 是待验证的网域。

系统错误

错误代码 详细信息
OrderErrored

AuthzErrored

ChallengeErrored

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

这些错误通常是暂时性错误,Knative 服务会重试。

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

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

kubectl delete order DOMAIN -n NAMESPACE

ACMEAPIFailed 如果 Knative 服务无法调用 Let's Encrypt,则会出现此类错误。此错误通常是暂时性错误,Knative 服务会重试。

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

kubectl delete order DOMAIN -n NAMESPACE

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

检查订单状态

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

kubectl get order DOMAIN -n NAMESPACE -oyaml

替换

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

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

订单超时

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

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

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

    host DOMAIN
  3. 检查入站流量负载均衡器的外部 IP 地址:

    如需获取负载均衡器的外部 IP,请运行以下命令:

    kubectl get svc istio-ingressgateway -n ASM-INGRESS-NAMESPACE
    

    ASM-INGRESS-NAMESPACE 替换为 Anthos Service Mesh 入站流量所在的命名空间。如果您使用默认配置安装了 Anthos Service Mesh,请指定 istio-system

    输出类似于以下内容:

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

    其中 EXTERNAL-IP 值是负载均衡器的外部 IP。

    如果网域的外部 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. 检查入站流量负载均衡器的外部 IP 地址:

      如需获取负载均衡器的外部 IP,请运行以下命令:

      kubectl get svc istio-ingressgateway -n ASM-INGRESS-NAMESPACE
      

      ASM-INGRESS-NAMESPACE 替换为 Anthos Service Mesh 入站流量所在的命名空间。如果您使用默认配置安装了 Anthos Service Mesh,请指定 istio-system

      输出类似于以下内容:

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

      其中 EXTERNAL-IP 值是负载均衡器的外部 IP。

    2. 通过运行以下命令检查网域的 DNS 记录:

      host DOMAIN

      如果 DNS 记录的 IP 地址与入站流量负载均衡器的外部 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,您可能需要在 istio-system 命名空间中重启 istiod 部署(如果您使用的是集群内控制平面 Anthos Service Mesh)。此错误在 kubernetes 1.14 上更加常见;如果服务是在 istiod 准备开始协调 VirtualServices 并将 Envoy 配置推送到入站网关之前创建的,则可能会出现此错误。

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

kubectl scale deployment istiod -n istio-system --replicas=0
kubectl scale deployment istiod -n istio-system --replicas=1

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

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

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