Урок 22-27: Модули, State и Multi-Cloud

Pavel 08.12.2025 18:58 5 просмотров

Часть 1: Создание Модулей

Структура модуля

terraform-modules/
├── vpc/
   ├── main.tf
   ├── variables.tf
   ├── outputs.tf
   └── README.md
├── security_group/
   ├── main.tf
   ├── variables.tf
   └── outputs.tf
├── compute/
   ├── main.tf
   ├── variables.tf
   └── outputs.tf
└── modules-usage/
    ├── main.tf
    ├── variables.tf
    └── terraform.tfvars

Модуль VPC

Файл: modules/vpc/variables.tf

variable "vpc_name" {
  type        = string
  description = "Name of VPC"
}

variable "cidr_block" {
  type        = string
  default     = "10.0.0.0/16"
  description = "CIDR block for VPC"
}

variable "enable_dns" {
  type        = bool
  default     = true
  description = "Enable DNS support"
}

variable "tags" {
  type        = map(string)
  default     = {}
  description = "Tags for resources"
}

Файл: modules/vpc/main.tf

resource "aws_vpc" "main" {
  cidr_block           = var.cidr_block
  enable_dns_hostnames = var.enable_dns
  enable_dns_support   = var.enable_dns

  tags = merge(var.tags, {
    Name = var.vpc_name
  })
}

resource "aws_internet_gateway" "main" {
  vpc_id = aws_vpc.main.id

  tags = merge(var.tags, {
    Name = "${var.vpc_name}-igw"
  })
}

resource "aws_subnet" "public" {
  vpc_id            = aws_vpc.main.id
  cidr_block        = "10.0.1.0/24"
  availability_zone = "us-west-2a"

  tags = merge(var.tags, {
    Name = "${var.vpc_name}-public-subnet"
  })
}

resource "aws_route_table" "public" {
  vpc_id = aws_vpc.main.id

  route {
    cidr_block      = "0.0.0.0/0"
    gateway_id      = aws_internet_gateway.main.id
  }

  tags = merge(var.tags, {
    Name = "${var.vpc_name}-public-rt"
  })
}

resource "aws_route_table_association" "public" {
  subnet_id      = aws_subnet.public.id
  route_table_id = aws_route_table.public.id
}

Файл: modules/vpc/outputs.tf

output "vpc_id" {
  value = aws_vpc.main.id
}

output "subnet_id" {
  value = aws_subnet.public.id
}

output "igw_id" {
  value = aws_internet_gateway.main.id
}

Использование модуля

Файл: main.tf

module "vpc" {
  source = "./modules/vpc"

  vpc_name = "production-vpc"
  cidr_block = "10.0.0.0/16"
  enable_dns = true

  tags = {
    Environment = "production"
    Project     = "MyApp"
  }
}

module "vpc_staging" {
  source = "./modules/vpc"

  vpc_name = "staging-vpc"
  cidr_block = "10.1.0.0/16"
  enable_dns = true

  tags = {
    Environment = "staging"
    Project     = "MyApp"
  }
}

Доступ к выходам модуля

resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"
  subnet_id     = module.vpc.subnet_id

  tags = {
    Name = "web-server"
  }
}

output "prod_vpc_id" {
  value = module.vpc.vpc_id
}

output "staging_vpc_id" {
  value = module.vpc_staging.vpc_id
}

Часть 2: Remote State

Хранение State в S3

Файл: terraform.tf

terraform {
  backend "s3" {
    bucket         = "my-terraform-state"
    key            = "prod/terraform.tfstate"
    region         = "us-west-2"
    encrypt        = true
    dynamodb_table = "terraform-locks"
  }
}

Создание S3 бакета для State

# backend.tf (используется только один раз локально)

resource "aws_s3_bucket" "terraform_state" {
  bucket = "my-terraform-state-${data.aws_caller_identity.current.account_id}"

  lifecycle {
    prevent_destroy = true
  }
}

resource "aws_s3_bucket_versioning" "terraform_state" {
  bucket = aws_s3_bucket.terraform_state.id

  versioning_configuration {
    status = "Enabled"
  }
}

resource "aws_s3_bucket_server_side_encryption_configuration" "terraform_state" {
  bucket = aws_s3_bucket.terraform_state.id

  rule {
    apply_server_side_encryption_by_default {
      sse_algorithm = "AES256"
    }
  }
}

resource "aws_dynamodb_table" "terraform_locks" {
  name           = "terraform-locks"
  billing_mode   = "PAY_PER_REQUEST"
  hash_key       = "LockID"

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

  lifecycle {
    prevent_destroy = true
  }
}

data "aws_caller_identity" "current" {}

Миграция State

# Инициализировать локально
terraform init

# Мигрировать в S3
terraform init -migrate-state

# Просмотр состояния
terraform state list
terraform state show

# Вытянуть state локально для backup
terraform state pull > terraform.tfstate.backup

Часть 3: Workspaces

Использование Workspaces

# Создать workspace
terraform workspace new dev
terraform workspace new staging
terraform workspace new prod

# Список workspaces
terraform workspace list

# Переключиться на workspace
terraform workspace select prod

# Текущий workspace
terraform workspace show

# Удалить workspace
terraform workspace delete dev

