Microsoft and OBC conducted a joint hackfest to introduce DevOps practices into delivery and support team of OBC’s ERP Software ‘BUGYO’. The DevOps practices we implemented are:

  • Continuous integration/continuous delivery
  • Infrastructure as Code/ARM/PowerShell DSC
  • Kanban collaboration
  • Azure Container Services(planed as next step)

Core team:

  • Hiroaki Kamimaeda - OBC
  • Seiji Hayashi - OBC
  • Toru Yasuda - OBC
  • Hiroyuki Yamaguchi - OBC
  • Junichi Anno - Technical Evangelist, Microsoft

Hackfest members

Customer profile

OBIC BUSINESS CONSULTANTS CO.,LTD., is one of the largest companies as a software vendor specializing in developing ERP software. It has been packaging and providing mission-critical business of small and medium-sized enterprises for 36 years since its founding. Their main product “BUGYO series” has received the No.1 rating for ERP category for the third consecutive year in Nikkei Computer’s customer satisfaction survey, and has accumulated ten times so far for the cumulative total. They have about 25% of share of the middle sized company in 2014.

Jfyi: “BUGYO” means magistrate.

Introduction

This unique case study suggests that Ops team’s change is effective for whole of process. Ops always keeps face with customers and they have to do a lot of inevitable homework from customers. The deadline for homework falling everyday is usually tomorrow or the day after tomorrow. Therefore, it is difficult for Ops to do the scheduled work as planned in advance. So Ops is always thinking reducing tasks or automated deployment. On the other hand, the schedule of the developer side is decided in advance. This may be delayed by trouble, but it will not be advanced. Developers should release software that maintains a certain quality according to the schedule and get the price. Even though the application life cycle will be one year or two years, many of them will not care if it is decided in advance.

“Changing developers” is difficult in traditional and large company. So we focused “Infrastructure Agile” first. we think that the change of Ops should have a good influence on the development side.

Background and their issues

OBC have 3 large divisions in their company, Devlopers, Sales/Marketing and Ops. Ops team is target for me at this time. Ops team in OBC have responsibilities as below,

  • Deploying their BUGYO series with VM on the Azure IaaS.
  • Doing windows update each VMs per month. They have 120 customers now.
  • Installing bug fixed program for their service. This is irregular task.
  • Regular update their service per customer per year.

Ops team have already adopted PowerShell for automation. Before introducing PowerShell automation, their lead time, from “acceptance of order” to “avairable to start using” was 1 month. Using PowerShell script they could realized cutting lead time to half.

  • Original : 2 month with physical server
  • Step1 : 1 month(after adapting VM on IaaS)
  • Step2 : 2 weeks(after adapting PowerShell automation)

Although PowerShell script could shorten their lead time, most of customers ask them to deploy within 5 days! They have to cut more half of lead time. But they didn’t have any ideas.

In addition, updating each windows server is also hard work. It takes 2-3 days for completely updating 120 customer’s environment. They are in anxirety about upcoming maintenance for 500 customers.

Value Stream Mapping

At first, we held Value Stream Mapping to understand and share correctly their issues among whole of team.

The following picture shows configuration in their VM.

Current Configuration

And following shows result of Value Strem Mapping. In this VSM, we suggested to write each step in detail, in extreme terms, in script units. Because we thought that many of the problems they had could be solved by reducing scripts.

Result of VSM

Sure enough, we were able to grasp from the VSM results that they are manually running so many scripts to create one virtual machine. Their problems are summarized below.

  • lot of scripts: They have a lot of scripts. These scripts have no relation each other. Although operator don’t have to configure server manually, they have to kick each script by manual along with their step-by-step document.
  • Each script takes too long time: Half of scripts are to setup common environment. e.g. Japanize, Windows Update and Installing ADDS/SQL Server/RDS. 1 day is consumed for this process. When I asked why they don’t make master image, they answered that “If we make master image, we have to do windows Update each time. And AD DS installed image can’t be generalize.
  • Trigger of scripts: As described above, they starts scripts manually. They don’t know how to kick scripts from out of VM.
  • Skillset of Managing Azure Resource: They don’t have skillset of Azure Resource Manager. So they just focus automation process.

