LoginSignup
5
4

More than 1 year has passed since last update.

【AWS】Django環境をEC2+ELB+RDSで構築してみた

Last updated at Posted at 2021-09-08

2021/9/20 Webサーバをプライベートサブネットに配置する構成に変更
2021/9/23 カスタムAMIを使用した起動テンプレートの作成について追記

はじめに

Djangoの実行環境を構築する機会があったため、せっかくなので現在学習を進めているAWSに絡めて構築してみようと思います。
※AWSがメインの内容となるため、Django実行環境についてはさらっと記載します。
※Django実行環境については独学となるのでご容赦ください...

構成図

以下のような構成を目指します。
diagram01_v2.png

EC2インスタンス OS:Amazon Linux 2
Webサーバ(リバースプロキシ):Nginx
APサーバ(WSGIサーバ):Gunicorn
データベース(RDS):MySQL

  • Nginx+GunicornをEC2インスタンスにインストール
  • データベースとしてマルチAZ構成のRDS(MySQL)を使用
  • EC2起動時にユーザーデータによって、Django環境構築を実行
  • EC2インスタンスの起動テンプレートを作成し、Auto Scaling グループを作成
  • ELBを作成し、EC2インスタンスへのトラフィックをロードバランシング
  • CloudWatchでAuto Scaling グループのCPU使用率に基づいたアラームを設定し、CPU使用率によってAuto Scaling グループ内のEC2インスタンスの数が増減するように設定

※リソースはすべて東京リージョンに作成します。

作業環境

macOS Big Sur バージョン 11.4

ネットワーク/セキュリティグループ/踏み台サーバ 作成

まずはAWS内でのネットワーク環境とELB、EC2インスタンス、RDSそれぞれにどういった通信を許可するかを定義するためのセキュリティグループを作成していきます。
また、後の手順でWebサーバにSSH接続するための踏み台サーバを用意します。

ネットワークを作成

AWS上にネットワークを作成します。
作成するものは以下となります。

  • VPC x 1
  • インターネットゲートウェイ x 1
  • NAT ゲートウェイ x 1
  • ELB用パブリックサブネット x 2 (同VPC、別AZ)
  • Webサーバ用プライベートサブネット x 2 (同VPC、別AZ)
  • RDS用プライベートサブネット x 2 (同VPC、別AZ)

基本的な作成・設定手順は以前作成した以下の記事をご参照ください。

セキュリティグループを作成

ELB、踏み台サーバ、Webサーバ、RDSに適用するセキュリティグループを作成します。
ELB用セキュリティグループはインバウンドで以下を許可するように作成します。

  • HTTP (Source:マイIP)

踏み台サーバ用セキュリティグループはインバウンドで以下を許可するように作成します。

  • SSH (Source:マイIP)

Webサーバ用セキュリティグループはインバウンドで以下を許可するように作成します。

  • HTTP (Source:ELB用セキュリティグループ)
  • SSH (Source:踏み台サーバ用セキュリティグループ)

RDS用セキュリティグループはインバウンドで以下を許可するように作成します。

  • MYSQL/Aurora (Source:Webサーバ用セキュリティグループ)
踏み台サーバを作成

踏み台サーバ用に1台のEC2インスタンスを起動します。
今回はELB用に作成したパブリックサブネットに配置し、踏み台サーバ用に作成したセキュリティグループを適用します。

構成図

ネットワーク作成後の構成図は以下の通りです。
diagram03_v2.png

RDS 作成

RDS(Relational Database Service)とは
  • AWSがPaaSサービスとして提供するリレーショナルデータベース
  • MySQL、MariaDB、PostgreSQL、Oracle、SQL Serverなどの様々なデータベースエンジンに対応
  • 他のAZ(アベイラビリティーゾーン)にレプリカを配置するマルチAZ構成を取ることができる
サブネットグループを作成

RDSをVPC・サブネットに配置するためには事前にサブネットグループの作成が必要となります。

AWS Management Consoleにログインし、RDSのダッシュボードを開きます。
画面左ツリーの[サブネットグループ]をクリックし、サブネットグループ一覧を表示します。
スクリーンショット 2021-07-10 15.07.18.png

画面右上の[DB サブネットグループを作成]をクリックします。
スクリーンショット 2021-07-10 15.34.06.png

