建立應用程式負載平衡器 (ALB)

本主題說明如何使用 GKE on AWS 設定 AWS Application Load Balancer (ALB)。

事前準備

開始使用 GKE on AWS 前,請務必完成下列工作:

  • 具備為負載平衡器建立 AWS IAM 政策、角色和使用者的權限。
  • 安裝管理服務
  • 建立使用者叢集。如果使用 Workload Identity,請使用 Workload Identity 建立使用者叢集
  • anthos-aws 目錄中,使用 anthos-gke 將環境切換至使用者叢集。
    cd anthos-aws
    env HTTPS_PROXY=http://localhost:8118 \
      anthos-gke aws clusters get-credentials CLUSTER_NAME
    CLUSTER_NAME 替換為使用者叢集名稱。
  • 安裝 curl 指令列工具或類似工具。

標記子網路

GKE on AWS 需要在包含 ALB 端點的子網路上加上標籤。GKE on AWS 會自動標記 AWSCluster 資源的 spec.Networking.ServiceLoadBalancerSubnetIDs 欄位中指定的所有子網路。

如果您已將 GKE on AWS 安裝到現有 VPC 中,或想使用其他子網路,請在兩個以上的 AWS 可用區中,將標記套用至子網路。

在 GKE on AWS 上設定 ALB

建立 ALB 之前,請先設定 AWS IAM 權限並提供存取金鑰,藉此設定 GKE on AWS。

建立 AWS IAM 權限

如要為使用者叢集建立 ALB,您必須設定 AWS IAM 使用者,並授予建立及運作 ALB 的權限。

  1. 下載 ALB Ingress 控制器的 IAM 政策。您可以在 GitHub 上查看政策。

    curl -o iam-policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.0/docs/install/iam_policy.json
    
  2. 使用 aws 指令列工具建立名為 ALBIngressControllerIAMPolicy 的 IAM 政策。

    aws iam create-policy \
      --policy-name ALBIngressControllerIAMPolicy \
      --policy-document file://iam-policy.json
    

    回應會包含 IAM 政策的 Amazon 資源名稱 (ARN)。儲存 ARN 以供日後使用。

授予負載平衡器存取權

在本節中,您會將使用者政策與 AWS IAM 使用者建立關聯,或是與已設定工作負載身分識別的 IAM 角色建立關聯。

IAM 使用者

  1. 使用 aws 工具為 ALB Ingress 控制器建立 IAM 使用者。

    aws iam create-user \
    --user-name ALB_CONTROLLER_USER_NAME
    

    ALB_CONTROLLER_USER_NAME 替換為要為 ALB Ingress 控制器建立的使用者名稱。

  2. ALBIngressControllerIAMPolicy 附加至使用者名稱。

    aws iam attach-user-policy \
     --user-name ALB_CONTROLLER_USER_NAME \
     --policy-arn ALB_IAM_POLICY_ARN
    

    更改下列內容:

    • ALB_CONTROLLER_USER_NAME,並將使用者名稱改為要為 ALB Ingress 控制器建立的名稱。
    • ALB_IAM_POLICY_ARN,換成您稍早建立的 IAM 政策 ARN。
  3. 為 ALB Ingress 控制器使用者建立 AWS IAM 存取金鑰。

    aws iam create-access-key --user-name ALB_CONTROLLER_USER_NAME
    

    ALB_CONTROLLER_USER_NAME 替換為要為 ALB Ingress 控制器建立的使用者名稱。

    aws 指令列工具會輸出存取金鑰的詳細資料。

    {
      "AccessKey": {
        "UserName": ALB_CONTROLLER_USER_NAME
        "AccessKeyId": "AKIAIOSFODNN7EXAMPLE",
        "Status": "Active",
        "SecretAccessKey": "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY",
        "CreateDate": "2020-07-23T17:53:58Z"
      }
    }
    
  4. 將存取金鑰和存取密鑰儲存到環境變數中。 您將使用這些值設定使用者叢集。

    ALB_ACCESS_KEY_ID=ACCESS_KEY_ID
    ALB_SECRET_ACCESS_KEY=SECRET_ACCESS_KEY
    
  5. 使用存取金鑰和私密存取金鑰,在叢集中建立密鑰。 ALB Ingress 控制器會使用這個 Secret 向 AWS 進行驗證,並管理 ALB。

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl create secret generic alb-ingress-controller-creds \
      -n kube-system \
      --from-literal=access_key_id=$ALB_ACCESS_KEY_ID \
      --from-literal=secret_access_key=$ALB_SECRET_ACCESS_KEY
    