Following shows summary of VSM. Sammary of VSM

There are roughly four processes in all. Total LT was 10.6 days and PT was 2.3 days. As you can see, there is a large gap between LT and PT. Originally, this divergence should be eliminated and the overall LT should be shortened. But a lot of departments are involved in Step 1 and Step 2. Therefore, I and Ops team decided to shorten the work which is purely done only by the Ops team as much as possible without putting hands on Step 1 and Step 4 this time.

  1. Order processing - Some divisions have stake, so this can’t be changed easily.
  2. Setup platform - Install OS, SQL Server, Active Directory and Remote Desktop Services. Windows Update. Setup VNET/DNS.
  3. Configuration - Configure each parameters. In this step, manual and automatic are mixed.
  4. finalize release - Some divisions have stake, so this can’t be changed easily this time.

Step1 takes 2.5 days, and 2.1 days in Step2. So “4.7 days” of lead time is fixed. Our goal is to release to customers within 5 days. The time left is only 0.3(8H * 0.3 = 2.4H) days. Will it be possible to build a VM in 0.3 days?

I think the answer is Yes.

To achieve the goal, we need to tackle two tasks.

One is “Mastering VM image”. In step2, Ops team installs every products. They are, indeed, automated using PowerShell, but it takes too much time. In the first place, this part is a common foundation, so it should not be different from customer to customer. Mastering VM image must reduce installing time simply.

The other is “Infrastructure as Code”. After VM image is fixed, Ops team can deploy VMs with VNET using ARM(Azure Resource Manager) template. Ops merely specifies the parameters(e.g. customer number, admin password etc.), and the virtual machine is deployed along with the virtual network on the cloud. , and click “deploy” button. We call this “One touch deployment”. The important thing is the incorporation of the automatic configuration function. One of their issue is “manual configuration and manualy kicking scripts”. This challenge can be solved by using PowerShell DSC(Desired State Configuration) together with ARM template.

One more thing.

As I mentioned, they have great anxiety about increasing their customers from now on because they have to do a Windows Update to the customer’s VM once a month. It takes 2-3 days for completely updating 120 customer’s environment. During this period, most Ops are working hours all night. In order to solve this problem, it is necessary to consider a thorough automation method. However, we also need to worry about urging customers to log out. I recommend them to use Azure Automation. Azure Automation is the task scheduler on Azure. PowerShell Script can be executed on it without preparing any servers.

New architecture and process

Following shows new architecture. There are 2 phases. First phase is “deployment”. In this phase, follwing steps will be done. This phase is executed by PowerShell script on Azure Automation.

  • Copy VHD file from master image to targeted storage account.
  • Deploy ARM template and setup Virtual Machine with Windows Server 2012 R2 and Virtual Network.
  • Configure ADDS, RDS, DNS and SQL Server using Azure Automation DSC. Second phase is “Management”. After first phase, VM is re-onboarded to another DSC configuration for Windows Update on a regular basis.

Deployment and Management using Azure Automation

Making master image

In applying Infrastructure as Code, it is good to create a master image. Since the new VM is created from the master image, it is unnecessary to re-install the application and setting common to each VM. Therefore, the setup time can be greatly shortened. This time, we made the following setup for the master image.

  • Japanize(Langpack, Timezone)
    1. Login VM after finished vm deployment
    2. Open Control Panel
    3. Install Japanese langpack
    4. Select ‘Japanese’ in Advanced Settings and save
    5. Set location to Japan(logoff is needed)
    6. Set system locale to Japan (reboot is needed)
    7. Copy current user profile to default account profile and system account(also reboot is needed)
    8. Set timezone to “UTC+9:00 OSAKA,SAPPORO,TOKYO”
  • Install DNS role and RSAT
  • Install ADDS role and RSAT,don’t dcpromo
  • Install RDS role and RSAT,don’t configure
  • Install SQL Server
  • Install Windows Management Framework v5 from HERE. If OS is Windows Server 2012 R2, “Win8.1AndW2K12R2-KB3134758-x64.msu” is the installer.This is required module to use PowerShell DSC. This is updated to 5.1 when Windows Update.
  • Windows Update
  • Install Other required modules for BUGYO
  • Install BUGYO

