AutoScaling(オートスケーリング)時のデプロイのベストプラクティス(CodeDeploy)

AutoScaling(オートスケーリング)時にはLaunchConfigのAMIを元に新しいインスタンスが作成されます。
しかし、GitHub等のリビジョンが進んでいると新しいインスタンスのみ古いリビジョンのソースになってしまいます。
そのため、主に以下の2つの方法があります。

デプロイの度にAMIを作成して、AutoScalingGroup(オートスケーリンググループ)とELBを差し替える

サーバー内の変更時もデプロイ時も常に同じことをすればいいので、判断が不要になることが利点です。
しかし、デプロイの度にAMIを作成して、AutoScalingGroupとELBを作成して、
CodeDeployのApplicationStopイベントが初回のデプロイ時には動かないため、
AutoScalingGroup(オートスケーリンググループ)に対して1回デプロイして、
Route53のCNAMEレコードを切り替えて、旧リソースを削除してと手順が多いです。

また、GitHubでプルリクがマージされた際に上記手順が実行されるように自動化するのは手間がかかります。
結果的に手動になり、事故の元となります。

DeploymentGroup(CodeDeploy)の対象をAutoScalingにする

新しいインスタンスが追加される前に自動的にGitHubの最新のリビジョンがデプロイされます。
デプロイの際にはデプロイの実行のみでよいです。
GitHubのプルリクがマージされた際に自動的にデプロイされるように簡単に設定することができます。

上記から基本的にAutoScaling(オートスケーリング)のデプロイにはCodeDeployを使用すべきです。
そこで詳細を記載致します。

AutoScaling(オートスケーリング)に対するDeploymentGroup(CodeDeploy)を設定した際に何が設定されているか

  • CodeDeploy用のLifecycleHookが設定される
$ aws autoscaling describe-lifecycle-hooks --auto-scaling-group-name XXXXXX
        {
            "AutoScalingGroupName": "XXXX-AutoScalingStack-XXXX-AutoScalingGroup-XXXX",
            "HeartbeatTimeout": 600,
            "DefaultResult": "ABANDON",
            "NotificationMetadata": "XXXXXXXXXXXX",
            "NotificationTargetARN": "XXXXXXXXXXX",
            "LifecycleHookName": "CodeDeploy-managed-automatic-launch-deployment-hook-production-XXXX",
            "GlobalTimeout": 60000,
            "LifecycleTransition": "autoscaling:EC2_INSTANCE_LAUNCHING"
        }

全体像は以下の図です。

AutoScaling時の挙動

f:id:keiwt:20160910203602p:plain

上記図を元に考慮すべきベストプラクティスは以下の通りです。

ベスト・プラクティス

  • CustomAMIではcodedeploy-agentを停止して、起動時にstartする
    ※CodeDeployを動かせたいタイミングでstartします
        "UserData": { "Fn::Base64" : { "Fn::Join" : ["", [
          "#!/bin/bash -xe\n",
          "# Install the files and packages from the metadata\n",
          "/opt/aws/bin/cfn-init",
          " --stack ", { "Ref" : "AWS::StackName" },
          " --resource LaunchConfig",
          " --configsets Install",
          " --region ", { "Ref" : "AWS::Region" }, "\n",

          "service codedeploy-agent start\n",

          "# Signal the status from cfn-init\n",
          "/opt/aws/bin/cfn-signal -e $?",
          " --stack ", { "Ref" : "AWS::StackName" },
          " --resource AutoScalingGroup",
          " --region ", { "Ref" : "AWS::Region" }, "\n"
        ]]}}
通常の場合は1リポジトリになっていると思います。  
もし、1AutoScalingGroup複数リポジトリになっている場合はアーキテクチャがおかしいです。 
AutoScalingGroupを分けるべきです。
※フロント、管理画面、API、バッチサーバー等が同居しているようなおかしいケースが該当します。
※1サーバー1機能

Troubleshoot Auto Scaling Issues - AWS CodeDeploy

参考・引用元

Under the Hood: AWS CodeDeploy and Auto Scaling Integration - AWS DevOps Blog - Amazon Web Services
Integrating AWS CodeDeploy with Auto Scaling - AWS CodeDeploy