教程:在 Azure 中缩放 Service Fabric 群集Tutorial: Scale a Service Fabric cluster in Azure

本教程是系列教程的第三部分,介绍如何扩大和缩小现有群集。This tutorial is part three of a series, and shows you how to scale your existing cluster out and in. 完成时,将知道如何缩放群集以及如何清理剩余的资源。When you've finished, you will know how to scale your cluster and how to clean up any left-over resources. 有关缩放 Azure 中运行的群集的详细信息,请阅读缩放 Service Fabric 群集For more information on scaling a cluster running in Azure, read Scaling Service Fabric clusters.

本教程介绍如何执行下列操作:In this tutorial, you learn how to:

  • 添加和删除节点(横向扩展和缩小)Add and remove nodes (scale out and scale in)
  • 添加和删除节点类型(横向扩展和缩小)Add and remove node types (scale out and scale in)
  • 增加节点资源(纵向扩展)Increase node resources (scale up)

在此系列教程中,你将学习如何:In this tutorial series you learn how to:

Note

本文进行了更新,以便使用新的 Azure PowerShell Az 模块。This article has been updated to use the new Azure PowerShell Az module. 你仍然可以使用 AzureRM 模块,至少在 2020 年 12 月之前,它将继续接收 bug 修补程序。You can still use the AzureRM module, which will continue to receive bug fixes until at least December 2020. 若要详细了解新的 Az 模块和 AzureRM 兼容性,请参阅新 Azure Powershell Az 模块简介To learn more about the new Az module and AzureRM compatibility, see Introducing the new Azure PowerShell Az module. 有关 Az 模块安装说明,请参阅安装 Azure PowerShellFor Az module installation instructions, see Install Azure PowerShell.

必备条件Prerequisites

在开始学习本教程之前:Before you begin this tutorial:

重要注意事项和指南Important considerations and guidelines

应用程序工作负荷会随时间推移而发生变化,现有服务是否需要更多(或更少)资源?Application workloads change over time, do your existing services need more (or less) resources? 从某个节点类型添加或删除节点以增加或减少群集资源。Add or remove nodes from a node type to increase or decrease cluster resources.

是否需要向群集添加超过 100 个节点?Do you need to add more than 100 nodes to your cluster? 单一 Service Fabric 节点类型/规模集不能包含超过 100 个节点/VM。A single Service Fabric node type/scale set can not contain more than 100 nodes/VMs. 若要将群集扩展到超过 100 个节点,需添加更多节点类型To scale a cluster beyond 100 nodes, add additional node types.

应用程序是否有多个服务,其中是否有任何服务需面向公众或面向 Internet?Does your application have multiple services, and do any of them need to be public or internet facing? 典型的应用程序包含可接收客户端输入的前端网关服务,以及一个或多个与前端服务通信的后端服务。Typical applications contain a front-end gateway service that receives input from a client and one or more back-end services that communicate with the front-end services. 在这种情况下,建议向群集添加至少两个节点类型In this case, we recommend you add at least two node types to the cluster.

服务是否有不同的基础结构需求,例如,更多的 RAM 或更高的 CPU 周期?Do your services have different infrastructure needs such as greater RAM or higher CPU cycles? 例如,应用程序包含前端服务和后端服务。For example, your application contains a front-end service and a back-end service. 前端服务可以在容量较小(如 D2 的 VM 大小)且向 Internet 开放了端口的 VM 上运行。The front-end service can run on smaller VMs (VM sizes like D2) that have ports open to the internet. 但是,后端服务是计算密集型的服务,需要放在容量较大(D4、D6、D15 等的 VM 大小)且不面向 Internet 的 VM 上运行。The back-end service, however, is computation intensive and needs to run on larger VMs (with VM sizes like D4, D6, D15) that are not internet facing. 在这种情况下,建议向群集添加两个或多个节点类型In this case, we recommended that you add two or more node types to your cluster. 这样,每个节点类型都有不同的属性,例如,Internet 连接或 VM 大小。This allows each node type to have distinct properties such as internet connectivity or VM size. 也可以单独缩放 VM 的数目。The number of VMs can be scaled independently, as well.

缩放 Azure 群集时,请记住以下准则:When scaling an Azure cluster, keep the following guidelines in mind:

  • 单一 Service Fabric 节点类型/规模集不能包含超过 100 个节点/VM。A single Service Fabric node type/scale set can not contain more than 100 nodes/VMs. 若要将群集扩展到超过 100 个节点,需添加更多节点类型。To scale a cluster beyond 100 nodes, add additional node types.
  • 运行生产工作负荷的主节点类型应具有金级或银级持久性级别并始终具有五个或更多个节点。Primary node types running production workloads should have a durability level of Gold or Silver and always have five or more nodes.
  • 运行有状态生产工作负荷的非主节点类型应始终具有五个或更多个节点。Non-primary node types running stateful production workloads should always have five or more nodes.
  • 运行无状态生产工作负荷的非主节点类型应始终具有两个或更多个节点。Non-primary node types running stateless production workloads should always have two or more nodes.
  • 持久性级别为金级或银级的任何节点类型应始终具有五个或更多个节点。Any node type of durability level of Gold or Silver should always have five or more nodes.
  • 如果要缩减主节点类型的规模(从其中删除节点),则不得将实例数减少到小于可靠性级别所要求的数量。If scaling in (removing nodes from) a primary node type, you should never decrease the number of instances to less than what the reliability level requires.

有关详细信息,请阅读群集容量指南For more information, read cluster capacity guidance.

导出资源组的模板Export the template for the resource group

