排解 kubectl 指令列工具的問題


本頁說明如何在 Google Kubernetes Engine (GKE) 中使用 kubectl 指令列工具時,解決相關問題。如需更多一般建議,請參閱 Kubernetes 說明文件中的「疑難排解 kubectl」。

驗證和授權錯誤

使用 kubectl 指令列工具指令時,如果發生與驗證和授權相關的錯誤,請參閱下列章節的建議。

錯誤:401 (未經授權)

連線至 GKE 叢集時,您可能會收到 HTTP 狀態碼為 401 (Unauthorized) 的驗證和授權錯誤。如果您嘗試從本機環境在 GKE 叢集中執行 kubectl 指令,就可能會發生這個問題。詳情請參閱「問題:驗證和授權錯誤」。

錯誤:驗證範圍不足

執行 gcloud container clusters get-credentials 時,您可能會收到下列錯誤訊息:

ERROR: (gcloud.container.clusters.get-credentials) ResponseError: code=403, message=Request had insufficient authentication scopes.

發生這個錯誤,是因為您嘗試從沒有 cloud-platform 範圍的 Compute Engine VM 存取 GKE API。

如要解決這項錯誤,請授予缺少的 cloud-platform 範圍。如需變更 Compute Engine VM 執行個體範圍的操作說明,請參閱 Compute Engine 說明文件中的「建立及啟用執行個體的服務帳戶」。

錯誤:找不到可執行的 gke-gcloud-auth-plugin

嘗試執行指令或與 GKE 互動的自訂用戶端時,可能會發生類似下列的錯誤訊息:kubectl

Unable to connect to the server: getting credentials: exec: executable gke-gcloud-auth-plugin not found

It looks like you are trying to use a client-go credential plugin that is not installed.

To learn more about this feature, consult the documentation available at:
      https://kubernetes.io/docs/reference/access-authn-authz/authentication/#client-go-credential-plugins

Visit cloud.google.com/kubernetes-engine/docs/how-to/cluster-access-for-kubectl#install_plugin to install gke-gcloud-auth-plugin.
Unable to connect to the server: getting credentials: exec: fork/exec /usr/lib/google-cloud-sdk/bin/gke-gcloud-auth-plugin: no such file or directory

如要解決這個問題,請按照「安裝必要外掛程式」一文所述安裝 gke-gcloud-auth-plugin

錯誤:找不到驗證供應商

如果 kubectl 或自訂 Kubernetes 用戶端是以 Kubernetes client-go 1.26 以上版本建構,就會發生下列錯誤:

no Auth Provider found for name "gcp"

如要解決這個問題,請完成下列步驟:

  1. 按照「安裝必要外掛程式」一文所述安裝 gke-gcloud-auth-plugin

  2. 更新至最新版 gcloud CLI:

    gcloud components update
    
  3. 更新 kubeconfig 檔案:

    gcloud container clusters get-credentials CLUSTER_NAME \
        --location=CONTROL_PLANE_LOCATION
    

    更改下列內容:

    • CLUSTER_NAME:叢集名稱。
    • CONTROL_PLANE_LOCATION:叢集控制層的 Compute Engine 位置。為地區叢集提供地區,或為區域叢集提供區域。

錯誤:gcp auth 外掛程式已淘汰,請改用 gcloud

安裝 gke-gcloud-auth-plugin 並對 GKE 叢集執行 kubectl 指令後,您可能會看到下列警告訊息:

WARNING: the gcp auth plugin is deprecated in v1.22+, unavailable in v1.25+; use gcloud instead.

如果用戶端版本早於 1.26,系統就會顯示這則訊息。

