跨可用性區域部署 Azure Service Fabric 叢集

可用性區域是高可用性供應項目,可保護應用程式和資料不受資料中心故障所影響。 可用性區域是 Azure 區域內獨特的實體位置,配備獨立的電源、冷卻和網路。

為了支援跨可用性區域的叢集,Azure Service Fabric 提供兩種設定方法,如本文接下來所述。 只在經過挑選的區域中才有可用性區域。 如需詳細資訊,請參閱可用性區域概觀

Service Fabric 跨可用性區域範本中提供範例範本。

主要節點類型跨可用性區域的拓撲

注意

跨可用性區域之間主要節點類型的優點,實際上只會針對三個區域看到,而非僅兩個區域。

  • 叢集可靠性層級設定為 Platinum
  • 使用標準 SKU 的單一公用 IP 資源
  • 使用標準 SKU 的單一負載平衡器資源
  • 您部署虛擬機器擴展集的子網路所參考的網路安全性群組 (NSG)

注意

虛擬機器擴展集單一放置群組屬性必須設定為 true

下列範例節點清單描述跨區域虛擬機器擴展集的 FD/UD 格式:

Screenshot that shows a sample node list of FD/UD formats in a virtual machine scale set spanning zones.

服務複本跨區域分佈

在跨可用性區域的節點類型上部署服務時,複本會安置為確保落在不同的區域。 在每個節點類型中的節點上,容錯網域都設定有區域資訊 (也就是 FD = fd:/zone1/1 等)。 例如,以五個複本或服務執行個體為例,分佈為 2-2-1,執行階段會設法確保平均分散於各區域。

使用者服務複本設定

在跨可用性區域的節點類型上部署的具狀態使用者服務,應該像這樣設定:複本計數目標 = 9,最小 = 5。 即使某個區域關閉,此設定也能維持服務運作,因為其他兩個區域仍有六個複本在運作。 在此情況下也能成功升級應用程式。

叢集 ReliabilityLevel

此值定義叢集的種子節點數目和系統服務的複本大小。 跨可用性區域設定有較多節點,分散於各區域以確保區域復原。

ReliabilityLevel 值越高可確保越多種子節點和系統服務複本存在,且平均分散於各區域,即使某個區域故障,也不影響叢集和系統服務。 ReliabilityLevel = Platinum (建議) 可確保有九個種子節點分散於叢集的各區域,每個區域各有三個種子。

區域關閉情節

當區域關閉時,該區域的所有節點和服務複本都呈現關閉。 因為其他區域還有複本,服務可繼續回應。 主要複本會容錯移轉至正常運作的區域。 因為尚未達到目標複本計數,且虛擬機器 (VM) 計數仍高於最小目標複本大小,服務會呈現警告狀態。

Service Fabric 負載平衡器會啟動運作中區域上的複本,以符合目標複本計數。 此時,服務顯得良好。 當關閉的區域恢復運作時,負載平衡器會將所有服務複本平均分散至各區域。

即將推出最佳化

  • 為了提供可靠的基礎結構更新,Service Fabric 規定虛擬機器擴展集持久性至少要設定為銀級。 這樣可讓基礎虛擬機器擴展集和 Service Fabric 執行階段提供可靠的更新。 這還需要每個區域至少有 5 個 VM。 我們正努力將此需求降到主要和非主要節點類型分別為每個區域 3 和 2 個 VM。
  • 下述所有設定和即將展開的工作支援客戶就地移轉,只要在相同叢集上新增 nodeTypes 並淘汰舊的 nodeTypes,就能升級為使用新的設定。

網路需求

公用 IP 和負載平衡器資源

若要在虛擬機器擴展集資源上啟用 zones 屬性,該虛擬機器擴展集所參考的負載平衡器和 IP 資源都必須使用標準 SKU。 建立沒有 SKU 屬性的負載平衡器或 IP 資源會產生基本 SKU,這不支援可用性區域。 標準 SKU 負載平衡器預設會封鎖外來的所有流量。 若要允許外部流量,請將 NSG 部署至子網路。

