AWS CDKでリソース作成 第2回: EC2・セキュリティグループ編

こんにちは。 エキサイト株式会社で内定者アルバイトをしています。

今回も、実際のリソースの作成を行いたいと思います。第2回は、セキュリティグループです。

前の記事 tech.excite.co.jp

リソースの説明

EC2とは?

EC2はAmazon Elastic Compute Cloudの略で、LinuxWindowsなどの仮想サーバを作成できるサービスです。

作成自体も容易で、作成後の変更や運用も簡単に実行できます。

EC2上で稼働するサーバはEC2インスタンスと呼ばれます。

セキュリティグループとは?

セキュリティグループは、そのグループを関連づけたリソースに到達するトラフィックとそこから離れるトラフィックを制御するためのリソースです。どのようなトラフィック(ポート番号、ソース、送信先などで指定)の通過を許可するか(拒否するか)を設定できます。

RDS(データベース)やEC2(仮想サーバ構築サービス)のような「メインとなる」リソースではありませんが、セキュリティ上重要なリソースです。

コード

前回までのコード

前回はVPCとそこに設置するサブネットを作成しました。

package com.myorg;

import software.amazon.awscdk.CfnTag;
import software.amazon.awscdk.services.ec2.CfnInternetGateway;
import software.amazon.awscdk.services.ec2.CfnVPCGatewayAttachment;
import software.amazon.awscdk.services.ec2.PrivateSubnet;
import software.amazon.awscdk.services.ec2.PublicSubnet;
import software.amazon.awscdk.services.ec2.Vpc;
import software.constructs.Construct;
import software.amazon.awscdk.Stack;
import software.amazon.awscdk.StackProps;

import java.util.List;

public class MyProjectStack extends Stack {
    public MyProjectStack(final Construct scope, final String id) {
        this(scope, id, null);
    }

    public MyProjectStack(final Construct scope, final String id, final StackProps props) {
        super(scope, id, props);

        Vpc vpc = Vpc.Builder.create(this, "SampleVPC")
                .vpcName("sample-vpc")
                .cidr("cidr")
                .subnetConfiguration(List.of())
                .build();

        // Availability zone: ap-northeast-1a
        PrivateSubnet privateSubnetA = PrivateSubnet.Builder.create(this, "PrivateSubnetA")
                .availabilityZone("ap-northeast-1a")
                .vpcId(vpc.getVpcId())
                .cidrBlock("cidr")
                .build();

        PublicSubnet publicSubnetA = PublicSubnet.Builder.create(this, "PublicSubnetA")
                .availabilityZone("ap-northeast-1a")
                .vpcId(vpc.getVpcId())
                .cidrBlock("cidr")
                .build();

        // Availability zone: ap-northeast-1c
        PrivateSubnet privateSubnetB = PrivateSubnet.Builder.create(this, "PrivateSubnetB")
                .availabilityZone("ap-northeast-1c")
                .vpcId(vpc.getVpcId())
                .cidrBlock("cidr")
                .build();

        PublicSubnet publicSubnetB = PublicSubnet.Builder.create(this, "PublicSubnetB")
                .availabilityZone("ap-northeast-1c")
                .vpcId(vpc.getVpcId())
                .cidrBlock("cidr")
                .build();

        // NAT gatewayの追加
        publicSubnetA.addNatGateway();
        publicSubnetB.addNatGateway();

        // Internet Gateway
        CfnInternetGateway internetGateway = CfnInternetGateway.Builder.create(this, "InternetGateway")
                .tags(List.of(CfnTag.builder()
                        .key("Name")
                        .value("sample-internet-gateway")
                        .build()))
                .build();

        // Internet gatewayをVPCにattachする
        CfnVPCGatewayAttachment.Builder.create(this, "VpcGateAwayAttachment")
                .vpcId(vpc.getVpcId())
                .internetGatewayId(internetGateway.getAttrInternetGatewayId())
                .build();
    }
}

セキュリティグループ

セキュリティグループはVPC内に定義します。今回は前回作成したVPC内に作成するため、vpc()に指定して結び付けています。

セキュリティグループを作成する部分のコードは以下の通りです。スタックのクラス内に記述します。

        SecurityGroup securityGroup = SecurityGroup.Builder.create(this, "SecurityGroup")
                .securityGroupName("sample-security-group")
                .vpc(vpc)
                .allowAllOutbound(true)
                .description("sample-security-group")
                .build();

        securityGroup.addIngressRule(Peer.ipv4("0.0.0.0/0"), Port.tcp(80));

セキュリティグループにインバウンドルール(流入)を追加するには、addIngressRule()メソッドを使用します。第一引数にIPv4アドレスを、第二引数にポート番号を指定します。 アウトバウンドルールを追加するには、addEgressRule()メソッドを使用します。

EC2インスタンス

今回は、2つのEC2インスタンスを作成します。それぞれのアベイラビリティゾーンはap-northeast-1aap-northeast-1cであり、以下のような共通の設定を持ちます。

設定項目 設定内容
Amazon マシンイメージ Amazon Linux
インスタンスタイプ t2.small

このEC2インスタンスを定義するVPCとセキュリティグループは前節で定義したものを使います。コードは以下のようになります。

        IMachineImage machineImage = MachineImage.latestAmazonLinux();

        Instance instance01 = Instance.Builder.create(this, "ec2-instance-01")
                .instanceName("ec2-instance-01")
                .vpcSubnets(SubnetSelection.builder().subnets(List.of(privateSubnetA)).build())
                .machineImage(machineImage)
                .vpc(vpc)
                .availabilityZone("ap-northeast-1a")
                .instanceType(InstanceType.of(InstanceClass.T2, InstanceSize.SMALL))
                .securityGroup(securityGroup)
                .build();
        
        Instance instance02 = Instance.Builder.create(this, "ec2-instance-02")
                .instanceName("ec2-instance-02")
                .vpcSubnets(SubnetSelection.builder().subnets(List.of(privateSubnetB)).build())
                .machineImage(machineImage)
                .vpc(vpc)
                .availabilityZone("ap-northeast-1c")
                .instanceType(InstanceType.of(InstanceClass.T2, InstanceSize.SMALL))
                .securityGroup(securityGroup)
                .build();

設定項目はメソッド名の通りなので特に説明は必要ないと思います。インスタンスタイプなども列挙型で用意されているなど、IDEの補完機能と組み合わせることで、マネジメントコンソールでのポチポチとあまり大差なく設定することができます。

補足

vpcSubnets()については少し補足が必要かと思います。

vpcSubnets()はさまざまな設定方法があります。例えば、

                .vpcSubnets(SubnetSelection.builder()
                        .subnetType(SubnetType.PRIVATE_WITH_EGRESS)
                        .build())
                .availabilityZone("ap-northeast-1a")

のようにすると、ap-northeast-1aにあるPrivateサブネットが選ばれてEC2インスタンスが作成されます。(ただし、ap-northeast-1a上に該当するサブネットが複数あるとエラーになります。)

また、availabilityZoneを指定しなければ、該当するサブネットの中から一つが選ばれてインスタンスが作成されます。

ちなみに、vpcSubnets()で指定したサブネットのアベイラビリティゾーンが、 availabilityZone()で指定したアベイラビリティゾーンと一致しない場合もエラーになります。

デプロイ

ここまで書いたら、いつものようにデプロイします。

cdk deploy

インスタンスの作成には少し時間がかかりますが、エラーなく完了したらOKです。

終わりに

今回は、EC2インスタンスとセキュリティグループを作成しました。

では、また次回。

次の記事 tech.excite.co.jp

参考文献