Dcpromo will be executed automatically when final phase of deployment. Windows Update also will be done at the same time. PowerShell DSC Extensions can help these tasks.

After common setup and configuration, you need to execute sysprep utility to initialize as a master image.

  1. Input “sysprep” in “Run” box and run. Then sysprep folder will open.
  2. Run sysprep.exe in the folder.
  3. Select “OOBE”, check “generalize(一般化)” and select “Shutdown(シャットダウン)”. Then click “OK”. Sysprep tool
  4. Clicking the OK button executes the generalization process and automatically shuts down after a while.
  5. When the shudwon is completed, you have to deallocate your storage. To deallocate, click “Stop” button on Azure Portal. When deallocated, you can see its status on Azure Portal as below, status
  6. From now on we need to work using PowerShell. This page describes in detail. Easy to write as follows.
    1. Login-AzureRmAccount
    2. Get-AzureRmVM to confirm VM name and resource group.
    3. If you have multiple subscription, Get-AzureRmSubscription and Select-AzureRmSubscription
    4. Stop-AzureRmVM -ResourceGroupName -Name . If you already STOP vm in previous step, you don't have to do this.
    5. Set-AzureRmVm -ResourceGroupName -Name -Generalized
    6. Get-AzureRmVM -ResourceGroupName -Name -Generalized -Status The current status will be displayed at the end of the output, so check it. ![status](/images/obc/obc-sysprep003.jpg)
    7. Save-AzureRmVMImage -ResourceGroupName -Name ` -DestinationContainerName -VHDNamePrefix ` -Path <C:\localPathOfFileName.json> This step tekes about 2 minutes.
    is simply the container name where the VHD file is saved, and the storage account URL is not necessary. The image file is stored in the same storage account as the OS disk. Its path is like as below, /system/Microsoft.Compute/Images//-osDisk.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.vhd" ![masterimage](/images/obc/obc-sysprep004.jpg)

Creation of master image is complete with this. You can see JSON file you specified in the last step. This is a ARM template you can use to deplot new VM using master image. You can customize this template as you like. Following is osDisk part of ARM template.

“storageProfile”: {
“osDisk”: {
“osType”: “Windows”,
“name”: “masterimage-osDisk.afe60002-5bf1-4609-a0be-3b32ab7d66b3.vhd”,
“createOption”: “FromImage”,
“image”: {
“uri”: “https://xxxxxxxxx.blob.core.windows.net/system/Microsoft.Compute/Images/vhds/masterimage-osDisk.xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.vhd”
},
“vhd”: {
“uri”: “https://xxxxxxxxx.blob.core.windows.net/xxxxxxxxxx/osDisk.xxxxxxx.vhd”
},
“caching”: “ReadWrite”
}
},

“FromImage” parameter means “VM is created from master image”. This parameter seems to be good for this project’s purpose. But caution is required for use. The “FromImage” parameter can only be used if the master image and the destination VM use the same storage account. If the master image and the storage account where the VM is created are different, it is first necessary to copy the VHD file to the target storage account.

difference between FromImage and Attach

<TIPS>

If VM is created using "Managed Disk", created image can be reisterd as one of Images. Once registerd, Image can be available from Azure Portal when creating new VM.

![Images](/images/obc/obc-images001.jpg)

Click "Add".

![Click Add](/images/obc/obc-images002.jpg)

In the "Create Image" page, enter necessary information on that page and click "Create".

![Click Add](/images/obc/obc-images002.jpg)

Azure Automation and source management

In this project, trigger is launching a PowerShell Script. To manage PowerShell Script and DSC Configuration, we decided to use Azure Automation and GitHub. Azure Automation can connect GitHub as a source repository.

