Azure vs GCP part 10: Virtual Machine - Scaling (Azure)
Tags: azure, gcp, cloud
Published: 2018-03-13 01:30:36

---
title: "Azure vs GCP part 10: Virtual Machine - Scaling (Azure)"
published: true
description: In this series, I compare Azure and GCP as C# developer
tags: azure,gcp,cloud
cover_image: https://thepracticaldev.s3.amazonaws.com/i/m57mmv4hgz9xrskaital.PNG
---

In [previous article](https://dev.to/kenakamu/azure-vs-gcp-part-9-virtual-machine-azure--29f3), I use Azure VM to host my application, as single instance.

I look into scaling options this time.

# Availability

One of the reasons why I recommend multi-instance is availability. There are two types of concerns.

- Hardware failure
- Software update

Azure offers solutions for each.

# Scale out

In addition to availability, I need to have multiple instances when I get high load. Azure offers scale out solution, as well as load balancing.

### Availability Set
One option is to use Availability Set. According to the document [here](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/tutorial-availability-sets#availability-set-overview)
> Availability Set is a logical grouping capability that you can use in Azure to ensure that the VM resources you place within it are isolated from each other when they are deployed within an Azure datacenter. 
When you put your VMs in an availability set, these VMs are split into multiple fault domain and update domain.

- Fault domain: This is for hardware failure. A hardware failure won't affect another domain.
- Update domain: This is for software update. OS reboot due to update won't happen in multiple domains at same time.

### Scale Sets
Another option is to use Scaling Set. According to the document [here](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/tutorial-create-vmss#scale-set-overview)
> A virtual machine scale sets allows you to deploy and manage a set of identical, auto-scaling virtual machines. VMs in a scale sets are distributed across logic fault and update domains in one or more placement groups. These are groups of similarly configured VMs, similar to availability sets.

### Difference
They are similar but there are differences.

- Any VMs or identical VMs
- Availability oriented or scale out oriented

Let's say, you have multiple VMs works as a set, then you may consider using availability set as you want to control how each VM sit together. On the other hand, if you simply scale out each layer, then scale sets sounds right.

### Load Balancer
Creating multiple instances with Availability Set or Scale Sets won't load balance them automatically. Azure offers Load Balancer service. According to the document [here](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/tutorial-load-balancer#azure-load-balancer-overview)
> An Azure load balancer is a Layer-4 (TCP, UDP) load balancer that provides high availability by distributing incoming traffic among healthy VMs. A load balancer health probe monitors a given port on each VM and only distributes traffic to an operational VM.

# Let's try!
There are several steps to make this work.

### Create image
When scale-out, it requires a seed image to copy from. There are multiple ways to prepare the image. I use the one I deployed in the [last article](https://dev.to/kenakamu/azure-vs-gcp-part-9-virtual-machine-azure--29f3).

1\. Go to [Azure Portal](https://portal.azure.com) and navigate to the VM you created.

2\. Click "Connect" and remote desktop in to the image.

3\. Once login, press Windows key + "R" and enter Sysprep, then run it.
![seed](https://thepracticaldev.s3.amazonaws.com/i/huzusdsz30g21z9cpirj.PNG)

4\. Generalize it with following settings. It will shutdown the OS.
![seed](https://thepracticaldev.s3.amazonaws.com/i/ysuydh8kc9ouumpk7807.PNG)

5\. Come back to Azure Portal and wait until the VM shutdown. Then click "Capture".
![seed](https://thepracticaldev.s3.amazonaws.com/i/maeqssc66hgetemhu8j1.PNG)

6\. Enter name. I specified new resource group. If you want to delete once image captured, you can check "Automatically delete..." checkbox.
![seed](https://thepracticaldev.s3.amazonaws.com/i/jbns5wn0d6y57fzesqzh.PNG)

Seed image is ready now.

# Try Availability Set
I try Availability Set first.

1\. Go to newly created Resource Group, click add and search Availability Set.
![as](https://thepracticaldev.s3.amazonaws.com/i/92q68rv1r158m0phhrje.PNG)

2\. Enter name and set values. I use default values for domains. Click "Create".
![as](https://thepracticaldev.s3.amazonaws.com/i/lv0uiygpz4u20geqdbdg.PNG)

3\. Go to seed image, and click "Create VM".
![as](https://thepracticaldev.s3.amazonaws.com/i/fsuego3qb8j7vieievv8.PNG)

4\. Enter configuration values. 
![as](https://thepracticaldev.s3.amazonaws.com/i/pjah2s3u4z46up6qm4gr.PNG)

5\. Select size in the next step. I selected "B1MS" for test.

6\. Select created "Availability Test" and change settings as you need. All the settings come from seed image. I just used the default settings.
![as](https://thepracticaldev.s3.amazonaws.com/i/je1ndkuj47lu2vk0qd4w.PNG)

7\. Click "OK" to create the image.

8\. Repeat the steps to create 2nd VM in same Availability Set. As a result, I have many resources created. This is because the seed image has them.
![as](https://thepracticaldev.s3.amazonaws.com/i/4yxbl8lolrls2i8kpvou.PNG)

9\. Go to each VM and confirm the public IP address. Access them one by one to see the application runs as expected.
![as](https://thepracticaldev.s3.amazonaws.com/i/bk86opkah429q31iu54l.PNG)
![as](https://thepracticaldev.s3.amazonaws.com/i/a4xojz6bg24oztarwlfv.PNG)

10\. Now I have two VMs up and running. Next, create load balancer. In Resource Group, click Add and find it.
![lb](https://thepracticaldev.s3.amazonaws.com/i/1vv6ss1xbh6f5cvm8iuf.PNG)

11\. Set parameters. I set public dynamic IP address for this test.
![lb](https://thepracticaldev.s3.amazonaws.com/i/ftphm1w26qzfa4gs6grg.PNG)

12\. Once load balancer created, go to the load balancer, select "Backend pools", then click "Add".
![lb](https://thepracticaldev.s3.amazonaws.com/i/s7vutddru87zzcpd19gm.PNG)

13\. Select "Availability set" to association and select the AG. Now you can add VMs in the Availability Set. Add all VMs and click "OK" to save.
![lb](https://thepracticaldev.s3.amazonaws.com/i/z5rapaodv8omln8d13fu.PNG)

14\. Next, create probe for health check. Select "Health probes" and  click "Add", then create a probe. In this case, I created port 80 probe.
![lb](https://thepracticaldev.s3.amazonaws.com/i/f3fr7y3smec8zvqtxi21.PNG)

15\. Lastly, create a rule. Select "Load balancer rules" and click "Add", then create a rule. Specify the probe just created for the rule.
![lb](https://thepracticaldev.s3.amazonaws.com/i/elulcs3hp8meb7gwvmjg.PNG)

16\. Check overview to confirm public IP address. The probe and rule are also linked. Access to the public IP via browser to confirm you can access to the app.
![lb](https://thepracticaldev.s3.amazonaws.com/i/ssko2w778awprw7yml2k.PNG)
![lb](https://thepracticaldev.s3.amazonaws.com/i/hxbn5o39cwj2c9glt1ix.PNG)

17\. I don't need the public IPs for each VM now. You can delete them if you want.

# Try Scale Sets
I try Scale Sets next.

1\. Go back to the resource group and click "Add", then find "Template Deployment" and click "Create". I need to use this to deploy custom image to scale sets.
![ss](https://thepracticaldev.s3.amazonaws.com/i/nxt50ij6nlkvazb82ut6.PNG)

2\. Click "Build your own template in the editor link. Here you need to enter a template. The code below is minimum template to create:

- Virtual Networks: myVnet, 10.0.0.0/16
- Subnet: mySubnet, 10.0.0.0/16
- virtual Machine Scale Sets: myScaleSet, 

VM for the scale sets is specified as virtualMachineProfile. It uses the seed image, start with vm, which has NIC(myNIC) connects to myVnet and size is Standard_A1.

```json
{
    "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "adminUsername": {
            "type": "String"
        },
        "adminPassword": {
            "type": "SecureString"
        }
    },
    "variables": {},
    "resources": [
        {
            "type": "Microsoft.Network/virtualNetworks",
            "name": "myVnet",
            "apiVersion": "2016-12-01",
            "location": "[resourceGroup().location]",
            "properties": {
                "addressSpace": {
                    "addressPrefixes": [
                        "10.0.0.0/16"
                    ]
                },
                "subnets": [
                    {
                        "name": "mySubnet",
                        "properties": {
                            "addressPrefix": "10.0.0.0/16"
                        }
                    }
                ]
            }
        },
        {
            "type": "Microsoft.Compute/virtualMachineScaleSets",
            "sku": {
                "name": "Standard_A1",
                "capacity": 2
            },
            "name": "myScaleSet",
            "apiVersion": "2016-04-30-preview",
            "location": "[resourceGroup().location]",
            "properties": {
                "upgradePolicy": {
                    "mode": "Manual"
                },
                "virtualMachineProfile": {
                    "storageProfile": {
                        "imageReference": {
                            "id": "[resourceId('Microsoft.Compute/images', 'vmtest1234-seed-image')]"
                        }
                    },
                    "osProfile": {
                        "computerNamePrefix": "vm",
                        "adminUsername": "[parameters('adminUsername')]",
                        "adminPassword": "[parameters('adminPassword')]"
                    },
                    "networkProfile": {
                        "networkInterfaceConfigurations": [
                            {
                                "name": "myNic",
                                "properties": {
                                    "primary": "true",
                                    "ipConfigurations": [
                                        {
                                            "name": "myIpConfig",
                                            "properties": {
                                                "subnet": {
                                                    "id": "[concat(resourceId('Microsoft.Network/virtualNetworks', 'myVnet'), '/subnets/mySubnet')]"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        ]
                    }
                }
            },
            "dependsOn": [
                "Microsoft.Network/virtualNetworks/myVnet"
            ]
        }
    ]
}
```
3\. Save the template and do deploy. Fill the parameters username and password.

4\. Wait until the deployment done. Once deploy completed, go to the resource.
![ss](https://thepracticaldev.s3.amazonaws.com/i/mz7bswje98owqfba91gu.PNG)

5\. As Scale Sets deployed, I create new load balancer.
![ss](https://thepracticaldev.s3.amazonaws.com/i/3u9ckvuvbf2j0nwmctl8.PNG)

6\. Once the load balancer created, go to backend pools and click "Add".
![ss](https://thepracticaldev.s3.amazonaws.com/i/9o8tdxlc58vqngtmr2fp.PNG)

7\. Select "Virtual machine scale sets" as association and select myScaleSet.
![ss](https://thepracticaldev.s3.amazonaws.com/i/8xmpdky4qjdexdevpl98.PNG)

8\. Create a probe and a rule same as before.
![ss](https://thepracticaldev.s3.amazonaws.com/i/yx5o3zp1gnqfxuzfsri7.PNG)

9\. Access to the application via public IP of the load balancer to confirm the application is up and running.
![ss](https://thepracticaldev.s3.amazonaws.com/i/qsbjfbbi231b87rgv1rb.PNG)

### Auto scale settings for Scale Sets
The reason why I want to use Scale Sets is to use auto-scale. Though I could set this up in the template above, I didn't. Therefore I need to configure it manually here.

1\. Go to the scale sets resource and select "Scaling".
![as](https://thepracticaldev.s3.amazonaws.com/i/y94ro63m4mjorey5mcqc.PNG)

2\. Click "Enable autoscale", then click "Add a rule".
![as](https://thepracticaldev.s3.amazonaws.com/i/vo5rn94wd3faluju8vcu.PNG)

3\. Add new rule. I specify 70% of CPU utilization for 5 minutes to increase one instance.
![as](https://thepracticaldev.s3.amazonaws.com/i/tlskcosshgc106izxhkf.PNG)

4\. Then enter "Autoscale settings name" and save. 

That's it!

# Summary
I briefly test availability and scaling feature of Azure and both works okay. The remaining task, as a developer, is to automate creating custom image, otherwise I need to keep creating image every time I have new release.

Actually it can be done from "Continuous delivery" section of the scale set. Refer to the blog at the end for further information.

In the next article, I look into GCP options

# Reference
[Windows Virtual Machines Documentation: Check out Tutorial Section](https://docs.microsoft.com/en-us/azure/virtual-machines/windows/)
[Best practices for Autoscale](https://docs.microsoft.com/en-us/azure/monitoring-and-diagnostics/insights-autoscale-best-practices)
[Deploying Applications to Azure Virtual Machine Scale Sets](https://blogs.msdn.microsoft.com/devops/2017/05/15/deploying-applications-to-azure-vm-scale-sets/)