Skip to content

Instantly share code, notes, and snippets.

@pngan
Last active April 17, 2025 09:30
Show Gist options
  • Save pngan/63e0b831941bdfe901696d42395639cd to your computer and use it in GitHub Desktop.
Save pngan/63e0b831941bdfe901696d42395639cd to your computer and use it in GitHub Desktop.
This is step by step guide to provision an Azure Service Fabric using PowerShell.

Service Fabric Provisioning

This is step by step guide to provision an Azure Service Fabric using PowerShell.

Prerequisites

  • Windows 7 or later
  • Administrator privileges
  • An active Azure subscription

Check PowerShell is later than v5

Open a Windows Powershell window as Administrator, and at the prompt run:

Write-Host $PSVersionTable.PSVersion

which will print out the current version of PowerShell installed on the machine. If the version is version 4 or lower, install the latest version of PowerShell, which is part of the Windows Management Framework 5.1 or above: https://www.microsoft.com/en-us/download/details.aspx?id=54616

Install PowerShellGet

https://docs.microsoft.com/en-us/powershell/azure/install-azurerm-ps?view=azurermps-4.2.0&viewFallbackFrom=azurermps-4.2.0%7Cto

Next check that you have PowerShellGet installed. You can check by running command

Get-Module PowerShellGet -list | Select-Object Name,Version,Path

which will produce the following output if PowerShellGet is present

Name          Version Path
----          ------- ----
PowerShellGet 1.0.0.1 C:\Program Files\WindowsPowerShell\Modules\PowerShellGet\1.0.0.1\PowerShellGet.psd1

If PowerShellGet is not installed, install WMF 5+ from https://www.microsoft.com/en-us/download/details.aspx?id=54616

Install and Load Azure PowerShell components

Install-Module AzureRM #install the Azure PowerShell from the PowerShell gallery
Import-Module AzureRM

Login and Setup Resource Groups

Login-AzureRmAccount # Login into Azure, and enter your Azure subscription credentials when prompted

# Create some resource groups to hold the key vault and cluster
$locationRegion = "Southeast Asia" # You can use any region that supports service cluster
New-AzureRmResourceGroup -Name "sf-keyvault" -Location $locationRegion
New-AzureRmResourceGroup -Name "sf-cluster" -Location $locationRegion

Separate resource groups are provide a convenient way of recreating the cluster, without having to recreate the key vault.

Get Certificate Helper

Download the PowerShell cmdlet Invoke-AddCertToKeyVault which is part of the Azure PowerShell helpers from https://github.com/ChackDan/Service-Fabric Once downloaded, import the module

Import-Module "<path>\ServiceFabricRPHelpers.psm1"

Create Key Vault

Next get the subscription Id you are wanting to use for the provisioning. These can be obtained by running:

Get-AzureRmSubscription

and take note of the subscription Id. Once you have this, you can create the key vault and a self-signed certificate. if you already have a certificate, this may be used instead of the self-signed certificate. The key vault and service fabric cluster must reside in the same region, so choose this region carefully otherwise you'll have to recreate the key vault if the service fabric moves to another region.

$ResourceGroup = "sf-keyvault"
$VName = "sf-vault"

New-AzureRmKeyVault -VaultName $VName -ResourceGroupName $ResourceGroup -Location $locationRegion -EnabledForDeployment

This command will produce output similar to the following:

     Vault Name                       : sf-vault
     Resource Group Name              : sf-keyvault
     Location                         : Southeast Asia
     Resource ID                      : /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxx/resourceGroups/sf-vault/providers/Microsoft.KeyVault/vaults/sf-vault
     Vault URI                        : https://sf-vault.vault.azure.net
     Tenant ID                        : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxx
     SKU                              : Standard
     Enabled For Deployment?          : True
     Enabled For Template Deployment? : False
     Enabled For Disk Encryption?     : False
     Soft Delete Enabled?             :
     Access Policies                  :
                                        Tenant ID                   : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxx
                                        Object ID                   : xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxx
                                        Application ID              :
                                        Display Name                : John Doe 
                                        Permissions to Keys         : get, create, delete, list, update, import, backup, restore, recover
                                        Permissions to Secrets      : get, list, set, delete, backup, restore, recover
                                        Permissions to Certificates : get, delete, list, create, import, update, deleteissuers, getissuers, listissuers, managecontacts, manageissuers, setissuers