{
  "apiVersion": "2018-11-01",
  "type": "Microsoft.Network/publicIPAddresses",
  "name": "[concat('LB','-', parameters('clusterName')]",
  "location": "[parameters('computeLocation')]",
  "sku": {
    "name": "Standard"
  }
}
{
  "apiVersion": "2018-11-01",
  "type": "Microsoft.Network/loadBalancers",
  "name": "[concat('LB','-', parameters('clusterName')]",
  "location": "[parameters('computeLocation')]",
  "dependsOn": [
    "[concat('Microsoft.Network/networkSecurityGroups/', concat('nsg', parameters('subnet0Name')))]"
  ],
  "properties": {
    "addressSpace": {
      "addressPrefixes": [
        "[parameters('addressPrefix')]"
      ]
    },
    "subnets": [
      {
        "name": "[parameters('subnet0Name')]",
        "properties": {
          "addressPrefix": "[parameters('subnet0Prefix')]",
          "networkSecurityGroup": {
            "id": "[resourceId('Microsoft.Network/networkSecurityGroups', concat('nsg', parameters('subnet0Name')))]"
          }
        }
      }
    ]
  },
  "sku": {
    "name": "Standard"
  }
}

注意

在公用 IP 和負載平衡器資源上無法就地變更 SKU。 如果您要從具有基本 SKU 的現有資源遷移,請參閱本文的移轉章節。

虛擬機器擴展集的 NAT 規則

負載平衡器的輸入網路位址轉譯 (NAT) 規則,應該符合虛擬機器擴展集的 NAT 集區。 每個虛擬機器擴展集都必須有唯一的輸入 NAT 集區。

{
  "inboundNatPools": [
    {
      "name": "LoadBalancerBEAddressNatPool0",
      "properties": {
        "backendPort": "3389",
        "frontendIPConfiguration": {
          "id": "[variables('lbIPConfig0')]"
        },
        "frontendPortRangeEnd": "50999",
        "frontendPortRangeStart": "50000",
        "protocol": "tcp"
      }
    },
    {
      "name": "LoadBalancerBEAddressNatPool1",
      "properties": {
        "backendPort": "3389",
        "frontendIPConfiguration": {
          "id": "[variables('lbIPConfig0')]"
        },
        "frontendPortRangeEnd": "51999",
        "frontendPortRangeStart": "51000",
        "protocol": "tcp"
      }
    },
    {
      "name": "LoadBalancerBEAddressNatPool2",
      "properties": {
        "backendPort": "3389",
        "frontendIPConfiguration": {
          "id": "[variables('lbIPConfig0')]"
        },
        "frontendPortRangeEnd": "52999",
        "frontendPortRangeStart": "52000",
        "protocol": "tcp"
      }
    }
  ]
}

標準 SKU 負載平衡器的輸出規則

相較於使用基本 SKU,標準 SKU 負載平衡器和公用 IP 在輸出連線能力方面引進新的功能和不同行為。 使用標準 SKU 時,如果想要有輸出連線能力,您必須以標準 SKU 公用 IP 位址或標準 SKU 負載平衡器來明確定義。 如需詳細資訊,請參閱輸出連線什麼是 Azure Load Balancer?

注意

標準範本參考一個預設允許所有輸出流量的 NSG。 輸入流量僅限於 Service Fabric 管理作業所需的連接埠。 NSG 規則可以修改為符合您的需求。

重要

Service Fabric 叢集上使用標準 SKU 負載平衡器的每個節點類型,都需要規則來允許連接埠 443 上的輸出流量。 必須如此才能完成叢集設定。 缺少此規則的部署會失敗。

1.在單一虛擬機器擴展集啟用多個可用性區域

此解決方案可讓使用者跨越相同節點類型中的三個可用性區域。 這是建議的部署拓撲,因為可讓您跨多個可用性區域來部署,同時維持單一虛擬機器擴展集。

GitHub 上提供完整範例範本。

Diagram of the Azure Service Fabric Availability Zone architecture.

在虛擬機器擴展集設定區域

