ようへいの日々精進XP

よかろうもん

CodeDeploy をオンプレミス環境で利用してみる

はじめに

CodeDeploy は Deploy 先としてオンプレミス環境のサーバーも指定することが出来るようなので EC2 を複数起動するよりもコスト削減出来るかなあという軽い気持ちで触ってみた。

aws.typepad.com

デプロイの流れ

ざっくりとデプロイの流れを。

  1. オンプレサーバーを登録する
  2. オンプレサーバーを登録した際に作成した IAM ユーザーに権限を付与する(※ IAM グループに権限を付与した)
  3. オンプレサーバーに CodeDeploy Agent をインストールする
  4. aws deploy create-application でアプリケーションを登録
  5. aws deploy push でコンテンツを S3 にアップロード
  6. aws deploy create-deployment-group でデプロイ対象を定義(オンプレサーバーを追加する)
  7. aws depoy create-deploy でデプロイ

コスト

オンプレミスのサーバーだと EC2 の課金が発生しないぜーと思っていたら、オンプレミスのサーバーにデプロイする際には...

AWS CodeDeploy オンプレミス: AWS CodeDeploy を使用したアップデートの料金は、1 つのオンプレミスインスタンスあたり 0.02 USD です。最低料金や前払いの義務は発生しません。例えば、3 つのインスタンスへのデプロイと、3 つのインスタンスへのアップデートは同じ料金となります。CodeDeploy を実行してインスタンスをアップデートしたときのみ料金が発生します。デプロイが実行されなかったインスタンスがあれば、その分は課金されません。

とあるので 1 台あたり 0.02 ドルは掛かるので財布と相談しながら Deploy したい。

エージェントのサポート対象

尚、エージェントがサポートしている環境は以下の通り。

上記の通りなので、今回のオンプレミスサーバーは Ubuntu 14.04 で用意する。


IAM 関連の設定

Deploy 用グループを作成

IAM にて deploy という名前でグループを作成する。ポリシーとして Inline Policy に以下を設定する。(※もう少し権限は絞れるはず)

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "codedeploy:*"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:Get*",
                "s3:List*"
            ],
            "Resource": [
                "arn:aws:s3:::*/*"
            ]
        }
    ]
}

Deploy グループにデプロイ用ユーザーを追加する

f:id:inokara:20150715170751p:plain

  • deploy グループにユーザーを追加する。今回は ubuntu01 と ubuntu02 ユーザーを作成する
  • 作成したユーザーの credential 情報を控えておく(後ほど CodeDeploy-Agent をインストールする際に利用する)

サービスロールを作成する

docs.aws.amazon.com

上記を参考にサービスロールを作成する。


オンプレサーバーの準備

今回の構成

以下のようにオンプレサーバーを Docker コンテナで用意した。

f:id:inokara:20150715214429p:plain

オンプレサーバーを登録する

$ aws deploy register --instance-name ubuntu01 --iam-user-arn arn:aws:iam::1234567890123:user/ubuntu01 --tags Key=deploy,Value=true --region us-east-1
$ aws deploy register --instance-name ubuntu02 --iam-user-arn arn:aws:iam::1234567890123:user/ubuntu02 --tags Key=deploy,Value=true --region us-east-1

それぞれ以下のように出力される。

Registering the on-premises instance... DONE
Adding tags to the on-premises instance... DONE
Copy the on-premises configuration file named codedeploy.onpremises.yml to the on-premises instance, and run the following command on the on-premises instance to install and configure the AWS CodeDeploy Agent:
aws deploy install --config-file codedeploy.onpremises.yml

CodeDeploy-Agent をインストールする

先ほどユーザーを作成した際に控えておいた各ユーザーの credential 情報を利用して codedeploy.onpremises.yml ファイルを作成する。

---
aws_access_key_id: AKxxxxxxxxxxxxxxxxx
aws_secret_access_key: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
iam_user_arn: arn:aws:iam::1234567890123:user/deploy
region: us-east-1

作成したら以下を実行してインストールを行う。

$ sudo aws deploy install --override-config --config-file /path/to/codedeploy.onpremises.yml --region us-east-1

インストールが完了したら ps コマンドを利用して CodeDeploy-Agent が起動していることを確認する。

$ ps aux | grep codedeploy
root      2895  0.0  0.8  92124 18352 pts/0    Sl   06:14   0:00 codedeploy-agent: master 2895
root      2899  0.0  1.6 313868 33792 pts/0    Sl   06:14   0:00 codedeploy-agent: InstanceAgent::Plugins::CodeDeployPlugin::CommandPoller of master 2895

デプロイしてみる

アプリケーションを作成

$ aws deploy create-application --application-name MyApp --region us-east-1

以下のように出力される。

{
    "applicationId": "08b751f5-f0ee-40cc-b34f-6c17195102e8"
}

ソースコードを push

今回は S3 バケットからソースコードを配信するので事前にバケット(今回は inokappa-codedeploy というバケットを事前に作成しておく)を作成しておく。

以下のとおり appspec.yml を用意する。

