Edited at

Ruby aws-sdkを使ってECSをデプロイ※サンプルコード


これはなに?

Circle Ciを用いたAutoDeployを設定した際、Ruby aws-sdkの知見があまり見当たらなかったのでサンプルコードとしてまとめさせて頂きました。

特にBlue Green Deployment x Fargateのデプロイ記事は少なかったので、お役に立てましたら幸いです。

Circle Ciでの設定諸々は割愛させていただきます。


前提

ECRで最新のcommit hashをタグにしたdocker imageが既に上がっている


タスク定義

require 'aws-sdk-ecs'

REPO_HOST = 'XXXXXXXX.dkr.ecr.XXXXXXXX.amazonaws.com'.freeze # ECRホスト
REPO = 'XXXXXXXX'.freeze # ECRリポジトリ名
IMAGE_HASH = ARGV.first # 対象のcommit hash
SERVICE_NAME = 'XXXXXXXX-service'.freeze # ECSサービス名
CLUSTER_NAME = 'XXXXXXXX-ecs-cluster'.freeze # ECSクラスター名
FAMILY = 'XXXXXXXX-taskdef'.freeze # ECSタスク定義

client = Aws::ECS::Client.new

# タスク定義一覧を取得
# 最新のタスク定義を取得
latest_task = client.list_task_definitions(
{
family_prefix: FAMILY
}
).task_definition_arns.last

# 最新のタスク定義から新たに作製するタスク定義の設定をコピー
task_def_hash = client.describe_task_definition(
{
task_definition: latest_task
}
).task_definition.to_hash

# タスク定義の設定を整形していく
# imageはdeployしたいものに変更する
task_def_hash[:container_definitions].first[:image] = REPO_HOST + '/' + REPO + ':' + IMAGE_HASH

# いらないkeyは削除する
task_def_hash.delete :task_definition_arn
task_def_hash.delete :revision
task_def_hash.delete :status
task_def_hash.delete :requires_attributes
task_def_hash.delete :compatibilities

# タスク定義を登録
response = client.register_task_definition(task_def_hash)


サービス更新 ※Rolling Deployment

require 'aws-sdk-ecs'

# タスク定義を作った時のresponseからtask_definitionは指定する
client.update_service(
{
cluster: CLUSTER_NAME,
service: SERVICE_NAME,
task_definition: res.task_definition.family + ':' + response.task_definition.revision.to_s
}
)


サービス更新 ※Blue Green Deployment

require 'aws-sdk-ecs'

require 'aws-sdk-codedeploy'
require 'digest'
# タスク定義の指定用にarnを控えておく
arn = client.register_task_definition(task_def_hash).task_definition.task_definition_arn

# code-deploy clientを生成
code_deploy_client = Aws::CodeDeploy::Client.new

# AppSpecContentのjsonを整形
# AppSpecContentとはbree gree deploymentで必要な設定のこと
# AWS コンソール上のCodeDeploy >アプリケーション > hogehoge > Revisionのアプリ仕様に記載。
content_json = {
version: 1,
'Resources' => [
{
'TargetService': {
'Type': 'AWS::ECS::Service',
'Properties': {
'TaskDefinition': arn,
'LoadBalancerInfo': {
'ContainerName': CONTAINER_NAME,
'ContainerPort': 80
},
'PlatformVersion': 'latest'
}
}
}
]
}.to_json

# execute
code_deploy_client.create_deployment(
{
application_name: DEPLOYMENT_APP_NAME,
deployment_group_name: DEPLOYMENT_GROUP_NAME,
revision: {
revision_type: 'AppSpecContent',
app_spec_content: {
content: content_json,
sha256: Digest::SHA256.hexdigest(content_json)
}
}
}
)

以上。

circle ciでうまくフックしてデプロイを無人化しましょう。