若要在虛擬機器擴展集啟用區域,請將下列三個值加入虛擬機器擴展集資源中:

  • 第一個值是 zones 屬性,用於指定虛擬機器擴展集上的可用性區域。

  • 第二個值是 singlePlacementGroup 屬性,必須設定為 true。 即使 singlePlacementGroup = true,跨三個可用性區域的擴展集仍可擴大至 300 個 VM。

  • 第三個值是 zoneBalance,可確保嚴格的區域平衡。 此值應該為 true。 這可確保跨區域的 VM 分佈沒有不平衡,表示當某個區域關閉時,另兩個區域有足夠的 VM 可維持叢集運作。

    VM 分佈不平衡的叢集可能經不起區域關閉的情況,因為大多數 VM 可能都在該區域內。 跨區域的 VM 分佈不平衡也會導致服務放置問題和基礎結構更新停滯。 深入了解 zoneBalancing

您不需要設定 FaultDomainUpgradeDomain 覆寫。

{
  "apiVersion": "2018-10-01",
  "type": "Microsoft.Compute/virtualMachineScaleSets",
  "name": "[parameters('vmNodeType1Name')]",
  "location": "[parameters('computeLocation')]",
  "zones": [ "1", "2", "3" ],
  "properties": {
    "singlePlacementGroup": true,
    "zoneBalance": true
  }
}

注意

  • Service Fabric 叢集應該至少有一個主要節點類型。 主要節點類型的持久性等級應該為銀級或更高。
  • 不論持久性等級是高或低,跨越虛擬機器擴展集的可用性區域至少應該設有三個可用性區域。
  • 如果可用性區域跨越銀級或具有更高持久性的虛擬機器擴展集,則至少應該有 15 個 VM (每個區域 5 個)。
  • 如果可用性區域跨越銅級持久性的虛擬機器擴展集,則至少應該有六個 VM。

在 Service Fabric 節點類型中支援多個區域

Service Fabric 節點類型必須能夠支援多個可用性區域。

  • 第一個值是 multipleAvailabilityZones,針對此節點類型應該設定為 true

  • 第二個值是 sfZonalUpgradeMode 而且是選用。 如果叢集上存在具有多個可用性區域的節點類型,則無法修改此屬性。 此屬性控制升級網域 (UD) 中的 VM 邏輯群組。

    • 如果此值設定為 Parallel:節點類型下的 VM 會分組為 UD,並忽略五個 UD 中的區域資訊。 此設定會使得所有區域的 UD 同時升級。 此部署模式的升級速度較快,不建議採用,因為違背 SDP 指導方針,其中規定應該一次更新一個區域。
    • 如果省略此值或設定為 Hierarchical:VM 的分組會反映最多 15 個 UD 的區域性分佈。 三個區域各有五個 UD。 這可確保一次更新一個區域,只有在完成第一個區域內的五個 UD 之後,才會移至下一個區域。 對於叢集和使用者應用程式,此更新流程較安全。

    此屬性只定義 Service Fabric 應用程式和程式碼升級的升級行為。 在所有可用性區域中,基礎虛擬機器擴展集升級仍然平行。 對於未啟用多個區域的節點類型,此屬性不影響 UD 分佈。

  • 第三個值 vmssZonalUpgradeMode 為選擇性,且可以隨時更新。 此屬性會定義虛擬機器擴展集的升級配置,以平行或循序跨可用性區域進行。

    • 如果此值設定為 Parallel:所有擴展集更新都會在所有區域中平行進行。 此部署模式的升級速度較快,不建議採用,因為違背 SDP 指導方針,其中規定應該一次更新一個區域。
    • 如果此值省略或設定為 Hierarchical:這可確保一次更新一個區域,只有在完成第一個區域內的五個 UD 之後,才會移至下一個區域。 對於叢集和使用者應用程式,此更新流程較安全。

重要

Service Fabric 叢集資源 API 版本應該為 2020-12-01-preview 或更新版本。

叢集程式碼版本至少應該為 8.1.321 或更新版本。

{
  "apiVersion": "2020-12-01-preview",
  "type": "Microsoft.ServiceFabric/clusters",
  "name": "[parameters('clusterName')]",
  "location": "[parameters('clusterLocation')]",
  "dependsOn": [
    "[concat('Microsoft.Storage/storageAccounts/', parameters('supportLogStorageAccountName'))]"
  ],
  "properties": {
    "reliabilityLevel": "Platinum",
    "sfZonalUpgradeMode": "Hierarchical",
    "vmssZonalUpgradeMode": "Parallel",
    "nodeTypes": [
      {
        "name": "[parameters('vmNodeType0Name')]",
        "multipleAvailabilityZones": true
      }
    ]
  }
}

