もがき系プログラマの日常

もがき系エンジニアの勉強したこと、日常のこと、気になっている技術、備忘録などを紹介するブログです。

実践 Terraformを読んでTerraform勉強中 Vol.11

はじめに

こんばんは。

今回は以下の本を読んで勉強中です。

前回の記事はこちら

# 実践 Terraformを読んでTerraform勉強中 Vol.1 - もがき系プログラマの日常

# 実践 Terraformを読んでTerraform勉強中 Vol.2 - もがき系プログラマの日常

実践 Terraformを読んでTerraform勉強中 Vol.3 - もがき系プログラマの日常

実践 Terraformを読んでTerraform勉強中 Vol.4 - もがき系プログラマの日常

実践 Terraformを読んでTerraform勉強中 Vol.5 - もがき系プログラマの日常

実践 Terraformを読んでTerraform勉強中 Vol.6 - もがき系プログラマの日常

実践 Terraformを読んでTerraform勉強中 Vol.7 - もがき系プログラマの日常

実践 Terraformを読んでTerraform勉強中 Vol.8 - もがき系プログラマの日常

実践 Terraformを読んでTerraform勉強中 Vol.9 - もがき系プログラマの日常

実践 Terraformを読んでTerraform勉強中 Vol.10 - もがき系プログラマの日常

今回は第14章です。

バージョンは以下です。

$ terraform --version
Terraform v1.0.3

本題

第14章 デプロイメントパイプライン

CodePipelineを中心にデプロイ関係を学べます。

ここらへんかなり知りたかったところでした。

こういうの使ってかっちょよくデプロイしたいなーと思ってたのですが、このへんで詰まってよくあるデプロイフローに落ち着いちゃってました。

以下のようなフローのようです

1. GithubのWebhookで変更を検知する
2. Githubからソースコードを取得する
3. DockerイメージをビルドしてECRへプッシュする
4. ECRからDockerイメージをpullしてECSへデプロイ

Repositoryの作成(Terraform)

resource "aws_ecr_repository" "default" {
  name = "example"
}
resource "aws_ecr_lifecycle_policy" "default" {
  repository = aws_ecr_repository.default.name

  policy = <<EOF
  {
    "rules": [
      {
        "rulePriority": 1,
        "description": "Keep last 30 release tagged images",
        "selection": {
          "tagStatus": "tagged",
          "tagPrefixList": ["release"],
          "countType": "imageCountMoreThan",
          "countNumber": 30
        },
        "action": {
          "type": "expire"
        }
      }
    ]
  }
EOF
}

作成完了!

f:id:kojirooooocks:20211024005010p:plain

Dockerイメージのpush(コマンド)

1. ログイン
$(aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin https://<aws_account_id>.dkr.ecr.ap-northeast-1.amazonaws.com)
Login Succeeded

aws ecr get-login は非推奨になっています。

2. ビルド
 docker build -t <aws_account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/example:latest contents
[+] Building 5.5s (9/9) FINISHED
=> [internal] load build definition from Dockerfile
=> => transferring dockerfile: 151B
=> [internal] load .dockerignore
=> => transferring context: 2B
=> [internal] load metadata for docker.io/library/nginx:latest
=> [internal] load build context
=> => transferring context: 244B
=> [1/4] FROM docker.io/library/nginx:latest@sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
=> [2/4] COPY ./example.conf /etc/nginx/conf.d/example.conf
=> [3/4] RUN nginx -t
=> [4/4] RUN service nginx restart
=> exporting to image
=> => exporting layers
=> => writing image sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
=> => naming to <aws_account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/example:latest
3. プッシュ
$ docker push <aws_account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/example:latest
The push refers to repository [<aws_account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/example]
b3262df98b84: Pushed 
3fda3d611238: Pushed 
d90d02eee307: Pushed 
9959a332cf6e: Pushed 
f7e00b807643: Pushed 
f8e880dfc4ef: Pushed 
788e89a4d186: Pushed 
43f4e41372e4: Pushed 
e81bff2725db: Pushed 
latest: digest: sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx size: 2191

追加完了!

f:id:kojirooooocks:20211024005318p:plain

CodeBuileの作成(Terraform)

Code Build
# CodeBuildのポリシー追加
data "aws_iam_policy_document" "codebuild" {
  statement {
    effect    = "Allow"
    resources = ["*"]
    actions = [
      "s3:PutObject",
      "s3:GetObject",
      "s3:GetObjectVersion",
      "logs:CreateLogGroup",
      "logs:CreateLogStream",
      "logs:PutLogEvents",
      "ecr:GetAuthorizationToken",
      "ecr:BatchCheckLayerAvailability",
      "ecr:GetDownloadUrlForLayer",
      "ecr:GetRepositoryPolicy",
      "ecr:DescribeRepositories",
      "ecr:ListImages",
      "ecr:DescribeImages",
      "ecr:BatchGetImage",
      "ecr:InitiateLayerUpload",
      "ecr:UploadLayerPart",
      "ecr:CompleteLayerUpload",
      "ecr:PutImage",
    ]
  }
}
# CodeBuildのIAM追加
module "codebuild_role" {
  source     = "./iam"
  name       = "codebuild"
  identifier = "codebuild.amazonaws.com"
  policy     = data.aws_iam_policy_document.codebuild.json
}
# CodeBuildプロジェクトの追加
resource "aws_codebuild_project" "default" {
  name         = "example"
  service_role = module.codebuild_role.iam_role_arn

  source {
    type = "CODEPIPELINE"
  }

  artifacts {
    type = "CODEPIPELINE"
  }

  environment {
    type            = "LINUX_CONTAINER"
    compute_type    = "BUILD_GENERAL1_SMALL"
    image           = "aws/codebuild/standard:2.0"
    privileged_mode = true
  }
}

追加完了!

f:id:kojirooooocks:20211024025403p:plain

終わりに

なかなか複雑...

CodePipelineとgithub連携に関しては別にしようと思います。

本日はここまで。

現場からは以上です。