具有 Workload Identity 的角色

完成「使用 Workload Identity 建立使用者叢集」中的步驟。建立政策時,請使用 ALBIngressControllerIAMPolicy 的 ARN 做為 EXISTING_AWS_POLICY 的值。

設定叢集

如要設定 ALB,您需要在使用者叢集中安裝下列元件:

  1. 從 GitHub 安裝資訊清單,部署 Jetstack cert-manager。

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl apply \
      --validate=false \
      -f https://github.com/jetstack/cert-manager/releases/download/v1.5.4/cert-manager.yaml
    
  2. 從 GitHub 下載 AWS Load Balancer Controller 資訊清單:

    curl -Lo v2_4_0_full.yaml https://github.com/kubernetes-sigs/aws-load-balancer-controller/releases/download/v2.4.0/v2_4_0_full.yaml
    
  3. 選取您是否使用 IAM 使用者或具備 Workload Identity 的角色。

    IAM 使用者

    編輯 v2_4_0_full.yaml 檔案,然後搜尋 kind: Deployment。以這個修改後的版本取代 Deployment 物件。

    kind: Deployment
    metadata:
      labels:
        app.kubernetes.io/component: controller
        app.kubernetes.io/name: aws-load-balancer-controller
      name: aws-load-balancer-controller
      namespace: kube-system
    spec:
      replicas: 1
      selector:
      matchLabels:
        app.kubernetes.io/component: controller
        app.kubernetes.io/name: aws-load-balancer-controller
      template:
        metadata:
          labels:
            app.kubernetes.io/component: controller
            app.kubernetes.io/name: aws-load-balancer-controller
        spec:
          containers:
            - args:
              - --cluster-name=CLUSTER_UID
              - --aws-region=AWS_REGION
              - --aws-vpc-id=AWS_VPC_ID
              - --ingress-class=alb
              - --disable-restricted-sg-rules=true
            image: amazon/aws-alb-ingress-controller:v2.4.0
            env:
            - name: AWS_ACCESS_KEY_ID
              valueFrom:
                secretKeyRef:
                  name: alb-ingress-controller-creds
                  key: access_key_id
            - name: AWS_SECRET_ACCESS_KEY
              valueFrom:
                secretKeyRef:
                  name: alb-ingress-controller-creds
                  key: secret_access_key
            livenessProbe:
              failureThreshold: 2
              httpGet:
                path: /healthz
                port: 61779
                scheme: HTTP
              initialDelaySeconds: 30
              timeoutSeconds: 10
            name: controller
            ports:
            - containerPort: 9443
              name: webhook-server
              protocol: TCP
            resources:
              limits:
                cpu: 200m
                memory: 500Mi
              requests:
                cpu: 100m
                memory: 200Mi
            securityContext:
              allowPrivilegeEscalation: false
              readOnlyRootFilesystem: true
              runAsNonRoot: true
            volumeMounts:
            - mountPath: /tmp/k8s-webhook-server/serving-certs
              name: cert
              readOnly: true
          priorityClassName: system-cluster-critical
          securityContext:
            fsGroup: 1337
          serviceAccountName: aws-load-balancer-controller
          terminationGracePeriodSeconds: 10
          volumes:
          - name: cert
            secret:
              defaultMode: 420
              secretName: aws-load-balancer-webhook-tls
        ---
    

    更改下列內容:

    • AWS_ACCESS_KEY_ID:建立 AWS IAM 使用者時產生的 AWS 存取金鑰
    • AWS_SECRET_ACCESS_KEY:建立 AWS IAM 使用者時產生的 AWS 存取密鑰

    具有 Workload Identity 的角色

    編輯 v2_4_0_full.yaml 檔案,然後搜尋 kind: Deployment。將整個 Deployment 物件替換為這個修改後的版本:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app.kubernetes.io/component: controller
        app.kubernetes.io/name: aws-load-balancer-controller
      name: aws-load-balancer-controller
      namespace: kube-system
    spec:
      replicas: 1
      selector:
        matchLabels:
          app.kubernetes.io/component: controller
          app.kubernetes.io/name: aws-load-balancer-controller
      template:
        metadata:
          labels:
            app.kubernetes.io/component: controller
            app.kubernetes.io/name: aws-load-balancer-controller
        spec:
          containers:
          - args:
            - --cluster-name=CLUSTER_UID
            - --aws-region=AWS_REGION
            - --aws-vpc-id=AWS_VPC_ID
            - --ingress-class=alb
            - --disable-restricted-sg-rules=true
            image: amazon/aws-alb-ingress-controller:v2.4.0
            env:
            - name: AWS_ROLE_ARN
              value: LB_CONTROLLER_ROLE_ARN
            - name: AWS_WEB_IDENTITY_TOKEN_FILE
              value: /var/run/secrets/aws-load-balancer-controller/serviceaccount/token
            livenessProbe:
              failureThreshold: 2
              httpGet:
                path: /healthz
                port: 61779
                scheme: HTTP
              initialDelaySeconds: 30
              timeoutSeconds: 10
            name: controller
            ports:
            - containerPort: 9443
              name: webhook-server
              protocol: TCP
            resources:
              limits:
                cpu: 200m
                memory: 500Mi
              requests:
                cpu: 100m
                memory: 200Mi
            securityContext:
              allowPrivilegeEscalation: false
              readOnlyRootFilesystem: true
              runAsNonRoot: true
            volumeMounts:
            - mountPath: /tmp/k8s-webhook-server/serving-certs
              name: cert
              readOnly: true
            - mountPath: /var/run/secrets/aws-load-balancer-controller/serviceaccount
              name: aws-iam-token
              readOnly: true
          priorityClassName: system-cluster-critical
          securityContext:
            fsGroup: 1337
          serviceAccountName: aws-load-balancer-controller
          terminationGracePeriodSeconds: 10
          volumes:
          - name: cert
            secret:
              defaultMode: 420
              secretName: aws-load-balancer-webhook-tls
          - name: aws-iam-token
            projected:
              defaultMode: 420
              sources:
              - serviceAccountToken:
                  audience: sts.amazonaws.com
                  expirationSeconds: 86400
                  path: token
    ---
    

    更改下列內容:

    • CLUSTER_UID:叢集的 UID,例如: bbc7d232-21f6-4bb1-90dd-4b064cf8ccf8
    • AWS_VPC_ID:AWS 虛擬私有雲的 ID,例如 vpc-1234567890abc
    • LB_CONTROLLER_ROLE_ARN:AWSLBControllerRole 角色的 ARN
    • AWS_REGION:叢集的 AWS 區域,例如 us-east-1
  4. 將控制器套用至叢集。

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl apply -f v2_4_0_full.yaml
    

    GKE on AWS 會安裝 ALB Ingress 控制器。