名前にサブネットグループの名前、VPCにサブネットグループに使用するサブネットが存在するVPCを選択します。
スクリーンショット 2021-07-10 15.34.55.png

アベイラビリティーゾーンで追加するサブネットを含むAZを選択後、サブネットで追加するサブネットを選択し、[作成]をクリックします。
スクリーンショット 2021-09-20 12.07.31.png

2つ以上のアベイラビリティーゾーンでサブネットグループを構成しないと以下のエラーが発生し、作成できません。

スクリーンショット 2021-07-10 15.35.23.png

データベースを作成

サブネットグループが作成できたら、画面左ツリーの[データベース]をクリックし、データベース一覧を表示します。
一覧画面右上の[データベースの作成]をクリックします。

データベース作成ウィザードが開きます。
今回は以下の設定でデータベースを作成します。
設定が入力・選択できたら、[データベースの作成]をクリックします。

項目
データベース作成方法 標準作成
エンジンのタイプ MySQL
テンプレート 無料利用枠
DBインスタンス識別子 django-database
マスターユーザー名 admin
マスターパスワード 任意のパスワード
DBインスタンスクラス db.t2.micro
VPC 作成したVPC
サブネットグループ 作成したサブネットグループ
パブリックアクセス なし
VPC セキュリティグループ 作成したRDS用セキュリティグループ
アベイラビリティーゾーン ap-northeast-1a
データベースポート 3306
最初のデータベース名 mysite

※記載のない項目はデフォルトとなります。

RDSが作成できたらEC2インスタンス側のDjango実行環境を構築していきます。
今回は起動テンプレート作成時にユーザーデータを使用することでDjango環境構築を行います。
まずはそのための事前準備を行っていきます。

Djangoプロジェクト 作成

基本的に以下のDjangoチュートリアルに沿って作成を進めます。

今回のAWS構成に関連する部分、チュートリアル通りに作業が進まなかった部分等を以下で補足していきます。

データベース設定を変更

settings.py内のデータベース設定を変更する際に作成したRDSの設定情報を入力します。

settings.py
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mysite',
        'USER': 'admin',
        'PASSWORD': '<adminのパスワード>',
        'HOST': '<RDSのエンドポイント>',
        'PORT': '3306',
    }
}
開発用サーバー起動

開発用サーバーを起動する際に以下のエラーが発生しました。

ec2
$ python3 manage.py runserver

以下のエラーが発生
django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module.
Did you install mysqlclient?

どうやらmysqlclietモジュールをインストールする必要がある様子。
pip3でインストールを実行してみます。

ec2
$ pip3 install mysqlclient

以下のエラーが発生
ERROR: Command errored out with exit status 1: python setup.py egg_info Check the logs for full command output.

以下を参考にしたところ、mysqlclientモジュールをインストールすることができました。

改めて開発用サーバーを起動します。
警告は出ていますが、開発用サーバーを起動することができました。

ec2
$ python3 manage.py runserver

Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).

You have 18 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions.
Run 'python manage.py migrate' to apply them.
July 18, 2021 - 08:22:04
Django version 3.2.5, using settings 'mysite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
ブラウザからアプリケーションにアクセス

外部からアクセスできるように開発用サーバーを起動する際にオプションを指定します。

ec2
$ python3 manage.py runserver 0:8000

EC2インスタンスのパブリックIPアドレスの8000番ポートに対してアクセスしましたが、デフォルト設定のままだと以下のエラーが発生します。

ec2
Invalid HTTP_HOST header: '<EC2インスタンスのパブリックIPアドレス>:8000'. You may need to add '<EC2インスタンスのパブリックIPアドレス>' to ALLOWED_HOSTS.

settings.pyの「ALLOWED_HOSTS」の値を変更することでアクセスできるようになります。

settings.py
ALLOWED_HOSTS = ["*"]
GitHubにDjangoプロジェクトをアップロード

チュートリアルに従って作成したDjangoプロジェクトをGitHubにアップロードしておきます。
後ほど、ユーザーデータの処理の中でDjangoプロジェクトをGitHubからダウンロードします。

Djangoパラメータファイル 作成

RDSへの接続情報などをDjangoプロジェクト内のsettings.pyに記載していましたが、別ファイル「settings_secret.py」を作成しそちらに情報を転記しました。
settings_secret.py は .gitignore を使用してGit管理対象外とします。

