Architecting Azure SQL Infrastructure via Terraform: From PaaS to IaaS

The deployment of database infrastructure has evolved from manual scripts and portal-based configuration to Infrastructure as Code (IaC). In the Azure ecosystem, the SQL offering is diverse, ranging from fully managed Platform as a Service (PaaS) options like Azure SQL Database and Azure SQL Managed Instance to Infrastructure as a Service (IaaS) deployments via SQL Server on Azure Virtual Machines. Using Terraform to manage these resources provides a repeatable, version-controlled method to provision environments, ensuring that production, staging, and development tiers remain synchronized without the risk of human error associated with "one-off" scripts.

Understanding Azure SQL Deployment Models

Before implementing Terraform configurations, it is critical to distinguish between the three primary ways to deploy SQL Server in Azure. The choice of resource determines the Terraform provider resources used and the level of management overhead.

Azure SQL Database (PaaS)

Azure SQL Database is a fully managed relational database service. In this model, Microsoft handles the heavy lifting of patching, backups, and high availability. It is designed for cloud-native applications and offers a "single database" option, which is the quickest and simplest deployment path. Within a SQL Database server, administrators can choose between:

  • Provisioned Compute: A model where a fixed amount of CPU and memory is pre-allocated.
  • Serverless Compute: A model that automatically scales compute based on workload demand and can pause during periods of inactivity.

Azure SQL Managed Instance (PaaS)

Managed Instances provide a middle ground between a single database and a full VM. They offer nearly full SQL Server compatibility but remain managed services. Deploying these via Terraform requires more complex networking configurations, as they must be deployed within a virtual network (VNet) and a dedicated subnet associated with a route table and a network security group (NSG).

SQL Server on Azure VM (IaaS)

Deploying a SQL Server VM gives the user full control over the operating system and the SQL Server instance. This is essential for legacy applications that require OS-level access or specific versions of SQL Server not supported in PaaS. This method requires significant networking overhead, including the configuration of host VMs and virtual network interfaces.

Core Terraform Provider Configuration

To interact with Azure SQL resources, Terraform requires the azurerm provider. For a standard deployment, it is recommended to use version 3.0 or higher. Additionally, the random provider is frequently utilized to generate secure, non-hardcoded credentials for database administrators.

The configuration is typically split across files to maintain organization. A versions.tf or providers.tf file ensures that the environment is using the correct binary versions to avoid state corruption during upgrades.

```hcl
terraform {
requiredversion = ">= 1.5.0"
required
providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 3.80"
}
random = {
source = "hashicorp/random"
version = "~> 3.5"
}
}
}

provider "azurerm" {
features {}
}
```

Deploying Azure SQL Database (PaaS)

The deployment of a PaaS SQL Database follows a hierarchical dependency: Resource Group $\rightarrow$ Logical SQL Server $\rightarrow$ SQL Database.

The Logical SQL Server

The azurerm_mssql_server resource acts as the management container for one or more databases. It handles authentication and authorization and serves as the logical grouping for the databases.

A critical security consideration during the server definition is the handling of administrator credentials. If SQL Authentication is used, the username and password are stored in plain text within the Terraform state file. To mitigate this risk, industry experts recommend using Microsoft Entra ID (formerly Azure Active Directory) for administration.

```hcl
resource "azurermmssqlserver" "az-sqlServer-01" {
name = var.azSqlServer01-Name
location = azurermresourcegroup.rg-deployment-core.location
resourcegroupname = azurermresourcegroup.rg-deployment-core.name
version = "12.0"

azureadadministrator {
login
username = var.azSqlServer01-aadAdminName
objectid = var.azSqlServer01-aadObjectId
azuread
authentication_only = true
}
}
```

The SQL Database Resource

Once the server is provisioned, the azurerm_mssql_database resource is used to create the actual data store. This allows for the definition of collation, pricing tiers, and compute models.

Feature Provisioned Tier Serverless Tier
Resource Allocation Fixed CPU/Memory Dynamic Scaling
Cost Model Hourly/Monthly Fixed Per-second billing
Availability High (Configurable) High (Auto-scaling)
Primary Use Case Predictable Workloads Unpredictable/Intermittent Workloads

Advanced Configuration and Security

A production-ready Azure SQL deployment requires more than just a server and a database. It requires a security perimeter and auditing.

Firewall Rules and Private Endpoints

By default, Azure SQL Servers block all access. Terraform can be used to define azurerm_mssql_firewall_rule resources to allow specific IP addresses or to enable Azure services to access the server. For higher security, Private Endpoints and Private DNS Zones are used to ensure traffic never leaves the Azure backbone network.

Secure Password Generation

To avoid hardcoding passwords, the random_password resource is utilized. This password can then be passed into the server resource and subsequently stored in an Azure Key Vault for retrieval by the application.

hcl resource "random_password" "admin_password" { length = 16 special = true override_complexity = true }

