1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

RailsとNuxt3でtodoリストを作ろう[REST-API/Terraform/Fargate]〜その6、Blue/Greenデプロイ前編

Last updated at Posted at 2023-06-05

はじめに

RailsとNuxt3でtodoリストの作り方を
初めから丁寧に説明したいと思います。

使用pcはmacを想定しています。

完成した構成図は以下の通りです。

aws_structure.png

また、githubレポジトリはこちらです。

各シリーズは以下の通りです。

RailsとNuxt3でtodoリストを作ろう[REST-API/Terraform/Fargate]〜その1、Rails基本設定編
RailsとNuxt3でtodoリストを作ろう[REST-API/Terraform/Fargate]〜その2、Rails API編
RailsとNuxt3でtodoリストを作ろう[REST-API/Terraform/Fargate]〜その3、Nuxt.js編
RailsとNuxt3でtodoリストを作ろう[REST-API/Terraform/Fargate]〜その4、TerraformECS前編
RailsとNuxt3でtodoリストを作ろう[REST-API/Terraform/Fargate]〜その5、TerraformECS後編
RailsとNuxt3でtodoリストを作ろう[REST-API/Terraform/Fargate]〜その6、Blue/Greenデプロイ前編
RailsとNuxt3でtodoリストを作ろう[REST-API/Terraform/Fargate]〜その7、Blue/Greenデプロイ後編

codepipline

一つのコンテナでBlue/Greenデプロイを行なっているバージョンです。
参考にしていただければ、幸いです。

main.tf

main.tfに以下を追加します。

ECSのサービスの立ち上げを待つ為、以下コメントアウトしたままapplyをして、
成功後、コメントアウトを解除し再度applyする。

terraform/main.tf

module "codepipeline" {
  source             = "./modules/codepipeline"
  app_name           = var.app_name
  web_app_name       = var.web_app_name
  api_app_name       = var.api_app_name
  api_blue_arn       = module.elb.api_blue_arn
  web_blue_arn       = module.elb.web_blue_arn
  api_green_arn      = module.elb.api_green_arn
  web_green_arn      = module.elb.web_green_arn
  http_arn           = module.elb.http_arn
  api_blue_name      = module.elb.api_blue_name
  web_blue_name      = module.elb.web_blue_name
  api_green_name     = module.elb.api_green_name
  web_green_name     = module.elb.web_green_name
  cluster-name       = module.ecs.cluster-name
  api-service-name   = module.ecs.api-service-name
  web-service-name   = module.ecs.web-service-name
  api-definition-arn = module.ecs.api-definition-arn
  web-definition-arn = module.ecs.web-definition-arn
}

cloudwatch

githubからcodecommitにミラーリングした後、codepiplineが発火するようにcloudwatchで監視しています。

terraform/modules/codepipeline/aws_cloudwatch_event_rule.tf
resource "aws_cloudwatch_event_rule" "image_push" {
  name     = "codecommit_push"
  role_arn = aws_iam_role.cwe_role.arn

  event_pattern = jsonencode({
    source      = ["aws.codecommit"]
    detail-type = ["CodeCommit Repository State Change"]
    resources   = ["${aws_codecommit_repository.codecommit_repository.arn}"]

    detail = {
      event         = ["referenceCreated", "referenceUpdated"]
      referenceType = ["branch"]
      referenceName = ["main"]
    }
  })
}
terraform/modules/codepipeline/aws_cloudwatch_event_target.tf
resource "aws_cloudwatch_event_target" "codepipeline" {
  rule      = aws_cloudwatch_event_rule.image_push.name
  target_id = "${var.app_name}-Image-Push-Codepipeline"
  arn       = aws_codepipeline.codepipeline.arn
  role_arn  = aws_iam_role.cwe_role.arn
}

s3

codepiplineのリソースは一旦s3に保存、経由し次のアクションを実行します。

CodeSourceからSourceArtiディレクトリーに
CodeBuildからBuildArtifディレクトリーに保存されます。

terraform/modules/codepipeline/aws_s3_bucket.tf
resource "aws_s3_bucket" "codepipeline_bucket" {
  bucket        = "codepipeline-bucket-${random_string.s3_unique_key.result}"
  force_destroy = true
}

resource "random_string" "s3_unique_key" {
  length  = 6
  upper   = false
  lower   = true
  numeric = true
  special = false
}

iam

codepipline、ccodecommit、codebuildに許可を与えます。

terraform/modules/codepipeline/aws_iam_role.tf
resource "aws_iam_role" "codepipeline_role" {
  name = "codepipeline-role"
  assume_role_policy = jsonencode({

    Statement = [
      {
        Effect = "Allow"
        Action = "sts:AssumeRole"
        Principal = {
          Service = "codepipeline.amazonaws.com"
        }
      }
    ]
  })
  tags = {
    Name = "${var.app_name}-codepipeline-role"
  }
}

