Build status | License |
---|---|
Task is to create 3 Azure VM images for legacy application installed and configured by Ansible
- Must be placed in pre-defined Azure VNet's Subnet (instead of temporary VNet and Subnet created by Packer by default)
- Must have Private IP only (by default Packer creates Public IPs)
- Must be set by Ansible (for demo purposes Ansible creates
C:\build_config.txt
) using variables from:
var1
from Azure DevOps Variable groupansible-build-common
as regular variablevar2
from Azure DevOps Variable groupansible-build-common
as secret variablevar3
from Azure DevOps Variable groupansible-build-vm*
as regular variablevar4
from Azure DevOps Variable groupansible-build-vm*
as secret variable
- Must be placed in pre-defined Azure VNet's Subnet
- Must have Private IP only
- Must be set by Ansible (for demo purposes Ansible creates
C:\deploy_config.txt
) using variables from:
var1
from Azure DevOps Variable groupansible-deploy-common
as regular variablevar2
from Azure DevOps Variable groupansible-deploy-common
as secret variablevar3
from Azure DevOps Variable groupansible-deploy-vm*
as regular variablevar4
from Azure DevOps Variable groupansible-deploy-vm*
as secret variablevar5
for VM2 and VM3 only: IP address of VM1 from Azure DevOps pipelinevar6
for VM3 only: IP address of VM2 from Azure DevOps pipeline
As you might noticed above ansible-build-common
and ansible-deploy-common
have the same variable names as required by legacy app
..and all VMs have the same variable names in ansible-deploy-vm1
, ansible-deploy-vm2
and ansible-deploy-vm3
This issue is solved by linking Azure DevOps Variable groups to specific stages and jobs in pipeline instead of the whole pipeline's level
Solution is to use "Azure Active Directory Service Principal" which is less safe and convenient than Azure DevOps Service connection
https://stackoverflow.com/questions/59599834/packers-ansible-connection-plugin-fails-for-windows
https://stackoverflow.com/questions/59864732/packer-dedicated-provisioners-for-builders
https://stackoverflow.com/questions/59864317/packer-azure-arm-fails-when-running-in-parallel
https://stackoverflow.com/questions/59990155/packer-vs-vm-on-azure-timeout-waiting-for-winrm
Solution is to use Azure CLI to replace what Packer does, e.g. CReate VM, Setup WinRM, Run Ansible, Capture image, Terminate tmp resources
Pipeline supports Pull requests verification (on Pull request to master
branch) and VM image build and deploy (on commit to master
branch)
Pull request verification (PRV) builds and deploys image to temporary environment:
If PRV verification is successful, code snapshot is marked as valid for merging and tmp environment is deleted
If PRV verification failed code snapshot is marked as invalid and tmp environment is not deleted for manual investigation
Azure DevOps agent must have access to the virtual network that is used for VM image build
Azure DevOps agents are executed in Docker kagarlickij/packer-ansible-azure-docker-runtime:3.1.0 runtime with preinstalled Packer, Ansible, Azure CLI and necessary Python packages
Azure DevOps agents can be started on VM on system startup: @reboot /root/ados-agents-start.sh
in crontab -e
ados-agents-start.sh
script:
#!/bin/bash
for run in {1..5}
do
docker run -d -e VSTS_ACCOUNT='kagarlickij' -e VSTS_POOL='Self-Hosted-Containers' -e VSTS_TOKEN='a***q' kagarlickij/packer-ansible-azure-docker-runtime:3.1.0 > /dev/null 2>&1
done
Pipeline has some repeating steps which are moved to ./templates
to avoid code duplication
Templates are not plugins so some pieces (e.g network settings) are "hardcoded"
Template types are Job (for deploy) and Step (for all other) not because of the most suitable kind but because templates can not be used as dependency for other jobs/stages/etc
Environment in ADOS Pipelines will be created automatically by Pipeline
To Set Deploy approval open Approvals and checks
params of Environment and add Approval
Deploy notifications don't work in ADOS yet
Name | Value | Type | Comment |
---|---|---|---|
azureSubscription | Pay-As-You-Go (b31bc8ae-8938-41f1-b0b2-f707d811d596) |
Regular | Subscription Name under which the build will be performed |
azureSubscriptionId | b31bc8ae-8938-41f1-b0b2-f707d811d596 |
Regular | azure_subscription_id Subscription Id under which the build will be performed |
Name | Value | Type | Comment |
---|---|---|---|
environment | sbx |
Regular | Tags are applied to every resource deployed, i.e. Resource Group, VM, NIC, etc. |
project | ere |
Regular | Tags are applied to every resource deployed, i.e. Resource Group, VM, NIC, etc. |
Name | Value | Type | Comment |
---|---|---|---|
vmRegion | East US |
Regular | Azure Region used for build, deploy and prv; However different regions can be used for different activities |
vmSourceImage | Win2016Datacenter |
Regular | Azure Image to be used a source; Solution is tested with both Windows 2016 and Windows 2019 |
vmBuildVnetName | vm-build-vnet |
Regular | Name of Azure Virtual Network used by build activities; However all activities can happen in the same VNet |
vmBuildVnetResourceGroupName | vm-build-vnet-rg |
Regular | Name of the Azure Resource Group that hosts Azure Virtual Network used by build activities |
vmBuildVnetSubnetName | vm-build-subnet1 |
Regular | Name of the Subnet used by build activities; Obviously must belong to vmBuildVnetName |
vmBuildPrvVnetSubnetName | vm-build-subnet2 |
Regular | Name of the Subnet used by prv activities; Obviously must belong to vmBuildVnetName |
vmImagesResourceGroupName | vm-images-rg |
Regular | Name of the Azure Resource Group that hosts created VM images |
vmVnetName | vm-vnet |
Regular | Name of Azure Virtual Network used to host deployed VMs |
vmVnetResourceGroupName | vm-vnet-rg |
Regular | Name of the Azure Resource Group that hosts Azure Virtual Network used to host deployed VMs |
vmVnetSubnetName | vm-subnet1 |
Regular | Name of the Subnet used to host deployed VMs; Obviously must belong to vmVnetName |
vmResourceGroupName | vm-rg |
Regular | Name of the Azure Resource Group that hosts deployed VMs |
vm1BuildResourceGroupName | vm1-build-rg |
Regular | Name of the Azure Resource Group that hosts temporary VM used for Image creation; This one is automatically created/deleted by pipeline |
vm1ImageName | vm1-image |
Regular | Name of the Azure Image for VM1 |
vm1KeyVaultName | vm1-kv |
Regular | Name of the Azure KeyVault used to encrypt VM1 |
vm1Name | vm1 |
Regular | Name of the VM1 |
vm1Size | Standard_DS2_v2 |
Regular | Size of the VM1 |
vm2BuildResourceGroupName | vm2-build-rg |
Regular | Name of the Azure Resource Group that hosts temporary VM used for Image creation; This one is automatically created/deleted by pipeline |
vm2ImageName | vm2-image |
Regular | Name of the Azure Image for VM2 |
vm2KeyVaultName | vm2-kv |
Regular | Name of the Azure KeyVault used to encrypt VM2 |
vm2Name | vm2 |
Regular | Name of the VM2 |
vm2Size | Standard_DS2_v2 |
Regular | Size of the VM2 |
vm3BuildResourceGroupName | vm3-build-rg |
Regular | Name of the Azure Resource Group that hosts temporary VM used for Image creation; This one is automatically created/deleted by pipeline |
vm3ImageName | vm3-image |
Regular | Name of the Azure Image for VM3 |
vm3KeyVaultName | vm3-kv |
Regular | Name of the Azure KeyVault used to encrypt VM3 |
vm3Name | vm3 |
Regular | Name of the VM3 |
vm3Size | Standard_DS2_v2 |
Regular | Size of the VM3 |
Name | Value | Type | Comment |
---|---|---|---|
var1 | sample-value-of-ansible-build-common-var1 |
Regular | Just a sandbox example |
var2 | ******** |
Secret | Just a sandbox example |
Name | Value | Type | Comment |
---|---|---|---|
var3 | sample-value-of-ansible-build-vm1-var3 |
Regular | Just a sandbox example |
var4 | ******** |
Secret | Just a sandbox example |
Name | Value | Type | Comment |
---|---|---|---|
var3 | sample-value-of-ansible-build-vm2-var3 |
Regular | Just a sandbox example |
var4 | ******** |
Secret | Just a sandbox example |
Name | Value | Type | Comment |
---|---|---|---|
var3 | sample-value-of-ansible-build-vm3-var3 |
Regular | Just a sandbox example |
var4 | ******** |
Secret | Just a sandbox example |
Name | Value | Type | Comment |
---|---|---|---|
var1 | sample-value-of-ansible-deploy-common-var1 |
Regular | Just a sandbox example |
var2 | ******** |
Secret | Just a sandbox example |
Name | Value | Type | Comment |
---|---|---|---|
var3 | sample-value-of-ansible-deploy-vm1-var3 |
Regular | Just a sandbox example |
var4 | ******** |
Secret | Just a sandbox example |
Name | Value | Type | Comment |
---|---|---|---|
var3 | sample-value-of-ansible-deploy-vm2-var3 |
Regular | Just a sandbox example |
var4 | ******** |
Secret | Just a sandbox example |
Name | Value | Type | Comment |
---|---|---|---|
var3 | sample-value-of-ansible-deploy-vm3-var3 |
Regular | Just a sandbox example |
var4 | ******** |
Secret | Just a sandbox example |
Name | Value | Type | Comment |
---|---|---|---|
ansibleUser | ansible |
Regular | Windows user created for Ansible |
ansibleUserPass | ******** |
Secret | Windows user password created for Ansible |