Terraform module for deploying Materialize on Azure with all required infrastructure components.
This module sets up:
- AKS cluster for Materialize workloads
- Azure Database for PostgreSQL Flexible Server for metadata storage
- Azure Blob Storage for persistence
- Required networking and security configurations
- Managed identities with proper RBAC permissions
Warning
This module is intended for demonstration/evaluation purposes as well as for serving as a template when building your own production deployment of Materialize.
This module should not be directly relied upon for production deployments: future releases of the module will contain breaking changes. Instead, to use as a starting point for your own production deployment, either:
- Fork this repo and pin to a specific version, or
- Use the code as a reference when developing your own deployment.
The module has been tested with:
- AKS version 1.28
- PostgreSQL 15
- terraform-helm-materialize v0.1.12 (Materialize Operator v25.1.7)
This module requires active Azure credentials in your environment, either set up through environment variables containing the required keys or by logging in with the Azure CLI using:
az loginYou also need to set an Azure subscription ID in the subscription_id variable or set the ARM_SUBSCRIPTION_ID environment variable, eg:
export ARM_SUBSCRIPTION_ID="your-subscription-id"Additionally, this module runs a Python script to generate Azure SAS tokens for the storage account. This requires Python 3.12 or greater.
Before running the module, ensure you have the necessary Python dependencies installed:
-
Install Python 3.12+ if you haven't already.
-
Install the required dependencies using
pip:pip install -r requirements.txt
Or alternatively, you can install the dependencies manually:
pip install azure-identity azure-storage-blob azure-keyvault-secrets azure-mgmt-storage
If you are using a virtual environment, you can set it up as follows:
python -m venv venv
source venv/bin/activate # On macOS/Linux
venv\Scripts\activate # On Windows
pip install -r requirements.txtThis will install the required Python packages in a virtual environment.
This module requires an existing Azure Resource Group. You can either:
-
Create one with Terraform before running this module:
resource "azurerm_resource_group" "materialize" { name = var.resource_group_name location = var.location }
Then set the
resource_group_namevariable in yourterraform.tfvarsfile:resource_group_name = "your-desired-rg-name"
-
Use an existing one by just setting the name in your
terraform.tfvarsfile:resource_group_name = "your-existing-rg"
The materialize_instances variable is a list of objects that define the configuration for each Materialize instance.
Optional list of additional command-line arguments to pass to the environmentd container. This can be used to override default system parameters or enable specific features.
environmentd_extra_args = [
"--system-parameter-default=max_clusters=1000",
"--system-parameter-default=max_connections=1000",
"--system-parameter-default=max_tables=1000",
]These flags configure default limits for clusters, connections, and tables. You can provide any supported arguments here.
| Name | Version |
|---|---|
| terraform | >= 1.0 |
| azuread | >= 2.45.0 |
| azurerm | >= 3.75.0 |
| deepmerge | ~> 1.0 |
| helm | ~> 2.0 |
| kubernetes | ~> 2.0 |
No providers.
| Name | Source | Version |
|---|---|---|
| aks | ./modules/aks | n/a |
| certificates | ./modules/certificates | n/a |
| database | ./modules/database | n/a |
| load_balancers | ./modules/load_balancers | n/a |
| materialize_nodepool | ./modules/nodepool | n/a |
| networking | ./modules/networking | n/a |
| operator | github.com/MaterializeInc/terraform-helm-materialize | v0.1.36 |
| storage | ./modules/storage | n/a |
No resources.
| Name | Description | Type | Default | Required |
|---|---|---|---|---|
| cert_manager_chart_version | Version of the cert-manager helm chart to install. | string |
"v1.17.1" |
no |
| cert_manager_install_timeout | Timeout for installing the cert-manager helm chart, in seconds. | number |
300 |
no |
| cert_manager_namespace | The name of the namespace in which cert-manager is or will be installed. | string |
"cert-manager" |
no |
| database_config | Azure Database for PostgreSQL configuration | object({ |
n/a | yes |
| helm_chart | Chart name from repository or local path to chart. For local charts, set the path to the chart directory. | string |
"materialize-operator" |
no |
| helm_values | Additional Helm values to merge with defaults | any |
{} |
no |
| install_cert_manager | Whether to install cert-manager. | bool |
true |
no |
| install_materialize_operator | Whether to install the Materialize operator | bool |
true |
no |
| location | The location where resources will be created | string |
"eastus2" |
no |
| materialize_instances | Configuration for Materialize instances | list(object({ |
[] |
no |
| materialize_node_pool_disk_size_gb | Disk size in GB for Materialize node pool | number |
100 |
no |
| materialize_node_pool_max_nodes | Maximum number of nodes in Materialize node pool | number |
4 |
no |
| materialize_node_pool_min_nodes | Minimum number of nodes in Materialize node pool | number |
1 |
no |
| materialize_node_pool_vm_size | VM size for Materialize node pool | string |
"Standard_E4pds_v6" |
no |
| namespace | Namespace for all resources, usually the organization or project name | string |
"materialize" |
no |
| network_config | Network configuration for the AKS cluster | object({ |
n/a | yes |
| operator_namespace | Namespace for the Materialize operator | string |
"materialize" |
no |
| operator_version | Version of the Materialize operator to install | string |
null |
no |
| orchestratord_version | Version of the Materialize orchestrator to install | string |
null |
no |
| prefix | Prefix to be used for resource names | string |
"materialize" |
no |
| resource_group_name | The name of an existing resource group to use | string |
n/a | yes |
| system_node_pool_disk_size_gb | Disk size in GB for system node pool | number |
100 |
no |
| system_node_pool_max_nodes | Maximum number of nodes in system node pool | number |
4 |
no |
| system_node_pool_min_nodes | Minimum number of nodes in system node pool | number |
2 |
no |
| system_node_pool_vm_size | VM size for system node pool | string |
"Standard_D2ps_v6" |
no |
| tags | Tags to apply to all resources | map(string) |
{} |
no |
| use_local_chart | Whether to use a local chart instead of one from a repository | bool |
false |
no |
| use_self_signed_cluster_issuer | Whether to install and use a self-signed ClusterIssuer for TLS. To work around limitations in Terraform, this will be treated as false if no materialize instances are defined. |
bool |
true |
no |
| Name | Description |
|---|---|
| aks_cluster | AKS cluster details |
| connection_strings | Formatted connection strings for Materialize |
| database | Azure Database for PostgreSQL details |
| identities | Managed Identity details |
| kube_config | The kube_config for the AKS cluster |
| kube_config_raw | The kube_config for the AKS cluster |
| load_balancer_details | Details of the Materialize instance load balancers. |
| network | Network details |
| operator | Materialize operator details |
| resource_group_name | n/a |
| storage | Azure Storage Account details |
The AKS cluster can be accessed using the kubectl command-line tool. To authenticate with the cluster, run the following command:
az aks get-credentials --resource-group $(terraform output -raw resource_group_name) --name $(terraform output -json aks_cluster | jq -r '.name')This command retrieves the AKS cluster credentials and merges them into the ~/.kube/config file. You can now interact with the AKS cluster using kubectl.
By default, two LoadBalancer Services are created for each Materialize instance:
- One for balancerd, listening on:
- Port 6875 for SQL connections to the database.
- Port 6876 for HTTP(S) connections to the database.
- One for the web console, listening on:
- Port 8080 for HTTP(S) connections.
The IP addresses of these load balancers will be in the terraform output as load_balancer_details.
TLS support is provided by using cert-manager and a self-signed ClusterIssuer.
More advanced TLS support using user-provided CAs or per-Materialize Issuers are out of scope for this Terraform module. Please refer to the cert-manager documentation for detailed guidance on more advanced usage.
You must upgrade to at least v0.7.x before upgrading to v0.8.x of this terraform code.
Breaking changes:
- The system node pool is renamed and significantly modified, forcing a recreation.
- Openebs is removed, and with it all support for lgalloc, our legacy spill to disk mechanism.
This is an intermediate version to handle some changes that must be applied in stages. It is recommended to upgrade to v0.8.x after upgrading to this version.
Breaking changes:
- Swap is enabled by default.
- Support for lgalloc, our legacy spill to disk mechanism, is deprecated, and will be removed in the next version.
- We now always use two node pools, one for system workloads and one for Materialize workloads.
- Variables for configuring these node pools have been renamed, so they may be configured separately.
To avoid downtime when upgrading to future versions, you must perform a rollout at this version.
- Ensure your
environmentd_versionis at leastv26.0.0. - Update your
request_rollout(andforce_rolloutif already at the correctenvironmentd_version). - Run
terraform apply.
You must upgrade to at least v0.6.x before upgrading to v0.7.0 of this terraform code.
It is strongly recommended to have enabled swap on v0.6.x before upgrading to v0.7.0 or higher.
We recommend upgrading to at least v0.5.10 before upgrading to v0.6.x of this terraform code.
To use swap:
- Set
swap_enabledtotrue. - Ensure your
environmentd_versionis at leastv26.0.0. - Update your
request_rollout(andforce_rolloutif already at the correctenvironmentd_version). - Run
terraform apply.
This will create a new node group configured for swap, and migrate your clusterd pods there.
This version is missing the updated helm chart. Skip this version, go to v0.6.1.
We now install cert-manager and configure a self-signed ClusterIssuer by default.
Due to limitations in Terraform, it cannot plan Kubernetes resources using CRDs that do not exist yet. We have worked around this for new users by only generating the certificate resources when creating Materialize instances that use them, which also cannot be created on the first run.
For existing users upgrading Materialize instances not previously configured for TLS:
- Leave
install_cert_managerat its default oftrue. - Set
use_self_signed_cluster_issuertofalse. - Run
terraform apply. This will install cert-manager and its CRDs. - Set
use_self_signed_cluster_issuerback totrue(the default). - Update the
request_rolloutfield of the Materialize instance. - Run
terraform apply. This will generate the certificates and configure your Materialize instance to use them.