深度解析:AWS NLB 与 ALB 在 EKS 集群中的最佳选择

前言

AWS 提供多种弹性负载均衡器,包括应用程序负载均衡器 (ALB)、网络负载均衡器 (NLB)、网关负载均衡器 (GWLB) 和经典负载均衡器 (CLB)。本文重点介绍 ALB 和 NLB,因为它们是 EKS 集群最相关的选项。

在确定合适的负载均衡器类型时,需要考虑的主要因素是工作负载的具体需求。

什么是应用程序负载均衡器 (ALB)

应用程序负载均衡器 (ALB) 的主要功能是将传入流量分配到多个目标,这些目标可以是:

  • EC2 实例(例如,传统计算服务器、EKS 工作节点、ECS 工作节点)。
  • IP 地址(例如,本地服务器、第三方服务、跨 VPC 实例)。
  • Lambda 函数(例如,用于无服务器应用程序、API 网关的替代方案、混合架构)。

 

以上示例可视化了一个附加了三个目标组的 ALB,每个目标组代表一种特定的目标类型,例如 EC2 实例、IP 地址和 Lambda 函数。

流量可以分配到至少两个或更多可用区。创建 ALB 时,必须指定要在哪些可用区(每个可用区一个子网)中“启用”它。这意味着 ALB 只能将流量分配到已启用的可用区。

更详细地说,您为 ALB 启用的每个可用区实际上都会为该特定 ALB 创建一个实例。如下所示,我们在 3 个公有子网中启用了 ALB,以将流量分配到 EC2 实例,并且创建了 3 个网络接口(每个启用的子网中一个):

 

有趣的是,如果没有为特定 ALB 分配目标,那么最初只会创建一个网络接口;当然,这完全由 AWS 管理,不会以任何方式影响 ALB 的性能。 

什么是网络负载均衡器 (NLB)

网络负载均衡器可以将传入流量分配到多个目标:

  • EC2 实例(例如,传统计算服务器、EKS 工作节点、ECS 工作节点)。
  • IP 地址(例如,本地服务器、第三方服务、跨 VPC 实例)。
  • 应用程序负载均衡器(例如,将 TCP/UDP 流量分流到更高级的 HTTP/HTTPS 路由、混合架构)。

与 ALB 类似,当您创建 NLB 并在特定可用区中启用它时,每个可用区中都会创建一个负载均衡器实例。每个实例由一个网络接口表示:

 负载均衡器如何与EKS集成

负载均衡器接收传入流量,并将其分发到 EKS 集群中托管的目标应用程序的目标上。这提高了应用程序的弹性。当部署到 EKS 集群中时,AWS 负载均衡器控制器将为该集群创建和管理 AWS 弹性负载均衡器。创建 LoadBalancer 类型的 Kubernetes 服务时,AWS 负载均衡器控制器会创建一个网络负载均衡器 (NLB),用于在 OSI 模型的第 4 层对接收到的流量进行负载均衡。而创建 Kubernetes Ingress 对象时,AWS 负载均衡器控制器会创建一个应用程序负载均衡器 (ALB),用于在 OSI 模型的第 7 层对流量进行负载均衡。

何时选择应用程序负载均衡器 (ALB)


对于通过 HTTP/HTTPS 运行的工作负载,请选择应用程序负载均衡器 (ALB)。

如果您的应用程序需要 OSI 模型中的第 7 层负载均衡,AWS 负载均衡器控制器可以预置 ALB,ALB 通过 Ingress 资源进行管理和配置,并将 HTTP 或 HTTPS 流量定向到集群内的各个 Pod。它提供了更改路由算法的灵活性,默认采用循环路由,而 LISTING 请求数算法则作为替代方案。

何时选择网络负载均衡器 (NLB)


如果您的工作负载基于 TCP 或需要为客户端保留源 IP,请选择网络负载均衡器 (NLB)。

NLB 运行在 OSI 模型的传输层(第 4 层),因此适用于使用 TCP 和 UDP 协议的工作负载。默认情况下,NLB 在将流量转发到 Pod 时会保留客户端的原始源 IP 地址。

使用 NLB 的另一个重要考虑因素是客户端无法使用 DNS 的情况。在这种情况下,NLB 通常是更合适的选择,因为它具有静态 IP 地址。虽然建议客户端使用 DNS 将域名解析为用于负载均衡器连接的 IP 地址,但如果客户端的应用程序仅接受硬编码 IP 地址,则 NLB 的静态 IP 地址将是一个更佳的选择。

在EKS中预置负载均衡器


目前有两种主要的 Kubernetes 控制器可用于管理 AWS 负载均衡器实例:

  • 旧版 Kubernetes“云控制器管理器”
  • “AWS 负载均衡器控制器”

旧版控制器


第一种控制器的代码库位于 Kubernetes 代码库中(也称为“in-tree”云控制器)。它已被弃用并迁移到新的外部代码库。

  • in tree(弃用) 