如要解決這個問題,請要求用戶端改用gke-gcloud-auth-plugin驗證外掛程式:

  1. 在文字編輯器中開啟 Shell 登入指令碼:

    Bash

    vi ~/.bashrc

    Zsh

    vi ~/.zshrc

    如果使用 PowerShell,請略過這個步驟。

  2. 設定下列環境變數:

    Bash

    export USE_GKE_GCLOUD_AUTH_PLUGIN=True
    

    Zsh

    export USE_GKE_GCLOUD_AUTH_PLUGIN=True
    

    PowerShell

    [Environment]::SetEnvironmentVariable('USE_GKE_GCLOUD_AUTH_PLUGIN', True, 'Machine')
    
  3. 在環境中套用變數:

    Bash

    source ~/.bashrc

    Zsh

    source ~/.zshrc
    

    PowerShell

    結束終端機,然後開啟新的終端機工作階段。

  4. 更新 gcloud CLI:

    gcloud components update
    
  5. 驗證叢集:

    gcloud container clusters get-credentials CLUSTER_NAME \
        --location=CONTROL_PLANE_LOCATION
    

    更改下列內容:

    • CLUSTER_NAME:叢集名稱。
    • CONTROL_PLANE_LOCATION:叢集控制層的 Compute Engine 位置。為地區叢集提供地區,或為區域叢集提供區域。

問題:找不到 kubectl 指令

如果收到找不到 kubectl 指令的訊息,請重新安裝 kubectl 二進位檔,並設定 $PATH 環境變數:

  1. 安裝 kubectl 二進位檔:

    gcloud components update kubectl
    
  2. 當安裝程式提示您修改 $PATH 環境變數時,請輸入 y 繼續。修改此變數後,您不用輸入完整的路徑就能使用 kubectl 指令。

    或者,將下列這行新增至殼層儲存環境變數的位置,例如 ~/.bashrc (或 macOS 中的 ~/.bash_profile):

    export PATH=$PATH:/usr/local/share/google/google-cloud-sdk/bin/
    
  3. 執行下列指令來載入更新的檔案。以下範例使用 .bashrc

    source ~/.bashrc
    

    如果您使用 macOS,請改用 ~/.bash_profile,而非 .bashrc

問題:kubectl 指令傳回「連線遭拒」錯誤

如果 kubectl 指令傳回「連線遭拒」錯誤,請使用下列指令設定叢集內容:

gcloud container clusters get-credentials CLUSTER_NAME \
       --location=CONTROL_PLANE_LOCATION

更改下列內容:

  • CLUSTER_NAME:叢集名稱。
  • CONTROL_PLANE_LOCATION:叢集控制層的 Compute Engine 位置。為地區叢集提供地區,或為區域叢集提供區域。

如果您不確定要在叢集名稱或位置輸入什麼,請使用以下指令列出您的叢集:

gcloud container clusters list

錯誤:kubectl 指令逾時

如果您建立叢集並嘗試對叢集執行 kubectl 指令,但 kubectl 指令逾時,您會看到類似下列內容的錯誤:

  • Unable to connect to the server: dial tcp IP_ADDRESS: connect: connection timed out
  • Unable to connect to the server: dial tcp IP_ADDRESS: i/o timeout

這些錯誤表示 kubectl 無法與叢集控制層通訊。

如要解決這個問題,請驗證並設定叢集所在環境,並確保叢集連線正常:

  1. 前往 $HOME/.kube/config 或執行 kubectl config view 指令,確認設定檔包含叢集環境和控制層的外部 IP 位址。

  2. 設定叢集憑證:

    gcloud container clusters get-credentials CLUSTER_NAME \
        --location=CONTROL_PLANE_LOCATION \
        --project=PROJECT_ID
    

    更改下列內容:

    • CLUSTER_NAME:叢集名稱。
    • CONTROL_PLANE_LOCATION:叢集控制層的 Compute Engine 位置。為地區叢集提供地區,或為區域叢集提供區域。
    • PROJECT_ID:叢集建立所在的專案 ID。
  3. 如果您已在叢集中啟用授權網路,請確認現有的授權網路清單包含您嘗試連線的電腦輸出 IP。您可以在主控台中找到現有的授權網路,或執行下列指令:

    gcloud container clusters describe CLUSTER_NAME \
        --location=CONTROL_PLANE_LOCATION \
        --project=PROJECT_ID \
        --format "flattened(controlPlaneEndpointsConfig.ipEndpointsConfig.authorizedNetwork
    sConfig.cidrBlocks[])"
    

    如果電腦的輸出 IP 不在上述指令輸出內容的授權網路清單中,請完成下列其中一個步驟:

