フォーム読み込み中
皆さんこんにちは。クラウドエンジニアのKangです。
この記事では、Terraformを利用して必要なリソースをAWS上で構築し、EC2、NodeJS、RDS-MySQLを組み合わせることで、クラウドネイティブCovid19追跡 Webアプリをデプロイする方法を紹介していきます。
依然、新型コロナが猛威を振るっていますね。記事執筆時の2022年8月末現在でも、新型コロナ感染者数が日々増加し続いており、感染者数が気になる方は多くいらっしゃると思います。一方でタイムリーに感染者数の情報が入手できないこともあると思います。
この情報収集に関する課題をクラウドサービスを使って解決できたらと思い、「Covid-19 Tracker」をAWSにデプロイ、感染者数情報の収集する手順をご紹介したいと思います。
この「Covid-19 Tracker」は、有志の方たちがGitHubで公開している感染者数を収集・閲覧するためのウェブアプリケーションです。COVID-19 の拡散と影響を視覚化し、毎日の更新を購読し、統計を表示することができます。
これを利用すれば、すぐに最新の感染者数状況を把握できます。また、日本国内だけではなく、世界中の感染データも簡単に手に入れることができます。
また、デプロイにはTerraformを使い、「IaC (Infrastructure as Code)」の便利さ・素晴らしさも体感してもらいたいと思います。
実現するにあたって、Terraformを利用して必要なリソースをAWS上で構築し、EC2、NodeJS、RDS-MySQLを組み合わせることで、クラウドネイティブCovid19追跡 Webアプリをデプロイする方法を紹介させていただきます。
(Terraform がすでにインストールされている場合は、この手順をスキップしてください)
デスクトップに terraform CLI 環境をセットアップします。 Terraform CLI のセットアップ方法に関するチュートリアルについては下記のドキュメントを参照してください。
Install and configure Terraform on your computer
Terraform を初めて使用する場合は、Githubの alibabacloud-howto / terraform-templates を参照して、さまざまなオペレーティング システムに Terraform のインストール方法及び使い方を確認してください。 (どちらもAlibabaCloudのドキュメントで、今回の手順と直接関係ありませんが、とても参考になりました。)
以下に示すように、AWSコンソールにログインし、[セキュリティ認証情報] をクリックします。
[新しいアクセス キーの作成] をクリックします。 AccessKey が正常に作成されると、[アクセス キーの表示]により、アクセスキー IDとシークレットアクセスキーを確認できます。AWSAccessKeyID と AWSSecretKey は後で使用するので、メモしておいてください。
Terraform がインストールされている環境で以下のコマンドで2つのファイルが作成されます。
EC2にssh接続する際に必要になるので、先に作成しておきましょう。
$ ssh-keygen -t rsa -f covid19 -N ''
出力
Generating public/private rsa key pair. Your identification has been saved in covid19. Your public key has been saved in covid19.pub. The key fingerprint is: SHA256:DeQAbvjw3YynDp417c9DALmVWjiEsEoP4Tf80g68g1c root@ip-172-31-3-200.ap-northeast-1.compute.internal The key's randomart image is: +---[RSA 2048]----+ | ....+oo.. | |. o+. =++ | | +++o Bo | |..==+.o+.o | |. =oEo S.. | | . * + . | | . +..+ .. | | ...= o .. | | o . ..o. | +----[SHA256]-----+
$ aws configure --profile covid19
先程メモしたAWSAccessKeyID と AWSSecretKeyを入力します。
はじめに任意の作業ディレクトリに移動します。本記事は下記ディレクトリ構成で作成しています。
ディレクトリ構成
.
|-- terraform
| |-- provider.tf
| |-- vpc.tf
| |-- ec2.tf
| |-- terraform.output.tf
| |-- rds.tf
`-- ssh
|-- covid19
|-- covid19.pub
各種ファイル説明
ファイル名 | 役割 |
|---|---|
provider.tf | プロバイダーや、AccessKeyなどの定義ファイル |
ec2.tf | EC2の定義ファイル |
vpc.tf | VPCネットワークの定義ファイル |
terraform.output.tf | EC2のパブリックIPを出力するファイル |
rds.tf | RDSインスタンスの定義ファイル |
covid19 | SSH秘密鍵 |
covid19.pub | SSH公開鍵 |
provider.tf
# ====================
#
# Provider
#
# ====================
provider "aws" {
profile = "covid19"
region = "ap-northeast-1"
}
ec2.tf
# ====================
#
# AMI
#
# ====================
# 最新版のAmazonLinux2のAMI情報
data "aws_ami" "covid19" {
most_recent = true
owners = ["amazon"]
filter {
name = "architecture"
values = ["x86_64"]
}
filter {
name = "root-device-type"
values = ["ebs"]
}
filter {
name = "name"
values = ["amzn2-ami-hvm-*"]
}
filter {
name = "virtualization-type"
values = ["hvm"]
}
filter {
name = "block-device-mapping.volume-type"
values = ["gp2"]
}
filter {
name = "state"
values = ["available"]
}
}
# ====================
#
# EC2 Instance
#
# ====================
resource "aws_instance" "covid19" {
ami = data.aws_ami.covid19.image_id
vpc_security_group_ids = [aws_security_group.covid19.id]
subnet_id = aws_subnet.covid19.id
key_name = aws_key_pair.covid19.id
instance_type = "t2.micro"
tags = {
Name = "covid19"
}
}
# ====================
#
# Elastic IP
#
# ====================
resource "aws_eip" "covid19" {
instance = aws_instance.covid19.id
vpc = true
}
# ====================
#
# Key Pair
#
# ====================
resource "aws_key_pair" "covid19" {
key_name = "covid19"
public_key = file("./covid19.pub")
# 先程`ssh-keygen`コマンドで作成した公開鍵を指定
}
vpc.tf
# ====================
#
# VPC
#
# ====================
resource "aws_vpc" "covid19" {
cidr_block = "10.0.0.0/16"
enable_dns_support = true # DNS解決を有効化
enable_dns_hostnames = true # DNSホスト名を有効化
tags = {
Name = "covid19"
}
}
# ====================
#
# Subnet
#
# ====================
# Public
resource "aws_subnet" "covid19" {
cidr_block = "10.0.1.0/24"
availability_zone = "ap-northeast-1a"
vpc_id = aws_vpc.covid19.id
# trueにするとインスタンスにパブリックIPアドレスを自動的に割り当ててくれる
map_public_ip_on_launch = true
tags = {
Name = "covid19"
}
}
# Private
resource "aws_subnet" "private-db1" {
vpc_id = aws_vpc.covid19.id
cidr_block = "10.0.2.0/24"
availability_zone = "ap-northeast-1a"
tags = {
Name = "private-db1"
}
}
resource "aws_subnet" "private-db2" {
vpc_id = aws_vpc.covid19.id
cidr_block = "10.0.3.0/24"
availability_zone = "ap-northeast-1c"
tags = {
Name = "private-db2"
}
}
# ====================
#
# Internet Gateway
#
# ====================
resource "aws_internet_gateway" "covid19" {
vpc_id = aws_vpc.covid19.id
tags = {
Name = "covid19"
}
}
# ====================
#
# Route Table
#
# ====================
resource "aws_route_table" "covid19" {
vpc_id = aws_vpc.covid19.id
tags = {
Name = "covid19"
}
}
resource "aws_route" "covid19" {
gateway_id = aws_internet_gateway.covid19.id
route_table_id = aws_route_table.covid19.id
destination_cidr_block = "0.0.0.0/0"
}
resource "aws_route_table_association" "covid19" {
subnet_id = aws_subnet.covid19.id
route_table_id = aws_route_table.covid19.id
}
# ====================
#
# Security Group
#
# ====================
resource "aws_security_group" "covid19" {
vpc_id = aws_vpc.covid19.id
name = "covid19"
tags = {
Name = "covid19"
}
}
# インバウンドルール(ssh接続用)
resource "aws_security_group_rule" "in_ssh" {
security_group_id = aws_security_group.covid19.id
type = "ingress"
cidr_blocks = ["0.0.0.0/0"]
from_port = 22
to_port = 22
protocol = "tcp"
}
# インバウンドルール(pingコマンド用)
resource "aws_security_group_rule" "in_icmp" {
security_group_id = aws_security_group.covid19.id
type = "ingress"
cidr_blocks = ["0.0.0.0/0"]
from_port = -1
to_port = -1
protocol = "icmp"
}
# アウトバウンドルール(全開放)
resource "aws_security_group_rule" "out_all" {
security_group_id = aws_security_group.covid19.id
type = "egress"
cidr_blocks = ["0.0.0.0/0"]
from_port = 0
to_port = 0
protocol = "-1"
}
terraform.output.tf
# ====================
#
# Output
#
# ====================
# apply後にElastic IPのパブリックIPを出力する
output "public_ip" {
value = aws_eip.covid19.public_ip
}
rds.tf
# ====================
#
# RDS
#
# ====================
resource "aws_db_subnet_group" "praivate-db" {
name = "praivate-db"
subnet_ids = ["${aws_subnet.private-db1.id}", "${aws_subnet.private-db2.id}"]
tags = {
Name = "praivate-db"
}
}
# DBエンジン、バージョン、DB名、ユーザ名、パスワードなどの情報を定義する
resource "aws_db_instance" "covid19" {
identifier = "covid19"
allocated_storage = 20
storage_type = "gp2"
engine = "mysql"
engine_version = "5.7.23"
instance_class = "db.t3.micro"
name = "covid19db"
username = "covid19"
password = "covid19test!"
vpc_security_group_ids = ["${aws_security_group.covid19.id}"]
db_subnet_group_name = "${aws_db_subnet_group.praivate-db.name}"
skip_final_snapshot = true
}
次のコマンドを入力し、terraformプラグインを初期化します。
$ terraform init
次のコマンドを入力し、terraformの構文・パラメータチェックを行います。
$ terraform plan
次のコマンドを入力し、terraformを実行します。
$ terraform apply
途中で入力を求められるため、yesと入力してEnterキーを押しましょう。
これでリソースの作成が完了します。
今回はCovid-19追跡WebAppを動作させる為のプラットフォームとして、NodeJSとSparkpostを利用しております。
AWS EC2コンソールに戻ると、先程Terraformで作成した新しい EC2インスタンスが表示され、インスタンスにリモートでログインします。
先程作成した秘密鍵でEC2にログインします。
# ssh -i covid19 ec2-user@xxx.xxx.xxx.xxx -p22
次のコマンドを入力して、nodejs インストール パッケージをダウンロードします。
wget https://nodejs.org/dist/v14.17.1/node-v14.17.1-linux-x64.tar.xz
次のコマンドを入力して、ダウンロードされた パッケージを展開します。
tar -xf node-v14.17.1-linux-x64.tar.xz
次のコマンドを入力して、コマンド ソフト リンクを作成します。
sudo ln -s /home/ec2-user/node-v14.17.1-linux-x64/bin/node /usr/bin/ sudo ln -s /home/ec2-user/node-v14.17.1-linux-x64/bin/npm /usr/bin/
次のコマンドを入力して、ノードのバージョンを確認します。
node -v npm -v
次のコマンドを入力して、git をインストールします。
sudo yum update && yum -y install git
次のコマンドを入力して、サンプル プロジェクトをプルします。
git clone https://github.com/yankidank/covid-19-tracker.git
次のコマンドを入力して、プロジェクト ディレクトリに入ります。
cd covid-19-tracker
次のコマンドを入力して、プロジェクトの依存関係をインストールします。
sudo npm install --unsafe-perm
次の図を参照して、AWS RDS コンソールに移動します。
DB識別子である「covid19」のリンクをクリックして、データベースの接続エンドポイント及びポートなどの情報を確認できます。
EC2 コマンド ラインに戻り、 mysql clientコマンドをインストールします。
インストール方法に手間取ってしまったので、筆者は以下の記事を参考にさせていただきました。
【AWS EC2】Amazon Linux2にMySQLのclientだけをインストールしてRDSに接続する方法 (Qiita @tamorieeeen)
次のコマンドを入力して、RDSインスタンス データベースにログインします。 YOUR-RDS-ENDPOINT をユーザ自身の RDS インスタンスの接続エンドポイントに置き換えるように注意してください。
mysql -hYOUR-RDS-ENDPOINT -ucovid19 -pcovid19test!
次のコマンドを入力して、先程作成したcovid19dbに切り替えます。
mysql> use covid19db;
次のコマンドを入力して、「stats」テーブルを作成します。
CREATE TABLE stats
(
id int NOT NULL AUTO_INCREMENT,
FIPS INTEGER NULL,
Admin2 VARCHAR(100) NULL,
city VARCHAR(100) NULL,
province VARCHAR(500) NULL,
country VARCHAR(100) NULL,
confirmed INTEGER default 0,
deaths INTEGER default 0,
recovery INTEGER default 0,
last_update datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
latitude Decimal(18,15) NULL,
longitude Decimal(18,15) NULL,
active INTEGER NULL,
combined_key VARCHAR(500) NULL,
primary key(id)
);
次のコマンドを入力して、データベース接続を終了して、EC2のコマンドラインに戻ります。
exit
次のコマンド を入力して構成ファイルを開き、次の図を参照してデータベースの接続構成を変更します。
vim config/config.json
次のコマンドを入力して構成ファイルを開き、データベースの接続構成も変更します。
vim csv_to_mysql/read-file-4.js
次のコマンドを入力してスクリプト ファイルを実行し、データをデータベースにインポートします。
cd csv_to_mysql node read-file-4.js
SparkPost は開発者中心のメール配信サービスです。 全てのメール送受信は API を使用して行うことができます。
今回はSparkpos 公式 Web サイトにアカウントを登録してログインする必要があります。
ログインした後、[Configuration]をクリックして KEY を作成してください。
EC2 コマンドラインに戻ります。コマンド「vim /etc/profile」を入力し、ファイルの末尾に次の内容を追加します。 YOUR-API-KEY と YOUR-SECRET を自分のものに置き換えるように注意してください。
sudo vim /etc/profile
export SPARKPOST_API_KEY=YOUR-API-KEY export LOGIN_SECRET=YOUR-SECRET
次のコマンドを入力して、変更を有効にします。
source /etc/profile
次のコマンドを入力して、アプリケーションを起動します。
cd /root/covid-19-tracker node server.js
EC2の パブリック IP アドレスを使用してブラウザにアクセスします。
http://<EC2_IP>:8080
上記の画面が表示されたら起動に成功したことを示しています。
日本のヒートマップも表示することが可能です。
AWS環境におけるリソース作成時の留意事項を少し纏めました。
・AWSの認証情報
provider.tf設定ファイルに、AWSのアクセスキーID・シークレットアクセスキーを直接指定しているサンプルコードをたまに見かけますが、流出の危険等もあるため、基本的には`aws configure`コマンドでprofileを設定して使うようにしましょう。
・アベイラビリティゾーン
RDSの作成には複数のアベイラビリティゾーンの指定が必要です。単一では作成できません。本記事執筆時点で日本リージョンの場合、以下から2つのアベイラビリティゾーンを指定する必要があります。
zones: ap-northeast-1c, ap-northeast-1a, ap-northeast-1d.
・RDSへのアクセス
MySQLコマンドによりRDSデータベースに接続時及びデータをRDSにインポートする前に、RDSのセキュリティグループ設定で、該当IPからのアクセス許可設定が必要です。そうしないと、タイムアウトエラーが発生してしまい前に進められません。
Terraformは本当に便利なツールですね。最初はリソースを追加で作成する時、前利用していた*.tfファイルをそのまま利用すると、セキュリティグループidやVPC idなどと重複してしまい、エラーが発生するのではないかと心配したんですが、試してみたら、新規リソースを追加時、Terraformは前作成したリソースの差分と比較しているようで、前のtfファイルをそのまま利用しても全然問題なかったです。一度Terraformを利用すると離れられなくなりますね。
本記事ではTerraformにより簡単にAWS上でEC2とRDSを作成し、Covid19追跡のWebアプリケーションのデプロイ方法を纏めました。興味を持っている方はぜひお試しいただければ幸いです。
条件に該当するページがございません