AWSにDjangoの環境を整えていく03(ALB)

こんにちは。
株式会社クラスアクト インフラストラクチャ事業部の大塚です。

今回は前回作成したEC2+RDSにALBを追加していき、EC2に負荷分散的なことをしていきたいと思います。

他の記事は以下の記事で別途管理しております為、適宜ご覧ください。

https://qiita.com/ohtsuka-shota/items/4b80538569b81f8c19a6

# 環境イメージ
前回構築した環境にpublic-subnetをもう1つ作成し、そこにDjangoをインストールしたEC2を1つ用意します。このEC2はRDSに繋げています。
このあと、ALB(Application Load Balancer)をデプロイします。
最後にALBをターゲットにして、Webブラウジングが出来るかを確認していきたいと思います。
![aws-django01-ページ9.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/f1c050e1-24f2-44fe-118b-f62ab9f31881.png)


# 構築
## subnetを1つ作成する
public subnetを1つデプロイします。
- VPC
    - vpc：classact-vpc
- サブネットの設定
    - サブネット名：classact-public-subnet03
    - AZ：ap-northeast-1c
    - CIDR：192.168.3.0/24
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/26311f7a-acfb-3159-3619-1f5576335bf2.png)
作成されたことを確認します。
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/b7839f0e-1806-aaba-cc3b-6c4211751549.png)

## EC2のデプロイと環境構築及びRDSとの紐づけ
EC2をデプロイします。デプロイ先のsubnetは上記で作成したものです。
後は前デプロイした状態と同じです。
名前：classact-ec2-django-other01
サブネット：classact-public-subnet03
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/6161f582-b15d-fd34-410c-9030ebc33ff8.png)

デプロイが出来たら今度はRDSの管理画面に移動してEC2と紐づけをしていきます。
Djangoで使用しているRDSを選択し、EC2接続のセットアップを押下します。
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/c293dfd8-8a81-bfda-98f9-57c2334b1ddf.png)
上記でデプロイしたインスタンスを選択します。
![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/b556c992-f669-904c-f419-8874fcdbc16c.png)
確認して次に進みます。
![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/02a2f13b-6611-018f-3501-59e329660dbf.png)
RDSの欄の1つである接続されたコンピューティングリソースにEC2インスタンスが追加されていることを確認します。
![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/96a30810-319b-0633-1230-f557997d3fcb.png)

EC2の設定を入れ込んでいきます。各コマンドの内容は省略します。
DB周りの設定は以前設定済みですので、今回は実行しません。settings.pyの中身も前回のと同様です。
※本当であればAMIを作ってデプロイしたほうが良いのかなぁ・・・とは思います。
```
root@ip-192-168-3-183:~# apt update && apt upgrade -y 
root@ip-192-168-3-183:~# python3 -V
Python 3.10.12
root@ip-192-168-3-183:~# apt install python3-pip -y
root@ip-192-168-3-183:~# pip3 -V
pip 22.0.2 from /usr/lib/python3/dist-packages/pip (python 3.10)
root@ip-192-168-3-183:~# apt install python3-dev default-libmysqlclient-dev pkg-config mysql-client -y
root@ip-192-168-3-183:~# pip3 install django mysqlclient
root@ip-192-168-3-183:~# django-admin startproject classactPJ
root@ip-192-168-3-183:~# ls
classactPJ  snap
root@ip-192-168-3-183:~# cd classactPJ/
root@ip-192-168-3-183:~/classactPJ# ls
classactPJ  manage.py
root@ip-192-168-3-183:~/classactPJ# cd classactPJ/
root@ip-192-168-3-183:~/classactPJ/classactPJ# ls
__init__.py  asgi.py  settings.py  urls.py  wsgi.py
root@ip-192-168-3-183:~/classactPJ/classactPJ# vi settings.py 
root@ip-192-168-3-183:~/classactPJ/classactPJ# cd ..
root@ip-192-168-3-183:~/classactPJ# python3 manage.py runserver 0.0.0.0:80
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
April 16, 2024 - 20:22:06
Django version 5.0.4, using settings 'classactPJ.settings'
Starting development server at http://0.0.0.0:80/
Quit the server with CONTROL-C.
```

## ALBのターゲットグループを作成する
EC2の管理画面の左タブにターゲットグループがありますので押下します。
デフォルトだと何も表示されてないと思います。作成していきます。
![08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/e27416ad-ff3b-c768-3da4-68837222f5c1.png)
以下の設定を入れます。ヘルスチェックはデフォルトでいったん進めます。
- 基本的な設定
    - ターゲットタイプの選択：インスタンス
    - ターゲットグループ名：classact-tg-django
    - プロトコル：HTTP
    - IPアドレスタイプ：IPv4
    - VPC：classact-vpc
    - プロトコルバージョン：HTTP1

