使用CircleCI和Terraform部署静态网页

首先

这是使用CircleCI和Terraform部署React等静态网站的示例过程。

使用Terraform构建S3和CloudFront,然后使用CircleCI将构建的静态文件上传到S3。

在这里,我们不会创建从独立域名到CloudFront的别名记录。我们的目标是在创建了CloudFront分发之后,默认情况下会创建一个 *.cloudfront.net 域,以便可以访问静态网站。

土地整治

AWS的配置

在中国本地化,只需要一个选项:
指定区域、固定AWS提供商版本,指定使用的凭证(~/.aws/credentials)。

provider "aws" {
  region  = "ap-northeast-1"
  profile = "private"
  version = "2.40.0"
}

土壤配置

为了利用特定版本的固定。

terraform {
  required_version = "0.12.6"
}

S3的配置

创建一个桶。

resource "aws_s3_bucket" "connpass-map-front" {
  bucket = "connpass-map-front"
  acl    = "private"
  region = "ap-northeast-1"
}

云前端和身份访问管理(IAM)的配置

一旦上传所有的tf文件。

resource "aws_cloudfront_origin_access_identity" "origin_access_identity" {
  comment = "origin access identity for s3"
}

resource "aws_cloudfront_distribution" "s3_distribution" {
  origin {
    domain_name = "${aws_s3_bucket.connpass-map-front.bucket_regional_domain_name}"
    origin_id   = "${aws_s3_bucket.connpass-map-front.id}"

    s3_origin_config {
      origin_access_identity = "${aws_cloudfront_origin_access_identity.origin_access_identity.cloudfront_access_identity_path}"
    }
  }

  enabled             = true
  is_ipv6_enabled     = false
  comment             = "connpass-map-front"
  default_root_object = "index.html"

  default_cache_behavior {
    allowed_methods  = ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
    cached_methods   = ["GET", "HEAD"]
    target_origin_id = "${aws_s3_bucket.connpass-map-front.id}"

    forwarded_values {
      query_string = false

      cookies {
        forward = "none"
      }
    }

    viewer_protocol_policy = "allow-all"
    min_ttl                = 0
    default_ttl            = 3600
    max_ttl                = 86400
  }

  restrictions {
    geo_restriction {
      restriction_type = "none"
    }
  }

  viewer_certificate {
    cloudfront_default_certificate = true
  }
}

data "aws_iam_policy_document" "cf_to_s3_policy" {
  statement {
    actions = ["s3:GetObject"]

    resources = [
      "${aws_s3_bucket.connpass-map-front.arn}",
      "${aws_s3_bucket.connpass-map-front.arn}/*",
    ]

    principals {
      type        = "AWS"
      identifiers = ["${aws_cloudfront_origin_access_identity.origin_access_identity.iam_arn}"]
    }
  }
}

resource "aws_s3_bucket_policy" "cf-to-s3" {
  bucket = "${aws_s3_bucket.connpass-map-front.id}"
  policy = "${data.aws_iam_policy_document.cf_to_s3_policy.json}"
}

设置Origin Access Identity

为了只允许从CloudFront访问S3,我们进行了Origin Access Identity的配置。

首先,创建一个名为origin_access_identity的资源。

resource "aws_cloudfront_origin_access_identity" "origin_access_identity" {

创建与该资源关联的策略。

data "aws_iam_policy_document" "cf_to_s3_policy" {

将创建的策略与创建策略的 S3 存储桶关联起来。这样就可以通过 CloudFront 来访问 S3,并且只能通过 CloudFront 访问。

resource "aws_s3_bucket_policy" "cf-to-s3" {

创建CloudFront分发

resource "aws_cloudfront_distribution" "s3_distribution" {

在distribution的资源中,值得特别提到的是指定s3存储桶的位置(如origin),应该将创建的存储桶进行指定。

  origin {
    domain_name = "${aws_s3_bucket.connpass-map-front.bucket_regional_domain_name}"
    origin_id   = "${aws_s3_bucket.connpass-map-front.id}"

假设构建的文件组中含有 index.html,将 default_root_object 设置为 index.html。

  default_root_object = "index.html"

由于不使用自定义域名,将保持默认的viewer_certificate设置。

  viewer_certificate {
    cloudfront_default_certificate = true
  }

只需运行 terraform apply,便会创建 s3 和 cloudfront。

对tfstate文件进行管理

执行terraform apply会在本地创建tfstate文件,但是通常最佳实践是将tfstate文件存储在s3或terraform cloud中进行管理(如果是团队开发的话)。

我們將嘗試使用Terraform Cloud進行tfstate的管理。
操作流程如下:

1) [浏览器] 在 Terraform Cloud 上创建账号。
2) [浏览器] 创建一个组织。
3) [浏览器] 创建用于访问 Terraform Cloud 的令牌。
4) [本地] 将创建的令牌写入 $HOME/.terraformrc 文件中。
5) [本地] 配置以将 tfstate 存储到 Terraform Cloud。
6) [浏览器] 在工作区设置中将 AWS 操作更改为从本地进行。
7) [本地] 运行 terraform init 命令。

