ISUCON公式AMIを使ってAWS上にISUCON環境をTerraformで構築レシピ


# はじめに

ISUCONの練習は公式GitHubのドキュメントにならってローカル環境でひとまず始めることはできますが、本番のように複数台IaaSな環境で練習したい！

AWS上に複数台EC2があるISUCON環境をVPC配下から作れるようなシンプルなTerraform構築ができたので記事にしました。

terraformを実行すると以下のような感じで新規作成されたVPC配下にISUCON環境を持ったEC2が複数台立ち上がります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91562/d419db42-dddc-83a9-63b5-f444454ebf0c.png)

公開鍵の配置やAMI指定など実行者依存のパラメータ的部分があるので複雑になってしまっています。あくまでも参考程度にとらえてもらえればと思います。


# 免責事項

下記の内容をご理解していただいた上で記事内容をご参考ください。

* 本記事にあるコマンドを実行しAWSリソースが作成されることによりAWS利用料金が発生します。その料金に関して責任を負うことができません。
* 本記事のterraform実行では既存AWSリソースに対する影響が無いように考慮していますが、影響が発生することも起こりえます。その場合、その責任を負うことはできません。
* 本記事で構築されるAWSリソースにおいてセキュリティ面で万全ではありません。不測のセキュリティ攻撃等を受けた場合の被害についてもその責任を負うことはできません。

# 環境構築の流れ概要

環境構築の流れの概要として以下のステップになります。

* Step1: Ansible×Packerを利用しISUCON環境が入ったAMIをAWSに作成する ← 最後に記載する
* Step2: 作成したAMIを指定したEC2とVPCを含んだ必要なAWSリソースをTerraformで構築する

以下の記事を参考にさせてもらいました。

https://qiita.com/kanagi/items/6af87a3a59e70e7e06db

