コマンド1発でAWSに極小構成のWebサーバー(SSL/TLS対応済み)を構築したい

「とりあえず動けばいい。お金払いたくない。ドメインとかSSL証明書設定めんどい。ロードバランサーとかいらん。」という忙しくてケチな人向け。

# なにする
SSL/TLS対応済みのWebサーバーの極小の構成をささっと作ります。CloudFormationを使います。

大体の流れをつかめばDockerなどとの組み合わせで、コマンド1発でWebサーバーとそのインフラを構築、削除できます。

今回書いたコード等:
https://github.com/ponsea/aws-minimal-webserver


## インフラ仕様
- サーバーはEC2インスタンス1個のみ
- WebサーバーのURLのホスト名は適当になるがHTTPSで接続できる。(自前でドメインや証明書の用意をする必要無し)
    - このようなURLになる => `https://xxxxxxx.execute-api.ap-northeast-1.amazonaws.com/`
- サーバーにSSHできる
- 課金は 任意のEC2インスタンスの料金 + Route53のホストゾーン(月50円) + CloudMapのNamespace (月10円) ほど
    - 料金面は適宜、公式ページでご確認ください

# インフラ構成
最終的なインフラ構成です。
![AWS Minimal WebServer](https://user-images.githubusercontent.com/19386206/92299841-074cee00-ef91-11ea-99c8-439843315198.png)

API GatewayのVPCリンクと、プライベート統合機能を用いてリクエストをEC2にバイパスします。
Cloud MapはApiGatewayがEC2インスタンスのIPアドレス/ポート番号を解決するために用います。

# 前提
- アカウント登録してAWS CLIをインストール済み
- 前述のインフラ構成を構築する権限がある
- EC2のキーペアを1個作っている

今回はCloudFormationを使います。CloudFormationとは端的に言うと、前述のインフラ構成を定義したファイル(yamlまたはjson形式)を用意して実行すると、そのインフラ構成を実際に構築してくれる優れものです。

以下に今回のCloudFormationのテンプレートファイル(インフラ構成を定義したファイル)があります。

https://github.com/ponsea/aws-minimal-webserver

`template.yaml` がインフラ構成の定義ファイルです。

`template.yaml`の中ではすでに、自動でDockerのhttpdイメージが80番ポートで実行される様に設定されています。(詳細は後述)

```
docker run -d -p 80:80 httpd
```

# コマンド1発でインフラを構築する
`template.yaml`があるディレクトリで以下のコマンドを実行します。すると実際にインフラ構成が構築されます。

```
aws cloudformation create-stack \
  --stack-name minimal-webserver \ 任意のスタック名 (実際に作成されるAWSリソースの総称のようなもの)
  --template-body file://template.yaml \
  --parameters \
      ParameterKey=Ec2InstanceType,ParameterValue=t2.micro \ インスタンスタイプはお好みで(t2.microの部分)
      ParameterKey=SshKeyName,ParameterValue=<YOUR SSH KEY NAME> \ 予め作っておいたEC2のSSHキーペア名を指定
      ParameterKey=SshLocation,ParameterValue=<YOUR SSH LOCATION> SSH元のIPをx.x.x.x/x形式で指定し制限することをお勧めします。省略すれば0.0.0.0/0(制限なし)となります。
```
構築の様子はAWSのCloudFormationのコンソールで確認できます。ステータスが`CREATE_COMPLETE`になれば構築完了です。

構築が完了したあと、EC2インスタンスのパブリックIPとWebサーバーのURL(エンドポイント)を確認します。

```bash
aws cloudformation describe-stacks --stack-name minimal-webserver

{
    "Stacks": [
        {
            ...

            "StackStatus": "CREATE_COMPLETE"

            ...

            "Outputs": [
                { 
                    "OutputKey": "ApiGatewayUrl",
                    ↓ WebサーバーのURL
                    "OutputValue": "https://xxxxxx.execute-api.ap-northeast-1.amazonaws.com/",
                    "Description": "API Gateway endpoint URL for $default stage"
                },
                {
                    "OutputKey": "Ec2InstancePublicIp",
                    ↓ EC2 インスタンスのパブリックIP
                    "OutputValue": "xxx.xxx.xxx.xxx",
                    "Description": "EC2 Instance Public IP"
                }
            ],

            ...
    ]
}
```
`"OutputValue": "https://xxxxxx.execute-api.ap-northeast-1.amazonaws.com/",` のURLにアクセスすれば、Webページが見れます。

現状ではDockerのhttpdイメージの「It works!」というページが表示されるはずです。

SSH接続したい場合

```
ssh -i "/path/to/your-ssh-key.pem" ec2-user@<YOUR EC2 PUBLIC IP>
```
全部まとめて削除したい場合:

```
aws cloudformation delete-stack  --stack-name minimal-webserver
```

# template.yaml 分析
今回事前に用意したtemplate.yamlで定義したEC2インスタンスは、予めDocker, docker-compose, gitをインストールし、Dockerのhttpdイメージを実行するスクリプトを埋め込んでいます。このスクリプトはEC2インスタンスの初回起動時に実行されます。

```yaml
      UserData:
        Fn::Base64: !Sub |
          #!/bin/bash -xe
          # docker, gitインストール
          yum install -y docker git
          # docker-composeインストール
          curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
          chmod +x /usr/local/bin/docker-compose
          systemctl start docker # Dockerデーモン起動
          systemctl enable docker # Dockerデーモン自動起動設定
          usermod -a -G docker ec2-user # dockerコマンドをec2-userで実行できる様に
          docker run -d -p 80:80 httpd # httpdイメージを実行
```
https://github.com/ponsea/aws-minimal-webserver/blob/master/template.yaml#L100

用途に合わせて、ここでDockerのコンテナ構成を定義すれば、すぐにシングルノードの小さいWebサービス建てれそうですね。


CloudFormation便利!

# 転載元
https://ponsea.hatenablog.com/entry/aws-minimal-webserver