Receber por email
← Voltar para o catálogo

infrastructure-as-code

Provides Infrastructure as Code best practices for Terraform, Pulumi, CloudFormation, and OpenTofu. Use when provisioning infrastructure, writing IaC modules, managing cloud resources, scanning for misconfigurations, or when user mentions 'terraform', 'pulumi', 'cloudformation', 'IaC', 'opentofu', 'infrastructure', 'tfsec', 'checkov', 'drift'.

65estrelas
Atualizado há 4 meses

Ver no GitHub ↗ Licença: NOASSERTION

Como adicionar

/plugin marketplace add Tibsfox/gsd-skill-creator

O comando exato pode variar conforme o repositório. Confira o README no GitHub.

Para o autor da skill

Cole no README do seu repo

Mostra que sua skill está catalogada na Skillteca, gera backlink e tráfego rastreável.

[![Skillteca](https://www.skillteca.com.br/api/badge/infrastructure-as-code/svg)](https://www.skillteca.com.br/skills/infrastructure-as-code)

Skills relacionadas

Ver todas de DevOps e Infra →

Alerta por categoria

Receba novas skills de DevOps e Infra toda segunda

1 email curto, só com as skills novas de DevOps e Infra. 4 minutos de leitura, sem spam, cancela com 1 clique.

Você confirma o email no primeiro envio. Sem spam. Cancela com 1 clique.

Ler descrição completa

Infrastructure as Code

Best practices for managing cloud infrastructure declaratively with Terraform, Pulumi, CloudFormation, and OpenTofu. Covers module composition, state management, security scanning, and drift prevention.

IaC Tool Comparison

Choose the right tool based on team skills, cloud strategy, and operational requirements.

| Tool | Language | State Management | Multi-Cloud | Learning Curve | Ecosystem | |------|----------|-----------------|-------------|----------------|-----------| | Terraform | HCL | Remote backend (S3, GCS, etc.) | Excellent | Medium | Largest provider ecosystem | | OpenTofu | HCL | Same as Terraform | Excellent | Medium | Fork-compatible with Terraform | | Pulumi | TypeScript, Python, Go, C# | Pulumi Cloud or self-managed | Excellent | Low for developers | Growing, SDK-based | | CloudFormation | YAML/JSON | AWS-managed | AWS only | Medium | Native AWS integration | | CDK | TypeScript, Python, Java, Go | AWS-managed (synths to CFN) | AWS only | Low for developers | Leverages CFN resources |

| Decision Factor | Recommendation | |-----------------|---------------| | Multi-cloud required | Terraform or Pulumi | | AWS-only shop | CloudFormation or CDK | | Team knows TypeScript | Pulumi or CDK | | Need open-source license | OpenTofu | | Existing Terraform codebase | Stay Terraform or migrate to OpenTofu | | Complex logic and loops | Pulumi (general-purpose language) |

State Management Patterns

State is the source of truth for what IaC has provisioned. Mismanaging state causes orphaned resources, duplicate deployments, and data loss.

+------------------+       +------------------+       +------------------+
|  Developer CLI   | ----> |  Remote Backend  | <---- |   CI/CD Pipeline  |
+------------------+       +------------------+       +------------------+
                           |  - S3 + DynamoDB |
                           |  - GCS + Lock    |
                           |  - Terraform Cloud|
                           +------------------+

| Pattern | When to Use | Implementation | |---------|------------|----------------| | Single state file | Small projects, <20 resources | One backend config | | State per environment | Separate dev/staging/prod | Workspace or directory per env | | State per component | Large infra, team boundaries | Separate root modules with data sources | | Hierarchical state | Complex multi-team orgs | Layers: network -> compute -> app |

Terraform Remote State Configuration

# backend.tf -- Remote state with locking
terraform {
  backend "s3" {
    bucket         = "myorg-terraform-state"
    key            = "prod/network/terraform.tfstate"
    region         = "us-east-1"
    dynamodb_table = "terraform-locks"
    encrypt        = true
  }
}

# State locking table -- provision FIRST with a bootstrap module
resource "aws_dynamodb_table" "terraform_locks" {
  name         = "terraform-locks"
  billing_mode = "PAY_PER_REQUEST"
  hash_key     = "LockID"

  attribute {
    name = "LockID"
    type = "S"
  }
}

# Cross-stack references via remote state data source
data "terraform_remote_state" "network" {
  backend = "s3"
  config = {
    bucket = "myorg-terraform-state"
    key    = "prod/network/terraform.tfstate"
    region = "us-east-1"
  }
}

resource "aws_instance" "app" {
  subnet_id = data.terraform_remote_state.network.outputs.private_subnet_ids[0]
}

Module Composition and Versioning

Modules are the unit of reuse in Terraform and OpenTofu. Good module design follows the single-responsibility principle.

modules/
  vpc/
    main.tf          # Resources
    variables.tf     # Input variables with validation
    outputs.tf       # Output values for consumers
    versions.tf      # Required providers and versions
environments/
  dev/
    main.tf          # Calls modules with dev parameters
    backend.tf       # Dev state backend
    terraform.tfvars # Dev variable values
  prod/
    main.tf
    backend.tf
    terraform.tfvars

Terraform Module Example

# modules/vpc/variables.tf
variable "name" {
  description = "Name prefix for all VPC resources"
  type        = string
  validation {
    condition     = length(var.name) <= 24
    error_message = "Name must be 24 characters or fewer."
  }
}

variable "cidr_block" {
  description = "CIDR block for the VPC"
  type        = string
  default     = "10.0.0.0/16"
  validation {
    condition     = can(cidrhost(var.cidr_block, 0))
    error_message = "Must be a valid CIDR block."
  }
}

variable "availability_zones" {
  type = list(string)
}

variable "tags" {
  type    = map(string)
  default = {}
}

# modules/vpc/main.tf
resource "aws_vpc" "this" {
  cidr_block           = var.cidr_block
  enable_dns_hostnames = true
  enable_dns_support   = true
  tags = merge(var.tags, { Name = "${var.name}-vpc" })
}

resource "aws_subnet" "public" {
  count             = length(var.availability_zones)
  vpc_id            = aws_vpc.this.id
  cidr_block        = cidrsubnet(var.cidr_block, 8, count.index)
  availability_zone = var.availability_zones[count.index]
  tags = merge(var.tags, {
    Name = "${var.name}-public-${var.availability_zones[count.index]}"
    Tier = "public"
  })
}

resource "aws_subnet" "private" {
  count             = length(var.availability_zones)
  vpc_id            = aws_vpc.this.id
  cidr_block        = cidrsubnet(var.cidr_block, 8, count.index + length(var.availability_zones))
  availability_zone = var.availability_zones[count.index]
  tags = merge(var.tags, {
    Name = "${var.name}-private-${var.availability_zones[count.index]}"
    Tier = "private"
  })
}

# modules/vpc/outputs.tf
output "vpc_id" {
  value = aws_vpc.this.id
}
output "public_subnet_ids" {
  value = aws_subnet.public[*].id
}
output "private_subnet_ids" {
  value = aws_subnet.private[*].id
}

# environments/prod/main.tf -- Consuming the module
module "vpc" {
  source  = "git::https://github.com/myorg/terraform-modules.git//vpc?ref=v2.1.0"

  name               = "prod"
  cidr_block         = "10.0.0.0/16"
  availability_zones = ["us-east-1a", "us-east-1b", "us-east-1c"]
  tags = { Environment = "production", Team = "platform" }
}

| Versioning Strategy | Source Format | When to Use | |---------------------|-------------|-------------| | Git tag | git::https://...?ref=v2.1.0 | Internal modules, full control | | Terraform Registry | source = "hashicorp/consul/aws" version = "0.1.0" | Public modules | | Local path | source = "../../modules/vpc" | Monorepo, development | | S3/GCS archive | source = "s3::https://..." | Air-gapped environments |

Pulumi TypeScript Example

Pulumi uses general-purpose languages, giving full IDE support, type checking, and testing capabilities.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const config = new pulumi.Config();
const env = pulumi.getStack();
const vpcCidr = config.get("vpcCidr") || "10.0.0.0/16";

class VpcComponent extends pulumi.ComponentResource {
  public readonly vpcId: pulumi.Output<string>;
  public readonly publicSubnetIds: pulumi.Output<string>[];
  public readonly privateSubnetIds: pulumi.Output<string>[];

  constructor(name: string, args: {
    cidr: string; azCount: number; enableNat: boolean;
  }, opts?: pulumi.ComponentResourceOptions) {
    super("custom:network:Vpc", name, {}, opts);

    const vpc = new aws.ec2.Vpc(`${name}-vpc`, {
      cidrBlock: args.cidr,
      enableDnsHostnames: true,
      enableDnsSupport: true,
      tags: { Name: `${name}-vpc`, Environment: env },
    }, { parent: this });

    this.vpcId = vpc.id;
    this.publicSubnetIds = [];
    this.privateSubnetIds = [];
    const azs = aws.getAvailabilityZones({ state: "available" });

    for (let i = 0; i < args.azCount; i++) {
      const pub = new aws.ec2.Subnet(`${name}-public-${i}`, {
        vpcId: vpc.id,
        cidrBlock: `10.0.${i}.0/24`,
        availabilityZone: azs.then(az => az.names[i]),
        mapPublic
Compartilhar X LinkedIn