錯誤:kubectl 指令傳回「無法交涉 api 版本」

如果 kubectl 指令傳回 failed to negotiate an API version 錯誤,請確認 kubectl 具有驗證憑證:

gcloud auth application-default login

問題:kubectllogsattachexecport-forward 指令停止回應

如果 kubectllogsattachexecport-forward 指令停止回應,通常表示 API 伺服器無法與節點通訊。

首先,請檢查叢集是否有任何節點。如果將叢集中的節點數目減至零,指令將無法運作。如要解決這個問題,請重新調整叢集大小,確保叢集至少有一個節點。

如果叢集至少有一個節點,請檢查您是否使用 SSH 或 Konnectivity Proxy 通道來啟用安全通訊。下列各節將討論各項服務的專屬疑難排解步驟:

排解 SSH 問題

如果您使用 SSH,GKE 會在 Compute Engine 專案中繼資料中儲存 SSH 公開金鑰檔案。所有使用 Google 提供的映像檔的 Compute Engine VM 都會定期檢查其專案的通用中繼資料及其執行個體的中繼資料,以將 SSH 金鑰加入 VM 的授權使用者清單中。GKE 也會將一個防火牆規則新增到您的 Compute Engine 網路,讓您從控制層的 IP 位址透過 SSH 存取叢集中的每個節點。

下列設定可能會導致 SSH 通訊發生問題:

  • 您網路的防火牆規則不允許從控制層進行 SSH 存取。

    所有 Compute Engine 網路在建立時都會有一個稱為「default-allow-ssh」的防火牆規則,以允許從所有 IP 位址透過 SSH 進行存取 (當然需要有效的私密金鑰)。default-allow-sshGKE 還會為每個公開叢集插入一個 SSH 規則,格式為 gke-CLUSTER_NAME-RANDOM_CHARACTERS-ssh,以專門允許從叢集的控制層透過 SSH 存取叢集的節點。

    如果這些規則都不存在,控制平面就無法開啟 SSH 通道。

    如要確認問題是否為此原因所致,請檢查設定是否包含這些規則。

    如要解決這個問題,請找出叢集所有節點上的標記,然後重新加入防火牆規則,允許從控制平面的 IP 位址存取含有該標記的 VM。

  • 您專案的「ssh-keys」通用中繼資料項目已滿。

    如果名為 ssh-keys 的專案中繼資料項目大小接近上限,GKE 即無法新增自己的 SSH 金鑰來開啟 SSH 通道。

    如要確認這是否為問題,請檢查 ssh-keys 清單的長度。您可以執行下列指令,查看專案的中繼資料,並視需要加入 --project 標記:

    gcloud compute project-info describe [--project=PROJECT_ID]
    

    如要解決這個問題,請刪除不再需要的 SSH 金鑰

  • 您在叢集中的 VM 上設定了一個包含 ssh-keys 金鑰的中繼資料欄位。

    VM 上的節點代理程式會優先使用執行個體專屬的 SSH 金鑰,而不會使用適用於全專案的 SSH 金鑰。如果您曾在叢集節點上設定任何 SSH 金鑰,節點就不會採用專案中繼資料中的控制平面 SSH 金鑰。

    如要確認是否為這個問題,請執行 gcloud compute instances describe VM_NAME,並在 metadata 中尋找 ssh-keys 欄位。

    如要解決這個問題,請從執行個體中繼資料刪除執行個體專屬的 SSH 金鑰

排解 Konnectivity Proxy 問題

如要判斷叢集是否使用 Konnectivity Proxy,請檢查下列系統 Deployment:

kubectl get deployments konnectivity-agent --namespace kube-system

