Рубрики
Uncategorized

[Террафор] Статический сайт инфраструктуры на AWS

Развертывание статического веб-сайта является одним из самых простых задач веб-разработчика. Есть несколько золь … Помечено террафом, WebDev, DevOps, AWS.

Развертывание статического веб-сайта является одним из самых простых задач веб-разработчика. Существует ряд решений, позволяющих выполнять процесс развертывания в течение нескольких минут, и несколько кнопок кликов. В каком замечательном мире мы живем! Однако этот подход имеет одно огромное ограничение. Вы на самом деле не владеете базовой инфраструктурой. Я утверждаю, что есть способ, которым вы можете сделать развертывание быстро, и владеют базовой инфраструктурой. Вы можете террафовать это!

Эта статья не является руководством, а артефакт, документировавший свое путешествие на пути для развертывания личного блога и его базовой инфраструктуры. Возможно, вы захотите проверить начало путешествия, где я разделяю мою установку непрерывного развертывания.

TLDR, у меня есть статический сайт Hugo, размещенный в ведре S3. Теперь пришло время сделать его добычу!

Давайте определим окончательные характеристики:

  • Доменное имя (используя AWS Route53)
  • Распределен CDN (с использованием AWS Cloudfront)
  • Поддержка SSL/TLS (используя диспетчер сертификата AWS)

Шаг 1: Получить доменное имя

Этот шаг довольно много руководства. AWS имеет подробную инструкцию на Получение домена Отказ Обратите внимание, что AWS автоматически создает размещенную зону, а имена подача (NS) для вас. Важно, чтобы у вас есть существующая действующая размещенная зона, прежде чем перейти к следующему шагу. Если вам нужна дополнительная информация о том, как создать новую размещенную зону, или настроить запись NS, обратитесь к Эта часть руководства AWS.

Шаг 2: Предоставление ресурсов AWS

Эта статья предполагает, что вы уже знаете какую-то террафом. Если вы не знакомы с этим, у меня есть Вводная статья чтобы заставить вас идти. Для более подробного введения см. В Террафом Учебный центр Отказ

Я буду использовать облако террафора, чтобы хранить свое состояние. Узнайте больше об этой конфигурации на Сайт Terraform Отказ Вы также можете изменить шаблоны для настройки террафора для использования локальной Backend.

Структура папок шаблонов

├── main.tf
├── outputs.tf
├── variables.auto.tfvars
└── variables.tf

main.tf

Это полный шаблон, который я использую для моей настройки сайта. Он не только положения ресурсов AWS (S3, Route53, Cloudfront и etc), но и учетные данные для развертывания CIRCLECI. Если вам не интересно создать конвейеров CI/CD, вы можете исключить пользователя IAM и политику из шаблона.

Помните, что террафом хранит ключи в своем государство как открытый текст. Вы несете ответственность за сохранение своей секретности.

terraform {
  required_version = "~> 0.12.25"

  backend "remote" {
    hostname     = "app.terraform.io"
    organization = "example-organization"

    workspaces {
      name = "example-workspace"
    }
  }
}

provider "aws" {
  version = "~> 2.0"
  region  = var.region
}

data "aws_route53_zone" "static_bucket_zone" {
  name = var.domain_name
}

resource "aws_s3_bucket" "static_bucket" {
  bucket = var.domain_name
  acl    = "public-read"

  force_destroy = true

  website {
    index_document = "index.html"
  }

  policy = <<-EOT
    {
      "Version": "2012-10-17",
      "Statement": [
          {
              "Sid": "PublicReadGetObject",
              "Effect": "Allow",
              "Principal": "*",
              "Action": [
                  "s3:GetObject"
              ],
              "Resource": [
                  "arn:aws:s3:::${var.domain_name}/*"
              ]
          }
      ]
    }
  EOT
}

resource "aws_acm_certificate" "static_bucket_certificate" {
  domain_name       = var.domain_name
  validation_method = "DNS"

  tags = {
    terraform = "true"
  }

  lifecycle {
    create_before_destroy = true
  }
}

