Tuesday, April 2, 2019

AZ-300: Automate deployment of Virtual Machines (VMs)

Automate deployment of Virtual Machines (VMs)
  • May include but not limited to: Modify Azure Resource Manager (ARM) template; configure location of new VMs; configure VHD template; deploy from template; save a deployment as an ARM template; deploy Windows and Linux VMs
1) Modify Azure Resource Manager (ARM) template:
What is Azure Resource Manager?
Azure Resource Manager is the deployment and management service for Azure. It provides a consistent management layer that enables you to create, update, and delete resources in your Azure subscription. You can use its access control, auditing, and tagging features to secure and organize your resources after deployment.

What are the benefits of Resource Manager?
  • You can deploy, manage, and monitor all the resources for your solution as a group, rather than handling these resources individually.
  • You can repeatedly deploy your solution throughout the development lifecycle and have confidence your resources are deployed in a consistent state.
  • You can manage your infrastructure through declarative templates rather than scripts.
  • You can define the dependencies between resources so they're deployed in the correct order.
  • You can apply access control to all services in your resource group because Role-Based Access Control (RBAC) is natively integrated into the management platform.
  • You can apply tags to resources to logically organize all the resources in your subscription.
  • You can clarify your organization's billing by viewing costs for a group of resources sharing the same tag.

What is Resource?
Resource is a manageable item that is available through Azure. Virtual machines, storage accounts, web apps, databases, and virtual networks are examples of resources.

What is Resource Group?
Resoure Group is container that holds related resources for an Azure solution. The resource group includes those resources that you want to manage as a group. You decide how to allocate resources to resource groups based on what makes the most sense for your organization.

What is Resource Provider?
Resource Provider is a service that supplies Azure resources. For example, a common resource provider is Microsoft.Compute, which supplies the virtual machine resource. Microsoft.Storage, Microsoft.KeyVault is another common resource provider.

What is Resource Manager template?
A JavaScript Object Notation (JSON) file that defines one or more resources to deploy to a resource group or subscription. The template can be used to deploy the resources consistently and repeatedly. 

What is Management scope?
Azure provides four levels of management scope: management groups, subscriptions, resource groups, and resources. You apply management settings at any of these levels of scope. The level you select determines how widely the setting is applied. Lower levels inherit settings from higher levels.

What are the factors to consider when defining your resource group?
  • All the resources in your group should share the same lifecycle. You deploy, update, and delete them together. If one resource, such as a database server, needs to exist on a different deployment cycle it should be in another resource group.
  • Each resource can only exist in one resource group.
  • You can add or remove a resource to a resource group at any time.
  • You can move a resource from one resource group to another group. For more information, see Move resources to new resource group or subscription.
  • A resource group can contain resources that are located in different regions.
  • A resource group can be used to scope access control for administrative actions.
  • A resource can interact with resources in other resource groups. This interaction is common when the two resources are related but don't share the same lifecycle (for example, web apps connecting to a database).
What is ARM Template?
With Azure Resource Manager, you can create a template (in JSON format) that defines the infrastrucutre and configuration of your Azure solution. By using a template, you can repeatedly deploy your solution throughout its lifecycle and have confidence your resources are deployed in a consistent state.

How does ARM Template is processed?
Resource Manager processes the template like any other request. It parses the template and converts its syntax into REST API operations for the appropriate resource providers. 

It converts the definition to the following REST API operation, which is sent to the Microsoft.Storage resource provider:

PUT
https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Storage/storageAccounts/mystorageaccount?api-version=2016-01-01


What are the common practices to define templates and resource groups?
How you define templates and resource groups is entirely up to you and how you want to manage your solution. 
1) For example, you can deploy your three-tier application through a single template to a single resource group.

2) Another example, on how to deploy a three-tier solution through a parent template that includes three nested templates

3) If you envision your tiers having separate lifecycles, you can deploy your three tiers to separate resource groups.

What is Virtual machine vCPU quotas?
The vCPU quotas for virtual machines and virtual machine scale sets are arranged in two tiers for each subscription, in each region. The first tier is the Total Regional vCPUs, and the second tier is the various VM size family cores such as the D-series vCPUs.  Any time a new VM is deployed the vCPUs for the VM must not exceed the vCPU quota for the VM size family or the total regional vCPU quota. If either of those quotas are exceeded, the VM deployment will not be allowed. There is also a quota for the overall number of virtual machines in the region.