Source Control

But unfortunately, Azure Automation does not support VSTS at the moment.

VSTS is not supported now

The method of connecting Azure Automation and GitHub is ticketed in detail at the following site.

Source control integration in Azure Automation

ARM template

Following shows the OBC`s ARM template to deploy VM from master image.

Deploy-CustomerVM.json

The point to notice in this template is that FromImage is used as the createOption of the VM.

{
“apiVersion”: “2015-06-15”,
“type”: “Microsoft.Compute/virtualMachines”,
“name”: “[variables(‘vmName’)]”,
“location”: “[variables(‘location’)]”,
“dependsOn”: [
“[concat(‘Microsoft.Network/networkInterfaces/’, variables(‘nicName’))]”
],
“tags”: {
“displayName”: “[variables(‘VMName’)]”
},
“properties”: {
“hardwareProfile”: { “vmSize”: “[variables(‘vmSize’)]” },
“osProfile”: {
“computerName”: “[variables(‘vmName’)]”,
“adminUsername”: “[parameters(‘adminUsername’)]”,
“adminPassword”: “[parameters(‘adminPassword’)]”
},
“storageProfile”: {
“osDisk”: {
“name”: “[concat(variables(‘vmName’),’-osDisk’)]”,
“osType”: “Windows”,
“caching”: “ReadWrite”,
“createOption”: “FromImage”,
“image”: {
“uri”: “[variables(‘srcOsDiskVhdName’)]”
},
“vhd”: {
“uri”: “[variables(‘osDiskVhdName’)]”
},
}
},
“networkProfile”: {
“networkInterfaces”: [
{
“id”: “[resourceId(‘Microsoft.Network/networkInterfaces’,variables(‘nicName’))]”
}
]
}
},

As mentioned above, if the storage account is different, VHD can not be used as the master image. Therefore, it is necessary to copy the OS VHD file to the storage account to be created in advance. If you use the FromImage option in the copied state, copying of the VHD file is executed again, resulting in a large waste of storage. Therefore, you should remove copied VHD file after completed deployment.

Azure Automation DSC

Azure Automation DSC is very useful platform that can be DSC pull server on the cloud. Initially, while trying to process inside the virtual machine without DSC pull server, we noticed that the structure of the script and the processing method became too complicated when we were about to try it.

To configure VMs automaticaly by Azure Automation DSC, we constructed the environment by the following procedure.

  1. Create Azure Automation Account
  2. Create Credential assets
  3. Upload DSC extention module(xActiveDirectory,xNetworking,xWindowsUpdate,xRemoteDesktopSessionHost and xSQLServer)
  4. Create DSC configuration file and upload
  5. Create DSC configuration data file
  6. Compile DSC configuration file

1. Create Azure Automation Account

  1. Open Azure Portal
  2. Click “New”, then search “Automation”
  3. Select “Automation” Select Automation
  4. Click “Create”
  5. Set Automation Account “Name”, “Subscription”, “Resource Group” and “Location”, then click “Create”

In about 5 minutes, Automation Account is created.

2. Create Credential assets

We made 2 credentials. One is Domain Admin’s credential. This is used to deploy Domain Controller. Another is user credential for logging in as a application user.

This step is described here.

3. Upload DSC extention modules

DSC extention modules must be installed DSC Pull Server. You can easily upload/install DSC extention modules to click following link on the PowerShell Gallery.

  1. Open PowerShell Gallery
  2. Find DSC extension module Find DSC extension module
  3. Click the link “Deploy to Azure Automation” Find DSC extension module
  4. Select Automation Account to install DSC extension module Find DSC extension module

Repeat the same operation for the number of Extensions.

4. Create DSC Configuration File and upload

DSC Configuration File is used to configure Server on Azure. Following is OBC’s DSC configuration file for dcpromo.

DSC-SetupADDS.ps1

Import-DscResource is used to import DSC module. If multiple versions are installed in Azure Automation, you have to specify which version is used.

Import-DscResource -ModuleName xActiveDirectory -ModuleVersion 2.16.0.0
Import-DscResource -ModuleName xNetworking -ModuleVersion 3.2.0.0
Import-DscResource -ModuleName xPendingReboot -ModuleVersion 0.3.0.0

Get-AutomationPSCredential is used to get credential which is defined as “Credential” on Azure Automation.

$DomainCreds = Get-AutomationPSCredential -Name “cloudadmin”
$UserCreds = Get-AutomationPSCredential -Name “user01”

“WindowsFeature” section is used to install role or feature. Following means “install DNS role”. You can know roll or feature name using Get-WindowsFeature cmdlet on Windows Server. You have to specify Roll or feature name in Name parameter. If you install ADDS, AD-Domain-Services is specified.

WindowsFeature DNS
{
Ensure = “Present”
Name = “DNS”
}

xDnsServerAddress is used to configure DNS Server’s address for NIC. VM on Azure by definition refers to Azure standard DNS. Therefore, when deploying Active Directory, it is necessary to change to refer to DNS for AD. 10.0.0.4 is the IP address obtained by the first VM deployed on Azure VNET. “イーサネット” IS Eathernet in Japanese. “Eathernet 2” is the name of first NIC when VM is created.

xDnsServerAddress DnsServerAddress
{
Address = ‘10.0.0.4’
InterfaceAlias = ‘イーサネット 2’
AddressFamily = ‘IPv4’
DependsOn = “[WindowsFeature]DNS”
}

xADDomain is a function provided by xActiveDirectory and is used to deploy domain controllers. Each parameters are not difficult. “DependsOn” parameter defines a dependency relation with each step. In this case, this means that this step is not executed if “Step ADDSInstall and DnsServerAddress are not completed”.

xADDomain FirstDC
{
DomainName = $DomainName
DomainAdministratorCredential = $DomainCreds
SafemodeAdministratorPassword = $DomainCreds
DatabasePath = “C:\NTDS”
LogPath = “C:\NTDS”
SysvolPath = “C:\SYSVOL”
DependsOn = “[WindowsFeature]ADDSInstall”,”[xDnsServerAddress]DnsServerAddress”
}

xWaitForADDomain finction is used to wait until domain controller construction is complete. RetryIntervalSec is an interval for checking the existence of domain controllers. RetryCount is the number of checks performed.

xWaitForADDomain DscForestWait   
{   
	DomainName = $DomainName   
	DomainUserCredential = $DomainCreds   
	RetryCount = $RetryCount   
	RetryIntervalSec = $RetryIntervalSec   
	DependsOn = "[xADDomain]FirstDC"   
}   

After create DSC Configuration file, save this file with “ps1” extension, then upload this file onto Azure DSC Configuration.

  1. Open Automation Account
  2. Click “DSC Configuration” on the Automation blade. DSC Configuration
  3. Click “Add to configuration”
  4. select configuration file and input description, then click “ok” DSC Configuration

If you want to renewal DSC configuration files, you can simply overwrite them.

6. Compile DSC configuration file

Uploaded configuration file must be compiled and make mof file. To compile, it seems that the compile button of Azure Automation can not be used. You have to create “ConfigurationData” file first, then execute Start-AzureRmAutomationDscCompilationJob cmdlet. Follows shows script to compile.

$ConfigData = @{
	AllNodes = @(
    	@{
        	NodeName = "localhost"
        	PSDscAllowPlainTextPassword = $True
	    }
	)
} 

$ResourceGroup="<Resource Group Name>"
$AccountName="<Automation Account Name>"
$ConfigurationName="CreateNewADForest"

Login-AzureRmAccount
Select-AzureRmSubscription -SubscriptionName "<Subscription Name>"
Start-AzureRmAutomationDscCompilationJob -ResourceGroupName $ResourceGroup -AutomationAccountName $AccountName -ConfigurationName $ConfigurationName -ConfigurationData $ConfigData

Tips1

When compiling, error had occured. The running command stopped because the preference variable “ErrorActionPreference” or common parameter is set to Stop: System.InvalidOperationException error processing property ‘DomainAdministratorCredential’ OF TYPE ‘xADDomain’: Converting and storing encrypted passwords as plain text is not recommended. For more information on securing credentials in MOF file, please refer to MSDN blog: http://go.microsoft.com/fwlink/?LinkId=393729 At line:62 char:9 + xADDomain

how to resolve

DSC doesn’t allow secure string password in default. “PSDscAllowPlainTextPassword = $True” can エラーを回避できる。でも本当は証明書を登録してセキュアにやるべき。

$ConfigData = @{ AllNodes = @( @{ NodeName = “localhost” PSDscAllowPlainTextPassword = $True } ) }

Tips2

No matching MSFT_DNSClientServerAddress objects found by CIM query for instances of the ROOT/StandardCimv2/MSFT_DNSClientServerAddress class on the CIM server: SELECT * FROM MSFT_DNSClientServerAddress WHERE ((InterfaceAlias LIKE ‘Ethernet’)) AND ((AddressFamily = 2)). Verify query parameters and retry. The SendConfigurationApply function did not succeed.”.” } ] } }

how to resolve

In Japanese OS, InterfaceAlias is also Japanese, ethernet is イーサネット. I think this is over transrated. And this query “InterfaceAlias LIKE ‘Ethernet’” does not work correctly because % is insufficient. This works like ‘equal’. However, it turned out that specifying % on both ends does not work well, like %Ethernet%. So we must specify that the InterfaceAlias match exactly. In Azure IaaS, the InterfaceAlias ​​of the first ethernet card seems to be “Ethernet 2(イーサネット 2)”, so it worked fine if specified.

xDnsServerAddress DnsServerAddress
{
Address = ‘127.0.0.1’
InterfaceAlias = ‘イーサネット 2’
AddressFamily = ‘IPv4’
DependsOn = “[WindowsFeature]DNS
}

Tips3

When in xWaitForADDomain step, error has occured. According to the information on the Internet, upgrading xActiveDirectory to version 2.16.0.0 will resolve this. But we couldn’t. As a result of a two-day investigation, we found that there is a problem with the credential registered with Azure Automation.

[ERROR] PowerShell DSC resource MSFT_xWaitForADDomain failed to execute Set-TargetResource functionality with error message: Domain ‘domainname.com’ NOT found after 20 attempts.

how to resolve

Add domain name before user name like \.

Script for Deployment

Advance preparation is complete. Their script for deployment is as follows. This script is saved as Azure Automation Runbook.

Deploy-VM.ps1

Login Azure Subscription You must log on to Azure subscription beforehand if you do something with resources on Azure. Azure Automation has a function to manage “RunAs account” as “Connection” in “Asset”. You can call this connection in the script and use it as credentials when logging on to the Azure subscription. Get-AutomationConnection is a cmdlet to get RunAs Connection from ‘Asset’. When we use In Add-AzureRmAccount, -Credential parameter is often used, but in this case -ServicePrincipal is used. And connection information acquired by Get-AutomationConnection is used for authentication of Runbook. Detail is described here - Authenticate Runbooks with Azure Run As account

$servicePrincipalConnection = Get-AutomationConnection -Name 'AzureRunAsConnection'  
Add-AzureRmAccount `  
   -ServicePrincipal `  
   -TenantId $servicePrincipalConnection.TenantId `  
   -ApplicationId $servicePrincipalConnection.ApplicationId `  
   -CertificateThumbprint   $servicePrincipalConnection.CertificateThumbprint   

Each variable can be centrally managed by “Azure Automation” as an “Asset” rather than writing directly into the script. Get-AutomationVariable is a cmdlet used to retrieve variables from “Asets”.

$srcStorageAccount = Get-AutomationVariable -Name 'srcStorageAccount'    
$srcStorageAccountResourceGroup = Get-AutomationVariable -Name 'srcStorageAccountResourceGroup' 
$srcStorageContainerName = Get-AutomationVariable -Name 'srcStorageContainerName'  
$srcVHD = Get-AutomationVariable -Name 'srcVHD'  

Start-AzureStorageBlobCopy is used to copy blob between different storage account.

$blob1 = Start-AzureStorageBlobCopy `  
	-SrcContainer $srcStorageContainerName `  
	-SrcBlob $srcVHD `  
	-srcContext $srcContext.Context `  
	-DestContainer $destStorageContainerName `  
	-DestBlob $destVHD `  
	-DestContext $destContext.Context -Force  

Since Start-AzureStorageBlobCopy is performed asynchronously, it is necessary to wait until uplication is completed. That is as follows. Get-AzureStorageBlobCopyState is the cmdlet to get status of progress.

$status = $blob1 | Get-AzureStorageBlobCopyState 
While($status.Status -eq "Pending")
{
	$status = $blob1 | Get-AzureStorageBlobCopyState 
	Start-Sleep 10
  	$status
}

AdminCredential is First Admins Account of Windows Server. This is saved as one of Assets. In the ARM template, administrator ID and password must be given in plain text. Password is encrypted in Asset. Therefore, it is necessary to crypto and return to the original plaintext.

$AdminCredential = Get-AutomationPSCredential -Name 'cloudadmin'  
$AdminUserName = $AdminCredential.UserName  
$AdminPassword_tmp = [System.Runtime.InteropServices.Marshal]::SecureStringToCoTaskMemUnicode($cred.password)  
$AdminPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($AdminPassword_tmp)  

The acquired parameters are stored in the hash table as follows and used as parameters of the New-AzureRmResourceGroupDeployment cmdlet.

$parameters = @{  
	    "adminUserName"=$AdminUserName  
		"adminPassword"=$AdminPassword  
		"CustomerNumber"=$customernumber                 }  
New-AzureRmResourceGroupDeployment `  
	-Name $deploymentName `  
	-ResourceGroupName $destResourceGroupName `  
	-TemplateUri $TemplateUri `  
	-TemplateParameterObject $parameters `  
	-mode Incremental    