resource "aws_route53_record" "static_bucket_record" {
  zone_id = data.aws_route53_zone.static_bucket_zone.zone_id
  name    = var.domain_name
  type    = "A"

  alias {
    name                   = aws_cloudfront_distribution.static_bucket_distribution.domain_name
    zone_id                = aws_cloudfront_distribution.static_bucket_distribution.hosted_zone_id
    evaluate_target_health = false
  }
}

resource "aws_acm_certificate_validation" "static_bucket_certificate" {
  certificate_arn = aws_acm_certificate.static_bucket_certificate.arn
  timeouts {
    create = "20m"
  }
}

resource "aws_cloudfront_distribution" "static_bucket_distribution" {
  origin {
    custom_origin_config {
      http_port              = "80"
      https_port             = "443"
      origin_protocol_policy = "http-only"
      origin_ssl_protocols   = ["TLSv1", "TLSv1.1", "TLSv1.2"]
    }

    domain_name = aws_s3_bucket.static_bucket.website_endpoint
    origin_id   = var.domain_name
  }

  enabled             = true
  default_root_object = "index.html"

  default_cache_behavior {
    viewer_protocol_policy = "redirect-to-https"
    compress               = true
    allowed_methods        = ["GET", "HEAD"]
    cached_methods         = ["GET", "HEAD"]
    target_origin_id       = var.domain_name
    min_ttl                = 0
    default_ttl            = 86400
    max_ttl                = 31536000

    forwarded_values {
      query_string = false
      cookies {
        forward = "none"
      }
    }
  }

  aliases = [var.domain_name]

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  viewer_certificate {
    acm_certificate_arn = aws_acm_certificate_validation.static_bucket_certificate.certificate_arn
    ssl_support_method  = "sni-only"
  }
}

resource "aws_iam_user" "circle_ci_user" {
  name = "circle-ci"
}

resource "aws_iam_access_key" "circle_ci_access_key" {
  user = aws_iam_user.circle_ci_user.name
}

resource "aws_iam_user_policy" "circle_ci_policy" {
  name = "circle-ci-policy"
  user = aws_iam_user.circle_ci_user.name

  policy = <<-EOT
    {
      "Version": "2012-10-17",
      "Statement": [
          {
              "Effect": "Allow",
              "Action": "s3:*",
              "Resource": [
                  "arn:aws:s3:::${var.domain_name}",
                  "arn:aws:s3:::${var.domain_name}/*"
              ]
          }
      ]
    }
  EOT
}

variables.tf

variable "domain_name" {
  type        = string
  description = "Website root domain name"
}

variable "region" {
  type        = string
  description = "AWS region to create resources"
}

outputs.tf

Опять же, если вы не используете CI/CD, эта часть может быть безопасной игнорирующей.

output "circle_ci_access_key" {
  value = aws_iam_access_key.circle_ci_access_key.id
}

output "circle_ci_access_key_secret" {
  value = aws_iam_access_key.circle_ci_access_key.secret
}

variables.auto.tf

Обратите внимание, что добавление автоматического суффикса к определению переменных террафора сделает файл нагрузки автоматически.

domain_name  = "example.com"
region       = "us-east-1"

Шаг 3: Наслаждайтесь результатом

После того, как обеспечение успешно завершено, он может по-прежнему занять несколько минут для Cloudfront, а конфигурации Route53 для полной синхронизации. Если вы использовали услуги AWS CDN с вашим доменом доменного имени, это хорошая идея Недействительный кэш Отказ

Вы можете найти свой последний результат на artem.lol Отказ Если у вас есть какие-либо вопросы или столкнуться с проблемами, пытающимися предоставление инфраструктуры, используя мой шаблон, пожалуйста, дайте мне знать в комментариях!

Оригинал: «https://dev.to/aakatev/static-website-infrastructure-with-terraform-jgi»