What are the important 6 JSON elements in the ARM Resource Template?
1) Schema
2) ContentVersion
3) Parameters
4) Variables
5) Resources
6) Output


Note: resources have square brackets [ ], whereas others have curly braces { }.

$schema: specify the location of the JSON schema file that describes the version of the template language.
contentVersion: specify any value for this element to document significant changes in your template.
parameters: specify the values that are provided when deployment is executed to customize resource deployment.
variables: specify the values that are used as JSON fragments in the template to simplify template language expressions.
resources: specify the resource types that are deployed or updated in a resource group.
outputs: specify the values that are returned after deployment.

Provide an example template to create 3 storage accounts?
Refer the details in the Microsoft docs here

{ "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "storageAccountType": { "type": "string", "defaultValue": "Standard_LRS", "allowedValues": [ "Standard_LRS", "Standard_GRS", "Standard_ZRS", "Premium_LRS" ], "metadata": { "description": "Storage Account type" } }, "location": { "type": "string", "defaultValue": "[resourceGroup().location]", "metadata": { "description": "Location for all resources." } } }, "resources": [ { "type": "Microsoft.Storage/storageAccounts", "name": "[concat(copyIndex(),'storage', uniqueString(resourceGroup().id))]", "apiVersion": "2018-02-01", "location": "[parameters('location')]", "sku": { "name": "[parameters('storageAccountType')]" }, "kind": "Storage", "properties": {}, "copy": { "name": "storagecopy", "count": 3 } } ] }

Explain the element copy and copyIndex() function in the above example.
copy element is where you specify the iterations and variables for this loop
copyIndex() is function returns the current iteration in the loop. You use the index as the name prefix. copyIndex() is zero-based. To offset the index value, you can pass a value in the copyIndex() function. For example, copyIndex(1).

What is purpose of a dependsOn element in ARM template?
The dependsOn element enables you to define one resource as dependent on one or more resources. The resource Microsoft.Network/NetworkInterface depends on two other resources:
Microsoft.Network/publicIPAddresses
Microsoft.Network/virtualNetworks

Similarly, the resource Microsoft.Compute/virtualMachines depends on:
Microsoft.Storage/storageAccounts
Microsoft.Network/networkInterfaces

Refer the example here.

Explain the ARM template structure for VM.
Refer the template here.
"resources": [ { "apiVersion": "2016-04-30-preview", "type": "Microsoft.Compute/virtualMachines", "name": "[concat('myVM', copyindex())]", "location": "[resourceGroup().location]", "copy": { "name": "virtualMachineLoop", "count": "[parameters('numberOfInstances')]" }, "dependsOn": [ "[concat('Microsoft.Network/networkInterfaces/myNIC', copyindex())]" ], "properties": { "hardwareProfile": { "vmSize": "Standard_DS1" }, "osProfile": { "computername": "[concat('myVM', copyindex())]", "adminUsername": "[parameters('adminUsername')]", "adminPassword": "[parameters('adminPassword')]" }, "storageProfile": { "imageReference": { "publisher": "MicrosoftWindowsServer", "offer": "WindowsServer", "sku": "2012-R2-Datacenter", "version": "latest" }, "osDisk": { "name": "[concat('myOSDisk', copyindex())]", "caching": "ReadWrite", "createOption": "FromImage" }, "dataDisks": [ { "name": "[concat('myDataDisk', copyindex())]", "diskSizeGB": "100", "lun": 0, "createOption": "Empty" } ] }, "networkProfile": { "networkInterfaces": [ { "id": "[resourceId('Microsoft.Network/networkInterfaces', concat('myNIC', copyindex()))]" } ] }, "diagnosticsProfile": { "bootDiagnostics": { "enabled": "true", "storageUri": "[concat('https://', variables('storageName'), '.blob.core.windows.net')]" } } }, "resources": [ { "name": "Microsoft.Insights.VMDiagnosticsSettings", "type": "extensions", "location": "[resourceGroup().location]", "apiVersion": "2016-03-30", "dependsOn": [ "[concat('Microsoft.Compute/virtualMachines/myVM', copyindex())]" ], "properties": { "publisher": "Microsoft.Azure.Diagnostics", "type": "IaaSDiagnostics", "typeHandlerVersion": "1.5", "autoUpgradeMinorVersion": true, "settings": { "xmlCfg": "[base64(concat(variables('wadcfgxstart'), variables('wadmetricsresourceid'), concat('myVM', copyindex()), variables('wadcfgxend')))]", "storageAccount": "[variables('storageName')]" }, "protectedSettings": { "storageAccountName": "[variables('storageName')]", "storageAccountKey": "[listkeys(variables('accountid'), '2015-06-15').key1]", "storageAccountEndPoint": "https://core.windows.net" } } }, { "name": "MyCustomScriptExtension", "type": "extensions", "apiVersion": "2016-03-30", "location": "[resourceGroup().location]", "dependsOn": [ "[concat('Microsoft.Compute/virtualMachines/myVM', copyindex())]" ], "properties": { "publisher": "Microsoft.Compute", "type": "CustomScriptExtension", "typeHandlerVersion": "1.7", "autoUpgradeMinorVersion": true, "settings": { "fileUris": [ "[concat('https://', variables('storageName'), '.blob.core.windows.net/customscripts/start.ps1')]" ], "commandToExecute": "powershell.exe -ExecutionPolicy Unrestricted -File start.ps1" } } } ] } ]


Explain the important sections in VM
Note: This section covers the following topics covered in the Certification:
2) Configure location of new VMs:
3) Configure VHD template:

2) Configure location of new VMs:

"resources": [
  { 
    "apiVersion": "2016-04-30-preview", 
    "type": "Microsoft.Compute/virtualMachines", 
    "name": "[concat('myVM', copyindex())]", 
    "location": "[resourceGroup().location]",

It is possible to configure the locat

a) API Version: 
When you deploy resources using a template, you have to specify a version of the API to use

"apiVersion": "2016-04-30-preview",

b) Location: 
When you deploy resources using a template, you have to specify Azure location where this resource has to be deployed. Location can be provided as values OR it is logical to use the location from the ResourceGroup

    "location": "[resourceGroup().location]",

c) Parameters:
Parameters make it easy for you to specify values for the template when you run it.

"parameters": {
  "adminUsername": { "type": "string" },
  "adminPassword": { "type": "securestring" },
  "numberOfInstances": { "type": "int" }
}

d) Variables:
Variables make it easy for you to set up values in the template that are used repeatedly throughout it or that can change over time. 

"variables": { 
  "storageName": "mystore1",
  "accountid": "[concat('/subscriptions/', subscription().subscriptionId, 
    '/resourceGroups/', resourceGroup().name,
  '/providers/','Microsoft.Storage/storageAccounts/', variables('storageName'))]", 

e) Resource loops: - copy and copyIndex()
Copy:
When you need more than one virtual machine for your application, you can use a copy element in a template. This optional element loops through creating the number of VMs that you specified as a parameter:
"copy": {
  "name": "virtualMachineLoop",
  "count": "[parameters('numberOfInstances')]"
},

copyIndex():
the loop index is used when specifying some of the values for the resource. For example, if you entered an instance count of three, the names of the operating system disks are myOSDisk1, myOSDisk2, and myOSDisk3:

"osDisk": { 
  "name": "[concat('myOSDisk', copyindex())]",
  "caching": "ReadWrite", 
  "createOption": "FromImage" 
}

f) Dependencies
Most resources depend on other resources to work correctly. Virtual machines must be associated with a virtual network and to do that it needs a network interface. The dependsOn element is used to make sure that the network interface is ready to be used before the VMs are created:

"dependsOn": [
  "[concat('Microsoft.Network/networkInterfaces/', 'myNIC', copyindex())]"
],

g) Profiles:
Some profile are mandatory and some are optional. hardwareProfile, osProfile, storageProfile, and networkProfile elements are required, but the diagnosticsProfile is optional. 
Few profiles include:

  • size
  • name and credentials
  • disk and operating system settings
  • network interface
  • boot diagnostics
3) Configure VHD template:

h) Disks and images:

Create new virtual machines and new disks from a platform image:
When you create a VM, you must decide what operating system to use. The imageReference element is used to define the operating system of a new VM. 