成功创建一个安全的 Windows 群集并设置资源组后,导出该资源组的资源管理器模板。After creating a secure Windows cluster and setting up your resource group successfully, export the Resource Manager template for the resource group. 导出模板后,便可自动执行群集及其资源的未来部署,因为模板包含所有完整的基础结构。Exporting the template allows you to automate future deployments of the cluster and its resources because the template contains all the complete infrastructure. 有关导出模板的详细信息,请阅读使用 Azure 门户管理 Azure 资源管理器资源组For more info on exporting templates, read Manage Azure Resource Manager resource groups by using the Azure portal.

  1. Azure 门户中,转到包含群集的资源组(如果按本教程操作,即为 sfclustertutorialgroup)。In the Azure portal, go to the resource group containing the cluster (sfclustertutorialgroup, if you are following this tutorial).

  2. 在左窗格中选择“部署”,或者选择“部署”下的链接。 In the left pane, select Deployments, or select the link under Deployments.

  3. 从列表中选择最近的成功部署。Select the most recent successful deployment from the list.

  4. 在左窗格中,选择“模板” ,然后选择“下载” ,将模板导出为 ZIP 文件。In the left pane, select Template and then select Download to export the template as a ZIP file. 将模板和参数保存到本地计算机。Save the template and parameters to your local computer.

添加或删除某个节点类型的节点Add nodes to or remove nodes from a node type

横向扩展和缩减或水平缩放会更改群集中的节点数。Scaling in and out, or horizontal scaling, changes the number of nodes in the cluster. 横向扩展和缩减时,会添加更多虚拟机实例到规模集。When you scale in or out, you add more virtual machine instances to the scale set. 这些实例成为 Service Fabric 使用的节点。These instances become the nodes that Service Fabric uses. Service Fabric 知道规模集什么时候添加了更多实例(通过扩大实现)并自动做出反应。Service Fabric knows when the scale set has more instances added (by scaling out) and reacts automatically. 随时可以缩放群集,即使该群集上正在运行工作负荷。You can scale the cluster at any time, even when workloads are running on the cluster.

更新模板Update the template

从最近的部署的资源组中导出模板和参数文件Export a template and parameters file from the resource group for the most recent deployment. 打开 Parameters.json 文件。Open the parameters.json file. 如果使用本教程中的示例模板部署了群集,群集中就有三个节点类型,且有三个参数,这些参数分别为每个节点类型设置节点数:nt0InstanceCount、nt1InstanceCount 和 nt2InstanceCount 。If you deployed the cluster using the sample template in this tutorial, there are three node types in the cluster and three parameters that set the number of nodes for each node type: nt0InstanceCount, nt1InstanceCount, and nt2InstanceCount. 例如,Nt1InstanceCount 参数,为第二个节点类型设置实例计数,并设置关联的虚拟机规模集中的 VM 数。The nt1InstanceCount parameter, for example, sets the instance count for the second node type and sets the number of VMs in the associated virtual machine scale set.

这样,可通过更新 nt1InstanceCount 的值来更改第二个节点类型中的节点数。So, by updating the value of the nt1InstanceCount you change the number of nodes in the second node type. 请记住,无法将一个节点类型横向扩展到超过 100 个节点。Remember, you cannot scale a node type out to more than 100 nodes. 运行有状态生产工作负荷的非主节点类型应始终具有五个或更多个节点。Non-primary node types running stateful production workloads should always have five or more nodes. 运行无状态生产工作负荷的非主节点类型应始终具有两个或更多个节点。Non-primary node types running stateless production workloads should always have two or more nodes.

如果缩减铜级持久性级别的节点类型规模(从其中删除节点),必须手动删除这些节点的状态If you are scaling in, removing nodes from, a node type of Bronze durability level you must manually remove the state of those nodes. 对于白银和黄金持久性层,平台会自动完成上述步骤。For Silver and Gold durability tier, these steps are done automatically by the platform.

部署已更新的模板Deploy the updated template

将任何更改保存到 template.json 和 parameters.json 文件 。Save any changes to the template.json and parameters.json files. 若要部署更新的模板,请运行以下命令:To deploy the updated template, run the following command:

New-AzResourceGroupDeployment -ResourceGroupName sfclustertutorialgroup -TemplateFile c:\temp\template.json -TemplateParameterFile c:\temp\parameters.json -Name "ChangingInstanceCount"

或者运行以下 Azure CLI 命令:Or the following Azure CLI command:

az group deployment create --resource-group sfclustertutorialgroup --template-file c:\temp\template.json --parameters c:\temp\parameters.json

向群集添加节点类型Add a node type to the cluster

在 Azure 中运行的 Service Fabric 群集中定义的每个节点类型将设置为独立的虚拟机规模集Every node type that is defined in a Service Fabric cluster running in Azure is set up as a separate virtual machine scale set. 然后可以单独管理每个节点类型。Each node type can then be managed separately. 可独立增加或减少每个节点类型、打开不同的端口集,并使用不同的容量指标。You can independently scale each node type up or down, have different sets of ports open, and use different capacity metrics. 还可以独立更改每个群集节点上运行的 OS SKU,但请注意,不能混合示例群集中运行的 Windows 和 Linux。You can also independently change the OS SKU running on each cluster node, but note that you can't have a mix of Windows and Linux running in the sample cluster. 单个节点类型/规模集不能包含超过 100 个节点。A single node type/scale set cannot contain more than 100 nodes. 可以通过添加其他节点类型/规模集将群集横向扩展到超过 100 个节点。You can scale a cluster horizontally to more than 100 nodes by adding additional node types/scale sets. 随时可以缩放群集,即使该群集上正在运行工作负荷。You can scale the cluster at any time, even when workloads are running on the cluster.