![09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/74273e69-548d-c7d6-4937-6a6b2ee6cc45.png)
以下の画面が表示されます。
使用可能なインスタンスの欄に今までにデプロイしたEC2が2つ表示されていると思います。
それぞれにチェックを入れて、画面中央付近にある"保留中に以下を含める"を押下します。
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/9010da3e-087b-eb75-c849-e7ceb886feab.png)
画面下にあるターゲットを確認欄にEC2が表示されると思います。
このまま次に進みます。
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/22b21afc-e8fc-201a-07fa-a71cee8f4724.png)
ターゲットグループが作成されていることを確認します。
![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/4b5633b4-c836-6cad-ad7a-6632d873456a.png)

## ALBをデプロイして接続テストをする（一部失敗アリ）
EC2管理画面の左にロードバランサータブを押下します。
ロードバランサーの作成を押下します。
![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/b01aeb6e-19cd-9770-e528-8211c8283000.png)
ロードバランサーのタイプを聞かれます。今回はALBを選択します。
![14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/dd9b8fe7-62b2-7306-8ab9-4ff7b8ba6fc3.png)
以下の内容で設定していきます。
- 基本的な設定
    - 名前；classact-alb-django
    - スキーム：インターネット向け
    - IPアドレス：IPv4
- ネットワークマッピング
    - VPC：classact-vpc
    - マッピング
        - ap-northeast-1a
            - サブネット：classact-public-subnet01
        - ap-northeast-1c
            - サブネット：classact-public-subnet03
- セキュリティグループ：classact-sg-django
- リスナーとルーティング
    - プロトコル：HTTP
    - デフォルトアクション：classact-tg-django

![15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/8d476b47-bc10-ccb3-7bde-e281ff2e2f39.png)
![16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/693e9387-7ce0-9ba0-1270-51609083fd0b.png)
![17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/800abae6-aa45-5fac-691a-80722f24bfee.png)
![18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/74f39740-530c-ad83-01c8-68b6cb325dbe.png)
![19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/1a9c89de-cc0b-eff8-2e2f-cfd32008de6e.png)
ALBがデプロイされたことを確認します。
![20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/381f00e0-7b7a-bd94-796e-aef88ed2053e.png)
ALBのリソースマップ-新規タブを押下するとどこに通信が流れるかを確認することが出来ます。
![21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/b03f12fd-4f48-42d2-c238-6171867078c2.png)
ALBのDNS名でhttp接続をしてみるとALBを抜けてEC2のDjangoにアクセスできます。
これで問題なさそうに見えるのですが、管理画面にログインして色々操作しようとすると、遷移がバグります。具体的には何度も何度もログインを求められるようになります。
![22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/bc1911de-77f7-ec3c-e353-d985290e964c.png)
これはロードバランシング時にEC2インスタンス2つに対してバラバラにロードバランシングしてしまうためだと思われます。
わかりにくいと思いますが、以下がそのログになります。左がsubnet01にデプロイされたEC2のログ、右がsubnet03にデプロイされたEC2のログとなります。38~46秒あたりを見てみると双方に通信をしていることがわかります。これはターゲットグループのロードバランシングアルゴリズムがラウンドロビンになっていることによると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/8bcf7b3e-18b6-d98c-e267-74e1229a400a.png)


以下は完全に私のイメージですが、例えば赤矢印の流れでEC2にアクセスしてDjangoの管理画面に入った後、Django管理画面の別のページに遷移すると改めてロードバランシングされて青の矢印の流れで下のEC2にアクセスしてしまったとします。こっちの方ではログインをしていないので「ん？お前誰や！」的な話になって改めてログインを求められるのかなと。。。
この辺りは私の勉強不足感が否めません。。。
![aws-django01-ページ4.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/d021e090-ee86-4100-b39b-0863c4d8b050.png)
これを回避するために、同じEC2に接続し続けるように設定をしてあげる必要があります。

## 環境の修正
作成したターゲットグループのターゲット選択設定の維持設定を確認してみるとオフになっていることがわかります。（スクショ小さくて恐縮です。画面左少し下位です。）
この設定をオンにしてあげることで、最初にアクセスしたEC2に接続し続けるようになります。右上のアクションからターゲット属性編集を編集を押下します。
![23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/91bddea4-4455-850f-448f-06277baa8fb8.png)
維持設定の欄で、維持設定をオンにチェックマークを入れます。
維持設定タイプをロードバランサーがCookieを生成しましたにします。
![24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/54d19696-04cd-cb1e-5511-a5c3cbfff123.png)

この状態でALB経由でEC2に接続すると同じEC2に対して接続をし続けるようになります。
改めてログを見てみると、subnet03に対して接続をし続けることでログが明らかに増えていることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/07d7899a-cd9f-e168-e357-22f283a08b84.png)