EC2 Container Service(ECS)を管理して、Blue-Green Deploymentを実現するツールを書いた

最近は暑いのでめっきり外に出なくなりましたが、相変わらずDevOpsのOpsばっかりやっています。

さて、今やってるプロジェクトではAmazon EC2 Container Service(ECS)で完全にDockerベースでの開発をしています。本番運用を見越したオペレーションの作り込みをやってるわけですが、今回はBlue-Green Deploymentを実現してみたよってお話。

材料

必要な材料は以下の通り。

  • VPC
  • Route53
  • EC2
  • ELB
  • AutoScaling Group
  • ECS

方式

最近ELBがAutoScaling Group単位での切り替えができるようになったので、これを利用します。基本的に構成はクラスメソッドさんが紹介されたエントリを参考にさせていただきました。

dev.classmethod.jp

というわけで今回構築した構成がこちら。

f:id:a-yamada:20150722121631p:plain

簡単に説明すると

  • BlueとGreenのEC2 AutoScaling Groupをつくる
  • ECSでBlueとGreen用のClusterをつくる
  • AutoScaling GroupでLaunchされるEC2はECSのクラスタにジョインさせる(userdataで定義すれば勝手にジョインされる)
  • ECS Cluster上ではTask(Dockerコンテナの集合)を稼働させる
  • Primary ELB(ユーザーから参照される方)にぶら下がるAutoScaling Groupが現在の稼動系
  • 稼働してないAutoScaling GroupにはStandbyがぶらさがり、ELBの切り替えによってBlueとGreenを切り替える

というオペレーションです。

ecs-formation

今回はこの流れを実現するためにecs-formationというツールを書きました。

github.com

以下の機能をサポートしています。まあどんな感じかはREADMEをご覧あれ。

  • docker-composeライクなTask Definitionの定義
  • ECSのServiceの更新
  • Blue-Green Deployment

Task Definition

docker-compose.ymlを拡張してmemoryとかcpu_unitsとかの定義ができるようにしてます。

nginx:
  image: nginx:latest
  ports:
    - 80:80
  environment:
    PARAM1: value1
    PARAM2: value2
  links:
    - api
  memory: 512
  cpu_units: 512
  essential: true

Service

Serviceはいわゆるスケジューラーのことで、指定したTask数(desired_count)分のタスクをクラスタ上で走らせるようコントロールします。これも以下のように定義できます。

test-service:
  task_definition: test-definition
  desired_count: 2

Blue-Green Deployment

Blue-Grenn Deploymentは以下のように定義します。

blue:
  cluster: test-blue
  service: test-service
  autoscaling_group: test-blue-asg
green:
  cluster: test-green
  service: test-service
  autoscaling_group: test-green-asg
primary_elb: test-elb-primary
standby_elb: test-elb-standby

あとはecs-formation bluegreen apply Blue-Grenn定義名 みたいな感じでコマンド打つとBlue-Greenの切り替えが起こります。この処理ではELBの切り替えと、次に稼働系統となる方のECSクラスタの更新を行います。

ChatOps

今のプロジェクトではdeployをSlack → CircleCI経由で行ってます。Blue-Greenも同様です。

Slackでこんな感じで指示すると・・・

f:id:a-yamada:20150722125325p:plain

CircleCIが走りだして・・・

f:id:a-yamada:20150722125105p:plain

(途中省略・・・、Serviceの起動確認等が行われる)

f:id:a-yamada:20150722125648p:plain

切り替わったっぽい。めでたしめでたし。