建立 ALB

在本節中,您將建立範例 ALB,提供 2048 遊戲的重製版。

  1. 將下列 YAML 設定複製到名為 2048.yaml 的檔案中。這項設定會建立 Kubernetes 命名空間、服務和部署作業。Deployment 會透過 Ingress 公開。

    apiVersion: v1
    kind: Namespace
    metadata:
      name: "2048-game"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: "service-2048"
      namespace: "2048-game"
    spec:
      ports:
        - port: 80
          targetPort: 80
          protocol: TCP
      type: NodePort
      selector:
        app: "2048"
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: "2048-deployment"
      namespace: "2048-game"
    spec:
      selector:
        matchLabels:
          app: "2048"
      replicas: 5
      template:
        metadata:
          labels:
            app: "2048"
        spec:
          containers:
          - image: alexwhen/docker-2048
            imagePullPolicy: Always
            name: "2048"
            ports:
            - containerPort: 80
    ---
    apiVersion: extensions/v1beta1
    kind: Ingress
    metadata:
      name: "2048-ingress"
      namespace: "2048-game"
      annotations:
        kubernetes.io/ingress.class: alb
        alb.ingress.kubernetes.io/scheme: internet-facing
      labels:
        app: 2048-ingress
    spec:
      rules:
        - http:
            paths:
              - path: /*
                backend:
                  serviceName: "service-2048"
                  servicePort: 80
    
  2. 使用 kubectl 將設定套用到叢集。

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl apply -f 2048.yaml
    
  3. 使用 kubectl 檢查 Ingress 資源的狀態。

    env HTTPS_PROXY=http://localhost:8118 \
      kubectl get ingress -n 2048-game 2048-ingress
    

    系統會顯示 Ingress 的狀態。「ADDRESS」欄包含 Ingress 的端點。

    NAME           HOSTS   ADDRESS                                                             PORTS   AGE
    2048-ingress   *       123456-2048game-2048ingr-6fa0-abcdefg.us-east-1.elb.amazonaws.com   80      2m19s
    
  4. 在瀏覽器中前往 ALB 端點。 例如: http://123456-2048game-2048ingr-6fa0-abcdefg.us-east-1.elb.amazonaws.com 系統會顯示 2048 遊戲。

後續步驟