Then create a self-signed certificate and add this certificate to the key vault.

$SubscriptionID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxx"
$newCertName = "clustercert"
$dnsName = "https://sf-vault.vault.azure.net/" #The certificate's subject name must match the domain used to access the Service Fabric cluster.
$localCertPath = "C:\MyCertificates" # location where you want the .PFX to be stored
Invoke-AddCertToKeyVault -SubscriptionId $SubscriptionID -ResourceGroupName $ResourceGroup -Location $locationRegion -VaultName $VName -CertificateName $newCertName -CreateSelfSignedCertificate -DnsName $dnsName -OutputPath $localCertPath

This will produce output similar too:

   Name                           Value
     ----                           -----
     CertificateThumbprint          yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy
                                    
     SourceVault                    /subscriptions/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxx/resourceGroups/sf-keyvault/providers/Microsoft.KeyVault/vaults/sf-vault
     CertificateURL                 https://sf-vault.vault.azure.net:443/secrets/clustercert/zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz

Copy this information to a text file because needed to create the deployment template later.

Install the certificate in the local machines certificate store. This can be done by opening the file C:\MyCertificates\clustercert.pfx and placing it into the certicate store for Current User. Any machine used to start, stop, update the service fabric deployment will need this certificate to be installed in the machines certificate store.

Create Service Fabric Cluster

First create a resource group for the cluster

 $ResouceGroup = "sf-cluster"
 $locationRegion = "Southeast Asia"
 New-AzureRmResourceGroup -Name $ResouceGroup -Location $locationRegion

Here is a deployment template based on the templates given in : https://github.com/Azure/azure-quickstart-templates/tree/master/service-fabric-secure-cluster-5-node-1-nodetype This json should be placed in a file named azuredeploy.parameters.json.

In order to reduce the cost we have altered the template to use three A1 virtual machines.

This template will need to be customized for your configuration. The certificate related values that need to be changed can be obtained using:

  • $VaultName = (Get-AzureRmKeyVault).VaultName
  • The sourceVaultvalue value can be retrieved using the command Get-AzureRmKeyVault.
  • The clusterCertificateUrlValue value can be retrieved using the command Get-AzureKeyVaultSecret -VaultName $VaultName -Name (Get-AzureKeyVaultSecret -VaultName $VaultName).Name

azuredeploy.parameters.json

{
  "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "clusterLocation": {
      "value": "southeastasia"
    },
    "clusterName": {
      "value": "sf-cluster"
    },
    "adminUserName": {
      "value": "admuser"
    },
    "adminPassword": {
      "value": "Pa$$word$1"
    },
    "vmImagePublisher": {
      "value": "MicrosoftWindowsServer"
    },
    "vmImageOffer": {
      "value": "WindowsServer"
    },
    "vmImageSku": {
      "value": "2016-Datacenter"
    },
    "vmImageVersion": {
      "value": "latest"
    },
    "loadBalancedAppPort1": {
      "value": 80
    },
    "loadBalancedAppPort2": {
      "value": 8081
    },
    "certificateStorevalue": {
      "value": "My"
    },
    "certificateThumbprint": {
      "value": "99912345o458045827c723047234"
    },
    "sourceVaultvalue": {
      "value": "/subscriptions/<Sub ID>/resourceGroups/<Resource group name>/providers/Microsoft.KeyVault/vaults/<vault name>"
    },
    "certificateUrlvalue": {
      "value": "https://sf-vault.vault.azure.net:443/secrets/<exact location>"
    },
    "clusterProtectionLevel": {
      "value": "EncryptAndSign"
    },
    "storageAccountType": {
      "value": "Standard_LRS"
    },
    "supportLogStorageAccountType": {
      "value": "Standard_LRS"
    },
    "applicationDiagnosticsStorageAccountType": {
      "value": "Standard_LRS"
    },
	"nodeTypeSize": {
      "value": "Standard_A1"
    },
    "nt0InstanceCount": {
      "value": 3
    },
	"nodeTypeReliabilityLevel": {
      "value": "Bronze"
    }
  }
}

