CDKでAWS 環境の作成 EC2編

## 概要

CDKを使ってAWS環境を作成するときの方法についてまとめていこうと思います。
今回は[前回](https://qiita.com/dmikita/items/f13771b816c6aa019f1e)作成したCDKの定義にEC2の定義を追加して[こちら](https://qiita.com/mongamae-nioh/items/7525be957f4e5e10d403)を参照しAdvendCalendarを公開してみました。


## 準備

* 準備部分は[前回](https://qiita.com/dmikita/items/f13771b816c6aa019f1e)等を参照してください。

* `VPC`を作り直す場合はパラメータストアから値を取得しなおすため`cdk.context.json`を一度削除してください。

## コンパイルの準備
* ライブラリインストール後にプロジェクトを作成したディレクトリに移動して以下のコマンドを実行します。windowsの場合はライブラリのインストール時には停止する必要があるので注意を
    * `npm run watch`


## 各モジュールの説明
* モジュールは[github](https://github.com/dmikita-sss/cdk-sample)で公開しています。今回追加した部分のみ追記します。
* /vpc
    * `yum update` を行うためS3へアクセスするためのエンドポイントを追加しています。
* /rds-s3
    * EC2の設定を追加しています。
    * `./bin/rds-s3.ts` の方で以下のように設定することで複数のソースの定義を使えるようにしています。今回はEC2の要素を追加しています。

        ```typescript
            import { RdsS3Stack } from '../lib/rds-s3-stack';
            import { CdkRdsStack } from '../lib/cdk-rds-stack';
            import { CdkS3Stack } from '../lib/cdk-s3-stack';
            import { CdkEc2Stack } from '../lib/cdk-ec2-stack';

            import { env } from 'process';

            const app = new cdk.App();

            new RdsS3Stack(app,'RdsS3Stack',{
                env: {
                    region: 'ap-northeast-1',
                    account: env.AWS_ACCOUNT,
            }});
            new CdkRdsStack(app,'CdkRdsStack',{
                env: {
                    region: 'ap-northeast-1',
                    account: env.AWS_ACCOUNT,
            }});
            new CdkS3Stack(app,'CdkS3Stack',{
                env: {
                    region: 'ap-northeast-1',
                    account: env.AWS_ACCOUNT,
            }});

            new CdkEc2Stack(app,'CdkEc2Stack',{
                env: {
                    region: 'ap-northeast-1',
                    account: env.AWS_ACCOUNT,
            }});
        ```
    * デプロイするときはStack名を指定して実施します。ワイルドカードの指定も可能です。
        * `cdk deploy * ` または `cdk deploy CdkRdsStack` の用に指定します。
        * 今回はEC2インスタンスを作成するときにキーペアを登録するためコマンドは次のようになります XXXXXXX の部分はキーペア名を設定します。 
            * `cdk deploy CdkEc2Stack -c key_pair=XXXXXXX` 

### CDKの定義

* VPC
    * `yum update` を行うためS3へアクセスするためのエンドポイントを追加しています。

* EC2
    * 該当部分は以下のようになっています。

    ```typescript
  let ec2Instance = new ec2.CfnInstance(this, 'ec2-AdventCalendar', {
    imageId:  'ami-00f58a07aaa3179b8',
    // 新規でインスタンスを作成する場合は以下を使用
    //imageId : new ec2.AmazonLinuxImage().getImage(this).imageId,
    instanceType: new ec2.InstanceType('t3.micro').toString(),
    networkInterfaces: [{
      associatePublicIpAddress: true,
      deviceIndex: '0',
      groupSet: [securityGroup.securityGroupId],
      subnetId: targetVpc.publicSubnets[0].subnetId
    }],
    keyName: this.node.tryGetContext('key_pair'),
  });

    ```

    * 事前にdockerのインストールなどを済ませたamiを用意しているためimage-IDを設定しています。
        * `imageId:  'ami-00f58a07aaa3179b8',`
    * amiを使わない場合は次のように設定します。
        * `imageId : new ec2.AmazonLinuxImage().getImage(this).imageId,`
    * インスタンスタイプは無料枠が有効なら `t2.micro` がよいですが無料枠が終わっている場合は `t3.micro` の方が安いようです。
    * 今回はキーペアを登録して接続するようにしていますが、セッションマネージャーを利用することも検討してもよさそうです。
    * SSHで接続するための設定はコンソールから別途設定しています。

## AdventCalendarの作成
### dockerのインストール
* 作成したEC2インスタンスにDockerのインストール手順です。
* 事前に以下の状態を確認します。
    * アウトバウントの許可 (443,80のポートのみでよいかも)
    * S3エンドポイントの追加
* teratermなどでインスタンスにログインし以下を実行します。
    * `sudo yum update -y`
    * `sudo yum install -y docker`
    * `sudo usermod -a -G docker ec2-user`

### コンテナの設定
* コンテナのダウンロードを行います。
    * `docker run -it --name コンテナ名 -p 8083:3000 mongamaenioh/radvent:latest /bin/bash`
    * ポート番号はCDKの定義でアウトバウンドに指定しているポートを指定します。ポートを変えるときはそちらに合わせてください。
    * このコマンドでコンテナを起動するとコンテナ内に入った状態となるので抜けたいときは CTRLキーを押したまま`P`と`Q`キーを押します。

* advent calendar の設定を行います。
    * `cd /home/radvent`
    * `export SECRET_KEY_BASE=`bundle exec rake secret`
    * `vi /home/radvent/config/initializers/constants.rb`
        * こちらのコマンドで公開する日付を修正します。
    * AMIいったんコンテナを作って翌年も使用するならこのタイミングでAMIを取得しておきましょう。

### AdventCalendarの起動
* 起動させるときは以下のコマンドを実行します。
    * `nohup bundle exec rails server -e production &`