Skip to main content

VNet and Virtual Machine

In this example, we'll demonstrate how to set up a simple Virtual Network (VNet) with a Virtual Machine (VM) in Azure using stackql-deploy. This setup is ideal for getting started with basic networking and compute resources on Azure.

Simple Azure VNet VM Stack

The Virtual Machine is bootstrapped with a web server that serves a simple page using the Azure Custom Script Extension.

Deploying the Stack

Install stackql-deploy using pip install stackql (see Installing stackql-deploy), set the AZURE_SUBSCRIPTION_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, and AZURE_TENANT_ID environment variables, and you're ready to go!

Once you have set up your project directory (your "stack"), you can use the stackql-deploy CLI application to deploy, test, or teardown the stack in any given environment. To deploy the stack to an environment labeled sit, run the following:

stackql-deploy build azure-stack sit \
-e AZURE_SUBSCRIPTION_ID=$AZURE_SUBSCRIPTION_ID

Use the --dry-run flag to view the queries to be run without actually running them. Here’s an example of a dry-run operation for a prd environment:

stackql-deploy build azure-stack prd \
-e AZURE_SUBSCRIPTION_ID=$AZURE_SUBSCRIPTION_ID \
--dry-run

stackql_manifest.yml

The stackql_manifest.yml defines the resources in your stack and their property values (for one or more environments).

Click to expand the stackql_manifest.yml file
version: 1
name: "azure-stack"
description: description for "azure-stack"
providers:
- azure
globals:
- name: subscription_id
description: azure subscription id
value: "{{ AZURE_SUBSCRIPTION_ID }}"
- name: location
description: default location for resources
value: eastus
- name: global_tags
value:
provisioner: stackql
stackName: "{{ stack_name }}"
stackEnv: "{{ stack_env }}"
resources:
- name: example_resource_group
props:
- name: resource_group_name
value: "{{ stack_name }}-{{ stack_env }}-rg"
exports:
- resource_group_name
- name: example_vnet
props:
- name: vnet_name
value: "{{ stack_name }}-{{ stack_env }}-vnet"
- name: vnet_cidr_block
values:
prd:
value: "10.0.0.0/16"
sit:
value: "10.1.0.0/16"
dev:
value: "10.2.0.0/16"
exports:
- vnet_name
- vnet_cidr_block
- name: example_subnet
props:
- name: subnet_name
value: "{{ stack_name }}-{{ stack_env }}-subnet-1"
- name: subnet_cidr
values:
prd:
value: "10.0.1.0/24"
sit:
value: "10.1.1.0/24"
dev:
value: "10.2.1.0/24"
exports:
- subnet_name
- subnet_id
- name: example_public_ip
props:
- name: public_ip_name
value: "{{ stack_name }}-{{ stack_env }}-public-ip"
exports:
- public_ip_name
- public_ip_id
- public_ip_address
- name: example_nsg
props:
- name: nsg_name
value: "{{ stack_name }}-{{ stack_env }}-nsg"
- name: security_rules
value:
- name: AllowHTTP
properties:
access: Allow
protocol: Tcp
direction: Inbound
priority: 100
sourceAddressPrefix: "*"
sourcePortRange: "*"
destinationAddressPrefix: "*"
destinationPortRange: "8080"
- name: AllowSSH
properties:
access: Allow
protocol: Tcp
direction: Inbound
priority: 200
sourceAddressPrefix: "{{ vnet_cidr_block }}"
sourcePortRange: "*"
destinationAddressPrefix: "*"
destinationPortRange: "22"
exports:
- network_security_group_id
- name: example_nic
props:
- name: nic_name
value: "{{ stack_name }}-{{ stack_env }}-nic"
- name: nic_ip_config
value:
name: ipconfig1
properties:
subnet:
id: "{{ subnet_id }}"
privateIPAllocationMethod: Dynamic
publicIPAddress:
id: "{{ public_ip_id }}"
exports:
- network_interface_id
- name: example_web_server
props:
- name: vm_name
value: "{{ stack_name }}-{{ stack_env }}-vm"
- name: hardwareProfile
value:
vmSize: Standard_DS1_v2
- name: storageProfile
value:
imageReference:
publisher: Canonical
offer: UbuntuServer
sku: 18.04-LTS
version: latest
osDisk:
name: "{{ stack_name }}-{{ stack_env }}-vm-disk1"
createOption: FromImage
managedDisk:
storageAccountType: Standard_LRS
diskSizeGB: 30
- name: osProfile
value:
computerName: myVM-{{ stack_name }}-{{ stack_env }}
adminUsername: azureuser
adminPassword: Password1234!
linuxConfiguration:
disablePasswordAuthentication: false
- name: networkProfile
value:
networkInterfaces:
- id: "{{ network_interface_id }}"
exports:
- vm_name
- vm_id
- name: example_vm_ext
props:
- name: vm_ext_name
value: "{{ stack_name }}-{{ stack_env }}-microsoft.custom-script-linux"
- name: command_to_execute
value: |
wget -O index.html https://raw.githubusercontent.com/stackql/stackql-deploy/main/examples/azure/azure-stack/resources/hello-stackql.html && nohup busybox httpd -f -p 8080 &
exports:
- web_url

Resource Query Files

Resource query files are templates used to create, update, test, and delete resources in your stack. Here are some example resource query files for this Azure example:

/*+ createorupdate */
INSERT INTO azure.network.virtual_networks(
virtualNetworkName,
resourceGroupName,
subscriptionId,
data__location,
data__properties,
data__tags
)
SELECT
'{{ vnet_name }}',
'{{ resource_group_name }}',
'{{ subscription_id }}',
'{{ location }}',
'{"addressSpace": {"addressPrefixes":["{{ vnet_cidr_block }}"]}}',
'{{ global_tags }}'

/*+ statecheck, retries=5, retry_delay=5 */
SELECT COUNT(*) as count FROM azure.network.virtual_networks
WHERE subscriptionId = '{{ subscription_id }}'
AND resourceGroupName = '{{ resource_group_name }}'
AND virtualNetworkName = '{{ vnet_name }}'
AND JSON_EXTRACT(properties, '$.addressSpace.addressPrefixes[0]') = '{{ vnet_cidr_block }}'

/*+ exports */
SELECT '{{ vnet_name }}' as vnet_name,
'{{ vnet_cidr_block }}' as vnet_cidr_block

/*+ delete */
DELETE FROM azure.network.virtual_networks
WHERE subscriptionId = '{{ subscription_id }}'
AND resourceGroupName = '{{ resource_group_name }}'
AND virtualNetworkName = '{{ vnet_name }}'

More Information

The complete code for this example stack is available here. For more information on how to use StackQL and StackQL Deploy, visit: