跳至内容

如何排查使用 AWS 负载均衡器控制器创建负载均衡器时出现的问题?

4 分钟阅读
0

我想排查尝试使用 AWS 负载均衡器控制器创建负载均衡器时出现的问题。

简短描述

AWS 负载均衡器控制器管理 Amazon Elastic Kubernetes Service (Amazon EKS) 集群的弹性负载平衡。

控制器提供以下资源:

  • 创建 Kubernetes 入口时的应用程序负载均衡器。
  • 创建 LoadBalancer 类型的 Kubernetes 服务时的网络负载均衡器。
    **注意:**使用 AWS 负载均衡器控制器版本 2.3.0 或更高版本,可以创建具有实例或 IP 目标类型的网络负载均衡器。

解决方法

确保您满足安装和使用 AWS 负载均衡器控制器的所有先决条件

有关要执行的初始操作的列表,请参阅先决条件

运行以下命令以验证您是否成功部署了 AWS 负载均衡器控制器

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

如果您使用应用程序负载均衡器,请检查您在不同的可用区中是否有至少两个子网。网络负载均衡器必须至少有一个子网。子网必须至少有八个可用的 IP 地址。有关详细信息,请参阅创建虚拟私有云 (VPC)

在某些情况下,您必须使用以下标签:

  • 键:“kubernetes.io/cluster/cluster-name”
  • 值:“shared”或“owned”

应用程序负载均衡器

在下列情况下,您必须标记一个安全组:

  • 使用附加到一个 Worker 节点的多个安全组。
  • 使用 AWS 负载均衡器控制器版本 v2.1.1 或更早版本。

网络负载均衡器

如果使用 AWS 负载均衡器控制器版本 v2.1.1 或更早版本,必须向子网添加标签

如果您没有在服务或入口注释中指定子网 ID,请确保您的子网具有子网自动发现所需的标签。有关详细信息,请参阅 GitHub 网站上的 Subnet auto discovery(子网自动发现)

对于私有子网,请使用以下标签:

  • 键:“kubernetes.io/role/internal-elb”
  • 值: “1”

对于公有子网,请使用以下标签:

  • 键:“kubernetes.io/role/elb”
  • 值: “1”

检查入口或服务对象的注释

确保服务对象或入口对象上的注释正确无误。

**注意:**在以下命令中,将 SERVICE-NAMEINGRESS-NAMENAMESPACE 替换为您的值。

要查看服务对象,请运行以下命令:

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 负载均衡器控制器支持应用程序负载均衡器的注释列表,请参阅 GitHub 网站上的 Ingress annotations(入口注释)。有关网络负载均衡器支持的注释列表,请参阅 GitHub 网站上的 Service annotations(服务注释)

应用程序负载均衡器

在 1.18 之前的 Kubernetes 版本中,入口类使用引用入口控制器名称的 kubernetes.io/ingress.class 注释。所有更高版本的 Kubernetes 中的入口类都使用引用入口类资源的 ingressClassName 注释。

有关详细信息,请参阅 GitHub 网站上的 Deprecated kubernetes.io/ingress.class annotation(已弃用的 kubernetes.io/ingress.class 注释)

网络负载均衡器

使用以下注释:

  • 对于 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 policy JSON(IAM 策略 JSON)

有关详细信息,请参阅使用 eksctl 创建 IAM 角色

可用区不支持负载均衡器

如果您在受限的可用区中指定子网,则可能会收到一条类似于以下内容的错误消息:

“Load balancers with type 'network' are not supported in availability-zone-name”

要解决此问题,请在另一个不受限的可用区中指定一个子网。然后,使用跨区域负载均衡将流量分配到受限可用区中的目标。

要使用不同的子网,请为用于创建内部网络负载均衡器的子网添加 kubernetes.io/role/internal-elb=1 标签。有关详细信息,请参阅标记网络负载均衡器

或者,添加以下注释以指定服务清单文件中的子网:

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 负载均衡器控制器会自动发现网络子网。对于应用程序负载均衡器,您必须在不同的可用区中至少有两个子网。网络负载均衡器只需要一个子网。