"imageReference": { 
  "publisher": "MicrosoftWindowsServer", 
  "offer": "WindowsServer", 
  "sku": "2012-R2-Datacenter", 
  "version": "latest" 
},

If you want to create a Linux operating system, you might use this definition:

"imageReference": {
  "publisher": "Canonical",
  "offer": "UbuntuServer",
  "sku": "14.04.2-LTS",
  "version": "latest"
},

Defines a new managed OS disk with the caching mode set to ReadWrite and that the disk is being created from a platform image:

"osDisk": { 
  "name": "[concat('myOSDisk', copyindex())]",
  "caching": "ReadWrite", 
  "createOption": "FromImage" 
},

Create new virtual machines from a managed image

If you want to create a virtual machine from a managed image, change the imageReference element and define these disk settings:

"storageProfile": {
  "imageReference": {
    "id": "[resourceId('Microsoft.Compute/images', 'myImage')]"
  },
  "osDisk": {
    "name": "[concat('myOSDisk', copyindex())]",
    "osType": "Windows",
    "caching": "ReadWrite",
    "createOption": "FromImage"
  }
},

Attach data disks:
You can optionally add data disks to the VMs. The number of disks depends on the size of operating system disk that you use.

"dataDisks": [
  {
    "name": "[concat('myDataDisk', copyindex())]",
    "diskSizeGB": "100",
    "lun": 0,
    "caching": "ReadWrite",
    "createOption": "Empty"
  }
],

i) Extensions
Although extensions are a separate resource, they're closely tied to VMs. Extensions can be added as a child resource of the VM or as a separate resource.

{
  "name": "Microsoft.Insights.VMDiagnosticsSettings",
  "type": "extensions",
  "location": "[resourceGroup().location]",
  "apiVersion": "2016-03-30",
  "dependsOn": [
    "[concat('Microsoft.Compute/virtualMachines/myVM', copyindex())]"
  ],
  "properties": {
    "publisher": "Microsoft.Azure.Diagnostics",
    "type": "IaaSDiagnostics",
    "typeHandlerVersion": "1.5",
    "autoUpgradeMinorVersion": true,
    "settings": {
      "xmlCfg": "[base64(concat(variables('wadcfgxstart'),
      variables('wadmetricsresourceid'),
      concat('myVM', copyindex()),
      variables('wadcfgxend')))]",
      "storageAccount": "[variables('storageName')]"
    },
    "protectedSettings": {
      "storageAccountName": "[variables('storageName')]",
      "storageAccountKey": "[listkeys(variables('accountid'),
        '2015-06-15').key1]",
      "storageAccountEndPoint": "https://core.windows.net"
    }
  }
},

This extension resource uses the storageName variable and the diagnostic variables to provide values. If you want to change the data that is collected by this extension, you can add more performance counters to the wadperfcounters variable. You could also choose to put the diagnostics data into a different storage account than where the VM disks are stored.

Custom Script Extension invoking the PowerShell script:

{
  "name": "MyCustomScriptExtension",
  "type": "extensions",
  "apiVersion": "2016-03-30",
  "location": "[resourceGroup().location]",
  "dependsOn": [
    "[concat('Microsoft.Compute/virtualMachines/myVM', copyindex())]"
  ],
  "properties": {
    "publisher": "Microsoft.Compute",
    "type": "CustomScriptExtension",
    "typeHandlerVersion": "1.7",
    "autoUpgradeMinorVersion": true,
    "settings": {
      "fileUris": [
        "[concat('https://', variables('storageName'),
          '.blob.core.windows.net/customscripts/start.ps1')]"
      ],
      "commandToExecute": "powershell.exe -ExecutionPolicy Unrestricted -File start.ps1"
    }
  }
}

4) Deploy from template:

What is the command to deploy the template?
CLI:
az group deployment create --resource-group $resourceGroupName --template-file "$HOME/azuredeploy.json"

PowerShell:
New-AzResourceGroupDeployment -ResourceGroupName $resourceGroupName -TemplateFile "$HOME/azuredeploy.json"