1. 一到三
2. 第一到第三
3. 1至3

以下的文章中包含了1到3的详细流程,并附有图片,请点击以下链接查看:
https://dev.classmethod.jp/cloud/aws/manage-tfstate-terraform-cloud/

将在3中创建的令牌写入$HOME/terraformrc文件。

credentials "app.terraform.io" {
  token = "作成したトークンをここに"
}

5) 将 [本地] tfstate 设置为保存在 Terraform Cloud 中。

在 terraform.tf 文件中添加配置。

terraform {
  required_version = "0.12.6"

  backend "remote" {
    organization = "connpass-map-front"

    workspaces {
      name = "connpass-map-front-workspace"
    }
  }
}

6) 在[浏览器]的工作空间设置中,将AWS的操作更改为从本地执行。

如果在本地运行terraform,aws的凭证将通过查找本地的 ~/.aws/credentials 文件来获取。如果使用terraform cloud,可以在工作区设置中选择是从terraform cloud还是从本地执行aws操作。

スクリーンショット 2019-12-01 13.14.48.png

当此处设置为远程(默认值)时,执行 terraform apply 或 terraform plan 时将不再查看本地的 ~/.aws/credentials 文件,从而导致以下错误。

Error: No valid credential sources found for AWS Provider.
        Please see https://terraform.io/docs/providers/aws/index.html for more information on
        providing credentials for the AWS Provider

如果将其设置为本地(Local),则可以从本地执行AWS操作,并且仅由terraform cloud负责管理tfstate,因此不会再出现上述错误。

7) 【本地】运行 terraform init。

如果可以访问Terraform Cloud,那么”init”命令将成功执行。现在,如果运行”terraform apply”,tfstate文件将会上传到Terraform Cloud中。

$ terraform init

Initializing the backend...

Successfully configured the backend "remote"! Terraform will automatically
use this backend unless the backend configuration changes.

Initializing provider plugins...
- Checking for available provider plugins...
- Downloading plugin for provider "aws" (hashicorp/aws) 2.40.0...

Terraform has been successfully initialized!

You may now begin working with Terraform. Try running "terraform plan" to see
any changes that are required for your infrastructure. All Terraform commands
should now work.

If you ever set or change modules or backend configuration for Terraform,
rerun this command to reinitialize your working directory. If you forget, other
commands will detect it and remind you to do so if necessary.

现在环境已经准备好了,但关键的S3存储桶里还没有内容,所以我们需要在CircleCI中配置一个流程,将打包的静态文件上传到S3。

圆圈持续集成

假设已经使用 npm run build 命令构建了文件,并将其放置在 /build 文件夹中。

version: 2.1
orbs:
  aws-s3: circleci/aws-s3@1.0.11
executors:
  default:
    docker:
      - image: circleci/node:12
    working_directory: ~/repo
commands:
  npm_install:
    steps:
      - restore_cache:
          keys:
            - v2-dependencies-{{ checksum "package.json" }}
            - v2-dependencies-
      - run: npm install
      - save_cache:
          paths:
            - node_modules
          key: v2-dependencies-{{ checksum "package.json" }}
jobs:
  build:
    executor: default
    steps:
      - checkout
      - npm_install
      - run: npm run build
      - persist_to_workspace:
          root: .
          paths:
            - "*"
            - ".*"
  deploy:
    executor: default
    steps:
      - attach_workspace:
          at: ~/repo
      - aws-s3/sync:
          from: build
          to: s3://connpass-map-front
          overwrite: true
workflows:
  version: 2
  build-deploy:
    jobs:
      - build
      - deploy:
          requires:
            - build
          filters:
            branches:
              only:
                - /feature.*/
                - master

由于使用了aws-s3的orbs,因此可以将build文件夹中的文件与connpass-map-front的存储桶进行同步。

      - aws-s3/sync:
          from: build
          to: s3://connpass-map-front
          overwrite: true

另外,为了使用此s3的orbs,您需要事先在circleci的环境变量中设置AWS_ACCESS_KEY_ID、AWS_SECRET_ACCESS_KEY、AWS_REGION。

每次将分支合并到主分支时,最新的捆绑文件将通过此CircleCI配置上传到S3。

在上传完成之后,您可以访问所创建的CloudFront分发的域名(*.cloudfront.net),来查看已上传的静态网站。

请你提供以下内容的中文本地语言释义,只需要一个选项:

参考:

1. https://qiita.com/natsumisawa/items/404217208ab1c96d8719
– 这个网址是关于如何使用Terraform管理AWS资源状态的文章。

2. https://dev.classmethod.jp/cloud/aws/manage-tfstate-terraform-cloud/
– 这个网址是关于使用Terraform Cloud管理AWS资源状态的文章。

广告
将在 10 秒后关闭
bannerAds