You can deploy a Service Fabric application using an ARM templat with a number very different mechanisms, whichever you’d like:
- PowerShell
- the CLI
- the Portal
But first you need the actual ARM template. Here’s an example of an application consisting of one stateless service (the frontend) and one stateful service (the backend):
{
"$schema": "http://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"type": "string",
"defaultValue": "[resourceGroup().location]",
"metadata": {
"description": "The Azure region where the cluster is located."
}
},
"clusterName": {
"type": "string",
"metadata": {
"description": "Name of your cluster - Between 3 and 23 characters. Letters and numbers only."
}
},
"appPackageUrl": {
"type": "string",
"metadata": {
"description": "The URL to the application package sfpkg file."
}
},
"applicationName": {
"type": "string",
"defaultValue": "MyApplication",
"metadata": {
"description": "The application name."
}
},
"applicationTypeName": {
"type": "string",
"defaultValue": "MyApplicationType",
"metadata": {
"description": "The application type name."
}
},
"applicationTypeVersion": {
"type": "string",
"metadata": {
"description": "The application type version."
}
},
"applicationParameters": {
"type": "object",
"metadata": {
"description": "Application parameters override to be applied when creating or upgrading an application."
},
"defaultValue": {
"MyStatelessService_PlacementConstraints": "[parameters('MyStatelessService_PlacementConstraints')]",
"MyStatelessService_InstanceCount": "[parameters('MyStatelessService_InstanceCount')]",
"MyStatefulService_PlacementConstraints": "[parameters('MyStatefulService_PlacementConstraints')]",
"MyStatefulService_TargetReplicaSetSize": "[parameters('MyStatefulService_TargetReplicaSetSize')]",
"MyStatefulService_MinReplicaSetSize": "[parameters('MyStatefulService_MinReplicaSetSize')]",
"MyStatefulService_PartitionCount": "[parameters('MyStatefulService_PartitionCount')]"
}
},
"MyStatelessService_PlacementConstraints": {
"type": "string"
},
"MyStatelessService_InstanceCount": {
"type": "int",
"defaultValue": -1
},
"MyStatefulService_PlacementConstraints": {
"type": "string"
},
"MyStatefulService_TargetReplicaSetSize": {
"type": "int"
},
"MyStatefulService_MinReplicaSetSize": {
"type": "int"
},
"MyStatefulService_PartitionCount": {
"type": "int"
}
},
"variables": {
"sfApiVersion": "2021-06-01"
},
"resources": [
{
"name": "[format('{0}/{1}', parameters('clusterName'), parameters('applicationTypeName'))]",
"apiVersion": "[variables('sfApiVersion')]",
"type": "Microsoft.ServiceFabric/clusters/applicationTypes",
"location": "[parameters('location')]",
"properties": {
},
"dependsOn": []
},
{
"name": "[format('{0}/{1}/{2}', parameters('clusterName'), parameters('applicationTypeName'), parameters('applicationTypeVersion'))]",
"apiVersion": "[variables('sfApiVersion')]",
"type": "Microsoft.ServiceFabric/clusters/applicationTypes/versions",
"location": "[parameters('location')]",
"properties": {
"appPackageUrl": "[parameters('appPackageUrl')]"
},
"dependsOn": [
"[concat('Microsoft.ServiceFabric/clusters/', parameters('clusterName'), '/applicationTypes/', parameters('applicationTypeName'))]"
]
},
{
"name": "[format('{0}/{1}', parameters('clusterName'), parameters('applicationName'))]",
"apiVersion": "[variables('sfApiVersion')]",
"type": "Microsoft.ServiceFabric/clusters/applications",
"location": "[parameters('location')]",
"properties": {
"typeName": "[parameters('applicationTypeName')]",
"typeVersion": "[parameters('applicationTypeVersion')]",
"parameters": "[parameters('applicationParameters')]",
"upgradePolicy": {
"upgradeReplicaSetCheckTimeout": "01:00:00.0",
"forceRestart": true,
"rollingUpgradeMonitoringPolicy": {
"healthCheckWaitDuration": "00:02:00.0",
"healthCheckStableDuration": "00:05:00.0",
"healthCheckRetryTimeout": "00:10:00.0",
"upgradeTimeout": "01:00:00.0",
"upgradeDomainTimeout": "00:20:00.0"
},
"applicationHealthPolicy": {
"considerWarningAsError": false,
"maxPercentUnhealthyDeployedApplications": 0,
"defaultServiceTypeHealthPolicy": {
"maxPercentUnhealthyServices": 0,
"maxPercentUnhealthyPartitionsPerService": 0,
"maxPercentUnhealthyReplicasPerPartition": 0
}
}
}
},
"dependsOn": [
"[concat('Microsoft.ServiceFabric/clusters/', parameters('clusterName'), '/applicationTypes/', parameters('applicationTypeName'), '/versions/', parameters('applicationTypeVersion'))]"
]
},
{
"name": "[format('{0}/{1}/{1}~{2}', parameters('clusterName'), parameters('applicationName'), 'MyStatelessService')]",
"apiVersion": "[variables('sfApiVersion')]",
"type": "Microsoft.ServiceFabric/clusters/applications/services",
"location": "[parameters('location')]",
"properties": {
"serviceKind": "Stateless",
"correlationScheme": [],
"serviceLoadMetrics": [],
"servicePlacementPolicies": [],
"serviceTypeName": "MyStatelessServiceType",
"placementConstraints": "[parameters('MyStatelessService_PlacementConstraints')]",
"instanceCount": "[parameters('MyStatelessService_InstanceCount')]",
"partitionDescription": {
"partitionScheme": "Singleton"
}
},
"dependsOn": [
"[concat('Microsoft.ServiceFabric/clusters/', parameters('clusterName'), '/applications/', parameters('applicationName'))]"
]
},
{
"name": "[format('{0}/{1}/{1}~{2}', parameters('clusterName'), parameters('applicationName'), 'MyStatefulService')]",
"apiVersion": "[variables('sfApiVersion')]",
"type": "Microsoft.ServiceFabric/clusters/applications/services",
"location": "[parameters('location')]",
"properties": {
"serviceKind": "Stateful",
"serviceTypeName": "MyStatefulServiceType",
"placementConstraints": "[parameters('MyStatefulService_PlacementConstraints')]",
"hasPersistedState": true,
"defaultMoveCost": "Zero",
"replicaRestartWaitDuration": "00:01:00.0",
"quorumLossWaitDuration": "00:02:00.0",
"standByReplicaKeepDuration": "00:00:30.0",
"targetReplicaSetSize": "[parameters('MyStatefulService_TargetReplicaSetSize')]",
"minReplicaSetSize": "[parameters('MyStatefulService_MinReplicaSetSize')]",
"partitionDescription": {
"partitionScheme": "UniformInt64Range",
"count": "[parameters('MyStatefulService_PartitionCount')]",
"lowKey": "-9223372036854775808",
"highKey": "9223372036854775807"
}
},
"dependsOn": [
"[concat('Microsoft.ServiceFabric/clusters/', parameters('clusterName'), '/applications/', parameters('applicationName'))]"
]
}
]
}
Note that there is a number of different ways to get the latest API version for Service Fabric applications, such as:
Happy deployment!
Can you provide any examples for the “applicationParameters” parameter. I’m trying to get this working with the Service Fabric Patch Orchestration Application, but having no luck.
hi, sure. here you go:
Thank you, that did the trick.
You’re welcome .Feel free to follow up if run into any other issues.
which URl I need to provide as there is no such file .sfpkg in my application package.
Your build has to produce a pkg folder first. Then a sfpkg, it’s just a zip archive of the pkg folder. Then you upload it to a blob storage, and preferable generate a short-living SAS token. And that’s your URI.
Thank You:)
You’re welcome. Happy to help. Don’t hesitate to ask follow-up questions.
why do we need to zip pkg folder to get Application Package URL,
Can we directly provide path of the pkg folder? or how can we get the .sfpkg zip folder(I am not able to get the required URL, I did the same that you mentioned,but didn’t work for me).
That’s how ARM works: all additional to the template itself resources must be available from an online location. Such as linked templates, or a package to be deployed.
Service Fabric basically supports two ways to deploy an application:
– Connect to cluster management endpoint using PowerShell (the old way and the new way) or C# (using the new HTTP client). This accepts a file on the disk or a URL/SAS
– ARM. This accepts only a URL/SAS
Ideally ARM would have uploaded your package to a hidden blob storage transparently for you. But would this would complicate the deployment process and also cost money to Microsoft so instead this burden is unfortunately on the user.
How to create sfpkg you can find in the docs.
Thanks you 🙂 Works fine now.
Can you provide an example of supplying EnvironmentOverrides to services?
Do you mean this kind of overrides?
Yes, thanks!
And more generally, how does ServiceManifestImport in ApplicationManifest translate to the ARM json template?
For example:
We’re parsing XML and generating JSON manually, haven’t found any tool to do that. Only model classes from a DLL shipped within the SF NuGet package.
I have generated several application parameters XML files which I use to set environment variable values in service manifest. When deploying through visual studio I can choose which application parameter file to use, how can I set that here on an ARM template deployment?
I see that on applicationParameters you can provide specific values, what would be the process to specify a specific XML application parameter file?
Basically, you can’t do that. XML files with application parameters play no role in deployment using ARM. You specify them inside template or template parameters (preferably) and that’s it. Only Visual Studio uses those files during local deployment, the PowerShell script which is shipped alongside the template parses them.
XML files for application and services manifest are still used, though. But they come within SFPKG which you have to produce either way.
So, you end up having two options:
Generate JSON files based on XML files
Keep application parameters for local cluster in XML and use them from VS, and in JSON for cloud-based environments.
Oh I get it now, I shall generate the JSON template param files based on those XML files, and on deployment of the ARM template I specify the correct JSON param file to use.
Thanks!
where does the JSON reside? are you copying the contents in main arm template or are you providing the path to the json?
Hey, sorry, just saw your comment. Do you still have this question?