如果叢集使用 Konnectivity Proxy,輸出內容會類似於下列內容:

NAME                 READY   UP-TO-DATE   AVAILABLE   AGE
konnectivity-agent   3/3     3            3           18d

確認您使用的是 Konnectivity Proxy 後,請確保 Konnectivity 代理程式具備必要的防火牆存取權,且網路政策設定正確無誤。

允許必要的防火牆存取權

確認網路的防火牆規則允許存取下列通訊埠:

  • 控制層通訊埠:建立叢集時,Konnectivity 代理程式會建立與控制層的連線,通訊埠為 8132。執行 kubectl 指令時,API 伺服器會使用這個連線與叢集通訊。請務必允許輸出流量透過通訊埠 8132 傳送至叢集控制層 (相較之下,API 伺服器使用通訊埠 443)。如果規則會拒絕輸出存取權,您可能需要修改規則或建立例外狀況。
  • kubelet 通訊埠:由於 Konnectivity 代理程式是部署在叢集節點上的系統 Pod,請確保防火牆規則允許下列類型的流量:

    • 從 Pod 範圍傳入工作負載的流量 (通訊埠 10250)。
    • 來自 Pod 範圍的外送流量。

    如果防火牆規則不允許這類流量,請修改規則

調整網路政策

如果叢集的網路政策執行下列任一操作,Konnectivity Proxy 可能會發生問題:

  • 封鎖kube-system 命名空間到 workload 命名空間的 Ingress
  • 封鎖通訊埠 8132 上的叢集控制層輸出

如果工作負載 Pod 的網路政策封鎖連入流量,konnectivity-agent 記錄檔會包含類似下列內容的錯誤訊息:

"error dialing backend" error="dial tcp POD_IP_ADDRESS:PORT: i/o timeout"

在錯誤訊息中,POD_IP_ADDRESS 是工作負載 Pod 的 IP 位址。

如果網路政策封鎖輸出,konnectivity-agent 記錄檔會包含類似下列內容的錯誤訊息:

"cannot connect once" err="rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing: dial tcp CP_IP_ADDRESS:8132: i/o timeout

在錯誤訊息中,CP_IP_ADDRESS 是叢集控制層的 IP 位址。

這些功能不會影響叢集的正常運作。如果您想要鎖定叢集的網路以防止外部存取,像這樣的功能其實沒有什麼作用。

如要確認網路政策的傳入或傳出規則是否導致問題,請執行下列指令,找出受影響命名空間中的網路政策:

kubectl get networkpolicy --namespace AFFECTED_NAMESPACE

如要解決 Ingress 政策問題,請在網路政策的 spec.ingress 欄位中新增下列項目:

ingress:
- from:
  - namespaceSelector:
      matchLabels:
        kubernetes.io/metadata.name: kube-system
    podSelector:
      matchLabels:
        k8s-app: konnectivity-agent

如要解決輸出政策問題,請在網路政策的 spec.egress 欄位中新增下列項目:

egress:
- to:
  - ipBlock:
      cidr: CP_IP_ADDRESS/32
  ports:
  - protocol: TCP
    port: 8132

如果網路政策同時使用輸入和輸出規則,請考慮調整這兩項規則。

調整 IP 偽裝代理程式

如果來源 IP 位址位於 Pod IP 位址範圍內,叢集控制層就會接受來自 Konnectivity 代理程式的流量。如果修改 ip-masq-agent 的設定,將傳送至叢集控制平面的流量來源 IP 位址偽裝起來,Konnectivity 代理程式可能會發生連線錯誤。

如要解決這個問題,並確保從 Konnectivity 代理程式到叢集控制層的流量不會偽裝成節點 IP 位址,請將控制層 IP 位址新增至 ip-masq-agent ConfigMap 中的 nonMasqueradeCIDRs 清單:

nonMasqueradeCIDRs:
- CONTROL_PLANE_IP_ADDRESS/32

如要進一步瞭解這項設定,請參閱 IP 偽裝代理程式

後續步驟