如何對使用 AWS 負載平衡器控制器建立負載平衡器時出現的問題進行疑難排解?
我想對在使用 AWS Load Balancer Controller建立負載平衡器時發生的問題進行疑難排解。
簡短說明
AWS Load Balancer Controller 可管理 Amazon Elastic Kubernetes Service (Amazon EKS) 叢集的 Elastic Load Balancing。
該控制器提供以下資源:
- 當您建立 Kubernetes 輸入時,提供 Application Load Balancer。
- 當您建立 LoadBalancer 類型的 Kubernetes 服務時,提供 Network Load Balancer。
**注意:**在 AWS Load Balancer Controller 版本 2.3.0 或更新版本中,您可以使用執行個體或 IP 目標類型建立 Network Load Balancer。
解決方法
確認您已滿足安裝及使用 AWS Load Balancer Controller 的所有先決條件
有關初始操作清單,請參閱先決條件。
執行以下命令來確認您已成功部署 AWS Load Balancer Controller:
kubectl get deployment -n kube-system aws-load-balancer-controller
**注意:**最佳實務是使用版本 2.4.4 或更新版本。
輸出範例:
NAME READY UP-TO-DATE AVAILABLE AGE aws-load-balancer-controller 2/2 2 2 84s
如果您使用 Application Load Balancer,請確認在不同可用區域中至少有兩個子網路。Network Load Balancer 必須至少有一個子網路。子網路必須至少有八個可用 IP 位址。如需更多資訊,請參閱建立虛擬私有雲端 (VPC)。
在某些情境中,您必須使用以下標籤:
- 索引鍵:「kubernetes.io/cluster/cluster-name」
- 值:「shared」或「owned」
Application Load Balancers
在以下情境中,您必須標記一個安全群組:
- 您使用多個附加到工作節點的安全群組。
- 您使用 AWS Load Balancer Controller 版本 v2.1.1 或更舊版本。
Network Load Balancer
如果您使用的是 AWS Load Balancer Controller 版本 v2.1.1 或更舊版本,您必須將標籤新增至子網路。
如果您未在服務或輸入註解中指定子網路 ID,請確保您的子網路具有子網路自動探索所需的標籤。如需更多資訊,請參閱 GitHub 網站上的子網路自動探索。
若為私有子網路,請使用以下標籤:
- 索引鍵:「kubernetes.io/role/internal-elb」
- 值: 「1」
若為公有子網路,請使用以下標籤:
- 索引鍵:「kubernetes.io/role/elb」
- 值: 「1」
查看輸入或服務物件的註解
確保服務物件或輸入物件上的註解正確。
**注意:**在以下命令中,將 SERVICE-NAME、INGRESS-NAME 和 NAMESPACE 替換為您的值。
若要查看服務物件,請執行以下命令:
kubectl describe service SERVICE-NAME -n NAMESPACE
若要查看輸入物件,請執行以下命令:
kubectl describe ingress INGRESS-NAME -n NAMESPACE
若要編輯服務物件,請執行以下命令:
kubectl edit service SERVICE-NAME -n NAMESPACE
若要編輯輸入物件,請執行以下命令:
kubectl edit ingress INGRESS-NAME -n NAMESPACE
其他註解使用預設值。有關 AWS Load Balancer Controller 支援的 Application Load Balancer 註解清單,請參閱 GitHub 網站上的輸入註解。有關 Network Load Balancer 支援的註解清單,請參閱 GitHub 網站上的服務註解。
應用程式負載平衡器
在 Kubernetes 1.18 版本之前,輸入類別使用 kubernetes.io/ingress.class 註解來參考輸入控制器名稱。在 Kubernetes 後續所有版本中,輸入類別都使用 ingressClassName 註解來參考輸入類別資源。
如需更多資訊,請參閱 GitHub 網站上的已棄用的 kubernetes.io/ingress.class 註解。
Network Load Balancer
使用以下註解:
- 使用 IP 目標時,請使用 service.beta.kubernetes.io/aws-load-balancer-type: "external" 和 service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "ip"。
- 使用執行個體目標時,請使用 service.beta.kubernetes.io/aws-load-balancer-type: "external" 和 service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "instance"。
對在 Amazon EKS 中建立輸入或服務類型負載平衡器時發生的問題進行疑難排解
您收到「AccessDenied」錯誤
您收到以下錯誤訊息:
「Failed deploy model due to AccessDenied」
會發生此錯誤是因為建立資源的 elasticloadbalancing:AddTags 權限已變更。若要解決此問題,請將最新的 AWS Identity and Access Management (IAM) 政策附加到 AWSLoadBalancerController 角色。若要取得最新政策,請參閱 GitHub 網站上的 IAM 政策 JSON。
如需更多資訊,請參閱使用 eksctl 建立 IAM 角色。
該負載平衡器不支援在此可用區域中使用
如果您在受限制的可用區域中指定子網路,那麼您可能會收到類似以下的錯誤訊息:
「Load balancers with type 'network' are not supported in availability-zone-name」
若要解決此問題,請在未受限制的另一個可用區域中指定子網路。然後,使用跨區域負載平衡將流量分配到受限制可用區域的目標。
若要使用不同子網路,請為用於建立內部 Network Load Balancer 的子網路新增 kubernetes.io/role/internal-elb=1 標籤。如需更多資訊,請參閱標記 Network Load Balancer。
或者,將以下註解新增到服務資訊清單檔案中以指定子網路:
service.beta.kubernetes.io/aws-load-balancer-subnets: subnet-xxxx, mySubnet
**注意:**將 subnet-xxxx 替換為您的子網路 ID,將 mySubnet 替換為您的子網路名稱。
您無法對子網路使用自動探索
如果您未為自動探索標記子網路,則可能會收到以下錯誤訊息:
「couldn't auto-discover subnets: unable to resolve at least one subnet」
AWS Load Balancer Controller 預設會自動探索網路子網路。對於 Application Load Balancer,您必須在不同可用區域中至少有兩個子網路。Network Load Balancer 僅需要一個子網路。
若要使自動探索正常運作,您必須將適當的標籤套用到子網路。控制器會從每個可用區域選取一個子網路。如果某個可用區域有多個標記子網路,則控制器只會根據子網路 ID 的字母順序選擇一個。
如需更多私有與公有子網路所需子網路標籤的資訊,請參閱 GitHub 網站上的子網路自動探索。
Certificate Manager 或 webhook 組態發生問題
如果您的 webhook 驗證失敗,您可能會收到以下錯誤訊息:
「Internal error occurred: failed calling webhook "vingress.elbv2.k8s.aws": Post "https://aws-load-balancer-webhook-service.kube-system.svc:443/validate-networking-v1beta1-ingress?timeout=10s": x509: certificate has expired or is not yet valid」
當 AWS Certificate Manager (ACM) 管理的 webhook 憑證存在問題時,就會發生此錯誤。
若要解決此問題,請檢查 Certificate Manager Pod 是否正在運作。
若要取得 Pod 狀態,請執行以下命令:
kubectl describe pod your-pod-name -n your-namespace
若要收集日誌,請執行以下命令:
kubectl logs your-pod-name -n your-namespace
**注意:**在上述命令中,將 your-pod-name 替換為您的 Pod 名稱,將 your-namespace 替換為您的命名空間名稱。
目標群組繫結建立失敗
如果目標群組繫結建立失敗,您可能會收到以下錯誤訊息:
「Warning FailedDeployModel 11m (x2 over 39m) ingress Failed deploy model due to Internal error occurred: failed calling webhook "vtargetgroupbinding.elbv2.k8s.aws": failed to call webhook: Post "https://aws-load-balancer-webhook-service.kube-system.svc:443/validate-elbv2-k8s-aws-v1beta1-targetgroupbinding?timeout=10s": context deadline exceeded」
當安全群組限制阻擋對 webhook 服務的存取時,就會發生此錯誤。該服務預設使用 9443 連接埠。
若要解決此問題,請修改節點的安全群組。允許控制平面安全群組對 9443 連接埠的傳入流量。如需更多資訊,請參閱 GitHub 網站上的控制器組態選項。
節點角色的 AssumeRoleWithWebIdentity 失敗
如果您的節點角色無法擔任您在服務帳戶中指定的角色,您可能會收到以下錯誤訊息:
「WebIdentityErr: failed to retrieve credentials\ncaused by: AccessDenied: Not authorized to perform sts:AssumeRoleWithWebIdentity\n\tstatus code: 403, request id: c6241a7d-d8a8-452c-bb67-bf1ff9bab0c0」
會發生此錯誤是因為您的 IAM Roles for Service Accounts (IRSA) 設定不正確。
若要解決此問題,請在服務帳戶中使用正確的角色,並為該角色定義信任政策。
如需更多資訊,請參閱為何使用 AWS Load Balancer Controller 時會出現「WebIdentityErr」錯誤?以及如何在 Amazon EKS 對 OIDC 提供者與 IRSA 進行疑難排解?
控制器 Pod 日誌中的資料不足
如果您需要比預設控制器 Pod 日誌提供的更多除錯資訊,請在控制器 Pod 組態中新增 --log-level debug 旗標。
如需更多資訊,請參閱 GitHub 網站上的控制器命令列旗標。
查看 AWS Load Balancer Controller pod 的日誌以取得更多資訊
若要查看 AWS Load Balancer Controller 日誌,請執行以下命令:
kubectl logs -n kube-system deployment.apps/aws-load-balancer-controller
如果存在問題,您會看到「Reconciler error」。您還會看到詳細錯誤訊息,說明輸入物件或負載平衡器服務無法建立或更新的原因。
出現此失敗的原因如下:
- 如果錯誤發生在控制器嘗試進行 AWS API 呼叫時,則可能是權限或連線發生問題。請查看控制器的 IAM 權限。然後,確保安全群組或網路存取控制清單 (網路 ACL) 未明確拒絕傳出連線。
- 如果錯誤發生在物件組態中,則可能是輸入或服務的規格或註解設定錯誤。請查看 GitHub 網站上 Application Load Balancer 或 Network Load Balancer 的註解。
如果沒有任何控制器 Pod 顯示日誌,請執行以下命令,以確認控制器 Pod 是否正在運作:
kubectl get deployment -n kube-system aws-load-balancer-controller
升級到支援的控制器版本
如果您使用的 AWS Load Balancer Controller 版本已不再受支援,則無法升級至更新版本。您必須移除現有控制器,然後安裝最新版本。
使用 AWS Load Balancer Controller 而非舊版雲端提供者
Kubernetes 包含針對 AWS 的舊版雲端提供者,可提供 Classic Load Balancers。如果您未安裝 AWS Load Balancer Controller,則 Kubernetes 將使用舊版雲端提供者。但最佳實務是使用 AWS Load Balancer Controller。
AWS Load Balancer Controller 版本 2.5 及更新版本是 Kubernetes LoadBalancer 類型服務資源的預設控制器。它們會為各個服務建立 Network Load Balancer。最新版本還可為服務實作變更型 webhook。它們將 spec.loadBalancerClass 欄位設定為 service.k8s.aws/nlb,用於新的 LoadBalancer 服務類型。
若要升級至 AWS Load Balancer Controller,請執行以下命令:
helm upgrade aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system --set clusterName=CLUSTER-NAME --set serviceAccount.create=false --set serviceAccount.name=aws-load-balancer-controller --set enableServiceMutatorWebhook=false
**注意:**將 CLUSTER-NAME 替換為您的叢集名稱。
如果您必須使用舊版雲端提供者,請將 Helm 圖表值 enableServiceMutatorWebhook 設為 false,以避免提供新的 Classic Load Balancers。只有現有的 Classic Load Balancers 會繼續運作。
確認您已為輸入或服務物件所在的命名空間建立了 Fargate 設定檔
當目標 Pod 在 AWS Fargate 上執行時,您必須加入 IP 目標類型。若要確認您在輸入或服務物件所在的命名空間擁有 Fargate 設定檔,請執行以下命令:
eksctl get fargateprofile --cluster CLUSTER-NAME -o yaml
**注意:**將 CLUSTER-NAME 替換為您的叢集名稱。
若要建立 Fargate 設定檔,請執行下列命令:
eksctl create fargateprofile --cluster CLUSTER-NAME --region REGION --name FARGATE-PROFILE-NAME --namespace NAMESPACE
**注意:**將 CLUSTER-NAME、REGION、FARGATE-PROFILE-NAME 與 NAMESPACE 替換為您的值。
確認您符合流量路由的要求
為確保您符合所有要求,請參閱 Application Load Balancer 的先決條件 以及 Network Load Balancer 的先決條件。例如,如果您使用 Application Load Balancer,則服務物件必須指定 NodePort 或 LoadBalancer 以使用執行個體流量模式。
Amazon EKS 會向節點的安全群組新增以下規則:
- 針對用戶端流量的傳入規則
- 針對每個您為運作狀態檢查建立的 Network Load Balancer 的 VPC 負載平衡器子網路新增傳入規則
如果 Amazon EKS 新增的規則導致安全群組超過最大規則數,則您的負載平衡器部署可能會失敗。
- 語言
- 中文 (繁體)