更新模板Update the template

从最近的部署的资源组中导出模板和参数文件Export a template and parameters file from the resource group for the most recent deployment. 打开 Parameters.json 文件。Open the parameters.json file. 如果使用本教程中的示例模板部署了群集,群集中就有三个节点类型。If you deployed the cluster using the sample template in this tutorial, there are three node types in the cluster. 在本部分中,通过更新和部署资源管理器模板添加第四个节点类型。In this section you add a fourth node type by updating and deploying a Resource Manager template.

除了新的节点类型,还添加关联的虚拟机规模集(运行在虚拟网络的独立子网中)和网络安全组。In addition to the new node type, you also add the associated virtual machine scale set (which runs in a separate subnet of the virtual network) and network security group. 可以选择添加新的或现有的公共 IP 地址和新规模集的 Azure 负载均衡器资源。You can choose to add new or existing public IP address and Azure load balancer resources for the new scale set. 新的节点类型具有银级持久性级别和“Standard_D2_V2”的大小。The new node type has a durability level of Silver and size of "Standard_D2_V2".

在 template.json 文件中,添加以下新参数:In the template.json file, add the following new parameters:

"nt3InstanceCount": {
    "defaultValue": 5,
    "type": "Int",
    "metadata": {
        "description": "Instance count for node type"
    }
},
"vmNodeType3Size": {
    "defaultValue": "Standard_D2_V2",
    "type": "String"
},

在 template.json 文件中,添加以下新变量:In the template.json file, add the following new variables:

"lbID3": "[resourceId('Microsoft.Network/loadBalancers',concat('LB','-', parameters('clusterName'),'-',variables('vmNodeType3Name')))]",
"lbIPConfig3": "[concat(variables('lbID3'),'/frontendIPConfigurations/LoadBalancerIPConfig')]",
"lbPoolID3": "[concat(variables('lbID3'),'/backendAddressPools/LoadBalancerBEAddressPool')]",
"lbProbeID3": "[concat(variables('lbID3'),'/probes/FabricGatewayProbe')]",
"lbHttpProbeID3": "[concat(variables('lbID3'),'/probes/FabricHttpGatewayProbe')]",
"lbNatPoolID3": "[concat(variables('lbID3'),'/inboundNatPools/LoadBalancerBEAddressNatPool')]",
"vmNodeType3Name": "[toLower(concat('NT4', variables('vmName')))]",
"vmStorageAccountName3": "[toLower(concat(uniqueString(resourceGroup().id), '1', '3' ))]",
"nt3applicationStartPort": "20000",
"nt3applicationEndPort": "30000",
"nt3ephemeralStartPort": "49152",
"nt3ephemeralEndPort": "65534",
"nt3fabricTcpGatewayPort": "19000",
"nt3fabricHttpGatewayPort": "19080",
"nt3reverseProxyEndpointPort": "19081",
"subnet3Name": "Subnet-3",
"subnet3Prefix": "10.0.3.0/24",
"subnet3Ref": "[concat(variables('vnetID'),'/subnets/',variables('subnet3Name'))]",

在 template.json 文件中,向虚拟网络资源添加新子网:In the template.json file, add a new subnet to the virtual network resource:

{
    "type": "Microsoft.Network/virtualNetworks",
    "name": "[variables('virtualNetworkName')]",
    "apiVersion": "2018-08-01",
    "location": "[variables('computeLocation')]",
    "tags": {
        "resourceType": "Service Fabric",
        "clusterName": "[parameters('clusterName')]"
    },
    "properties": {
        "addressSpace": {
            "addressPrefixes": [
                "[variables('addressPrefix')]"
            ]
        },
        "subnets": [
            ...
            {
                "name": "[variables('subnet3Name')]",
                "properties": {
                    "addressPrefix": "[variables('subnet3Prefix')]",
                    "networkSecurityGroup": {
                        "id": "[resourceId('Microsoft.Network/networkSecurityGroups', concat('nsg', variables('subnet3Name')))]"
                    }
                }
            }
        ]
    },
    "dependsOn": [
        ...
        "[concat('Microsoft.Network/networkSecurityGroups/', concat('nsg', variables('subnet3Name')))]"
    ]
},

在 template.json 文件中,添加新的公共 IP 地址和负载均衡器资源:In the template.json file, add new public IP address and load balancer resources:

