使用 Google Kubernetes Engine (GKE) 時,如果 kubectl 指令列工具發生問題,可能會導致您無法部署應用程式或管理叢集資源。這些問題通常分為兩類:驗證失敗 (叢集無法辨識您的身分),以及連線失敗 (工具無法連線至叢集的控制層)。
這個頁面可協助您診斷及解決這些問題。瞭解如何排解各種驗證問題,以及偵錯 kubectl 工具與叢集控制層之間的連線問題。瞭解如何檢查是否已安裝及設定必要外掛程式,並查看 SSH 和 Konnectivity 等服務的網路政策和防火牆注意事項。
如果您使用 kubectl 指令管理 GKE 上的應用程式或叢集資源,請務必瞭解這項資訊。對於依賴 kubectl 指令處理日常核心工作的應用程式開發人員、平台管理員和營運人員來說,這項功能尤其重要。如要進一步瞭解
內容中提及的常見角色和範例工作 Google Cloud
,請參閱「常見的 GKE 使用者角色和
工作」。
如需相關資訊,請參閱下列資源:
- 如要進一步瞭解非 GKE 特有的問題,請參閱 Kubernetes 說明文件中的「排解 kubectl 問題」。
- 如要進一步瞭解如何使用
kubectl指令診斷叢集和工作負載的問題,請參閱「使用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
嘗試執行 kubectl 指令或與 GKE 互動的自訂用戶端時,可能會出現類似下列的錯誤訊息:
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"
如要解決這個問題,請完成下列步驟:
如「安裝必要外掛程式」一節所述,安裝
gke-gcloud-auth-plugin。更新至最新版 gcloud CLI:
gcloud components update更新
kubeconfig檔案:gcloud container clusters get-credentials CLUSTER_NAME \ --location=CONTROL_PLANE_LOCATION更改下列內容:
CLUSTER_NAME:叢集名稱。CONTROL_PLANE_LOCATION:叢集控制層的 Compute Engine 位置。如果是區域叢集,請提供區域;如果是可用區叢集,請提供可用區。
錯誤:gcp 驗證外掛程式已淘汰,請改用 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
驗證外掛程式:
在文字編輯器中開啟 Shell 登入指令碼:
Bash
vi ~/.bashrcZsh
vi ~/.zshrc如果使用 PowerShell,請略過這個步驟。
設定下列環境變數:
Bash
export USE_GKE_GCLOUD_AUTH_PLUGIN=TrueZsh
export USE_GKE_GCLOUD_AUTH_PLUGIN=TruePowerShell
[Environment]::SetEnvironmentVariable('USE_GKE_GCLOUD_AUTH_PLUGIN', True, 'Machine')在環境中套用變數:
Bash
source ~/.bashrcZsh
source ~/.zshrcPowerShell
結束終端機,並開啟新的終端機工作階段。
更新 gcloud CLI:
gcloud components update驗證叢集:
gcloud container clusters get-credentials CLUSTER_NAME \ --location=CONTROL_PLANE_LOCATION更改下列內容:
CLUSTER_NAME:叢集名稱。CONTROL_PLANE_LOCATION:叢集控制層的 Compute Engine 位置。如果是區域叢集,請提供區域;如果是可用區叢集,請提供可用區。
問題:找不到 kubectl 指令
如果收到找不到 kubectl 指令的訊息,請重新安裝 kubectl 二進位檔,並設定 $PATH 環境變數:
安裝
kubectl二進位檔:gcloud components update kubectl安裝程式提示您修改
$PATH環境變數時,請輸入y繼續。修改這個變數後,您可以使用kubectl指令,不必輸入完整路徑。或者,您也可以在殼層儲存環境變數的位置 (例如
~/.bashrc或 macOS 中的~/.bash_profile) 新增下列程式碼:export PATH=$PATH:/usr/local/share/google/google-cloud-sdk/bin/執行下列指令,載入更新後的檔案。以下範例使用
.bashrc:source ~/.bashrc如果使用 macOS,請改用
~/.bash_profile,而非.bashrc。
問題:kubectl 指令傳回「connection refused」錯誤
如果 kubectl 指令傳回「connection refused」錯誤,請使用下列指令設定叢集環境:
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 outUnable to connect to the server: dial tcp IP_ADDRESS: i/o timeout。
這些錯誤表示 kubectl 無法與叢集控制層通訊。
如要解決這個問題,請驗證並設定叢集所在環境,並確保叢集連線正常:
前往
$HOME/.kube/config或執行kubectl config view指令,確認設定檔包含叢集內容和控制層的外部 IP 位址。設定叢集憑證:
gcloud container clusters get-credentials CLUSTER_NAME \ --location=CONTROL_PLANE_LOCATION \ --project=PROJECT_ID更改下列內容:
CLUSTER_NAME:叢集名稱。CONTROL_PLANE_LOCATION:叢集控制層的 Compute Engine 位置。如果是區域叢集,請提供區域;如果是可用區叢集,請提供可用區。PROJECT_ID:叢集建立所在專案的 ID。
如果您已在叢集中啟用授權網路,請確認現有授權網路清單包含您嘗試連線的電腦傳出 IP。您可以在控制台中找到現有的授權網路,也可以執行下列指令:
gcloud container clusters describe CLUSTER_NAME \ --location=CONTROL_PLANE_LOCATION \ --project=PROJECT_ID \ --format "flattened(controlPlaneEndpointsConfig.ipEndpointsConfig.authorizedNetwork sConfig.cidrBlocks[])"如果電腦的輸出 IP 不在先前指令輸出內容的授權網路清單中,請完成下列其中一個步驟:
- 如果您使用控制台,請按照「無法連上沒有外部端點的叢集控制層」一文中的操作說明進行。
- 如果是從 Cloud Shell 連線,請按照「使用 Cloud Shell 存取已停用外部端點的叢集」中的操作說明進行。
錯誤:kubectl 指令傳回「failed to negotiate an api version」(無法協商 API 版本)
如果 kubectl 指令傳回 failed to negotiate an API version 錯誤,請確認 kubectl 具有驗證憑證:
gcloud auth application-default login
問題:kubectl、logs、attach、exec 或 port-forward 指令停止回應
如果 kubectl logs、attach、exec 或 port-forward 指令停止回應,通常表示 API 伺服器無法與節點通訊。
首先,請檢查叢集是否有任何節點。如果叢集中的節點數量已縮減為零,指令將無法運作。如要解決這個問題,請調整叢集大小,使其至少有一個節點。
如果叢集至少有一個節點,請檢查您是否使用 SSH 或 Konnectivity Proxy 通道來啟用安全通訊。以下各節將討論各項服務的專屬疑難排解步驟:
疑難排解 SSH 問題
如果您使用 SSH,GKE 會將安全殼層公開金鑰檔案儲存在 Compute Engine 專案中繼資料中。所有使用 Google 提供映像檔的 Compute Engine VM,都會定期檢查專案的通用中繼資料和執行個體的中繼資料,找出要新增至 VM 授權使用者清單的 SSH 金鑰。GKE 也會在 Compute Engine 網路中新增防火牆規則,允許從控制層的 IP 位址透過 SSH 存取叢集中的每個節點。
下列設定可能會導致 SSH 通訊問題:
網路的防火牆規則不允許從控制層進行 SSH 存取。
所有 Compute Engine 網路都會建立名為
default-allow-ssh的防火牆規則,允許來自所有 IP 位址的 SSH 存取權 (需要有效的私密金鑰)。GKE 也會為每個公開叢集插入gke-CLUSTER_NAME-RANDOM_CHARACTERS-ssh格式的 SSH 規則,允許從叢集的控制層到叢集節點的 SSH 存取。如果這兩項規則都不存在,控制層就無法開啟 SSH 通道。
如要確認這是否為問題原因,請檢查設定是否包含這些規則。
如要解決這個問題,請找出叢集所有節點上的標記,然後重新新增防火牆規則,允許從控制層的 IP 位址存取具有該標記的 VM。
專案的
ssh-keys一般中繼資料項目已達上限。如果專案中名為
ssh-keys的中繼資料項目即將達到大小上限,GKE 就無法新增自己的安全殼層金鑰來開啟 SSH 通道。如要確認這是否為問題,請檢查
ssh-keys清單的長度。您可以執行下列指令,查看專案的中繼資料,並視需要加入--project旗標:gcloud compute project-info describe [--project=PROJECT_ID]如要解決這個問題,請刪除一些不再需要的 安全殼層金鑰。
您已在叢集中的 VM 上,設定鍵為
ssh-keys的中繼資料欄位。VM 上的節點代理程式會優先使用執行個體專屬的安全殼層金鑰,而非專案範圍的安全殼層金鑰,因此如果您已在叢集節點上設定任何安全殼層金鑰,節點就不會採用專案中繼資料中的控制層安全殼層金鑰。
如要確認是否為這個問題,請執行
gcloud compute instances describe VM_NAME,並在 metadata 中尋找ssh-keys欄位。如要解決這個問題,請從執行個體中繼資料刪除個別執行個體的安全殼層金鑰。
排解 Konnectivity Proxy 問題
您可以檢查下列系統 Deployment,判斷叢集是否使用 Konnectivity Proxy:
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
如要解決輸入政策的問題,請在網路政策的 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 偽裝代理程式」。
錯誤:kubectl 指令失敗,並顯示沒有可用的代理程式錯誤
執行需要從 GKE 控制層連線至 Pod 的 kubectl 指令時 (例如 kubectl exec、kubectl logs 或 kubectl
port-forward),指令可能會失敗,並顯示類似下列內容的錯誤訊息:
Error from server: error dialing backend: No agent available
failed to call webhook: Post "https://WEBHOOK_SERVICE.WEBHOOK_NAMESPACE.svc:PORT/PATH?timeout=10s": No agent available
v1beta1.metrics.k8s.io failed with: failing or missing response from https://NODE_IP:10250/apis/metrics.k8s.io/v1beta1: Get "https://NODE_IP:10250/apis/metrics.k8s.io/v1beta1": No agent available
這些錯誤表示 Konnectivity 發生問題,Konnectivity 是 GKE 控制層與叢集節點之間的安全通訊通道。具體來說,這表示控制層上的 konnectivity-server 無法連線至 kube-system 命名空間中任何健康狀態良好的 konnectivity-agent Pod。
如要解決這個問題,請嘗試下列解決方法:
確認
konnectivity-agentPod 的健康狀態:檢查
konnectivity-agentPod 是否正在執行:kubectl get pods -n kube-system -l k8s-app=konnectivity-agent輸出結果會與下列內容相似:
NAME READY STATUS RESTARTS AGE konnectivity-agent-abc123def4-xsy1a 2/2 Running 0 31d konnectivity-agent-abc123def4-yza2b 2/2 Running 0 31d konnectivity-agent-abc123def4-zxb3c 2/2 Running 0 31d查看「
Status」欄中的值。如果 Pod 的狀態為Running,請檢查記錄,找出連線問題。否則,請調查 Pod 未執行的原因。查看記錄檔,瞭解連線問題。如果 Pod 的狀態為
Running,請檢查記錄是否有連線問題。由於kubectl logs指令取決於 Konnectivity,請在Google Cloud 控制台中使用記錄檔探索工具:前往 Google Cloud 控制台的「Logs Explorer」。
在查詢窗格中輸入下列查詢。
resource.type="k8s_container" resource.labels.cluster_name="CLUSTER_NAME" resource.labels.namespace_name="kube-system" labels."k8s-pod/k8s-app"="konnectivity-agent" resource.labels.container_name="konnectivity-agent"將
CLUSTER_NAME替換為叢集名稱。點選「執行查詢」。
查看輸出內容。查看
konnectivity-agent記錄時,請找出指出代理程式無法連線原因的錯誤。驗證或權限錯誤通常表示設定錯誤的 Webhook 封鎖權杖評論。「連線遭拒」或「逾時」錯誤通常表示防火牆規則或網路政策封鎖了 TCP 通訊埠 8132 上傳送至控制層的流量,或是封鎖了 Konnectivity 代理程式和其他節點之間的流量。憑證錯誤表示防火牆或 Proxy 正在檢查並干擾加密的 TLS 流量。
調查 Pod 無法執行的原因。如果 Pod 的狀態為
Pending或其他非執行中狀態,請調查原因。konnectivity-agent會以 Deployment 的形式執行,而非 DaemonSet。由於代理程式 Pod 是以 Deployment 形式執行,因此只需要在部分節點上執行。不過,如果該特定節點子集無法使用,整個服務可能會失敗。Pod 未執行的常見原因包括:
- 防止 Pod 排程的自訂節點 taint。
- 節點資源 (CPU 或記憶體) 不足。
- 封鎖 GKE 系統映像檔的限制性二進位授權政策。
如要進一步瞭解特定 Pod 未執行的原因,請使用
kubectl describe指令:kubectl describe pod POD_NAME -n kube-system將
POD_NAME替換為未執行的 Pod 名稱。
調查准入 Webhook,確保沒有任何 Webhook 封鎖
TokenReviewAPI 要求。konnectivity-agent依賴服務帳戶權杖,因此干擾權杖審查可能會導致代理程式無法連線。如果問題出在 Webhook,Konnectivity 無法復原,直到移除或修復有問題的 Webhook 為止。確認防火牆規則允許從 GKE 節點輸出 TCP 流量,傳向控制層 IP 位址的通訊埠 8132。
konnectivity-agent必須透過這個連線才能連上 Konnectivity 服務。詳情請參閱「允許必要的防火牆存取權」。請確認沒有任何網路政策規則會限制必要的 Konnectivity 流量。網路政策規則應允許
kube-system命名空間內的叢集內流量 (Pod 對 Pod),以及從konnectivity-agentPod 到 GKE 控制層的輸出流量。
排解 kubectl 用戶端節流問題
問題:
使用 kubectl 時,您可能會遇到用戶端節流,錯誤訊息包含下列內容:...Throttling request took 1.002582473s, request: GET:... 或 Waited for 1.183040416s due to client-side throttling, not priority and fairness, request: GET: ...。
原因:
執行 kubectl 指令時,系統會先從 API 伺服器快取資源清單。這份清單對應於 API 伺服器提供的自訂資源定義 (CRD)。
如果 GKE 叢集有大量 CRD (例如 300 個以上),kubectl 會向 API 伺服器傳送大量要求,以建構或重新整理快取。為避免 API 伺服器超載,kubectl 會自行調節。
解決方法:
這類節流錯誤訊息是預期行為,是由 kubectl 端的用戶端節流所導致。這個問題應該會自行解決。
後續步驟
如果說明文件無法解決您的問題,請參閱「取得支援」一文,瞭解如何取得進一步協助,包括下列主題的建議:
- 向 Cloud Customer Care 團隊申請開立支援案件。
- 在 StackOverflow 上提問,並使用
google-kubernetes-engine標記搜尋類似問題,向社群尋求支援。你也可以加入#kubernetes-engineSlack 頻道,取得更多社群支援。 - 使用公開 Issue Tracker 開啟問題或功能要求。