MENU

AWS CDKでインフラ構築③(EC2・ALB作成)

はじめに

[前回の記事] kumagoro-95.hatenablog.com

前回の記事でCDKのプロジェクト作成までやったので、とりあえずEC2+RDSの簡単な構成をCDKで書いてみたいと思います。

あんまりちゃんと考えてないので後から変わるかもですが、↓みたいな構成を考えてます。 ちょっと迷いましたが、VPCとサブネットはマネジメントコンソールから作りました。

既存のVPCを取得

EC2やらなんやらを作るために、作成済みのVPCの情報を取得します。

[test-stack.ts]

const vpc = ec2.Vpc.fromLookup(this, "existing-vpc" ,{
    vpcId: "vpc-xxxxxxxxxx" //vpcIdを指定
});

これだけで取ってこれそうな感じでしたが、こんなエラーが。

Cannot retrieve value from context provider vpc-provider since account/region are not specified at the stack level. Either configure "env" with explicit account and region when you define your stack, or use the environment variables "CDK_DEFAULT_ACCOUNT" and "CDK_DEFAULT_REGION" to inherit environment information from the CLI (not recommended for production stacks)
Subprocess exited with error 1

accountとregionの情報を持ってないのが問題みたい。envにaccountとregionの値を設定するか、EnvironmentVariablesを使うよう言われている。

参考1:aws-cdkでvpc.fromLookupが動作しない - com4dc’s blog

参考2:cdk deploy 時に Cannot retrieve value from context provider vpc-provider ... と言われる - Qiita

今回は、スタック生成時にenvで渡してあげることにしました。

[cdk-test.ts]

const app = new cdk.App();
new CdkTestStack(app, 'CdkTestStack', {
  env: {
    account: 'xxxxxxxxxx',
    region: 'us-east-1'
  }

cdk synth を叩いてみて、既存のVPCの情報を取ってこれることを確認。

VPCが取れたので、次はサブネットを取ってくる。

サブネットはサブネットIDを直接指定して取得しました。

    const publicSubnet1 =  ec2.Subnet.fromSubnetId(this, 'publicSubnet1', 'subnet-xxxx');
    const publicSubnet2 =  ec2.Subnet.fromSubnetId(this, 'publicSubnet2', 'subnet-yyyy');

ALB作成

全然覚えてなかったけど、ALBには下記のルールがある。(合ってる?)

  • 外と通信できるALBを作るには、ALBを各AZのパブリックサブネットに紐づけてやる必要がある。

  • ALBに紐づけるAZは2つ以上でないといけない。

上記2点を踏まえて書いたらこんな感じに。

    /**
     * ALB作成
     */
    const alb = new elb.ApplicationLoadBalancer(this, 'Alb', {
      vpc,
      internetFacing: true,  // 外部と通信するためのalbなのでtrue
      loadBalancerName: "cdk-test-alb",
      securityGroup: albSecurityGroup,  // 後述
      vpcSubnets: {
        subnets: [publicSubnet1, publicSubnet2],
      }
    })
    // port80からの通信を許可
    const listener = alb.addListener('listener', { port: 80 });
    listener.addTargets('target', {
      port: 80,
    });

参考:class ApplicationLoadBalancer (construct) · AWS CDK

ALBへ紐づけるセキュリティグループは、SSHと外からのHTTP通信を許可しておきます。

    const albSecurityGroup = new ec2.SecurityGroup(this, "alb-security-group", {
      vpc,
      description: "Allow SSH and HTTP in",
      allowAllOutbound: true,
    });

    // ssh接続を許可
    albSecurityGroup.addIngressRule(
      ec2.Peer.anyIpv4(),
      ec2.Port.tcp(22),
      "Allow SSH Access"
    );

    // http接続を許可
    albSecurityGroup.addIngressRule(
      ec2.Peer.anyIpv4(),
      ec2.Port.tcp(80),
      "Allow http Access"
    ); 

参考:class SecurityGroup (construct) · AWS CDK

これでALBの設定は完了。

EC2作成

次はEC2インスタンスを作ります。

    /**
     * EC2インスタンス作成
     */
    const machineImage = new ec2.AmazonLinuxImage()
    const ec2Instance = new ec2.Instance(this, 'ec2-instance', {
      vpc: vpc,
      instanceType: ec2.InstanceType.of(ec2.InstanceClass.T2, ec2.InstanceSize.MICRO),
      machineImage: machineImage,
      securityGroup: ec2SecurityGroup,
      availabilityZone: 'us-east-1a',
      vpcSubnets: {
        subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
      }
    })

    const ec2Instance2 = new ec2.Instance(this, 'ec2-instance2', {
      vpc: vpc,
      instanceType: ec2.InstanceType.of(ec2.InstanceClass.T2, ec2.InstanceSize.MICRO),
      machineImage: machineImage,
      securityGroup: ec2SecurityGroup,
      availabilityZone: 'us-east-1b',
      vpcSubnets: {
        subnetType: ec2.SubnetType.PRIVATE_ISOLATED,
      }
    })

参考: class Instance (construct) · AWS CDK

EC2のセキュリティグループでは、SSH接続とALBからのHTTP接続を許可します。

    const ec2SecurityGroup = new ec2.SecurityGroup(this, "ec2-security-group", {
      vpc,
      description: "Allow SSH and HTTP in",
      allowAllOutbound: true,
    });

    // ssh接続を許可
    ec2SecurityGroup.addIngressRule(
      ec2.Peer.anyIpv4(),
      ec2.Port.tcp(22),
      "Allow SSH Access"
    );

    // albからのhttp接続を許可
    ec2SecurityGroup.addIngressRule(
      albSecurityGroup,
      ec2.Port.tcp(80),
      "Allow http Access from Alb"
    ); 

これで、ALBのdnsにアクセスするとEC2インスタンスに通信が通るようになりました。 次はRDS作ります。

参考