{
    "type": "Microsoft.Network/publicIPAddresses",
    "name": "[concat(variables('lbIPName'),'-',variables('vmNodeType3Name'))]",
    "apiVersion": "2018-08-01",
    "location": "[variables('computeLocation')]",
    "tags": {
        "resourceType": "Service Fabric",
        "clusterName": "[parameters('clusterName')]"
    },
    "properties": {
        "dnsSettings": {
            "domainNameLabel": "[concat(variables('dnsName'),'-','nt4')]"
        },
        "publicIPAllocationMethod": "Dynamic"
    }
},
        {
    "type": "Microsoft.Network/loadBalancers",
    "name": "[concat('LB','-', parameters('clusterName'),'-',variables('vmNodeType3Name'))]",
    "apiVersion": "2018-08-01",
    "location": "[variables('computeLocation')]",
    "tags": {
        "resourceType": "Service Fabric",
        "clusterName": "[parameters('clusterName')]"
    },
    "properties": {
        "frontendIPConfigurations": [
            {
                "name": "LoadBalancerIPConfig",
                "properties": {
                    "publicIPAddress": {
                        "id": "[resourceId('Microsoft.Network/publicIPAddresses',concat(variables('lbIPName'),'-',variables('vmNodeType3Name')))]"
                    }
                }
            }
        ],
        "backendAddressPools": [
            {
                "name": "LoadBalancerBEAddressPool",
                "properties": {}
            }
        ],
        "loadBalancingRules": [
            {
                "name": "LBRule",
                "properties": {
                    "backendAddressPool": {
                        "id": "[variables('lbPoolID3')]"
                    },
                    "backendPort": "[variables('nt3fabricTcpGatewayPort')]",
                    "enableFloatingIP": "false",
                    "frontendIPConfiguration": {
                        "id": "[variables('lbIPConfig3')]"
                    },
                    "frontendPort": "[variables('nt3fabricTcpGatewayPort')]",
                    "idleTimeoutInMinutes": "5",
                    "probe": {
                        "id": "[variables('lbProbeID3')]"
                    },
                    "protocol": "tcp"
                }
            },
            {
                "name": "LBHttpRule",
                "properties": {
                    "backendAddressPool": {
                        "id": "[variables('lbPoolID3')]"
                    },
                    "backendPort": "[variables('nt3fabricHttpGatewayPort')]",
                    "enableFloatingIP": "false",
                    "frontendIPConfiguration": {
                        "id": "[variables('lbIPConfig3')]"
                    },
                    "frontendPort": "[variables('nt3fabricHttpGatewayPort')]",
                    "idleTimeoutInMinutes": "5",
                    "probe": {
                        "id": "[variables('lbHttpProbeID3')]"
                    },
                    "protocol": "tcp"
                }
            },
            {
                "name": "AppPortLBRule1",
                "properties": {
                    "backendAddressPool": {
                        "id": "[variables('lbPoolID3')]"
                    },
                    "backendPort": "[parameters('loadBalancedAppPort1')]",
                    "enableFloatingIP": "false",
                    "frontendIPConfiguration": {
                        "id": "[variables('lbIPConfig3')]"
                    },
                    "frontendPort": "[parameters('loadBalancedAppPort1')]",
                    "idleTimeoutInMinutes": "5",
                    "probe": {
                        "id": "[concat(variables('lbID3'),'/probes/AppPortProbe1')]"
                    },
                    "protocol": "tcp"
                }
            },
            {
                "name": "AppPortLBRule2",
                "properties": {
                    "backendAddressPool": {
                        "id": "[variables('lbPoolID3')]"
                    },
                    "backendPort": "[parameters('loadBalancedAppPort2')]",
                    "enableFloatingIP": "false",
                    "frontendIPConfiguration": {
                        "id": "[variables('lbIPConfig3')]"
                    },
                    "frontendPort": "[parameters('loadBalancedAppPort2')]",
                    "idleTimeoutInMinutes": "5",
                    "probe": {
                        "id": "[concat(variables('lbID3'),'/probes/AppPortProbe2')]"
                    },
                    "protocol": "tcp"
                }
            }
        ],
        "probes": [
            {
                "name": "FabricGatewayProbe",
                "properties": {
                    "intervalInSeconds": 5,
                    "numberOfProbes": 2,
                    "port": "[variables('nt3fabricTcpGatewayPort')]",
                    "protocol": "tcp"
                }
            },
            {
                "name": "FabricHttpGatewayProbe",
                "properties": {
                    "intervalInSeconds": 5,
                    "numberOfProbes": 2,
                    "port": "[variables('nt3fabricHttpGatewayPort')]",
                    "protocol": "tcp"
                }
            },
            {
                "name": "AppPortProbe1",
                "properties": {
                    "intervalInSeconds": 5,
                    "numberOfProbes": 2,
                    "port": "[parameters('loadBalancedAppPort1')]",
                    "protocol": "tcp"
                }
            },
            {
                "name": "AppPortProbe2",
                "properties": {
                    "intervalInSeconds": 5,
                    "numberOfProbes": 2,
                    "port": "[parameters('loadBalancedAppPort2')]",
                    "protocol": "tcp"
                }
            }
        ],
        "inboundNatPools": [
            {
                "name": "LoadBalancerBEAddressNatPool",
                "properties": {
                    "backendPort": "3389",
                    "frontendIPConfiguration": {
                        "id": "[variables('lbIPConfig3')]"
                    },
                    "frontendPortRangeEnd": "4500",
                    "frontendPortRangeStart": "3389",
                    "protocol": "tcp"
                }
            }
        ]
    },
    "dependsOn": [
        "[concat('Microsoft.Network/publicIPAddresses/',concat(variables('lbIPName'),'-',variables('vmNodeType3Name')))]"
    ]
},

在 template.json 文件中,添加新网络安全组和虚拟机规模集资源。In the template.json file, add new network security group and virtual machine scale set resources. 虚拟机规模集的 Service Fabric 扩展属性内的 NodeTypeRef 属性会将指定的节点类型映射到规模集。The NodeTypeRef property within the Service Fabric extension properties of the virtual machine scale set maps the specified node type to the scale set.

