全部產品
Search
文件中心

Container Service for Kubernetes:構建同城容災系統

更新時間:Nov 09, 2024

通過ACK One ALB多叢集網關,結合ACK One GitOps或多叢集應用分發,可以快速實現應用的同城多活容災,保證應用高可用,並在故障發生時自動平滑遷移。本文介紹如何通過多叢集網關構建同城容災系統。

容災概述

目前雲上容災主要分為以下三類:

  • 同城跨AZ容災:同城容災包含同城多活容災和同城主備容災2種策略,同城中心之間物理距離較近,網路延遲低,可防範AZ層級性質的災難損害,例如火災、斷網或斷電等。此方案在實現資料備份和快速恢複方面相對簡單,仍具備較強的實用意義。

  • 跨地區多活容災:跨地區多活容災對於網路延遲相對較高,但可以防範地區性質的災難損害,例如地震、水災等。

  • 兩地三中心:兩地三中心將同城雙中心和跨地區災備結合起來,兼具兩者的優點,適用於應用與資料連續性和可用性要求高的情境。

從業務架構上來說,企業的業務系統自上而下通常分為接入層、應用程式層和資料層。

  • 接入層:流量入口,負責接收流量,根據路由轉寄規則將流量轉寄到後端應用程式層。

  • 應用程式層:應用服務,根據請求對資料進行處理,並返回給上遊。

  • 資料層:資料存放區服務,為應用程式層提供資料和儲存資料。

為了實現整個業務容災,需對上述每一層實施相應的容災處理措施。

  • 接入層:ACK One多叢集網關作為接入層,其自身支援同城跨AZ高可用。

  • 應用程式層:ACK One多叢集網關處理應用程式層容災,可實現應用的同城多活/主備容災、跨地區容災。

  • 資料層:資料層容災和資料同步,需要依賴於中介軟體自身。

功能優勢

基於ACK One多叢集網關的容災方案與基於DNS流量分發的容災方案對比優勢如下:

  • 基於DNS流量分發的容災方案需要多個LB IP(每個叢集1個),而基於多叢集網關的容災方案在地區層級僅需要1個LB IP,且預設提供同地區多可用性區域的高可用性。

  • 基於多叢集網關的容災支援七層路由轉寄能力,而基於DNS流量分發的容災不支援七層路由轉寄。

  • 基於DNS流量分發的容災方案在IP切換時,通常會因用戶端緩衝造成服務短暫不可用,而基於多叢集網關的容災方案則可以更平滑地將流量Fallback到另一個叢集的服務後端。

  • 多叢集網關是地區層級的,所有操作都僅需在Fleet執行個體中進行,無需在每個ACK叢集中安裝Ingress Controller和建立Ingress資源。它提供地區級全域流量管理能力的同時,還能減少多叢集管理成本。

方案架構

本文以Web應用為樣本,展示了通過ALB多叢集網關實現同城容災的方案架構,包括Deployment和Service資源,具體結構如下圖所示。

  • 在同一個地區兩個不同可用性區域AZ 1和AZ 2中,分別建立一個ACK叢集Cluster 1和Cluster 2。

  • 通過ACK One GitOps將應用分發到已建立的Cluster 1和Cluster 2叢集中。

  • ACK One Fleet執行個體中通過AlbConfig資源來建立ALB多叢集網關。

  • 建立ALB多叢集網關後,通過建立Ingress來實現按權重路由流量、根據Header將流量路由到指定叢集的能力,當其中一個叢集異常時,流量將自動路由到另一個叢集中。

  • RDS資料同步需要依賴中介軟體自身能力。

前提條件

步驟一:使用GitOps或應用分發部署應用到多個叢集

