Does appsettings disappearance of Azure Function relate to configuration drift?

I use terraform v1.0.4 to create Azure Function resources, here is my terraform script:

resource "azurerm_app_service_plan" "B1" {
  name                = "plan-B1"
  resource_group_name = azurerm_resource_group.mygroup.name
  location            = azurerm_resource_group.mygroup.location
  kind                = "Linux"
  reserved            = true
  sku {
    tier = "Basic"
    size = "B1"
  }
}

resource "azurerm_function_app" "myapp" {
  name                = format("myapp-%s", terraform.workspace)
  resource_group_name = azurerm_resource_group.mygroup.name
  location            = azurerm_resource_group.mygroup.location
  os_type = "linux"
  version = "~4"

  storage_account_name       = azurerm_storage_account.myapp.name
  storage_account_access_key = azurerm_storage_account.myapp.primary_access_key

  app_service_plan_id = azurerm_app_service_plan.B1.id

  identity {
    type = "SystemAssigned"
  }

  app_settings = {
    APPINSIGHTS_INSTRUMENTATIONKEY = "${azurerm_application_insights.myapp.instrumentation_key}"
    FUNCTIONS_WORKER_RUNTIME = "dotnet"
  }

  site_config {
    linux_fx_version = "dotnet|6"
    always_on = true
    cors {
      allowed_origins = []
      support_credentials = false
    }
  }
}

Then, I use the following commands to deploy by zip in Jenkins:

sh 'dotnet restore my_project.csproj'
sh 'dotnet publish my_project.csproj --output publish'
  dir('publish') {
    sh 'zip -r publish.zip *'
    withCredentials([azureServicePrincipal($params.MY_SP)]) {
    // Use 'az webapp' rather than 'az functionapp' because of https://github.com/Azure/azure-cli/issues/13655
    sh """
      az login --service-principal -u $AZURE_CLIENT_ID -p $AZURE_CLIENT_SECRET --tenant $AZURE_TENANT_ID
      az webapp deployment source config-zip -g $params.RESOURCE_GROUP -n $params.FUNCTION_APP_NAME --src ./publish.zip --timeout 300
    """        
  }
}

After deployment, I’ll use the following Ansible script to set my custom appsettings:

- name: Force Login using identity
  command: az login --identity

- name: Config app settings
  command:
    az function app config appsettings set --name "{{ functionapp_name }}"
    --resource-group "{{ functionapp_resource_group }}" --settings "{{ item }}"
  with_items:
    - "WEBSITE_RUN_FROM_PACKAGE=1"
    - "SubscriptionExpiredSchedule=* 30 * * * *"
    - "KeycloakEndpoint={{ keycloak_endpoint }}"
    - "KEY=VALUE..."

My Azure Function works fine when it just be deployed. But usually, all of my custom appsettings are lost in about 20 minutes except APPINSIGHTS_INSTRUMENTATIONKEY and FUNCTIONS_WORKER_RUNTIME . After a while, I found that there is a mechanism called configuration drift, It makes the resource corresponding to the Terraform state. I wonder does Azure automatically delete my custom appsettings to make resources conform to Terraform?

I actually began to trace this issue a month ago, I thought it was related to Docker, but it occurs whether I deploy using a container or a zip, so I highly guess it’s because of configuration drift. The issue link: Container-based function app lost costom appsettings after being recycled by `CORSSettingsChanged` and `AppSettingsChange` · Issue #2327 · Azure/Azure-Functions · GitHub

1 Like

Its sad to see how barren this forum can be. Terraform will definitely apply the configuration that is defined when you apply, so if you want to prevent certain properties from doing this, the ignore_changes meta argument helps here.

It seems right. The problem never happened again after I added the following code block.

lifecycle {
  ignore_changes = [
    app_settings # prevent TF reporting configuration drift after app code is deployed
  ]
}

The ARM template document also says: “If you don’t specify certain properties, Resource Manager interprets the deployment as overwriting those values. Properties that aren’t included in the template are reset to the default values.”

But the azurerm provider document doesn’t explicitly mention how ignore_change will affect Azure API, and I don’t want to look into the source code of azurerm provider to figure it out. I just want to confirm the ignore_change will actually disable the reset mechanism.