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.

ecspresso + ecschedule + Actionsでスケジュールタスクを自動更新

Last updated at Posted at 2024-06-23

はじめに

スケジュールタスクの管理・運用に便利な「ecschedule」について、別の記事で基本操作をご紹介しました。前回の記事では、ローカル環境で操作しタスクスケジュールを更新する方法を説明しました。

しかし、ecscheduleにはタスク定義を更新する機能がないため、実運用では別の方法でタスク定義を更新する必要があります。

そこで、ecspressoのタスク定義更新機能と組み合わせることで、タスクスケジュールの更新を自動化できるのではないかと考えました。
今回は、ecscheduleに加え、ecspressoとGitHub Actionsを組み合わせて、タスクスケジュールを自動更新する方法について書いていきます。

書くこと

  • ecspresso + ecschedule + Actionsでスケジュールタスクを自動更新する方法

前提

  • AWS Fargate上でApache httpdイメージからコンテナを起動する環境を用意
  • ecspressoで使用する設定ファイルの用意
  • AWSのnetwork周りをTerraformで管理

ディレクトリ構成

.

├── .github
│   └── workflows
│       └── deploy.yml
├── .gitignore
├── deploy
│   ├── ecs-task-def.json
│   ├── ecschedule.yaml
│   └── ecspresso.yml
└── terraform
    └── env
        └── prod
            ├── .terraform-version
            ├── .terraform.lock.hcl
            ├── main.tf
            ├── network.tf
            └── variable.tf

Actionsの作成

Github Actionsを使ってスケジュールタスクの自動更新ワークフローを作成していきます。
大まかな処理の流れは以下の通りです。

  1. ecspressoを使ってタスク定義の更新
  2. 最新のタスク定義のリビジョンを取得
  3. ecscheduleでスケジュールタスクを更新
deploy.yml
name: 'deploy'

on:
  push:
    branches:
      - master

jobs:
  register-task-definition:
    runs-on: ubuntu-latest
    steps:
    - name: "checkoutする"
      uses: actions/checkout@v4
    - name: "ecspressoのインストール"
      uses: kayac/ecspresso@v2
      with:
        version: latest
    - name: "タスク定義の登録"
      run: |
        ecspresso register --config ecspresso.yml
      shell:
        bash
      working-directory: ./deploy
      env:
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID_PROD }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY_PROD }}
        AWS_DEFAULT_REGION: ap-northeast-1
  
  update-ecs-schedule:
    needs: ["register-task-definition"]
    runs-on: ubuntu-latest
    steps:
    - name: "checkoutする"
      uses: actions/checkout@v4
    - name: "ecscheduleのインストール"
      uses: Songmu/ecschedule@main
      with:
        version: latest
    - name: configure aws credentials
      uses: aws-actions/configure-aws-credentials@v2
      with:
        aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID_PROD }}
        aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_PROD }}
        aws-region: ap-northeast-1
    - name: "ECSのスケジュールを更新する"
      run: |
        ecschedule -conf ecschedule.yaml apply -all
      shell: bash
      working-directory: ./deploy
      env:
        S3_TFSTATE_URL: ${{ secrets.S3_TFSTATE_URL_PROD }}

タスク定義の更新

はじめにregister-task-definitionジョブでタスク定義を更新しています。
まずはタスク定義の更新に必要なecspressoをインストールし、その後registerコマンドでタスク定義を更新しています。
deployディレクトリ以下にあるecspresso関連の設定ファイルの内容は以下のようになっています。

ecspresso.yml
region: "ap-northeast-1"
cluster: ecshedule-test
service: ecschedule-test
task_definition: ecs-task-def.json
timeout: "10m0s"

ecs-task-def.json
{
  "containerDefinitions": [
    {
      "command": [
        "sh",
        "-c",
        "echo 'Hello World.' \u003e index.html \u0026\u0026 httpd-foreground"
      ],
      "cpu": 0,
      "essential": true,
      "image": "httpd:latest",
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-create-group": "true",
          "awslogs-group": "/ecs/ecschedule-test",
          "awslogs-region": "ap-northeast-1",
          "awslogs-stream-prefix": "ecs"
        }
      },
      "name": "apache",
      "portMappings": [
        {
          "appProtocol": "http",
          "containerPort": 80,
          "hostPort": 80,
          "name": "apache-80-tcp",
          "protocol": "tcp"
        }
      ],
      "workingDirectory": "/usr/local/apache2/htdocs/"
    }
  ],
  "cpu": "256",
  "executionRoleArn": "arn:aws:iam::XXXXXXXXXXX:role/ecsTaskExecutionRole",
  "family": "ecschedule-test",
  "memory": "512",
  "networkMode": "awsvpc",
  "requiresCompatibilities": [
    "FARGATE"
  ],
  "runtimePlatform": {
    "cpuArchitecture": "X86_64",
    "operatingSystemFamily": "LINUX"
  },
  "taskRoleArn": "arn:aws:iam::XXXXXXXXXXX:role/ecsTaskExecutionRole"
}

スケジュールタスクの更新

update-ecs-scheduleジョブでは、最新のタスク定義リビジョンの取得とスケジュールタスクの更新を行います。ここで、register-task-definitionジョブで登録されたタスク定義のリビジョンを取得するために、needsキーワードを使って依存関係を作成しています。

最新のリビジョン番号を取得するには、AWS CLIのaws ecs list-task-definitionsコマンドとシェルスクリプトを組み合わせています。取得したリビジョン番号はGitHub Actionsの環境変数TASK_DEFINITION_REVISIONに追加され、後続のステップで利用可能になります。

今回は--family-prefix ecschedule-testで対象のタスク定義を指定していますが、皆さんの環境に合わせて適宜書き換えてください。

taskDefinitionにリビジョン番号を指定しなければ、自動的に最新のリビジョンを指定してくれるので上記の手順は必要ありませんでした。

ecschedule.yamlの設定は以下のようになっています。

ecschedule.yaml
region: ap-northeast-1
cluster: ecshedule-test
rules:
- name: ecschedule-example
  scheduleExpression: rate(10 minutes)
  disabled: true
  targetId: test
  taskDefinition: ecschedule-test
  launch_type: FARGATE
  platform_version: LATEST
  network_configuration:
    aws_vpc_configuration:
      subnets:
      - {{ tfstate `aws_subnet.private_subnet_a.id` }}
      - {{ tfstate `aws_subnet.private_subnet_c.id` }}
      - {{ tfstate `aws_subnet.private_subnet_d.id` }}
      security_groups:
      - {{ tfstate `aws_security_group.default_sg.id` }}
      assign_public_ip: DISABLE
plugins:
- name: tfstate
  config:
    url: {{ must_env `S3_TFSTATE_URL` }}

説明

タスク定義リビジョンの置き換え
  • taskDefinitionのリビジョン番号部分を、最新のリビジョン番号であるTASK_DEFINITION_REVISIONに置き換えます
ネットワーク設定
  • subnetsおよびsecurity_groupsの値は、tfstateから取得するように設定しています。これにより、TerraformのstateファイルからサブネットIDとセキュリティグループIDを動的に取得します
プラグイン設定
  • tfstateプラグインを追加し、Terraformの状態ファイルが保管されているURLもしくはパスを指定する必要があります
  • 今回はstateファイルをS3で管理しているのでs3のURLを入れています

この設定により、最新のタスク定義リビジョンを確実に取得し、それを使用してスケジュールタスクを更新することができます。サブネットとセキュリティグループの設定は、Terraformのstateファイルから動的に取得されるため、インフラストラクチャの変更や複数環境への反映に柔軟に対応できます。

デプロイに必要な権限

上記Actionsを実行するために必要な権限は以下になります。
各用途毎にpolicyを分けています。

ecschedule-policy
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "events:TagResource",
                "events:PutTargets",
                "events:PutRule",
                "events:ListTargetsByRule",
                "events:ListRules"
            ],
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}
get-tfstate
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject"
            ],
            "Resource": [
                "arn:aws:s3:::hoge/terraform.tfstate"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::hoge" #tfstateを保管しているバケットを指定
            ]
        }
    ]
}
passrole
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "IAM",
            "Effect": "Allow",
            "Action": "iam:PassRole",
            "Resource": [
                "arn:aws:iam::XXXXXXXXXXXX:role/ecsTaskExecutionRole",
                "arn:aws:iam::XXXXXXXXXXXX:role/ecsEventsRole"
            ]
        }
    ]
}
register-ecs-task-def
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "ecs:RegisterTaskDefinition",
                "ecs:ListTaskDefinitions",
                "ecs:DescribeTaskDefinition"
            ],
            "Effect": "Allow",
            "Resource": "*",
            "Sid": "ECSRegisterTaskDefinition"
        }
    ]
}

実行結果

実際に動くか検証していきます。
タスク定義のcomanndを書き換えてapacheのバージョンを出力するように書き換えます。

command": [
-  "sh",
-  "-c",
-  "echo 'Hello World.' \u003e index.html \u0026\u0026 httpd-foreground"
+  "httpd",
+  "-v"
]

変更をコミットしてリポジトリにpush

スクリーンショット 2024-06-23 20.10.02.png

ワークフローが実行完了したことを確認

スクリーンショット 2024-06-24 1.47.13.png

Cloudwatch logsにApacheのバージョンが記録されているので、更新したスケジュールタスクの処理が完了している

まとめ

今回は、ecschedule、ecspresso、そしてGitHub Actionsを使ってスケジュールタスクを自動更新する方法を紹介しました。
自動化することで、タスク定義を更新した際にスケジュールタスクの設定を変更し忘れるといったミスを防ぐことが期待できます。

皆さんの環境に合わせて設定を調整し、より効率的なスケジュールタスクの運用を目指していきましょう!!

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?