azuredeploy.json

The accompanying deployment template is stored in azuredeploy.json.

{
  "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json",
  "contentVersion": "1.0.0.0",
  "parameters": {
    "clusterLocation": {
      "type": "string",
      "metadata": {
        "description": "Location of the Cluster"
      }
    },
    "clusterName": {
      "type": "string",
      "defaultValue": "sf-cluster",
      "metadata": {
        "description": "Name of your cluster - Between 3 and 23 characters. Letters and numbers only"
      }
    },
    "adminUserName": {
      "type": "string",
      "metadata": {
        "description": "Remote desktop user Id"
      }
    },
    "adminPassword": {
      "type": "securestring",
      "metadata": {
        "description": "Remote desktop user password. Must be a strong password"
      }
    },
    "vmImagePublisher": {
      "type": "string",
      "defaultValue": "MicrosoftWindowsServer",
      "metadata": {
      "description": "VM image Publisher"}
    },
    "vmImageOffer": {
      "type": "string",
      "defaultValue": "WindowsServer",
      "metadata": {
      "description": "VM image offer"}
    },
    "vmImageSku": {
      "type": "string",
      "defaultValue": "2012-R2-Datacenter",
      "metadata": {
      "description": "VM image SKU"}
    },
    "vmImageVersion": {
      "type": "string",
      "defaultValue": "latest",
      "metadata": {
      "description": "VM image version"}
    },
    "loadBalancedAppPort1": {
      "type": "int",
      "defaultValue": 80,
      "metadata": {
        "description": "Input endpoint1 for the application to use. Replace it with what your application uses"
      }
    },
    "loadBalancedAppPort2": {
      "type": "int",
      "defaultValue": 8081,
      "metadata": {
        "description": "Input endpoint2 for the application to use. Replace it with what your application uses"
      }
    },
    "sourceVaultValue": {
      "type": "string",
      "metadata": {
        "description": "Resource Id of the key vault, is should be in the format of /subscriptions/<Sub ID>/resourceGroups/<Resource group name>/providers/Microsoft.KeyVault/vaults/<vault name>"
      }
    },    
    "clusterProtectionLevel": {
      "type": "string",
      "allowedValues": [
        "None",
        "Sign",
        "EncryptAndSign"
      ],
      "defaultValue": "EncryptAndSign",
      "metadata": {
        "description": "Protection level.Three values are allowed - EncryptAndSign, Sign, None. It is best to keep the default of EncryptAndSign, unless you have a need not to"
      }
    },
    "storageAccountType": {
      "type": "string",
      "allowedValues": [
        "Standard_LRS",
        "Standard_GRS"
      ],
      "defaultValue": "Standard_LRS",
      "metadata": {
        "description": "Replication option for the VM image storage account"
      }
    },
    "supportLogStorageAccountType": {
      "type": "string",
      "allowedValues": [
        "Standard_LRS",
        "Standard_GRS"
      ],
      "defaultValue": "Standard_LRS",
      "metadata": {
        "description": "Replication option for the support log storage account"
      }
    },
    "applicationDiagnosticsStorageAccountType": {
      "type": "string",
      "allowedValues": [
        "Standard_LRS",
        "Standard_GRS"
      ],
      "defaultValue": "Standard_LRS",
      "metadata": {
        "description": "Replication option for the application diagnostics storage account"
      }
    },
	"nodeTypeSize": {
      "type": "string",
      "metadata": {
        "description": "Node Type size of the Cluster"
      }
    },
    "nt0InstanceCount": {
      "type": "int",
      "defaultValue": 3,
      "metadata": {
        "description": "Instance count for node type"
      }
    },
	"nodeTypeReliabilityLevel": {
      "type": "string",
      "metadata": {
        "description": "It can be one of 'Platinum'(9 replicas), 'Gold'(7 replicas), Silver'(5 replicas) and 'Bronze'(3 replicas)"
      }
    },
	"clusterCertificateUrlValue": {
      "type": "string",
      "metadata": {
        "description": "Refers to the location URL in your key vault where the certificate was uploaded, it is should be in the format of https://<name of the vault>.vault.azure.net:443/secrets/<exact location>"
      }
    },
	"clusterCertificateThumbprint": {
      "type": "string",
      "metadata": {
        "description": "Cluster Certificate Thumbprint"
      }
    },
	"clusterCertificateStoreValue": {
      "type": "string",
      "allowedValues": [
        "My"
      ],
      "defaultValue": "My",
      "metadata": {
        "description": "The store name where the cert will be deployed in the virtual machine"
      }
    }
  },
  "variables": {
    "computeLocation": "[parameters('clusterLocation')]",
    "dnsName": "[parameters('clusterName')]",
    "vmStorageAccountName": "[toLower(concat(uniqueString(resourceGroup().id), '1' ))]",
    "vmName": "vm",
    "publicIPAddressName": "PublicIP-VM",
    "publicIPAddressType": "Dynamic",
    "vmStorageAccountContainerName": "vhds",
    "virtualNetworkName": "VNet",
    "addressPrefix": "10.0.0.0/16",
    "nicName": "NIC",
    "lbName": "LoadBalancer",
    "lbIPName": "PublicIP-LB-FE",
    "availSetName": "AvailabilitySet",
    "maxPercentUpgradeDomainDeltaUnhealthyNodes": "100",
    "vnetID": "[resourceId('Microsoft.Network/virtualNetworks',variables('virtualNetworkName'))]",
    "overProvision": "false",
    "vmssApiVersion": "2016-03-30",
    "lbApiVersion": "2015-06-15",
    "vNetApiVersion": "2015-06-15",
    "storageApiVersion": "2016-01-01",
    "publicIPApiVersion": "2015-06-15",
    "nt0applicationStartPort": "20000",
    "nt0applicationEndPort": "30000",
    "nt0ephemeralStartPort": "49152",
    "nt0ephemeralEndPort": "65534",
    "nt0fabricTcpGatewayPort": "19000",
    "nt0fabricHttpGatewayPort": "19080",
    "subnet0Name": "Subnet-0",
    "subnet0Prefix": "10.0.0.0/24",
    "subnet0Ref": "[concat(variables('vnetID'),'/subnets/',variables('subnet0Name'))]",
    "supportLogStorageAccountName": "[toLower( concat(uniqueString(resourceGroup().id),'2', 'supportlog'))]",
    "applicationDiagnosticsStorageAccountName": "[toLower( concat(uniqueString(resourceGroup().id),'3', 'servicelog'))]",
    "lbID0": "[resourceId('Microsoft.Network/loadBalancers',concat('LB','-', parameters('clusterName'),'-',variables('vmNodeType0Name')))]",
    "lbIPConfig0": "[concat(variables('lbID0'),'/frontendIPConfigurations/LoadBalancerIPConfig')]",
    "lbPoolID0": "[concat(variables('lbID0'),'/backendAddressPools/LoadBalancerBEAddressPool')]",
    "lbProbeID0": "[concat(variables('lbID0'),'/probes/FabricGatewayProbe')]",
    "lbHttpProbeID0": "[concat(variables('lbID0'),'/probes/FabricHttpGatewayProbe')]",
    "lbNatPoolID0": "[concat(variables('lbID0'),'/inboundNatPools/LoadBalancerBEAddressNatPool')]",
    "vmNodeType0Name": "[toLower(concat('NT1', variables('vmName')))]",
    "vmNodeType0Size": "[parameters('nodeTypeSize')]",
    "vmStorageAccountName0": "[toLower(concat(uniqueString(resourceGroup().id), '1', '0' ))]",
    "uniqueStringArray0": [
      "[concat(variables('vmStorageAccountName0'), '0')]",
      "[concat(variables('vmStorageAccountName0'), '1')]",
      "[concat(variables('vmStorageAccountName0'), '2')]",
      "[concat(variables('vmStorageAccountName0'), '3')]",
      "[concat(variables('vmStorageAccountName0'), '4')]"
    ]
  },
  "resources": [
    {
      "apiVersion": "[variables('storageApiVersion')]",
      "type": "Microsoft.Storage/storageAccounts",
      "name": "[variables('supportLogStorageAccountName')]",
      "location": "[variables('computeLocation')]",
      "dependsOn": [],
      "properties": {},
      "kind": "Storage",
      "sku": {
        "name": "[parameters('supportLogStorageAccountType')]"
      },
      "tags": {
        "resourceType": "Service Fabric",
        "clusterName": "[parameters('clusterName')]"
      }
    },
    {
      "apiVersion": "[variables('storageApiVersion')]",
      "type": "Microsoft.Storage/storageAccounts",
      "name": "[variables('applicationDiagnosticsStorageAccountName')]",
      "location": "[variables('computeLocation')]",
      "dependsOn": [],
      "properties": {},
      "kind": "Storage",
      "sku": {
        "name": "[parameters('applicationDiagnosticsStorageAccountType')]"
      },
      "tags": {
        "resourceType": "Service Fabric",
        "clusterName": "[parameters('clusterName')]"
      }
    },
    {
      "apiVersion": "[variables('vNetApiVersion')]",
      "type": "Microsoft.Network/virtualNetworks",
      "name": "[variables('virtualNetworkName')]",
      "location": "[variables('computeLocation')]",
      "properties": {
        "addressSpace": {
          "addressPrefixes": [
            "[variables('addressPrefix')]"
          ]
        },
        "subnets": [
          {
            "name": "[variables('subnet0Name')]",
            "properties": {
              "addressPrefix": "[variables('subnet0Prefix')]"
            }
          }
        ]
      },
      "tags": {
        "resourceType": "Service Fabric",
        "clusterName": "[parameters('clusterName')]"
      }
    },
    {
      "apiVersion": "[variables('publicIPApiVersion')]",
      "type": "Microsoft.Network/publicIPAddresses",
      "name": "[concat(variables('lbIPName'),'-','0')]",
      "location": "[variables('computeLocation')]",
      "properties": {
        "dnsSettings": {
          "domainNameLabel": "[variables('dnsName')]"
        },
        "publicIPAllocationMethod": "Dynamic"
      },
      "tags": {
        "resourceType": "Service Fabric",
        "clusterName": "[parameters('clusterName')]"
      }
    },
    {
      "apiVersion": "[variables('lbApiVersion')]",
      "type": "Microsoft.Network/loadBalancers",
      "name": "[concat('LB','-', parameters('clusterName'),'-',variables('vmNodeType0Name'))]",
      "location": "[variables('computeLocation')]",
      "dependsOn": [
        "[concat('Microsoft.Network/publicIPAddresses/',concat(variables('lbIPName'),'-','0'))]"
      ],
      "properties": {
        "frontendIPConfigurations": [
          {
            "name": "LoadBalancerIPConfig",
            "properties": {
              "publicIPAddress": {
                "id": "[resourceId('Microsoft.Network/publicIPAddresses',concat(variables('lbIPName'),'-','0'))]"
              }
            }
          }
        ],
        "backendAddressPools": [
          {
            "name": "LoadBalancerBEAddressPool",
            "properties": {}
          }
        ],
        "loadBalancingRules": [
          {
            "name": "LBRule",
            "properties": {
              "backendAddressPool": {
                "id": "[variables('lbPoolID0')]"
              },
              "backendPort": "[variables('nt0fabricTcpGatewayPort')]",
              "enableFloatingIP": "false",
              "frontendIPConfiguration": {
                "id": "[variables('lbIPConfig0')]"
              },
              "frontendPort": "[variables('nt0fabricTcpGatewayPort')]",
              "idleTimeoutInMinutes": "5",
              "probe": {
                "id": "[variables('lbProbeID0')]"
              },
              "protocol": "tcp"
            }
          },
          {
            "name": "LBHttpRule",
            "properties": {
              "backendAddressPool": {
                "id": "[variables('lbPoolID0')]"
              },
              "backendPort": "[variables('nt0fabricHttpGatewayPort')]",
              "enableFloatingIP": "false",
              "frontendIPConfiguration": {
                "id": "[variables('lbIPConfig0')]"
              },
              "frontendPort": "[variables('nt0fabricHttpGatewayPort')]",
              "idleTimeoutInMinutes": "5",
              "probe": {
                "id": "[variables('lbHttpProbeID0')]"
              },
              "protocol": "tcp"
            }
          },
          {
            "name": "AppPortLBRule1",
            "properties": {
              "backendAddressPool": {
                "id": "[variables('lbPoolID0')]"
              },
              "backendPort": "[parameters('loadBalancedAppPort1')]",
              "enableFloatingIP": "false",
              "frontendIPConfiguration": {
                "id": "[variables('lbIPConfig0')]"
              },
              "frontendPort": "[parameters('loadBalancedAppPort1')]",
              "idleTimeoutInMinutes": "5",
              "probe": {
                "id": "[concat(variables('lbID0'),'/probes/AppPortProbe1')]"
              },
              "protocol": "tcp"
            }
          },
          {
            "name": "AppPortLBRule2",
            "properties": {
              "backendAddressPool": {
                "id": "[variables('lbPoolID0')]"
              },
              "backendPort": "[parameters('loadBalancedAppPort2')]",
              "enableFloatingIP": "false",
              "frontendIPConfiguration": {
                "id": "[variables('lbIPConfig0')]"
              },
              "frontendPort": "[parameters('loadBalancedAppPort2')]",
              "idleTimeoutInMinutes": "5",
              "probe": {
                "id": "[concat(variables('lbID0'),'/probes/AppPortProbe2')]"
              },
              "protocol": "tcp"
            }
          },
        ],
        "probes": [
          {
            "name": "FabricGatewayProbe",
            "properties": {
              "intervalInSeconds": 5,
              "numberOfProbes": 2,
              "port": "[variables('nt0fabricTcpGatewayPort')]",
              "protocol": "tcp"
            }
          },
          {
            "name": "FabricHttpGatewayProbe",
            "properties": {
              "intervalInSeconds": 5,
              "numberOfProbes": 2,
              "port": "[variables('nt0fabricHttpGatewayPort')]",
              "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('lbIPConfig0')]"
              },
              "frontendPortRangeEnd": "4500",
              "frontendPortRangeStart": "3389",
              "protocol": "tcp"
            }
          }
        ]
      },
      "tags": {
        "resourceType": "Service Fabric",
        "clusterName": "[parameters('clusterName')]"
      }
    },
    {
      "apiVersion": "[variables('storageApiVersion')]",
      "type": "Microsoft.Storage/storageAccounts",
      "name": "[variables('uniqueStringArray0')[copyIndex()]]",
      "location": "[variables('computeLocation')]",
      "dependsOn": [],
      "properties": {},
      "copy": {
        "name": "storageLoop",
        "count": 5
      },
      "kind": "Storage",
      "sku": {
        "name": "[parameters('storageAccountType')]"
      },
      "tags": {
        "resourceType": "Service Fabric",
        "clusterName": "[parameters('clusterName')]"
      }
    },
    {
      "apiVersion": "[variables('vmssApiVersion')]",
      "type": "Microsoft.Compute/virtualMachineScaleSets",
      "name": "[variables('vmNodeType0Name')]",
      "location": "[variables('computeLocation')]",
      "dependsOn": [
        "[concat('Microsoft.Network/virtualNetworks/', variables('virtualNetworkName'))]",
        "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[0])]",
        "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[1])]",
        "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[2])]",
        "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[3])]",
        "[concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[4])]",
        "[concat('Microsoft.Network/loadBalancers/', concat('LB','-', parameters('clusterName'),'-',variables('vmNodeType0Name')))]",
        "[concat('Microsoft.Storage/storageAccounts/', variables('supportLogStorageAccountName'))]",
        "[concat('Microsoft.Storage/storageAccounts/', variables('applicationDiagnosticsStorageAccountName'))]"
      ],
      "properties": {
        "overprovision": "[variables('overProvision')]",
        "upgradePolicy": {
          "mode": "Automatic"
        },
        "virtualMachineProfile": {
          "extensionProfile": {
            "extensions": [
              {
                "name": "[concat('ServiceFabricNodeVmExt','_vmNodeType0Name')]",
                "properties": {
                  "type": "ServiceFabricNode",
                  "autoUpgradeMinorVersion": false,
                  "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('vmNodeType0Name')]",
                    "dataPath": "D:\\\\SvcFab",
                    "durabilityLevel": "Bronze",
                    "nicPrefixOverride": "10.0.0",
                    "certificate": {
							"thumbprint": "[parameters('clusterCertificateThumbprint')]",
							"x509StoreName": "[parameters('clusterCertificateStoreValue')]"
					}	
                  },
                  "typeHandlerVersion": "1.0"
                }
              },
              {
                "name": "[concat('VMDiagnosticsVmExt','_vmNodeType0Name')]",
                "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.windows.net/"
                  },
                  "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"
                }
              }
            ]
          },
          "networkProfile": {
            "networkInterfaceConfigurations": [
              {
                "name": "[concat(variables('nicName'), '-0')]",
                "properties": {
                  "ipConfigurations": [
                    {
                      "name": "[concat(variables('nicName'),'-',0)]",
                      "properties": {
                        "loadBalancerBackendAddressPools": [
                          {
                            "id": "[variables('lbPoolID0')]"
                          }
                        ],
                        "loadBalancerInboundNatPools": [
                          {
                            "id": "[variables('lbNatPoolID0')]"
                          }
                        ],
                        "subnet": {
                          "id": "[variables('subnet0Ref')]"
                        }
                      }
                    }
                  ],
                  "primary": true
                }
              }
            ]
          },
          "osProfile": {
            "adminPassword": "[parameters('adminPassword')]",
            "adminUsername": "[parameters('adminUsername')]",
            "computernamePrefix": "[variables('vmNodeType0Name')]",
            "secrets": [
              {
                "sourceVault": {
                  "id": "[parameters('sourceVaultValue')]"
                },
                "vaultCertificates": [                  
				  {
					"certificateStore": "[parameters('clusterCertificateStorevalue')]",
					"certificateUrl": "[parameters('clusterCertificateUrlValue')]"
				  }
                ]
              }
            ]
          },
          "storageProfile": {
            "imageReference": {
              "publisher": "[parameters('vmImagePublisher')]",
              "offer": "[parameters('vmImageOffer')]",
              "sku": "[parameters('vmImageSku')]",
              "version": "[parameters('vmImageVersion')]"
            },
            "osDisk": {
              "vhdContainers": [
                "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[0]), variables('storageApiVersion')).primaryEndpoints.blob, variables('vmStorageAccountContainerName'))]",
                "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[1]), variables('storageApiVersion')).primaryEndpoints.blob, variables('vmStorageAccountContainerName'))]",
                "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[2]), variables('storageApiVersion')).primaryEndpoints.blob, variables('vmStorageAccountContainerName'))]",
                "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[3]), variables('storageApiVersion')).primaryEndpoints.blob, variables('vmStorageAccountContainerName'))]",
                "[concat(reference(concat('Microsoft.Storage/storageAccounts/', variables('uniqueStringArray0')[4]), variables('storageApiVersion')).primaryEndpoints.blob, variables('vmStorageAccountContainerName'))]"
              ],
              "name": "vmssosdisk",
              "caching": "ReadOnly",
              "createOption": "FromImage"
            }
          }
        }
      },
      "sku": {
        "name": "[variables('vmNodeType0Size')]",
        "capacity": "[parameters('nt0InstanceCount')]",
        "tier": "Standard"
      },
      "tags": {
        "resourceType": "Service Fabric",
        "clusterName": "[parameters('clusterName')]"
      }
    },
    {
      "apiVersion": "2016-09-01",
      "type": "Microsoft.ServiceFabric/clusters",
      "name": "[parameters('clusterName')]",
      "location": "[parameters('clusterLocation')]",
      "dependsOn": [
        "[concat('Microsoft.Storage/storageAccounts/', variables('supportLogStorageAccountName'))]"
      ],
      "properties": {
        "certificate": {
				"thumbprint": "[parameters('clusterCertificateThumbprint')]",
				"x509StoreName": "[parameters('clusterCertificateStoreValue')]"
		},		
        "clientCertificateCommonNames": [],
        "clientCertificateThumbprints": [],
        "clusterState": "Default",
        "diagnosticsStorageAccountConfig": {
          "blobEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', variables('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.blob]",
          "protectedAccountKeyName": "StorageAccountKey1",
          "queueEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', variables('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.queue]",
          "storageAccountName": "[variables('supportLogStorageAccountName')]",
          "tableEndpoint": "[reference(concat('Microsoft.Storage/storageAccounts/', variables('supportLogStorageAccountName')), variables('storageApiVersion')).primaryEndpoints.table]"
        },
        "fabricSettings": [
          {
            "parameters": [
              {
                "name": "ClusterProtectionLevel",
                "value": "[parameters('clusterProtectionLevel')]"
              }
            ],
            "name": "Security"
          }
        ],
        "managementEndpoint": "[concat('https://',reference(concat(variables('lbIPName'),'-','0')).dnsSettings.fqdn,':',variables('nt0fabricHttpGatewayPort'))]",
        "nodeTypes": [
          {
            "name": "[variables('vmNodeType0Name')]",
            "applicationPorts": {
              "endPort": "[variables('nt0applicationEndPort')]",
              "startPort": "[variables('nt0applicationStartPort')]"
            },
            "clientConnectionEndpointPort": "[variables('nt0fabricTcpGatewayPort')]",
            "durabilityLevel": "Bronze",
            "ephemeralPorts": {
              "endPort": "[variables('nt0ephemeralEndPort')]",
              "startPort": "[variables('nt0ephemeralStartPort')]"
            },
            "httpGatewayEndpointPort": "[variables('nt0fabricHttpGatewayPort')]",
            "isPrimary": true,
            "vmInstanceCount": "[parameters('nt0InstanceCount')]"
          }
        ],
        "provisioningState": "Default",
        "reliabilityLevel": "[parameters('nodeTypeReliabilityLevel')]",
        "upgradeMode": "Automatic",
        "vmImage": "Windows"
      },
      "tags": {
        "resourceType": "Service Fabric",
        "clusterName": "[parameters('clusterName')]"
      }
    }
  ],
  "outputs": {
    "clusterProperties": {
      "value": "[reference(parameters('clusterName'))]",
      "type": "object"
    }
  }
}

Create the Service Fabric Cluster

First you can test the deployment templates by issuing the test command, which if is OK prints no output.

$ResourceGroup = "sf-cluster"
$TemplateFilePath = "azuredeploy.json"
$TemplateParameterFilePath = "azuredeploy.parameters.json"
Test-AzureRmResourceGroupDeployment -ResourceGroupName $ResouceGroup -TemplateFile $TemplateFilePath -TemplateParameterFile $TemplateParameterFilePath

If everything looks good, then carry out the actual deployment

 New-AzureRmResourceGroupDeployment -ResourceGroupName $ResourceGroup -TemplateFile $TemplateFilePath -TemplateParameterFile $TemplateParameterFilePath

The deployment should take less than 30 minutess.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment