Blog

Bereitstellen einer Azure-Funktion mit Terraform

Aktualisiert Oktober 16, 2025
4 Minuten

Bereitstellung von Azure-Funktionen nur mit Terraform

Bei unseren Kunden setzen wir häufig Azure Functions ein. Das Einlesen von Daten über HTTP und/oder Eventhubs ist relativ einfach, da das Azure Function SDK bereits mit Triggern für diese Szenarien ausgestattet ist. Die Bereitstellung mit Terraform ist jedoch nicht so trivial. Das Erstellen des App Service-Plans usw. ist durchaus machbar. Aber die Bereitstellung des Funktionscodes oder einer neuen Version des Codes erfordert in der Regel die Verwendung der cli oder die Bereitstellungsschritte von Azure Devops. In diesem Blogpost erkläre ich Ihnen, wie Sie diese Abhängigkeiten beseitigen und alles über Terraform bereitstellen können.

Optionen für die Bereitstellung

Eine der Bereitstellungsoptionen, die Azure Function bietet, ist die Verwendung von WEBSITE_RUN_FROM_PACKAGE. Dies ist eine App-Einstellung, die es ermöglicht, einen Link zu einer Zip-Datei bereitzustellen, die die Azure Function enthält, die Sie ausführen möchten. Die Zip-Datei sollte vollständig in sich geschlossen sein, d.h. alle Abhängigkeiten müssen in ihr enthalten sein. Wir gehen darauf ein, wie Sie das erreichen können.

Die App-Einstellung

resource "azurerm_function_app" "function-app" {
  ...
  identity {
    type = "SystemAssigned"
  }

  app_settings = {
    "WEBSITE_RUN_FROM_PACKAGE" = azurerm_storage_blob.storage_blob_function.url
  }
}

Ich beginne mit der Bereitstellung der Funktion selbst (ich habe den größten Teil des Codes weggelassen, aber Sie finden ihn im Github Repo hier). Ich gebe die für eine Datei an, die in einem Speicherkonto gespeichert ist. Außerdem wollen wir eine verwaltete Identität verwenden, um auf diese Datei zugreifen zu können, daher die SystemAssigned Identität.

Erstellen des Speicherkontos

resource "azurerm_storage_account" "storage_account_function" {
  ...
}

resource "azurerm_storage_container" "storage_container_function" {
  name                 = "function-releases"
  storage_account_name = azurerm_storage_account.storage_account_function.name
}

resource "azurerm_role_assignment" "role_assignment_storage" {
  scope                            = azurerm_storage_account.storage_account_function.id
  role_definition_name             = "Storage Blob Data Contributor"
  principal_id                     = azurerm_function_app.function-app.identity.0.principal_id
}

Das Speicherkonto ist nichts Besonderes, wir brauchen nur einen Ort, um den Code zu speichern, den wir in der Funktion ausführen möchten. Der Code wird in einem separaten Speichercontainer (namens function-releases) abgelegt. Und wir geben der verwalteten Identität die Berechtigung, die Zip-Datei herunterzuladen. In diesem Beispiel habe ich Storage Blob Data Contributor verwendet, da ich dasselbe Speicherkonto auch für die Speicherung des Status der Eventhub-Offsets usw. verwende und daher die Möglichkeit haben muss, Daten zu schreiben.

Hochladen der Zip-Datei


resource "azurerm_storage_blob" "storage_blob_function" {
  name                   = "functions-${substr(data.archive_file.function.output_md5, 0, 6)}.zip"
  storage_account_name   = azurerm_storage_account.storage_account_function.name
  storage_container_name = azurerm_storage_container.storage_container_function.name
  type                   = "Block"
  content_md5            = data.archive_file.function.output_md5
  source                 = "${path.module}/functions.zip"
}

Der Speichercontainer ist fertig, und der nächste Schritt ist das Hochladen der Zip-Datei. Einige Dinge, die Sie beachten sollten, sind der eindeutige Name der Datei. Ich verwende den md5-Hash der Zip-Datei, damit sich der Dateiname ändert, wenn sich der Inhalt der Zip-Datei ändert. So kann die Azure Function-Laufzeitumgebung leichter erkennen, dass sie den Code neu laden muss.

Außerdem musste ich die content_md5 angeben, damit Terraform weiß, dass es das Archiv neu hochladen muss.

Erstellen des Archivs

data "archive_file" "function" {
  type        = "zip"
  source_dir  = "${path.module}/functions"
  output_path = "${path.module}/functions.zip"

  depends_on = [null_resource.pip]
}

Um die Zip-Datei zu erstellen, verwende ich einen Terraform-Anbieter. Das funktioniert perfekt. Wenn sich die Daten im source_dir ändern, wird eine neue Zipdatei erstellt.

Abhängigkeiten einbeziehen


resource "null_resource" "pip" {
  triggers = {
    requirements_md5 = "${filemd5("${path.module}/functions/requirements.txt")}"
  }
  provisioner "local-exec" {    
    command = "pip install --target='.python_packages/lib/site-packages' -r requirements.txt"
    working_dir = "${path.module}/functions"
  }
}

Wie ich bereits sagte, muss die Zip-Datei in sich geschlossen sein, d.h. alle Abhängigkeiten müssen enthalten sein. Diese null_resource tut genau das. Ich verwende eine gezielte pip-Installation in den Ordner , der von der Azure-Funktion verwendet wird, um zusätzliche Pakete zu laden. Der Auslöser sorgt dafür, dass pip erneut ausgeführt wird, wenn sich die Datei requirements.txt ändert.

Eines sollten Sie hier beachten. Die Python-Version Ihrer lokalen Pip und die Version, die Sie bei der Bereitstellung der Azure-Funktion angeben, müssen identisch sein.

Schlussbemerkungen

Das war's also, eine vollständige Bereitstellung einer Azure-Funktion über Terraform. Es sind keine weiteren Schritte erforderlich. Die Ausführung von pip und die Neuerstellung der Zip-Datei erfolgt nur, wenn sich der tatsächliche Code ändert, so dass die Neubereitstellung in der Regel sehr schnell erfolgt.

Ein vollständiges Beispiel für diese Pipeline + zwei kleine Funktionen, die ein EventHub-Thema veröffentlichen/anhören, finden Sie auf github. Wenn Sie Anmerkungen haben, öffnen Sie einen Eintrag im Github-Repository, und ich werde mir ansehen, ob wir den Terraform-Code für Ihren Anwendungsfall korrigieren können.

Contact

Let’s discuss how we can support your journey.