ECS+ALB+hakoでホットデプロイ

ホットデプロイが流行っているらしいので。

github.com

hakoはECS用のデプロイツールで社内ではいろいろと使われています。 ALBと組み合わせて使うと、頑張っている感じのホットデプロイまわりがシンプルになってよいです。

まだ正式にはALBに対応していないのですが、使う方法を後ろの席の人が教えてくれたので、メモしておきます。

2016/09/07 ALBに対応したようです。 https://github.com/eagletmt/hako/pull/11

hakoのインストール

gemでインストール。

gem install hako

EC2インスタンスの準備

とりあえず適当なインスタンスがあればいいのでecs-cliインスタンス群を起動。

ecs-cli configure \
  -r ap-northeast-1 \
  -c hello-hako

ecs-cli up \
  --keypair winebarrel \
  --capability-iam \
  --size 2 \
  --vpc vpc-... \
  --subnets subnet-... \
  --security-group sg-... \
  --instance-type m4.large

f:id:winebarrel:20160902232008p:plain

f:id:winebarrel:20160902232034p:plain

おけおけ。

タスク定義

以下のようなタスクを定義したyamlを用意。 だいたいはjsonにそのまま対応しているのんですが、微妙に差異があったりなかったり(リファレンス欲しいなぁ)

  • hello-hako.yml(ファイル名がサービス名・タスク名・クラスタ名になる)
scheduler:
  type: ecs
  region: ap-northeast-1
  cluster: hello-hako
  desired_count: 2
app:
  image: nginx
  memory: 300
  cpu: 256
  essential: true
  mount_points:
    - container_path: /usr/share/nginx/html
      source_volume: vol
    - container_path: /var/log/httpd
      source_volume: log
  port_mappings:
    - host_port: 0
      container_port: 80
additional_containers:
  busybox:
    image_tag: busybox
    cpu: 64
    memory: 256
    env:
      MSG: hello
    volumes_from:
      - source_container: app
    # entry_pointはまだ使えないっぽい
    command:
      - /bin/sh
      - -c
      - |
        while true; do
          date >> /usr/share/nginx/html/index.html
          echo $MSG >> /usr/share/nginx/html/index.html
          echo '<br>' >> /usr/share/nginx/html/index.html
          sleep 3
        done
volumes:
  vol: {}
  log:
    source_path: /var/log/httpd

デプロイ

以下のコマンドをたたいて、タスクをデプロイ。

