# Magic Pocket - Django Serverless Deployment

magic-pocket の目標は、サーバレスDjangoです。Djangoを以下の環境にデプロイします。

- AWS Lambda
- Neon Postgres
- S3 storages

!!! info "ライブラリ作るほどじゃない？英語が読めたらそうかも。"
    このライブラリを作った理由として、英語ドキュメントへの苦労というのがあります。
    作者は日本人で英語が出来ません。
    日本語への機会翻訳は、ドキュメントを読む助けにはなりません。
    AWSインフラをコードに落とし込もうとすると、多くのドキュメントを読む必要がありました。
    もはや、プログラミングをしているのか、英語の勉強をしているのか分からない状況でした。

    「英語勉強すれば？」というのは、怠惰じゃないにも程がありますし、他の苦しむ人たちの助けにもならない。
    そもそもコマンド1つ叩いて環境が出来れば、日本語すら読めなくて良くて最高かなと。

??? question "とはいえ英語ぐらい勉強しようよ。"
    おっしゃる通りです。
    が、どうやっても勉強できなかったです。

    - 3歳児でもできることを、何年もかけて学ぶの、ばからしい。
    - 良い大人が、1年勉強して身に付かないとか、意味不明。
    - もっと簡単なはず、教え方が悪い。

    そう思って、自分が使いたい英語学習のサイトを作る事にしました。
    このライブラリは、そのためのライブラリでもあります。

!!! success "リソースの理解について"
    AWSリソースの多くはクラウドフォーメーションで作成されます。
    私は、コンソールからリソースを作ってしまい、訳が分からなくなった事が何度もあり、作ったリソースの把握も重要な要件になりました。

    例外として、データ保存を行う以下のリソースは、 APIから直接作成されます。

    - S3バケット
    - ECRレポジトリ
    - route53レコード
    - SecretsManagerシークレット

## Motivation

小規模な個人プロジェクトを、1人で複数同時に運用するため開発されたライブラリです。
気軽に作り、飽きたら放っておく、というスタイルで運用するため、以下の要件が最終目標になっています。

- サーバーの保守が不要
- 使わない間のコストが不要
- 環境を作る時にやる気を出す必要なし

??? question "やる気ってなに？"
    作者の場合、環境を作るステップ毎に1時間の休憩が必要です。このステップは、コマンドを1つ打つだけでもカウントされるため、5ステップもあると1日が終わります。
    コマンド1つなら1時間、2つだと2時間になるので、コマンドを1つまとめるだけで大違いです。

    さらに、この精神的負荷は、環境を作るとお金がかかる、消すのが手間、ということから来ている部分も多く、100個作っても平気で消すのも簡単となると、1時間以下で作れるようになるのではないかと考えています。

## Background

小規模プロジェクトを運用する際、課題が2つありました。

- **サーバーセキュリティ**: サーバーがあるから悩む => サーバーレス
- **開発環境のコスト**: 利用していない時に止めたい => サーバーレス

とりあえず、クラウドフォーメーションのテンプレートを使いまわしていたのですが、様々な問題(1)に直面し、なかなか簡単な環境作成とはなりませんでした。
{.annotate}

1.  !!! failure "様々な問題"
    - Django側に同じ設定を書く必要がある
    - コピペを間違える（yamlがややこしすぎる）
    - クラウドフォーメーションを削除しても一部リソースが残る（S3バケットとか）
    - 依存関係がややこしく、作成順を間違える

    ??? question "自分が悪くない？"
        いや、間違えさせる仕組みが悪い:angry:


そうしている中で、「そもそも、やりたいことってこんな複雑なんだっけ？」という疑問が湧き、設定したい内容を tomlで書いてみました。

5行ぐらいでした。

そのtomlを読み込んでインフラ構築を行うライブラリを作成した結果が、magic-pocket です。

途中、tomlが複雑になりすぎ(1)、yamlに変更しようかとも思いましたが、それならクラウドフォーメーションでいいじゃん、ということで複雑な機能を開発するのは止めて、設定ファイルはtomlになっています。
{.annotate}

1. 実際に設定したい情報は少なくても、ある程度AWSのリソースと対応させた方が分かりやすかったため。寄せすぎて、劣化クラウドフォーメーションになりそうでした。

??? question "なぜFargateでなくLambda？"
    最初は順当に Fargate を使いましたが、私が個人で保守するのは厳しいと感じました。

    `設定が分からない`
    :   特にヘルスチェック周りの設定が理解できませんでした。最初にDBに接続してmigrationを行いたいのに、ヘルスチェックが通らず詰みました。

    `インスタンスが立ち上がるのが遅い`
    :   20分待ってやっと設定エラーで動かない事が分かる、という地獄に何度も会いました。
        また、せっかくサーバーレスなのに、アクセスにスパイクがあるとレスポンスが出来ない、というのは残念です。
        当然出来ると思い立ち上げたら、いきなり落ちて愕然としました。


!!! warning annotate "固定費は必要"
    以下は、無視できない固定費として必要です。

    `NAT gateway`
    :   EFS(cache)、Neonに接続可能なIP制限、RDSなどで必要。
        dev環境を大量に作るなら、共通化するか、そもそも作らないか検討が必須。

        magic-pocketでは、同プロジェクト内であれば、別環境でも共有する設定が可能。

    `SecretsManager`
    :   個数に対する従量課金ではあるが、気軽に作りすぎると無視できないコストになる。
        可能な場合に保存場所を共通化すれば良い。

        magic-pocketでは、同プロジェクト内であれば、別環境でも共有する設定が可能。(1)

    `Neon`
    :   月額サブスク料金。1アカウントで複数プロジェクト使えるので、RDSと比較すれば十分安い。

1. 当然、利用する値は環境ごとに異なります。ただし、レコードを共有するため、値を取得する権限は共有されます。