注意

  • 公用 IP 和負載平衡器資源應該使用本文稍早所述的標準 SKU。
  • 只有在建立節點類型時,才能在節點類型上定義 multipleAvailabilityZones 屬性,之後無法修改。 無法對現有的節點類型設定此屬性。
  • 當省略 sfZonalUpgradeMode 或設定為 Hierarchical 時,因為叢集有更多升級網域,叢集和應用程式部署會變慢。 必須考慮 15 個升級網域所需的升級時間,正確調整升級原則逾時。 應該更新應用程式和叢集的升級原則,以確保部署不超過 Azure 資源服務部署時間限制 12 小時。 這表示部署 15 個 UD 不應該超過 12 小時 (亦即每個 UD 不應該超過 40 分鐘)。
  • 將叢集可靠性等級設定為 Platinum,以確保叢集經得起一次區域關閉情況。
  • 不支援針對具有 multipleAvailabilityZones 的 nodetype 升級 DurabilityLevel。 請改為建立具有較高持久性的新 nodetype。
  • SF 僅支援 3 個 AvailabilityZones。 目前不支援任何更高的數目。

提示

建議將 sfZonalUpgradeMode 設定為 Hierarchical 或省略。 部署遵循 VM 的區域性分佈,只影響少數複本或執行個體,較為安全。 如果部署速度是首要考量,或在具有多個可用性區域的節點類型上只執行無狀態工作負載,請將 sfZonalUpgradeMode 設定為 Parallel。 這會使得 UD 在所有可用性區域中平行發生。

遷移至具有多個可用性區域的節點類型

在所有移轉情節中,您需要新增支援多個可用性區域的新節點類型。 無法遷移現有的節點類型來支援多個區域。 擴大 Service Fabric 叢集的主要節點類型一文包含詳細步驟來新增節點類型,以及新節點類型所需的其他資源,例如 IP 和負載平衡器資源。 該文章也說明將具有多個可用性區域的新節點類型加入叢集之後,如何淘汰現有的節點類型。

  • 從使用基本負載平衡器和 IP 資源的節點類型移轉:下列一小節中,已針對每個可用性區域各有一個節點類型的解決方案來描述此流程。

    若為新的節點類型,唯一差別在於只有一個虛擬機器擴展集,而全部可用性區域就只有一個節點類型,而不是每個可用性區域各有一個節點類型。

  • 從使用標準 SKU 負載平衡器和 IP 資源及 NSG 的節點類型移轉:遵循前述的相同程序。 但是,不需要加入新的負載平衡器、IP 和 NSG 資源。 相同的資源可以重複用在新的節點類型中。

2.將一個虛擬機器擴展集釘選至每個區域以部署區域

這是目前常用的設定。 若要讓 Service Fabric 叢集跨可用性區域,您必須在該區域所支援的每個可用性區域中建立主要節點類型。 這樣會將種子節點平均分散至每個主要節點類型。

主要節點類型的建議拓撲需要:

  • 三個標示為主要的節點類型
    • 每個節點類型必須對應至其本身在另一個區域的虛擬機器擴展集。
    • 每個虛擬機器擴展集至少應該有五個節點 (銀級持久性)。

下圖顯示 Azure Service Fabric 可用性區域架構:

Diagram that shows the Azure Service Fabric Availability Zone architecture.

在虛擬機器擴展集啟用區域

