1. Add the definition for an application gateway to last code snippet

    Python

    The following Pulumi Python program demonstrates how to define an Azure Application Gateway with minimal configuration. Note that you should adjust the properties and parameters to suit your specific requirements, as this is a foundational setup.

    import pulumi import pulumi_azure_native as azure_native # Create an Azure Resource Group resource_group = azure_native.resources.ResourceGroup("resource_group") # Define a subnet for the Application Gateway subnet = azure_native.network.Subnet( "appgwsubnet", address_prefix="10.0.0.0/24", resource_group_name=resource_group.name, virtual_network_name="yourVNetName", ) # Define an Application Gateway app_gateway = azure_native.network.ApplicationGateway( "appGateway", resource_group_name=resource_group.name, sku=azure_native.network.SkuArgs( name="Standard_v2", tier="Standard_v2", ), location=resource_group.location, gateway_ip_configurations=[ azure_native.network.ApplicationGatewayIPConfigurationArgs( name="appGwIpConfig", subnet=azure_native.network.SubnetArgs( id=subnet.id, ), ), ], frontend_ip_configurations=[ azure_native.network.ApplicationGatewayFrontendIPConfigurationArgs( name="appGwFrontendIp", private_ip_allocation_method="Dynamic", subnet=azure_native.network.SubnetArgs( id=subnet.id, ), ), ], frontend_ports=[ azure_native.network.ApplicationGatewayFrontendPortArgs( name="appGwFrontendPort", port=80, ), ], http_listeners=[ azure_native.network.ApplicationGatewayHttpListenerArgs( name="appGwHttpListener", frontend_ip_configuration=azure_native.network.ApplicationGatewayFrontendIPConfigurationArgs( id=pulumi.Output.concat(resource_group.id, "/frontEndIpConfigurations/appGwFrontendIp"), ), frontend_port=azure_native.network.ApplicationGatewayFrontendPortArgs( id=pulumi.Output.concat(resource_group.id, "/frontendPorts/appGwFrontendPort"), ), protocol="Http", ), ], request_routing_rules=[ azure_native.network.ApplicationGatewayRequestRoutingRuleArgs( name="appGwRequestRoutingRule", rule_type="Basic", http_listener=azure_native.network.ApplicationGatewayHttpListenerArgs( id=pulumi.Output.concat(resource_group.id, "/httpListeners/appGwHttpListener"), ), backend_address_pool=azure_native.network.ApplicationGatewayBackendAddressPoolArgs( id=pulumi.Output.concat(resource_group.id, "/backendAddressPools/appGwBackendPool"), ), backend_http_settings=azure_native.network.ApplicationGatewayBackendHttpSettingsArgs( id=pulumi.Output.concat(resource_group.id, "/backendHttpSettingsCollection/appGwBackendHttpSettings"), ), ), ], backend_address_pools=[ azure_native.network.ApplicationGatewayBackendAddressPoolArgs( name="appGwBackendPool", ), ], backend_http_settings_collection=[ azure_native.network.ApplicationGatewayBackendHttpSettingsArgs( name="appGwBackendHttpSettings", port=80, protocol="Http", cookie_based_affinity="Disabled", ), ], ) # Export the ID of the Application Gateway pulumi.export("applicationGatewayId", app_gateway.id)

    Make sure you replace "yourVNetName" with the name of your existing virtual network where you want to deploy the Application Gateway. Adjust additional parameters as necessary for your setup, such as the SKU, the ports, or the HTTP settings.



  2. Add the code to create two virtual machines that are load balanced by the application gateway

    Python

    To achieve the goal of having two Virtual Machines behind an Application Gateway, the following Pulumi program creates two VMs within the same availability set and virtual network. The Application Gateway is set up with a front-end IP, a back-end pool consisting of the VMs, listeners, and routing rules to control the traffic flow to the VMs.

    This example assumes the existence of a Virtual Network (VNet) and subnet where the Application Gateway and VMs will be deployed, as well as a configured Network Security Group to allow the necessary traffic. Adjust the parameters as needed for your specific setup.

    Note: The detailed configuration for the Public IP, Network Interface, VM Image, and other elements need to be adjusted based on your requirements. This is a simplified version to illustrate the idea.

    import pulumi import pulumi_azure_native as azure_native from pulumi_azure_native import network, compute # Create an Azure Resource Group resource_group = azure_native.resources.ResourceGroup('resource_group') # Create an Azure Virtual Network virtual_network = network.VirtualNetwork( 'virtualNetwork', resource_group_name=resource_group.name, address_space=network.AddressSpaceArgs(address_prefixes=['10.0.0.0/16']), location=resource_group.location) # Create a Subnet for Application Gateway app_gateway_subnet = network.Subnet( 'appGatewaySubnet', resource_group_name=resource_group.name, virtual_network_name=virtual_network.name, address_prefix="10.0.1.0/24") # Create a Subnet for VMs vm_subnet = network.Subnet( 'vmSubnet', resource_group_name=resource_group.name, virtual_network_name=virtual_network.name, address_prefix="10.0.2.0/24") # Create an Application Gateway Public IP Address public_ip = network.PublicIPAddress( 'publicIp', resource_group_name=resource_group.name, location=resource_group.location, public_ip_allocation_method=network.IPAllocationMethod.STATIC) # Create an Application Gateway app_gateway = network.ApplicationGateway( 'appGateway', resource_group_name=resource_group.name, location=resource_group.location, sku=network.ApplicationGatewaySkuArgs( name=network.ApplicationGatewaySkuName.STANDARD_V2, tier=network.ApplicationGatewayTier.STANDARD_V2, ), gateway_ip_configurations=[network.ApplicationGatewayIPConfigurationArgs( name='appGatewayConfig', subnet=azure_native.network.SubnetArgs(id=app_gateway_subnet.id) )], frontend_ip_configurations=[network.ApplicationGatewayFrontendIPConfigurationArgs( name='appGwPublicFrontendIp', public_ip_address=azure_native.network.PublicIPAddressArgs(id=public_ip.id) )], frontend_ports=[network.ApplicationGatewayFrontendPortArgs( name='appGatewayFrontendPort', port=80 )], http_listeners=[network.ApplicationGatewayHttpListenerArgs( name='appGatewayHttpListener', frontend_ip_configuration=network.ApplicationGatewayFrontendIPConfigurationArgs( id=pulumi.Output.concat(app_gateway.id, "/frontendIPConfigurations/appGwPublicFrontendIp") ), frontend_port=network.ApplicationGatewayFrontendPortArgs( id=pulumi.Output.concat(app_gateway.id, "/frontendPorts/appGatewayFrontendPort") ), protocol=network.ApplicationGatewayProtocol.HTTP, )], backend_address_pools=[network.ApplicationGatewayBackendAddressPoolArgs( name='appGatewayBackendPool' )], backend_http_settings=[network.ApplicationGatewayBackendHttpSettingsArgs( name='appGatewayBackendHttpSettings', port=80, protocol=network.ApplicationGatewayProtocol.HTTP, cookie_based_affinity=network.ApplicationGatewayCookieBasedAffinity.DISABLED )], request_routing_rules=[network.ApplicationGatewayRequestRoutingRuleArgs( name='appGwRule', rule_type=network.ApplicationGatewayRequestRoutingRuleType.BASIC, http_listener=network.ApplicationGatewayHttpListenerArgs( id=pulumi.Output.concat(app_gateway.id, "/httpListeners/appGatewayHttpListener") ), backend_address_pool=network.ApplicationGatewayBackendAddressPoolArgs( id=pulumi.Output.concat(app_gateway.id, "/backendAddressPools/appGatewayBackendPool") ), backend_http_settings=network.ApplicationGatewayBackendHttpSettingsArgs( id=pulumi.Output.concat(app_gateway.id, "/backendHttpSettingsCollection/appGatewayBackendHttpSettings") ), )], ) # Create an Availability Set for the VMs availability_set = compute.AvailabilitySet( 'availabilitySet', resource_group_name=resource_group.name, location=resource_group.location, platform_fault_domain_count=2, platform_update_domain_count=2) # Helper function to create a network interface for a VM def create_network_interface(index: int, subnet_id: pulumi.Output[str], resource_group_name: str): return network.NetworkInterface( f'vm{index}NIC', resource_group_name=resource_group_name, location=resource_group.location, ip_configurations=[network.NetworkInterfaceIPConfigurationArgs( name=f'vm{index}IPConfig', subnet=network.SubnetArgs(id=subnet_id), private_ip_allocation_method=network.IPAllocationMethod.DYNAMIC )]) # Function to create a Virtual Machine def create_virtual_machine(index: int, availability_set_id: pulumi.Output[str], resource_group_name: str, nic_id: pulumi.Output[str]): return compute.VirtualMachine( f'vm{index}', resource_group_name=resource_group_name, location=resource_group.location, availability_set=compute.SubResourceArgs( id=availability_set_id, ), network_profile=compute.NetworkProfileArgs( network_interfaces=[compute.NetworkInterfaceReferenceArgs( id=nic_id, primary=True )] ), os_profile=compute.OSProfileArgs( admin_username='testadmin', computer_name=f'vm{index}', admin_password='Password1234!', ), os_profile_linux_config=compute.OSProfileLinuxConfigurationArgs( disable_password_authentication=False, ), hardware_profile=compute.HardwareProfileArgs( vm_size=compute.VirtualMachineSizeTypes.STANDARD_A2 ), storage_profile=compute.StorageProfileArgs( image_reference=compute.ImageReferenceArgs( publisher='Canonical', offer='UbuntuServer', sku='18.04-LTS', version='latest', ), os_disk=compute.OSDiskArgs( create_option=compute.DiskCreateOptionTypes.FROM_IMAGE, name=f'vm{index}OSDisk', ), ) ) # Create two VMs vms = [] for i in range(1, 3): nic = create_network_interface(i, vm_subnet.id, resource_group.name) vm = create_virtual_machine(i, availability_set.id, resource_group.name, nic.id) # Add VM to backend pool backend_address_pool_association = network.ApplicationGatewayBackendAddressPoolAssociation( f'appGatewayBackendPoolAssociation{i}', ip_configuration_id=nic.ip_configurations.apply( lambda ip_configs: ip_configs[0].id ), backend_address_pool_id=app_gateway.backend_address_pools.apply( lambda pools: pools[0].id ) ) vms.append(vm) # Export the Public IP address of the Application Gateway pulumi.export('app_gateway_public_ip', public_ip.ip_address)

    This program sets up the Application Gateway and the VMs in a simplified manner. After running pulumi up with this code, you'll have two VMs behind an Application Gateway, which provides load balancing and traffic management capabilities.



  3. associate the backend address pool inside the create_virtual_machine function

    Python

    To associate the backend address pool with virtual machines, we modify the create_virtual_machine function to include a step to create an association between the network interface of the VM and the Application Gateway's backend address pool. This association is necessary so that the Application Gateway knows to which VMs it should direct the traffic.

    Here's how you can incorporate this association within your existing Pulumi program in Python:

    import pulumi import pulumi_azure_native as azure_native from pulumi_azure_native import network, compute # ... (other resources like resource_group, virtual_network, app_gateway, etc.) # Function to create a Virtual Machine and associate it with the Application Gateway's backend address pool def create_virtual_machine(index: int, availability_set_id: pulumi.Output[str], resource_group_name: str, subnet_id: pulumi.Output[str], backend_address_pool_id: pulumi.Output[str]): # Create a network interface for the VM nic = network.NetworkInterface( f'vm{index}NIC', resource_group_name=resource_group_name, location=resource_group.location, ip_configurations=[network.NetworkInterfaceIPConfigurationArgs( name=f'vm{index}IPConfig', subnet=network.SubnetArgs(id=subnet_id), private_ip_allocation_method=network.IPAllocationMethod.DYNAMIC )] ) # Associate the network interface with the backend address pool backend_address_pool_association = network.ApplicationGatewayBackendAddressPoolAssociation( f'appGatewayBackendPoolAssociation{index}', ip_configuration_id=nic.ip_configurations.apply(lambda ip_configs: ip_configs[0].id), backend_address_pool_id=backend_address_pool_id ) # Create the Virtual Machine vm = compute.VirtualMachine( f'vm{index}', # ... (other VM properties) network_profile=compute.NetworkProfileArgs( network_interfaces=[compute.NetworkInterfaceReferenceArgs( id=nic.id, primary=True )] ), # ... (other VM properties) ) return vm # ... (other parts of Pulumi program like setting up subnets, etc.) # Usage of create_virtual_machine with backend_address_pool as an argument vm1 = create_virtual_machine( index=1, availability_set_id=availability_set.id, resource_group_name=resource_group.name, subnet_id=vm_subnet.id, backend_address_pool_id=app_gateway.backend_address_pools.apply(lambda pools: pools[0].id), ) # Similarly, create more VMs and associate with the backend address pool as needed.

    In the program above, we add an additional parameter backend_address_pool_id to the create_virtual_machine function to pass the ID of the Application Gateway's backend address pool. We then create a NetworkInterface resource, which includes a reference to the subnet in which the VM will be created. After the network interface is created, we establish an association between it and the backend address pool through the ApplicationGatewayBackendAddressPoolAssociation resource, which connects the IP configuration of the created network interface with the backend address pool of the Application Gateway.