{
    "type": "Microsoft.Network/networkSecurityGroups",
    "name": "[concat('nsg', variables('subnet3Name'))]",
    "apiVersion": "2018-08-01",
    "location": "[resourceGroup().location]",
    "tags": {
        "resourceType": "Service Fabric",
        "clusterName": "[parameters('clusterName')]"
    },
    "properties": {
        "securityRules": [
            {
                "name": "allowSvcFabSMB",
                "properties": {
                    "access": "Allow",
                    "destinationAddressPrefix": "*",
                    "destinationPortRange": "445",
                    "direction": "Inbound",
                    "priority": 3950,
                    "protocol": "*",
                    "sourceAddressPrefix": "VirtualNetwork",
                    "sourcePortRange": "*",
                    "description": "allow SMB traffic within the net, used by fabric to move packages around"
                }
            },
            {
                "name": "allowSvcFabCluser",
                "properties": {
                    "access": "Allow",
                    "destinationAddressPrefix": "*",
                    "destinationPortRange": "1025-1027",
                    "direction": "Inbound",
                    "priority": 3920,
                    "protocol": "*",
                    "sourceAddressPrefix": "VirtualNetwork",
                    "sourcePortRange": "*",
                    "description": "allow ports within vnet that are used by the fabric to talk between nodes"
                }
            },
            {
                "name": "allowSvcFabEphemeral",
                "properties": {
                    "access": "Allow",
                    "destinationAddressPrefix": "*",
                    "destinationPortRange": "[concat(variables('nt3ephemeralStartPort'), '-', variables('nt3ephemeralEndPort'))]",
                    "direction": "Inbound",
                    "priority": 3930,
                    "protocol": "*",
                    "sourceAddressPrefix": "VirtualNetwork",
                    "sourcePortRange": "*",
                    "description": "allow fabric ephemeral ports within the vnet"
                }
            },
            {
                "name": "allowSvcFabPortal",
                "properties": {
                    "access": "Allow",
                    "destinationAddressPrefix": "*",
                    "destinationPortRange": "[variables('nt3fabricHttpGatewayPort')]",
                    "direction": "Inbound",
                    "priority": 3900,
                    "protocol": "*",
                    "sourceAddressPrefix": "*",
                    "sourcePortRange": "*",
                    "description": "allow port used to access the fabric cluster web portal"
                }
            },
            {
                "name": "allowSvcFabClient",
                "properties": {
                    "access": "Allow",
                    "destinationAddressPrefix": "*",
                    "destinationPortRange": "[variables('nt3fabricTcpGatewayPort')]",
                    "direction": "Inbound",
                    "priority": 3910,
                    "protocol": "*",
                    "sourceAddressPrefix": "*",
                    "sourcePortRange": "*",
                    "description": "allow port used by the fabric client (includes powershell)"
                }
            },
            {
                "name": "allowSvcFabApplication",
                "properties": {
                    "access": "Allow",
                    "destinationAddressPrefix": "*",
                    "destinationPortRange": "[concat(variables('nt3applicationStartPort'), '-', variables('nt3applicationEndPort'))]",
                    "direction": "Inbound",
                    "priority": 3940,
                    "protocol": "*",
                    "sourceAddressPrefix": "*",
                    "sourcePortRange": "*",
                    "description": "allow fabric application ports within the vnet"
                }
            },
            {
                "name": "blockAll",
                "properties": {
                    "access": "Deny",
                    "destinationAddressPrefix": "*",
                    "destinationPortRange": "*",
                    "direction": "Inbound",
                    "priority": 4095,
                    "protocol": "*",
                    "sourceAddressPrefix": "*",
                    "sourcePortRange": "*",
                    "description": "block all traffic except what we've explicitly allowed"
                }
            },
            {
                "name": "allowVNetRDP",
                "properties": {
                    "access": "Allow",
                    "destinationAddressPrefix": "*",
                    "destinationPortRange": "3389",
                    "direction": "Inbound",
                    "priority": 3960,
                    "protocol": "*",
                    "sourceAddressPrefix": "*",
                    "sourcePortRange": "*",
                    "description": "allow RDP within the net"
                }
            },
            {
                "name": "allowSvcFabReverseProxy",
                "properties": {
                    "access": "Allow",
                    "destinationAddressPrefix": "*",
                    "destinationPortRange": "[variables('nt3reverseProxyEndpointPort')]",
                    "direction": "Inbound",
                    "priority": 3980,
                    "protocol": "*",
                    "sourceAddressPrefix": "*",
                    "sourcePortRange": "*",
                    "description": "allow port used to access the fabric cluster using reverse proxy"
                }
            },
            {
                "name": "allowAppPort1",
                "properties": {
                    "access": "Allow",
                    "destinationAddressPrefix": "*",
                    "destinationPortRange": "[parameters('loadBalancedAppPort1')]",
                    "direction": "Inbound",
                    "priority": 2001,
                    "protocol": "*",
                    "sourceAddressPrefix": "*",
                    "sourcePortRange": "*",
                    "description": "allow public application port 1"
                }
            },
            {
                "name": "allowAppPort2",
                "properties": {
                    "access": "Allow",
                    "destinationAddressPrefix": "*",
                    "destinationPortRange": "[parameters('loadBalancedAppPort2')]",
                    "direction": "Inbound",
                    "priority": 2002,
                    "protocol": "*",
                    "sourceAddressPrefix": "*",
                    "sourcePortRange": "*",
                    "description": "allow public application port 2"
                }
            }
        ]
    }
},
{
    "type": "Microsoft.Compute/virtualMachineScaleSets",
    "sku": {
        "name": "[parameters('vmNodeType3Size')]",
        "capacity": "[parameters('nt3InstanceCount')]",
        "tier": "Standard"
    },
    "name": "[variables('vmNodeType3Name')]",
    "apiVersion": "2018-10-01",
    "location": "[variables('computeLocation')]",
    "tags": {
        "resourceType": "Service Fabric",
        "clusterName": "[parameters('clusterName')]"
    },
    "properties": {
        "overprovision": "[variables('overProvision')]",
        "upgradePolicy": {
            "mode": "Automatic"
        },
        "virtualMachineProfile": {
            "extensionProfile": {
                "extensions": [
                    {
                        "name": "[concat(variables('vmNodeType3Name'),'OMS')]",
                        "properties": {
                            "publisher": "Microsoft.EnterpriseCloud.Monitoring",
                            "type": "MicrosoftMonitoringAgent",
                            "typeHandlerVersion": "1.0",
                            "autoUpgradeMinorVersion": true,
                            "settings": {
                                "workspaceId": "[reference(resourceId('Microsoft.OperationalInsights/workspaces/', parameters('omsWorkspacename')), '2015-11-01-preview').customerId]"
                            },
                            "protectedSettings": {
                                "workspaceKey": "[listKeys(resourceId('Microsoft.OperationalInsights/workspaces/', parameters('omsWorkspacename')),'2015-11-01-preview').primarySharedKey]"
                            }
                        }
                    },
                    {
                        "name": "[concat('ServiceFabricNodeVmExt','_vmNodeType3Name')]",
                        "properties": {
                            "type": "ServiceFabricNode",
                            "autoUpgradeMinorVersion": true,
                            "protectedSettings": {
                                "StorageAccountKey1": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('supportLogStorageAccountName')),'2015-05-01-preview').key1]",
                                "StorageAccountKey2": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('supportLogStorageAccountName')),'2015-05-01-preview').key2]"
                            },
                            "publisher": "Microsoft.Azure.ServiceFabric",
                            "settings": {
                                "clusterEndpoint": "[reference(parameters('clusterName')).clusterEndpoint]",
                                "nodeTypeRef": "[variables('vmNodeType3Name')]",
                                "dataPath": "D:\\SvcFab",
                                "durabilityLevel": "Silver",
                                "enableParallelJobs": true,
                                "nicPrefixOverride": "[variables('subnet3Prefix')]",
                                "certificate": {
                                    "thumbprint": "[parameters('certificateThumbprint')]",
                                    "x509StoreName": "[parameters('certificateStoreValue')]"
                                }
                            },
                            "typeHandlerVersion": "1.0"
                        }
                    },
                    {
                        "name": "[concat('VMDiagnosticsVmExt','_vmNodeType3Name')]",
                        "properties": {
                            "type": "IaaSDiagnostics",
                            "autoUpgradeMinorVersion": true,
                            "protectedSettings": {
                                "storageAccountName": "[variables('applicationDiagnosticsStorageAccountName')]",
                                "storageAccountKey": "[listKeys(resourceId('Microsoft.Storage/storageAccounts', variables('applicationDiagnosticsStorageAccountName')),'2015-05-01-preview').key1]",
                                "storageAccountEndPoint": "https://core.chinacloudapi.cn/"
                            },
                            "publisher": "Microsoft.Azure.Diagnostics",
                            "settings": {
                                "WadCfg": {
                                    "DiagnosticMonitorConfiguration": {
                                        "overallQuotaInMB": "50000",
                                        "EtwProviders": {
                                            "EtwEventSourceProviderConfiguration": [
                                                {
                                                    "provider": "Microsoft-ServiceFabric-Actors",
                                                    "scheduledTransferKeywordFilter": "1",
                                                    "scheduledTransferPeriod": "PT5M",
                                                    "DefaultEvents": {
                                                        "eventDestination": "ServiceFabricReliableActorEventTable"
                                                    }
                                                },
                                                {
                                                    "provider": "Microsoft-ServiceFabric-Services",
                                                    "scheduledTransferPeriod": "PT5M",
                                                    "DefaultEvents": {
                                                        "eventDestination": "ServiceFabricReliableServiceEventTable"
                                                    }
                                                }
                                            ],
                                            "EtwManifestProviderConfiguration": [
                                                {
                                                    "provider": "cbd93bc2-71e5-4566-b3a7-595d8eeca6e8",
                                                    "scheduledTransferLogLevelFilter": "Information",
                                                    "scheduledTransferKeywordFilter": "4611686018427387904",
                                                    "scheduledTransferPeriod": "PT5M",
                                                    "DefaultEvents": {
                                                        "eventDestination": "ServiceFabricSystemEventTable"
                                                    }
                                                }
                                            ]
                                        }
                                    }
                                },
                                "StorageAccount": "[variables('applicationDiagnosticsStorageAccountName')]"
                            },
                            "typeHandlerVersion": "1.5"
                        }
                    },
                    {
                        "name": "[concat('VMIaaSAntimalware','_vmNodeType3Name')]",
                        "properties": {
                            "publisher": "Microsoft.Azure.Security",
                            "type": "IaaSAntimalware",
                            "typeHandlerVersion": "1.5",
                            "settings": {
                                "AntimalwareEnabled": "true",
                                "Exclusions": {
                                    "Paths": "D:\\SvcFab;D:\\SvcFab\\Log;C:\\Program Files\\Microsoft Service Fabric",
                                    "Processes": "Fabric.exe;FabricHost.exe;FabricInstallerService.exe;FabricSetup.exe;FabricDeployer.exe;ImageBuilder.exe;FabricGateway.exe;FabricDCA.exe;FabricFAS.exe;FabricUOS.exe;FabricRM.exe;FileStoreService.exe"
                                },
                                "RealtimeProtectionEnabled": "true",
                                "ScheduledScanSettings": {
                                    "isEnabled": "true",
                                    "scanType": "Quick",
                                    "day": "7",
                                    "time": "120"
                                }
                            },
                            "protectedSettings": null
                        }
                    }
                ]
            },
            "networkProfile": {
                "networkInterfaceConfigurations": [
                    {
                        "name": "[concat(variables('nicName'), '-2')]",
                        "properties": {
                            "ipConfigurations": [
                                {
                                    "name": "[concat(variables('nicName'),'-',2)]",
                                    "properties": {
                                        "loadBalancerBackendAddressPools": [
                                            {
                                                "id": "[variables('lbPoolID3')]"
                                            }
                                        ],
                                        "loadBalancerInboundNatPools": [
                                            {
                                                "id": "[variables('lbNatPoolID3')]"
                                            }
                                        ],
                                        "subnet": {
                                            "id": "[variables('subnet3Ref')]"
                                        }
                                    }
                                }
                            ],
                            "primary": true
                        }
                    }
                ]
            },
            "osProfile": {
                "adminPassword": "[parameters('adminPassword')]",
                "adminUsername": "[parameters('adminUsername')]",
                "computernamePrefix": "[variables('vmNodeType3Name')]",
                "secrets": [
                    {
                        "sourceVault": {
                            "id": "[parameters('sourceVaultValue')]"
                        },
                        "vaultCertificates": [
                            {
                                "certificateStore": "[parameters('certificateStoreValue')]",
                                "certificateUrl": "[parameters('certificateUrlValue')]"
                            }
                        ]
                    }
                ]
            },
            "storageProfile": {
                "imageReference": {
                    "publisher": "[parameters('vmImagePublisher')]",
                    "offer": "[parameters('vmImageOffer')]",
                    "sku": "[parameters('vmImageSku')]",
                    "version": "[parameters('vmImageVersion')]"
                },
                "osDisk": {
                    "caching": "ReadOnly",
                    "createOption": "FromImage",
                    "managedDisk": {
                        "storageAccountType": "[parameters('storageAccountType')]"
                    }
                }
            }
        }
    },
    "dependsOn": [
        "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]",
        "[concat('Microsoft.Network/loadBalancers/', concat('LB','-', parameters('clusterName'),'-',variables('vmNodeType3Name')))]",
        "[concat('Microsoft.Storage/storageAccounts/', variables('supportLogStorageAccountName'))]",
        "[concat('Microsoft.Storage/storageAccounts/', variables('applicationDiagnosticsStorageAccountName'))]"
    ]
},