settings_secret.py
SECRET_KEY = '<プロジェクト作成時に生成されるキー>'

DB_NAME = 'mysite'
DB_USER = 'admin'
DB_PASS = '<adminのパスワード>'
DB_HOST = '<RDSのエンドポイント>'
DB_PORT = '3306'
settings.py
from .settings_secret import *

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': DB_NAME,
        'USER': DB_USER,
        'PASSWORD': DB_PASS,
        'HOST': DB_HOST,
        'PORT': DB_PORT,
    }
}

settings.py 設定変更

settings.py 内の「DEBUG」の値を変更し、「STATIC_ROOT」を追加します。

settings.py
DEBUG = False

STATIC_ROOT = '/usr/share/nginx/html/static'

Gunicornサービスユニットファイル 作成

Gunicornをsystemdに登録し、サービスとして扱うためにサービスユニットファイルを作成します。

Gunicornサービスユニットファイルを作成

以下を参考にGunicornをsystemdに登録するためのサービスユニットファイルを作成します。

gunicorn.service
[Unit]
Description=gunicorn daemon
After=network.target

[Service]
Type=notify
PIDFile=/run/gunicorn/pid
User=ec2-user
Group=ec2-user
RuntimeDirectory=gunicorn
WorkingDirectory=/home/ec2-user/mysite
ExecStart=/usr/local/bin/gunicorn --workers 3 --bind=localhost:8000 mysite.wsgi
ExecReload=/bin/kill -s HUP $MAINPID
ExecStop=/bin/kill -s TERM $MAINPID
KillMode=mixed
TimeoutStopSec=5
PrivateTmp=true
Restart=always

[Install]
WantedBy=multi-user.target

Nginx設定ファイル 作成

