rubric/modules/devopsmodules/devops_terraform.go

291 lines
8.6 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package devopsmodules
import (
"rubric/utils"
)
var TerraformModule = Module{
Key: "terraform",
Aliases: []string{"tf", "iac", "infra"},
Title: "Terraform — инфраструктура как код",
Description: "HCL, провайдеры, ресурсы, state, модули, workspace",
Run: showTerraform,
}
func showTerraform() {
utils.Header("DevOps — Terraform")
utils.Section("Основы и установка")
utils.Code(`Terraform — декларативный IaC инструмент от HashiCorp.
Описываешь желаемое состояние → Terraform приводит инфраструктуру к нему.
# Установка:
# https://developer.hashicorp.com/terraform/install
# Linux (apt):
wget -O - https://apt.releases.hashicorp.com/gpg | sudo gpg --dearmor \
-o /usr/share/keyrings/hashicorp-archive-keyring.gpg
echo "deb [signed-by=...] https://apt.releases.hashicorp.com $(lsb_release -cs) main" \
| sudo tee /etc/apt/sources.list.d/hashicorp.list
sudo apt update && sudo apt install terraform
terraform version
terraform -install-autocomplete`)
utils.Section("Жизненный цикл")
utils.Code(`terraform init # скачать провайдеры, инициализировать backend
terraform validate # проверить синтаксис
terraform fmt # форматировать код
terraform plan # показать что изменится
terraform apply # применить изменения
terraform destroy # удалить всю инфраструктуру
terraform plan -out=plan.tfplan # сохранить план
terraform apply plan.tfplan # применить сохранённый план
terraform apply -auto-approve # без подтверждения (CI/CD)
terraform apply -target=aws_instance.web # только конкретный ресурс
terraform plan -var="region=eu-west-1"
terraform plan -var-file="prod.tfvars"`)
utils.Section("Синтаксис HCL")
utils.Code(`# main.tf — основная конфигурация:
terraform {
required_version = ">= 1.7"
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
backend "s3" {
bucket = "my-tf-state"
key = "prod/terraform.tfstate"
region = "eu-west-1"
encrypt = true
}
}
provider "aws" {
region = var.aws_region
profile = "myprofile"
}`)
utils.Code(`# variables.tf — входные переменные:
variable "aws_region" {
description = "AWS регион"
type = string
default = "eu-west-1"
}
variable "instance_count" {
type = number
default = 2
}
variable "allowed_cidrs" {
type = list(string)
default = ["10.0.0.0/8"]
}
variable "tags" {
type = map(string)
default = {
Environment = "production"
Team = "backend"
}
}
variable "db_password" {
type = string
sensitive = true # не показывать в логах
}`)
utils.Code(`# outputs.tf — выходные значения:
output "web_ip" {
value = aws_instance.web.public_ip
description = "Публичный IP веб-сервера"
}
output "db_endpoint" {
value = aws_db_instance.main.endpoint
sensitive = true
}`)
utils.Code(`# Использование переменных:
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
count = var.instance_count
tags = merge(var.tags, {
Name = "web-${count.index + 1}"
})
}
# locals — локальные вычисляемые значения:
locals {
name_prefix = "${var.project}-${var.environment}"
common_tags = {
Project = var.project
Environment = var.environment
ManagedBy = "terraform"
}
}`)
utils.Section("Основные ресурсы (AWS)")
utils.Code(`# Data sources — чтение существующих ресурсов:
data "aws_ami" "ubuntu" {
most_recent = true
owners = ["099720109477"] # Canonical
filter {
name = "name"
values = ["ubuntu/images/hvm-ssd/ubuntu-*-22.04-amd64-server-*"]
}
}
data "aws_vpc" "default" {
default = true
}
# EC2:
resource "aws_instance" "web" {
ami = data.aws_ami.ubuntu.id
instance_type = "t3.micro"
subnet_id = aws_subnet.public.id
vpc_security_group_ids = [aws_security_group.web.id]
key_name = "mykey"
user_data = file("scripts/init.sh")
root_block_device {
volume_size = 20
encrypted = true
}
lifecycle {
create_before_destroy = true
ignore_changes = [ami]
}
tags = local.common_tags
}
# Security Group:
resource "aws_security_group" "web" {
name = "${local.name_prefix}-web-sg"
vpc_id = aws_vpc.main.id
ingress {
from_port = 80
to_port = 80
protocol = "tcp"
cidr_blocks = ["0.0.0.0/0"]
}
egress {
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
# S3 Bucket:
resource "aws_s3_bucket" "assets" {
bucket = "${local.name_prefix}-assets"
}
resource "aws_s3_bucket_versioning" "assets" {
bucket = aws_s3_bucket.assets.id
versioning_configuration {
status = "Enabled"
}
}`)
utils.Section("Модули (Modules)")
utils.Code(`# Модуль — переиспользуемая конфигурация
# modules/ec2/main.tf, variables.tf, outputs.tf
# Использование модуля:
module "web_servers" {
source = "./modules/ec2"
# или из реестра:
# source = "terraform-aws-modules/ec2-instance/aws"
# version = "~> 5.0"
instance_count = 3
instance_type = "t3.small"
vpc_id = aws_vpc.main.id
subnet_ids = aws_subnet.public[*].id
tags = local.common_tags
}
output "web_ips" {
value = module.web_servers.public_ips
}
# Популярные модули из реестра registry.terraform.io:
# terraform-aws-modules/vpc/aws
# terraform-aws-modules/eks/aws
# terraform-aws-modules/rds/aws`)
utils.Section("State и Backend")
utils.Code(`# State — файл состояния (terraform.tfstate)
# Хранит текущее состояние инфраструктуры.
# НЕ коммити в Git! Содержит секреты.
# Remote backend — общий state для команды:
# S3 + DynamoDB (для lock):
backend "s3" {
bucket = "my-tf-state"
key = "prod/terraform.tfstate"
region = "eu-west-1"
encrypt = true
dynamodb_table = "tf-state-lock" # блокировка
}
# Команды state:
terraform state list # список ресурсов в state
terraform state show aws_instance.web # детали ресурса
terraform state mv aws_instance.old aws_instance.new # переименовать
terraform state rm aws_instance.web # убрать из state (не удалять)
terraform import aws_instance.web i-1234567890 # импортировать существующий
# Workspace — несколько окружений в одном конфиге:
terraform workspace list
terraform workspace new staging
terraform workspace select production
# В коде: terraform.workspace → "staging" / "production"`)
utils.Section("Лучшие практики")
utils.Code(`Структура проекта:
infra/
├── modules/ # переиспользуемые модули
│ ├── vpc/
│ ├── eks/
│ └── rds/
├── environments/
│ ├── staging/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── staging.tfvars
│ └── production/
│ ├── main.tf
│ └── production.tfvars
└── .terraform.lock.hcl # версии провайдеров (коммитить!)
Правила:
- Всегда планируй перед apply: terraform plan
- Remote state с блокировкой для командной работы
- Раздели state по окружениям и компонентам
- Используй .terraform.lock.hcl в git
- sensitive = true для секретных переменных
- Используй terragrunt для DRY-конфигураций
Инструменты:
tflint — линтинг Terraform
tfsec — статический анализ безопасности
checkov — security и compliance checks
terragrunt — обёртка для DRY-конфигурации
atlantis — автоматизация PR для Terraform`)
utils.Footer()
}