What is purpose of Mode parameter?
-mode is an additional parameter that can be used in the above command 
(New-AzResourceGroupDeployment OR az group deployment)
It can accept values - Complete OR Incremental
In complete mode, Resource Manager deletes resources that exist in the resource group but are not specified in the template. In incremental mode, Resource Manager leaves unchanged resources that exist in the resource group but are not specified in the template.

Ex:
New-AzResourceGroupDeployment -ResourceGroupName $resourceGroupName -mode incremental -TemplateFile "$HOME/azuredeploy.json"

5) Save a deployment as an ARM template:
Explain the steps to save a deployment as ARM template.
Details are provided in this link.

6) Deploy Windows and Linux VMs
Explain the steps involved in creating an Windows VM.
Details are provided in this link

Explain the steps involved in creating an Linux VM.
Details are provided in this link

7) General:

What are the functions you can use in an Azure Resource Manager template?
a) Resource Manager provides several functions for working with arrays and objects.
  • array
  • coalesce
  • concat
  • contains
  • createArray
  • empty
  • first
  • intersection
  • json
  • last
  • length
  • min
  • max
  • range
  • skip
  • take
  • union

b) Comparison functions
Resource Manager provides several functions for making comparisons in your templates.
  • equals
  • less
  • lessOrEquals
  • greater
  • greaterOrEquals

c) Deployment value functions
Resource Manager provides the following functions for getting values from sections of the template and values related to the deployment:
  • deployment
  • parameters
  • variables

d) Logical functions
Resource Manager provides the following functions for working with logical conditions:
  • and
  • bool
  • if
  • not
  • or

e) Numeric functions
Resource Manager provides the following functions for working with integers:
  • add
  • copyIndex
  • div
  • float
  • int
  • min
  • max
  • mod
  • mul
  • sub

f) Resource functions
Resource Manager provides the following functions for getting resource values:
  • listAccountSas
  • listKeys
  • listSecrets
  • list*
  • providers
  • reference
  • resourceGroup
  • resourceId
  • subscription

g) String functions
Resource Manager provides the following functions for working with strings:
  • base64
  • base64ToJson
  • base64ToString
  • concat
  • contains
  • dataUri
  • dataUriToString
  • empty
  • endsWith
  • first
  • format
  • guid
  • indexOf
  • last
  • lastIndexOf
  • length
  • newGuid
  • padLeft
  • replace
  • skip
  • split
  • startsWith
  • string
  • substring
  • take
  • toLower
  • toUpper
  • trim
  • uniqueString
  • uri
  • uriComponent
  • uriComponentToString
  • utcNow

Explain about "Parameters" in ARM template?
With parameters, you specify which values you can input when deploying the resources. These parameter values enable you to customize the deployment by providing values that are tailored for a particular environment (such as dev, test, and production).

Available properties
The available properties for a parameter are:

"parameters": {
  "<parameter-name>" : {
    "type" : "<type-of-parameter-value>",
    "defaultValue": "<default-value-of-parameter>",
    "allowedValues": [ "<array-of-allowed-values>" ],
    "minValue": <minimum-value-for-int>,
    "maxValue": <maximum-value-for-int>,
    "minLength": <minimum-length-for-string-or-array>,
    "maxLength": <maximum-length-for-string-or-array-parameters>,
    "metadata": {
      "description": "<description-of-the parameter>" 
    }
  }
}

Example:
"parameters": {
  "storageSKU": {
    "type": "string",
    "allowedValues": [
      "Standard_LRS",
      "Standard_ZRS",
      "Standard_GRS",
      "Standard_RAGRS",
      "Premium_LRS"
    ],
    "defaultValue": "Standard_LRS",
    "metadata": {
      "description": "The type of replication to use for the storage account."
    }
  }   
}

Template functions with parameters

"parameters": {
  "siteName": {
    "type": "string",
    "defaultValue": "[concat('site', uniqueString(resourceGroup().id))]",
    "metadata": {
      "description": "The site name. To use the default value, do not specify a new value."
    }
  },
  "hostingPlanName": {
    "type": "string",
    "defaultValue": "[concat(parameters('siteName'),'-plan')]",
    "metadata": {
      "description": "The host name. To use the default value, do not specify a new value."
    }
  }
}

Objects as parameters

