From 0ba0adfdbc626fcfcdebc215d2e763f24d0d7b5b Mon Sep 17 00:00:00 2001 From: Bobby Iliev Date: Fri, 20 Dec 2024 20:57:52 +0200 Subject: [PATCH 01/14] Make VPC creation optional --- README.md | 7 +++++-- main.tf | 13 +++++++++---- modules/networking/main.tf | 2 ++ modules/networking/variables.tf | 6 ++++++ variables.tf | 18 ++++++++++++++++++ 5 files changed, 40 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index def3361..7f3588c 100644 --- a/README.md +++ b/README.md @@ -17,12 +17,13 @@ The module has been tested with: | [aws](#requirement\_aws) | ~> 5.0 | | [helm](#requirement\_helm) | ~> 2.0 | | [kubernetes](#requirement\_kubernetes) | ~> 2.0 | +| [random](#requirement\_random) | ~> 3.0 | ## Providers | Name | Version | |------|---------| -| [aws](#provider\_aws) | 5.76.0 | +| [aws](#provider\_aws) | 5.81.0 | ## Modules @@ -52,10 +53,10 @@ The module has been tested with: | [bucket\_force\_destroy](#input\_bucket\_force\_destroy) | Enable force destroy for the S3 bucket | `bool` | `false` | no | | [bucket\_lifecycle\_rules](#input\_bucket\_lifecycle\_rules) | List of lifecycle rules for the S3 bucket |
list(object({
id = string
enabled = bool
prefix = string
transition_days = number
transition_storage_class = string
expiration_days = number
noncurrent_version_expiration_days = number
}))
|
[
{
"enabled": true,
"expiration_days": 365,
"id": "cleanup",
"noncurrent_version_expiration_days": 90,
"prefix": "",
"transition_days": 90,
"transition_storage_class": "STANDARD_IA"
}
]
| no | | [bucket\_name](#input\_bucket\_name) | Name of the S3 bucket | `string` | n/a | yes | -| [bucket\_prefix](#input\_bucket\_prefix) | Prefix for the S3 bucket | `string` | `"system"` | no | | [cluster\_enabled\_log\_types](#input\_cluster\_enabled\_log\_types) | List of desired control plane logging to enable | `list(string)` |
[
"api",
"audit",
"authenticator",
"controllerManager",
"scheduler"
]
| no | | [cluster\_name](#input\_cluster\_name) | Name of the EKS cluster | `string` | `"materialize-cluster"` | no | | [cluster\_version](#input\_cluster\_version) | Kubernetes version for the EKS cluster | `string` | `"1.31"` | no | +| [create\_vpc](#input\_create\_vpc) | Controls if VPC should be created (it affects almost all resources) | `bool` | `true` | no | | [database\_name](#input\_database\_name) | Name of the database to create | `string` | `"materialize"` | no | | [database\_password](#input\_database\_password) | Password for the database (should be provided via tfvars or environment variable) | `string` | n/a | yes | | [database\_username](#input\_database\_username) | Username for the database | `string` | `"materialize"` | no | @@ -75,6 +76,8 @@ The module has been tested with: | [mz\_iam\_role\_name](#input\_mz\_iam\_role\_name) | Name of the IAM role for Materialize S3 access (will be prefixed with environment name) | `string` | `"materialize-s3-role"` | no | | [mz\_iam\_service\_account\_name](#input\_mz\_iam\_service\_account\_name) | Name of the IAM user for Materialize service authentication (will be prefixed with environment name) | `string` | `"materialize-user"` | no | | [namespace](#input\_namespace) | Namespace for Materialize resources | `string` | `"materialize-environment"` | no | +| [network\_id](#input\_network\_id) | The ID of the VPC in which resources will be deployed. Only used if create\_vpc is false. | `string` | `""` | no | +| [network\_private\_subnet\_ids](#input\_network\_private\_subnet\_ids) | A list of private subnet IDs in the VPC. Only used if create\_vpc is false. | `list(string)` | `[]` | no | | [node\_group\_ami\_type](#input\_node\_group\_ami\_type) | AMI type for the node group | `string` | `"AL2023_x86_64_STANDARD"` | no | | [node\_group\_capacity\_type](#input\_node\_group\_capacity\_type) | Capacity type for worker nodes (ON\_DEMAND or SPOT) | `string` | `"ON_DEMAND"` | no | | [node\_group\_desired\_size](#input\_node\_group\_desired\_size) | Desired number of worker nodes | `number` | `2` | no | diff --git a/main.tf b/main.tf index abbb229..3e16687 100644 --- a/main.tf +++ b/main.tf @@ -16,8 +16,8 @@ module "eks" { cluster_name = var.cluster_name cluster_version = var.cluster_version - vpc_id = module.networking.vpc_id - private_subnet_ids = module.networking.private_subnet_ids + vpc_id = local.network_id + private_subnet_ids = local.network_private_subnet_ids environment = var.environment node_group_desired_size = var.node_group_desired_size node_group_min_size = var.node_group_min_size @@ -51,8 +51,8 @@ module "database" { database_name = var.database_name database_username = var.database_username multi_az = var.db_multi_az - database_subnet_ids = module.networking.private_subnet_ids - vpc_id = module.networking.vpc_id + database_subnet_ids = local.network_private_subnet_ids + vpc_id = local.network_id eks_security_group_id = module.eks.cluster_security_group_id eks_node_security_group_id = module.eks.node_security_group_id tags = var.tags @@ -60,6 +60,11 @@ module "database" { database_password = var.database_password } +locals { + network_id = var.create_vpc ? module.networking.vpc_id : var.network_id + network_private_subnet_ids = var.create_vpc ? module.networking.private_subnet_ids : var.network_private_subnet_ids +} + resource "aws_cloudwatch_log_group" "materialize" { count = var.enable_monitoring ? 1 : 0 diff --git a/modules/networking/main.tf b/modules/networking/main.tf index a307c43..bd5ff68 100644 --- a/modules/networking/main.tf +++ b/modules/networking/main.tf @@ -2,6 +2,8 @@ module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "~> 5.0" + create_vpc = var.create_vpc + name = var.vpc_name cidr = var.vpc_cidr diff --git a/modules/networking/variables.tf b/modules/networking/variables.tf index b0d1e2a..0a8c1a1 100644 --- a/modules/networking/variables.tf +++ b/modules/networking/variables.tf @@ -1,3 +1,9 @@ +variable "create_vpc" { + description = "Controls if VPC should be created (it affects almost all resources)" + type = bool + default = true +} + variable "vpc_name" { description = "Name of the VPC" type = string diff --git a/variables.tf b/variables.tf index bd4163c..6c5632b 100644 --- a/variables.tf +++ b/variables.tf @@ -16,6 +16,24 @@ variable "tags" { } # Networking Variables +variable "create_vpc" { + description = "Controls if VPC should be created (it affects almost all resources)" + type = bool + default = true +} + +variable "network_id" { + default = "" + description = "The ID of the VPC in which resources will be deployed. Only used if create_vpc is false." + type = string +} + +variable "network_private_subnet_ids" { + default = [] + description = "A list of private subnet IDs in the VPC. Only used if create_vpc is false." + type = list(string) +} + variable "vpc_name" { description = "Name of the VPC" type = string From c740eae8107a23b973702d9e0a6ccb7fdbb683b1 Mon Sep 17 00:00:00 2001 From: Bobby Iliev Date: Sun, 22 Dec 2024 19:39:12 +0200 Subject: [PATCH 02/14] Refactor resource names definitions --- .terraform.lock.hcl | 32 ++++++++-------- examples/simple/main.tf | 17 +++++---- main.tf | 66 ++++++++++++++++++++++++--------- modules/database/main.tf | 12 ++++-- modules/database/variables.tf | 9 ++++- modules/eks/main.tf | 11 ++++-- modules/eks/outputs.tf | 5 +++ modules/eks/variables.tf | 14 +++---- modules/networking/main.tf | 14 ++++--- modules/networking/variables.tf | 20 +++++----- modules/storage/main.tf | 10 ++++- modules/storage/variables.tf | 9 ++++- modules/storage/versions.tf | 4 ++ outputs.tf | 4 +- providers.tf | 2 +- terraform.tfvars.example | 8 ++-- variables.tf | 59 ++++++++--------------------- 17 files changed, 170 insertions(+), 126 deletions(-) diff --git a/.terraform.lock.hcl b/.terraform.lock.hcl index d77d284..ee1045d 100644 --- a/.terraform.lock.hcl +++ b/.terraform.lock.hcl @@ -2,25 +2,25 @@ # Manual edits may be lost in future updates. provider "registry.terraform.io/hashicorp/aws" { - version = "5.82.1" + version = "5.82.2" constraints = ">= 4.33.0, ~> 5.0, >= 5.46.0, >= 5.59.0, >= 5.62.0, >= 5.81.0" hashes = [ - "h1:QTOtDMehUfiD3wDbbDuXYuTqGgLDkKK9Agkd5NCUEic=", - "zh:0fde8533282973f1f5d33b2c4f82d962a2c78860d39b42ac20a9ce399f06f62c", - "zh:1fd1a252bffe91668f35be8eac4e0a980f022120254eae1674c3c05049aff88a", - "zh:31bbd380cd7d74bf9a8c961fc64da4222bed40ffbdb27b011e637fa8b2d33641", - "zh:333ee400cf6f62fa199dc1270bf8efac6ffe56659f86918070b8351b8636e03b", - "zh:42ea9fee0a152d344d548eab43583299a13bcd73fae9e53e7e1a708720ac1315", - "zh:4b78f25a8cda3316eb56aa01909a403ec2f325a2eb0512c9a73966068c26cf29", - "zh:5e9cf9a275eda8f7940a41e32abe0b92ba76b5744def4af5124b343b5f33eb94", - "zh:6a46c8630c16b9e1338c2daed6006118db951420108b58b8b886403c69317439", - "zh:6efe11cf1a01f98a8d8043cdcd8c0ee5fe93a0e582c2b69ebb73ea073f5068c3", - "zh:88ab5c768c7d8133dab94eff48071e764424ad2b7cfeee5abe6d5bb16e4b85c6", + "h1:ce6Dw2y4PpuqAPtnQ0dO270dRTmwEARqnfffrE1VYJ8=", + "zh:0262fc96012fb7e173e1b7beadd46dfc25b1dc7eaef95b90e936fc454724f1c8", + "zh:397413613d27f4f54d16efcbf4f0a43c059bd8d827fe34287522ae182a992f9b", + "zh:436c0c5d56e1da4f0a4c13129e12a0b519d12ab116aed52029b183f9806866f3", + "zh:4d942d173a2553d8d532a333a0482a090f4e82a2238acf135578f163b6e68470", + "zh:624aebc549bfbce06cc2ecfd8631932eb874ac7c10eb8466ce5b9a2fbdfdc724", "zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425", - "zh:a614beb312574342b27dbc34d65b450997f63fa3e948d0d30f441e4f69337380", - "zh:c1f486e27130610a9b64cacb0bd928009c433d62b3be515488185e6467b4aa1f", - "zh:dccd166e89e1a02e7ce658df3c42d040edec4b09c6f7906aa5743938518148b1", - "zh:e75a3ae0fb42b7ea5a0bb5dffd8f8468004c9700fcc934eb04c264fda2ba9984", + "zh:9e632dee2dfdf01b371cca7854b1ec63ceefa75790e619b0642b34d5514c6733", + "zh:a07567acb115b60a3df8f6048d12735b9b3bcf85ec92a62f77852e13d5a3c096", + "zh:ab7002df1a1be6432ac0eb1b9f6f0dd3db90973cd5b1b0b33d2dae54553dfbd7", + "zh:bc1ff65e2016b018b3e84db7249b2cd0433cb5c81dc81f9f6158f2197d6b9fde", + "zh:bcad84b1d767f87af6e1ba3dc97fdb8f2ad5de9224f192f1412b09aba798c0a8", + "zh:cf917dceaa0f9d55d9ff181b5dcc4d1e10af21b6671811b315ae2a6eda866a2a", + "zh:d8e90ecfb3216f3cc13ccde5a16da64307abb6e22453aed2ac3067bbf689313b", + "zh:d9054e0e40705df729682ad34c20db8695d57f182c65963abd151c6aba1ab0d3", + "zh:ecf3a4f3c57eb7e89f71b8559e2a71e4cdf94eea0118ec4f2cb37e4f4d71a069", ] } diff --git a/examples/simple/main.tf b/examples/simple/main.tf index f897ef0..52da570 100644 --- a/examples/simple/main.tf +++ b/examples/simple/main.tf @@ -7,11 +7,10 @@ module "materialize_infrastructure" { # source = "git::https://github.com/MaterializeInc/terraform-aws-materialize.git" source = "../../" - # Basic settings - environment = "dev" - vpc_name = "materialize-simple" - cluster_name = "materialize-eks-simple" - mz_iam_service_account_name = "materialize-user" + # The namespace and environment variables are used to construct the names of the resources + # e.g. ${namespace}-${environment}-storage, ${namespace}-${environment}-db etc. + namespace = "simple-mz-tf" + environment = "dev" # VPC Configuration vpc_cidr = "10.0.0.0/16" @@ -21,7 +20,8 @@ module "materialize_infrastructure" { single_nat_gateway = true # EKS Configuration - cluster_version = "1.31" + cluster_version = "1.31" + # node_group_instance_types = ["m6g.medium"] node_group_instance_types = ["r5.xlarge"] node_group_desired_size = 2 node_group_min_size = 1 @@ -30,14 +30,12 @@ module "materialize_infrastructure" { enable_cluster_creator_admin_permissions = true # Storage Configuration - bucket_name = "materialize-simple-storage-${random_id.suffix.hex}" enable_bucket_versioning = true enable_bucket_encryption = true bucket_force_destroy = true # Database Configuration database_password = var.database_password - db_identifier = "materialize-simple" postgres_version = "15" db_instance_class = "db.t3.large" db_allocated_storage = 20 @@ -57,6 +55,7 @@ module "materialize_infrastructure" { } } +<<<<<<< HEAD variable "database_password" { description = "Password for the database (should be provided via tfvars or environment variable)" type = string @@ -68,6 +67,8 @@ resource "random_id" "suffix" { byte_length = 4 } +======= +>>>>>>> be3d603 (Refactor resource names definitions) # Outputs output "vpc_id" { description = "VPC ID" diff --git a/main.tf b/main.tf index 3e16687..d596000 100644 --- a/main.tf +++ b/main.tf @@ -1,50 +1,67 @@ module "networking" { source = "./modules/networking" - vpc_name = var.vpc_name + # The namespace and environment variables are used to construct the names of the resources + # e.g. ${namespace}-${environment}-vpc + namespace = var.namespace + environment = var.environment + vpc_cidr = var.vpc_cidr availability_zones = var.availability_zones private_subnet_cidrs = var.private_subnet_cidrs public_subnet_cidrs = var.public_subnet_cidrs - cluster_name = var.cluster_name single_nat_gateway = var.single_nat_gateway - tags = var.tags + + tags = local.common_tags } module "eks" { source = "./modules/eks" - cluster_name = var.cluster_name + # The namespace and environment variables are used to construct the names of the resources + # e.g. ${namespace}-${environment}-eks + namespace = var.namespace + environment = var.environment + cluster_version = var.cluster_version vpc_id = local.network_id private_subnet_ids = local.network_private_subnet_ids - environment = var.environment node_group_desired_size = var.node_group_desired_size node_group_min_size = var.node_group_min_size node_group_max_size = var.node_group_max_size node_group_instance_types = var.node_group_instance_types node_group_ami_type = var.node_group_ami_type - tags = var.tags cluster_enabled_log_types = var.cluster_enabled_log_types node_group_capacity_type = var.node_group_capacity_type enable_cluster_creator_admin_permissions = var.enable_cluster_creator_admin_permissions + + tags = local.common_tags } module "storage" { source = "./modules/storage" - bucket_name = var.bucket_name - tags = var.tags + # The namespace and environment variables are used to construct the names of the resources + # e.g. ${namespace}-${environment}-storage + namespace = var.namespace + environment = var.environment + bucket_lifecycle_rules = var.bucket_lifecycle_rules enable_bucket_encryption = var.enable_bucket_encryption enable_bucket_versioning = var.enable_bucket_versioning bucket_force_destroy = var.bucket_force_destroy + + tags = local.common_tags } module "database" { source = "./modules/database" - db_identifier = var.db_identifier + # The namespace and environment variables are used to construct the names of the resources + # e.g. ${namespace}-${environment}-db + namespace = var.namespace + environment = var.environment + postgres_version = var.postgres_version instance_class = var.db_instance_class allocated_storage = var.db_allocated_storage @@ -55,27 +72,38 @@ module "database" { vpc_id = local.network_id eks_security_group_id = module.eks.cluster_security_group_id eks_node_security_group_id = module.eks.node_security_group_id - tags = var.tags max_allocated_storage = var.db_max_allocated_storage database_password = var.database_password + + tags = local.common_tags } locals { network_id = var.create_vpc ? module.networking.vpc_id : var.network_id network_private_subnet_ids = var.create_vpc ? module.networking.private_subnet_ids : var.network_private_subnet_ids + + # Common tags that apply to all resources + common_tags = merge( + var.tags, + { + Namespace = var.namespace + Environment = var.environment + ManagedBy = "terraform" + } + ) } resource "aws_cloudwatch_log_group" "materialize" { count = var.enable_monitoring ? 1 : 0 - name = "/aws/${var.log_group_name_prefix}/${var.cluster_name}/${var.environment}" + name = "/aws/${var.log_group_name_prefix}/${module.eks.cluster_name}/${var.environment}" retention_in_days = var.metrics_retention_days tags = var.tags } resource "aws_iam_user" "materialize" { - name = "${var.environment}-${var.mz_iam_service_account_name}" + name = "${local.name_prefix}-mz-user" } resource "aws_iam_access_key" "materialize_user" { @@ -83,7 +111,7 @@ resource "aws_iam_access_key" "materialize_user" { } resource "aws_iam_user_policy" "materialize_s3" { - name = var.mz_iam_policy_name + name = "${local.name_prefix}-mz-s3-policy" user = aws_iam_user.materialize.name policy = jsonencode({ @@ -107,7 +135,7 @@ resource "aws_iam_user_policy" "materialize_s3" { } resource "aws_iam_role" "materialize_s3" { - name = "${var.environment}-${var.mz_iam_role_name}" + name = "${local.name_prefix}-mz-role" # Trust policy allowing EKS to assume this role assume_role_policy = jsonencode({ @@ -120,7 +148,7 @@ resource "aws_iam_role" "materialize_s3" { } Action = "sts:AssumeRoleWithWebIdentity" Condition = { - StringEquals = { + StringLike = { "${trimprefix(module.eks.cluster_oidc_issuer_url, "https://")}:sub" : "system:serviceaccount:*:*", "${trimprefix(module.eks.cluster_oidc_issuer_url, "https://")}:aud" : "sts.amazonaws.com" } @@ -129,7 +157,7 @@ resource "aws_iam_role" "materialize_s3" { ] }) - tags = var.tags + tags = local.common_tags depends_on = [ module.eks @@ -137,7 +165,7 @@ resource "aws_iam_role" "materialize_s3" { } resource "aws_iam_role_policy" "materialize_s3" { - name = var.mz_iam_policy_name + name = "${local.name_prefix}-mz-role-policy" role = aws_iam_role.materialize_s3.id policy = jsonencode({ @@ -159,3 +187,7 @@ resource "aws_iam_role_policy" "materialize_s3" { ] }) } + +locals { + name_prefix = "${var.namespace}-${var.environment}" +} diff --git a/modules/database/main.tf b/modules/database/main.tf index a9380c1..e03acb9 100644 --- a/modules/database/main.tf +++ b/modules/database/main.tf @@ -1,8 +1,12 @@ +locals { + name_prefix = "${var.namespace}-${var.environment}" +} + module "db" { source = "terraform-aws-modules/rds/aws" version = "~> 6.0" - identifier = var.db_identifier + identifier = "${local.name_prefix}-db" engine = "postgres" engine_version = var.postgres_version @@ -25,7 +29,7 @@ module "db" { subnet_ids = var.database_subnet_ids vpc_security_group_ids = [aws_security_group.database.id] create_db_subnet_group = true - db_subnet_group_name = "${var.db_identifier}-subnet-group" + db_subnet_group_name = "${local.name_prefix}-db-subnet" maintenance_window = var.maintenance_window backup_window = var.backup_window @@ -38,7 +42,7 @@ module "db" { } resource "aws_security_group" "database" { - name_prefix = "${var.db_identifier}-sg-" + name_prefix = "${local.name_prefix}-sg-" vpc_id = var.vpc_id ingress { @@ -65,7 +69,7 @@ resource "aws_security_group" "database" { } tags = merge(var.tags, { - Name = "${var.db_identifier}-sg" + Name = "${local.name_prefix}-sg" }) lifecycle { diff --git a/modules/database/variables.tf b/modules/database/variables.tf index e6a2ef6..518f78d 100644 --- a/modules/database/variables.tf +++ b/modules/database/variables.tf @@ -1,5 +1,10 @@ -variable "db_identifier" { - description = "Identifier for the RDS instance" +variable "namespace" { + description = "Namespace prefix for all resources" + type = string +} + +variable "environment" { + description = "Environment name" type = string } diff --git a/modules/eks/main.tf b/modules/eks/main.tf index 8f21337..9bcadaa 100644 --- a/modules/eks/main.tf +++ b/modules/eks/main.tf @@ -1,8 +1,13 @@ +locals { + name_prefix = "${var.namespace}-${var.environment}" +} + module "eks" { source = "terraform-aws-modules/eks/aws" version = "~> 20.0" - cluster_name = var.cluster_name + cluster_name = "${local.name_prefix}-eks" + cluster_version = var.cluster_version vpc_id = var.vpc_id @@ -14,7 +19,7 @@ module "eks" { cluster_enabled_log_types = var.cluster_enabled_log_types eks_managed_node_groups = { - "${var.environment}-mz-workers" = { + "${local.name_prefix}-mz" = { desired_size = var.node_group_desired_size min_size = var.node_group_min_size max_size = var.node_group_max_size @@ -23,7 +28,7 @@ module "eks" { capacity_type = var.node_group_capacity_type ami_type = var.node_group_ami_type - name = "${var.environment}-mz" + name = local.name_prefix labels = { Environment = var.environment diff --git a/modules/eks/outputs.tf b/modules/eks/outputs.tf index c307267..1ba5e27 100644 --- a/modules/eks/outputs.tf +++ b/modules/eks/outputs.tf @@ -3,6 +3,11 @@ output "cluster_endpoint" { value = module.eks.cluster_endpoint } +output "cluster_name" { + description = "Name of the EKS cluster" + value = module.eks.cluster_name +} + output "cluster_security_group_id" { description = "Security group ID attached to the EKS cluster" value = module.eks.cluster_security_group_id diff --git a/modules/eks/variables.tf b/modules/eks/variables.tf index ec0c983..3d18d80 100644 --- a/modules/eks/variables.tf +++ b/modules/eks/variables.tf @@ -1,5 +1,10 @@ -variable "cluster_name" { - description = "Name of the EKS cluster" +variable "namespace" { + description = "Namespace prefix for all resources" + type = string +} + +variable "environment" { + description = "Environment name" type = string } @@ -50,11 +55,6 @@ variable "cluster_enabled_log_types" { default = ["api", "audit", "authenticator", "controllerManager", "scheduler"] } -variable "environment" { - description = "Environment name" - type = string -} - variable "tags" { description = "Tags to apply to all resources" type = map(string) diff --git a/modules/networking/main.tf b/modules/networking/main.tf index bd5ff68..12bb2f7 100644 --- a/modules/networking/main.tf +++ b/modules/networking/main.tf @@ -1,10 +1,14 @@ +locals { + name_prefix = "${var.namespace}-${var.environment}" +} + module "vpc" { source = "terraform-aws-modules/vpc/aws" version = "~> 5.0" create_vpc = var.create_vpc - name = var.vpc_name + name = "${local.name_prefix}-vpc" cidr = var.vpc_cidr azs = var.availability_zones @@ -18,13 +22,13 @@ module "vpc" { # Tags required for EKS private_subnet_tags = { - "kubernetes.io/cluster/${var.cluster_name}" = "shared" - "kubernetes.io/role/internal-elb" = "1" + "kubernetes.io/role/internal-elb" = "1" + "kubernetes.io/cluster/${local.name_prefix}-eks" = "shared" } public_subnet_tags = { - "kubernetes.io/cluster/${var.cluster_name}" = "shared" - "kubernetes.io/role/elb" = "1" + "kubernetes.io/role/elb" = "1" + "kubernetes.io/cluster/${local.name_prefix}-eks" = "shared" } tags = var.tags diff --git a/modules/networking/variables.tf b/modules/networking/variables.tf index 0a8c1a1..4093125 100644 --- a/modules/networking/variables.tf +++ b/modules/networking/variables.tf @@ -1,14 +1,19 @@ +variable "namespace" { + description = "Namespace prefix for all resources" + type = string +} + +variable "environment" { + description = "Environment name" + type = string +} + variable "create_vpc" { description = "Controls if VPC should be created (it affects almost all resources)" type = bool default = true } -variable "vpc_name" { - description = "Name of the VPC" - type = string -} - variable "vpc_cidr" { description = "CIDR block for VPC" type = string @@ -35,11 +40,6 @@ variable "single_nat_gateway" { default = false } -variable "cluster_name" { - description = "Name of the EKS cluster for subnet tagging" - type = string -} - variable "tags" { description = "Tags to apply to all resources" type = map(string) diff --git a/modules/storage/main.tf b/modules/storage/main.tf index 7d60265..5470cc1 100644 --- a/modules/storage/main.tf +++ b/modules/storage/main.tf @@ -1,5 +1,13 @@ +locals { + name_prefix = "${var.namespace}-${var.environment}" +} + +resource "random_id" "bucket_suffix" { + byte_length = 4 +} + resource "aws_s3_bucket" "materialize_storage" { - bucket = var.bucket_name + bucket = "${local.name_prefix}-storage-${random_id.bucket_suffix.hex}" force_destroy = var.bucket_force_destroy tags = var.tags diff --git a/modules/storage/variables.tf b/modules/storage/variables.tf index a34ab80..62b97c5 100644 --- a/modules/storage/variables.tf +++ b/modules/storage/variables.tf @@ -1,5 +1,10 @@ -variable "bucket_name" { - description = "Name of the S3 bucket" +variable "namespace" { + description = "Namespace prefix for all resources" + type = string +} + +variable "environment" { + description = "Environment name" type = string } diff --git a/modules/storage/versions.tf b/modules/storage/versions.tf index a8de733..6e5125e 100644 --- a/modules/storage/versions.tf +++ b/modules/storage/versions.tf @@ -6,5 +6,9 @@ terraform { source = "hashicorp/aws" version = "~> 5.0" } + random = { + source = "hashicorp/random" + version = "~> 3.0" + } } } diff --git a/outputs.tf b/outputs.tf index a045719..1c032d9 100644 --- a/outputs.tf +++ b/outputs.tf @@ -32,9 +32,9 @@ output "metadata_backend_url" { output "persist_backend_url" { description = "S3 connection URL in the format required by Materialize using IRSA" value = format("s3://%s/%s:serviceaccount:%s:%s", - var.bucket_name, + module.storage.bucket_name, var.environment, - var.namespace, + var.kubernetes_namespace, var.service_account_name ) } diff --git a/providers.tf b/providers.tf index 00fa5ad..c85f25e 100644 --- a/providers.tf +++ b/providers.tf @@ -4,7 +4,7 @@ provider "kubernetes" { exec { api_version = "client.authentication.k8s.io/v1beta1" - args = ["eks", "get-token", "--cluster-name", var.cluster_name] + args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name] command = "aws" } } diff --git a/terraform.tfvars.example b/terraform.tfvars.example index 76b7961..df94855 100644 --- a/terraform.tfvars.example +++ b/terraform.tfvars.example @@ -1,7 +1,7 @@ -environment = "my-environment" -vpc_name = "my-environment-vpc" -cluster_name = "my-environment-eks" -bucket_name = "my-environment-bucket" +# The namespace and the environment are used to create a unique name for the resources +# eg. ${namespace}-${environment}-${resource_name} +namespace = "my-namespace" +environment = "dev" database_password = "your-secure-password-here" tags = { diff --git a/variables.tf b/variables.tf index 6c5632b..e4d6b60 100644 --- a/variables.tf +++ b/variables.tf @@ -1,8 +1,20 @@ # General Variables +variable "namespace" { + description = "Namespace for all resources, usually the organization or project name" + type = string + validation { + condition = length(var.namespace) <= 18 && can(regex("^[a-z0-9-]+$", var.namespace)) + error_message = "Namespace must be lowercase alphanumeric and hyphens only, max 18 characters" + } +} + variable "environment" { description = "Environment name (e.g., prod, staging, dev)" type = string - default = "dev" + validation { + condition = length(var.environment) <= 8 && can(regex("^[a-z0-9]+$", var.environment)) + error_message = "Environment must be lowercase alphanumeric only, max 8 characters" + } } variable "tags" { @@ -34,12 +46,6 @@ variable "network_private_subnet_ids" { type = list(string) } -variable "vpc_name" { - description = "Name of the VPC" - type = string - default = "materialize-vpc" -} - variable "vpc_cidr" { description = "CIDR block for VPC" type = string @@ -71,12 +77,6 @@ variable "single_nat_gateway" { } # EKS Variables -variable "cluster_name" { - description = "Name of the EKS cluster" - type = string - default = "materialize-cluster" -} - variable "cluster_version" { description = "Kubernetes version for the EKS cluster" type = string @@ -139,12 +139,6 @@ variable "enable_cluster_creator_admin_permissions" { } # RDS Variables -variable "db_identifier" { - description = "Identifier for the RDS instance" - type = string - default = "materialize-db" -} - variable "postgres_version" { description = "Version of PostgreSQL to use" type = string @@ -194,11 +188,6 @@ variable "db_multi_az" { } # S3 Variables -variable "bucket_name" { - description = "Name of the S3 bucket" - type = string -} - variable "bucket_force_destroy" { description = "Enable force destroy for the S3 bucket" type = bool @@ -252,8 +241,8 @@ variable "metrics_retention_days" { default = 7 } -variable "namespace" { - description = "Namespace for Materialize resources" +variable "kubernetes_namespace" { + description = "The Kubernetes namespace for the Materialize resources" type = string default = "materialize-environment" } @@ -264,24 +253,6 @@ variable "service_account_name" { default = "12345678-1234-1234-1234-123456789012" } -variable "mz_iam_service_account_name" { - description = "Name of the IAM user for Materialize service authentication (will be prefixed with environment name)" - type = string - default = "materialize-user" -} - -variable "mz_iam_role_name" { - description = "Name of the IAM role for Materialize S3 access (will be prefixed with environment name)" - type = string - default = "materialize-s3-role" -} - -variable "mz_iam_policy_name" { - description = "Name of the IAM policy for Materialize S3 access" - type = string - default = "materialize-s3-access" -} - variable "log_group_name_prefix" { description = "Prefix for the CloudWatch log group name (will be combined with environment name)" type = string From d7c67faef4e2be0efac700c9068e7fb69af4d100 Mon Sep 17 00:00:00 2001 From: Bobby Iliev Date: Sun, 22 Dec 2024 19:40:05 +0200 Subject: [PATCH 03/14] Regenerate readme file --- README.md | 14 ++++---------- examples/simple/main.tf | 9 +-------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 7f3588c..b00a766 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ The module has been tested with: | Name | Version | |------|---------| -| [aws](#provider\_aws) | 5.81.0 | +| [aws](#provider\_aws) | 5.82.2 | ## Modules @@ -52,16 +52,13 @@ The module has been tested with: | [availability\_zones](#input\_availability\_zones) | List of availability zones | `list(string)` |
[
"us-east-1a",
"us-east-1b",
"us-east-1c"
]
| no | | [bucket\_force\_destroy](#input\_bucket\_force\_destroy) | Enable force destroy for the S3 bucket | `bool` | `false` | no | | [bucket\_lifecycle\_rules](#input\_bucket\_lifecycle\_rules) | List of lifecycle rules for the S3 bucket |
list(object({
id = string
enabled = bool
prefix = string
transition_days = number
transition_storage_class = string
expiration_days = number
noncurrent_version_expiration_days = number
}))
|
[
{
"enabled": true,
"expiration_days": 365,
"id": "cleanup",
"noncurrent_version_expiration_days": 90,
"prefix": "",
"transition_days": 90,
"transition_storage_class": "STANDARD_IA"
}
]
| no | -| [bucket\_name](#input\_bucket\_name) | Name of the S3 bucket | `string` | n/a | yes | | [cluster\_enabled\_log\_types](#input\_cluster\_enabled\_log\_types) | List of desired control plane logging to enable | `list(string)` |
[
"api",
"audit",
"authenticator",
"controllerManager",
"scheduler"
]
| no | -| [cluster\_name](#input\_cluster\_name) | Name of the EKS cluster | `string` | `"materialize-cluster"` | no | | [cluster\_version](#input\_cluster\_version) | Kubernetes version for the EKS cluster | `string` | `"1.31"` | no | | [create\_vpc](#input\_create\_vpc) | Controls if VPC should be created (it affects almost all resources) | `bool` | `true` | no | | [database\_name](#input\_database\_name) | Name of the database to create | `string` | `"materialize"` | no | | [database\_password](#input\_database\_password) | Password for the database (should be provided via tfvars or environment variable) | `string` | n/a | yes | | [database\_username](#input\_database\_username) | Username for the database | `string` | `"materialize"` | no | | [db\_allocated\_storage](#input\_db\_allocated\_storage) | Allocated storage for the RDS instance (in GB) | `number` | `20` | no | -| [db\_identifier](#input\_db\_identifier) | Identifier for the RDS instance | `string` | `"materialize-db"` | no | | [db\_instance\_class](#input\_db\_instance\_class) | Instance class for the RDS instance | `string` | `"db.t3.large"` | no | | [db\_max\_allocated\_storage](#input\_db\_max\_allocated\_storage) | Maximum storage for autoscaling (in GB) | `number` | `100` | no | | [db\_multi\_az](#input\_db\_multi\_az) | Enable multi-AZ deployment for RDS | `bool` | `false` | no | @@ -69,13 +66,11 @@ The module has been tested with: | [enable\_bucket\_versioning](#input\_enable\_bucket\_versioning) | Enable versioning for the S3 bucket | `bool` | `true` | no | | [enable\_cluster\_creator\_admin\_permissions](#input\_enable\_cluster\_creator\_admin\_permissions) | To add the current caller identity as an administrator | `bool` | `true` | no | | [enable\_monitoring](#input\_enable\_monitoring) | Enable CloudWatch monitoring | `bool` | `true` | no | -| [environment](#input\_environment) | Environment name (e.g., prod, staging, dev) | `string` | `"dev"` | no | +| [environment](#input\_environment) | Environment name (e.g., prod, staging, dev) | `string` | n/a | yes | +| [kubernetes\_namespace](#input\_kubernetes\_namespace) | The Kubernetes namespace for the Materialize resources | `string` | `"materialize-environment"` | no | | [log\_group\_name\_prefix](#input\_log\_group\_name\_prefix) | Prefix for the CloudWatch log group name (will be combined with environment name) | `string` | `"materialize"` | no | | [metrics\_retention\_days](#input\_metrics\_retention\_days) | Number of days to retain CloudWatch metrics | `number` | `7` | no | -| [mz\_iam\_policy\_name](#input\_mz\_iam\_policy\_name) | Name of the IAM policy for Materialize S3 access | `string` | `"materialize-s3-access"` | no | -| [mz\_iam\_role\_name](#input\_mz\_iam\_role\_name) | Name of the IAM role for Materialize S3 access (will be prefixed with environment name) | `string` | `"materialize-s3-role"` | no | -| [mz\_iam\_service\_account\_name](#input\_mz\_iam\_service\_account\_name) | Name of the IAM user for Materialize service authentication (will be prefixed with environment name) | `string` | `"materialize-user"` | no | -| [namespace](#input\_namespace) | Namespace for Materialize resources | `string` | `"materialize-environment"` | no | +| [namespace](#input\_namespace) | Namespace for all resources, usually the organization or project name | `string` | n/a | yes | | [network\_id](#input\_network\_id) | The ID of the VPC in which resources will be deployed. Only used if create\_vpc is false. | `string` | `""` | no | | [network\_private\_subnet\_ids](#input\_network\_private\_subnet\_ids) | A list of private subnet IDs in the VPC. Only used if create\_vpc is false. | `list(string)` | `[]` | no | | [node\_group\_ami\_type](#input\_node\_group\_ami\_type) | AMI type for the node group | `string` | `"AL2023_x86_64_STANDARD"` | no | @@ -91,7 +86,6 @@ The module has been tested with: | [single\_nat\_gateway](#input\_single\_nat\_gateway) | Use a single NAT Gateway for all private subnets | `bool` | `false` | no | | [tags](#input\_tags) | Default tags to apply to all resources | `map(string)` |
{
"Environment": "dev",
"Project": "materialize",
"Terraform": "true"
}
| no | | [vpc\_cidr](#input\_vpc\_cidr) | CIDR block for VPC | `string` | `"10.0.0.0/16"` | no | -| [vpc\_name](#input\_vpc\_name) | Name of the VPC | `string` | `"materialize-vpc"` | no | ## Outputs diff --git a/examples/simple/main.tf b/examples/simple/main.tf index 52da570..efa771c 100644 --- a/examples/simple/main.tf +++ b/examples/simple/main.tf @@ -55,20 +55,13 @@ module "materialize_infrastructure" { } } -<<<<<<< HEAD variable "database_password" { description = "Password for the database (should be provided via tfvars or environment variable)" + default = "your-secure-password" type = string sensitive = true } -# Generate random suffix for unique S3 bucket name -resource "random_id" "suffix" { - byte_length = 4 -} - -======= ->>>>>>> be3d603 (Refactor resource names definitions) # Outputs output "vpc_id" { description = "VPC ID" From 38e54d68145b440d20baa0cffa5a968620ce39f5 Mon Sep 17 00:00:00 2001 From: Bobby Iliev Date: Sun, 22 Dec 2024 22:25:11 +0200 Subject: [PATCH 04/14] Add Optional Helm Install Support --- README.md | 4 + examples/simple/main.tf | 26 +++++ main.tf | 48 +++++++++ modules/operator/main.tf | 188 ++++++++++++++++++++++++++++++++++ modules/operator/outputs.tf | 24 +++++ modules/operator/variables.tf | 58 +++++++++++ modules/operator/versions.tf | 18 ++++ providers.tf | 11 +- terraform.tfvars.example | 24 +++++ variables.tf | 24 +++++ 10 files changed, 421 insertions(+), 4 deletions(-) create mode 100644 modules/operator/main.tf create mode 100644 modules/operator/outputs.tf create mode 100644 modules/operator/variables.tf create mode 100644 modules/operator/versions.tf diff --git a/README.md b/README.md index b00a766..f278d27 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ The module has been tested with: | [database](#module\_database) | ./modules/database | n/a | | [eks](#module\_eks) | ./modules/eks | n/a | | [networking](#module\_networking) | ./modules/networking | n/a | +| [operator](#module\_operator) | ./modules/operator | n/a | | [storage](#module\_storage) | ./modules/storage | n/a | ## Resources @@ -44,6 +45,7 @@ The module has been tested with: | [aws_iam_role_policy.materialize_s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_user.materialize](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user) | resource | | [aws_iam_user_policy.materialize_s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_policy) | resource | +| [aws_eks_cluster_auth.cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/eks_cluster_auth) | data source | ## Inputs @@ -67,8 +69,10 @@ The module has been tested with: | [enable\_cluster\_creator\_admin\_permissions](#input\_enable\_cluster\_creator\_admin\_permissions) | To add the current caller identity as an administrator | `bool` | `true` | no | | [enable\_monitoring](#input\_enable\_monitoring) | Enable CloudWatch monitoring | `bool` | `true` | no | | [environment](#input\_environment) | Environment name (e.g., prod, staging, dev) | `string` | n/a | yes | +| [install\_materialize\_operator](#input\_install\_materialize\_operator) | Whether to install the Materialize operator | `bool` | `false` | no | | [kubernetes\_namespace](#input\_kubernetes\_namespace) | The Kubernetes namespace for the Materialize resources | `string` | `"materialize-environment"` | no | | [log\_group\_name\_prefix](#input\_log\_group\_name\_prefix) | Prefix for the CloudWatch log group name (will be combined with environment name) | `string` | `"materialize"` | no | +| [materialize\_instances](#input\_materialize\_instances) | Configuration for Materialize instances |
list(object({
name = string
instance_id = string
namespace = optional(string)
database_name = optional(string)
database_username = optional(string)
database_password = optional(string)
database_host = optional(string)
cpu_request = optional(string)
memory_request = optional(string)
memory_limit = optional(string)
}))
| `[]` | no | | [metrics\_retention\_days](#input\_metrics\_retention\_days) | Number of days to retain CloudWatch metrics | `number` | `7` | no | | [namespace](#input\_namespace) | Namespace for all resources, usually the organization or project name | `string` | n/a | yes | | [network\_id](#input\_network\_id) | The ID of the VPC in which resources will be deployed. Only used if create\_vpc is false. | `string` | `""` | no | diff --git a/examples/simple/main.tf b/examples/simple/main.tf index efa771c..4b921cd 100644 --- a/examples/simple/main.tf +++ b/examples/simple/main.tf @@ -22,6 +22,7 @@ module "materialize_infrastructure" { # EKS Configuration cluster_version = "1.31" # node_group_instance_types = ["m6g.medium"] + # TODO: Defaulting to a smaller instance type due to resource constraints node_group_instance_types = ["r5.xlarge"] node_group_desired_size = 2 node_group_min_size = 1 @@ -47,6 +48,31 @@ module "materialize_infrastructure" { enable_monitoring = true metrics_retention_days = 3 + # Enable and configure Materialize operator + install_materialize_operator = true + + # Configure Materialize instances + materialize_instances = [ + { + name = "analytics" + instance_id = "12345678-1234-1234-1234-123456789012" + namespace = "materialize-environment" + database_name = "analytics_db" + database_username = "materialize" + database_password = var.database_password + database_host = module.materialize_infrastructure.database_endpoint + }, + { + name = "production" + instance_id = "87654321-4321-4321-4321-210987654321" + namespace = "materialize-environment" + database_name = "production_db" + database_username = "materialize" + database_password = var.database_password + database_host = module.materialize_infrastructure.database_endpoint + } + ] + # Tags tags = { Environment = "dev" diff --git a/main.tf b/main.tf index d596000..eb4e8d7 100644 --- a/main.tf +++ b/main.tf @@ -78,10 +78,54 @@ module "database" { tags = local.common_tags } +module "operator" { + count = var.install_materialize_operator ? 1 : 0 + source = "./modules/operator" + + namespace = var.namespace + environment = var.environment + instances = var.materialize_instances + iam_role_arn = aws_iam_role.materialize_s3.arn + cluster_endpoint = module.eks.cluster_endpoint + cluster_ca_certificate = module.eks.cluster_certificate_authority_data + s3_bucket_name = module.storage.bucket_name + + providers = { + kubernetes = kubernetes, + helm = helm + } + + depends_on = [ + module.eks, + module.storage, + module.database + ] +} + locals { network_id = var.create_vpc ? module.networking.vpc_id : var.network_id network_private_subnet_ids = var.create_vpc ? module.networking.private_subnet_ids : var.network_private_subnet_ids + # instance_backend_urls = { + # for instance in var.materialize_instances : instance.name => { + # metadata_backend_url = format( + # "postgres://%s:%s@%s/%s?sslmode=require", + # coalesce(instance.database_username, var.database_username), + # coalesce(instance.database_password, var.database_password), + # module.database.db_instance_endpoint, + # coalesce(instance.database_name, "${instance.name}_db") + # ) + # persist_backend_url = format( + # "s3://%s/%s/%s:serviceaccount:%s:%s", + # module.storage.bucket_name, + # var.environment, + # instance.name, + # coalesce(instance.namespace, "materialize-environment"), + # instance.instance_id + # ) + # } + # } + # Common tags that apply to all resources common_tags = merge( var.tags, @@ -191,3 +235,7 @@ resource "aws_iam_role_policy" "materialize_s3" { locals { name_prefix = "${var.namespace}-${var.environment}" } + +data "aws_eks_cluster_auth" "cluster" { + name = module.eks.cluster_name +} diff --git a/modules/operator/main.tf b/modules/operator/main.tf new file mode 100644 index 0000000..22a6de2 --- /dev/null +++ b/modules/operator/main.tf @@ -0,0 +1,188 @@ +locals { + name_prefix = "${var.namespace}-${var.environment}" +} + +resource "kubernetes_namespace" "materialize" { + metadata { + name = var.operator_namespace + } +} + +resource "kubernetes_namespace" "instance_namespaces" { + for_each = toset(compact([for instance in var.instances : instance.namespace if instance.namespace != null])) + + metadata { + name = each.key + } +} + +resource "helm_release" "materialize_operator" { + name = "${local.name_prefix}-operator" + namespace = kubernetes_namespace.materialize.metadata[0].name + # TODO: Publish the chart to a public repository, currently using a forked version of the chart + repository = "https://raw.githubusercontent.com/bobbyiliev/materialize/refs/heads/helm-chart-package/misc/helm-charts" + chart = "materialize-operator" + # version = var.operator_version + # TODO: Use the latest version of the chart + version = "v25.1.0-beta.1" + + values = [ + yamlencode({ + operator ={ + cloudProvider = { + type = "aws" + region = data.aws_region.current.name + providers = { + aws = { + enabled = true + accountID = data.aws_caller_identity.current.account_id + iam = { + roles = { + environment = var.iam_role_arn + } + } + } + } + } + } + }) + ] + + depends_on = [kubernetes_namespace.materialize] +} + +resource "kubernetes_secret" "materialize_backends" { + for_each = { for idx, instance in var.instances : instance.name => instance } + + metadata { + name = "${each.key}-materialize-backend" + namespace = coalesce(each.value.namespace, var.operator_namespace) + } + + data = { + metadata_backend_url = format( + "postgres://%s:%s@%s/%s?sslmode=require", + each.value.database_username, + each.value.database_password, + each.value.database_host, + coalesce(each.value.database_name, "${each.key}_db") + ) + persist_backend_url = format( + "s3://%s/%s-%s:serviceaccount:%s:%s", + var.s3_bucket_name, + var.environment, + each.key, + coalesce(each.value.namespace, kubernetes_namespace.materialize.metadata[0].name), + each.value.instance_id + ) + } +} + +resource "kubernetes_manifest" "materialize_instances" { + for_each = { for idx, instance in var.instances : instance.name => instance } + + manifest = { + apiVersion = "materialize.cloud/v1alpha1" + kind = "Materialize" + metadata = { + name = each.value.instance_id + namespace = coalesce(each.value.namespace, var.operator_namespace) + } + spec = { + environmentdImageRef = "materialize/environmentd:${var.operator_version}" + backendSecretName = "${each.key}-materialize-backend" + environmentdResourceRequirements = { + limits = { + memory = each.value.memory_limit + } + requests = { + cpu = each.value.cpu_request + memory = each.value.memory_request + } + } + balancerdResourceRequirements = { + limits = { + memory = "256Mi" + } + requests = { + cpu = "100m" + memory = "256Mi" + } + } + } + } + + depends_on = [ + helm_release.materialize_operator, + kubernetes_secret.materialize_backends, + kubernetes_namespace.instance_namespaces + ] +} + +# Materialize does not currently create databases within the instances, so we need to create them ourselves +resource "kubernetes_manifest" "db_init_configmap" { + for_each = { for idx, instance in var.instances : instance.name => instance } + + manifest = { + apiVersion = "v1" + kind = "ConfigMap" + metadata = { + name = "init-db-script-${each.key}" + namespace = coalesce(each.value.namespace, var.operator_namespace) + } + data = { + "init.sql" = format( + "CREATE DATABASE IF NOT EXISTS %s;", + coalesce(each.value.database_name, "${each.key}_db") + ) + } + } +} + +resource "kubernetes_manifest" "db_init_job" { + for_each = { for idx, instance in var.instances : instance.name => instance } + + manifest = { + apiVersion = "batch/v1" + kind = "Job" + metadata = { + name = "create-db-${each.key}" + namespace = coalesce(each.value.namespace, var.operator_namespace) + } + spec = { + template = { + spec = { + containers = [{ + name = "init-db" + image = "postgres:latest" + command = [ + "/bin/sh", + "-c", + format( + "psql $DATABASE_URL -c \"CREATE DATABASE %s;\"", + coalesce(each.value.database_name, "${each.key}_db") + ) + ] + env = [ + { + name = "DATABASE_URL" + value = format( + "postgres://%s:%s@%s/%s?sslmode=require", + each.value.database_username, + each.value.database_password, + each.value.database_host, + "postgres" # Default database to connect to + ) + } + ] + }] + restartPolicy = "OnFailure" + } + } + backoffLimit = 3 + } + } +} + +data "aws_region" "current" {} +data "aws_caller_identity" "current" {} diff --git a/modules/operator/outputs.tf b/modules/operator/outputs.tf new file mode 100644 index 0000000..1c68797 --- /dev/null +++ b/modules/operator/outputs.tf @@ -0,0 +1,24 @@ +output "operator_namespace" { + description = "Namespace where the operator is installed" + value = kubernetes_namespace.materialize.metadata[0].name +} + +output "operator_release_name" { + description = "Helm release name of the operator" + value = helm_release.materialize_operator.name +} + +output "operator_release_status" { + description = "Status of the helm release" + value = helm_release.materialize_operator.status +} + +output "materialize_instances" { + description = "Details of created Materialize instances" + value = { + for name, instance in kubernetes_manifest.materialize_instances : name => { + id = instance.manifest.metadata.name + namespace = instance.manifest.metadata.namespace + } + } +} diff --git a/modules/operator/variables.tf b/modules/operator/variables.tf new file mode 100644 index 0000000..a100265 --- /dev/null +++ b/modules/operator/variables.tf @@ -0,0 +1,58 @@ +variable "namespace" { + description = "Namespace prefix for all resources" + type = string +} + +variable "environment" { + description = "Environment name" + type = string +} + +variable "operator_version" { + description = "Version of the Materialize operator to install" + type = string + default = "v0.127.1" +} + +variable "iam_role_arn" { + description = "IAM role ARN for Materialize S3 access" + type = string +} + +variable "cluster_endpoint" { + description = "EKS cluster endpoint" + type = string +} + +variable "cluster_ca_certificate" { + description = "EKS cluster CA certificate" + type = string +} + +variable "s3_bucket_name" { + description = "Name of the S3 bucket for Materialize storage" + type = string +} + +variable "operator_namespace" { + description = "Namespace for the Materialize operator" + type = string + default = "materialize" +} + +variable "instances" { + description = "Configuration for Materialize instances" + type = list(object({ + name = string + instance_id = string + namespace = optional(string, "materialize-environment") + database_name = string + database_username = string + database_password = string + database_host = string + cpu_request = optional(string, "1") + memory_request = optional(string, "1Gi") + memory_limit = optional(string, "1Gi") + })) + default = [] +} diff --git a/modules/operator/versions.tf b/modules/operator/versions.tf new file mode 100644 index 0000000..6f04d7c --- /dev/null +++ b/modules/operator/versions.tf @@ -0,0 +1,18 @@ +terraform { + required_version = ">= 1.0" + + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 5.0" + } + kubernetes = { + source = "hashicorp/kubernetes" + version = "~> 2.0" + } + helm = { + source = "hashicorp/helm" + version = "~> 2.0" + } + } +} diff --git a/providers.tf b/providers.tf index c85f25e..44a18eb 100644 --- a/providers.tf +++ b/providers.tf @@ -1,10 +1,13 @@ provider "kubernetes" { host = module.eks.cluster_endpoint cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data) + token = data.aws_eks_cluster_auth.cluster.token +} - exec { - api_version = "client.authentication.k8s.io/v1beta1" - args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name] - command = "aws" +provider "helm" { + kubernetes { + host = module.eks.cluster_endpoint + cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data) + token = data.aws_eks_cluster_auth.cluster.token } } diff --git a/terraform.tfvars.example b/terraform.tfvars.example index df94855..589f52a 100644 --- a/terraform.tfvars.example +++ b/terraform.tfvars.example @@ -20,3 +20,27 @@ db_allocated_storage = 20 db_multi_az = false enable_cluster_creator_admin_permissions = true + +# Materialize Helm chart values +install_materialize_operator = false +materialize_instances = [ + { + name = "analytics" + instance_id = "12345678-1234-1234-1234-123456789012" + namespace = "analytics-env" # Separate namespace + database_password = "secure-password-1" + cpu_request = "4" + }, + { + name = "reporting" + instance_id = "87654321-4321-4321-4321-987654321098" + # No namespace specified - will use the operator namespace + database_password = "secure-password-2" + }, + { + name = "monitoring" + instance_id = "11111111-2222-3333-4444-555555555555" + namespace = "analytics-env" # Share namespace with analytics + database_password = "secure-password-3" + } +] diff --git a/variables.tf b/variables.tf index e4d6b60..620a5e5 100644 --- a/variables.tf +++ b/variables.tf @@ -258,3 +258,27 @@ variable "log_group_name_prefix" { type = string default = "materialize" } + +# Materialize Helm Chart Variables +variable "install_materialize_operator" { + description = "Whether to install the Materialize operator" + type = bool + default = false +} + +variable "materialize_instances" { + description = "Configuration for Materialize instances" + type = list(object({ + name = string + instance_id = string + namespace = optional(string) + database_name = optional(string) + database_username = optional(string) + database_password = optional(string) + database_host = optional(string) + cpu_request = optional(string) + memory_request = optional(string) + memory_limit = optional(string) + })) + default = [] +} From 8edf57c29a39838a5158d788a3dfd04e28e84573 Mon Sep 17 00:00:00 2001 From: Bobby Iliev Date: Sun, 22 Dec 2024 22:27:54 +0200 Subject: [PATCH 05/14] Fix lint warnings --- modules/operator/main.tf | 44 ++++++++++++++++++------------------- modules/operator/outputs.tf | 10 +++++++++ 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/modules/operator/main.tf b/modules/operator/main.tf index 22a6de2..d6c8a81 100644 --- a/modules/operator/main.tf +++ b/modules/operator/main.tf @@ -17,32 +17,32 @@ resource "kubernetes_namespace" "instance_namespaces" { } resource "helm_release" "materialize_operator" { - name = "${local.name_prefix}-operator" - namespace = kubernetes_namespace.materialize.metadata[0].name + name = "${local.name_prefix}-operator" + namespace = kubernetes_namespace.materialize.metadata[0].name # TODO: Publish the chart to a public repository, currently using a forked version of the chart repository = "https://raw.githubusercontent.com/bobbyiliev/materialize/refs/heads/helm-chart-package/misc/helm-charts" chart = "materialize-operator" # version = var.operator_version # TODO: Use the latest version of the chart - version = "v25.1.0-beta.1" + version = "v25.1.0-beta.1" values = [ yamlencode({ - operator ={ + operator = { cloudProvider = { - type = "aws" - region = data.aws_region.current.name - providers = { + type = "aws" + region = data.aws_region.current.name + providers = { aws = { - enabled = true - accountID = data.aws_caller_identity.current.account_id - iam = { + enabled = true + accountID = data.aws_caller_identity.current.account_id + iam = { roles = { - environment = var.iam_role_arn + environment = var.iam_role_arn } - } - } + } } + } } } }) @@ -68,12 +68,12 @@ resource "kubernetes_secret" "materialize_backends" { coalesce(each.value.database_name, "${each.key}_db") ) persist_backend_url = format( - "s3://%s/%s-%s:serviceaccount:%s:%s", - var.s3_bucket_name, - var.environment, - each.key, - coalesce(each.value.namespace, kubernetes_namespace.materialize.metadata[0].name), - each.value.instance_id + "s3://%s/%s-%s:serviceaccount:%s:%s", + var.s3_bucket_name, + var.environment, + each.key, + coalesce(each.value.namespace, kubernetes_namespace.materialize.metadata[0].name), + each.value.instance_id ) } } @@ -153,8 +153,8 @@ resource "kubernetes_manifest" "db_init_job" { template = { spec = { containers = [{ - name = "init-db" - image = "postgres:latest" + name = "init-db" + image = "postgres:latest" command = [ "/bin/sh", "-c", @@ -165,7 +165,7 @@ resource "kubernetes_manifest" "db_init_job" { ] env = [ { - name = "DATABASE_URL" + name = "DATABASE_URL" value = format( "postgres://%s:%s@%s/%s?sslmode=require", each.value.database_username, diff --git a/modules/operator/outputs.tf b/modules/operator/outputs.tf index 1c68797..dad8bc9 100644 --- a/modules/operator/outputs.tf +++ b/modules/operator/outputs.tf @@ -22,3 +22,13 @@ output "materialize_instances" { } } } + +output "cluster_endpoint" { + description = "Outcluster endpoint for Materialize instances" + value = var.cluster_endpoint +} + +output "cluster_ca_certificate" { + description = "CA certificate for the EKS cluster" + value = var.cluster_ca_certificate +} From 0a806fe605cf25c2442a2ff0354d92243da3bb09 Mon Sep 17 00:00:00 2001 From: Bobby Iliev Date: Mon, 30 Dec 2024 11:38:48 +0200 Subject: [PATCH 06/14] Metadata db: pinning to a version that matches RDS --- main.tf | 1 + modules/operator/main.tf | 2 +- modules/operator/variables.tf | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/main.tf b/main.tf index eb4e8d7..9ffb536 100644 --- a/main.tf +++ b/main.tf @@ -89,6 +89,7 @@ module "operator" { cluster_endpoint = module.eks.cluster_endpoint cluster_ca_certificate = module.eks.cluster_certificate_authority_data s3_bucket_name = module.storage.bucket_name + postgres_version = var.postgres_version providers = { kubernetes = kubernetes, diff --git a/modules/operator/main.tf b/modules/operator/main.tf index d6c8a81..7cad969 100644 --- a/modules/operator/main.tf +++ b/modules/operator/main.tf @@ -154,7 +154,7 @@ resource "kubernetes_manifest" "db_init_job" { spec = { containers = [{ name = "init-db" - image = "postgres:latest" + image = "postgres:${var.postgres_version}" command = [ "/bin/sh", "-c", diff --git a/modules/operator/variables.tf b/modules/operator/variables.tf index a100265..ab9416b 100644 --- a/modules/operator/variables.tf +++ b/modules/operator/variables.tf @@ -56,3 +56,9 @@ variable "instances" { })) default = [] } + +variable "postgres_version" { + description = "Postgres version to use for the metadata backend" + type = string + default = "15" +} From bd159a648e70236a4bb3428c8d4d348ebc49a6a2 Mon Sep 17 00:00:00 2001 From: Bobby Iliev Date: Wed, 1 Jan 2025 19:05:48 +0200 Subject: [PATCH 07/14] Switch away from kubernetes_manifest resource --- README.md | 3 +- examples/simple/main.tf | 46 +++++++------- main.tf | 4 +- modules/operator/main.tf | 114 ++++++++++++++++++---------------- modules/operator/variables.tf | 1 - outputs.tf | 5 ++ providers.tf | 7 ++- terraform.tfvars.example | 3 - variables.tf | 1 - 9 files changed, 100 insertions(+), 84 deletions(-) diff --git a/README.md b/README.md index f278d27..73ee6b1 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ The module has been tested with: | [install\_materialize\_operator](#input\_install\_materialize\_operator) | Whether to install the Materialize operator | `bool` | `false` | no | | [kubernetes\_namespace](#input\_kubernetes\_namespace) | The Kubernetes namespace for the Materialize resources | `string` | `"materialize-environment"` | no | | [log\_group\_name\_prefix](#input\_log\_group\_name\_prefix) | Prefix for the CloudWatch log group name (will be combined with environment name) | `string` | `"materialize"` | no | -| [materialize\_instances](#input\_materialize\_instances) | Configuration for Materialize instances |
list(object({
name = string
instance_id = string
namespace = optional(string)
database_name = optional(string)
database_username = optional(string)
database_password = optional(string)
database_host = optional(string)
cpu_request = optional(string)
memory_request = optional(string)
memory_limit = optional(string)
}))
| `[]` | no | +| [materialize\_instances](#input\_materialize\_instances) | Configuration for Materialize instances |
list(object({
name = string
namespace = optional(string)
database_name = optional(string)
database_username = optional(string)
database_password = optional(string)
database_host = optional(string)
cpu_request = optional(string)
memory_request = optional(string)
memory_limit = optional(string)
}))
| `[]` | no | | [metrics\_retention\_days](#input\_metrics\_retention\_days) | Number of days to retain CloudWatch metrics | `number` | `7` | no | | [namespace](#input\_namespace) | Namespace for all resources, usually the organization or project name | `string` | n/a | yes | | [network\_id](#input\_network\_id) | The ID of the VPC in which resources will be deployed. Only used if create\_vpc is false. | `string` | `""` | no | @@ -97,6 +97,7 @@ The module has been tested with: |------|-------------| | [database\_endpoint](#output\_database\_endpoint) | RDS instance endpoint | | [eks\_cluster\_endpoint](#output\_eks\_cluster\_endpoint) | EKS cluster endpoint | +| [eks\_cluster\_name](#output\_eks\_cluster\_name) | EKS cluster name | | [materialize\_s3\_role\_arn](#output\_materialize\_s3\_role\_arn) | The ARN of the IAM role for Materialize | | [metadata\_backend\_url](#output\_metadata\_backend\_url) | PostgreSQL connection URL in the format required by Materialize | | [oidc\_provider\_arn](#output\_oidc\_provider\_arn) | The ARN of the OIDC Provider | diff --git a/examples/simple/main.tf b/examples/simple/main.tf index 4b921cd..61dafb2 100644 --- a/examples/simple/main.tf +++ b/examples/simple/main.tf @@ -51,27 +51,26 @@ module "materialize_infrastructure" { # Enable and configure Materialize operator install_materialize_operator = true - # Configure Materialize instances - materialize_instances = [ - { - name = "analytics" - instance_id = "12345678-1234-1234-1234-123456789012" - namespace = "materialize-environment" - database_name = "analytics_db" - database_username = "materialize" - database_password = var.database_password - database_host = module.materialize_infrastructure.database_endpoint - }, - { - name = "production" - instance_id = "87654321-4321-4321-4321-210987654321" - namespace = "materialize-environment" - database_name = "production_db" - database_username = "materialize" - database_password = var.database_password - database_host = module.materialize_infrastructure.database_endpoint - } - ] + # Once the operator is installed, you can define your Materialize instances here. + # Uncomment the following block (or provide your own instances) to configure them. + # materialize_instances = [ + # { + # name = "analytics" + # namespace = "materialize-environment" + # database_name = "analytics_db" + # database_username = "materialize" + # database_password = var.database_password + # database_host = module.materialize_infrastructure.database_endpoint + # }, + # { + # name = "production" + # namespace = "materialize-environment" + # database_name = "production_db" + # database_username = "materialize" + # database_password = var.database_password + # database_host = module.materialize_infrastructure.database_endpoint + # } + # ] # Tags tags = { @@ -99,6 +98,11 @@ output "eks_cluster_endpoint" { value = module.materialize_infrastructure.eks_cluster_endpoint } +output "eks_cluster_name" { + description = "EKS cluster name" + value = module.materialize_infrastructure.eks_cluster_name +} + output "database_endpoint" { description = "RDS instance endpoint" value = module.materialize_infrastructure.database_endpoint diff --git a/main.tf b/main.tf index 9ffb536..6f50214 100644 --- a/main.tf +++ b/main.tf @@ -92,7 +92,7 @@ module "operator" { postgres_version = var.postgres_version providers = { - kubernetes = kubernetes, + kubernetes = kubernetes helm = helm } @@ -122,7 +122,7 @@ locals { # var.environment, # instance.name, # coalesce(instance.namespace, "materialize-environment"), - # instance.instance_id + # instance.name # ) # } # } diff --git a/modules/operator/main.tf b/modules/operator/main.tf index 7cad969..55b86fd 100644 --- a/modules/operator/main.tf +++ b/modules/operator/main.tf @@ -17,7 +17,7 @@ resource "kubernetes_namespace" "instance_namespaces" { } resource "helm_release" "materialize_operator" { - name = "${local.name_prefix}-operator" + name = local.name_prefix namespace = kubernetes_namespace.materialize.metadata[0].name # TODO: Publish the chart to a public repository, currently using a forked version of the chart repository = "https://raw.githubusercontent.com/bobbyiliev/materialize/refs/heads/helm-chart-package/misc/helm-charts" @@ -73,11 +73,17 @@ resource "kubernetes_secret" "materialize_backends" { var.environment, each.key, coalesce(each.value.namespace, kubernetes_namespace.materialize.metadata[0].name), - each.value.instance_id + each.value.name ) } } +# The kubernetes_manifest resource is used to create Materialize instances +# It currently has a few limitations: +# - It requires the Kubernetes cluster to be running, otherwise it will fail to connect +# - It requires the Materialize operator to be installed in the cluster, otherwise it will fail +# Tracking issue: +# https://github.com/hashicorp/terraform-provider-kubernetes/issues/1775 resource "kubernetes_manifest" "materialize_instances" { for_each = { for idx, instance in var.instances : instance.name => instance } @@ -85,7 +91,7 @@ resource "kubernetes_manifest" "materialize_instances" { apiVersion = "materialize.cloud/v1alpha1" kind = "Materialize" metadata = { - name = each.value.instance_id + name = each.value.name namespace = coalesce(each.value.namespace, var.operator_namespace) } spec = { @@ -120,66 +126,66 @@ resource "kubernetes_manifest" "materialize_instances" { } # Materialize does not currently create databases within the instances, so we need to create them ourselves -resource "kubernetes_manifest" "db_init_configmap" { +resource "kubernetes_config_map" "db_init_configmap" { for_each = { for idx, instance in var.instances : instance.name => instance } - manifest = { - apiVersion = "v1" - kind = "ConfigMap" - metadata = { - name = "init-db-script-${each.key}" - namespace = coalesce(each.value.namespace, var.operator_namespace) - } - data = { - "init.sql" = format( - "CREATE DATABASE IF NOT EXISTS %s;", - coalesce(each.value.database_name, "${each.key}_db") - ) - } + metadata { + name = "init-db-script-${each.key}" + namespace = coalesce(each.value.namespace, var.operator_namespace) + } + + data = { + "init.sql" = format( + "CREATE DATABASE IF NOT EXISTS %s;", + coalesce(each.value.database_name, "${each.key}_db") + ) } } -resource "kubernetes_manifest" "db_init_job" { +resource "kubernetes_job" "db_init_job" { for_each = { for idx, instance in var.instances : instance.name => instance } - manifest = { - apiVersion = "batch/v1" - kind = "Job" - metadata = { - name = "create-db-${each.key}" - namespace = coalesce(each.value.namespace, var.operator_namespace) - } - spec = { - template = { - spec = { - containers = [{ - name = "init-db" - image = "postgres:${var.postgres_version}" - command = [ - "/bin/sh", - "-c", - format( - "psql $DATABASE_URL -c \"CREATE DATABASE %s;\"", - coalesce(each.value.database_name, "${each.key}_db") - ) - ] - env = [ - { - name = "DATABASE_URL" - value = format( - "postgres://%s:%s@%s/%s?sslmode=require", - each.value.database_username, - each.value.database_password, - each.value.database_host, - "postgres" # Default database to connect to - ) - } - ] - }] - restartPolicy = "OnFailure" + metadata { + name = "create-db-${each.key}" + namespace = coalesce(each.value.namespace, var.operator_namespace) + } + + spec { + backoff_limit = 3 + template { + metadata { + labels = { + app = "init-db-${each.key}" + } + } + spec { + container { + name = "init-db" + image = "postgres:${var.postgres_version}" + + command = [ + "/bin/sh", + "-c", + format( + "psql $DATABASE_URL -c \"CREATE DATABASE %s;\"", + coalesce(each.value.database_name, "${each.key}_db") + ) + ] + + env { + name = "DATABASE_URL" + value = format( + "postgres://%s:%s@%s/%s?sslmode=require", + each.value.database_username, + each.value.database_password, + each.value.database_host, + "postgres" // Default database + ) + } } + + restart_policy = "OnFailure" } - backoffLimit = 3 } } } diff --git a/modules/operator/variables.tf b/modules/operator/variables.tf index ab9416b..83eebe2 100644 --- a/modules/operator/variables.tf +++ b/modules/operator/variables.tf @@ -44,7 +44,6 @@ variable "instances" { description = "Configuration for Materialize instances" type = list(object({ name = string - instance_id = string namespace = optional(string, "materialize-environment") database_name = string database_username = string diff --git a/outputs.tf b/outputs.tf index 1c032d9..03abf2e 100644 --- a/outputs.tf +++ b/outputs.tf @@ -8,6 +8,11 @@ output "eks_cluster_endpoint" { value = module.eks.cluster_endpoint } +output "eks_cluster_name" { + description = "EKS cluster name" + value = module.eks.cluster_name +} + output "database_endpoint" { description = "RDS instance endpoint" value = module.database.db_instance_endpoint diff --git a/providers.tf b/providers.tf index 44a18eb..5c68240 100644 --- a/providers.tf +++ b/providers.tf @@ -8,6 +8,11 @@ provider "helm" { kubernetes { host = module.eks.cluster_endpoint cluster_ca_certificate = base64decode(module.eks.cluster_certificate_authority_data) - token = data.aws_eks_cluster_auth.cluster.token + + exec { + api_version = "client.authentication.k8s.io/v1beta1" + command = "aws" + args = ["eks", "get-token", "--cluster-name", module.eks.cluster_name] + } } } diff --git a/terraform.tfvars.example b/terraform.tfvars.example index 589f52a..0b096a4 100644 --- a/terraform.tfvars.example +++ b/terraform.tfvars.example @@ -26,20 +26,17 @@ install_materialize_operator = false materialize_instances = [ { name = "analytics" - instance_id = "12345678-1234-1234-1234-123456789012" namespace = "analytics-env" # Separate namespace database_password = "secure-password-1" cpu_request = "4" }, { name = "reporting" - instance_id = "87654321-4321-4321-4321-987654321098" # No namespace specified - will use the operator namespace database_password = "secure-password-2" }, { name = "monitoring" - instance_id = "11111111-2222-3333-4444-555555555555" namespace = "analytics-env" # Share namespace with analytics database_password = "secure-password-3" } diff --git a/variables.tf b/variables.tf index 620a5e5..26dc0a5 100644 --- a/variables.tf +++ b/variables.tf @@ -270,7 +270,6 @@ variable "materialize_instances" { description = "Configuration for Materialize instances" type = list(object({ name = string - instance_id = string namespace = optional(string) database_name = optional(string) database_username = optional(string) From 36e745e4599e42ff713e6585bcbd119be2ffe079 Mon Sep 17 00:00:00 2001 From: Bobby Iliev Date: Wed, 15 Jan 2025 14:07:34 +0200 Subject: [PATCH 08/14] Switch to the abstracted helm module --- README.md | 10 +- examples/simple/main.tf | 40 ++++--- main.tf | 106 ++++++++++++------- modules/operator/main.tf | 194 ---------------------------------- modules/operator/outputs.tf | 34 ------ modules/operator/variables.tf | 63 ----------- modules/operator/versions.tf | 18 ---- outputs.tf | 8 ++ variables.tf | 34 ++++-- 9 files changed, 137 insertions(+), 370 deletions(-) delete mode 100644 modules/operator/main.tf delete mode 100644 modules/operator/outputs.tf delete mode 100644 modules/operator/variables.tf delete mode 100644 modules/operator/versions.tf diff --git a/README.md b/README.md index 73ee6b1..ca6111b 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ The module has been tested with: | [database](#module\_database) | ./modules/database | n/a | | [eks](#module\_eks) | ./modules/eks | n/a | | [networking](#module\_networking) | ./modules/networking | n/a | -| [operator](#module\_operator) | ./modules/operator | n/a | +| [operator](#module\_operator) | github.com/MaterializeInc/terraform-helm-materialize | v0.1.0 | | [storage](#module\_storage) | ./modules/storage | n/a | ## Resources @@ -45,7 +45,9 @@ The module has been tested with: | [aws_iam_role_policy.materialize_s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role_policy) | resource | | [aws_iam_user.materialize](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user) | resource | | [aws_iam_user_policy.materialize_s3](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_user_policy) | resource | +| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | | [aws_eks_cluster_auth.cluster](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/eks_cluster_auth) | data source | +| [aws_region.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/region) | data source | ## Inputs @@ -69,10 +71,11 @@ The module has been tested with: | [enable\_cluster\_creator\_admin\_permissions](#input\_enable\_cluster\_creator\_admin\_permissions) | To add the current caller identity as an administrator | `bool` | `true` | no | | [enable\_monitoring](#input\_enable\_monitoring) | Enable CloudWatch monitoring | `bool` | `true` | no | | [environment](#input\_environment) | Environment name (e.g., prod, staging, dev) | `string` | n/a | yes | +| [helm\_values](#input\_helm\_values) | Additional Helm values to merge with defaults | `any` | `{}` | no | | [install\_materialize\_operator](#input\_install\_materialize\_operator) | Whether to install the Materialize operator | `bool` | `false` | no | | [kubernetes\_namespace](#input\_kubernetes\_namespace) | The Kubernetes namespace for the Materialize resources | `string` | `"materialize-environment"` | no | | [log\_group\_name\_prefix](#input\_log\_group\_name\_prefix) | Prefix for the CloudWatch log group name (will be combined with environment name) | `string` | `"materialize"` | no | -| [materialize\_instances](#input\_materialize\_instances) | Configuration for Materialize instances |
list(object({
name = string
namespace = optional(string)
database_name = optional(string)
database_username = optional(string)
database_password = optional(string)
database_host = optional(string)
cpu_request = optional(string)
memory_request = optional(string)
memory_limit = optional(string)
}))
| `[]` | no | +| [materialize\_instances](#input\_materialize\_instances) | Configuration for Materialize instances |
list(object({
name = string
namespace = optional(string)
database_name = string
environmentd_version = optional(string, "v0.127.1")
cpu_request = optional(string, "1")
memory_request = optional(string, "1Gi")
memory_limit = optional(string, "1Gi")
}))
| `[]` | no | | [metrics\_retention\_days](#input\_metrics\_retention\_days) | Number of days to retain CloudWatch metrics | `number` | `7` | no | | [namespace](#input\_namespace) | Namespace for all resources, usually the organization or project name | `string` | n/a | yes | | [network\_id](#input\_network\_id) | The ID of the VPC in which resources will be deployed. Only used if create\_vpc is false. | `string` | `""` | no | @@ -83,6 +86,8 @@ The module has been tested with: | [node\_group\_instance\_types](#input\_node\_group\_instance\_types) | Instance types for worker nodes.

Recommended Configuration for Running Materialize with disk:
- Tested instance types: `m6g`, `m7g` families (ARM-based Graviton instances)
- AMI: AWS Bottlerocket (optimized for container workloads)
- Note: Ensure instance store volumes are available and attached to the nodes for optimal performance with disk-based workloads. | `list(string)` |
[
"m6g.medium"
]
| no | | [node\_group\_max\_size](#input\_node\_group\_max\_size) | Maximum number of worker nodes | `number` | `4` | no | | [node\_group\_min\_size](#input\_node\_group\_min\_size) | Minimum number of worker nodes | `number` | `1` | no | +| [operator\_namespace](#input\_operator\_namespace) | Namespace for the Materialize operator | `string` | `"materialize"` | no | +| [operator\_version](#input\_operator\_version) | Version of the Materialize operator to install | `string` | `"v25.1.0-beta.1"` | no | | [postgres\_version](#input\_postgres\_version) | Version of PostgreSQL to use | `string` | `"15"` | no | | [private\_subnet\_cidrs](#input\_private\_subnet\_cidrs) | CIDR blocks for private subnets | `list(string)` |
[
"10.0.1.0/24",
"10.0.2.0/24",
"10.0.3.0/24"
]
| no | | [public\_subnet\_cidrs](#input\_public\_subnet\_cidrs) | CIDR blocks for public subnets | `list(string)` |
[
"10.0.101.0/24",
"10.0.102.0/24",
"10.0.103.0/24"
]
| no | @@ -101,6 +106,7 @@ The module has been tested with: | [materialize\_s3\_role\_arn](#output\_materialize\_s3\_role\_arn) | The ARN of the IAM role for Materialize | | [metadata\_backend\_url](#output\_metadata\_backend\_url) | PostgreSQL connection URL in the format required by Materialize | | [oidc\_provider\_arn](#output\_oidc\_provider\_arn) | The ARN of the OIDC Provider | +| [operator\_details](#output\_operator\_details) | Details of the installed Materialize operator | | [persist\_backend\_url](#output\_persist\_backend\_url) | S3 connection URL in the format required by Materialize using IRSA | | [s3\_bucket\_name](#output\_s3\_bucket\_name) | Name of the S3 bucket | | [vpc\_id](#output\_vpc\_id) | VPC ID | diff --git a/examples/simple/main.tf b/examples/simple/main.tf index 61dafb2..eb02d27 100644 --- a/examples/simple/main.tf +++ b/examples/simple/main.tf @@ -9,8 +9,8 @@ module "materialize_infrastructure" { # The namespace and environment variables are used to construct the names of the resources # e.g. ${namespace}-${environment}-storage, ${namespace}-${environment}-db etc. - namespace = "simple-mz-tf" - environment = "dev" + namespace = var.namespace + environment = var.environment # VPC Configuration vpc_cidr = "10.0.0.0/16" @@ -55,20 +55,20 @@ module "materialize_infrastructure" { # Uncomment the following block (or provide your own instances) to configure them. # materialize_instances = [ # { - # name = "analytics" - # namespace = "materialize-environment" - # database_name = "analytics_db" - # database_username = "materialize" - # database_password = var.database_password - # database_host = module.materialize_infrastructure.database_endpoint + # name = "analytics" + # namespace = "materialize-environment" + # database_name = "analytics_db" + # cpu_request = "2" + # memory_request = "4Gi" + # memory_limit = "4Gi" # }, # { - # name = "production" - # namespace = "materialize-environment" - # database_name = "production_db" - # database_username = "materialize" - # database_password = var.database_password - # database_host = module.materialize_infrastructure.database_endpoint + # name = "production" + # namespace = "materialize-environment" + # database_name = "production_db" + # cpu_request = "4" + # memory_request = "8Gi" + # memory_limit = "8Gi" # } # ] @@ -80,6 +80,18 @@ module "materialize_infrastructure" { } } +variable "namespace" { + description = "Namespace for the resources. Used to prefix the names of the resources" + type = string + default = "simple-mz-tf" +} + +variable "environment" { + description = "Environment name" + type = string + default = "dev" +} + variable "database_password" { description = "Password for the database (should be provided via tfvars or environment variable)" default = "your-secure-password" diff --git a/main.tf b/main.tf index 6f50214..defca9c 100644 --- a/main.tf +++ b/main.tf @@ -79,53 +79,84 @@ module "database" { } module "operator" { - count = var.install_materialize_operator ? 1 : 0 - source = "./modules/operator" - - namespace = var.namespace - environment = var.environment - instances = var.materialize_instances - iam_role_arn = aws_iam_role.materialize_s3.arn - cluster_endpoint = module.eks.cluster_endpoint - cluster_ca_certificate = module.eks.cluster_certificate_authority_data - s3_bucket_name = module.storage.bucket_name - postgres_version = var.postgres_version + source = "github.com/MaterializeInc/terraform-helm-materialize?ref=v0.1.0" - providers = { - kubernetes = kubernetes - helm = helm - } + count = var.install_materialize_operator ? 1 : 0 depends_on = [ module.eks, - module.storage, - module.database + module.database, + module.storage ] + + namespace = var.namespace + environment = var.environment + operator_version = var.operator_version + operator_namespace = var.operator_namespace + + helm_values = local.merged_helm_values + instances = local.instances + + providers = { + kubernetes = kubernetes + helm = helm + } } locals { network_id = var.create_vpc ? module.networking.vpc_id : var.network_id network_private_subnet_ids = var.create_vpc ? module.networking.private_subnet_ids : var.network_private_subnet_ids - # instance_backend_urls = { - # for instance in var.materialize_instances : instance.name => { - # metadata_backend_url = format( - # "postgres://%s:%s@%s/%s?sslmode=require", - # coalesce(instance.database_username, var.database_username), - # coalesce(instance.database_password, var.database_password), - # module.database.db_instance_endpoint, - # coalesce(instance.database_name, "${instance.name}_db") - # ) - # persist_backend_url = format( - # "s3://%s/%s/%s:serviceaccount:%s:%s", - # module.storage.bucket_name, - # var.environment, - # instance.name, - # coalesce(instance.namespace, "materialize-environment"), - # instance.name - # ) - # } - # } + default_helm_values = { + operator = { + cloudProvider = { + type = "aws" + region = data.aws_region.current.name + providers = { + aws = { + enabled = true + accountID = data.aws_caller_identity.current.account_id + iam = { + roles = { + environment = aws_iam_role.materialize_s3.arn + } + } + } + } + } + } + } + + merged_helm_values = merge(local.default_helm_values, var.helm_values) + + instances = [ + for instance in var.materialize_instances : { + name = instance.name + namespace = instance.namespace + database_name = instance.database_name + + metadata_backend_url = format( + "postgres://%s:%s@%s/%s?sslmode=require", + var.database_username, + var.database_password, + module.database.db_instance_endpoint, + coalesce(instance.database_name, instance.name) + ) + + persist_backend_url = format( + "s3://%s/%s-%s:serviceaccount:%s:%s", + module.storage.bucket_name, + var.environment, + instance.name, + coalesce(instance.namespace, var.operator_namespace), + instance.name + ) + + cpu_request = instance.cpu_request + memory_request = instance.memory_request + memory_limit = instance.memory_limit + } + ] # Common tags that apply to all resources common_tags = merge( @@ -240,3 +271,6 @@ locals { data "aws_eks_cluster_auth" "cluster" { name = module.eks.cluster_name } + +data "aws_region" "current" {} +data "aws_caller_identity" "current" {} diff --git a/modules/operator/main.tf b/modules/operator/main.tf deleted file mode 100644 index 55b86fd..0000000 --- a/modules/operator/main.tf +++ /dev/null @@ -1,194 +0,0 @@ -locals { - name_prefix = "${var.namespace}-${var.environment}" -} - -resource "kubernetes_namespace" "materialize" { - metadata { - name = var.operator_namespace - } -} - -resource "kubernetes_namespace" "instance_namespaces" { - for_each = toset(compact([for instance in var.instances : instance.namespace if instance.namespace != null])) - - metadata { - name = each.key - } -} - -resource "helm_release" "materialize_operator" { - name = local.name_prefix - namespace = kubernetes_namespace.materialize.metadata[0].name - # TODO: Publish the chart to a public repository, currently using a forked version of the chart - repository = "https://raw.githubusercontent.com/bobbyiliev/materialize/refs/heads/helm-chart-package/misc/helm-charts" - chart = "materialize-operator" - # version = var.operator_version - # TODO: Use the latest version of the chart - version = "v25.1.0-beta.1" - - values = [ - yamlencode({ - operator = { - cloudProvider = { - type = "aws" - region = data.aws_region.current.name - providers = { - aws = { - enabled = true - accountID = data.aws_caller_identity.current.account_id - iam = { - roles = { - environment = var.iam_role_arn - } - } - } - } - } - } - }) - ] - - depends_on = [kubernetes_namespace.materialize] -} - -resource "kubernetes_secret" "materialize_backends" { - for_each = { for idx, instance in var.instances : instance.name => instance } - - metadata { - name = "${each.key}-materialize-backend" - namespace = coalesce(each.value.namespace, var.operator_namespace) - } - - data = { - metadata_backend_url = format( - "postgres://%s:%s@%s/%s?sslmode=require", - each.value.database_username, - each.value.database_password, - each.value.database_host, - coalesce(each.value.database_name, "${each.key}_db") - ) - persist_backend_url = format( - "s3://%s/%s-%s:serviceaccount:%s:%s", - var.s3_bucket_name, - var.environment, - each.key, - coalesce(each.value.namespace, kubernetes_namespace.materialize.metadata[0].name), - each.value.name - ) - } -} - -# The kubernetes_manifest resource is used to create Materialize instances -# It currently has a few limitations: -# - It requires the Kubernetes cluster to be running, otherwise it will fail to connect -# - It requires the Materialize operator to be installed in the cluster, otherwise it will fail -# Tracking issue: -# https://github.com/hashicorp/terraform-provider-kubernetes/issues/1775 -resource "kubernetes_manifest" "materialize_instances" { - for_each = { for idx, instance in var.instances : instance.name => instance } - - manifest = { - apiVersion = "materialize.cloud/v1alpha1" - kind = "Materialize" - metadata = { - name = each.value.name - namespace = coalesce(each.value.namespace, var.operator_namespace) - } - spec = { - environmentdImageRef = "materialize/environmentd:${var.operator_version}" - backendSecretName = "${each.key}-materialize-backend" - environmentdResourceRequirements = { - limits = { - memory = each.value.memory_limit - } - requests = { - cpu = each.value.cpu_request - memory = each.value.memory_request - } - } - balancerdResourceRequirements = { - limits = { - memory = "256Mi" - } - requests = { - cpu = "100m" - memory = "256Mi" - } - } - } - } - - depends_on = [ - helm_release.materialize_operator, - kubernetes_secret.materialize_backends, - kubernetes_namespace.instance_namespaces - ] -} - -# Materialize does not currently create databases within the instances, so we need to create them ourselves -resource "kubernetes_config_map" "db_init_configmap" { - for_each = { for idx, instance in var.instances : instance.name => instance } - - metadata { - name = "init-db-script-${each.key}" - namespace = coalesce(each.value.namespace, var.operator_namespace) - } - - data = { - "init.sql" = format( - "CREATE DATABASE IF NOT EXISTS %s;", - coalesce(each.value.database_name, "${each.key}_db") - ) - } -} - -resource "kubernetes_job" "db_init_job" { - for_each = { for idx, instance in var.instances : instance.name => instance } - - metadata { - name = "create-db-${each.key}" - namespace = coalesce(each.value.namespace, var.operator_namespace) - } - - spec { - backoff_limit = 3 - template { - metadata { - labels = { - app = "init-db-${each.key}" - } - } - spec { - container { - name = "init-db" - image = "postgres:${var.postgres_version}" - - command = [ - "/bin/sh", - "-c", - format( - "psql $DATABASE_URL -c \"CREATE DATABASE %s;\"", - coalesce(each.value.database_name, "${each.key}_db") - ) - ] - - env { - name = "DATABASE_URL" - value = format( - "postgres://%s:%s@%s/%s?sslmode=require", - each.value.database_username, - each.value.database_password, - each.value.database_host, - "postgres" // Default database - ) - } - } - - restart_policy = "OnFailure" - } - } - } -} - -data "aws_region" "current" {} -data "aws_caller_identity" "current" {} diff --git a/modules/operator/outputs.tf b/modules/operator/outputs.tf deleted file mode 100644 index dad8bc9..0000000 --- a/modules/operator/outputs.tf +++ /dev/null @@ -1,34 +0,0 @@ -output "operator_namespace" { - description = "Namespace where the operator is installed" - value = kubernetes_namespace.materialize.metadata[0].name -} - -output "operator_release_name" { - description = "Helm release name of the operator" - value = helm_release.materialize_operator.name -} - -output "operator_release_status" { - description = "Status of the helm release" - value = helm_release.materialize_operator.status -} - -output "materialize_instances" { - description = "Details of created Materialize instances" - value = { - for name, instance in kubernetes_manifest.materialize_instances : name => { - id = instance.manifest.metadata.name - namespace = instance.manifest.metadata.namespace - } - } -} - -output "cluster_endpoint" { - description = "Outcluster endpoint for Materialize instances" - value = var.cluster_endpoint -} - -output "cluster_ca_certificate" { - description = "CA certificate for the EKS cluster" - value = var.cluster_ca_certificate -} diff --git a/modules/operator/variables.tf b/modules/operator/variables.tf deleted file mode 100644 index 83eebe2..0000000 --- a/modules/operator/variables.tf +++ /dev/null @@ -1,63 +0,0 @@ -variable "namespace" { - description = "Namespace prefix for all resources" - type = string -} - -variable "environment" { - description = "Environment name" - type = string -} - -variable "operator_version" { - description = "Version of the Materialize operator to install" - type = string - default = "v0.127.1" -} - -variable "iam_role_arn" { - description = "IAM role ARN for Materialize S3 access" - type = string -} - -variable "cluster_endpoint" { - description = "EKS cluster endpoint" - type = string -} - -variable "cluster_ca_certificate" { - description = "EKS cluster CA certificate" - type = string -} - -variable "s3_bucket_name" { - description = "Name of the S3 bucket for Materialize storage" - type = string -} - -variable "operator_namespace" { - description = "Namespace for the Materialize operator" - type = string - default = "materialize" -} - -variable "instances" { - description = "Configuration for Materialize instances" - type = list(object({ - name = string - namespace = optional(string, "materialize-environment") - database_name = string - database_username = string - database_password = string - database_host = string - cpu_request = optional(string, "1") - memory_request = optional(string, "1Gi") - memory_limit = optional(string, "1Gi") - })) - default = [] -} - -variable "postgres_version" { - description = "Postgres version to use for the metadata backend" - type = string - default = "15" -} diff --git a/modules/operator/versions.tf b/modules/operator/versions.tf deleted file mode 100644 index 6f04d7c..0000000 --- a/modules/operator/versions.tf +++ /dev/null @@ -1,18 +0,0 @@ -terraform { - required_version = ">= 1.0" - - required_providers { - aws = { - source = "hashicorp/aws" - version = "~> 5.0" - } - kubernetes = { - source = "hashicorp/kubernetes" - version = "~> 2.0" - } - helm = { - source = "hashicorp/helm" - version = "~> 2.0" - } - } -} diff --git a/outputs.tf b/outputs.tf index 03abf2e..800bc37 100644 --- a/outputs.tf +++ b/outputs.tf @@ -55,3 +55,11 @@ output "materialize_s3_role_arn" { description = "The ARN of the IAM role for Materialize" value = aws_iam_role.materialize_s3.arn } + +output "operator_details" { + description = "Details of the installed Materialize operator" + value = var.install_materialize_operator ? { + namespace = module.operator[0].operator_namespace + instances = module.operator[0].materialize_instances + } : null +} diff --git a/variables.tf b/variables.tf index 26dc0a5..7454ddd 100644 --- a/variables.tf +++ b/variables.tf @@ -266,18 +266,34 @@ variable "install_materialize_operator" { default = false } +variable "operator_version" { + description = "Version of the Materialize operator to install" + type = string + default = "v25.1.0-beta.1" +} + +variable "operator_namespace" { + description = "Namespace for the Materialize operator" + type = string + default = "materialize" +} + +variable "helm_values" { + description = "Additional Helm values to merge with defaults" + type = any + default = {} +} + variable "materialize_instances" { description = "Configuration for Materialize instances" type = list(object({ - name = string - namespace = optional(string) - database_name = optional(string) - database_username = optional(string) - database_password = optional(string) - database_host = optional(string) - cpu_request = optional(string) - memory_request = optional(string) - memory_limit = optional(string) + name = string + namespace = optional(string) + database_name = string + environmentd_version = optional(string, "v0.127.1") + cpu_request = optional(string, "1") + memory_request = optional(string, "1Gi") + memory_limit = optional(string, "1Gi") })) default = [] } From af381f71c6c938650eba1e6a111f8a47974d81b1 Mon Sep 17 00:00:00 2001 From: Bobby Iliev Date: Wed, 15 Jan 2025 16:23:01 +0200 Subject: [PATCH 09/14] Create data sources file --- README.md | 2 +- datasources.tf | 6 ++++++ main.tf | 7 ------- modules/storage/variables.tf | 2 +- variables.tf | 2 +- 5 files changed, 9 insertions(+), 10 deletions(-) create mode 100644 datasources.tf diff --git a/README.md b/README.md index ca6111b..ca7f304 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,7 @@ The module has been tested with: | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [availability\_zones](#input\_availability\_zones) | List of availability zones | `list(string)` |
[
"us-east-1a",
"us-east-1b",
"us-east-1c"
]
| no | -| [bucket\_force\_destroy](#input\_bucket\_force\_destroy) | Enable force destroy for the S3 bucket | `bool` | `false` | no | +| [bucket\_force\_destroy](#input\_bucket\_force\_destroy) | Enable force destroy for the S3 bucket | `bool` | `true` | no | | [bucket\_lifecycle\_rules](#input\_bucket\_lifecycle\_rules) | List of lifecycle rules for the S3 bucket |
list(object({
id = string
enabled = bool
prefix = string
transition_days = number
transition_storage_class = string
expiration_days = number
noncurrent_version_expiration_days = number
}))
|
[
{
"enabled": true,
"expiration_days": 365,
"id": "cleanup",
"noncurrent_version_expiration_days": 90,
"prefix": "",
"transition_days": 90,
"transition_storage_class": "STANDARD_IA"
}
]
| no | | [cluster\_enabled\_log\_types](#input\_cluster\_enabled\_log\_types) | List of desired control plane logging to enable | `list(string)` |
[
"api",
"audit",
"authenticator",
"controllerManager",
"scheduler"
]
| no | | [cluster\_version](#input\_cluster\_version) | Kubernetes version for the EKS cluster | `string` | `"1.31"` | no | diff --git a/datasources.tf b/datasources.tf new file mode 100644 index 0000000..ef3873f --- /dev/null +++ b/datasources.tf @@ -0,0 +1,6 @@ +data "aws_eks_cluster_auth" "cluster" { + name = module.eks.cluster_name +} + +data "aws_region" "current" {} +data "aws_caller_identity" "current" {} diff --git a/main.tf b/main.tf index defca9c..d0bb27f 100644 --- a/main.tf +++ b/main.tf @@ -267,10 +267,3 @@ resource "aws_iam_role_policy" "materialize_s3" { locals { name_prefix = "${var.namespace}-${var.environment}" } - -data "aws_eks_cluster_auth" "cluster" { - name = module.eks.cluster_name -} - -data "aws_region" "current" {} -data "aws_caller_identity" "current" {} diff --git a/modules/storage/variables.tf b/modules/storage/variables.tf index 62b97c5..8726a39 100644 --- a/modules/storage/variables.tf +++ b/modules/storage/variables.tf @@ -11,7 +11,7 @@ variable "environment" { variable "bucket_force_destroy" { description = "Enable force destroy for the S3 bucket" type = bool - default = false + default = true } variable "enable_bucket_versioning" { diff --git a/variables.tf b/variables.tf index 7454ddd..2b217cc 100644 --- a/variables.tf +++ b/variables.tf @@ -191,7 +191,7 @@ variable "db_multi_az" { variable "bucket_force_destroy" { description = "Enable force destroy for the S3 bucket" type = bool - default = false + default = true } variable "enable_bucket_versioning" { From 28502fc0c092c6727509970bf6fdb27c7c67ee40 Mon Sep 17 00:00:00 2001 From: Bobby Iliev Date: Fri, 17 Jan 2025 15:38:23 +0200 Subject: [PATCH 10/14] Change example db names --- examples/simple/main.tf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/simple/main.tf b/examples/simple/main.tf index eb02d27..7abaf2e 100644 --- a/examples/simple/main.tf +++ b/examples/simple/main.tf @@ -63,9 +63,9 @@ module "materialize_infrastructure" { # memory_limit = "4Gi" # }, # { - # name = "production" + # name = "demo" # namespace = "materialize-environment" - # database_name = "production_db" + # database_name = "demo_db" # cpu_request = "4" # memory_request = "8Gi" # memory_limit = "8Gi" From 7002de99e0e335882a878d7ebfa53085fcc28fa1 Mon Sep 17 00:00:00 2001 From: Bobby Iliev Date: Tue, 21 Jan 2025 13:54:11 +0200 Subject: [PATCH 11/14] Bump Helm terraform module to v0.1.1 --- README.md | 4 ++-- docs/header.md | 2 +- main.tf | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ca7f304..e7e3b65 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ Terraform module for deploying Materialize on AWS Cloud Platform with all requir The module has been tested with: - PostgreSQL 15 -- Materialize Operator v0.1.0 +- Materialize Helm Operator Terraform Module v0.1.1 ## Requirements @@ -32,7 +32,7 @@ The module has been tested with: | [database](#module\_database) | ./modules/database | n/a | | [eks](#module\_eks) | ./modules/eks | n/a | | [networking](#module\_networking) | ./modules/networking | n/a | -| [operator](#module\_operator) | github.com/MaterializeInc/terraform-helm-materialize | v0.1.0 | +| [operator](#module\_operator) | github.com/MaterializeInc/terraform-helm-materialize | v0.1.1 | | [storage](#module\_storage) | ./modules/storage | n/a | ## Resources diff --git a/docs/header.md b/docs/header.md index 66e1b15..f771633 100644 --- a/docs/header.md +++ b/docs/header.md @@ -6,4 +6,4 @@ Terraform module for deploying Materialize on AWS Cloud Platform with all requir The module has been tested with: - PostgreSQL 15 -- Materialize Operator v0.1.0 +- Materialize Helm Operator Terraform Module v0.1.1 diff --git a/main.tf b/main.tf index d0bb27f..93aaa90 100644 --- a/main.tf +++ b/main.tf @@ -79,7 +79,7 @@ module "database" { } module "operator" { - source = "github.com/MaterializeInc/terraform-helm-materialize?ref=v0.1.0" + source = "github.com/MaterializeInc/terraform-helm-materialize?ref=v0.1.1" count = var.install_materialize_operator ? 1 : 0 From 494e76468ca93bf2102d03e86758e3ed22d49be1 Mon Sep 17 00:00:00 2001 From: Bobby Iliev Date: Tue, 21 Jan 2025 13:55:32 +0200 Subject: [PATCH 12/14] Bump environmentd version to v0.130.0 --- README.md | 2 +- variables.tf | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e7e3b65..6c7b135 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ The module has been tested with: | [install\_materialize\_operator](#input\_install\_materialize\_operator) | Whether to install the Materialize operator | `bool` | `false` | no | | [kubernetes\_namespace](#input\_kubernetes\_namespace) | The Kubernetes namespace for the Materialize resources | `string` | `"materialize-environment"` | no | | [log\_group\_name\_prefix](#input\_log\_group\_name\_prefix) | Prefix for the CloudWatch log group name (will be combined with environment name) | `string` | `"materialize"` | no | -| [materialize\_instances](#input\_materialize\_instances) | Configuration for Materialize instances |
list(object({
name = string
namespace = optional(string)
database_name = string
environmentd_version = optional(string, "v0.127.1")
cpu_request = optional(string, "1")
memory_request = optional(string, "1Gi")
memory_limit = optional(string, "1Gi")
}))
| `[]` | no | +| [materialize\_instances](#input\_materialize\_instances) | Configuration for Materialize instances |
list(object({
name = string
namespace = optional(string)
database_name = string
environmentd_version = optional(string, "v0.130.0")
cpu_request = optional(string, "1")
memory_request = optional(string, "1Gi")
memory_limit = optional(string, "1Gi")
}))
| `[]` | no | | [metrics\_retention\_days](#input\_metrics\_retention\_days) | Number of days to retain CloudWatch metrics | `number` | `7` | no | | [namespace](#input\_namespace) | Namespace for all resources, usually the organization or project name | `string` | n/a | yes | | [network\_id](#input\_network\_id) | The ID of the VPC in which resources will be deployed. Only used if create\_vpc is false. | `string` | `""` | no | diff --git a/variables.tf b/variables.tf index 2b217cc..ccc9330 100644 --- a/variables.tf +++ b/variables.tf @@ -290,7 +290,7 @@ variable "materialize_instances" { name = string namespace = optional(string) database_name = string - environmentd_version = optional(string, "v0.127.1") + environmentd_version = optional(string, "v0.130.0") cpu_request = optional(string, "1") memory_request = optional(string, "1Gi") memory_limit = optional(string, "1Gi") From 61342416b98bf7c3b49694eeb2b1ad3bd7a6a8d7 Mon Sep 17 00:00:00 2001 From: Bobby Iliev Date: Tue, 21 Jan 2025 14:38:03 +0200 Subject: [PATCH 13/14] Add orechestratord version var --- README.md | 1 + main.tf | 3 +++ variables.tf | 6 ++++++ 3 files changed, 10 insertions(+) diff --git a/README.md b/README.md index 6c7b135..f9ba622 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,7 @@ The module has been tested with: | [node\_group\_min\_size](#input\_node\_group\_min\_size) | Minimum number of worker nodes | `number` | `1` | no | | [operator\_namespace](#input\_operator\_namespace) | Namespace for the Materialize operator | `string` | `"materialize"` | no | | [operator\_version](#input\_operator\_version) | Version of the Materialize operator to install | `string` | `"v25.1.0-beta.1"` | no | +| [orchestratord\_version](#input\_orchestratord\_version) | Version of the Materialize orchestrator to install | `string` | `"v0.130.0"` | no | | [postgres\_version](#input\_postgres\_version) | Version of PostgreSQL to use | `string` | `"15"` | no | | [private\_subnet\_cidrs](#input\_private\_subnet\_cidrs) | CIDR blocks for private subnets | `list(string)` |
[
"10.0.1.0/24",
"10.0.2.0/24",
"10.0.3.0/24"
]
| no | | [public\_subnet\_cidrs](#input\_public\_subnet\_cidrs) | CIDR blocks for public subnets | `list(string)` |
[
"10.0.101.0/24",
"10.0.102.0/24",
"10.0.103.0/24"
]
| no | diff --git a/main.tf b/main.tf index 93aaa90..41989d1 100644 --- a/main.tf +++ b/main.tf @@ -109,6 +109,9 @@ locals { default_helm_values = { operator = { + image = { + tag = var.orchestratord_version + } cloudProvider = { type = "aws" region = data.aws_region.current.name diff --git a/variables.tf b/variables.tf index ccc9330..b81f5b9 100644 --- a/variables.tf +++ b/variables.tf @@ -278,6 +278,12 @@ variable "operator_namespace" { default = "materialize" } +variable "orchestratord_version" { + description = "Version of the Materialize orchestrator to install" + type = string + default = "v0.130.0" +} + variable "helm_values" { description = "Additional Helm values to merge with defaults" type = any From 75f7af89aa9845e5d5ec2d9dc0938f643f5fd19b Mon Sep 17 00:00:00 2001 From: Bobby Iliev Date: Tue, 21 Jan 2025 20:25:48 +0200 Subject: [PATCH 14/14] Bump version to v0.130.1 --- README.md | 4 ++-- variables.tf | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index f9ba622..d5deab5 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ The module has been tested with: | [install\_materialize\_operator](#input\_install\_materialize\_operator) | Whether to install the Materialize operator | `bool` | `false` | no | | [kubernetes\_namespace](#input\_kubernetes\_namespace) | The Kubernetes namespace for the Materialize resources | `string` | `"materialize-environment"` | no | | [log\_group\_name\_prefix](#input\_log\_group\_name\_prefix) | Prefix for the CloudWatch log group name (will be combined with environment name) | `string` | `"materialize"` | no | -| [materialize\_instances](#input\_materialize\_instances) | Configuration for Materialize instances |
list(object({
name = string
namespace = optional(string)
database_name = string
environmentd_version = optional(string, "v0.130.0")
cpu_request = optional(string, "1")
memory_request = optional(string, "1Gi")
memory_limit = optional(string, "1Gi")
}))
| `[]` | no | +| [materialize\_instances](#input\_materialize\_instances) | Configuration for Materialize instances |
list(object({
name = string
namespace = optional(string)
database_name = string
environmentd_version = optional(string, "v0.130.1")
cpu_request = optional(string, "1")
memory_request = optional(string, "1Gi")
memory_limit = optional(string, "1Gi")
}))
| `[]` | no | | [metrics\_retention\_days](#input\_metrics\_retention\_days) | Number of days to retain CloudWatch metrics | `number` | `7` | no | | [namespace](#input\_namespace) | Namespace for all resources, usually the organization or project name | `string` | n/a | yes | | [network\_id](#input\_network\_id) | The ID of the VPC in which resources will be deployed. Only used if create\_vpc is false. | `string` | `""` | no | @@ -88,7 +88,7 @@ The module has been tested with: | [node\_group\_min\_size](#input\_node\_group\_min\_size) | Minimum number of worker nodes | `number` | `1` | no | | [operator\_namespace](#input\_operator\_namespace) | Namespace for the Materialize operator | `string` | `"materialize"` | no | | [operator\_version](#input\_operator\_version) | Version of the Materialize operator to install | `string` | `"v25.1.0-beta.1"` | no | -| [orchestratord\_version](#input\_orchestratord\_version) | Version of the Materialize orchestrator to install | `string` | `"v0.130.0"` | no | +| [orchestratord\_version](#input\_orchestratord\_version) | Version of the Materialize orchestrator to install | `string` | `"v0.130.1"` | no | | [postgres\_version](#input\_postgres\_version) | Version of PostgreSQL to use | `string` | `"15"` | no | | [private\_subnet\_cidrs](#input\_private\_subnet\_cidrs) | CIDR blocks for private subnets | `list(string)` |
[
"10.0.1.0/24",
"10.0.2.0/24",
"10.0.3.0/24"
]
| no | | [public\_subnet\_cidrs](#input\_public\_subnet\_cidrs) | CIDR blocks for public subnets | `list(string)` |
[
"10.0.101.0/24",
"10.0.102.0/24",
"10.0.103.0/24"
]
| no | diff --git a/variables.tf b/variables.tf index b81f5b9..629bdab 100644 --- a/variables.tf +++ b/variables.tf @@ -281,7 +281,7 @@ variable "operator_namespace" { variable "orchestratord_version" { description = "Version of the Materialize orchestrator to install" type = string - default = "v0.130.0" + default = "v0.130.1" } variable "helm_values" { @@ -296,7 +296,7 @@ variable "materialize_instances" { name = string namespace = optional(string) database_name = string - environmentd_version = optional(string, "v0.130.0") + environmentd_version = optional(string, "v0.130.1") cpu_request = optional(string, "1") memory_request = optional(string, "1Gi") memory_limit = optional(string, "1Gi")