【15分でできる】EC2(Web+DB)ネットワーク構築 〜画面ポチポチ〜


最近EC2を使うケースは少ないですが、まずは基本としてオーソドックスなEC2+ネットワーク構築の流れをまとめました。

VPCを作成する

IPv4 CIDERブロックを「10.0.0.0/16」にしてVPCを作成します。

DNSホスト名を利用するのでVPCのDNSホスト名をONにします。

パブリックサブネットを作成する

作成したVPCを選択し、IPv4 CIDERブロックを「10.0.1.0/24」にして作成します。

プライベートサブネットを作成する

作成したVPCを選択し、IPv4 CIDERブロックを「10.0.2.0/24」にして作成します。

インターネットゲートウェイを作成する

作成したインターネットゲートウェイをVPCにアタッチします。

VPCにパブリックルートテーブルを作成する

作成したVPCにパブリックルートテーブルを作成します。

作成したパブリックルートテーブルに「サブネットの関連付け」からパブリックサブネットを関連付けます。

パブリックサブネットに関連づけたルートテーブルのルートを編集し、送信先を「0.0.0.0/0」としターゲットにインターネットゲートウェイを設定します。

WebサーバーとしてEC2を作成する

作成した VPCを設定とパブリックサブネットを設定します。

IPはパブリックサブネット内の「10.0.1.10」を割り当てます。

「セキュリティグループ」をソース「カスタム」で「0.0.0.0/0」にして作成します。EC2インスタンスが作成できたらElasticIPを関連付けます。

鍵を取得してEC2にSSHアクセスする

# 例
$ chmod 400 ~/.ssh/my-key.pem
$ ssh -i ~/.ssh/my-key.pem ec2-user@ec2-xx-xx-xx-xx.ap-northeast-1.compute.amazonaws.com

Nginxをインストールする

# インストール
$ sudo yum -y install nginx
# サービス起動
$ sudo service nginx start
# 自動起動ON
$ sudo chkconfig nginx on

セキュリティグループ(ファイアウォール)を設定する

「インバウンドルール」にHTTP(80ポート)で「0.0.0.0/0」を設定しWebからのアクセスを許可します。

「パブリック DNS」でブラウザからアクセスができることを確認します。

DBサーバーとしてEC2を作成する

作成したVPCとプライベートサブネットを設定します。パブリックIPは不要なので自動割り当てパブリックIPを無効化します。

内部IPをプライベートサブネット内の「10.0.2.10」に設定します。

プライベートサブネットからしかアクセスしないので「セキュリティグループ」をソースカスタムで「SSH」と「MySQL/Aurora」にパブリックサブネット「10.0.1.0/24」を指定します。

Webサーバーに秘密鍵(my-key.pem)を送り、WebサーバーからDBサーバーにアクセス可能にします。

# 秘密鍵をWebサーバーに送る
$ scp -i ~/.ssh/my-key.pem ~/.ssh/my-key.pem ec2-user@ec2-18-178-132-45.ap-northeast-1.compute.amazonaws.com:~/.ssh/
# Webサーバーアクセス
$ ssh -i ~/.ssh/my-key.pem ec2-user@ec2-18-178-132-45.ap-northeast-1.compute.amazonaws.com
# 権限変更
$ chmod 400 ~/.ssh/my-key.pem
# DBサーバーアクセス
$ ssh -i ~/.ssh/my-key.pem ec2-user@10.0.2.10

パブリックゲートウェイにNATゲートウェイを作成する

DBサーバーにMySQLをインストールするためにパブリックサブネットのNATゲートウェイを通してインターネットへ接続可能にします。

メインのルートテーブルに送信先「0.0.0.0/0」としてNATゲートウェイを設定します。

MySQLをインストールする

# インストール
$ sudo yum -y install mysql-server
# MySQL起動
$ sudo service mysqld start
# 自動起動ON
$ sudo chkconfig mysqld on

MySQLをセットアップする

