疑難排解

本頁面提供一些常見錯誤的疑難排解策略以及解決方案。

排解 Knative 服務問題時,請先確認您可以在本機執行容器映像檔

如果您的應用程式無法在本機執行,您將需要診斷該應用程式並修正問題。 請使用 Cloud Logging 協助對部署的專案進行偵錯。

排解 Knative Serving 問題時,請參考以下各節,瞭解問題的可能解決辦法。

檢查指令列輸出

如果您使用 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 容器資源。

檢查服務狀態

執行下列指令,取得已部署的 Knative 服務服務狀態:

gcloud run services describe SERVICE

您可以新增 --format yaml(status)--format json(status),取得完整狀態,例如:

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

status 中的狀況有助於找出失敗原因。條件可包括 TrueFalseUnknown

如要進一步瞭解狀態條件,請參閱「Knative 錯誤信號」。

檢查轉送狀態

每個 Knative 服務都會管理 Route,代表服務修訂版本的目前路由狀態。

如要查看路線的整體狀態,請查看服務狀態:

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

status 中的 RoutesReady 狀況會提供 Route 的狀態。

您可以執行下列指令,進一步診斷路徑狀態:

kubectl get route SERVICE -o yaml

status 中的狀況提供失敗原因。您還是可以透過 Google 相簿取得這些內容:

  • 「就緒」表示服務已設定且有可用的後端。如果這是 true,表示路徑已正確設定。

  • AllTrafficAssigned 會指出服務是否已正確設定,且有可用的後端。如果這個條件的 status 不是 True

  • IngressReady:指出 Ingress 是否已準備就緒。 如果這個條件的 status 不是 True,請嘗試檢查輸入狀態

  • CertificateProvisioned 會指出是否已佈建 Knative 憑證。如果這個條件的 status 不是 True,請嘗試排解受管理 TLS 問題

如要進一步瞭解狀態條件,請參閱「Knative 錯誤條件和回報」。

檢查 Ingress 狀態

Knative Serving 使用名為 istio-ingressgateway 的負載平衡器服務,負責處理來自叢集外部的連入流量。

如要取得負載平衡器的外部 IP,請執行下列指令:

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

ASM-INGRESS-NAMESPACE 替換為 Cloud Service Mesh Ingress 所在的命名空間。如果您使用預設設定安裝 Cloud 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」。

檢查修訂版本狀態

如要取得 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 中的狀況提供失敗原因。您還是可以透過 Google 相簿取得這些內容:

  • 「就緒」:表示執行階段資源是否已準備就緒。如果是 true,表示修訂版本已正確設定。
  • ResourcesAvailable 會指出基礎 Kubernetes 資源是否已佈建。如果這個條件的 status 不是 True,請嘗試檢查 Pod 狀態
  • ContainerHealthy:指出修訂版本就緒檢查是否已完成。 如果這個條件的 status 不是 True,請嘗試檢查 Pod 狀態
  • 有效:表示修訂版本是否正在接收流量。

