Build Terraform Modules That Your Team Will Actually Reuse

Sedang Trending 2 bulan yang lalu

Many organizations struggle pinch Terraform module adoption, experiencing challenges specified as:

  • Version fragmentation: Different projects/teams extremity up connected different versions.
  • Breaking changes: Teams can’t upgrade without risking errors during aliases post-deployment.
  • Shadow modules: Teams constitute their ain erstwhile modules don’t fresh their needs.

This guideline shows really 2 package engineering principles tin toggle shape Terraform modules into components teams really want to use.

From Monolithic to Modular: 2 Patterns

Starting Point: What Most Teams Have

Most teams commencement pinch moving infrastructure: a bucket, immoderate personality and entree guidance (IAM) permissions and basal information settings. The problem isn’t that it’s broken; it’s conscionable that everything is tangled together successful 1 module:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

# modules/s3-with-access/main.tf

resource "aws_s3_bucket" "app_bucket" {

  bucket = "mycompany-app-uploads"  # Hardcoded name

}

resource "aws_iam_role" "app_role" {  # Creating roles wrong retention module

  name = "app-s3-access-role"

  assume_role_policy = jsonencode({

    Version = "2012-10-17"

    Statement = [{

      Action = "sts:AssumeRole"

      Effect = "Allow"

      Principal = { Service = "lambda.amazonaws.com" }  # Lambda only

    }]

  })

}

resource "aws_iam_role_policy" "app_bucket_access" {

  role = aws_iam_role.app_role.id

  policy = jsonencode({

    Version = "2012-10-17"

    Statement = [{

      Effect = "Allow"

      Action = ["s3:GetObject", "s3:PutObject"]  # Raw IAM actions

      Resource = "${aws_s3_bucket.app_bucket.arn}/*"

    }]

  })

}


This module has bundled successful nan bucket, nan IAM domiciled and nan policies, but what happens erstwhile you need:

  • The aforesaid bucket for an Elastic Container Service (ECS) task alternatively of Lambda? You can’t reuse this module because nan domiciled is hardcoded for Lambda.
  • Multiple services to entree 1 bucket? You’d request to transcript and modify nan full module for each service.
  • Just nan bucket without nan IAM role? They’re inseparably coupled.

This is why teams extremity up pinch somewhat different copies of nan aforesaid point – s3-module-lambda, s3-module-ecs, s3-module-ec2.

Pattern 1: Separation of Concerns — 1 Module, 1 Purpose

The first problem: Modules effort to do excessively much. When your S3 module besides creates IAM roles and policies, it becomes intolerable to reuse for different services.

Single work says each module does 1 point well. Let’s abstracted our concerns pinch a module that only manages S3 buckets. No IAM roles. No policies. Just buckets pinch sensible defaults.

S3 Module — Just Manages Buckets

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

# modules/s3/main.tf

locals {

  bucket_name = "${var.environment}-${replace(lower(var.name), "_", "-")}"

}

resource "aws_s3_bucket" "this" {

  bucket = local.bucket_name

  tags   = var.tags

}

resource "aws_s3_bucket_public_access_block" "this" {

  bucket = aws_s3_bucket.this.id

  block_public_acls       = true

  block_public_policy     = true

  ignore_public_acls      = true

  restrict_public_buckets = true

}

resource "aws_s3_bucket_versioning" "this" {

  count  = var.enable_versioning ? 1 : 0

  bucket = aws_s3_bucket.this.id

  versioning_configuration {

    status = "Enabled"

  }

}

output "arn" {

  value = aws_s3_bucket.this.arn

}

output "id" {

  value = aws_s3_bucket.this.id

}


In practice: Your S3 module will beryllium much complex, requiring encryption, cross-origin assets sharing (CORS), life rhythm policies and more. Keep IAM, networking and compute resources successful abstracted modules truthful that they become reusable crossed different services and teams.

Pattern 2: Composability — Modules That Work Together

The 2nd principle: Modules should constitute cleanly. Each module requires a clear interface pinch predictable outputs that different modules tin use.

First, create your infrastructure resources utilizing nan separated modules:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

# Create retention pinch nan S3 module

module "uploads" {

  source      = "./modules/s3"

  name        = "uploads"

  environment = "production"

}

module "backups" {

  source      = "./modules/s3"

  name        = "backups"

  environment = "production"

}

# Create compute resources

resource "aws_iam_role" "app_service" {

  name = "app-service"

  assume_role_policy = jsonencode({

    Version = "2012-10-17"

    Statement = [{

      Action = "sts:AssumeRole"

      Effect = "Allow"

      Principal = { Service = "ecs-tasks.amazonaws.com" }

    }]

  })

}


Then ligament them together pinch definitive permissions:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

# Grant nan work entree to nan buckets it needs

resource "aws_iam_role_policy" "app_access" {

  name = "app-bucket-access"

  role = aws_iam_role.app_service.name

  policy = jsonencode({

    Version = "2012-10-17"

    Statement = [

      {

        Effect = "Allow"

        Action = ["s3:GetObject", "s3:PutObject"]

        Resource = "${module.uploads.arn}/*"

      },

      {

        Effect = "Allow"

        Action = ["s3:PutObject"]

        Resource = "${module.backups.arn}/*"

      }

    ]

  })

}


Because modules person predictable interfaces:

  • Any work tin usage immoderate bucket.
  • Permissions are definitive and auditable.
  • No hidden limitations betwixt modules.
  • Each portion tin beryllium tested independently.

In practice: Your modules will beryllium larger units — an “application stack” aliases “data pipeline” alternatively than individual resources. Standardized interfaces and outputs fto modules activity together, whether you’re composing buckets and policies aliases full Virtual Private Clouds (VPCs) and Amazon Elastic Kubernetes Service (EKS) clusters. Predictable interfaces alteration composition.

From Patterns to Platform

These patterns lick nan protector module problem. Teams won’t request to bypass well-designed, composable modules. But you still look type fragmentation and breaking changes. When half your teams are connected an older type and only caller projects summation entree to nan latest version, each update now involves nan added complexity of migration.

The spread betwixt bully modules and a bully level is coordination. You request to make judge each squad benefits from improvements without forcing them to alteration their workflows.

We’ve built a caller level that makes this possible. With Suga, your Terraform modules go ocular building blocks. Every squad gets nan aforesaid unafraid defaults. Platform updates use each apps automatically, not conscionable caller ones. Developers constitute infrastructure done drag-and-drop, while your standards enforce themselves invisibly.

Good modules get reused. Great modules go platforms. Request early entree today.

YOUTUBE.COM/THENEWSTACK

Tech moves fast, don't miss an episode. Subscribe to our YouTube channel to watercourse each our podcasts, interviews, demos, and more.

Group Created pinch Sketch.

Selengkapnya