Step1に関して、以下のISUCON公式で発信している、[matsuu](https://twitter.com/matsuu)さんが作成されたAMIを利用することができます。

そのため、Step1は既に作成されているという前提でStep2の詳細を記載します。それによりISUCON環境としてはシンプルなものが完成です。

本記事の最後に、AMIをカスタマイズする場合の方法を記述します。

https://twitter.com/isucon_official/status/1387939691094155265

# TerraformでAWS環境を構築する (Step2)

以下のレポジトリを作成しました。参考にするなり、forkするなり、コピペするなりしてもらえればと思います。

https://github.com/momotaro98/isucon-aws-terraform

## 構築インフラパラメータを設定する

パラメータ設定のためには`terraform.tfvars.json`ファイルを作成し設定する必要があります。

以下は例になります。それぞれの項目の意味を記載します。

```json:terraform.tfvars.json
{
  "standalone_ami_owner": "839726181030",
  "standalone_ami_name": "isucon10-qualify",
  "access_cidr_blocks": "xxx.xx.xx.xx/32",
  "vpc_net_mask": "10.2.0.0",
  "ec2_members": {
    "0": "isucon-01",
    "1": "isucon-02",
    "2": "isucon-03",
    "3": "isucon-bench"
  },
  "ec2_instance_type": "t3.medium",
  "ec2_volume_size": 20
}
```

#### `standalone_ami_owner`

利用するAMIの所有者のAWSアカウントIDです。デフォルト値はmatsuuさんのAWSアカウントID(839726181030)です。

#### `standalone_ami_name`

AMI名を指定します。ここでは、どのISUCON環境にするかという意味になります。

`isucon10-qualify`ならばISUCON10予選のAMIです。

実際には`isucon10-qualify-20210429011055`というタイムスタンプ付きの名前ですが、terraformにて`isucon10-qualify`を指定した場合は最新に作成された`isucon10-qualify`から始まるAMIを取得するようにしています。

matsuuさんが公開しているAMI名は以下のリンクで確認できます。

* GitHub上: https://github.com/matsuu/aws-isucon#ami
* AWSコンソール上: https://ap-northeast-1.console.aws.amazon.com/ec2/home?region=ap-northeast-1#Images:visibility=public-images;ownerAlias=839726181030;sort=name

また、`standalone_ami_owner`と`standalone_ami_name`には自身で作成したAMIも指定可能です。

#### `access_cidr_blocks`

AWS環境EC2へのSSHとHTTP通信用セキュリティグループのInboundに設定するグローバルIPアドレスです。

これは自分のグローバルIPのみからのアクセスになるように制限するためのものです。デフォルトでは`0.0.0.0/0`であり、どの環境からもネットワーク自体は22と80ポートが空くことになります。

また、指定のグローバルIPはカンマ区切りで複数指定可能で、別のチームメンバーの環境からもアクセスできるようにすることができます。

#### `vpc_net_mask`

Terraformが作成するVPCのCIDRを指定できます。デフォルト値は`10.1.0.0/16`です。

#### `ec2_members`

立ち上げるEC2の台数とそれぞれの名前を指定することができます。デフォルトでは4台立ち上がります。

#### `ec2_instance_type`

立ち上げるEC2のインスタンスタイプです。`ec2_members`にて複数台EC2を立ち上げた場合すべて同じインスタンスタイプになります。デフォルト値は`t2.small`です。

#### `ec2_volume_size`

立ち上げるEC2のEBSのサイズです。`ec2_members`にて複数台EC2を立ち上げた場合すべて同じ値になります。デフォルト値は`20`です。

## 現時点(2021-08-17)(version v1.1.0)での構築されるリソースの状態

* 新規にVPCが作成され、そのVPC配下に以下のリソースが作成されます。
  * サブネット
  * インターネットゲートウェイ
  * セキュリティグループ
  * など
  * 詳細はterraformの[modules郡](https://github.com/momotaro98/isucon-aws-terraform/tree/main/modules)を確認していただければと思います。
* EC2のスペック
  * Instance Type: `t2.micro`
  * Block size: 20GB
* Route53を使ったDNS設定はしていません。SSH, HTTPアクセスはEC2のパブリックIPかDNSを見る必要があります。
* HTTPS対応はしていません。
* パプリックサブネット上にすべてのEC2を立てます。
* 作成するEC2にアタッチするセキュリティグループは以下の設定になっています。
  * 22,80ポートのみ: 指定のIP(`access_cidr_blocks`)からのリクエストを受け付ける。指定しない場合は`0.0.0.0/0`(全許可)になる。
  * EC2間(セキュリティ間)はすべてのポートを許可。
* EC2へのSSH用の鍵を手元に用意し公開鍵は指定の場所に`isucon_id_rsa.pub`という名前で置く必要があります。詳細は後述します。

## 構築Step

### terraformレポジトリを取得

```
git clone git@github.com:momotaro98/isucon-aws-terraform.git
```

### 鍵設定

EC2へのSSH用鍵を生成し公開鍵を置く

```
ssh-keygen -t rsa -b 4096 -C "isucon key" -f isucon_id_rsa
```

公開鍵を`isucon_id_rsa.pub`の名前で以下の場所に置く。

```
modules/credential/isucon_id_rsa.pub
```

### `terraform.tfvars.json`ファイルを作成しパラメータ設定する

上述を参照し`terraform.tfvars.json`ファイルを作成しパラメータ設定する。

### terraformで構築&削除

terraformのコマンドで構築します。

初回のみ

```
terraform init
```

初回以降、起動コマンド

```
terraform apply
```

ISUCON環境で練習が終わったら削除する。

```
terraform destroy
```

### SSH ログイン

以下の設定で構築されたEC2へSSHログインできます。

```~/.ssh/config
Host isucon-practice-ec2
  HostName your_EC2_public_name
  Port 22
  User ubuntu
  IdentityFile ~/.ssh/isucon_id_rsa
  IdentitiesOnly yes
  RequestTTY yes
  RemoteCommand sudo su - isucon
```

```terminal
$ ssh isucon-practice-ec2
(ログイン後)
isucon@ip-10-2-0-25:~$ ls
bench  env.sh  go  local  webapp
```

# Ansible×PackerでAMIをカスタマイズする (Step1)

matsuuさんのISUCON用Ansibleファイルがまとまっているのが以下のレポジトリです。

https://github.com/matsuu/ansible-isucon

レポジトリをforkするなり参考にしたりできます。

自作したAnsibleファイルを参照する形でPackerでAWS ProviderによりEC2でBuildすることで自身のAMIを作成することができます。

matsuuさんのPackerファイルは以下レポジトリにあります。以下はISUCON9予選のものです。

https://github.com/matsuu/aws-isucon/tree/main/isucon9-qualify

`packer build .`のようにすることでビルドが走ります。

# その他参考にさせていただいたプロジェクト

https://github.com/recruit-tech/r-isucon