Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. IaC в пайплайнах
infrastructure_as_code

IaC в пайплайнах

Автоматизация Terraform, CloudFormation в CI/CD, state management.

IaC в пайплайнах

Infrastructure as Code позволяет управлять инфраструктурой через версионируемый код. Изучите интеграцию Terraform, CloudFormation и Pulumi в CI/CD пайплайны.

#Terraform в CI/CD

#Структура проекта

terraform/
├── main.tf
├── variables.tf
├── outputs.tf
├── versions.tf
├── environments/
│   ├── staging.tfvars
│   └── production.tfvars
└── modules/
    ├── vpc/
    ├── eks/
    └── rds/

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

# versions.tf terraform { required_version = ">= 1.5.0" required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } kubernetes = { source = "hashicorp/kubernetes" version = "~> 2.23" } } backend "s3" { bucket = "my-terraform-state" key = "production/terraform.tfstate" region = "us-east-1" encrypt = true dynamodb_table = "terraform-locks" } } # main.tf provider "aws" { region = var.aws_region } resource "aws_s3_bucket" "app" { bucket = var.bucket_name tags = { Environment = var.environment ManagedBy = "Terraform" } } resource "aws_s3_bucket_versioning" "app" { bucket = aws_s3_bucket.app.id versioning_configuration { status = "Enabled" } } # variables.tf variable "aws_region" { description = "AWS region" type = string default = "us-east-1" } variable "environment" { description = "Environment name" type = string } variable "bucket_name" { description = "S3 bucket name" type = string } # outputs.tf output "bucket_arn" { description = "ARN of the S3 bucket" value = aws_s3_bucket.app.arn } output "bucket_name" { description = "Name of the S3 bucket" value = aws_s3_bucket.app.bucket }

#GitHub Actions для Terraform

name: Terraform CI/CD on: push: branches: [main] pull_request: branches: [main] env: TF_VERSION: "1.6.0" AWS_REGION: "us-east-1" jobs: terraform-plan: runs-on: ubuntu-latest defaults: run: working-directory: ./terraform steps: - uses: actions/checkout@v4 - name: Setup Terraform uses: hashicorp/setup-terraform@v3 with: terraform_version: ${{ env.TF_VERSION }} - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} aws-region: ${{ env.AWS_REGION }} - name: Terraform Init run: terraform init - name: Terraform Format Check run: terraform fmt -check -recursive - name: Terraform Validate run: terraform validate - name: Terraform Plan run: terraform plan -out=tfplan -var-file=environments/${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }}.tfvars - name: Upload Plan uses: actions/upload-artifact@v4 with: name: tfplan path: terraform/tfplan terraform-apply: runs-on: ubuntu-latest needs: terraform-plan if: github.ref == 'refs/heads/main' environment: production defaults: run: working-directory: ./terraform steps: - uses: actions/checkout@v4 - name: Setup Terraform uses: hashicorp/setup-terraform@v3 with: terraform_version: ${{ env.TF_VERSION }} - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} aws-region: ${{ env.AWS_REGION }} - name: Terraform Init run: terraform init - name: Download Plan uses: actions/download-artifact@v4 with: name: tfplan path: terraform/ - name: Terraform Apply run: terraform apply -auto-approve tfplan - name: Terraform Output run: terraform output -json

#Terraform с approval workflow

