こんにちは。プロダクト事業部のまつもとです。
インフラを管理していて非常に労力を使うのが
- 変更箇所の確認(今度の変更点で修正するのはどこだっけ?)
- 環境が複数ある場合の適用状況の確認(この環境変更したっけ?)
- 把握してないリソースの残骸が残って知らない内に課金され続ける(あれ?このリソース何?)
など、インフラの設定内容を把握することです。
大体が、設定内容をEXCEL資料などで残して、設定変更する際にその資料直して。。。とマンパワーを割いてカバーしていますが、人間の力には限度もあればミスもあり、、、資料の修正忘れや最初から作ってなかったりなど多々あります。
プログラムソースのように現環境と新環境でDiffとって差を出してとかできれば、☝️で呟いてるような労力なんて少なくなるor必要なくなると思いませんか???
AWSにはインフラ環境をコードで定義する仕組みとして、AWS CloudFormationがあります。
AWS CloudFormation
https://aws.amazon.com/jp/cloudformation/
AWSサービスをJSON or XMLのテンプレートで定義して実行すると、EC2やS3などが自動でできてしまうという非常に魅力的なサービスで、テンプレート化できるということは、Gitでバージョン管理できるという事なので、パラメータとかの変更点がDIFFできちゃいます。
ただ、CloudFormationの難儀な点は、JSON or XMLで書くから長いくて意味わからんテンプレートになってしまう!ところだと個人的に思っています。
CloudFormationテンプレートの例
{
"Resources": {
"Instance": {
"Type": "AWS::EC2::Instance",
"Properties": {
"ImageId": "ami-xxxxxxxxxxxx",
"InstanceType": "t2.micro",
"Tags": [
{
"Key": "Name",
"Value": "Example EC2"
}
],
"NetworkInterfaces": [
{
"AssociatePublicIpAddress": true,
"DeviceIndex": 0,
"SubnetId": "subnet-xxxxxxxx",
"GroupSet": [{"Ref": "InstanceSecurityGroup"}]
}
]
}
},
"InstanceSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"VpcId": "vpc-xxxxxx"
, "SecurityGroupIngress": [
{
"FromPort": 22,
"ToPort": 22,
"IpProtocol": "tcp",
"CidrIp": "xxx.xxx.xxx.xxx/32"
},
{
"FromPort": 22,
"ToPort": 22,
"IpProtocol": "tcp",
"CidrIp": "xxx.xxx.xxx.xxx/32"
}
]
,"Tags": [
{
"Key": "Name",
"Value": "Example EC2"
}
]
}
}
}
}
そんな悩みを解決してくれそうなのがAWS CDKです。
AWS CDK
https://aws.amazon.com/jp/cdk/
JSON or XMLをゴリゴリ作成するのではなく、使い慣れたプログラミング言語を使ってAWSの環境を作る(正確にはCloudFormationのテンプレートを生成する)、夢がいっぱい詰まったフレームワークです!
ただ、CDKはバージョンアップが頻繁に行われていて、数ヶ月前に作ったコードが、最新のバージョンでは動かないなどの事態が発生したりします。
ちなみに、2019年11月に設定したCloud9上のCDKのバージョンは
1.19.0 (build 5597bbe)
で、2021年01月時点で1.85.0 (build 5f44668)
でした。
1年でマイナーバージョンが70近く上がってます。。。
マイナーが上がる事で、以前作ったコードが使えなくなったりするので、CDK使うときはバージョンアップに追従していく労力がかなり必要になります。
ということで、夢と希望がいっぱい詰まったCDKを利用したEC2の作成をご紹介したいと思います。
AWS CDK for Python 利用準備
環境は簡単に AWS Cloud9 で作ります。
(Cloud9の構築については割愛させて頂きます。)
Cloud9の画面下部のターミナル部分でコマンドを叩いて、cdkが使えるか確認してみます。
$ cdk --version
1.85.0 (build 5f44668)
簡単なウィザードをポチポチするだけでAWS CDKなど標準で入った環境が数分でできるなんて、Cloud9便利すぎます!
cdkが使えることが確認できたので、AWS CDK for Pythonをinitします。
ちなみになぜpythonかというと、個人的にpythonが好きだからです!(ここ重要)
$ mkdir example && cd example
$ cdk init --language python
✅ All done!
の表示がされればinit完了です。
README.mdにも書かれていますが、virtualenv使うようなので、起動後CDKを利用する場合は以下のコマンドを叩きます。
$ source .venv/bin/activate
EC2作成
キーペアの作成
EC2で利用するキーペアは、流石にCloudFormationでは作れません。(秘密鍵のダウンロードとか必要なので。)そのため、事前にEC2のサービスコンソールで作成しておきます。
作成後の秘密鍵は大事にしまっておきます。
CDKで利用するライブラリの定義
requirements.txtにEC2を作成するために必要なライブラリを記述します。-e .
以下に必要なライブラリを追加していきます。
-e .
aws_cdk.aws_ec2
ライブラリを追加した後は、README.mdにも記載がありますが、
$ pip install -r requirements.txt
を実行してライブラリをインストールします。
EC2を作成する
今までの流れで作成した場合、~/environment/example/example
の下に example_stack.py
ファイルが作成されているので、こちらを利用します。
ライブラリの読み込み
example_stack.py の先頭で、ec2のライブラリを読み込みます。
from aws_cdk import (
aws_ec2 as ec2,
)
example_stack.pyの __init__
メソッドに、
# The code that defines your stack goes here
のコメントがあります。このコメントの下に必要コードを記載していきます。
VPCの定義
VPCを新規作成なども行えますが、今回はDefaut VPCを利用します。
作成するのではなく、既にあるVPCを利用するので、 from_lookup
でVPCを参照します。
# Default VPCを参照
vpc = ec2.Vpc.from_lookup(
self,
id='DefaultVPC',
vpc_id="{Default VPCのVPC-ID}",
)
セキュリティグループの作成
EC2のセキュリティコードを作成します。
弊社ネットワークからのみsshで接続できるようにします。
# セキュリティグループの作成
security_group = ec2.SecurityGroup(
self,
id='ExampleSecurityGroup',
vpc=vpc,
security_group_name='example-security-group',
description='Example security group.',
)
# 作成したセキュリティグループのインバウンドルールを設定 - PSCからのsshは許可
security_group.add_ingress_rule(
connection=ec2.Port.tcp(22),
peer=ec2.Peer.ipv4('xxx.xxx.xxx.xxx/32'),
description='PSC global ipv4.',
)
EC2インスタンスを作成するイメージの定義
今回はAmazonLinux2を利用するので、AmazonLinux2のイメージを定義します。
image = ec2.AmazonLinuxImage(
generation=ec2.AmazonLinuxGeneration.AMAZON_LINUX_2,
storage=ec2.AmazonLinuxStorage.EBS,
)
EC2インスタンスの作成
上で作成した、VPC、セキュリティグループ、インスタンスイメージを利用して、EC2を作成します。
EBSのボリュームサイズは、10GBにしています。
ec2.CfnInstance(
self,
id='ExampleEC2',
image_id=image.get_image(self).image_id,
instance_type=ec2.InstanceType('t2.small').to_string(),
key_name="{事前に作成したキーペア名}",
security_group_ids=[
security_group.security_group_id,
],
subnet_id=vpc.select_subnets(subnet_type=ec2.SubnetType.PUBLIC).subnets[0].subnet_id,
block_device_mappings = [
{
'deviceName': '/dev/xvda',
'ebs': {'volumeSize': 10}
}
],
ebs_optimized=False,
tags=[
core.CfnTag(key='Name', value='Example EC2'),
],
)
app.py の修正
~/environment/example
の下にある app.py
を修正します。
スタックがデプロイされる環境を定義します。
env_JP = core.Environment(account="{自身のAWSアカウント}", region="ap-northeast-1")
自動生成で作成されている ExampleStack
に作成した環境情報を追加します。
Stackの第二引数は、CloudFormationのスタック名になるので、わかりやすく EC2
を追加します。
# ExampleStack(app, "example")
# ↓
ExampleStack(app, "example-ec2", env=env_JP)
デプロイ
では、作成したCDKから、実際に環境を作成してみます。
デプロイする場合は、Cloud9のターミナルで以下のコマンドを入力します。
$ cdk deploy
途中、以下のようにセキュリティグループを変更するけど良いですか?と質問されるので y
を入力します。
Security Group Changes
┌───┬─────────────────────────────────┬─────┬────────────┬────────────────────┐
│ │ Group │ Dir │ Protocol │ Peer │
├───┼─────────────────────────────────┼─────┼────────────┼────────────────────┤
│ + │ ${ExampleSecurityGroup.GroupId} │ In │ TCP 22 │ xxx.xxx.xxx.xxx/32 │
│ + │ ${ExampleSecurityGroup.GroupId} │ Out │ Everything │ Everyone (IPv4) │
└───┴─────────────────────────────────┴─────┴────────────┴────────────────────┘
(NOTE: There may be security-related changes not in this list. See https://github.com/aws/aws-cdk/issues/1299)
Do you wish to deploy these changes (y/n)? y
✅ example-ec2
が表示されれば成功です。
cdkは、CloudFormationのスタックを生成してくれるので、CloudFormationを確認してみます。
バッチリできてます!
EC2を確認します。
これまたバッチリできてます!
会社からの接続を確認してみます。EC2を作成した際に指定したキーペアを利用します。
ssh -i ~/.ssh/testkey.pem ec2-user@{作成したEC2に割り当てされたパブリックIP}
__| __|_ )
_| ( / Amazon Linux 2 AMI
___|\___|___|
https://aws.amazon.com/amazon-linux-2/
[ec2-user@ip-172-31-43-19 ~]$
繋がりました!
最後に
AWS CDKの触り部分の紹介となりましたが、いろいろなサービスがCDKを利用して作成することができます。
今後もシリーズとして色々なサービス構築例をご紹介して行きたいと思います。