version: 0.0
os: linux
files:
  - source: /
    destination: /opt/app/
hooks:
  BeforeInstall:
    - location: scripts/cleanup.sh
      timeout: 300
      runas: root
  AfterInstall:
    - location: scripts/install.sh
      timeout: 300
      runas: root
  ApplicationStart:
    - location: scripts/start.sh
      timeout: 300
      runas: root

更に scripts ディレクトリを作成して以下のとおりシェルスクリプトも作成しておく。最終的には以下のようなファイルとディレクトリ構成にする。

$ tree
.
|-- appspec.yml
`-- scripts
    |-- cleanup.sh
    |-- install.sh
    `-- start.sh

1 directory, 4 files

以下のように push する。

$ aws deploy push --application-name MyApp --s3-location s3://inokappa-codedeploy/MyApp.zip --source ./ --region us-east-1

以下のように出力される。

To deploy with this revision, run:
aws deploy create-deployment --application-name MyApp --s3-location bucket=inokappa-codedeploy,key=MyApp.zip,bundleType=zip,eTag="7b5af5dde7112f549dc0f9eb1070d363",version=_pWqu7dxkBMoupVOltq3DN4XId4FJV53 --deployment-group-name <deployment-group-name> --deployment-config-name <deployment-config-name> --description <description>

上記の出力は控えておく。

Deployment Group の定義

Deploy 先の EC2 インスタンス、オンプレミス環境の定義を行う。

$ aws deploy create-deployment-group --application-name MyApp --deployment-config-name CodeDeployDefault.OneAtATime --deployment-group-name MyApp_DG --on-premises-instance-tag-filters Key=deploy,Value=true,Type=KEY_AND_VALUE --service-role-arn arn:aws:iam::1234567890123:role/CodeDeployDemo --region us-east-1

以下のように出力される。

{
    "deploymentGroupId": "a91fa9d7-9230-4904-aa40-7b6ce2514cde"
}

Deploy の定義

デプロイを定義する。先ほどソースコードaws deploy push した際に出力された etagversion--s3-location に定義、合わせて Deployment Group も定義する。

$ aws deploy create-deployment --application-name MyApp --s3-location bucket=inokappa-codedeploy,key=MyApp.zip,bundleType=zip,eTag="63c4db89f7858854650c973c9660f66c",version=LC3zod9aX5PCnLLsvL14mHY6z87PUMiz --deployment-group-name MyApp_DG --deployment-config-name CodeDeployDefault.OneAtATime --description "Demo Deploy" --region us-east-1

以下のように出力される。

{
    "deploymentId": "d-xxxxxxxxx"
}

尚、--deployment-config-name には以下のような種類がデフォルトで利用可能となっており、別途、定義することも可能となっている。

パラメータ ざっくり説明
CodeDeployDefault.OneAtATime Deploy 対象 1 台ずつに対して Deploy を行う
CodeDeployDefault.AllAtOnce 全ての Deploy 対象に対して一度に Deploy を行う
CodeDeployDefault.HalfAtATime Deploy 対象の半分にまず Deploy を行う

Deployment configuration については以下の Deployment Components の図が解りやすい。

docs.aws.amazon.com

Deploy の結果を確認する

$ aws deploy get-deployment --deployment-id d-xxxxxxxxx --region us-east-1
{
    "deploymentInfo": {
        "applicationName": "MyApp",
        "status": "Succeeded",
        "deploymentOverview": {
            "Failed": 0,
            "InProgress": 0,
            "Skipped": 0,
            "Succeeded": 2,
            "Pending": 0
        },
        "description": "Demo Deploy",
        "deploymentConfigName": "CodeDeployDefault.OneAtATime",
        "creator": "user",
        "deploymentId": "d-xxxxxxxxx",
        "ignoreApplicationStopFailures": false,
        "deploymentGroupName": "MyApp_DG",
        "createTime": 1436944123.497,
        "completeTime": 1436944189.898,
        "revision": {
            "revisionType": "S3",
            "s3Location": {
                "bundleType": "zip",
                "version": "LC3zod9aX5PCnLLsvL14mHY6z87PUMiz",
                "bucket": "inokappa-codedeploy",
                "key": "MyApp.zip",
                "eTag": "63c4db89f7858854650c973c9660f66c"
            }
        }
    }
}

ファイルが展開されていることを確認する。

$ docker exec ubuntu01 ls /opt/app
appspec.yml
scripts
$ docker exec ubuntu02 ls /opt/app
appspec.yml
scripts

一応、デプロイ完了。


ということで

CodeDeploy をオンプレミスサーバーで試してみた。Deploy の度に課金されるようなのでじゃんじゃんばりばり Deploy するような場合にはちょっとつらい(早急に EC2 運用に切り替えた方が良いかも)が、オンプレミス環境から AWS への移行期間に一時的な並行運用期間が発生する場合には便利かもしれない。

で、検証していて気になったのが s3 にソースコードを push したら自動でデプロイする仕組みって提供されていないのかな...と思っていたら CodePipeline で出来そうなので次回試してみたいと思う。