name: Terraform with Approval on: pull_request: branches: [main] types: [opened, synchronize, labeled] jobs: plan: runs-on: ubuntu-latest if: contains(github.event.pull_request.labels.*.name, 'terraform') outputs: plan_exists: ${{ steps.plan.outputs.plan_exists }} steps: - uses: actions/checkout@v4 - name: Setup Terraform uses: hashicorp/setup-terraform@v3 - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} aws-region: us-east-1 - name: Terraform Init run: terraform init - name: Terraform Plan id: plan run: | terraform plan -out=tfplan -no-color > plan_output.txt echo "plan_exists=true" >> $GITHUB_OUTPUT - name: Comment PR uses: actions/github-script@v7 with: script: | const fs = require('fs'); const plan = fs.readFileSync('plan_output.txt', 'utf8'); github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: `## Terraform Plan\n\n\`\`\`\n${plan}\n\`\`\`` }) apply: runs-on: ubuntu-latest needs: plan if: contains(github.event.pull_request.labels.*.name, 'terraform-apply') environment: production steps: - uses: actions/checkout@v4 - name: Setup Terraform uses: hashicorp/setup-terraform@v3 - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} aws-region: us-east-1 - name: Terraform Init run: terraform init - name: Terraform Apply run: terraform apply -auto-approve - name: Remove apply label uses: actions/github-script@v7 with: script: | github.rest.issues.removeLabel({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, name: 'terraform-apply' })

#CloudFormation в CI/CD

#Шаблон CloudFormation

# cloudformation/template.yaml AWSTemplateFormatVersion: "2010-09-09" Description: Application Infrastructure Parameters: Environment: Type: String Default: staging AllowedValues: - staging - production InstanceType: Type: String Default: t3.micro AllowedValues: - t3.micro - t3.small - t3.medium Resources: VPC: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 EnableDnsSupport: true EnableDnsHostnames: true Tags: - Key: Name Value: !Sub "${AWS::StackName}-vpc" - Key: Environment Value: !Ref Environment PublicSubnet: Type: AWS::EC2::Subnet Properties: VpcId: !Ref VPC CidrBlock: 10.0.1.0/24 MapPublicIpOnLaunch: true AvailabilityZone: !Select [0, !GetAZs ""] Tags: - Key: Name Value: !Sub "${AWS::StackName}-public-subnet" SecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Application security group VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: 443 ToPort: 443 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 EC2Instance: Type: AWS::EC2::Instance Properties: InstanceType: !Ref InstanceType SubnetId: !Ref PublicSubnet SecurityGroupIds: - !Ref SecurityGroup ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", AMI] Tags: - Key: Name Value: !Sub "${AWS::StackName}-instance" - Key: Environment Value: !Ref Environment Mappings: RegionMap: us-east-1: AMI: ami-0c55b159cbfafe1f0 us-west-2: AMI: ami-0c55b159cbfafe1f1 eu-west-1: AMI: ami-0c55b159cbfafe1f2 Outputs: VPCId: Description: VPC ID Value: !Ref VPC Export: Name: !Sub "${AWS::StackName}-VPCId" InstanceId: Description: EC2 Instance ID Value: !Ref EC2Instance Export: Name: !Sub "${AWS::StackName}-InstanceId"

#GitHub Actions для CloudFormation

name: CloudFormation CI/CD on: push: branches: [main] jobs: deploy: runs-on: ubuntu-latest environment: production steps: - uses: actions/checkout@v4 - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} aws-region: us-east-1 - name: Validate Template run: | aws cloudformation validate-template \ --template-body file://cloudformation/template.yaml - name: Deploy Stack run: | aws cloudformation deploy \ --template-file cloudformation/template.yaml \ --stack-name my-app-${{ github.ref == 'refs/heads/main' && 'prod' || 'staging' }} \ --parameter-overrides \ Environment=${{ github.ref == 'refs/heads/main' && 'production' || 'staging' }} \ InstanceType=t3.small \ --capabilities CAPABILITY_NAMED_IAM \ --no-fail-on-empty-changeset \ --tags \ Project=my-app \ DeployedBy=github-actions \ CommitSha=${{ github.sha }} - name: Get Stack Outputs run: | aws cloudformation describe-stacks \ --stack-name my-app-prod \ --query "Stacks[0].Outputs" \ --output table

#Pulumi в CI/CD

#Pulumi проект (TypeScript)