Database Initialization

Certain Terraform modules support the execution of custom SQL scripts during the initial deployment phase. This allows for the creation of schemas, tables, and stored procedures immediately after the database resource is provisioned.

Deploying SQL Server on Azure VM (IaaS)

Deploying a SQL Server VM is significantly more complex than a PaaS deployment because it involves the compute and networking layers.

Networking Requirements

Unlike a single SQL Database, a VM requires:
- A Virtual Network (VNet).
- A Subnet.
- A Network Interface Card (NIC).
- A Network Security Group (NSG) to control ingress and egress traffic (e.g., opening port 1433 for SQL).

Configuration Workflow

The deployment typically involves creating a networking.tf file to isolate the VNet and subnet logic from the main.tf file where the VM and SQL software extensions are defined. This modularity allows the networking team to manage the VNet independently of the database administrator managing the VM.

Azure SQL Managed Instance (MI) Infrastructure

Managed Instances are designed for those who need the operational ease of PaaS but the feature set of a full SQL Server. The Terraform deployment for MI is distinct because it is natively integrated into a VNet.

Terraform Deployment Logic

The process involves:
1. Defining the VNet and a dedicated subnet.
2. Associating the subnet with a Route Table to manage traffic routing.
3. Creating a Network Security Group to protect the instance.
4. Deploying the azurerm_mssql_virtual_cluster and azurerm_mssql_managed_instance resources.

Comparison of Azure SQL Deployment Options via Terraform

The following table provides a detailed comparison of the resources and configurations required for each deployment type.

Requirement Azure SQL Database SQL Managed Instance SQL Server on VM
Terraform Resource azurerm_mssql_database azurerm_mssql_managed_instance azurerm_windows_virtual_machine
Network Complexity Low (Firewall/Private Link) High (VNet/Subnet/Route Table) High (VNet/NIC/NSG)
OS Access None None Full Administrator
Management Effort Low (Microsoft Managed) Medium (Partially Managed) High (User Managed)
Provisioning Speed Fast Slow Medium
Deployment Method Logical Server $\rightarrow$ DB VNet $\rightarrow$ Subnet $\rightarrow$ MI VNet $\rightarrow$ VM $\rightarrow$ SQL Ext

Lifecycle Management and Execution

Terraform provides powerful tools to visualize and manage the lifecycle of the SQL infrastructure.

The Planning Phase

Using the terraform plan command, operators can preview infrastructure changes. This is crucial for database deployments where an accidental change to a property (like changing the server name) could trigger a "Destroy and Recreate" action, leading to catastrophic data loss.

Visualizing Dependencies

The terraform graph command generates a digraph of the resource dependencies. This allows architects to verify that the resource group is created before the server, and the server is created before the database.

Example of a dependency chain in a Terraform graph:
- azurerm_resource_group.rg-deployment-core $\rightarrow$ azurerm_mssql_server.az-sqlServer-01 $\rightarrow$ azurerm_mssql_database.az-sqldb-01

Implementation Best Practices

To ensure stability and security, the following patterns should be implemented in all Terraform Azure SQL projects:

  • Use Variable Files: Store environment-specific values (e.g., eastus vs westus) in .tfvars files.
  • State Management: Use a remote backend (such as Azure Blob Storage) to store the Terraform state file, enabling team collaboration and locking.
  • Resource Naming: Utilize the random_pet resource or a consistent naming convention (e.g., rg-sql-production) to avoid naming collisions in global Azure namespaces.
  • Least Privilege: Assign the Terraform service principal the minimum RBAC roles required to create the resources, rather than granting Global Administrator rights.
  • Entra ID Integration: Prioritize azuread_administrator over SQL authentication to keep secrets out of the state file.

Conclusion

The transition to managing Azure SQL infrastructure via Terraform fundamentally changes how databases are deployed and maintained. By utilizing a PaaS approach with Azure SQL Database, organizations can achieve rapid deployment and minimal overhead, leveraging serverless compute to optimize costs. For those requiring deep integration and full SQL feature parity, Azure SQL Managed Instance and SQL Server on VMs provide the necessary control, albeit with significantly higher networking complexity involving VNets and NSGs.

The strategic use of the azurerm provider, combined with a strict adherence to security practices—such as avoiding hardcoded passwords via the random provider and favoring Microsoft Entra ID authentication—ensures that the infrastructure is not only repeatable but also secure. Ultimately, the ability to graph dependencies and plan changes before execution mitigates the risks inherent in database management, making Terraform an essential tool for any modern Azure data architecture.

Sources

  1. How to Create Azure SQL Database in Terraform
  2. Terraform Foundation AzureRM MSSQL DB
  3. Terraform Azure SQL Server VM
  4. Create Azure SQL Managed Instance with Terraform
  5. Deploy Azure DB with Terraform
  6. Create Azure SQL Single Database with Terraform Quickstart

Related Posts