ACK One支援多叢集GitOps和多叢集應用資源分發兩種方式,方便您將應用部署到多個叢集。請參見GitOps快速入門建立多叢集應用應用分發快速入門。本步驟以GitOps的多叢集應用分發為例。

  1. 登入ACK One控制台,在左側導覽列選擇艦隊 > 多叢集應用

  2. 多叢集應用頁面左上方,單擊艦隊名稱後的Dingtalk_20231226104633.jpg按鈕,在下拉式清單中選擇目標艦隊。

  3. 單擊建立多叢集應用 > GitOps進入建立多叢集應用 - GitOps頁面。

    說明
  4. YAML建立頁簽,將以下YAML內容複寫到控制台,然後點擊確定進行建立和部署應用。

    說明

    以下YAML內容是將web-demo部署到所有關聯集群中,您也可以通過快捷建立選擇叢集,變化會同步到YAML建立的內容。

    apiVersion: argoproj.io/v1alpha1
    kind: ApplicationSet
    metadata:
      name: appset-web-demo
      namespace: argocd
    spec:
      template:
        metadata:
          name: '{{.metadata.annotations.cluster_id}}-web-demo'
          namespace: argocd
        spec:
          destination:
            name: '{{.name}}'
            namespace: gateway-demo
          project: default
          source:
            repoURL: https://github.com/AliyunContainerService/gitops-demo.git
            path: manifests/helm/web-demo
            targetRevision: main
            helm:
              valueFiles:
                - values.yaml
              parameters:
                - name: envCluster
                  value: '{{.metadata.annotations.cluster_name}}'
          syncPolicy:
            automated: {}
            syncOptions:
              - CreateNamespace=true
      generators:
        - clusters:
            selector:
              matchExpressions:
                - values:
                    - cluster
                  key: argocd.argoproj.io/secret-type
                  operator: In
                - values:
                    - in-cluster
                  key: name
                  operator: NotIn
      goTemplateOptions:
        - missingkey=error
      syncPolicy:
        preserveResourcesOnDeletion: false
      goTemplate: true

步驟二:在艦隊中通過kubectl建立ALB多叢集網關

通過在ACK One Fleet執行個體中建立AlbConfig對象來建立一個ACK One ALB多叢集網關,並為ALB多叢集網關添加關聯集群。

  1. 從ACK One艦隊所在VPC,擷取兩個虛擬交換器ID。

  2. 使用以下內容,建立gateway.yaml檔案。

    說明
    • 請將${vsw-id1}${vsw-id2}替換為您上一步擷取的交換器ID,${cluster1}${cluster2}替換為您待添加的關聯集群ID。

    • 子叢集${cluster1}${cluster2}的安全性群組的入方向需要允許該交換器網段的IP和所有連接埠通過。

    apiVersion: alibabacloud.com/v1
    kind: AlbConfig
    metadata:
      name: ackone-gateway-demo
      annotations:
        # 添加要處理流量的關聯集群到ALB多叢集執行個體。
        alb.ingress.kubernetes.io/remote-clusters: ${cluster1},${cluster2}
    spec:
      config:
        name: one-alb-demo
        addressType: Internet
        addressAllocatedMode: Fixed
        zoneMappings:
        - vSwitchId: ${vsw-id1}
        - vSwitchId: ${vsw-id2}
      listeners:
      - port: 8001
        protocol: HTTP
    ---
    apiVersion: networking.k8s.io/v1
    kind: IngressClass
    metadata:
      name: alb
    spec:
      controller: ingress.k8s.alibabacloud/alb
      parameters:
        apiGroup: alibabacloud.com
        kind: AlbConfig
        name: ackone-gateway-demo

    需要同步的參數及其說明如下表所示:

    參數

    是否必填

    說明

    metadata.name

    AlbConfig的名稱。

    metadata.annotations:

    alb.ingress.kubernetes.io/remote-clusters

    表示待添加到ALB多叢集網關的關聯集群列表。此處所填的是已經關聯到艦隊執行個體的叢集ID。

    spec.config.name

    ALB執行個體的名稱。

    spec.config.addressType

    ALB執行個體的網路類型。取值如下:

    • Internet(預設值):公網類型。面向公網提供應用型負載平衡服務,公網可訪問。

      說明

      應用型負載平衡通過綁定Elastic IP Address進行公網服務,使用公網類型ALB執行個體將收取Elastic IP Address的執行個體費與頻寬、流量費用,詳情參見隨用隨付

      Intranet:私網類型。面向VPC內部提供應用型負載平衡服務,公網不可訪問。

    spec.config.zoneMappings

    設定ALB交換器ID。建立交換器具體操作請參見建立和管理交換器

    說明
    • 指定的交換器必須在ALB當前所支援的可用性區域內,且與叢集處於同一VPC。關於ALB支援的地區與可用性區域,請參見ALB支援的地區與可用性區域

    • 應用型負載平衡支援多可用性區域部署,若當前地區支援2個及以上可用性區域,為保障業務高可用,請至少選擇2個或以上不同可用性區域的交換器。

    spec.listeners

    配置ALB的監聽連接埠和協議。本文配置樣本為連接埠8001的HTTP監聽。

    監聽定義了流量進入負載平衡的方式和規則,此處建議保留該配置,否則您需要另行建立監聽才可使用ALB Ingress。

  3. 執行以下命令,部署gateway.yaml,建立ALB多叢集網關和IngressClass。

    kubectl apply -f gateway.yaml
  4. 執行以下命令,查看ALB多叢集網關是否建立成功(1~3min)。

    kubectl get albconfig ackone-gateway-demo

    預期輸出如下:

    NAME      		      ALBID      DNSNAME                               PORT&PROTOCOL   CERTID   AGE
    ackone-gateway-demo           alb-xxxx   alb-xxxx.<regionid>.alb.aliyuncs.com                           4d9h
  5. 確認關聯集群是否添加成功,執行以下命令查看狀態。

    kubectl get albconfig ackone-gateway-demo -ojsonpath='{.status.loadBalancer.subClusters}'

    預期輸出為叢集ID列表。