在 template.json 文件中,更新群集资源,并添加新的节点类型:In the template.json file, update the cluster resource and add a new node type:

{
    "type": "Microsoft.ServiceFabric/clusters",
    "name": "[parameters('clusterName')]",
    "apiVersion": "2018-02-01",
    "location": "[parameters('clusterLocation')]",
    "tags": {
        "resourceType": "Service Fabric",
        "clusterName": "[parameters('clusterName')]"
    },
    "properties": {
        "nodeTypes": [
            ...
            {
                "name": "[variables('vmNodeType3Name')]",
                "applicationPorts": {
                    "endPort": "[variables('nt3applicationEndPort')]",
                    "startPort": "[variables('nt3applicationStartPort')]"
                },
                "clientConnectionEndpointPort": "[variables('nt3fabricTcpGatewayPort')]",
                "durabilityLevel": "Silver",
                "ephemeralPorts": {
                    "endPort": "[variables('nt3ephemeralEndPort')]",
                    "startPort": "[variables('nt3ephemeralStartPort')]"
                },
                "httpGatewayEndpointPort": "[variables('nt3fabricHttpGatewayPort')]",
                "isPrimary": false,
                "reverseProxyEndpointPort": "[variables('nt3reverseProxyEndpointPort')]",
                "vmInstanceCount": "[parameters('nt3InstanceCount')]"
            }
        ],    
    }
}