要使自动发现起作用,必须对子网应用相应的标签。控制器从每个可用区中选择一个子网。如果一个可用区有多个带标签的子网,则控制器仅根据按字母顺序排列的子网 ID 选择一个子网。

有关私有和公有子网所需子网标签的详细信息,请参阅 GitHub 网站上的 Subnet auto discovery(子网自动发现)

存在证书管理器或 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 容器组是否正在运行。

要获取容器组状态,请运行以下命令:

kubectl describe pod your-pod-name -n your-namespace

要收集日志,请运行以下命令:

kubectl logs your-pod-name -n your-namespace

**注意:**在前面的命令中,将 your-pod-name 替换为您的容器组名称,将 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 网站上的 Controller configuration options(控制器配置选项)

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”

出现此错误是因为您错误地配置了服务账户 (IRSA) 的 IAM 角色。

要解决此问题,请在服务账户中使用正确的角色,并为该角色定义信任策略。

有关详细信息,请参阅为什么我在 Amazon EKS 中使用 AWS 负载均衡器控制器时收到了“WebIdentityErr”错误?以及如何对 Amazon EKS 中的 OIDC 提供商和 IRSA 问题进行故障排除?

控制器容器组日志中的数据不足

如果您需要的调试信息比默认控制器容器组日志提供的还要多,请在控制器容器组配置中添加 --log-level debug 标志。

有关详细信息,请参阅 GitHub 网站上的 Controller command line flags(控制器命令行标志)

查看 AWS 负载均衡器控制器容器组的日志,以获取更多信息

要查看 AWS 负载均衡器控制器日志,请运行以下命令:

kubectl logs -n kube-system deployment.apps/aws-load-balancer-controller

如果存在问题,则会出现“Reconciler error”。此外,还会收到一条详细的错误消息,说明入口对象或负载均衡器服务无法创建或更新的原因。

出现此问题的原因可能如下:

如果控制器容器组均未显示日志,请运行以下命令以确认控制器容器组正在运行:

kubectl get deployment -n kube-system aws-load-balancer-controller

升级到支持的控制器版本

如果您使用不再支持的 AWS 负载均衡器控制器版本,则无法升级到更高版本。您必须移除现有控制器,然后安装最新版本

使用 AWS 负载均衡器控制器而不是传统的云提供商

Kubernetes 包括一个传统的 AWS 云提供商,可以提供经典负载均衡器。如果您不安装 AWS 负载均衡器控制器,则 Kubernetes 会使用传统的云提供商。但最佳做法是使用 AWS 负载均衡器控制器。

AWS 负载均衡器控制器版本 2.5 及更高版本是 LoadBalancer 类型的 Kubernetes 服务资源的默认控制器。它们为每项服务创建网络负载均衡器。最新版本还为服务实现了变异 Webhook。对于新类型的负载均衡器服务,它们将 spec.loadBalancerClass 字段设置为 service.k8s.aws/nlb

要升级到 AWS 负载均衡器控制器,请运行以下命令:

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 替换为您的集群名称。

如果您必须使用传统的云提供商,请将 enableServiceMutatorWebhook Helm 图表值设置为 false,这样就不会提供新的经典负载均衡器。只有现有的经典负载均衡器可以继续运行。

验证是否为入口或服务对象所在的命名空间创建了 Fargate 配置文件

当目标容器组在 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-NAMEREGIONFARGATE-PROFILE-NAMENAMESPACE 替换为您的值。

检查您是否符合流量路由要求

为确保满足所有要求,请参阅应用程序负载均衡器的先决条件和网络负载均衡器的先决条件。例如,如果使用应用程序负载均衡器,则服务对象必须指定 NodePortLoadBalancer 才能使用实例流量模式。

Amazon EKS 会在节点的安全组中添加以下规则:

  • 客户端流量的入站规则
  • 创建每个网络负载均衡器时 VPC 中每个负载均衡器子网的入站规则(用于运行状况检查)

如果 Amazon EKS 添加的规则导致您的安全组超过最大规则数,则您的负载均衡器部署可能会失败。

AWS 官方已更新 4 个月前