步驟三:使用Ingress實現同城容災

多叢集網關通過Ingress對多叢集流量進行管理,您可以在ACK One Fleet執行個體中建立Ingress對象來實現同城多活容災。

  1. 在艦隊執行個體中建立Service所在的Namespace,本樣本為gateway-demo

  2. 使用以下內容,建立ingress-demo.yaml檔案。

    說明
    • 多個alb.ingress.kubernetes.io/cluster-weight註解權重總和必須等於100。

    • 通過網域名稱example.com下的/svc1路由規則暴露後端服務service1。請先替換${cluster1-id}${cluster2-id}

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      annotations:
        alb.ingress.kubernetes.io/listen-ports: |
         [{"HTTP": 8001}]
        alb.ingress.kubernetes.io/cluster-weight.${cluster1-id}: "20"
        alb.ingress.kubernetes.io/cluster-weight.${cluster2-id}: "80"
      name: web-demo
      namespace: gateway-demo
    spec:
      ingressClassName: alb
      rules:
      - host: alb.ingress.alibaba.com
        http:
          paths:
          - path: /svc1
            pathType: Prefix
            backend:
              service:
                name: service1
                port:
                  number: 80
  3. 執行以下命令,在ACK One艦隊中部署Ingress。

    kubectl apply -f ingress-demo.yaml -n gateway-demo

步驟四:驗證同城多活容災效果

流量按設定比例路由到各叢集處理

訪問服務的格式如下:

curl -H "host: alb.ingress.alibaba.com" alb-xxxx.<regionid>.alb.aliyuncs.com:<listeners port>/svc1

需要同步的參數及其說明如下表所示:

參數

說明

alb-xxxx.<regionid>.alb.aliyuncs.com

步驟二中擷取的AlbConfig的DNSNAME

<listeners port>

AlbConfig中定義及Ingress中annotations聲明的8001。

執行以下命令後,從結果可以看出,請求按照20:80的比例發送到叢集1(poc-ack-1)和叢集2(poc-ack-2)處理。

for i in {1..500}; do curl -H "host: alb.ingress.alibaba.com" alb-xxxx.cn-beijing.alb.aliyuncs.com:8001/svc1; done > res.txt

image

某個叢集應用異常時流量自動平滑遷移

執行以下命令後,我們手動將叢集2的應用副本數設定為0,此時流量自動平滑遷移至叢集1。

for i in {1..500}; do curl -H "host: alb.ingress.alibaba.com" alb-xxxx.cn-beijing.alb.aliyuncs.com:8001/svc1; sleep 1; done

image