// index.ts import * as pulumi from "@pulumi/pulumi"; import * as aws from "@pulumi/aws"; const config = new pulumi.Config(); const environment = config.get("environment") || "staging"; // S3 Bucket const bucket = new aws.s3.Bucket("app-bucket", { tags: { Environment: environment, ManagedBy: "Pulumi" } }); // Enable versioning const bucketVersioning = new aws.s3.BucketVersioningV2("app-bucket-versioning", { bucket: bucket.id, versioningConfiguration: { status: "Enabled" } }); // CloudFront Distribution const oai = new aws.cloudfront.OriginAccessIdentity("app-oai", { comment: "OAI for app bucket" }); const distribution = new aws.cloudfront.Distribution("app-cdn", { enabled: true, origins: [{ originId: bucket.arn, domainName: bucket.bucketRegionalDomainName, s3OriginConfig: { originAccessIdentity: oai.cloudfrontAccessIdentityPath } }], defaultCacheBehavior: { targetOriginId: bucket.arn, viewerProtocolPolicy: "redirect-to-https", allowedMethods: ["GET", "HEAD", "OPTIONS"], cachedMethods: ["GET", "HEAD"], forwardedValues: { queryString: false, cookies: { forward: "none" } } }, restrictions: { geoRestriction: { restrictionType: "none" } }, viewerCertificate: { cloudfrontDefaultCertificate: true }, tags: { Environment: environment } }); // Outputs export const bucketName = bucket.bucket; export const bucketArn = bucket.arn; export const cdnDomain = distribution.domainName; export const cdnId = distribution.id;

#Pulumi.yaml

name: my-app-infra runtime: nodejs description: Application infrastructure config: my-app-infra:environment: default: staging my-app-infra:region: default: us-east-1

#GitHub Actions для Pulumi

name: Pulumi CI/CD on: push: branches: [main] pull_request: branches: [main] env: PULUMI_ACCESS_TOKEN: ${{ secrets.PULUMI_ACCESS_TOKEN }} AWS_REGION: us-east-1 jobs: pulumi-preview: runs-on: ubuntu-latest if: github.event_name == 'pull_request' steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' - name: Install dependencies run: npm ci - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} aws-region: ${{ env.AWS_REGION }} - name: Pulumi Preview uses: pulumi/actions@v5 with: command: preview stack-name: prod work-dir: ./pulumi comment-on-pr: true pulumi-up: runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' environment: production steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: '20' - name: Install dependencies run: npm ci - name: Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v4 with: role-to-assume: ${{ secrets.AWS_ROLE_ARN }} aws-region: ${{ env.AWS_REGION }} - name: Pulumi Up uses: pulumi/actions@v5 with: command: up stack-name: prod work-dir: ./pulumi - name: Get Stack Outputs uses: pulumi/actions@v5 with: command: stack-output stack-name: prod work-dir: ./pulumi

#State Management

#Terraform State Locking

# backend "s3" с DynamoDB locking terraform { backend "s3" { bucket = "my-terraform-state" key = "production/terraform.tfstate" region = "us-east-1" encrypt = true dynamodb_table = "terraform-locks" } } # DynamoDB таблица для locking resource "aws_dynamodb_table" "terraform_locks" { name = "terraform-locks" billing_mode = "PAY_PER_REQUEST" hash_key = "LockID" attribute { name = "LockID" type = "S" } tags = { Name = "Terraform Lock Table" } }

#Import существующих ресурсов

# Импортировать существующий S3 bucket terraform import aws_s3_bucket.app my-existing-bucket # Импортировать VPC terraform import aws_vpc.main vpc-12345678 # Импортировать с указанием модуля terraform import module.vpc.aws_vpc.main vpc-12345678

#Workspace для окружений

# Terraform workspaces terraform workspace new staging terraform workspace new production # Переключение terraform workspace select staging # Применить с workspace terraform apply -var-file=environments/$(terraform workspace show).tfvars
# GitHub Actions с workspaces jobs: deploy: runs-on: ubuntu-latest steps: - name: Terraform Workspace & Apply run: | terraform workspace select ${{ vars.TF_WORKSPACE }} terraform apply -auto-approve \ -var-file=environments/${{ vars.TF_WORKSPACE }}.tfvars

Далее: Управление секретами