Использование в коде

locals {
  workspace = terraform.workspace

  environment_config = {
    dev = {
      instance_type = "t2.micro"
      instance_count = 1
    }
    staging = {
      instance_type = "t2.small"
      instance_count = 2
    }
    prod = {
      instance_type = "t2.large"
      instance_count = 3
    }
  }

  config = local.environment_config[local.workspace]
}

resource "aws_instance" "web" {
  count         = local.config.instance_count
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = local.config.instance_type

  tags = {
    Name        = "${local.workspace}-web-${count.index + 1}"
    Environment = local.workspace
  }
}

State файлы для Workspaces

.terraform/
├── terraform.tfstate              # default workspace
└── terraform.tfstate.d/
    ├── dev
       └── terraform.tfstate
    ├── staging
       └── terraform.tfstate
    └── prod
        └── terraform.tfstate

Часть 4: Multi-Region

Создание ресурсов в нескольких регионах

provider "aws" {
  alias  = "us-west-2"
  region = "us-west-2"
}

provider "aws" {
  alias  = "eu-west-1"
  region = "eu-west-1"
}

resource "aws_instance" "us_web" {
  provider      = aws.us-west-2
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"

  tags = {
    Name   = "us-web"
    Region = "us-west-2"
  }
}

resource "aws_instance" "eu_web" {
  provider      = aws.eu-west-1
  ami           = "ami-0d71ea30463e0ff89"  # Different AMI ID in EU
  instance_type = "t2.micro"

  tags = {
    Name   = "eu-web"
    Region = "eu-west-1"
  }
}

output "us_instance_ip" {
  value = aws_instance.us_web.public_ip
}

output "eu_instance_ip" {
  value = aws_instance.eu_web.public_ip
}

Multi-Region с модулями

module "vpc_us" {
  source = "./modules/vpc"

  providers = {
    aws = aws.us-west-2
  }

  vpc_name = "us-vpc"
  cidr_block = "10.0.0.0/16"
}

module "vpc_eu" {
  source = "./modules/vpc"

  providers = {
    aws = aws.eu-west-1
  }

  vpc_name = "eu-vpc"
  cidr_block = "10.1.0.0/16"
}

Часть 5: Multi-Account

Работа с несколькими AWS аккаунтами

provider "aws" {
  alias             = "dev"
  region            = "us-west-2"
  assume_role_arn   = "arn:aws:iam::ACCOUNT_ID_DEV:role/TerraformRole"
  assume_role_session_name = "terraform-dev"
}

provider "aws" {
  alias             = "prod"
  region            = "us-west-2"
  assume_role_arn   = "arn:aws:iam::ACCOUNT_ID_PROD:role/TerraformRole"
  assume_role_session_name = "terraform-prod"
}

resource "aws_instance" "dev" {
  provider      = aws.dev
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.micro"

  tags = {
    Name    = "dev-web"
    Account = "dev"
  }
}

resource "aws_instance" "prod" {
  provider      = aws.prod
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t2.large"

  tags = {
    Name    = "prod-web"
    Account = "prod"
  }
}

Часть 6: Google Cloud Platform (GCP)

Базовая конфигурация GCP

terraform {
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

provider "google" {
  project = var.gcp_project
  region  = var.gcp_region
}

variable "gcp_project" {
  type = string
}

variable "gcp_region" {
  type    = string
  default = "us-central1"
}

Создание VM в GCP

resource "google_compute_instance" "web" {
  name         = "web-server"
  machine_type = "e2-micro"
  zone         = "us-central1-a"

  boot_disk {
    initialize_params {
      image = "debian-cloud/debian-11"
    }
  }

  network_interface {
    network = "default"
    access_config {
      // Автоматический external IP
    }
  }

  tags = ["web-server"]
}

Создание Storage Bucket в GCP

resource "google_storage_bucket" "app_data" {
  name          = "${var.gcp_project}-app-data"
  location      = "US"
  force_destroy = false

  versioning {
    enabled = true
  }

  encryption {
    default_kms_key_name = google_kms_crypto_key.storage.id
  }

  lifecycle_rule {
    condition {
      age = 30
    }
    action {
      type          = "Delete"
    }
  }
}

Полный пример: Production Environment

# terraform.tf
terraform {
  required_version = ">= 1.0"

  backend "s3" {
    bucket         = "company-terraform-state"
    key            = "prod/terraform.tfstate"
    region         = "us-west-2"
    encrypt        = true
    dynamodb_table = "terraform-locks"
  }
}

# main.tf
module "vpc_prod" {
  source = "./modules/vpc"

  vpc_name = "prod-vpc"
  cidr_block = "10.0.0.0/16"

  tags = {
    Environment = "prod"
  }
}

module "compute_prod" {
  source = "./modules/compute"

  subnet_id = module.vpc_prod.subnet_id
  environment = "prod"
  instance_count = 3

  tags = {
    Environment = "prod"
  }
}

# outputs.tf
output "vpc_id" {
  value = module.vpc_prod.vpc_id
}

output "instance_ips" {
  value = module.compute_prod.instance_ips
}

Комментарии (0)

Для добавления комментария необходимо войти в аккаунт

Войти / Зарегистрироваться