在 parameters.json 文件中,添加以下新参数和值:In the parameters.json file, add the following new parameters and values:

"nt3InstanceCount": {
    "Value": 5    
},
"vmNodeType3Size": {
    "Value": "Standard_D2_V2"
},

部署已更新的模板Deploy the updated template

将任何更改保存到 template.json 和 parameters.json 文件 。Save any changes to the template.json and parameters.json files. 若要部署更新的模板,请运行以下命令:To deploy the updated template, run the following command:

New-AzResourceGroupDeployment -ResourceGroupName sfclustertutorialgroup -TemplateFile c:\temp\template.json -TemplateParameterFile c:\temp\parameters.json -Name "AddingNodeType"

或者运行以下 Azure CLI 命令:Or the following Azure CLI command:

az group deployment create --resource-group sfclustertutorialgroup --template-file c:\temp\template.json --parameters c:\temp\parameters.json

从群集中删除节点类型Remove a node type from the cluster

创建 Service Fabric 群集之后,可以通过删除节点类型(虚拟机规模集)及其所有节点来水平缩放群集。After creating a Service Fabric cluster, you can scale a cluster horizontally by removing a node type (virtual machine scale set) and all of its nodes. 随时可以缩放群集,即使该群集上正在运行工作负荷。You can scale the cluster at any time, even when workloads are running on the cluster. 在缩放群集的同时,应用程序也会随之自动缩放。As the cluster scales, your applications automatically scale as well.

Warning

建议不要频繁使用 Remove-AzServiceFabricNodeType 从生产群集中删除节点类型。Using Remove-AzServiceFabricNodeType to remove a node type from a production cluster is not recommended to be used on a frequent basis. 这是一个非常危险的命令,因为它会删除节点类型后的虚拟机规模集资源。It is a dangerous command as it deletes the virtual machine scale set resource behind the node type.