"parameters": {
  "VNetSettings": {
    "type": "object",
    "defaultValue": {
      "name": "VNet1",
      "location": "eastus",
      "addressPrefixes": [
        {
          "name": "firstPrefix",
          "addressPrefix": "10.0.0.0/22"
        }
      ],
      "subnets": [
        {
          "name": "firstSubnet",
          "addressPrefix": "10.0.0.0/24"
        },
        {
          "name": "secondSubnet",
          "addressPrefix": "10.0.1.0/24"
        }
      ]
    }
  }
},

Then, reference the subproperties of the parameter by using the dot operator.

"resources": [
  {
    "apiVersion": "2015-06-15",
    "type": "Microsoft.Network/virtualNetworks",
    "name": "[parameters('VNetSettings').name]",
    "location": "[parameters('VNetSettings').location]",
    "properties": {
      "addressSpace":{
        "addressPrefixes": [
          "[parameters('VNetSettings').addressPrefixes[0].addressPrefix]"
        ]
      },
      "subnets":[
        {
          "name":"[parameters('VNetSettings').subnets[0].name]",
          "properties": {
            "addressPrefix": "[parameters('VNetSettings').subnets[0].addressPrefix]"
          }
        },
        {
          "name":"[parameters('VNetSettings').subnets[1].name]",
          "properties": {
            "addressPrefix": "[parameters('VNetSettings').subnets[1].addressPrefix]"
          }
        }
      ]
    }
  }
]

Explain about "Variables" in ARM template?
In the variables section, you construct values that can be used throughout your template. You don't need to define variables, but they often simplify your template by reducing complex expressions.

Available definitions
The following example shows the available options for defining a variable:

"variables": {
  "<variable-name>": "<variable-value>",
  "<variable-name>": { 
    <variable-complex-type-value> 
  },
  "<variable-object-name>": {
    "copy": [
      {
        "name": "<name-of-array-property>",
        "count": <number-of-iterations>,
        "input": <object-or-value-to-repeat>
      }
    ]
  },
  "copy": [
    {
      "name": "<variable-array-name>",
      "count": <number-of-iterations>,
      "input": <object-or-value-to-repeat>
    }
  ]
}

Define and use a variable
The following example shows a variable definition. It creates a string value for a storage account name. It uses several template functions to get a parameter value, and concatenates it to a unique string.

"variables": {
  "storageName": "[concat(toLower(parameters('storageNamePrefix')), uniqueString(resourceGroup().id))]"
},

You use the variable when defining the resource.

"resources": [
  {
    "name": "[variables('storageName')]",
    "type": "Microsoft.Storage/storageAccounts",
    ...

Configuration variables
You can use complex JSON types to define related values for an environment.

"variables": {
  "environmentSettings": {
    "test": {
      "instanceSize": "Small",
      "instanceCount": 1
    },
    "prod": {
      "instanceSize": "Large",
      "instanceCount": 4
    }
  }
},

In parameters, you create a value that indicates which configuration values to use.

"parameters": {
  "environmentName": {
    "type": "string",
    "allowedValues": [
      "test",
      "prod"
    ]
  }
},

You retrieve the current settings with:

"[variables('environmentSettings')[parameters('environmentName')].instanceSize]"





8 comments:

  1. Thank you for explaining the AZ: 300 Architect Technologies analysis in a effective way so that it reaches us in a manner which is understandable .Keep Sharing.

    ReplyDelete
  2. Thank you for explaining the AZ: 300 Architect Technologies in a effective way so that it reaches us in a manner which is understandable .Keep Sharing.

    ReplyDelete

  3. Good Post! Thank you so much for sharing this post, it was so good to read and useful to improve my knowledge on AZ: 300 Architect Technologies, keep blogging.

    ReplyDelete
  4. Great post! Thanks for sharing this amazing post on AZ: 300 Architect Technologies, keep blogging.

    ReplyDelete
  5. This post on AZ: 300 Architect Technologies is amazing & knowledgable. Keep Sharing.

    ReplyDelete
  6. Thankyou for sharing this wonderful knowledge on AZ: 300 Architect Technologies. Keep Sharing.

    ReplyDelete
  7. Thankyou for sharing this wonderful knowledge on AZ: 300 Architect Technologies. It is so much helpful for beginners like me .Keep Sharing.

    ReplyDelete