$ hako deploy hello-hako.yml
I, [2016-09-02T22:42:59.125887 #10722]  INFO -- : Registered task definition: arn:aws:ecs:ap-northeast-1:...:task-definition/hello-hako:36
I, [2016-09-02T22:42:59.263683 #10722]  INFO -- : Updated service: arn:aws:ecs:ap-northeast-1:...:service/hello-hako
I, [2016-09-02T22:43:07.825926 #10722]  INFO -- : 2016-09-02 22:43:07 +0900: (service hello-hako) has started 2 tasks: (task adf37618-c758-456b-a35c-cbac2a4a34a4) (task 5b1412d1-ca3d-46d0-8ed8-f3b0fedd3904).
I, [2016-09-02T22:43:13.976431 #10722]  INFO -- : Deployment completed

そうするとサービスが作られます。

f:id:winebarrel:20160902232531p:plain

が、これは削除。(事前にNumber of tasks0にする)

f:id:winebarrel:20160902232624p:plain

ALBの作成

次にコマンドラインからALBを作成。

aws elbv2 create-load-balancer --name hello-hako --subnets subnet-xxx subnet-yyy --security-group sg-...

サービスの再作成

同じ名前でサービスを再作成。 このときにALBの設定もします。

f:id:winebarrel:20160902233046p:plain f:id:winebarrel:20160902233147p:plain f:id:winebarrel:20160902233131p:plain

あと、ターゲットグループのDeregistration delayは短めで。 f:id:winebarrel:20160902233230p:plain

で、サービス作成完了。

f:id:winebarrel:20160902233347p:plain

一応、ALBにアクセス。

f:id:winebarrel:20160902233533p:plain

おけおけ。

ホットデプロイ

yamlを以下のように変更してデプロイ。

    command:
      - /bin/sh
      - -c
      - |
        while true; do
          echo modified >> /usr/share/nginx/html/index.html 
          date >> /usr/share/nginx/html/index.html
          echo $MSG >> /usr/share/nginx/html/index.html
          echo '<br>' >> /usr/share/nginx/html/index.html
          sleep 3
        done
$ hako deploy hello-hako.yml
I, [2016-09-02T23:06:55.847629 #16101]  INFO -- : Registered task definition: arn:aws:ecs:ap-northeast-1:...:task-definition/hello-hako:37
...

デプロイと同時にサービスを監視。

$ while true; do echo `date +%X`" | "`curl -s http://hello-hako-1111294014.ap-northeast-1.elb.amazonaws.com/ | head -n 1`; sleep 1; done
230710秒 | Fri Sep 2 14:05:25 UTC 2016
...

しばらく待つとデプロイ完了。

$ hako deploy hello-hako.yml
I, [2016-09-02T23:06:55.847629 #16101]  INFO -- : Registered task definition: arn:aws:ecs:ap-northeast-1:...:task-definition/hello-hako:37
I, [2016-09-02T23:06:56.190146 #16101]  INFO -- : Updated service: arn:aws:ecs:ap-northeast-1:...:service/hello-hako
I, [2016-09-02T23:07:29.817474 #16101]  INFO -- : 2016-09-02 23:07:28 +0900: (service hello-hako) has started 2 tasks: (task c8467e26-c46b-41f7-87b1-f58690fdc1de) (task 058bd7d7-4cfe-4f1b-baf9-46b4d623581a).
I, [2016-09-02T23:07:29.817558 #16101]  INFO -- : 2016-09-02 23:07:28 +0900: (service hello-hako) has begun draining connections on 1 tasks.
I, [2016-09-02T23:07:29.817599 #16101]  INFO -- : 2016-09-02 23:07:28 +0900: (service hello-hako) deregistered 1 targets in (target-group arn:aws:elasticloadbalancing:ap-northeast-1:...:targetgroup/ecs-hello-hello-hako/f1593d29b6a39517)
I, [2016-09-02T23:07:43.310115 #16101]  INFO -- : 2016-09-02 23:07:38 +0900: (service hello-hako) registered 2 targets in (target-group arn:aws:elasticloadbalancing:ap-northeast-1:...:targetgroup/ecs-hello-hello-hako/f1593d29b6a39517)
I, [2016-09-02T23:07:43.310198 #16101]  INFO -- : 2016-09-02 23:07:38 +0900: (service hello-hako) has stopped 1 running tasks: (task a1bb3d3a-ebfa-45dd-8022-907f9c212d49).
I, [2016-09-02T23:07:56.160512 #16101]  INFO -- : 2016-09-02 23:07:51 +0900: (service hello-hako) has begun draining connections on 2 tasks.
I, [2016-09-02T23:07:56.160670 #16101]  INFO -- : 2016-09-02 23:07:51 +0900: (service hello-hako) deregistered 1 targets in (target-group arn:aws:elasticloadbalancing:ap-northeast-1:...:targetgroup/ecs-hello-hello-hako/f1593d29b6a39517)
I, [2016-09-02T23:08:08.035586 #16101]  INFO -- : 2016-09-02 23:08:05 +0900: (service hello-hako) registered 1 targets in (target-group arn:aws:elasticloadbalancing:ap-northeast-1:...:targetgroup/ecs-hello-hello-hako/f1593d29b6a39517)
I, [2016-09-02T23:08:08.035677 #16101]  INFO -- : 2016-09-02 23:08:04 +0900: (service hello-hako) has stopped 1 running tasks: (task 31877197-9498-45be-b345-8f3457e4dd09).
I, [2016-09-02T23:08:18.055483 #16101]  INFO -- : Deployment completed

監視の方は…

23時07分37秒 | Fri Sep 2 14:05:24 UTC 2016
23時07分38秒 | Fri Sep 2 14:05:25 UTC 2016
23時07分39秒 | Fri Sep 2 14:05:25 UTC 2016
23時07分40秒 | Fri Sep 2 14:05:25 UTC 2016
23時07分41秒 | modified
23時07分43秒 | Fri Sep 2 14:05:25 UTC 2016
23時07分44秒 | modified
23時07分45秒 | modified
23時07分46秒 | Fri Sep 2 14:05:25 UTC 2016
23時07分47秒 | modified
23時07分48秒 | modified
23時07分49秒 | Fri Sep 2 14:05:25 UTC 2016
23時07分50秒 | modified
23時07分51秒 | modified
23時07分52秒 | Fri Sep 2 14:05:25 UTC 2016
23時07分54秒 | modified
23時07分55秒 | modified
23時07分56秒 | Fri Sep 2 14:05:25 UTC 2016
23時07分57秒 | modified
23時07分58秒 | modified
23時07分59秒 | Fri Sep 2 14:05:25 UTC 2016
23時08分00秒 | modified
23時08分01秒 | modified
23時08分02秒 | Fri Sep 2 14:05:25 UTC 2016
23時08分03秒 | modified
23時08分04秒 | modified
23時08分06秒 | modified
23時08分07秒 | modified

おけおけ。 ダウンタイムないですね。