Edit

Share via


Quickstart: Create and deploy Azure Functions resources from Terraform

In this quickstart, you use Terraform to create a function app in a Flex Consumption plan in Azure Functions, along with other required Azure resources. The Flex Consumption plan provides serverless hosting that lets you run your code on demand without explicitly provisioning or managing infrastructure. The function app runs on Linux and is configured to use Azure Blob storage for code deployments.

Terraform enables the definition, preview, and deployment of cloud infrastructure. Using Terraform, you create configuration files using HCL syntax. The HCL syntax allows you to specify the cloud provider - such as Azure - and the elements that make up your cloud infrastructure. After you create your configuration files, you create an execution plan that allows you to preview your infrastructure changes before they're deployed. Once you verify the changes, you apply the execution plan to deploy the infrastructure.

  • Create an Azure resource group with a unique name.
  • Generate a random string of 13 lowercase letters to name resources.
  • Create a storage account in Azure.
  • Create a blob storage container in the storage account.
  • Create a Flex Consumption plan in Azure Functions.
  • Create a function app with a Flex Consumption plan in Azure.
  • Output the names of the resource group, storage account, service plan, function app, and Azure Functions Flex Consumption plan.

Prerequisites

Implement the Terraform code

The sample code for this article is located in the Azure Terraform GitHub repo. You can view the log file containing the test results from current and previous versions of Terraform. See more articles and sample code showing how to use Terraform to manage Azure resources.

  1. Create a directory in which to test and run the sample Terraform code, and make it the current directory.

  2. Create a file named main.tf, and insert the following code:

    # This Terraform configuration creates a Flex Consumption plan app in Azure Functions 
    # with the required Storage account and Blob Storage deployment container.
    
    # Create a random pet to generate a unique resource group name
    resource "random_pet" "rg_name" {
      prefix = var.resource_group_name_prefix
    }
    
    # Create a resource group
    resource "azurerm_resource_group" "example" {
      location = var.resource_group_location
      name     = random_pet.rg_name.id
    }
    
    # Random String for unique naming of resources
    resource "random_string" "name" {
      length  = 8
      special = false
      upper   = false
      lower   = true
      numeric = false
    }
    
    # Create a storage account
    resource "azurerm_storage_account" "example" {
      name                     = coalesce(var.sa_name, random_string.name.result)
      resource_group_name      = azurerm_resource_group.example.name
      location                 = azurerm_resource_group.example.location
      account_tier             = var.sa_account_tier
      account_replication_type = var.sa_account_replication_type
    }
    
    # Create a storage container
    resource "azurerm_storage_container" "example" {
      name                  = "example-flexcontainer"
      storage_account_id    = azurerm_storage_account.example.id
      container_access_type = "private"
    }
    
    # Create a Log Analytics workspace for Application Insights
    resource "azurerm_log_analytics_workspace" "example" {
      name                = coalesce(var.ws_name, random_string.name.result)
      location            = azurerm_resource_group.example.location
      resource_group_name = azurerm_resource_group.example.name
      sku                 = "PerGB2018"
      retention_in_days   = 30
    }
    
    # Create an Application Insights instance for monitoring
    resource "azurerm_application_insights" "example" {
      name                = coalesce(var.ai_name, random_string.name.result)
      location            = azurerm_resource_group.example.location
      resource_group_name = azurerm_resource_group.example.name
      application_type    = "web"
      workspace_id = azurerm_log_analytics_workspace.example.id
    }
    
    # Create a service plan
    resource "azurerm_service_plan" "example" {
      name                = coalesce(var.asp_name, random_string.name.result)
      resource_group_name = azurerm_resource_group.example.name
      location            = azurerm_resource_group.example.location
      sku_name            = "FC1"
      os_type             = "Linux"
    }
    
    # Create a function app
    resource "azurerm_function_app_flex_consumption" "example" {
      name                = coalesce(var.fa_name, random_string.name.result)
      resource_group_name = azurerm_resource_group.example.name
      location            = azurerm_resource_group.example.location
      service_plan_id     = azurerm_service_plan.example.id
    
      storage_container_type      = "blobContainer"
      storage_container_endpoint  = "${azurerm_storage_account.example.primary_blob_endpoint}${azurerm_storage_container.example.name}"
      storage_authentication_type = "StorageAccountConnectionString"
      storage_access_key          = azurerm_storage_account.example.primary_access_key
      runtime_name                = var.runtime_name
      runtime_version             = var.runtime_version
      maximum_instance_count      = 50
      instance_memory_in_mb       = 2048
      
      site_config {
      }
    }
    
  3. Create a file named outputs.tf, and insert the following code:

    output "resource_group_name" {
      value = azurerm_resource_group.example.name
    }
    
    output "sa_name" {
      value = azurerm_storage_account.example.name
    }
    
    output "asp_name" {
      value = azurerm_service_plan.example.name
    }
    
    output "fa_name" {
      value = azurerm_function_app_flex_consumption.example.name
    }
    
    output "fa_url" {
      value = "https://${azurerm_function_app_flex_consumption.example.name}.azurewebsites.net"
    }
    
  4. Create a file named providers.tf, and insert the following code:

    terraform {
      required_version = ">=1.0"
    
      required_providers {
        azurerm = {
          source  = "hashicorp/azurerm"
          version = "~>4.0"
        }
        random = {
          source  = "hashicorp/random"
          version = "~>3.0"
        }
      }
    }
    
    provider "azurerm" {
      features {}
    }
    
  5. Create a file named variables.tf, and insert the following code:

    variable "resource_group_name" {
      type        = string
      default     = ""
      description = "The name of the Azure resource group. If blank, a random name will be generated."
    }
    
    variable "resource_group_name_prefix" {
      type        = string
      default     = "rg"
      description = "Prefix of the resource group name that's combined with a random ID so name is unique in your Azure subscription."
    }
    
    variable "resource_group_location" {
      type        = string
      default     = "eastus"
      description = "Location of the resource group."
    }
    
    variable "sa_account_tier" {
      description = "The tier of the storage account. Possible values are Standard and Premium."
      type        = string
      default     = "Standard"
    }
    
    variable "sa_account_replication_type" {
      description = "The replication type of the storage account. Possible values are LRS, GRS, RAGRS, and ZRS."
      type        = string
      default     = "LRS"
    }
    
    variable "sa_name" {
      description = "The name of the storage account. If blank, a random name will be generated."
      type        = string
      default     = ""
    }
    
    variable "ws_name" {
      description = "The name of the Log Analytics workspace. If blank, a random name will be generated."
      type        = string
      default     = ""
    }
    
    variable "ai_name" {
      description = "The name of the Application Insights instance. If blank, a random name will be generated."
      type        = string
      default     = ""
    }
    
    variable "asp_name" {
      description = "The name of the App Service Plan. If blank, a random name will be generated."
      type        = string
      default     = ""
    }
    
    variable "fa_name" {
      description = "The name of the Function App. If blank, a random name will be generated."
      type        = string
      default     = ""
    }
    
    variable "runtime_name" {
      description = "The name of the language worker runtime."
      type        = string
      default     = "node" # Allowed: dotnet-isolated, java, node, powershell, python
    }
    
    variable "runtime_version" {
      description = "The version of the language worker runtime."
      type        = string
      default     = "20" # Supported versions: see https://aka.ms/flexfxversions
    }
    
  6. Use this Azure CLI command to set the ARM_SUBSCRIPTION_ID environment variable to the ID of your current subscription:

    export ARM_SUBSCRIPTION_ID=$(az account show --query "id" --output tsv)
    

    You must have this variable set for Terraform to be able to authenticate to your Azure subscription.

Initialize Terraform

Run terraform init to initialize the Terraform deployment. This command downloads the Azure provider required to manage your Azure resources.

terraform init -upgrade

Key points:

  • The -upgrade parameter upgrades the necessary provider plugins to the newest version that complies with the configuration's version constraints.

Create a Terraform execution plan

Run terraform plan to create an execution plan.

terraform plan -out main.tfplan -var="runtime_name=dotnet-isolated" -var="runtime_version=8"
terraform plan -out main.tfplan -var="runtime_name=powershell" -var="runtime_version=7.4"
terraform plan -out main.tfplan -var="runtime_name=python" -var="runtime_version=3.12"
terraform plan -out main.tfplan -var="runtime_name=java" -var="runtime_version=21"
terraform plan -out main.tfplan -var="runtime_name=node" -var="runtime_version=20"

Make sure that runtime_version matches the language stack version you verified locally. Select your preferred language stack at the top of the article.

Key points:

  • The terraform plan command creates an execution plan, but doesn't execute it. Instead, it determines what actions are necessary to create the configuration specified in your configuration files. This pattern allows you to verify whether the execution plan matches your expectations before making any changes to actual resources.
  • The optional -out parameter allows you to specify an output file for the plan. Using the -out parameter ensures that the plan you reviewed is exactly what is applied.

Apply a Terraform execution plan

Run terraform apply to apply the execution plan to your cloud infrastructure.

terraform apply main.tfplan

Key points:

  • The example terraform apply command assumes you previously ran terraform plan -out main.tfplan.
  • If you specified a different filename for the -out parameter, use that same filename in the call to terraform apply.
  • If you didn't use the -out parameter, call terraform apply without any parameters.

Verify the results

The outputs.tf file returns these values for your new function app:

Value Description
resource_group_name The name of the resource group you created.
sa_name The name of the Azure storage account required by the Functions host.
asp_name The name of the Flex Consumption plan that hosts your new app.
fa_name The name of your new function app.
fa_url The URL of your new function app endpoint.

Open a browser and browse to the URL location in fa_url. You can also use the terraform output command to review these values at a later time.

Screenshot of Azure Functions app 'Welcome page'.

Clean up resources

When you no longer need the resources created via Terraform, do the following steps:

  1. Run terraform plan and specify the destroy flag.

    terraform plan -destroy -out main.destroy.tfplan
    

    Key points:

    • The terraform plan command creates an execution plan, but doesn't execute it. Instead, it determines what actions are necessary to create the configuration specified in your configuration files. This pattern allows you to verify whether the execution plan matches your expectations before making any changes to actual resources.
    • The optional -out parameter allows you to specify an output file for the plan. Using the -out parameter ensures that the plan you reviewed is exactly what is applied.
  2. Run terraform apply to apply the execution plan.

    terraform apply main.destroy.tfplan
    

Troubleshoot Terraform on Azure

Troubleshoot common problems when using Terraform on Azure.

Next steps

You can now deploy a code project to the function app resources you created in Azure.

You can create, verify, and deploy a code project to your new function app from these local environments: