はじめに
案件でECS、EFS、RDSを利用した構成を見る機会がありました。
最初は、
EFSにファイルがあるなら、RDSはいらないのでは?
ECSはどうやってRDSの情報を取得しているの?
なぜ環境変数を使うの?
といった疑問を持っていました。
上司に確認しながら整理できた内容が、自分と同じように初学者の方の参考になるかもしれないと思ったのでまとめてみます。
下記はAIに作成させたイメージ図です。
これを詳しく説明していく記事なので、ご参照ください!
システム構成
全体像は以下のような構成です。
ECR
│
(Dockerイメージ取得)
↓
ECS(Fargate)
↑ ↑
│ │
↓ ↓
RDS EFS
<格納されているデータ>
RDS:メタ情報管理
EFS:実ファイル保存
各サービスの役割は以下のようになっています。
ECR : Dockerイメージの管理
ECS : アプリケーションの実行
RDS: 状態やメタ情報の管理
EFS : 実ファイルの保存(画像などのアプリで使用するデータ)
最初の疑問「EFSだけではダメなのか?」
正直、EFSにファイルが保存されているなら、RDSは必要ないのでは?
と思っていました。
例えば、EFS上に以下のようなファイルが存在していたとします。
/input
├── A.csv
├── B.csv
└── C.csv
しかし、この状態ではECS側から見ると、
どのファイルを処理するのか
処理中なのか
処理済みなのか
エラーになったのか
といった情報が分かりません。
ここで次のRDSを挟む理由につながります。
RDSを挟む理由
RDSにはアプリで使用するファイルそのものではなく、管理情報を保存しています。
例えば、以下のようなテーブルを用意します。
| id | file_name | status |
|---|---|---|
| 1 | A.csv | WAITING |
| 2 | B.csv | RUNNING |
| 3 | C.csv | COMPLETED |
ECSは以下のようなSQLで処理対象を取得します。
SELECT *
FROM jobs
WHERE status = 'WAITING';
取得した結果をもとに、
- EFS上のファイルを読み込む
- 処理を実行する
- statusを更新する
という流れになります。
つまり、
EFS = 実データ置き場
RDS = 管理台帳
という役割分担になっています。
全体としては下記のような流れで動作していました。
ECR
↓
Dockerイメージ取得
↓
ECSコンテナ起動
↓
アプリケーションコード実行
↓
RDSへ接続
↓
必要な情報取得
↓
EFS上のファイルを処理
アプリケーションはRDSに接続して情報を取得する
例えばPythonの場合、アプリケーションコード内で下記のように記載されています。
<RDSに接続するためのコード>
conn = psycopg2.connect(
host=os.getenv("DB_HOST"),
database=os.getenv("DB_NAME"),
user=os.getenv("DB_USER"),
password=os.getenv("DB_PASSWORD")
)
Dockerイメージ内のアプリケーションコードが、
起動後にRDSへ接続して必要なデータを取得している
という形になります。
なぜ環境変数を利用するのか
実務を進めていく際に上司から、
「環境変数を変更するだけで取得するデータを切り替えられるのが便利」
という話を聞きました。
最初はよく理解できませんでしたが、
質問や情報収集を行い理解することができました。
例えば、DEV環境でECSの環境変数が以下のような設定になっているとします。
DB_HOST=dev-db
DB_NAME=dev_db
一方、PROD環境では、
DB_HOST=prod-db
DB_NAME=prod_db
という設定になっているとします。
アプリケーション側のコード内で下記のようにした場合、
host = os.getenv("DB_HOST")
database = os.getenv("DB_NAME")
コードを変更する必要はなくなりますよね。
ということは、同じDockerイメージを利用したまま、
- DEV用RDS
- STG用RDS
- PROD用RDS
を切り替えることができます。
同じDockerイメージを全環境で利用できる
この仕組みにより、
ECR
│
共通のDockerイメージ
┌────────┼────────┐
↓ ↓ ↓
DEV環境 STG環境 PROD環境
DB_HOST DB_HOST DB_HOST
↓ ↓ ↓
dev-db stg-db prod-db
という構成が実現できます。
環境ごとに別々のDockerイメージを作成する必要がないため、
- 保守性の向上
- 運用コストの削減
- デプロイの簡略化
といったメリットがあります。
まとめ
最初は、
EFSだけで十分では? と思っていました。
しかし実際には、
EFSは実データを保存する
RDSは状態やメタ情報を管理する
ECSは実際に処理を行う
という役割分担になっていました。
また、環境変数を利用することで、
コードを変更せずDockerイメージを作り直さず
接続先や取得するデータを切り替えることができます。
このように責務を分離することで運用性や保守性を高めていることを学びました。
もし同じように、
「EFSだけでよくない?」
と思ったことがある方の参考になれば幸いです。
補足
実際の案件では構成や用途によって設計はさまざまであり、
必ずしもすべてのシステムでEFS+RDS構成が採用されるわけではありません。
今回の記事は、私が携わっている案件で学んだ構成をもとに整理した内容です。