At last, VM is registered to Azure Automation DSC as a DSC Node. After this step, DSC configuration is adopted to VM.

Register-AzureRmAutomationDscNode `  
	-AzureVMName $VMName `  
	-NodeConfigurationName CreateNewADForest.localhost `  
	-ConfigurationMode ApplyOnly `  
	-ActionAfterReboot ContinueConfiguration `  
	-ResourceGroupName $ResourceGroupName `  
	-RebootNodeIfNeeded $true `  
	-AzureVMResourceGroup $AzureVMResourceGroup `  
	-AutomationAccountName $AutomationAccountName `  
	-AllowModuleOverwrite $true  

There is another method of deploying virtual machines from the master image. Following is the way. 201-vm-custom-image-new-storage-account In this method, ScriptExtension is used in the ARM template, and the VHD file is copied during deploying ARM template.

Source versioning and quality deployment

They can share latest script among members now. But this is not guaranteed in the future. And they provision VMs using PowerShell from their own PC. This decreases quality to provisioning since each machine environment may be different. So we present as below.

  • Using VSTS for collaboration and managing tasks each other. VSTS Kanban

  • Using GitHub repository for versioning and deployment. GitHub repository

Finally

Utilizing these methods, OBC was able to realize its initial target of 0.3 days (about 3 hours) of deployment, as detailed above. As a result, the deployment time that took 10.6 days could be shortened to 5 days as planned. They are now completing automatic configuration using DSC for products other than Active Directory. Finally, they will develop their own DSC configuration module for their BUGYO application, and the application itself is also trying to correspond to DSC native. In addition, they are also working on containerization of application servers to further shorten deployment time.

Resource

Install Windows Management Framework v5
How to capture a VM image from a generalized Azure VM
Source control integration in Azure Automation
Credential assets in Azure Automation
PowerShell Gallery.
Authenticate Runbooks with Azure Run As account
201-vm-custom-image-new-storage-account