由于已经弃用,不在给出代码库和文档链接

  • out of tree 

代码库

文档

后者需要一些额外的步骤才能启用。

全新 AWS 负载均衡器控制器


原名为 ALB 入口控制器,现已更名为 AWS 负载均衡器控制器,并新增了以下功能和特性:

  • 适用于 Kubernetes 服务的网络负载均衡器 (NLB)
  • 与多个 Kubernetes 入口规则共享 ALB
  • 新增 TargetGroupBinding 自定义资源
  • 支持完全私有集群

因此,它可以用作管理 NLB 实例的控制器,也可以用作 Ingress 控制器(如果您喜欢使用 Ingress 自定义资源)。

我将演示用于 NLB 的全新 AWS 负载均衡器控制器。

为此,我们将使用这个特殊的注解 service.beta.kubernetes.io/aws-load-balancer-type: "external",同时我们还将部署 AWS 负载均衡器控制器,以便在 NLB 上提供更多选项。

EKS 集群设置


如果您已经运行了 EKS 集群,请跳过此部分,直接进入下一部分。

eksctl create cluster \
  --name ${CLUSTER_NAME} \
  --version 1.21 \
  --region ${REGION} \
  --nodegroup-name linux-nodes \
  --nodes 3 \
  --nodes-min 2 \
  --nodes-max 4 \
  --with-oidc \
  --spot \
  --managed

AWS NLB 的 Kubernetes in-tree控制器


这当然不是本文的目的,但了解我们的出发点总是有益的。所以,让我们快速了解一下 AWS ELB 的树内控制器。

CLB


在尝试 NLB 之前,出于好奇,我们创建一个基本服务,类型为 LoadBalancer,不添加任何额外注解,看看 AWS 端会发生什么:
 

kubectl apply -f -<<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
  name: httpbin
  namespace: default
spec:
  replicas: 1
  selector:
    matchLabels:
      app: httpbin
      version: v1
  template:
    metadata:
      labels:
        app: httpbin
        version: v1
    spec:
      containers:
      - image: docker.io/kennethreitz/httpbin
        imagePullPolicy: IfNotPresent
        name: httpbin
        env:
        - name: GUNICORN_CMD_ARGS
          value: "--capture-output --error-logfile - --access-logfile - --access-logformat '%(h)s %(t)s %(r)s %(s)s Host: %({Host}i)s}'"
        ports:
        - containerPort: 80
EOF

kubectl expose deploy httpbin --type LoadBalancer --port 8000 --target-port=80


结果是一个 Classic ELB (CLB) 实例。AWS 建议您迁移到 NLB 实例类型:

NLB


以下是注解的简单配置:

apiVersion: v1
kind: Service
metadata:
  name: httpbin
  namespace: default
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
spec:
  ports:
  - port: 8000
    protocol: TCP
    targetPort: 80
  selector:
    app: httpbin
    version: v1
  type: LoadBalancer

部署 AWS 负载均衡器控制器


因此,AWS 负载均衡器控制器现在是使用 NLB 的推荐方式。

完成IAM 绑定工作: 

export CLUSTER_NAME="my-cluster"
export REGION="eu-central-1"
export AWS_ACCOUNT_ID=XXXXXXXXXX
export IAM_POLICY_NAME=AWSLoadBalancerControllerIAMPolicy
export IAM_SA=aws-load-balancer-controller

# Setup IAM OIDC provider for a cluster to enable IAM roles for pods
eksctl utils associate-iam-oidc-provider \
    --region ${REGION} \
    --cluster ${CLUSTER_NAME} \
    --approve

# Fetch the IAM policy required for our Service-Account
curl -o iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.2.4/docs/install/iam_policy.json

# Create the IAM policy
aws iam create-policy \
    --policy-name ${IAM_POLICY_NAME} \
    --policy-document file://iam-policy.json

# Create the k8s Service Account
eksctl create iamserviceaccount \
--cluster=${CLUSTER_NAME} \
--namespace=kube-system \
--name=${IAM_SA} \
--attach-policy-arn=arn:aws:iam::${AWS_ACCOUNT_ID}:policy/${IAM_POLICY_NAME} \
--override-existing-serviceaccounts \
--approve \
--region ${REGION}

# Check out the new SA in your cluster for the AWS LB controller
kubectl -n kube-system get sa aws-load-balancer-controller -o yaml

 安装AWS load balancer 控制器

kubectl apply -k "github.com/aws/eks-charts/stable/aws-load-balancer-controller/crds?ref=master"

helm repo add eks https://aws.github.io/eks-charts
helm repo update
helm install aws-load-balancer-controller eks/aws-load-balancer-controller \
  -n kube-system \
  --set clusterName=${CLUSTER_NAME} \
  --set serviceAccount.create=false \
  --set serviceAccount.name=${IAM_SA}

 使用 AWS 负载均衡器控制器创建NLB