若要在虛擬機器擴展集啟用區域,請將下列三個值加入虛擬機器擴展集資源中:

  • 第一個值是 zones 屬性,用於指定虛擬機器擴展集部署至哪個可用性區域。
  • 第二個值是 singlePlacementGroup 屬性,必須設定為 true
  • 第三個值是 Service Fabric 虛擬機器擴展集擴充功能中的 faultDomainOverride 屬性。 此屬性應該只包含將放置此虛擬機器擴展集的區域。 範例:"faultDomainOverride": "az1"。 所有虛擬機器擴展集資源都必須放在相同的區域中,因為 Azure Service Fabric 叢集沒有跨區域支援。
{
  "apiVersion": "2018-10-01",
  "type": "Microsoft.Compute/virtualMachineScaleSets",
  "name": "[parameters('vmNodeType1Name')]",
  "location": "[parameters('computeLocation')]",
  "zones": [
    "1"
  ],
  "properties": {
    "singlePlacementGroup": true
  },
  "virtualMachineProfile": {
    "extensionProfile": {
      "extensions": [
        {
          "name": "[concat(parameters('vmNodeType1Name'),'_ServiceFabricNode')]",
          "properties": {
            "type": "ServiceFabricNode",
            "autoUpgradeMinorVersion": false,
            "publisher": "Microsoft.Azure.ServiceFabric",
            "settings": {
              "clusterEndpoint": "[reference(parameters('clusterName')).clusterEndpoint]",
              "nodeTypeRef": "[parameters('vmNodeType1Name')]",
              "dataPath": "D:\\\\SvcFab",
              "durabilityLevel": "Silver",
              "certificate": {
                "thumbprint": "[parameters('certificateThumbprint')]",
                "x509StoreName": "[parameters('certificateStoreValue')]"
              },
              "systemLogUploadSettings": {
                "Enabled": true
              },
              "faultDomainOverride": "az1"
            },
            "typeHandlerVersion": "1.0"
          }
        }
      ]
    }
  }
}

啟用 Service Fabric 叢集資源中啟用多個主要節點類型

若要在叢集資源中將一或多個節點類型設定為主要,請將 isPrimary 屬性設定為 true。 跨可用性區域部署 Service Fabric 叢集時,您應該有三個節點類型在各別區域中。

{
  "reliabilityLevel": "Platinum",
  "nodeTypes": [
    {
      "name": "[parameters('vmNodeType0Name')]",
      "applicationPorts": {
        "endPort": "[parameters('nt0applicationEndPort')]",
        "startPort": "[parameters('nt0applicationStartPort')]"
      },
      "clientConnectionEndpointPort": "[parameters('nt0fabricTcpGatewayPort')]",
      "durabilityLevel": "Silver",
      "ephemeralPorts": {
        "endPort": "[parameters('nt0ephemeralEndPort')]",
        "startPort": "[parameters('nt0ephemeralStartPort')]"
      },
      "httpGatewayEndpointPort": "[parameters('nt0fabricHttpGatewayPort')]",
      "isPrimary": true,
      "vmInstanceCount": "[parameters('nt0InstanceCount')]"
    },
    {
      "name": "[parameters('vmNodeType1Name')]",
      "applicationPorts": {
        "endPort": "[parameters('nt1applicationEndPort')]",
        "startPort": "[parameters('nt1applicationStartPort')]"
      },
      "clientConnectionEndpointPort": "[parameters('nt1fabricTcpGatewayPort')]",
      "durabilityLevel": "Silver",
      "ephemeralPorts": {
        "endPort": "[parameters('nt1ephemeralEndPort')]",
        "startPort": "[parameters('nt1ephemeralStartPort')]"
      },
      "httpGatewayEndpointPort": "[parameters('nt1fabricHttpGatewayPort')]",
      "isPrimary": true,
      "vmInstanceCount": "[parameters('nt1InstanceCount')]"
    },
    {
      "name": "[parameters('vmNodeType2Name')]",
      "applicationPorts": {
        "endPort": "[parameters('nt2applicationEndPort')]",
        "startPort": "[parameters('nt2applicationStartPort')]"
      },
      "clientConnectionEndpointPort": "[parameters('nt2fabricTcpGatewayPort')]",
      "durabilityLevel": "Silver",
      "ephemeralPorts": {
        "endPort": "[parameters('nt2ephemeralEndPort')]",
        "startPort": "[parameters('nt2ephemeralStartPort')]"
      },
      "httpGatewayEndpointPort": "[parameters('nt2fabricHttpGatewayPort')]",
      "isPrimary": true,
      "vmInstanceCount": "[parameters('nt2InstanceCount')]"
    }
  ]
}

使用基本 SKU 負載平衡器和基本 SKU IP,從叢集遷移至可用性區域