若要删除节点类型,请运行 Remove-AzServiceFabricNodeType cmdlet。To remove the node type, run the Remove-AzServiceFabricNodeType cmdlet. 节点类型必须为银级或金级持久性级别,此 cmdlet 会删除与节点类型关联的规模集,并需要一些时间来完成操作。The node type must be Silver or Gold durability level The cmdlet deletes the scale set associated with the node type and takes some time to complete. 然后在每个要删除的节点上运行 Remove-servicefabricnodestate cmdlet,这会删除节点状态并从群集删除节点。Then run the Remove-ServiceFabricNodeState cmdlet on each of the nodes to remove, which deletes the node state and removes the nodes from the cluster. 如果节点上有服务,则首先将服务移出到另一个节点。If there are services on the nodes, then the services are first moved out to another node. 如果群集管理器找不到副本/服务的节点,则会延迟/阻止该操作。If the cluster manager cannot find a node for the replica/service, then the operation is delayed/blocked.

$groupname = "sfclustertutorialgroup"
$nodetype = "nt4vm"
$clustername = "mysfcluster123"

Remove-AzServiceFabricNodeType -Name $clustername  -NodeType $nodetype -ResourceGroupName $groupname

Connect-ServiceFabricCluster -ConnectionEndpoint mysfcluster123.chinaeast.cloudapp.chinacloudapi.cn:19000 `
          -KeepAliveIntervalInSec 10 `
          -X509Credential -ServerCertThumbprint <thumbprint> `
          -FindType FindByThumbprint -FindValue <thumbprint> `
          -StoreLocation CurrentUser -StoreName My

$nodes = Get-ServiceFabricNode | Where-Object {$_.NodeType -eq $nodetype} | Sort-Object { $_.NodeName.Substring($_.NodeName.LastIndexOf('_') + 1) } -Descending

Foreach($node in $nodes)
{
    Remove-ServiceFabricNodeState -NodeName $node.NodeName -TimeoutSec 300 -Force 
}

增加节点资源Increase node resources

创建 Service Fabric 群集后,可以纵向缩放群集节点类型(更改节点的资源)或升级节点类型 VM 的操作系统。After creating a Service Fabric cluster, you can scale a cluster node type vertically (change the resources of the nodes) or upgrade the operating system of the node type VMs.

Warning

我们建议不要更改规模集/节点类型的 VM SKU,除非它在银级持久性或更高的级别运行。We recommend that you do not change the VM SKU of a scale set/node type unless it is running at Silver durability or greater. 更改 VM SKU 大小是一种破坏数据的就地基础结构操作。Changing the VM SKU size is a data-destructive in-place infrastructure operation. 由于无法延迟或监视此更改,此操作可能会导致有状态服务的数据丢失或其他意外操作问题(甚至可能影响无状态工作负载)。Without some ability to delay or monitor this change, it is possible that the operation can cause data loss for stateful services or cause other unforeseen operational issues, even for stateless workloads.

Warning

我们建议不要更改主节点类型的 VM SKU,这是一种不受支持的危险操作。We recommend that you do not change the VM SKU of the primary node type, which is a dangerous operation and unsupported. 如果需要更多群集容量,可以添加更多 VM 实例或更多节点类型。If you need more cluster capacity, you can add more VM instances or additional node types. 如果这不可行,可以创建新群集并从旧群集还原应用程序状态(如果适用)。If that is not possible, you can create a new cluster and restore application state (if applicable) from your old cluster. 如果无法执行此操作,则可以更改主节点类型的 VM SKUIf that is not possible, you can change the VM SKU of the primary node type.

更新模板Update the template

从最近的部署的资源组中导出模板和参数文件Export a template and parameters file from the resource group for the most recent deployment. 打开 Parameters.json 文件。Open the parameters.json file. 如果使用本教程中的示例模板部署了群集,群集中就有三个节点类型。If you deployed the cluster using the sample template in this tutorial, there are three node types in the cluster.

第二个节点类型中 VM 的大小在 vmNodeType1Size 参数中设置。The size of the VMs in the second node type is set in the vmNodeType1Size parameter. 将 vmNodeType1Size 参数值从 Standard_D2_V2 更改为 Standard_D3_V2,这会让每个 VM 实例的资源增加一倍。Change the vmNodeType1Size parameter value from Standard_D2_V2 to Standard_D3_V2, which doubles the resources of each VM instance.

所有三个节点类型的 VM SKU 在 vmImageSku 参数中设置。The VM SKU for all three node types is set in the vmImageSku parameter. 同样,更改节点类型的 VM SKU 应慎重,不建议对主节点类型执行此操作。Again, changing the VM SKU of a node type should be approached with caution and is not recommended for the primary node type.

部署已更新的模板Deploy the updated template

将任何更改保存到 template.json 和 parameters.json 文件 。Save any changes to the template.json and parameters.json files. 若要部署更新的模板,请运行以下命令:To deploy the updated template, run the following command:

New-AzResourceGroupDeployment -ResourceGroupName sfclustertutorialgroup -TemplateFile c:\temp\template.json -TemplateParameterFile c:\temp\parameters.json -Name "ScaleUpNodeType"

或者运行以下 Azure CLI 命令:Or the following Azure CLI command:

az group deployment create --resource-group sfclustertutorialgroup --template-file c:\temp\template.json --parameters c:\temp\parameters.json

后续步骤Next steps

在本教程中,你已学习了如何执行以下操作:In this tutorial, you learned how to:

  • 添加和删除节点(横向扩展和缩小)Add and remove nodes (scale out and scale in)
  • 添加和删除节点类型(横向扩展和缩小)Add and remove node types (scale out and scale in)
  • 增加节点资源(纵向扩展)Increase node resources (scale up)

接下来,请转到以下教程了解如何升级群集运行时。Next, advance to the following tutorial to learn how to upgrade the runtime of a cluster.