首先,让我们告诉 Kubernetes 内置云控制器不要处理该服务。AWS 负载均衡器控制器现在会处理这个问题。开关是这个注解:service.beta.kubernetes.io/aws-load-balancer-type
此外,我们希望 NLB 公开可见(默认情况下,它是一个内部 NLB),并且我们希望它处于实例模式(有助于客户端 IP 保护)

注解更改前

service.beta.kubernetes.io/aws-load-balancer-type: "nlb"

 更改后

# use the AWS LB Controller
service.beta.kubernetes.io/aws-load-balancer-type: "external"
# we want an internet-facing NLB
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
# use target groups in instance mode
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "instance"

为了启用backend config,访问日志和健康检查,需要添加更多的注解,下面是完整的注解

apiVersion: v1
kind: Service
metadata:
  name: httpbin
  namespace: default
  annotations:
    # NLB
    service.beta.kubernetes.io/aws-load-balancer-type: "external"
    service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
    service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "instance"

    # Backend
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http" # https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/legacy-cloud-providers/aws/aws.go#L182

    # Access logs
    service.beta.kubernetes.io/aws-load-balancer-access-log-enabled: "true"
    service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-name: "${BUCKET_NAME}"
    service.beta.kubernetes.io/aws-load-balancer-access-log-s3-bucket-prefix: "my-httpbin-app"
    # service.beta.kubernetes.io/aws-load-balancer-access-log-emit-interval: "5" # not yet implemented

    # LB attributes - you can concatenate values separated with comma signs ','
    service.beta.kubernetes.io/aws-load-balancer-attributes: "load_balancing.cross_zone.enabled=false"

    # Health checks
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-healthy-threshold: "2" # https://github.com/kubernetes/kubernetes/blob/master/staging/src/k8s.io/legacy-cloud-providers/aws/aws.go#L209 2 to 20
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-unhealthy-threshold: "2" # 2-10
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-interval: "10" # 10 or 30
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-path: "/status/200"
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-protocol: "HTTP"
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "traffic-port"
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-timeout: "6" # 6 is the minimum

spec:
  ports:
  - port: 8000
    protocol: TCP
    targetPort: 80
  selector:
    app: httpbin
    version: v1
  type: LoadBalancer

 

 使用 AWS 负载均衡器控制器创建ALB

每当在集群上使用 kubernetes.io/ingress.class: alb 注释创建 Kubernetes 入口资源时,AWS 负载均衡器控制器都会创建 ALB 及必要的 AWS 支持资源。入口资源会配置 ALB,以将 HTTP 或 HTTPS 流量路由到集群内的不同 Pod。为确保您的入口对象使用 AWS 负载均衡器控制器,请将以下注释添加到您的 Kubernetes 入口规范中。

annotations:
    kubernetes.io/ingress.class: alb

 下面一个完整的ingress 配置清单文件

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: generic-company-ingress
  annotations:
    kubernetes.io/ingress.class: alb  //使用alb
    alb.ingress.kubernetes.io/scheme: internet-facing。//external alb
    alb.ingress.kubernetes.io/target-type: ip. //使用IP mode,alb 直接和pod通信
    external-dns.alpha.kubernetes.io/hostname: mobile.generic123.net //绑定的域名
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}]' //监听的端口
    alb.ingress.kubernetes.io/group.name: "prod-external" //您可以使用 IngressGroups 在多个服务资源之间共享应用程序负载均衡器
spec:
  rules:
    - host: mobile.generic123.net
      http:
        paths:
          - path: /apple 
            pathType: Exact
            backend:
              service:
                name: ssl-redirect
                port:
                  name: use-annotation
          - path: /apple
            pathType: Exact 
            backend: 
              service:
                name: apple-service
                port:
                  number: 3000
          - path: /android
            pathType: Exact
            backend:
              service:
                name: ssl-redirect
                port:
                  name: use-annotation
          - path: /android
            pathType: Exact
            backend:
              service:
                name: android-service
                port:
                  number: 3000

 

总结

AWS提供了多种弹性负载均衡器,包括应用程序负载均衡器(ALB)、网络负载均衡器(NLB)、网关负载均衡器(GWLB)和经典负载均衡器(CLB)。本文重点介绍ALB和NLB,因为它们是与EKS集群最相关的选项。ALB适用于HTTP/HTTPS工作负载,支持第7层负载均衡,而NLB适用于TCP/UDP工作负载,支持第4层负载均衡,并能保留客户端源IP。在EKS集群中,AWS负载均衡器控制器负责创建和管理这些负载均衡器。选择哪种负载均衡器取决于工作负载的具体需求。此外,AWS负载均衡器控制器还支持NLB的实例模式和ALB的Ingress资源管理,提供了更灵活的配置选项。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云攀登者-望正茂

你的鼓你的鼓励是我前进的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值