Deploying Geneos on Azure Resource Manager using Bicep
Azure offers native IaC support through the Azure Resource Manager.
This guide outlines how to deploy Geneos components using Bicep templates and Azure Resource Manager Stacks.
Prerequisites Copied
- Azure CLI installed
Install from Azure - Bicep CLI installed
Note
This is normally bundled with the Azure CLI installation.
```bash
az bicep install
```
-
Logged in from CLI
az login
-
Storage account and key vault storing the Geneos resources
- Geneos component tarball file
- Configuration file
- Service file
Deployment commands Copied
Use the following az stack group
commands to manage Deployment Stacks at resource group.
Create or update a deployment stack Copied
Configure bicep templates and parameters.
az stack group create \
--name <StackName> \
--resource-group <ResourceGroup> \
--template-file <BicepFile> \
--parameters <BicepParameters> \
--action-on-unmanage deleteAll \
--deny-settings-mode none
For example:
az stack group create \
--name NetprobeStack \
--resource-group DeploymentGroup \
--template-file main.bicep \
--parameters .\resources\netprobe\netprobe_params.bicepparam \
--action-on-unmanage deleteAll \
--deny-settings-mode none
Show public IP addresses of virtual machines in the deployment stack Copied
az stack group show \
--name <StackName> \
--resource-group <ResourceGroup> \
--query "outputs.virtualMachinePublicIps.value" \
--output table
For example:
--name NetprobeStack \
--resource-group DeploymentGroup \
--query "outputs.virtualMachinePublicIps.value" \
--output table
Delete the deployment stack Copied
az stack group delete \
--name <StackName> \
--resource-group <ResourceGroup> \
--action-on-unmanage deleteAll
For example:
az stack group delete \
--name NetprobeStack \
--resource-group DeploymentGroup \
--action-on-unmanage deleteAll
Template file Copied
Several template files are available which can be used depending on your provisioning goal.
Can we add the diagram in the docs?
Template file | Description |
---|---|
main.bicep | Main template file that will provision all the necessary resources for a new Virtual Machine along with a Geneos component. |
NetworkSecurityGroup.bicep | Used for provisioning a Network Security Group. |
VirtualNetwork.bicep | Used for provisioning a Virtual Network. |
PublicIP.bicep | Used for provisioning a Public IP Address. |
NetworkInterface.bicep | Used for provisioning a Network Interface. |
VirtualMachine.bicep | Used for provisioning a Virtual Machine. |
RunCommand.bicep | Used to run a command within the Virtual Machine (ex. Java Installation). |
Geneos.bicep | Used to deploy Geneos components within the Virtual Machine. |
Parameters Copied
Reference parameters are already provided and can be found in the following paths:
Azure\resources\gateway\gateway_params.bicepparam
Azure\resources\netprobe\netprobe_params.bicepparam
Network Security Group Copied
targetScope = 'resourceGroup'
@description('Name of the network security group.')
param networkSecurityGroupName string
@description('TCP inbound destination port ranges for the network security group.')
param networkSecurityGroupTcpInboundDestinationPorts array = []
@description('Tags to apply to the network security group.')
param tags object = {}
resource nsg 'Microsoft.Network/networkSecurityGroups@2024-07-01' = {
name: networkSecurityGroupName
location: resourceGroup().location
properties: {
securityRules: [
{
name: 'AllowInboundTcp'
properties: {
protocol: 'Tcp'
sourcePortRange: '*'
destinationPortRanges: networkSecurityGroupTcpInboundDestinationPorts
sourceAddressPrefix: '*'
destinationAddressPrefix: '*'
access: 'Allow'
priority: 1000
direction: 'Inbound'
}
}
]
}
tags: tags
}
output networkSecurityGroupId string = nsg.id
Parameter | Description |
---|---|
networkSecurityGroupName | Name of the network security group.
|
networkSecurityGroupTcpInboundDestinationPorts | TCP inbound destination port ranges for the network security group. |
Virtual Network Copied
targetScope = 'resourceGroup'
@description('Name of the virtual network.')
param virtualNetworkName string
@description('Address prefixes for the virtual network.')
param virtualNetworkAddressPrefixes array = []
@description('Address prefixes for the virtual network subnets.')
param virtualNetworkAddressPrefixesSubnet array = []
@description('Tags to apply to the virtual network.')
param tags object = {}
var subnetName = '${virtualNetworkName}-subnet'
resource vnet 'Microsoft.Network/virtualNetworks@2024-07-01' = {
name: virtualNetworkName
location: resourceGroup().location
properties: {
addressSpace: {
addressPrefixes: virtualNetworkAddressPrefixes
}
subnets: [
{
name: subnetName
properties: {
addressPrefixes: virtualNetworkAddressPrefixesSubnet
}
}
]
}
tags: tags
}
output virtualNetworkId string = vnet.id
output virtualNetworkSubnetId string = '${vnet.id}/subnets/${subnetName}'
Parameter | Description |
---|---|
virtualNetworkName | Name of the virtual network.
|
virtualNetworkAddressPrefixes | Address prefixes for the virtual network. |
virtualNetworkAddressPrefixesSubnet | Address prefixes for the virtual network subnets. |
Public IP Address Copied
targetScope = 'resourceGroup'
@description('Name of the public IP address.')
param publicIpAddressName string
@description('SKU of the public IP address.')
param publicIpAddressSku string
@description('Type of the public IP address.')
param publicIpAddressType string
@description('Zones for the public IP address.')
param publicIpAddressZone array = []
@description('Tags to apply to the public IP address.')
param tags object = {}
resource pip 'Microsoft.Network/publicIPAddresses@2024-07-01' = {
name: publicIpAddressName
location: resourceGroup().location
sku: {
name: publicIpAddressSku
}
properties: {
publicIPAllocationMethod: publicIpAddressType
}
zones: publicIpAddressZone
tags: tags
}
output publicIpAddressId string = pip.id
output publicIpAddress string = pip.properties.ipAddress
Parameter | Description |
---|---|
publicIpAddressName | Name of the public IP address.
|
publicIpAddressSku | SKU of the public IP address. |
publicIpAddressType | Type of the public IP address. |
publicIpAddressZone | Zones for the public IP address. |
Network Interface Copied
targetScope = 'resourceGroup'
@description('Name of the network interface.')
param networkInterfaceName string
@description('ID of the network security group to associate with the network interface.')
param networkSecurityGroupId string
@description('ID of the public IP address to associate with the network interface.')
param publicIpAddressId string
@description('ID of the virtual network subnet to associate with the network interface.')
param virtualNetworkSubnetId string
@description('Tags to apply to the network interface.')
param tags object = {}
var ipConfigName = '${networkInterfaceName}-ipconfig'
resource nic 'Microsoft.Network/networkInterfaces@2024-07-01' = {
name: networkInterfaceName
location: resourceGroup().location
properties: {
ipConfigurations: [
{
name: ipConfigName
properties: {
subnet: {
id: virtualNetworkSubnetId
}
privateIPAllocationMethod: 'Dynamic'
publicIPAddress: {
id: publicIpAddressId
properties: {
deleteOption: 'Delete'
}
}
}
}
]
networkSecurityGroup: {
id: networkSecurityGroupId
}
}
tags: tags
}
output networkInterfaceId string = nic.id
Parameter | Description |
---|---|
networkInterfaceName | Name of the network interface.
|
Key Vault Copied
Parameter | Description |
---|---|
keyVaultName | Name of the Key Vault to retrieve secrets and files from. |
Virtual Machine Copied
targetScope = 'resourceGroup'
@description('Name of the virtual machine.')
param virtualMachineName string
@description('Availability zones for the virtual machine.')
param virtualMachineZone array = []
@description('Size of the virtual machine.')
param virtualMachineSize string
@description('OS disk type for the virtual machine.')
param virtualMachineOsDiskType string
@description('Image offer for the virtual machine.')
param virtualMachineImageOffer string
@description('Image SKU for the virtual machine.')
param virtualMachineImageSku string
@description('Image version for the virtual machine.')
param virtualMachineImageVersion string
@description('Admin username for the virtual machine.')
param virtualMachineAdminUser string
@secure()
@description('Admin password for the virtual machine.')
param virtualMachineAdminPassword string
@description('ID of the network interface to attach to the virtual machine.')
param networkInterfaceId string
@description('Tags to apply to the virtual machine.')
param tags object = {}
resource vm 'Microsoft.Compute/virtualMachines@2024-11-01' = {
name: virtualMachineName
location: resourceGroup().location
zones: virtualMachineZone
properties: {
hardwareProfile: {
vmSize: virtualMachineSize
}
storageProfile: {
osDisk: {
createOption: 'fromImage'
managedDisk: {
storageAccountType: virtualMachineOsDiskType
}
deleteOption: 'Delete'
}
imageReference: {
publisher: 'canonical'
offer: virtualMachineImageOffer
sku: virtualMachineImageSku
version: virtualMachineImageVersion
}
}
networkProfile: {
networkInterfaces: [
{
id: networkInterfaceId
properties: {
deleteOption: 'Delete'
}
}
]
}
securityProfile: {
securityType: 'TrustedLaunch'
uefiSettings: {
secureBootEnabled: true
vTpmEnabled: true
}
}
additionalCapabilities: {
hibernationEnabled: false
}
osProfile: {
computerName: virtualMachineName
adminUsername: virtualMachineAdminUser
adminPassword: virtualMachineAdminPassword
linuxConfiguration: {
disablePasswordAuthentication: false
patchSettings: {
assessmentMode: 'ImageDefault'
patchMode: 'ImageDefault'
}
}
}
}
tags: tags
}
output virtualMachineId string = vm.id
output virtualMachineName string = vm.name
Parameter | Description |
---|---|
virtualMachineName | Name of the virtual machine.
|
virtualMachineZone | Availability zones for the virtual machine. |
virtualMachineSize | Size of the virtual machine. |
virtualMachineOsDiskType | OS disk type for the virtual machine. |
virtualMachineImageOffer | Image offer for the virtual machine. |
virtualMachineImageSku | Image SKU for the virtual machine. |
virtualMachineImageVersion | Image version for the virtual machine. |
virtualMachineAdminUser | Admin username for the virtual machine. |
keyVaultKeyNameForAdminPass | Key Vault key name for the admin password. |
Run Command Copied
targetScope = 'resourceGroup'
@description('Name of the run command.')
param runCommandName string
@description('Name of the virtual machine.')
param virtualMachineName string
@description('Command to run.')
param commandToRun string
resource command 'Microsoft.Compute/virtualMachines/runCommands@2024-11-01' = {
name: '${virtualMachineName}/${runCommandName}'
location: resourceGroup().location
properties: {
asyncExecution: false
source: {
script: commandToRun
}
timeoutInSeconds: 300
}
}
Parameter | Description |
---|---|
installJavaCommand | Command to execute for Java installation |
Geneos Copied
targetScope = 'resourceGroup'
@description('Name of the Geneos deployment.')
param geneosDeploymentName string
@description('Name of the virtual machine.')
param virtualMachineName string
@description('Binary URL in data storage.')
param binaryUrlInDataStorage string
@description('Configuration URL in data storage.')
param configUrlInDataStorage string
@description('Service URL in data storage.')
param serviceUrlInDataStorage string
@secure()
@description('SAS token of data storage.')
param sasToken string
var binaryUrl = !empty(binaryUrlInDataStorage) ? '${binaryUrlInDataStorage}?${sasToken}' : ''
var binaryScript = !empty(binaryUrlInDataStorage) ? '''
tar -xvzf geneos-*.tar.gz -C /opt
''' : ''
var configUrl = !empty(configUrlInDataStorage) ? '${configUrlInDataStorage}?${sasToken}' : ''
var configScript = !empty(configUrlInDataStorage) ?'''
mkdir -p /opt/config && cp *.xml /opt/config
''' : ''
var serviceUrl = !empty(serviceUrlInDataStorage) ? '${serviceUrlInDataStorage}?${sasToken}' : ''
var serviceScript = !empty(serviceUrlInDataStorage) ? '''
svc=$(basename *.service)
cp "$svc" /etc/systemd/system/
systemctl daemon-reload
systemctl enable "$svc"
systemctl start "$svc"
''' : ''
resource extension 'Microsoft.Compute/virtualMachines/extensions@2024-11-01' = {
name: '${virtualMachineName}/${geneosDeploymentName}'
location: resourceGroup().location
properties: {
publisher: 'Microsoft.Azure.Extensions'
type: 'CustomScript'
typeHandlerVersion: '2.1'
settings: {
fileUris: [
binaryUrl
configUrl
serviceUrl
]
commandToExecute: '${binaryScript}\n${configScript}\n${serviceScript}'
}
}
}
Parameter | Description |
---|---|
binaryUrlInDataStorage | Binary URL in data storage. |
configUrlInDataStorage | Configuration URL in data storage. |
serviceUrlInDataStorage | Service URL in data storage. |
keyVaultKeyNameForSasToken | Key Vault key name for the SAS token. |
General Copied
Parameter | Description |
---|---|
tags | Tags to apply to all resources. |
vmCount | Number of virtual machines to deploy. |