📁 完全なコードはGitHubで公開:GitHub: pipeiac02
シリーズ一覧(全12回)
Phase 1: 基盤構築
Phase 2: ワークフロー
Phase 3: セキュリティ・運用
Phase 4: 開発効率化
1. はじめに
1-1. シリーズ完結
この記事では、シリーズ全体を振り返り、学んだことをまとめます。
1-2. この記事の内容
| セクション | 内容 |
|---|---|
| 全体の振り返り | 12回分のサマリー |
| 作成したもの | リソース一覧 |
| 比喩の総まとめ | レストラン対応表 |
| 学んだこと | 技術・設計・運用 |
| E2Eテスト | パイプライン動作確認 |
| 次のステップ | 発展的な学習 |
2. 全体の振り返り
2-1. シリーズの構成
2-2. 記事の各回のサマリー
| # | 記事タイトル要約 | テーマ |
|---|---|---|
| 1 | 全体像 | パイプラインの設計思想、レストラン比喩の導入 |
| 2 | S3設計 | Raw/Processedの分離、バケット設計 |
| 3 | Lambda ETL | Pythonでの変換処理、Parquet形式 |
| 4 | Glue Crawler | スキーマ自動検出、Athena連携 |
| 5 | Step Functions | ワークフロー制御、ステートマシン |
| 6 | EventBridge | イベント駆動、自動トリガー |
| 7 | IAM最小権限 | セキュリティ設計、権限の絞り込み |
| 8 | エラーハンドリング | Retry/Catch、SNS通知 |
| 9 | CloudWatch監視 | アラーム、ダッシュボード |
| 10 | Terraform設計 | ファイル構成、変数管理 |
| 11 | CI/CD | GitHub Actions、自動デプロイ |
| 12 | 総まとめ | 振り返り、次のステップ |
3. 作成したもの
3-1. アーキテクチャ全体図
3-2. AWSリソース一覧
| カテゴリ | リソース | 用途 | 作成回 |
|---|---|---|---|
| ストレージ | S3 Bucket | 生データ保存(raw) | 第2回 |
| ストレージ | S3 Bucket | 加工データ保存(processed) | 第2回 |
| コンピュート | Lambda | ETL処理(JSON→Parquet) | 第3回 |
| カタログ | Glue Database | メタデータ管理 | 第4回 |
| カタログ | Glue Crawler | スキーマ自動検出 | 第4回 |
| オーケストレーション | Step Functions | ワークフロー制御 | 第5回 |
| イベント | EventBridge Rule | S3アップロード検知 | 第6回 |
| イベント | S3 Notification | EventBridge連携有効化 | 第6回 |
| 認証 | IAM Role | Lambda用権限 | 第3回 |
| 認証 | IAM Role | Glue Crawler用権限 | 第4回 |
| 認証 | IAM Role | Step Functions用権限 | 第5回 |
| 認証 | IAM Role | EventBridge用権限 | 第6回 |
| 通知 | SNS Topic | アラート通知先 | 第8回 |
| 通知 | SNS Subscription | メール通知設定 | 第8回 |
| 監視 | CloudWatch Alarm | Lambdaエラー検知 | 第9回 |
| 監視 | CloudWatch Dashboard | 状態可視化 | 第9回 |
3-3. ファイル構成
シリーズ完成後の構成です(第1回の初期構成から発展した形)。
pipeiac02/
├── .github/
│ └── workflows/
│ ├── terraform-plan.yml # 第11回で追加(PR時にplan実行)
│ └── terraform-apply.yml # 第11回で追加(マージ時にapply実行)
├── oidc/ # 第11回:OIDC設定(別管理推奨)
│ ├── main.tf # 第11回:OIDCプロバイダ・IAMロール
│ ├── variables.tf # 第11回:変数定義
│ └── outputs.tf # 第11回:出力値
├── test-data/ # テスト用サンプルデータ
│ ├── ec-sales-03.json # 第3回:Lambda ETLテスト
│ ├── ec-sales-05.json # 第5回:Step Functionsテスト
│ ├── ec-sales-06.json # 第6回:EventBridge自動起動テスト
│ ├── iam-test.json # 第7回:IAM権限テスト
│ ├── error-test-ok.json # 第8回:エラーハンドリング正常系
│ ├── monitor-test.json # 第9回:CloudWatch監視テスト
│ ├── refactor-test.json # 第10回:リファクタリング後テスト
│ ├── e2e-test.json # 第12回:E2E正常系テスト
│ ├── invalid-json.json # 第12回:E2E異常系(不正JSON)
│ └── empty-array.json # 第12回:E2E異常系(空配列)
├── tf/
│ ├── main.tf # 第2回:プロバイダ設定・共通タグ
│ ├── variables.tf # 第2回:変数定義
│ ├── outputs.tf # 第2回:出力値定義
│ ├── backend.tf # 第11回:S3バックエンド設定
│ ├── terraform.tfvars # 第2回:変数値(Git管理外)
│ ├── s3.tf # 第2回:S3バケット
│ ├── lambda.tf # 第3回:Lambda関数
│ ├── glue.tf # 第4回:Glue Database・Crawler
│ ├── stepfunctions.tf # 第5回:Step Functions
│ ├── eventbridge.tf # 第6回:EventBridgeルール・S3通知
│ ├── sns.tf # 第8回:SNSトピック・サブスクリプション
│ ├── cloudwatch.tf # 第9回:アラーム・ダッシュボード
│ ├── iam.tf # 第3,4,5,6回:IAMロール・ポリシー
│ └── lambda/
│ └── etl.py # 第3回:ETL処理コード
└── README.md
補足:
-
terraform-plan.yml: PR作成時にterraform planを実行し、結果をPRにコメント -
terraform-apply.yml: mainマージ時にterraform applyを自動実行 -
oidc/: GitHub Actions用のOIDC認証設定(メインのtfとは別管理) -
backend.tf: tfstateをS3で管理するための設定
4. 比喩の総まとめ
4-1. レストラン × AWS 対応表
このシリーズでは、AWSサービスを「レストラン」に例えて説明しました。
| レストラン | AWS | 役割 | 記事 |
|---|---|---|---|
| お客さんの注文 | S3アップロード | データの投入 | #2 |
| ホールスタッフ | EventBridge | イベント検知・転送 | #6 |
| 調理長 | Step Functions | 工程管理・順序制御 | #5 |
| 料理人 | Lambda | データ変換処理 | #3 |
| 冷蔵庫 | S3 Raw | 生データの保管 | #2 |
| 盛り付け台 | S3 Processed | 加工済みデータ | #2 |
| メニュー係 | Glue Crawler | スキーマ検出 | #4 |
| メニュー表 | Glue Database | メタデータ管理 | #4 |
| 配膳とお会計 | Athena | データ分析・クエリ | #4 |
| スタッフ権限 | IAM | アクセス制御 | #7 |
| 作り直し | Retry | リトライ処理 | #8 |
| 店長報告 | SNS | エラー通知 | #8 |
| 監視パネル | CloudWatch | モニタリング | #9 |
| レシピ本 | Terraform | IaC | #10 |
| 自動発注 | CI/CD | 自動デプロイ | #11 |
4-2. データの流れ(レストラン版)
4-3. データの流れ(AWS版)
5. 学んだこと
5-1. 技術面
| カテゴリ | 学んだこと |
|---|---|
| ストレージ | S3のRaw/Processed分離、Parquet形式 |
| コンピュート | Lambda Layer、環境変数、タイムアウト設計 |
| ETL | pandas、JSON→Parquet変換、パーティション |
| カタログ | Glue Crawler、スキーマ自動検出 |
| ワークフロー | Step Functions、ASL、ステートマシン |
| イベント | EventBridge、イベントパターン、input_transformer |
| セキュリティ | IAM最小権限、リソースARN指定 |
| 耐障害性 | Retry/Catch、SNS通知 |
| 監視 | CloudWatchメトリクス、アラーム、ダッシュボード |
| IaC | Terraform構成、変数管理、モジュール化 |
| CI/CD | GitHub Actions、OIDC認証、自動デプロイ |
5-2. 設計面
| 原則 | 説明 |
|---|---|
| 疎結合 | サービス間を疎結合に保つ |
| イベント駆動 | ポーリングではなくイベントで起動 |
| 最小権限 | 必要な権限だけを付与 |
| 可観測性 | ログ・メトリクス・アラームで監視 |
| IaC | インフラをコードで管理 |
| 自動化 | CI/CDで人的ミスを防ぐ |
5-3. 運用面
| プラクティス | 説明 |
|---|---|
| エラー通知 | 障害を即座に検知 |
| リトライ | 一時的な障害に自動対応 |
| ダッシュボード | 状態を一目で把握 |
| コードレビュー | PRでplan結果を確認 |
| 自動デプロイ | マージで自動適用 |
6. E2Eテスト(パイプライン動作確認)
構築したパイプラインが正しく動作するか、End-to-Endでテストします。
6-1. テスト計画
6-1-1. 目的
| 項目 | 内容 |
|---|---|
| 目的 | データパイプラインが設計通りに動作することを確認する |
| 範囲 | S3アップロード → Athenaクエリ成功までの一連の流れ |
| 対象 | 正常系・異常系の両方 |
6-1-2. 前提条件
| # | 条件 |
|---|---|
| 1 |
terraform apply が完了している |
| 2 | SNSサブスクリプションが確認済み(メールのリンクをクリック) |
| 3 | AWS CLIが設定済み |
| 4 | jqコマンドがインストール済み |
6-1-3. 合格基準
| # | 基準 |
|---|---|
| 1 | 正常系:Step Functionsが SUCCEEDED で完了する |
| 2 | 正常系:S3 ProcessedにParquetファイルが出力される |
| 3 | 正常系:Athenaでデータがクエリできる |
| 4 | 異常系:不正データでStep Functionsが FAILED になる |
| 5 | 異常系:失敗時にSNS通知が届く |
6-2. テストケース一覧
| ID | カテゴリ | ケース名 | 入力データ | 期待結果 |
|---|---|---|---|---|
| TC-01 | 正常系 | 正常なJSON | 3件のEC売上データ | SUCCEEDED, Athenaクエリ成功 |
| TC-02 | 異常系 | 不正なJSON形式 | 文字列のみ | FAILED, SNS通知 |
| TC-03 | 異常系 | 空のJSON配列 | [] |
FAILED, SNS通知 |
6-3. テスト手順書
6-3-1. TC-01: 正常系テスト
| Step | 作業内容 | コマンド/操作 | 確認方法 | 期待結果 |
|---|---|---|---|---|
| 1 | 環境変数設定 | export RAW_BUCKET=... |
echo確認 | 変数設定完了 |
| 2 | テストデータ作成 | cat << 'EOF' > pipeiac02/test-data/... |
cat確認 | JSONファイル作成 |
| 3 | S3アップロード | aws s3 cp ... |
aws s3 ls |
アップロード成功 |
| 4 | 待機 | sleep 30 |
- | - |
| 5 | SFn状態確認 | aws stepfunctions list-executions ... |
Status確認 | SUCCEEDED |
| 6 | Parquet確認 | aws s3 ls s3://.../processed/ |
ファイル一覧 | Parquetファイル存在 |
| 7 | Athenaクエリ | aws athena start-query-execution ... |
結果確認 | データ取得成功 |
6-3-2. TC-02: 異常系テスト(不正JSON)
| Step | 作業内容 | コマンド/操作 | 確認方法 | 期待結果 |
|---|---|---|---|---|
| 1 | 不正データ作成 | cat << 'EOF' > pipeiac02/test-data/... |
cat確認 | ファイル作成 |
| 2 | S3アップロード | aws s3 cp ... |
aws s3 ls |
アップロード成功 |
| 3 | 待機 | sleep 30 |
- | - |
| 4 | SFn状態確認 | aws stepfunctions list-executions ... |
Status確認 | FAILED |
| 5 | SNS通知確認 | メール確認 | 受信確認 | 通知メール受信 |
6-3-3. TC-03: 異常系テスト(空配列)
| Step | 作業内容 | コマンド/操作 | 確認方法 | 期待結果 |
|---|---|---|---|---|
| 1 | 空データ作成 | echo '[]' > pipeiac02/test-data/... |
cat確認 | ファイル作成 |
| 2 | S3アップロード | aws s3 cp ... |
aws s3 ls |
アップロード成功 |
| 3 | 待機 | sleep 30 |
- | - |
| 4 | SFn状態確認 | aws stepfunctions list-executions ... |
Status確認 | FAILED |
| 5 | SNS通知確認 | メール確認 | 受信確認 | 通知メール受信 |
6-4. テストフロー図
6-4-1. 正常系フロー
6-4-2. 異常系フロー
6-5. 事前準備
6-5-1. バケット名の確認
# tfディレクトリで実行
cd tf
# バケット名を確認
terraform output raw_bucket_id
terraform output processed_bucket_id
6-5-2. 環境変数の設定
# 環境変数に設定
export RAW_BUCKET=$(terraform output -raw raw_bucket_id)
export PROCESSED_BUCKET=$(terraform output -raw processed_bucket_id)
export SFN_ARN=$(terraform output -raw sfn_arn)
# 確認
echo "Raw: $RAW_BUCKET"
echo "Processed: $PROCESSED_BUCKET"
echo "SFN: $SFN_ARN"
6-6. TC-01: 正常系テスト実行
リポジトリに含まれている test-data/e2e-test.json を使用します。
6-6-1. Step 1: テストデータ確認
# 内容確認
cat test-data/e2e-test.json | jq .
6-6-2. Step 2: S3アップロード
# アップロード
aws s3 cp test-data/e2e-test.json s3://$RAW_BUCKET/input/e2e-test.json
# 確認
aws s3 ls s3://$RAW_BUCKET/input/
6-6-3. Step 3: Step Functions実行確認
# 30秒待機(パイプライン実行時間)
echo "パイプライン実行中... 30秒待機"
sleep 30
# 最新の実行状態を確認
aws stepfunctions list-executions \
--state-machine-arn $SFN_ARN \
--max-results 1 \
--query 'executions[0].{Name:name,Status:status,StartDate:startDate}'
期待される出力:
{
"Name": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"Status": "SUCCEEDED",
"StartDate": "2025-01-10T12:00:00.000000+09:00"
}
6-6-4. Step 4: 各ステップの確認
# Processed バケットにParquetが出力されたか確認
aws s3 ls s3://$PROCESSED_BUCKET/processed/ --recursive
# Glue Crawlerの状態確認
aws glue get-crawler --name dp-crawler \
--query 'Crawler.{Name:Name,State:State,LastCrawl:LastCrawl.Status}'
# Lambda ログ確認(直近5分)
aws logs filter-log-events \
--log-group-name /aws/lambda/dp-etl \
--start-time $(date -d '5 minutes ago' +%s000) \
--query 'events[*].message' \
--output text | head -20
6-6-5. Step 5: Athenaでクエリ実行
# クエリ実行
QUERY_ID=$(aws athena start-query-execution \
--query-string "SELECT * FROM dp_db.processed LIMIT 10" \
--work-group primary \
--result-configuration OutputLocation=s3://$PROCESSED_BUCKET/athena-results/ \
--query 'QueryExecutionId' \
--output text)
echo "Query ID: $QUERY_ID"
# 結果を待機(5秒)
sleep 5
# クエリ結果確認
aws athena get-query-results --query-execution-id $QUERY_ID
6-7. TC-02: 異常系テスト(不正JSON)
リポジトリに含まれている test-data/invalid-json.json を使用します。
6-7-1. Step 1: アップロード
aws s3 cp test-data/invalid-json.json s3://$RAW_BUCKET/input/invalid-test.json
6-7-2. Step 3: 失敗確認
# 30秒待機
sleep 30
# Step Functions実行状態(FAILEDになるはず)
aws stepfunctions list-executions \
--state-machine-arn $SFN_ARN \
--max-results 1 \
--query 'executions[0].{Name:name,Status:status}'
期待される出力:
{
"Name": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"Status": "FAILED"
}
6-7-3. Step 4: SNS通知確認
登録したメールアドレスに通知が届いているか確認してください。
通知内容の例:
Pipeline failed: Lambda.Unknown
6-8. TC-03: 異常系テスト(空配列)
リポジトリに含まれている test-data/empty-array.json を使用します。
6-8-1. Step 1: アップロード & 確認
aws s3 cp test-data/empty-array.json s3://$RAW_BUCKET/input/empty-test.json
# 30秒待機
sleep 30
# 実行状態確認(FAILEDになるはず)
aws stepfunctions list-executions \
--state-machine-arn $SFN_ARN \
--max-results 1 \
--query 'executions[0].{Name:name,Status:status}'
6-9. テスト結果記録
| ID | ケース名 | 期待結果 | 実行結果 | 判定 |
|---|---|---|---|---|
| TC-01 | 正常なJSON | SUCCEEDED | ⬜ | |
| TC-02 | 不正なJSON | FAILED + SNS | ⬜ | |
| TC-03 | 空の配列 | FAILED + SNS | ⬜ |
テスト実行後、実行結果と判定(✅ or ❌)を記入
6-10. クリーンアップ
テスト後、S3上の不要なファイルを削除:
# S3テストファイル削除
aws s3 rm s3://$RAW_BUCKET/input/e2e-test.json
aws s3 rm s3://$RAW_BUCKET/input/invalid-test.json
aws s3 rm s3://$RAW_BUCKET/input/empty-test.json
# Athena結果削除(任意)
aws s3 rm s3://$PROCESSED_BUCKET/athena-results/ --recursive
6-11. トラブルシューティング
6-11-1. EventBridgeがトリガーされない
# S3のEventBridge設定確認
aws s3api get-bucket-notification-configuration --bucket $RAW_BUCKET
# EventBridgeルール確認
aws events describe-rule --name dp-s3-upload
確認ポイント:
-
eventbridge: trueが設定されているか - ルールが
ENABLEDになっているか
6-11-2. Lambda がタイムアウト
# Lambda設定確認
aws lambda get-function-configuration --function-name dp-etl \
--query '{Timeout:Timeout,MemorySize:MemorySize}'
対処:
- タイムアウト値を増やす(60秒 → 120秒)
- メモリを増やす(256MB → 512MB)
6-11-3. Glue Crawlerがテーブルを作成しない
# Crawler手動実行
aws glue start-crawler --name dp-crawler
# 状態確認
aws glue get-crawler --name dp-crawler --query 'Crawler.State'
# テーブル確認
aws glue get-tables --database-name dp_db
確認ポイント:
- S3パスが正しいか
- Parquetファイルが出力されているか
6-11-4. SNS通知が届かない
# サブスクリプション確認
aws sns list-subscriptions-by-topic \
--topic-arn $(terraform output -raw sns_topic_arn)
確認ポイント:
- サブスクリプションが
confirmedになっているか - 確認メールのリンクをクリックしたか
7. 次の学習テーマ考察(余談)
7-1. 発展テーマ
| トピック | 説明 | 関連サービス |
|---|---|---|
| マルチアカウント | 本番/開発環境の分離 | AWS Organizations, Control Tower |
| データ品質 | データの検証・クレンジング | Glue DataBrew, Deequ |
| 機械学習 | MLパイプライン | SageMaker, Step Functions |
| リアルタイム | ストリーミング処理 | Kinesis, MSK |
| コスト最適化 | リソースの最適化 | Cost Explorer, Budgets |
8. 最後に
このシリーズを通じて、設計思考を重視して自己学習しました。
設計過程の可視化 があると、Terraformコードがスムーズに書ける。
「なぜ?」を大切 に、インフラ設計を勉強していきたいと思います。