若要遷移使用負載平衡器和 IP 及基本 SKU 的叢集,您必須先使用標準 SKU 來建立全新的負載平衡器和 IP 資源。 無法更新這些資源。

在您要使用的跨可用性區域新節點類型中,參考新的負載平衡器和 IP。 在上述範例中,區域 1、2 和 3 中新增三個新的虛擬機器擴展集資源。 這些虛擬機器擴展集參考新建立的負載平衡器和 IP,並於 Service Fabric 叢集資源中標示為主要節點類型。

  1. 若要開始,請將新資源新增至現有的 Azure Resource Manager 範本。 這些資源包括:

    • 使用標準 SKU 的公用 IP 資源
    • 使用標準 SKU 的負載平衡器資源
    • 您部署虛擬機器擴展集的子網路所參考的 NSG
    • 三個標示為主要的節點類型
      • 每個節點類型必須對應至其本身在另一個區域的虛擬機器擴展集。
      • 每個虛擬機器擴展集至少應該有五個節點 (銀級持久性)。

    範例範本中可以找到這些資源的範例。

    New-AzureRmResourceGroupDeployment `
        -ResourceGroupName $ResourceGroupName `
        -TemplateFile $Template `
        -TemplateParameterFile $Parameters
    
  2. 當資源完成部署時,您可以從原始叢集停用主要節點類型中的節點。 當節點停用時,系統服務會遷移至您先前部署的新主要節點類型。

    Connect-ServiceFabricCluster -ConnectionEndpoint $ClusterName `
        -KeepAliveIntervalInSec 10 `
        -X509Credential `
        -ServerCertThumbprint $thumb  `
        -FindType FindByThumbprint `
        -FindValue $thumb `
        -StoreLocation CurrentUser `
        -StoreName My 
    
    Write-Host "Connected to cluster"
    
    $nodeNames = @("_nt0_0", "_nt0_1", "_nt0_2", "_nt0_3", "_nt0_4")
    
    Write-Host "Disabling nodes..."
    foreach($name in $nodeNames) {
        Disable-ServiceFabricNode -NodeName $name -Intent RemoveNode -Force
    }
    
  3. 節點全部停用之後,系統服務會在遍及各區域的主要節點類型上執行。 然後,您可以從叢集移除已停用的節點。 移除節點之後,您可以移除原始 IP、負載平衡器和虛擬機器擴展集資源。

    foreach($name in $nodeNames){
        # Remove the node from the cluster
        Remove-ServiceFabricNodeState -NodeName $name -TimeoutSec 300 -Force
        Write-Host "Removed node state for node $name"
    }
    
    $scaleSetName="nt0"
    Remove-AzureRmVmss -ResourceGroupName $groupname -VMScaleSetName $scaleSetName -Force
    
    $lbname="LB-cluster-nt0"
    $oldPublicIpName="LBIP-cluster-0"
    $newPublicIpName="LBIP-cluster-1"
    
    Remove-AzureRmLoadBalancer -Name $lbname -ResourceGroupName $groupname -Force
    Remove-AzureRmPublicIpAddress -Name $oldPublicIpName -ResourceGroupName $groupname -Force
    
  4. 接著,從您部署的 Resource Manager 範本中移除對這些資源的參考。

  5. 最後,更新 DNS 名稱和公用 IP。

$oldprimaryPublicIP = Get-AzureRmPublicIpAddress -Name $oldPublicIpName  -ResourceGroupName $groupname
$primaryDNSName = $oldprimaryPublicIP.DnsSettings.DomainNameLabel
$primaryDNSFqdn = $oldprimaryPublicIP.DnsSettings.Fqdn

Remove-AzureRmLoadBalancer -Name $lbname -ResourceGroupName $groupname -Force
Remove-AzureRmPublicIpAddress -Name $oldPublicIpName -ResourceGroupName $groupname -Force

$PublicIP = Get-AzureRmPublicIpAddress -Name $newPublicIpName  -ResourceGroupName $groupname
$PublicIP.DnsSettings.DomainNameLabel = $primaryDNSName
$PublicIP.DnsSettings.Fqdn = $primaryDNSFqdn
Set-AzureRmPublicIpAddress -PublicIpAddress $PublicIP