如果上述任一條件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 替換為 Cloud Service Mesh Ingress 所在的命名空間。如果您使用預設設定安裝 Cloud 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 & Admin」(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 記錄設定不正確。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.your-domain.com:
see https://letsencrypt.org/docs/rate-limits/

已超過 Let's Encrypt 配額。你必須提高該主機的 Let's Encrypt 憑證配額。

InvalidDomainMappingName 訊息DomainMapping 名稱「%s」不得與 Route URL 主機「%s」相同。

DomainMapping 名稱不得與對應的 Route 主機完全相同。為 DomainMapping 名稱使用其他網域。

ChallengeServingErrored 訊息系統無法提供 HTTP01 要求。

如果 istio-ingressgateway 服務無法處理 Let's Encrypt 的要求,驗證網域擁有權,就可能發生這個錯誤。

  1. 確認您的istio-ingressgateway服務可透過公開網際網路存取,且不使用 Virtual Private Cloud
  2. 請確認 istio-ingressgateway 服務接受來自網址 http://DOMAIN/.well-known/acme-challenge/... 的要求,其中 DOMAIN 是要驗證的網域。

系統錯誤

錯誤代碼 詳細資料
OrderErrored

AuthzErrored

ChallengeErrored

如果 Let's Encrypt 無法驗證網域擁有權,就會發生這 3 種錯誤。

這些通常是暫時性錯誤,Knative 服務會重試。

重試延遲時間會呈指數成長,最短為 8 秒,最長為 8 小時。

如要手動重試錯誤,可以手動刪除失敗的訂單。

kubectl delete order DOMAIN -n NAMESPACE

ACMEAPIFailed 如果 Knative Serving 無法呼叫 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 改成您用於網域對應的命名空間。

如果訂單成功,結果會顯示核發的認證和其他資訊。

訂單逾時

如果 Order 物件在 20 分鐘後仍無法取得憑證,就會逾時。

  1. 檢查網域對應狀態。如為逾時,請在狀態輸出中尋找類似以下的錯誤訊息:

    order (test.your-domain.com) timed out (20.0 minutes)
  2. 逾時問題的常見原因,是 DNS 記錄未正確設定,無法將使用的網域對應至 Ingress 服務的 IP 位址。執行下列指令來檢查 DNS 記錄:

    host DOMAIN
  3. 檢查 Ingress 負載平衡器的外部 IP 位址:

    如要取得負載平衡器的外部 IP,請執行下列指令:

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

    ASM-INGRESS-NAMESPACE 替換為 Cloud Service Mesh Ingress 所在的命名空間。如果您使用預設設定安裝 Cloud 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 位址與 Ingress IP 位址不符,請重新設定 DNS 記錄,對應至正確的 IP 位址。

  4. (更新後的) DNS 記錄生效後,請執行下列指令刪除 Order 物件,重新觸發要求 TLS 憑證的程序:

    kubectl delete order DOMAIN -n NAMESPACE

    取代

    • DOMAIN 改成您使用的網域名稱。
    • NAMESPACE 改為您使用的命名空間。

授權失敗

如果 DNS 記錄未及時在全球傳播,就可能發生授權失敗的情況。因此,Let's Encrypt 無法驗證網域擁有權。

  1. 查看訂單狀態。在狀態的 acmeAuthorizations 欄位下方找出授權連結。網址應如下所示:

    https://acme-v02.api.letsencrypt.org/acme/authz-v3/1717011827
  2. 開啟連結。如果看到類似以下的訊息:

    urn:ietf:params:acme:error:dns

    則問題是因 DNS 傳播不完整所致。

  3. 如要解決 DNS 傳播錯誤,請按照下列步驟操作:

    1. 檢查 Ingress 負載平衡器的外部 IP 位址:

      如要取得負載平衡器的外部 IP,請執行下列指令:

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

      ASM-INGRESS-NAMESPACE 替換為 Cloud Service Mesh Ingress 所在的命名空間。如果您使用預設設定安裝 Cloud 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 位址與 Ingress 負載平衡器的外部 IP 不符,請設定 DNS 記錄,將使用者的網域對應至外部 IP。

    3. (更新後的) DNS 記錄生效後,請執行下列指令刪除 Order 物件,重新觸發要求 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 部署作業 (如果您使用叢集內控制平面 Cloud Service Mesh)。如果服務是在 istiod 準備好開始調解 VirtualServices 並將 Envoy 設定推送至 Ingress 閘道之前建立,就可能發生這項錯誤 (在 Kubernetes 1.14 上更常發生)。

如要修正這個問題,請使用類似下列的指令,先縮減部署作業,然後再擴大:

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

缺少要求數和要求延遲指標

如果您已啟用 Workload Identity Federation for GKE,但未將特定權限授予服務使用的服務帳戶,服務可能不會回報修訂版本要求計數和要求延遲時間指標。

如要修正這個問題,請按照「在啟用 Workload Identity Federation for GKE 的叢集上啟用指標」一節中的步驟操作。