# ログイン
> mysqladmin -u root password
> mysql -uroot -p
# Schema作成
> create database example default character set utf8 collate utf8_general_ci;
# ユーザー作成と権限付与
> grant all on example.* to user@"%" identified by 'password';
flush privileges;

WebサーバーにMySQLクライアントをインストールする

WebサーバーへMySQLクライアントをインストールしDBサーバーのMySQLへサクセスできることを確認します。

# MySQLクライアントインストール
sudo yum -y install mysql
# DBサーバーのMySQLへアクセス確認
mysql -u user -p example -h 10.0.2.10

セットアップができたら必要に応じてNATゲートウェイは削除します。(料金がかかるため)

Nginxを設定する

「/etc/nginx/conf.d/nginx.conf」を編集し「root」をコメントアウトしlocationに「proxy_pass http://127.0.0.1:9000;」を追加します。

server {
listen       80 default_server;
listen       [::]:80 default_server;
server_name  localhost;
#root         /usr/share/nginx/html;
# Load configuration files for the default server block.
include /etc/nginx/default.d/*.conf;
location / {
proxy_pass http://127.0.0.1:9000;
}    server {
# --- 省略 ---

nginxを再起動します。

$ sudo service nginx restart

アプリケーションをセットアップします。

ここではGoのサンプルアプリケーションを実行します。起動したらusersテーブルを作成し、アクセスしたらusersテーブルにレコードをinsertします。

Goをインストールします。

$ sudo yum -y install go

サンプルプログラムをWebサーバーへ配置します。

package main
import (
"database/sql"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
_ "github.com/go-sql-driver/mysql"
"github.com/joho/godotenv"
)
type User struct {
FirstName string `json:"firstName"`
LastName  string `json:"lastName"`
}
var db *sql.DB
func main() {
err := godotenv.Load()
if err != nil {
log.Fatal(err)
}
db = Conn()
defer db.Close()
_, err = db.Exec("CREATE TABLE IF NOT EXISTS users(id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY, firstname VARCHAR(255) NOT NULL, lastname VARCHAR(255) NOT NULL)")
if err != nil {
log.Fatal(err)
}
http.HandleFunc("/users", users)
err = http.ListenAndServe(os.Getenv("LISTEN_PORT"), nil)
if err != nil {
log.Fatal(err)
}
}
func Conn() *sql.DB {
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s:3306)/%s", os.Getenv("MYSQL_USER"), os.Getenv("MYSQL_PASSWORD"), os.Getenv("MYSQL_HOST"), os.Getenv("MYSQL_SCHEMA")))
if err != nil {
log.Fatal(err)
}
return db
}
func users(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Content-Type", "application/json")
user := User{
FirstName: "John",
LastName:  "Doe",
}
var users []User
users = append(users, user)
stmt, err := db.Prepare("INSERT INTO users(firstname, lastname) VALUES(?, ?)")
if err != nil {
log.Print(err)
return
}
_, err = stmt.Exec(user.FirstName, user.LastName)
if err != nil {
log.Print(err)
return
}
json.NewEncoder(w).Encode(users)
}

main.goと同一ディレクトリに.envファイルを作成し環境変数に値を設定します。

MYSQL_HOST=10.0.2.10
MYSQL_USER=user
MYSQL_PASSWORD=password
MYSQL_SCHEMA=example
LISTEN_PORT=:9000

動作確認をする

パブリックDNSにアクセスしてJSONが返ってくることを確認します。

DBレコードを確認する

WebサーバーからDBサーバーへアクセスしusersテーブルにレコードが入っていることを確認します。

$ mysql -u user -p example -h 10.0.2.10
mysql> select * from users;
+----+-----------+----------+
| id | firstname | lastname |
+----+-----------+----------+
|  1 | John      | Doe      |
+----+-----------+----------+
1 row in set (0.00 sec)

 これで一通りのセットアップが完了しました。次からはこの環境を下記のツールでセットアップしてみます。

  • CloudFormation
  • CDK
  • Terraform

関連記事