If I understand the question, you have a scaleset that is created from a standard image. You apply the specific .Net framework. You then deploy your app.
Option 1: Simplest and Preferred - Edit app config file to use specific .Net Framework (so it works regardless of installed framework(s)). Below config will run your app under 2.0.50727 framework, regardless of patches.
<configuration>
<startup>
<supportedRuntime version="v2.0.50727"/>
</startup>
</configuration
Option 2: I think you will need to create a OS VM with the configuration you want. Then periodically create a new image from that VM with the various patches. It is possible to maintain a baseline VM and create images from a clone. In this scenario, I think you really have a "Windows Update" issue in wanting to block a specific patch. Then re-image your scaleset from the resulting image. This template creates a VMSS from a specific iamge:
{
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"location": {
"type": "string"
},
"vmssName": {
"type": "string"
},
"vmSku": {
"type": "string"
},
"adminUsername": {
"type": "string"
},
"instanceCount": {
"type": "string"
},
"singlePlacementGroup": {
"type": "string"
},
"pipName": {
"type": "string"
},
"pipLabel": {
"type": "string"
},
"skuType": {
"type": "string"
},
"ipAllocationMethod": {
"type": "string"
},
"priority": {
"type": "string"
},
"enableAcceleratedNetworking": {
"type": "string"
},
"publicIpAddressPerInstance": {
"type": "string"
},
"upgradeMode": {
"type": "string"
},
"adminPassword": {
"type": "securestring"
},
"spreadingAlgorithmPlatformFaultDomainCount": {
"type": "string"
},
"diagnosticStorageAccount": {
"type": "string"
},
//vNet
"vnetResourceGroup": {
"type": "string",
"defaultValue": "xxxxx"
},
"vnetName": {
"type": "string",
"defaultValue": "xxxxx"
},
"vnetSubnetName": {
"type": "string",
"defaultValue": "xxxxx"
},
//vm OS Image
"imageSubscription": {
"type": "string",
"defaultValue": "xxxxx-xxxx-xxxx-xxxx-xxxxx"
},
"imageResourceGroup": {
"type": "string",
"defaultValue": "xxxxx"
},
"imageName": {
"type": "string",
"defaultValue": "xxxxx_eastus_2019_11_21_18_21_29"
},
"domainName": {
"type": "string",
"defaultValue": "xxxxx.net"
},
"userName": {
"type": "string",
"defaultValue": "xxxxx",
"metadata": {
"description": "Do not use domainName here. domainName\\userName are concatenated at runtime."
}
},
"userPassword": {
"type": "securestring",
"defaultValue": "xxxxxxxxxxxxxxxxxx"
},
"ouPath": {
"type": "string",
"defaultValue": "OU=xx,DC=xxx,DC=xxxx,DC=net",
"metadata": {
"description": "Fully qualified path works."
}
},
"restart": {
"type": "string",
"defaultValue": "true",
"metadata": {
"description": "VM will restart, UNLESS account already esists in domain. This may impact a configuration sequence during deployment. This extension can remove the account when removing a machine from the domain, (according to the documentation)."
}
},
"options": {
"type": "string",
"defaultValue": "3",
"metadata": {
"description": "Extension uses NetJoinDomain Win32 API. Options is a OR mask documented in url below. ie '3' = NETSETUP_JOIN_DOMAIN & NETSETUP_ACCT_CREATE. ",
"url": "https://learn.microsoft.com/en-us/windows/win32/api/lmjoin/nf-lmjoin-netjoindomain"
}
},
"forceUpdateTag": {
"defaultValue": "[newGuid()]",
"type": "string",
"metadata": {
"description": "Forces extension to deploy every time."
}
}
},
"variables": {
"namingInfix": "[toLower(substring(concat(parameters('vmssName'), uniqueString(resourceGroup().id)), 0, 9))]",
"networkApiVersion": "2018-01-01",
"storageApiVersion": "2019-06-01",
"computeApiVersion": "2019-03-01",
"autoscaleApiVersion": "2015-04-01",
"subnetRef": "[resourceId(parameters('vnetResourceGroup'), 'Microsoft.Network/virtualNetworks/subnets', parameters('vnetName'), parameters('vnetSubnetName') )]",
"imageReferenceId": "[resourceId( parameters('imageSubscription'), parameters('imageResourceGroup'), 'Microsoft.Compute/images', parameters('imageName') )]"
},
"resources": [
{
"type": "Microsoft.Compute/virtualMachineScaleSets",
"apiVersion": "[variables('computeApiVersion')]",
"name": "[parameters('vmssName')]",
"location": "[parameters('location')]",
"dependsOn": [
],
"sku": {
"name": "[parameters('vmSku')]",
"tier": "Standard",
"capacity": "[int(parameters('instanceCount'))]"
},
"identity": {
"type": "SystemAssigned"
},
"properties": {
"overprovision": true,
"upgradePolicy": {
"mode": "[parameters('upgradeMode')]"
},
"singlePlacementGroup": "[parameters('singlePlacementGroup')]",
"virtualMachineProfile": {
"extensionProfile": {
"extensions": [
{
"type": "Microsoft.Compute/virtualMachines/extensions",
"name": "[concat(parameters('vmssName'), '_joindomain')]",
"properties": {
"publisher": "Microsoft.Compute",
"type": "JsonADDomainExtension",
"typeHandlerVersion": "1.3",
"autoUpgradeMinorVersion": true,
"forceUpdateTag": "[parameters('forceUpdateTag')]",
"settings": {
"Name": "[parameters('domainName')]",
"User": "[ concat( parameters('domainName'), '\u005c', parameters('userName') ) ]",
"OUPath": "[parameters('ouPath')]",
"Restart": "[parameters('restart')]",
"Options": "[parameters('options')]"
},
"protectedSettings": {
"Password": "[parameters('userPassword')]"
}
}
}
]
},
"storageProfile": {
"imageReference": {
"id": "[variables('imageReferenceId')]"
},
"osDisk": {
"createOption": "FromImage",
"caching": "ReadWrite"
}
},
"priority": "[parameters('priority')]",
"osProfile": {
"computerNamePrefix": "[variables('namingInfix')]",
"adminUsername": "[parameters('adminUsername')]",
"adminPassword": "[parameters('adminPassword')]"
},
"networkProfile": {
"networkInterfaceConfigurations": [
{
"name": "[concat(parameters('vmssName'), 'Nic')]",
"properties": {
"primary": true,
"enableAcceleratedNetworking": "[parameters('enableAcceleratedNetworking')]",
"ipConfigurations": [
{
"name": "[concat(parameters('vmssName'), 'IpConfig')]",
"properties": {
"subnet": {
"id": "[variables('subnetRef')]"
}
}
}
],
"dnsSettings": {
"dnsServers": [
"xx.xx.xx.xx"
]
}
}
}
]
},
"diagnosticsProfile": {
"bootDiagnostics": {
"enabled": true,
"storageUri": "[reference(parameters('diagnosticStorageAccount'), variables('storageApiVersion')).primaryEndpoints.blob]"
}
}
},
"platformFaultDomainCount": "[int(parameters('spreadingAlgorithmPlatformFaultDomainCount'))]"
}
}
]
}