CodeDeployを雰囲気だけ理解する。

こちらはCodeDeploy触ってみようとtutorialをやったけど成功しなかったつまらない話です。

ただCodeDeployの流れはなんとなく掴めたので備忘録としてまとめておく。

## 追記 12/19

成功しました。

* [超ミニマムなチュートリアルを通してCodeDeployを理解する。](https://qiita.com/Kept1994/items/fa3516fa8fe326b4ac3b)
* [超ミニマムなチュートリアルを通してCodeDeployを理解する2(AutoScaling編)](https://qiita.com/Kept1994/items/8abeeb8fa0980f95ab56)

## たぶんやってることはこんなこと

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406130/c8e1d74f-7f60-fccf-24b6-1b6ee5d3b5f0.png)


## EC2にAgentを導入する。

デフォルトではCodeDeployから操作できないためAgentを追加する必要がある。
（オンプレミスのサーバーも然り。Agentを入れればデプロイ可能となる。）

インスタンス作成画面の高度な詳細→ユーザーデータではインスタンスの起動時に実行する内容を記述できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/406130/a9778a37-686e-0755-c685-8a4e06623d74.png)

ここへ、CodeDeployを利用するためのAgentをインストールする処理を書く。

```sh
#!/bin/bash
yum -y update
yum install -y ruby
cd /home/ec2-user
curl -O https://バケット名.s3.amazonaws.com/latest/install
chmod +x ./install
./install auto
```

バケット名はCodeDeployリソースキットファイルが含まれている公式のバケットのものを指し、[リージョン別リソースキットバケット名](https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/resource-kit.html#resource-kit-bucket-names)から適切なものを選択して書く。

__コメント__

なお、Amazon Linux2では上記では成功したが、1世代前のAmazon Linuxでは最後のコマンド実行時にエラーした。（2019/11/18時点）

## appspec.ymlを作成する。

これは仕様書みたいなもの（Application Specification file）。

書き方は以下の規定がある。
[CodeDeploy AppSpec File リファレンス](https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/reference-appspec-file.html)

```yaml
version: 0.0
os: linux
files:
  - source: /
    destination: /var/www/html/WordPress
hooks:
  BeforeInstall:
    - location: scripts/install_dependencies.sh
      timeout: 300
      runas: root
  AfterInstall:
    - location: scripts/change_permissions.sh
      timeout: 300
      runas: root
  ApplicationStart:
    - location: scripts/start_server.sh
    - location: scripts/create_test_db.sh
      timeout: 300
      runas: root
  ApplicationStop:
    - location: scripts/stop_server.sh
      timeout: 300
      runas: root
```
`source`はソースファイルの場所を指定し、`destination`はzipで上げるアプリケーションの展開先を指定する。
`hooks`には、イベント名とそのイベントで実行するファイル（場所）と実行時間、ユーザーを指定する。各イベントのタイミングで指定したスクリプトが実行される。
なお、ApplicationStopフックは2回目のデプロイ以降で呼ばれる（1回目はそもそもインスタンスがないから）。

参考）[AppSpec の「hooks」セクション](https://docs.aws.amazon.com/ja_jp/codedeploy/latest/userguide/reference-appspec-file-structure-hooks.html)

## s3へアップロードし、CodeDeployと紐付ける。

デプロイするzipファイルを置くバケットを作成しておく。

### バケットポリシー

バケットポリシーでPutObject可能なように設定すること。

なお、ポリシーの見方は[アクセスポリシー言語の概要](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/dev/access-policy-language-overview.html)参照。

```json
{
    "Version": "2012-10-17",
    "Id": "ExamplePolicy01",
    "Statement": [
        {
            "Sid": "ExampleStatement01",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam:000011112222:user/許可するユーザー名"
            },
            "Action": [
                "s3:GetObject",
                "s3:GetBucketLocation",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::examplebucket/*",
                "arn:aws:s3:::examplebucket"
            ]
        }
    ]
}
```

`Effect`は許可するのか拒否するのか。競合する場合、一般に`設定なし＜許可＜拒否`の順で優先される。
`Principal`は誰が以下のアクションを実行するのか。アクセス元。rootユーザの指定方法は`"AWS": "arn:aws:iam:000011112222:root"`。
`Action`は対象の操作内容。アクション。
`Resource`はどのAWSリソースに対するアクションか。アクセス先。

### CodeDeployアプリケーションの作成と紐付け

```sh
$ aws deploy create-application --application-name アプリケーション名
```

```sh
$ aws deploy push \
  --application-name WordPress_App \
  --s3-location s3://codedeploydemobucket/WordPressApp.zip \
  --ignore-hidden-files
```

__コメント__

後者のコマンドはs3のポリシーとかIAMをいろいろやっても`Access Denied`だった（謎）。
ただ、裏では[こんなこと](https://dev.classmethod.jp/cloud/aws/codedeploy-push-behind-the-scenes/)をしているようなので、上記のコマンドをバラして一個一個実行していったところ、S3へアップできて紐付けまで成功した。

```sh
$ zip -r WordPressApp.zip .
$ aws s3api put-object --bucket YOUR-BUCKET --key WordPressApp.zip --body WordPressApp.zip
$ aws deploy register-application-revision \
  --application-name WordPress_App \
  --s3-location bucket=YOUR-BUCKET,key=WordPressApp.zip,bundleType=zip
```

## デプロイ

デプロイグループを作成する。
EC2にアクセスするがあるため、AWSCodeDeployRoleポリシーをあてたサービスロールを付与する。

```sh
$ aws deploy create-deployment-group \
  --application-name WordPress_App \
  --deployment-group-name WordPress_DepGroup \
  --deployment-config-name CodeDeployDefault.OneAtATime \
  --ec2-tag-filters Key=Name,Value=対象のEC2名,Type=KEY_AND_VALUE \
  --service-role-arn serviceRoleARN
```

デプロイする。

```sh
$ aws deploy create-deployment \
  --application-name WordPress_App \
  --deployment-config-name CodeDeployDefault.OneAtATime \
  --deployment-group-name WordPress_DepGroup \
  --s3-location bucket=YOUR-BUCKET,bundleType=zip,key=WordPressApp.zip
```

なんどもs3の参照先を設定する理由がよくわからないが、一応これでデプロイが走る。

__コメント__

tutorialで進めるとデプロイ成功までは行けなかった。
そもそも`yum install`ができない問題や、その先のhttpd、mysqldを起動できないといった問題が起きた。
気が向いたら調べてみる。

### CodeDeployの用語整理

|用語|意味|
|:---:|:---:|
|アプリケーション|デプロイしようとしているリビジョンのこと。今回はzipでS3に置いているので、どこに置いているか、形式は何かといったことを紐付けたデータがアプリケーション。|
|デプロイグループ|デプロイ先はどこか、一度にデプロイするのか、ロールなどの設定をしたものデプロイの型みたいなもの。|
|デプロイ|1回1回のデプロイのこと。成功/失敗のステータスが出る。|