0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS入門 — PHPエンジニアが最初に覚えるべきサービスを整理した

0
Posted at

はじめに

データ処理案件とNext.js + FastAPIの構成を作るにあたって、AWSを本格的に使い始めた。

AWSはサービスが多すぎて最初に何を覚えればいいかわからない。「EC2とS3とRDSは聞いたことある」くらいの状態から始めて、実務で必要になったサービスを中心に整理した。PHPエンジニアが最初に覚えるべきサービスという視点でまとめる。


AWSの全体像

まず使う頻度が高いサービスのカテゴリを把握する。

コンピュート:
  EC2     — 仮想サーバー(PHPのVPSに相当)
  ECS     — Dockerコンテナの実行環境
  Lambda  — サーバーレス関数実行

ストレージ:
  S3      — オブジェクトストレージ(ファイル置き場)
  EBS     — EC2にアタッチするブロックストレージ

データベース:
  RDS     — マネージドRDBMS(MySQL/PostgreSQL等)
  Aurora  — AWSのRDS互換高性能DB
  DynamoDB— NoSQL

ネットワーク:
  VPC     — 仮想プライベートネットワーク
  ALB     — ロードバランサー
  Route53 — DNSサービス
  CloudFront — CDN

認証・認可:
  IAM     — ユーザー・ロール・権限の管理

その他よく使う:
  CloudWatch — ログ・メトリクス監視
  ECR        — Dockerイメージのレジストリ
  SQS        — メッセージキュー
  SNS        — 通知サービス
  Secrets Manager — シークレット管理

全部一度に覚える必要はない。まずIAM・VPC・EC2かECS・S3・RDS・CloudWatchの7つを理解すれば実務の大半は動く。


IAM — 最初に理解すべき概念

AWSで最初に理解すべきなのがIAM(Identity and Access Management)。「誰が何をできるか」を管理する。

IAMの構成要素:
  ユーザー  — 人間が使うアカウント
  グループ  — ユーザーをまとめる
  ロール    — AWSサービスが使う権限(EC2がS3を読む、など)
  ポリシー  — 何ができるかを定義するJSON

最小権限の原則

// 悪い例  全権限を与える(絶対にやらない)
{
    "Effect": "Allow",
    "Action": "*",
    "Resource": "*"
}

// 良い例  必要な権限だけ
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect":   "Allow",
            "Action":   [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::my-bucket/*"
        }
    ]
}

PHPのアプリからAWSのサービスを使うとき、アクセスキーをコードに直書きするのは絶対にNG。EC2やECSにIAMロールをアタッチして、コードは認証情報を直接持たない設計にする。

# 悪い例(アクセスキーを直書き)
import boto3
s3 = boto3.client(
    's3',
    aws_access_key_id     = 'AKIAIOSFODNN7EXAMPLE',
    aws_secret_access_key = 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY',
)

# 良い例(IAMロールで自動取得)
import boto3
s3 = boto3.client('s3')  # EC2/ECSのロールから自動取得

VPC — ネットワークの基本

VPC(Virtual Private Cloud)はAWS内の仮想ネットワーク。サーバーを「どのネットワークに置くか」を定義する。

VPC(例: 10.0.0.0/16)
├── パブリックサブネット(10.0.1.0/24)
│   ├── ALB(ロードバランサー)
│   └── NAT Gateway
└── プライベートサブネット(10.0.2.0/24)
    ├── ECS/EC2(アプリサーバー)
    └── RDS(データベース)
ルール:
  パブリックサブネット  → インターネットから直接アクセスできる
  プライベートサブネット → インターネットから直接アクセスできない
  DBはプライベートサブネットに置く(外から直接叩けないようにする)

PHPを普通のVPSで動かしていたときはこういった分離を意識しなかったが、AWSではネットワーク設計が重要になる。

セキュリティグループ

セキュリティグループ = ファイアウォールのルール

ALBのセキュリティグループ:
  インバウンド: 0.0.0.0/0 → 80, 443(全てのIPからHTTP/HTTPS)
  アウトバウンド: ECSのSG → 8000(ECSにのみ転送)

ECSのセキュリティグループ:
  インバウンド: ALBのSG → 8000(ALBからのみ受け付ける)
  アウトバウンド: 0.0.0.0/0 → 443(外部API呼び出しのため)

RDSのセキュリティグループ:
  インバウンド: ECSのSG → 5432(ECSからのみ受け付ける)
  アウトバウンド: なし

「どこからどこへのアクセスを許可するか」を明示的に設定する。PHPのVPSではファイアウォールを手動で設定していたが、AWSではセキュリティグループで管理する。


S3 — ファイルストレージ

S3(Simple Storage Service)は容量無制限のオブジェクトストレージ。

PHPでの使い方と比較:
  PHPのstorage/  → S3バケット
  ファイルをPHPサーバーに保存 → S3に保存
  公開ファイルをpublic/に置く → S3の署名付きURLで配信
import boto3

s3 = boto3.client('s3', region_name='ap-northeast-1')

# アップロード
s3.upload_file(
    'local_file.txt',
    'my-bucket',
    'path/in/bucket/file.txt'
)

# ダウンロード
s3.download_file(
    'my-bucket',
    'path/in/bucket/file.txt',
    'downloaded_file.txt'
)

# 署名付きURL(一時的なダウンロードURL)
url = s3.generate_presigned_url(
    'get_object',
    Params     = {'Bucket': 'my-bucket', 'Key': 'private/file.pdf'},
    ExpiresIn  = 3600,  # 1時間有効
)

S3のバケットポリシー

// パブリックアクセスをブロックする(デフォルト推奨)
// 署名付きURLで個別にアクセスを許可する
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "s3:*",
            "Resource": [
                "arn:aws:s3:::my-bucket",
                "arn:aws:s3:::my-bucket/*"
            ],
            "Condition": {
                "Bool": {
                    "aws:SecureTransport": "false"
                }
            }
        }
    ]
}

EC2 — 仮想サーバー

EC2(Elastic Compute Cloud)はいわゆる仮想サーバー。PHPのVPSに相当する。

# EC2に接続
ssh -i my-key.pem ec2-user@xxx.xxx.xxx.xxx

ただし今はEC2を直接使うより、ECSでDockerコンテナを動かすほうが主流。EC2を使うケースは限られてきた。

EC2を選ぶとき:
  ✓ 特定のOSやミドルウェアが必要
  ✓ 長時間実行するプロセス(バッチ処理など)
  ✓ GPUが必要(機械学習など)

ECSを選ぶとき(現代的な選択):
  ✓ Dockerで動くアプリ
  ✓ スケールイン/アウトが必要
  ✓ マネージドサービスに任せたい

ECS — Dockerコンテナの実行

ECS(Elastic Container Service)はDockerコンテナを実行するサービス。FastAPIのデプロイで実際に使っている。

ECSの構成:
  クラスター — コンテナを動かす環境のまとまり
  タスク定義 — コンテナの設定(イメージ・CPU・メモリ・環境変数)
  サービス   — タスクを指定台数起動し続ける
  タスク     — 実際に動いているコンテナ
// タスク定義(一部)
{
    "family":           "fastapi-task",
    "networkMode":      "awsvpc",
    "requiresCompatibilities": ["FARGATE"],
    "cpu":              "512",
    "memory":           "1024",
    "containerDefinitions": [
        {
            "name":  "fastapi",
            "image": "123456789.dkr.ecr.ap-northeast-1.amazonaws.com/fastapi:latest",
            "portMappings": [
                { "containerPort": 8000, "protocol": "tcp" }
            ],
            "environment": [
                { "name": "APP_ENV", "value": "production" }
            ],
            "secrets": [
                {
                    "name":      "DATABASE_URL",
                    "valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123:secret:database-url"
                }
            ],
            "logConfiguration": {
                "logDriver": "awslogs",
                "options": {
                    "awslogs-group":         "/ecs/fastapi",
                    "awslogs-region":        "ap-northeast-1",
                    "awslogs-stream-prefix": "ecs"
                }
            }
        }
    ]
}

Fargate vs EC2起動タイプ

EC2起動タイプ:
  自分でEC2インスタンスを管理する
  コストが安い(大規模なら)

Fargate:
  サーバーレス。インスタンスを管理しなくていい
  コストが高め(少量なら)
  → 最初はFargateで始めるのが楽

RDS — マネージドデータベース

RDS(Relational Database Service)はMySQLやPostgreSQLなどのマネージドサービス。

PHPのMySQLと比べて何が違うか:
  自前MySQL: サーバーの管理・バックアップ・パッチ当てを自分でやる
  RDS: バックアップ・フェイルオーバー・パッチを自動でやってくれる
# Pythonからの接続(FastAPIと組み合わせる場合)
DATABASE_URL = os.environ.get("DATABASE_URL")
# "postgresql://user:pass@rds-endpoint.rds.amazonaws.com:5432/mydb"

engine = create_engine(DATABASE_URL)

RDSのエンドポイント

プライマリエンドポイント: 読み書き両用
リードレプリカのエンドポイント: 読み取り専用(複数レプリカある場合)

RDSはプライベートサブネットに置いて、ECSからのみアクセスできるようにするのが基本。


ALB — ロードバランサー

ALB(Application Load Balancer)はHTTPSの終端とトラフィックの振り分けを担う。

Internet → ALB(HTTPS終端・SSL証明書) → ECS(HTTP)
ALBの主な役割:
  ✓ HTTPS終端(SSL証明書の管理)
  ✓ 複数のECSタスクへのトラフィック振り分け
  ✓ ヘルスチェック(正常なタスクのみに転送)
  ✓ パスベースルーティング(/api/ → FastAPI、/ → Next.js)
パスベースルーティングの例:
  https://example.com/       → Next.js(ECS)
  https://example.com/api/*  → FastAPI(ECS)

CloudWatch — ログと監視

CloudWatch はAWSのログ収集・メトリクス監視サービス。

# ECSのタスク定義にawslogsドライバーを設定すると
# print()の出力がCloudWatch Logsに自動で送られる

import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

@app.get("/users")
def list_users():
    logger.info("ユーザー一覧を取得")
    users = db.query(User).all()
    logger.info(f"取得件数: {len(users)}")
    return users
# CLIでログを確認
aws logs tail /ecs/fastapi --follow

# 直近のログを取得
aws logs get-log-events \
    --log-group-name /ecs/fastapi \
    --log-stream-name ecs/fastapi/タスクID

アラートの設定

# CloudWatchアラームをboto3で作成
import boto3

cloudwatch = boto3.client('cloudwatch', region_name='ap-northeast-1')

cloudwatch.put_metric_alarm(
    AlarmName          = 'HighErrorRate',
    ComparisonOperator = 'GreaterThanThreshold',
    EvaluationPeriods  = 2,
    MetricName         = '5XXError',
    Namespace          = 'AWS/ApplicationELB',
    Period             = 300,  # 5分
    Statistic          = 'Sum',
    Threshold          = 10,
    AlarmDescription   = '5xxエラーが10件を超えた',
    AlarmActions       = ['arn:aws:sns:ap-northeast-1:123:MyTopic'],
)

Secrets Manager — 認証情報の安全な管理

環境変数に直接シークレットを入れるのではなく、Secrets Managerで管理する。

import boto3
import json

def get_secret(secret_name: str) -> dict:
    client = boto3.client(
        'secretsmanager',
        region_name='ap-northeast-1'
    )
    response = client.get_secret_value(SecretId=secret_name)
    return json.loads(response['SecretString'])

# 使う側
db_secret   = get_secret('production/database')
db_url      = f"postgresql://{db_secret['username']}:{db_secret['password']}@{db_secret['host']}/{db_secret['dbname']}"

ECSではタスク定義のsecretsでSecrets Managerの値をコンテナの環境変数に注入できる(前述のタスク定義のサンプルを参照)。


ECR — Dockerイメージレジストリ

ECS用のDockerイメージをECR(Elastic Container Registry)に保存する。

# ECRにログイン
aws ecr get-login-password --region ap-northeast-1 | \
    docker login --username AWS --password-stdin \
    123456789.dkr.ecr.ap-northeast-1.amazonaws.com

# イメージをビルドしてプッシュ
docker build -t fastapi .
docker tag fastapi:latest \
    123456789.dkr.ecr.ap-northeast-1.amazonaws.com/fastapi:latest
docker push \
    123456789.dkr.ecr.ap-northeast-1.amazonaws.com/fastapi:latest

PHPサーバー構成との比較

PHP(従来型VPS):
  Nginx + PHP-FPM → MySQL(同じサーバーまたは別サーバー)
  SSH + git pull でデプロイ
  ファイルはサーバーのローカルに保存

AWS(モダン構成):
  ALB → ECS(FastAPI) → RDS
         ↓
         S3(ファイル)
  GitHub Actions → ECR → ECS(CI/CD)
  シークレットはSecrets Manager
  ログはCloudWatch

最初の1週間で覚えること

Day 1: IAMユーザーとロールの概念
  → アクセスキーを作らずにIAMロールを使う設計を理解する

Day 2: S3の基本操作
  → バケット作成・ファイルのアップロード/ダウンロード・署名付きURL

Day 3: VPCとセキュリティグループ
  → パブリック/プライベートサブネットの違いを理解する

Day 4: RDSの作成と接続
  → PostgreSQLをプライベートサブネットに作ってEC2から接続する

Day 5: ECSでDockerコンテナを動かす
  → ECRにプッシュしてFargateでタスクを動かす

Day 6: ALBの設定
  → ALBの後ろにECSを置いてHTTPS経由でアクセスする

Day 7: CloudWatchでログを確認
  → ECSのログをCloudWatch Logsで見る

まとめ

  • IAMはAWSの全サービスの基盤。最初に理解する
  • VPCはネットワーク設計。DBはプライベートサブネットに置く
  • S3はファイルストレージ。アプリのファイルはS3に保存
  • ECSはDockerコンテナの実行環境。EC2より管理が楽
  • RDSはマネージドDB。バックアップやフェイルオーバーが自動
  • ALBはHTTPS終端とロードバランシング
  • CloudWatchはログと監視
  • Secrets Managerでシークレットを管理してコードに直書きしない

AWSは最初の設定が多くて大変だが、一度構築したら運用が楽になる部分が多い。「インフラの管理をAWSに任せてアプリの開発に集中できる」というのが実感できるようになるまで少し時間がかかった。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?