在 Day 16 我們已經透過 Ingress NGINX 建立了 L7 規則的流量入口,但這還不夠。要讓外部流量真的打進來,還需要有 AWS 端的 Load Balancer。這就是今天的主角 —— AWS Load Balancer Controller (LBC)。
它的角色是:幫我們把 Kubernetes 的 Service / Ingress,對應到 AWS 上的 NLB / ALB。
雖然我們使用 Helm 這個工具來部署,但 AWS Load Balancer Controller 本質上是一個 Kubernetes Controller。它監控叢集中的 Ingress 與 Service(type=LoadBalancer),且基本上只做兩件事:
並且 LB Controller 會以 Pod 的形式跑在 cluster 中。簡單來說,它不是負載平衡器本身,而是把「K8s 資源」翻譯成「AWS Load Balancer」的橋樑。
至於什麼情境下要採用哪種 Load Balancer 的架構呢?我們可以從「誰當 ingress controller」的角度切入。當我們採用 ALB 時,等於將 ingress controller 設置為 ALB;這樣做的好處是,AWS 幫忙管理 ingress controller,不需要自己維護,不過同時這也代表我們能操控的彈性下降。至於如果我們採用 NLB,也就是將 nginx 等工具設置為 ingress controller 時,雖然管理上可能會有額外成本,但我們對於路由規則會有更高度的掌握,可以調整各式各樣的客製化規則。
我們一樣用 ApplicationSet + Helm Chart 來部署 LB Controller:
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: load-balancer-controller
  namespace: {{ .Values.applicationSetNs }}
spec:
  goTemplate: true
  goTemplateOptions: ["missingkey=error"]
  generators:
    - git:
        repoURL: {{ .Values.repoURL }}
        revision: main
        directories:
          - path: infra-charts/load-balancer-controller/*-internal
          - path: infra-charts/load-balancer-controller/in-cluster/*-internal
  template:
    metadata:
      name: '{{"{{"}} .path.basename {{"}}"}}-load-balancer-controller'
    spec:
      project: {{ .Values.project }}
      sources:
        - repoURL: 'https://aws.github.io/eks-charts'
          chart: aws-load-balancer-controller
          targetRevision: 1.6.2
          helm:
            releaseName: aws-load-balancer-controller
            valueFiles:
              - $sharedValues/infra-charts/load-balancer-controller/shared-values.yaml
              - $sharedValues/{{"{{"}} .path.path {{"}}"}}/values.yaml
        - repoURL: {{ .Values.repoURL }}
          targetRevision: main
          ref: sharedValues
      destination:
        name: '{{"{{"}} index .path.segments 2 {{"}}"}}'
        namespace: kube-system
  syncPolicy:
    preserveResourcesOnDeletion: true
🔑 注意:ApplicationSet 使用上有些特殊語法,基本 template 細節可以參考文件。另外我們採用的是 Git Generator,這個 generator 可用的參數也可以參考這篇文件。
此外,這邊的 value files 架構與昨天相同,因此不再贅述架構細節。我只會在程式碼裡面的註解,寫上需要注意的地方哦 O.<
Shared values 範例
replicaCount: 1
rbac:
  create: true
serviceAccount:
  create: true
  name: aws-load-balancer-controller
### 昨天在 ingress-nginx 部署時已指定為 nginx
createIngressClassResource: false 
region: ap-northeast-1
### 我們讓 infra-charts 都會跑在 system nodes 上面
tolerations:
  - key: SystemOnly
    operator: Exists
podLabels:
  app: "aws-load-balancer-controller"
nodeSelector:
  usage: system
Cluster values 範例
replicaCount: 1
clusterName: example-internal
### 給定 LB Controller Role,因為他需要開 NLB 的權限
serviceAccount:
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::XXXXXXXXXXXX:role/load-balancer-controller
region: ap-northeast-1
vpcId: vpc-xxxxxxxxxxxxxxxxx
resources:
  requests:
    memory: 50Mi
在 Day 16 我們先留白,現在來補充:這些 annotation 是 LBC 判斷要怎麼建立 NLB 的「提示」,必須寫在 Service 本身,因為 Service(type=LoadBalancer) 才是聲明「要建外部 LB」的物件。
Shared values(跨叢集共用設定)
### 前兩項設定 external + internet-facing → 建立外部 NLB
service.beta.kubernetes.io/aws-load-balancer-type: external
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
### 透過 service 直送 Pod
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
### TLS 在 NLB 終結(SSL ports=https),轉發給 NGINX 時用 HTTP
service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https"
service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http
### 保留 client ip
service.beta.kubernetes.io/aws-load-balancer-target-group-attributes: preserve_client_ip.enabled=true
Cluster values(每個叢集差異設定)
### 指定 NLB 名稱(方便辨識)
service.beta.kubernetes.io/aws-load-balancer-name: example-internal
### 指定 NLB 落在哪些子網(public / private)
service.beta.kubernetes.io/aws-load-balancer-subnets: subnet-id1, subnet-id2
### 指定 ACM 憑證 ARN,讓 NLB 綁定 TLS 憑證
service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:ap-northeaxxx
最後我們的 client request 流量會如下圖:



今天我們安裝了 AWS Load Balancer Controller,讓 Kubernetes 的 Ingress 與 Service 能自動對應到 AWS 的 ALB / NLB:
有了 LBC,流量不只進得來,還能正確落到 AWS 的 LB 上。
接下來在 Day 18,我們會介紹 ExternalDNS,讓 ALB / NLB 自動綁定 DNS,不需要再手動更新 Route53。