AWS CDKを利用してインフラ環境をコードで作成する – EC2編

こんにちは。プロダクト事業部のまつもとです。

インフラを管理していて非常に労力を使うのが

  • 変更箇所の確認(今度の変更点で修正するのはどこだっけ?)
  • 環境が複数ある場合の適用状況の確認(この環境変更したっけ?)
  • 把握してないリソースの残骸が残って知らない内に課金され続ける(あれ?このリソース何?)

など、インフラの設定内容を把握することです。
大体が、設定内容を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

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のサービスコンソールで作成しておきます。

keypair

作成後の秘密鍵は大事にしまっておきます。

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を確認してみます。

cloudformation

バッチリできてます!
EC2を確認します。

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を利用して作成することができます。
今後もシリーズとして色々なサービス構築例をご紹介して行きたいと思います。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

%d人のブロガーが「いいね」をつけました。