NginxとGunicornを連携させるためにNginxの設定を編集します。
デフォルトでは /etc/nginx/conf.d に設定ファイル(.conf)を配置すると、設定として読み込まれます。
※/etc/nginx/nginx.conf のhttpディレクティブ内の「include /etc/nginx/conf.d/*.conf」によって読み込まれます。

以下を参考に設定ファイルを作成します。

mysite.conf
server {
  listen 80;
  server_name ec2-localip; → ユーザーデータ処理時に実際のローカルIPアドレスに置換

  location /static { 
    alias /usr/share/nginx/html/static;
  }

  location / {
    proxy_pass http://localhost:8000;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_set_header X-Forwarded-Proto $scheme;
  }
}

Git認証情報ファイル 作成

ユーザーデータ処理の中でGitHubリポジトリからDjangoプロジェクトをダウンロードするにあたって、処理中に対話型でユーザー・パスワードを求められないようにします。
実行ユーザーのホームディレクトリに「.netrc」というファイルを作成することで、ファイルに記述した認証情報を使用することができます。

.netrc
machine github.com
login <GitHubのユーザー名>
password <ユーザーのパスワード or Personal Access Token>

※Personal Access Tokenの作成は以下を参照しました。

S3バケット 作成・ファイル配置

S3バケットを作成し、ここまで作成した以下のファイルを配置します。

  • Djangoパラメータ用ファイル(settings_secret.py)
  • Gunicornサービスファイル(gunicorn.service)
  • Nginx設定ファイル(mysite.conf)
  • Git認証情報ファイル(.netrc)

IAMロール 作成

EC2インスタンスからS3へのアクセスを許可するためのIAMロールを作成します。
以下の設定でIAMロールを作成します。

項目
信頼されたエンティティ EC2
ポリシー AmazonS3FullAccess
ロール名 任意の名前

これでDjango環境構築の事前準備は完了です。

起動テンプレート 作成

Auto Scaling グループで使用する起動テンプレートを作成していきます。
EC2画面で[テンプレートの起動]から起動テンプレート一覧を開きます。
スクリーンショット 2021-09-04 14.09.53.png

画面右上の[起動テンプレートを作成]をクリックします。
スクリーンショット 2021-09-04 14.10.13.png

起動テンプレートの作成画面となります。
今回は以下の設定で起動テンプレートを作成します。
設定が入力・選択できたら、[起動テンプレートを作成]をクリックします。

項目
起動テンプレート名 django-launch-template
テンプレートバージョンの説明 任意
Auto Scaling のガイダンス 有効
AMI Amazon Linux 2 (x86)
インスタンスタイプ t2.micro
キーペア 任意のキーペア
ネットワーキングプラットフォーム Virtual Private Cloud (VPC)
ストレージ 変更なし
ネットワークインターフェイス 1つ追加 ※詳細は下に記載
IAM インスタンスプロフィール S3アクセス用IAMロール
ユーザーデータ ※詳細は下に記載

【ネットワークインターフェイス】

項目
デバイスインデックス 0
ネットワークインターフェイス New interface
セキュリティグループ Webサーバ用セキュリティグループ
パブリック IP の自動割り当て 無効化

【ユーザーデータ】
ユーザーデータにより必要パッケージのインストールやファイル・ディレクトリの権限設定、GitHub・S3から必要なファイルのダウンロードなどの処理を行っていきます。
※GitHubリポジトリのURL、S3バケットの名前は置き換えて使用してください。

userdata
#!/bin/bash
#必要なパッケージ・モジュールをインストール
yum -y update
yum -y install python3 git python3-devel mysql mysql-devel gcc
pip3 install django
pip3 install mysqlclient
pip3 install gunicorn
amazon-linux-extras install nginx1

#Nginxサービスの自動起動設定・開始
systemctl enable nginx
systemctl start nginx

#Staicファイル用ディレクトリの作成
mkdir /usr/share/nginx/html/static

#git clone用認証情報ファイルのダウンロード
aws s3 cp s3://<S3のバケット名>/.netrc /root/.netrc

#DjangoプロジェクトをGitHubから取得
git clone <GitHubリポジトリのURL> /home/ec2-user/mysite

#Djangoプロジェクトの所有者をec2-userに変更
chown -R ec2-user:ec2-user /home/ec2-user/mysite

#setting.py内で使用するパスワード等を記述した外部ファイルをダウンロード
aws s3 cp s3://<S3のバケット名>/settings_secret.py /home/ec2-user/mysite/mysite/settings_secret.py

#上記ファイルの所有者をec2-userに変更
chown ec2-user:ec2-user /home/ec2-user/mysite/mysite/settings_secret.py

#Gunicornのサービスユニットファイルをダウンロード
aws s3 cp s3://<S3のバケット名>/gunicorn.service /etc/systemd/system/gunicorn.service

#Gunicornサービスユニットファイルの権限を変更
chmod 644 /etc/systemd/system/gunicorn.service

#Gunicornサービスを自動起動設定・開始
systemctl enable gunicorn.service
systemctl start gunicorn.service

#Nginx設定ファイルをダウンロード・ローカルIPアドレスを置換
aws s3 cp s3://<S3のバケット名>/mysite.conf /etc/nginx/conf.d/mysite.conf
localip=`curl http://169.254.169.254/latest/meta-data/local-ipv4`
sed -i -e "s/ec2-localip/$localip/g" /etc/nginx/conf.d/mysite.conf

#Nginxサービスを再起動
systemctl restart nginx

#StaticファイルをSTATIC_ROOTに記述したパスに配置
cd /home/ec2-user/mysite
python3 manage.py collectstatic

#Staticファイル用ディレクトリの所有者をec2-userに変更
chown -R ec2-user:ec2-user /usr/share/nginx/html/static

ユーザーデータによる必要パッケージのインストールやファイル・ディレクトリの権限設定、GitHub・S3から必要なファイルのダウンロードなどの処理を事前に反映させたカスタムAMIから起動テンプレートを作成することも可能です。

カスタムAMIの作成については別記事として記載しました。

また、カスタムAMIを使用する場合は起動テンプレートを以下の設定で作成します。

項目
起動テンプレート名 django-launch-template
テンプレートバージョンの説明 任意
Auto Scaling のガイダンス 有効
AMI 作成したカスタムAMI
インスタンスタイプ t2.micro
キーペア 任意のキーペア
ネットワーキングプラットフォーム Virtual Private Cloud (VPC)
ストレージ 変更なし
ネットワークインターフェイス 1つ追加 ※詳細は下に記載
ユーザーデータ ※詳細は下に記載

※S3からのファイルダウンロードが不要となるため、IAMロールは適用しません。

【ネットワークインターフェイス】

項目
デバイスインデックス 0
ネットワークインターフェイス New interface
セキュリティグループ Webサーバ用セキュリティグループ
パブリック IP の自動割り当て 無効化

【ユーザーデータ】
Nginx設定ファイル内のserver_nameの値についてはWebサーバごとにローカルIPアドレスに置換する必要があるため、ユーザーデータで処理します。

userdata
#!/bin/bash
#Nginx設定ファイルのローカルIPアドレスを置換
localip=`curl http://169.254.169.254/latest/meta-data/local-ipv4`
sed -i -e "s/ec2-localip/$localip/g" /etc/nginx/conf.d/mysite.conf

#Nginxサービスを再起動
systemctl restart nginx

Auto Scaling グループ 作成

次に Auto Scaling グループを作成します。
EC2管理画面で[Auto Scaling グループ]からAuto Scaling グループ画面を開きます。
スクリーンショット 2021-09-04 14.12.36.png

[Auto Scaling グループの作成]をクリックします。
スクリーンショット 2021-09-04 14.12.51.png

Auto Scaling グループ名で名前を入力後、起動テンプレートで作成した起動テンプレートを選択し、[次へ]をクリックします。
スクリーンショット 2021-09-04 14.13.59.png

VPCで事前に作成したVPCを選択後、サブネットで2つのWebサーバ用プライベートサブネットを選択し、[次へ]をクリックします。
スクリーンショット 2021-09-20 12.27.28.png

ロードバランシングで[新しいロードバランサーにアタッチ]を選択後、以下の設定を行い、[次へ]をクリックします。
スクリーンショット 2021-09-04 14.15.10.png

項目
ロードバランサーのタイプ Application Load Balancer
ロードバランサーの名前 django-LB
ロードバランサーのスキーム Internet-facing
VPC 作成したVPC
アベイラビリティーゾーンとサブネット ELB用パブリックサブネット
プロトコル HTTP
ポート 80
デフォルトルーティング (転送先) ターゲットグループを作成する
新しいターゲットグループ名 django-TG
ヘルスチェックのタイプ EC2, ELB
ヘルスチェックの猶予期間 300 秒

今回はEC2インスタンスは最小2台、最大4台となるようにスケーリングするため、グループサイズでは以下のように設定します。
設定が完了したら[次へ]をクリックします。

項目
希望する容量 2
最小キャパシティ 2
最大キャパシティ 4

通知は今回はなしで進めますので、そのまま[次へ]をクリックします。

任意でタグを設定し、[次へ]をクリックします。

設定内容を確認し、[Auto Scaling グループを作成]をクリックします。

ターゲットグループ/ロードバランサー 設定変更

このままだとターゲットグループのヘルスチェックに失敗する状態となります。
原因は以下の2つです。

  • ヘルスチェックのパスからのレスポンスコードが「200」でない
  • ロードバランサーからEC2インスタンスへのHTTPが許可されていない

それぞれの問題をクリアするために対応を実施していきます。

ヘルスチェック設定を変更

Auto Scaling グループ作成ウィザード内でターゲットグループを作成したことにより、ヘルスチェック設定がデフォルト設定となっています。
今回の構成に合わせて設定を変更していきます。

EC2管理画面で[ターゲットグループ]からターゲットグループ一覧を開きます。
スクリーンショット 2021-09-04 14.17.23.png

先ほど作成されたターゲットグループを選択し、画面下部で[Health checks]タブを選択後、[Edit]をクリックします。
スクリーンショット 2021-09-04 14.17.54.png

以下のように設定を変更し、[Save changes]をクリックします。
※この画面では表記が英語になっています。

項目
Health check protocol HTTP
Health check path /polls/
Port 80
Healty threshold 2
Unhealth threshold 2
Timeout 5 seconds
Interval 10 seconds
Success code 200
ロードバランサーのセキュティグループを変更

Auto Scaling グループ作成ウィザード内でロードバランサーを作成したことにより、VPCデフォルトのセキュリティグループが適用されています。
こちらも今回の構成に合わせて設定を変更していきます。

EC2管理画面で[ロードバランサー]からロードバランサー一覧を開きます。
スクリーンショット 2021-09-04 14.18.44.png

先ほど作成されたロードバランサーを選択し、[アクション]-[セキュリティグループの編集]をクリックします。
スクリーンショット 2021-09-04 14.19.10.png

VPCデフォルトのセキュリティグループの選択を外し、ELB用セキュリティグループを選択後、[保存]をクリックします。
スクリーンショット 2021-09-04 14.19.29.png

ヘルスチェック/アクセスを確認

ターゲットグループのヘルスチェック状態を確認します。
ターゲットグループ一覧でターゲットグループを選択し、画面下部の[Targets]タブをクリックします。
登録済みのターゲットの一覧が表示されるので、すべてのEC2インスタンスでHealth statusが「healty」になっていることを確認します。
スクリーンショット 2021-09-04 14.20.51.png

ヘルスチェックが成功しているのを確認できたら、ブラウザから Django アプリケーションへのアクセスを確認します。
ブラウザで「http://ロードバランサーのDNS名/polls」にアクセスし、Djangoアプリケーションが表示されることを確認します。

構成図

Auto Scaling グループ作成後の構成図は以下の通りです。
スケーリングポリシーを設定していないので、EC2インスタンスは希望する容量で指定した2台となっています。
diagram04_v2.png

RDS マルチAZ構成

RDSをマルチAZ構成とします。

RDS管理画面で[データベース]からデータベース一覧を開きます。
マルチAZ構成とするデータベースを選択し、画面上部の[変更]をクリックします。
スクリーンショット 2021-09-04 14.25.51.png

変更画面が開くので、マルチ AZ 配置で「スタンバイインスタンスを作成する (本稼働環境向けに推奨)」を選択し、[続行]をクリックします。
スクリーンショット 2021-09-04 14.26.33.png

変更を適用するタイミングで「すぐに適用」を選択し、[DB インスタンスを変更]をクリックします。
スクリーンショット 2021-09-04 14.26.55.png

ステータスが「利用可能」、マルチ AZが「あり」に変更されることを確認します。
スクリーンショット 2021-09-04 14.37.55.png

構成図

RDSマルチAZ構成後の構成図は以下の通りです。
diagram05_v2.png

CloudWatch 監視設定

EC2インスタンスのCPU使用率に応じて、Auto Scaling グループ内のEC2インスタンス数を増減するための監視設定を行っていきます。

アラームを作成

まずは Auto Scaling グループのCPU使用率が高い場合のアラームを作成します。
CloudWatch管理画面で[アラーム]からアラーム一覧を開きます。
スクリーンショット 2021-09-04 14.38.33.png

[アラームの作成]をクリックします。
スクリーンショット 2021-09-04 14.38.46.png

[メトリクスの選択]をクリックし、[EC2]-[Auto Scaling グループ別]を選択します。
スクリーンショット 2021-09-04 14.39.03.png
スクリーンショット 2021-09-04 14.39.18.png
スクリーンショット 2021-09-04 14.39.29.png

先ほど作成した Auto Scaling グループのメトリクス[CPUUtilization]を選択し、[メトリクスの選択]をクリックします。
スクリーンショット 2021-09-04 14.39.48.png

条件を設定し、[次へ]をクリックします。

項目
しきい値の種類 静的
CPUUtilization が次の時... より大きい
...よりも 70
アラームを実行するデータポイント 1 / 1
欠落データの処理 欠落データを不正 (しきい値を超えている) として処理

通知は今回はなしで進めますので、通知内の[削除]をクリック後、[次へ]をクリックします。
スクリーンショット 2021-09-04 14.40.45.png

アラーム名で名前を入力後、[次へ]をクリックします。
スクリーンショット 2021-09-04 14.41.08.png

設定内容を確認し、[アラームの作成]をクリックします。

次に Auto Scaling グループのCPU使用率が低い場合のアラームを作成します。
以下の条件設定を使用して、同様の手順でアラームを作成します。

項目
しきい値の種類 静的
CPUUtilization が次の時... より低い
...よりも 30
アラームを実行するデータポイント 1 / 1
欠落データの処理 欠落データを見つかりませんとして処理
スケーリングポリシーを設定

Auto Scaling グループ にスケーリングポリシーを設定していきます。
Auto Scaling グループ一覧画面で作成した Auto Scaling グループを選択し、画面下部の[自動スケーリング]タブを選択します。
[Create dynamic scaling policy]をクリックします。
スクリーンショット 2021-09-04 14.43.30.png

まずはCPU高負荷時のスケーリングポリシーを作成します。
以下の設定を行い、[作成]をクリックします。

項目
ポリシータイプ シンプルなスケーリング
スケーリングポリシー名 CPU_add
CloudWatch アラーム 作成したCPU高負荷時のアラーム
アクションを実行 追加: 1 キャパシティユニット
別のスケーリングアクティビティを許可するまでの秒数 30 秒

次にCPU低負荷時のスケーリングポリシーを作成します。
以下の設定で作成します。

項目
ポリシータイプ シンプルなスケーリング
スケーリングポリシー名 CPU_remove
CloudWatch アラーム 作成したCPU低負荷時のアラーム
アクションを実行 削除: 1 キャパシティユニット
別のスケーリングアクティビティを許可するまでの秒数 30 秒
構成図

スケーリングポリシー設定後の構成図は以下の通りです。
diagram06_v2.png

負荷テスト

WebサーバにCPU負荷をかけて、自動スケーリングをテストします。
踏み台サーバ経由でWebサーバにSSH接続します。
SSH接続については以下を参照してください。

以下のコマンドを使用してCPU負荷をかけていきます。
※並列で負荷をかけるために複数回コマンドを実行しています。

ec2
$ yes >> /dev/null &
[1] 8457
$ yes >> /dev/null &
[2] 8459
$ yes >> /dev/null &
[3] 8460
$ yes >> /dev/null &
[4] 8461

top コマンドで確認すると、CPU使用率が100%近くになっていることが確認できます。

ec2
top - 08:24:23 up 17 min,  1 user,  load average: 2.68, 0.81, 0.31
Tasks:  94 total,   6 running,  52 sleeping,   0 stopped,   0 zombie
%Cpu(s): 99.7 us,  0.3 sy,  0.0 ni,  0.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  1006892 total,   258452 free,   227764 used,   520676 buff/cache
KiB Swap:        0 total,        0 free,        0 used.   625988 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S %CPU %MEM     TIME+ COMMAND                                   
 8457 ec2-user  20   0  114636    792    728 R 24.9  0.1   0:19.60 yes                                       
 8459 ec2-user  20   0  114636    756    692 R 24.9  0.1   0:17.22 yes                                       
 8461 ec2-user  20   0  114636    780    716 R 24.9  0.1   0:16.21 yes                                       
 8460 ec2-user  20   0  114636    764    700 R 24.6  0.1   0:16.70 yes

同様の手順でもう一台のWebサーバにも負荷をかけ、アラームが発生するまで待機します。

CloudWatch管理画面で[アラーム]からアラーム一覧を開きます。
スクリーンショット 2021-09-04 14.54.35.png

CPU高負荷時のアラームの状態が「アラーム状態」になっていることを確認したら、EC2インスタンス画面を開き、EC2インスタンスが自動的に増えていることを確認します。
スクリーンショット 2021-09-04 14.57.23.png

Auto Scaling グループのアクティビティ履歴からも自動スケールアウトが実行されたログを確認することができます。
スクリーンショット 2021-09-04 14.58.08.png

自動スケールアウトの動作が確認できたら、WebサーバのCPU負荷を下げ、自動スケールインの動作を確認します。
負荷をかけているWebサーバにSSH接続し、負荷をかけているコマンドのプロセスを停止します。

ec2
$ kill 8457
$ kill 8459
$ kill 8460
$ kill 8461
※プロセス番号が連続している場合は kill {8459..8461} のようにまとめて指定することが可能です。

CloudWatch管理画面で[アラーム]からアラーム一覧を開きます。
スクリーンショット 2021-09-04 15.06.35.png

CPU低負荷時のアラームの状態が「アラーム状態」になっていることを確認したら、Auto Scaling グループのアクティビティ履歴を確認します。
スクリーンショット 2021-09-04 15.07.49.png

スケールインの場合には即時EC2インスタンスが削除されると利用しているユーザーが困るため、Drainingと呼ばれる期間が設けられています。

Auto Scaling グループのアクティビティ履歴からもステータスがDrainingであるログを確認することができます。
Drainingの期間はターゲットグループによって設定されています。
※デフォルトは5分

Drainingの期間が経過すると、EC2インスタンスが削除されたことがアクティビティ履歴で確認できます。
スクリーンショット 2021-09-04 15.16.55.png

また、EC2インスタンス画面でもEC2インスタンスが削除されていることを確認します。
スクリーンショット 2021-09-04 15.17.11.png

あとがき

この記事は CloudTech の課題として作成しました。
動画やハンズオン等で学習を進めることができるので、AWS初学者にはおすすめです。

5
4
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
5
4