おさらい
前々回(第1回)の記事はこちらです。
前回(第2回)の記事はこちらです。
構成図
構成図は大事なので毎回記載します。完成形は以下です。
今回やること
今回はすべてのスタックをデプロイします。デプロイした後、カスタムAMIを作成します。
そしてCDKを修正して、EC2がカスタムAMIから起動されるように変更します。
また、WordPressの動作確認も行います。
デプロイ
準備
AWS CDKを使用するための前提条件は、AWS CDK Intro Workshopに詳しく書かれています。これから始める方はぜひ一度!
前提条件が書かれているリンクは下記です。
Networkスタックをデプロイ
Networkスタックのデプロイを行ったときのターミナルです。カラフルで見やすいですね!
IAMやSecurity Groupなどセキュリティに関するものは、特にわかりやすくハイライトされています。
CDKをYAMLで表示したい場合はcdk synth
コマンドをご利用ください。
Storageスタックをデプロイ
次にStorageスタックをデプロイします。
セキュリティグループに許可設定が入り、EC2とEFSの間で2049ポート通信が許可されています。
Databaseスタックをデプロイ
Databaseスタックをデプロイします。マルチAZ構成なので少し時間がかかります。(ここでは10分かかってます)
セキュリティグループに許可設定が入り、EC2とRDSの間で3306ポート通信が許可されています。
Computingスタックをデプロイ
最後にComputingスタックです。
動作確認(カスタムAMI設定前)
最終的にはカスタムAMIからEC2を起動するようにしますが、ここで一旦動作確認をします。
ELBのDNS名を確認
aws cli
で確認します。
% aws elbv2 describe-load-balancers | grep DNSName
"DNSName": "wp-dev-alb-XXXXXXXXX.ap-northeast-1.elb.amazonaws.com",
AWSコンソールから確認しても構いません。
WordPressにアクセス
ELBのDNS名でブラウザでアクセスします。
ページが表示できました。
WordPressへログイン
http://[ELBのDNS名]/wp-admin
へアクセスしてみます。
CDKのコード上で指定したユーザー名とパスワードを入力します。
ログインできました。
カスタムAMIの設定
このままだと、Auto Scalingによって作成されるEC2すべてがユーザーデータを実行してしまうので、カスタムAMIからの起動にしていきます。
カスタムAMIの作成
現在起動しているEC2からカスタムAMIを作成します。
まずはEC2のインスタンスIDを取得します。AWSコンソールからでもOKです。
% aws ec2 describe-instances --filters Name=instance-state-name,Values=running | grep InstanceId
"InstanceId": "i-XXXXXXXXXXXXXXXXX",
確認したインスタンスIDを指定してカスタムAMIを作成します。
% aws ec2 create-image --instance-id i-XXXXXXXXXXXXXXXXX --name "wp-dev-ami" --description "AMI for WordPress Server"
{
"ImageId": "ami-XXXXXXXXXXXXXXXXX"
}
カスタムAMIのState
がavailable
になればCDKコードの修正に入ります。
% aws ec2 describe-images --filters Name=name,Values="wp-dev-ami"
{
"Images": [
{
"Architecture": "x86_64",
"CreationDate": "2022-08-14T07:28:38.000Z",
"ImageId": "ami-XXXXXXXXXXXXXXXXX",
"ImageLocation": "XXXXXXXXXXXX/wp-dev-ami",
"ImageType": "machine",
"Public": false,
"OwnerId": "XXXXXXXXXXXX",
"PlatformDetails": "Linux/UNIX",
"UsageOperation": "RunInstances",
"State": "available",
"BlockDeviceMappings": [
{
"DeviceName": "/dev/xvda",
"Ebs": {
"DeleteOnTermination": true,
"SnapshotId": "snap-0fab3fef000ebe50a",
"VolumeSize": 8,
"VolumeType": "gp2",
"Encrypted": false
}
}
],
"Description": "AMI for WordPress Server",
"EnaSupport": true,
"Hypervisor": "xen",
"Name": "wp-dev-ami",
"RootDeviceName": "/dev/xvda",
"RootDeviceType": "ebs",
"SriovNetSupport": "simple",
"VirtualizationType": "hvm"
}
]
}
CDKコード一部修正
Computingスタック修正
Computingを修正します。修正した箇所はハイライトしています。
from aws_cdk import (
Duration,
Stack,
aws_ec2 as ec2,
aws_elasticloadbalancingv2 as elbv2,
aws_autoscaling as autoscaling,
aws_iam as iam,
)
from constructs import Construct
import aws_cdk as cdk
from aws_cdk.aws_s3_assets import Asset
class ComputingStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs) -> None:
super().__init__(scope, construct_id, **kwargs)
##############################################
############### Import Section ###############
##############################################
# Import VPC
wp_vpc = ec2.Vpc.from_lookup(self, "Vpc",
vpc_name="wp-dev-vpc"
)
# Import Security Group(EC2)
wp_sg_ec2 = ec2.SecurityGroup.from_lookup_by_name(self, "SgEC2",
vpc=wp_vpc,
security_group_name="wp-dev-sg-ec2"
)
# Import Security Group(EFS)
wp_sg_efs = ec2.SecurityGroup.from_lookup_by_name(self, "SgEFS",
vpc=wp_vpc,
security_group_name="wp-dev-sg-efs"
)
# Import Security Group(RDS)
wp_sg_rds = ec2.SecurityGroup.from_lookup_by_name(self, "SgRDS",
vpc=wp_vpc,
security_group_name="wp-dev-sg-rds"
)
# Import Security Group(ELB)
wp_sg_elb = ec2.SecurityGroup.from_lookup_by_name(self, "SgELB",
vpc=wp_vpc,
security_group_name="wp-dev-sg-elb"
)
# Import Secrurity Group(SSM)
wp_sg_ssm = ec2.SecurityGroup.from_lookup_by_name(self, "SgSSM",
vpc=wp_vpc,
security_group_name="wp-dev-sg-ssm"
)
# Import IAM Role(EC2)
wp_role_ec2 = iam.Role.from_role_name(self, "RoleEC2",
role_name="wp-dev-role-ec2"
)
##############################################
############### Server Section ###############
##############################################
# Upload Shell Script(User Data) to s3
# asset = Asset(self, "Asset",
# path="Computing/User_data.sh"
# )
# Create User Data Instance
# wp_userdata = ec2.UserData.for_linux()
# Launch Template
wp_lt = ec2.LaunchTemplate(self, "LaunchTemplate",
launch_template_name="wp-dev-lt",
instance_initiated_shutdown_behavior=ec2.InstanceInitiatedShutdownBehavior.TERMINATE,
security_group=wp_sg_ec2,
instance_type=ec2.InstanceType.of(
instance_class=ec2.InstanceClass.BURSTABLE2,
instance_size=ec2.InstanceSize.MICRO
),
role=wp_role_ec2,
# user_data=wp_userdata,
# machine_image=ec2.AmazonLinuxImage(
# generation=ec2.AmazonLinuxGeneration.AMAZON_LINUX_2
# ),
# Set the AMI from EC2 after installed WordPress
machine_image=ec2.MachineImage.generic_linux(
{"us-east-1": "ami-038b0c10ca70701f8"}
)
)
# Grant Read to Role of Template
# asset.grant_read(wp_lt.role)
# Download Shell Script(User Data) to local path
# wp_local_path = wp_userdata.add_s3_download_command(
# bucket=asset.bucket,
# bucket_key=asset.s3_object_key,
# region="us-east-1"
# )
# Add User Data to Template
# wp_lt.user_data.add_execute_file_command(
# file_path=wp_local_path
# )
# Auto Scaling Group
wp_asg = autoscaling.AutoScalingGroup(self, "Asg",
vpc = wp_vpc,
auto_scaling_group_name="wp-dev-asg",
launch_template=wp_lt,
health_check=autoscaling.HealthCheck.elb(
grace=cdk.Duration.seconds(30)
),
vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PRIVATE_WITH_NAT),
desired_capacity=2,
min_capacity=2,
max_capacity=4
)
#####################################################
############### Load Balancer Section ###############
#####################################################
# Application Load Balancer
wp_alb = elbv2.ApplicationLoadBalancer(self, "Alb",
vpc=wp_vpc,
http2_enabled=False,
ip_address_type=elbv2.IpAddressType.IPV4,
security_group=wp_sg_elb,
internet_facing=True,
load_balancer_name="wp-dev-alb",
vpc_subnets=ec2.SubnetSelection(subnet_type=ec2.SubnetType.PUBLIC)
)
# Target Group
wp_tg = elbv2.ApplicationTargetGroup(self, "TargetGroup",
vpc=wp_vpc,
port=80,
target_group_name="wp-dev-tg",
health_check=elbv2.HealthCheck(
enabled=True,
protocol=elbv2.Protocol.HTTP,
port="80",
path="/readme.html",
timeout=cdk.Duration.seconds(25), # Defaultis 5
unhealthy_threshold_count=5 # Default is 2
),
target_type=elbv2.TargetType.INSTANCE
)
# Add Targets To Auto Scaling Group
wp_tg.add_target(wp_asg)
# Add Listner To ELB
wp_alb.add_listener("AddListener",
port=80,
default_target_groups=[wp_tg]
)
######################################################
############### Add Allow Rule Section ###############
######################################################
# Add Allow Connection to EC2
wp_lt.connections.allow_from(wp_sg_elb, ec2.Port.tcp(80)) # Allow HTTP from ALB
wp_lt.connections.allow_to(wp_sg_ssm, ec2.Port.tcp(443)) # For Acces to EC2 by Sessions Manager
# wp_lt.connections.allow_to_any_ipv4(ec2.Port.tcp(80)) # For EC2 installs some packages by User Data. Disable after installing wordPress.
# wp_lt.connections.allow_to_any_ipv4(ec2.Port.tcp(443)) # For EC2 installs some packages by User Data. Disable after installing wordPress.
# Add Allow Connection to ELB
wp_alb.connections.allow_from_any_ipv4(ec2.Port.tcp(80))
Computingスタック修正箇所
- 66〜71行目
UserDataを生成する必要がなくなったためコメントアウトしています。
- 83〜86行目
起動テンプレートにUserDataを指定する必要がなくなったためコメントアウトしています。
また、AMIはカスタムAMIを使用するためコメントアウトしています。
- 88〜90行目
先ほど作ったカスタムAMIを指定しています。
- 93〜105行目
UserDataのダウンロードや実行の指定は必要がなくなったためコメントアウトしています。
- 116〜118行目
Auto Scalingの容量を変更しています。
EC2がマルチAZで配置されるようにするため、希望容量と最低容量を2にしています。最大容量はここでは4を指定しています。(実際に使うのであれば負荷テスト実施後になると思いますが)
- 168〜169行目
今のところEC2がインターネットに接続する必要はなくなるため、EC2からのHTTP(80)とHTTPS(443)のアウトバウンド許可を削除します。
再デプロイ(Computingスタック)
差分を比較してみます。cdk diff
コマンドです。
EC2のセキュリティグループの一部が削除されること、EC2の起動に使用されるAMIが変更されること、Auto Scalingの容量が変更されることが表示されています。
再デプロイします。
デプロイ成功しました。
カスタムAMIではないEC2を削除
EC2がもう1台起動して2台構成になっていると思いますが、片方だけカスタムAMIからの起動になっています。最初に起動したEC2は終了します。
希望容量を2台としているのでもう1台起動して、カスタムAMIから起動したEC2でマルチAZ構成となりました。
動作確認(カスタムAMI設定後)
カスタムAMI設定後もWordPressが正常にホストされているか確認します。
ELBのDNS名でアクセスして正常に画面が表示されました。管理画面にもログインすることができました。
Nat Gatewayについて
Nat Gatewayが1台起動しています。
起動しているだけで料金がかかってしまうので、AWSコンソールから削除することをおすすめします。
また、それに紐づくEIPも開放しておいたほうがよいと思います。アタッチされていないと料金が発生してしまうので。
コメント