Open2

AWS+Goでの環境構築

nerusannerusan

DBでユーザ作成

  • DBで特定のデータベースだけ操作できるユーザを作成する

go installでマイグレーション適用

# マイグレーションツール
$ go install golang.org/x/tools/gopls@latest
# マイグレーション適用
$ /home/ec2-user/go/bin/mysqldef -u [user] -p [password] -h sample-app-db.cluster-aaaa.ap-northeast-1.rds.amazonaws.com -P 3306 point_app < ./_tools/mysql/schema.sql
nerusannerusan

CI/CDの構築

今回はdocker imageのビルドおよびECRへの登録はGitHubActionで行い、ECRからDocker Imageを取得してきて、コンテナを際デプロイするのはAWSのcodepipelineに任せる

参考
https://zenn.dev/reireias/articles/8e987af2762eaa#3.-image-buildのみgithub-actionsでやる

GitHub Action

  1. GitHubからECRにアクセスするためのIAMユーザの作成
    IAM->ユーザ->ユーザ作成よりユーザを作成する
    「AWS 認証情報タイプを選択」では「アクセスキー - プログラムによるアクセス」のみを選択する
    ポリシーは、該当のECRにアクセスできるポリシーをアタッチする
ポリシーjson例
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ListImagesInRepository",
            "Effect": "Allow",
            "Action": [
                "ecr:ListImages"
            ],
            "Resource": [
                "arn:aws:ecr:ap-northeast-1:<アカウントID>:repository/point-app-backend"
            ]
        },
        {
            "Sid": "GetAuthorizationToken",
            "Effect": "Allow",
            "Action": [
                "ecr:GetAuthorizationToken"
            ],
            "Resource": "*"
        },
        {
            "Sid": "ManageRepositoryContents",
            "Effect": "Allow",
            "Action": [
                "ecr:BatchCheckLayerAvailability",
                "ecr:GetDownloadUrlForLayer",
                "ecr:GetRepositoryPolicy",
                "ecr:DescribeRepositories",
                "ecr:ListImages",
                "ecr:DescribeImages",
                "ecr:BatchGetImage",
                "ecr:InitiateLayerUpload",
                "ecr:UploadLayerPart",
                "ecr:CompleteLayerUpload",
                "ecr:PutImage"
            ],
            "Resource": [
                "arn:aws:ecr:ap-northeast-1:<アカウントID>:repository/point-app-backend"
            ]
        }
    ]
}

作成したらAWS_SECRET_ACCESS_KEY, AWS_SECRET_KEYが表示されるのでメモする。

  1. workflowsの作成
    mainブランチにマージされたら、dockerイメージをビルドECRに登録するworkflowを示す。
    該当リポジトリの.github/workflows/aws.ymlを作成する
aws.yml
name: Deploy to Amazon ECR

on: 
  push:
    branches:
      - main

env:
  AWS_REGION: ap-northeast-1              # set this to your preferred AWS region, e.g. us-west-1
  ECR_REPOSITORY: point-app-backend       # file, e.g. .aws/task-definition.json

permissions:
  contents: read

jobs:
  deploy:
    name: Deploy
    runs-on: ubuntu-latest
    environment: production

    steps:
    - name: Checkout
      uses: actions/checkout@v3

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v1
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        aws-region: ${{ env.AWS_REGION }}

    - name: Login to Amazon ECR
      id: login-ecr
      uses: aws-actions/amazon-ecr-login@v1

    - name: Build, tag, and push image to Amazon ECR
      id: build-image
      env:
        ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
        IMAGE_TAG: ${{ github.sha }}
      run: |
        # タグをlatestとコミットidをつけてビルド
        docker image build --target deploy -t $ECR_REGISTRY/$ECR_REPOSITORY:latest -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
        # ECRにpush
        docker image push -a $ECR_REGISTRY/$ECR_REPOSITORY
        echo "::set-output name=image::$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG"
  1. github secretsの登録
    プロジェクトのsettings->secretsを押してRepository secretsを作成をクリック。先ほどメモしたAWS_SECRET_ACCESS_KEY, AWS_SECRET_KEYをそれぞれ登録する。

  2. コミットPRして完了

タグを切った時にそれをビルドする方法は以下参照
https://dev.classmethod.jp/articles/github-action-ecr-push/

参考
https://dev.classmethod.jp/articles/githubactions-ecs-fargate-cicd-beginner/

CodePipeline

ECRが登録されたらそれをトリガーにECSにデプロイするCDをCodePipelineにより実現します。

  1. appspecファイルとタスク定義ファイルの用意

タスク定義jsonは、ECS->タスク定義->jsonよりコピーしてもってくる。ただ、 イメージは以下の様にIMAGE1_NAMEとして置き換える。

taskdef.json
{
  "executionRoleArn": "arn:aws:iam::[aws_account_id]:role/ecsTaskExecutionRole",
  "containerDefinitions": [
    {
      "logConfiguration": {
        "logDriver": "awslogs",
        "secretOptions": null,
        "options": {
          "awslogs-group": "/ecs/sbcntr-backend-def",
          "awslogs-region": "ap-northeast-1",
          "awslogs-stream-prefix": "ecs"
        }
      },
      "portMappings": [
        {
          "hostPort": 80,
          "protocol": "tcp",
          "containerPort": 80
        }
      ],
      "cpu": 256,
      "readonlyRootFilesystem": true,
      "environment": [],
      "secrets": [
        {
          "valueFrom": "arn:aws:secretsmanager:ap-northeast-1:[aws_account_id]:secret:[mysql_secret_alias]:host::",
          "name": "DB_HOST"
        },
        {
          "valueFrom": "arn:aws:secretsmanager:ap-northeast-1:[aws_account_id]:secret:[mysql_secret_alias]:dbname::",
          "name": "DB_NAME"
        },
        {
          "valueFrom": "arn:aws:secretsmanager:ap-northeast-1:[aws_account_id]:secret:[mysql_secret_alias]:password::",
          "name": "DB_PASSWORD"
        },
        {
          "valueFrom": "arn:aws:secretsmanager:ap-northeast-1:[aws_account_id]:secret:[mysql_secret_alias]:username::",
          "name": "DB_USERNAME"
        }
      ],
      "memory": null,
      "memoryReservation": 512,
      "image": "<IMAGE1_NAME>",
      "essential": true,
      "name": "app"
    }
  ],
  "memory": "1024",
  "taskRoleArn": null,
  "family": "sbcntr-backend-def",
  "requiresCompatibilities": ["FARGATE"],
  "networkMode": "awsvpc",
  "cpu": "512"
}
appspec.yaml
version: 1
Resources:
- TargetService:
    Type: AWS::ECS::Service
    Properties:
        TaskDefinition: <TASK_DEFINITION>
        LoadBalancerInfo: 
            ContainerName: "app"
            ContainerPort: 80
  1. 1のファイルをS3に登録
    appspec.yamlとtaskdef.jsonをzipにする
    S3->パケット作成をしてrootに先ほどのzipファイルを保存する

  2. codepipilineの設定
    codepipelineより新たに作成を選択。
    名前とロールを入れて次へ

ECRを選び該当のリポオジトリを選択。画像タグはlatestにして、latestが変更されるとトリガーとなる。

ビルドはスキップ。

デプロイはとりあえず以下で登録。

登録が完了すると再度編集を押す。

Sourceを編集を押して、アクションの追加を押す。
先ほどの登録した設定を呼び出すアクションを以下の様に追加する。

次にDeployを編集し、入力アーティファクトを追加して、タスク定義とappspecファイルの読み込み先を変更する

以上で準備完了。