resource "aws_iam_role" "codebuild-role" {
  name = "${var.app_name}-codebuild-role"
  assume_role_policy = jsonencode({
    Statement = [
      {
        Effect = "Allow"
        Action = "sts:AssumeRole"
        Principal = {
          Service = "codebuild.amazonaws.com"
        }
      }
    ]
  })
  tags = {
    Name = "${var.app_name}-codebuild-role"
  }
}

resource "aws_iam_role" "codedeploy-role" {
  name = "${var.app_name}-codedeploy-role"
  assume_role_policy = jsonencode({
    Statement = [
      {
        Effect = "Allow"
        Action = "sts:AssumeRole"
        Principal = {
          Service = "codedeploy.amazonaws.com"
        }
      }
    ]
  })
  tags = {
    Name = "${var.app_name}-codedeploy-role"
  }
}

# cloud watch
resource "aws_iam_role" "cwe_role" {
  name = "${var.app_name}-cwe-role"
  assume_role_policy = jsonencode({

    Version = "2012-10-17"
    Statement = [
      {
        Sid    = ""
        Effect = "Allow"
        Action = "sts:AssumeRole"
        Principal = {
          Service = "events.amazonaws.com"
        }
      }
    ]
  })
  tags = {
    Name = "${var.app_name}-cwe-role"
  }
}
terraform/modules/codepipeline/aws_iam_role_policy.tf
resource "aws_iam_role_policy" "codepipeline-policy" {
  name   = "codepipeline-policy"
  role   = aws_iam_role.codepipeline_role.id
  policy = data.aws_iam_policy_document.codepipeline-policy.json
}

data "aws_iam_policy_document" "codepipeline-policy" {
  statement {
    effect = "Allow"

    actions = [
      "s3:GetObject",
      "s3:GetObjectVersion",
      "s3:GetBucketVersioning",
      "s3:PutObjectAcl",
      "s3:PutObject",
    ]

    resources = [
      aws_s3_bucket.codepipeline_bucket.arn,
      "${aws_s3_bucket.codepipeline_bucket.arn}/*"
    ]
  }
  statement {
    effect = "Allow"

    actions = [
      "ecr:DescribeImages",
    ]

    resources = ["*"]
  }
  statement {
    effect = "Allow"

    actions = [
      "codedeploy:CreateDeployment",
      "codedeploy:GetDeployment",
      "codedeploy:GetApplication",
      "codedeploy:GetApplicationRevision",
      "codedeploy:RegisterApplicationRevision",
      "codedeploy:GetDeploymentConfig",
      "ecs:RegisterTaskDefinition"
    ]

    resources = ["*"]
  }
  statement {
    effect = "Allow"
    actions = [
      "codecommit:GetBranch",
      "codecommit:GetCommit",
      "codecommit:UploadArchive",
      "codecommit:GetUploadArchiveStatus",
      "codecommit:CancelUploadArchive"
    ]
    resources = ["${aws_codecommit_repository.codecommit_repository.arn}"]
  }
  statement {
    effect = "Allow"

    actions = [
      "codebuild:BatchGetBuilds",
      "codebuild:StartBuild",
    ]

    resources = ["*"]
  }
  statement {
    effect = "Allow"
    actions = [
      "iam:GetRole",
      "iam:PassRole"
    ]

    resources = ["*"]
  }
}

resource "aws_iam_role_policy" "codebuild-policy" {
  name   = "codebuild-policy"
  role   = aws_iam_role.codebuild-role.name
  policy = data.aws_iam_policy_document.codebuild-policy.json
}

data "aws_iam_policy_document" "codebuild-policy" {
  statement {
    effect = "Allow"

    actions = [
      "logs:CreateLogGroup",
      "logs:CreateLogStream",
      "logs:PutLogEvents",
    ]

    resources = ["*"]
  }
  statement {
    effect  = "Allow"
    actions = ["s3:*"]
    resources = [
      aws_s3_bucket.codepipeline_bucket.arn,
      "${aws_s3_bucket.codepipeline_bucket.arn}/*",
    ]
  }
  statement {
    effect    = "Allow"
    actions   = ["ecs:DescribeTaskDefinition"]
    resources = ["*"]
  }
}
terraform/modules/codepipeline/aws_iam_policy.tf
# cloud watch
resource "aws_iam_policy" "cwe_policy" {
  name = "${var.app_name}-cwe-policy"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Action = [
          "codepipeline:StartPipelineExecution",
        ]
        Resource = [
          "${aws_codepipeline.codepipeline.arn}",
        ]
        Effect = "Allow"
      },
    ]
  })
}
terraform/modules/codepipeline/aws_iam_policy_attachment.tf
resource "aws_iam_policy_attachment" "cws_policy_attachment" {

  name       = "${var.app_name}-cwe-policy"
  roles      = [aws_iam_role.cwe_role.name]
  policy_arn = aws_iam_policy.cwe_policy.arn
}

resource "aws_iam_role_policy_attachment" "AWSCodeDeployRoleForECS" {
  policy_arn = "arn:aws:iam::aws:policy/AWSCodeDeployRoleForECS"
  role       = aws_iam_role.codedeploy-role.name
}
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?