v4.2 / 作成日: 2026-06-07 / ALB + WebAPサーバ冗長化(プライベートサブネット)+ RDS PostgreSQL Multi-AZ / AWSマネジメントコンソール操作
| リソース | 名前 | 設定値 |
|---|---|---|
| VPC | handson-vpc | 10.0.0.0/16 |
| パブリックサブネット(ALB-1a) | handson-subnet-public-1a | 10.0.1.0/24 / ap-northeast-1a / ALBのみ配置 |
| パブリックサブネット(ALB-1c) | handson-subnet-public-1c | 10.0.2.0/24 / ap-northeast-1c / ALBのみ配置 |
| プライベートサブネット(WebAP-1a) | handson-subnet-private-webap-1a | 10.0.3.0/24 / ap-northeast-1a |
| プライベートサブネット(WebAP-1c) | handson-subnet-private-webap-1c | 10.0.4.0/24 / ap-northeast-1c |
| プライベートサブネット(DB-1a) | handson-subnet-private-db-1a | 10.0.5.0/24 / ap-northeast-1a |
| プライベートサブネット(DB-1c) | handson-subnet-private-db-1c | 10.0.6.0/24 / ap-northeast-1c |
| Internet Gateway | handson-igw | VPCにアタッチ |
| NAT Gateway | handson-natgw | public-1a に配置 / WebAP EC2のアウトバウンド通信用 |
| ALB | handson-alb | インターネット向け / HTTP:80 |
| ターゲットグループ | handson-tg-webap | HTTP:80 / WebAP EC2 2台 |
| EC2(WebAP-1a) | handson-webap-1a | t2.micro / Nginx + Node.js |
| EC2(WebAP-1c) | handson-webap-1c | t2.micro / Nginx + Node.js |
| RDS | handson-rds | PostgreSQL 16 / db.t3.micro / Multi-AZ |
| セキュリティグループ | sg-alb / sg-webap / sg-rds | 3つ |
| リソース | 概算料金 | 備考 |
|---|---|---|
| EC2 t2.micro × 2台 | 無料枠内 | 新規アカウント12ヶ月以内 |
| ALB × 1台 | 約$0.028/時間 | ハンズオン後すぐ削除 |
| RDS PostgreSQL db.t3.micro Multi-AZ | 約$0.052/時間 | 必ず削除すること |
| NAT Gateway × 1台 | 約$0.062/時間 | WebAP EC2のSSM接続・パッケージ取得に必要。必ず削除すること。 |
| 項目 | 内容 |
|---|---|
| AWSアカウント | AdministratorAccess権限を持つIAMユーザー |
| リージョン | 東京(ap-northeast-1)― コンソール右上で必ず確認 |
| ブラウザ | Chrome / Edge / Firefox(最新版) |
EC2インスタンスへのSession Manager接続に必要なIAMロールを作成します。
| 項目 | 値 |
|---|---|
| エンティティタイプ | AWSのサービス |
| ユースケース | EC2(「EC2」で検索して選択) |
検索欄に AmazonSSMManagedInstanceCore と入力 → チェックを入れる
| 項目 | 値 |
|---|---|
| ロール名 | handson-ec2-ssm-role |
| 項目 | 値 |
|---|---|
| 作成するリソース | VPCのみ |
| 名前タグ | handson-vpc |
| IPv4 CIDR | 10.0.0.0/16 |
| テナンシー | デフォルト |
handson-vpc を選択 → アクション → 「VPCの設定を編集」
| 項目 | 値 |
|---|---|
| DNS ホスト名を有効化 | チェックを入れる(有効化) |
| サブネット名 | AZ | CIDR | 用途 |
|---|---|---|---|
| handson-subnet-public-1a | ap-northeast-1a | 10.0.1.0/24 | ALB-1a |
| handson-subnet-public-1c | ap-northeast-1c | 10.0.2.0/24 | ALB-1c |
| handson-subnet-private-webap-1a | ap-northeast-1a | 10.0.3.0/24 | WebAP-1a |
| handson-subnet-private-webap-1c | ap-northeast-1c | 10.0.4.0/24 | WebAP-1c |
| handson-subnet-private-db-1a | ap-northeast-1a | 10.0.5.0/24 | DB-1a |
| handson-subnet-private-db-1c | ap-northeast-1c | 10.0.6.0/24 | DB-1c |
「新しいサブネットを追加」ボタンで6つをまとめて作成し、サブネットを作成
handson-subnet-public-1a を選択 → アクション → 「サブネットの設定を編集」
| 項目 | 値 |
|---|---|
| パブリック IPv4 アドレスの自動割り当てを有効化 | チェックを入れる |
handson-subnet-public-1c についても同様に設定します。
| 項目 | 値 |
|---|---|
| 名前タグ | handson-igw |
作成後、画面上部のバナーの「VPCにアタッチ」をクリック(または アクション → 「VPCにアタッチ」)
| 項目 | 値 |
|---|---|
| 使用可能な VPC | handson-vpc(プルダウンから選択) |
状態が 「Attached」 になっていることを確認します。
| 項目 | 値 |
|---|---|
| 名前 | handson-natgw |
| サブネット | handson-subnet-public-1a(パブリックサブネットに配置) |
| 接続タイプ | パブリック |
| Elastic IP 割り当て ID | Elastic IP を割り当て をクリックして新規EIPを取得 |
| 項目 | 値 |
|---|---|
| 名前 | handson-rt-public |
| VPC | handson-vpc |
handson-rt-public を選択 → 「ルート」タブ → ルートを編集 → ルートを追加
| 送信先 | ターゲット |
|---|---|
| 0.0.0.0/0 | Internet Gateway → handson-igw |
「サブネットの関連付け」タブ → サブネットの関連付けを編集
以下 2つにチェック → 関連付けを保存
handson-subnet-public-1ahandson-subnet-public-1c新しいルートテーブルを作成します:
| 項目 | 値 |
|---|---|
| 名前 | handson-rt-private-webap |
| VPC | handson-vpc |
handson-rt-private-webap を選択 → 「ルート」タブ → ルートを編集 → ルートを追加
| 送信先 | ターゲット |
|---|---|
| 0.0.0.0/0 | NAT Gateway → handson-natgw |
「サブネットの関連付け」タブ → サブネットの関連付けを編集
以下 2つにチェック → 関連付けを保存
handson-subnet-private-webap-1ahandson-subnet-private-webap-1c| 項目 | 値 |
|---|---|
| セキュリティグループ名 | sg-alb |
| 説明 | ALB security group |
| VPC | handson-vpc |
インバウンドルール:
| タイプ | プロトコル | ポート | ソース | 説明 |
|---|---|---|---|---|
| HTTP | TCP | 80 | 0.0.0.0/0 | インターネットからのHTTP |
| HTTPS | TCP | 443 | 0.0.0.0/0 | インターネットからのHTTPS |
アウトバウンドルール:デフォルト(すべてのトラフィックを許可)のまま
セキュリティグループを作成| 項目 | 値 |
|---|---|
| セキュリティグループ名 | sg-webap |
| 説明 | WebAP server security group |
| VPC | handson-vpc |
インバウンドルール:
| タイプ | プロトコル | ポート | ソース | 説明 |
|---|---|---|---|---|
| HTTP | TCP | 80 | sg-alb のSG ID | ALBからのみ許可(直接アクセス不可) |
| 項目 | 値 |
|---|---|
| セキュリティグループ名 | sg-rds |
| 説明 | RDS PostgreSQL security group |
| VPC | handson-vpc |
インバウンドルール:
| タイプ | プロトコル | ポート | ソース | 説明 |
|---|---|---|---|---|
| PostgreSQL | TCP | 5432 | sg-webap のSG ID | WebAPサーバからのみ許可 |
RDS Multi-AZ配置に必要な、2AZにまたがるサブネットグループを作成します。
| 項目 | 値 |
|---|---|
| 名前 | handson-db-subnet-group |
| 説明 | DB subnet group for Multi-AZ RDS |
| VPC | handson-vpc |
| アベイラビリティーゾーン | ap-northeast-1a と ap-northeast-1c の両方にチェック |
| サブネット | handson-subnet-private-db-1a と handson-subnet-private-db-1c を選択 |
| 項目 | 値 |
|---|---|
| データベース作成方法 | 標準作成 |
| エンジンタイプ | PostgreSQL |
| エンジンバージョン | PostgreSQL 16.x(リストの最新版) |
| 項目 | 値 |
|---|---|
| テンプレート | 開発/テスト |
| デプロイオプション | マルチ AZ DB インスタンス 冗長化のため必ず選択。プライマリ(1a)障害時にスタンバイ(1c)へ自動フェイルオーバーします。 |
| 項目 | 値 |
|---|---|
| DB インスタンス識別子 | handson-rds |
| マスターユーザー名 | admin |
| 認証情報の管理 | セルフマネージド |
| マスターパスワード | AdminPass123! |
| パスワードの確認 | AdminPass123! |
| 項目 | 値 |
|---|---|
| DB インスタンスクラス | バースト可能クラス(t クラスを含む) → db.t3.micro |
| 項目 | 値 |
|---|---|
| ストレージタイプ | 汎用 SSD (gp2) |
| 割り当てられたストレージ | 20 GiB |
| ストレージの自動スケーリング | 無効(チェックを外す)(ハンズオン用) |
| 項目 | 値 |
|---|---|
| コンピューティングリソース | EC2 コンピューティングリソースに接続しない |
| VPC | handson-vpc |
| DB サブネットグループ | handson-db-subnet-group |
| パブリックアクセス | なし(インターネットから直接アクセス不可) |
| VPC セキュリティグループ | 既存の選択 → sg-rds デフォルトのセキュリティグループは削除して sg-rds のみを選択 |
| アベイラビリティーゾーン | ap-northeast-1a(プライマリ) |
「追加設定」セクションをクリックして展開します。
| 項目 | 値 |
|---|---|
| 最初のデータベース名 | handson_db ここを空のままにするとデータベースが作成されません。必ず入力してください。 |
| 自動バックアップを有効化 | チェックを外す(ハンズオン用) |
| 削除保護の有効化 | チェックを外す(削除しやすくするため) |
handson-rds.xxxxxxxxxxxx.ap-northeast-1.rds.amazonaws.com(ポート: 5432)| 項目 | 値 |
|---|---|
| ターゲットタイプ | インスタンス |
| ターゲットグループ名 | handson-tg-webap |
| プロトコル | HTTP |
| ポート | 80 |
| VPC | handson-vpc |
| プロトコルバージョン | HTTP1 |
ヘルスチェック設定:
| 項目 | 値 |
|---|---|
| ヘルスチェックプロトコル | HTTP |
| ヘルスチェックパス | /health |
| 正常のしきい値 | 2 |
| 非正常のしきい値 | 3 |
| 間隔 | 30 秒 |
| 項目 | 値 |
|---|---|
| ロードバランサー名 | handson-alb |
| スキーム | インターネット向け |
| IP アドレスタイプ | IPv4 |
| 項目 | 値 |
|---|---|
| VPC | handson-vpc |
| マッピング(AZ 1) | ap-northeast-1a → handson-subnet-public-1a |
| マッピング(AZ 2) | ap-northeast-1c → handson-subnet-public-1c |
| 項目 | 値 |
|---|---|
| セキュリティグループ | sg-alb(デフォルトのSGは削除して sg-alb のみ選択) |
| 項目 | 値 |
|---|---|
| プロトコル | HTTP |
| ポート | 80 |
| デフォルトアクション | handson-tg-webap に転送 |
handson-alb-xxxxxxxxx.ap-northeast-1.elb.amazonaws.com| 項目 | 値 |
|---|---|
| 名前 | handson-webap-1a |
| AMI | Amazon Linux 2023 AMI(64ビット x86) |
| インスタンスタイプ | t2.micro |
| キーペア | キーペアなしで続行(Session Manager使用) |
| VPC | handson-vpc |
| サブネット | handson-subnet-private-webap-1a |
| パブリック IP の自動割り当て | 無効(デフォルト) |
| セキュリティグループ | sg-webap(既存のSGを選択) |
| ストレージ | 8 GiB / gp3 |
| IAM インスタンスプロフィール | handson-ec2-ssm-role(「高度な詳細」を展開して設定) |
「インスタンスを起動」から以下の項目だけ変更して同じ設定で起動します:
| 項目 | 値 |
|---|---|
| 名前 | handson-webap-1c |
| サブネット | handson-subnet-private-webap-1c |
インスタンス一覧から handson-webap-1a と handson-webap-1c にチェック
| 項目 | 値 |
|---|---|
| ポート | 80 |
handson-webap-1a と handson-webap-1c の両方で、同じ手順を実行します。
sudo -i -u ec2-user cd ~
sudo dnf update -y sudo dnf install -y nginx sudo systemctl enable nginx sudo systemctl start nginx sudo systemctl status nginx
Active: active (running) と表示されれば起動成功です。
sudo dnf install -y nodejs npm node -v npm -v
バージョン番号が表示されれば成功です。
【RDSエンドポイント】 を手順7でメモしたRDSエンドポイントに置き換えて実行します:
mkdir ~/app && cd ~/app npm init -y npm install express pg
cat > ~/app/app.js <<'EOF'
const express = require('express');
const { Pool } = require('pg');
const os = require('os');
const app = express();
const pool = new Pool({
host: '【RDSエンドポイント】',
port: 5432,
user: 'admin',
password: 'AdminPass123!',
database: 'handson_db',
ssl: { rejectUnauthorized: false },
max: 10
});
app.get('/health', (req, res) => {
res.json({ status: 'ok', server: os.hostname() });
});
app.get('/', (req, res) => {
res.json({
message: 'WebAP server is running!',
server: os.hostname(),
tier: 'webap'
});
});
app.get('/users', async (req, res) => {
try {
const result = await pool.query('SELECT * FROM users ORDER BY id');
res.json({ count: result.rowCount, users: result.rows, server: os.hostname() });
} catch (err) {
res.status(500).json({ error: err.message, server: os.hostname() });
}
});
app.listen(8080, '127.0.0.1', () => {
console.log('Node.js app listening on localhost:8080');
});
EOF
127.0.0.1(ローカルループバック)のみでリッスンしています。外部から直接8080へのアクセスはできず、Nginx経由のみアクセス可能です。RDSへの接続はSSL(ssl: { rejectUnauthorized: false })を使用しています。sudo npm install -g pm2 cd ~/app && pm2 start app.js --name webap-app pm2 save pm2 startup
pm2 startup が出力するコマンド(sudo env PATH=... で始まる行)をコピーして実行します。
pm2 status
status: online と表示されれば起動成功です。
sudo tee /etc/nginx/conf.d/webap.conf <<'EOF'
server {
listen 80;
server_name _;
location /health {
proxy_pass http://127.0.0.1:8080/health;
proxy_set_header Host $host;
access_log off;
}
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_connect_timeout 10s;
proxy_read_timeout 60s;
}
}
EOF
sudo nginx -t
syntax is ok と表示されたら:
sudo systemctl reload nginx
⬛ handson-webap-1c でも手順1〜6を同様に実行します。
WebAPサーバのどちらか1台(handson-webap-1a)のSession Managerから実行します。
sudo dnf install -y postgresql16
postgresql15 など適宜変更してください。psql -h 【RDSエンドポイント】 -U admin -d handson_db
パスワードを求められたら AdminPass123! を入力してEnter(入力文字は画面に表示されません)。
handson_db=> プロンプトが表示されれば接続成功です。
PGPASSWORD='AdminPass123!' psql -h 【RDSエンドポイント】 -U admin -d handson_db-- テーブル作成
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
email VARCHAR(200) NOT NULL UNIQUE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- サンプルデータ挿入
INSERT INTO users (name, email) VALUES
('田中 太郎', 'taro@example.com'),
('鈴木 花子', 'hanako@example.com'),
('佐藤 一郎', 'ichiro@example.com');
-- 確認
SELECT * FROM users;
-- 切断
\q
3件のレコードが表示されれば成功です。
AUTO_INCREMENT → SERIAL(PostgreSQL)、ENGINE=InnoDB は不要、終了コマンドは EXIT; の代わりに \q を使用します。handson-webap-1a と handson-webap-1c が 「healthy」 になっていることを確認します。
pm2 status でNode.jsの状態、sudo systemctl status nginx でNginxの状態を確認してください。手順9でメモした ALBのDNS名をブラウザのアドレスバーに入力してアクセスします:
| URL | 期待するレスポンス |
|---|---|
http://【ALBのDNS名】/ | {"message":"WebAP server is running!","server":"..."} |
http://【ALBのDNS名】/health | {"status":"ok","server":"..."} |
http://【ALBのDNS名】/users | RDSのusersテーブルデータ(3件) |
ブラウザで /health や /users に複数回アクセスすると、レスポンスの "server" フィールドが handson-webap-1a と handson-webap-1c で切り替わることを確認します。
EC2コンソールで handson-webap-1a を「停止」すると、ALBが自動的に handson-webap-1c のみにルーティングします。
ブラウザからのアクセスがエラーなく継続できることを確認します。
確認後は handson-webap-1a を「開始」して元の状態に戻してください。
「最終スナップショットを作成しますか?」→ いいえ を選択
確認テキスト(delete me)を入力して 削除
確認テキストを入力して 削除
デタッチ完了後 → 再度 アクション → 「インターネットゲートウェイを削除」
sg-rds → sg-webap → sg-alb の順に削除します(依存関係があるため逆順)。
サブネット 6つ → ルートテーブル(handson-rt-private-webap → handson-rt-public)→ VPC(handson-vpc)の順に削除します。