CDKでEC2インスタンスをデプロイする

これらの記事を参考にやってみる

実践!AWS CDK #17 EC2

https://dev.classmethod.jp/articles/cdk-practice-17-ec2/

AWS CDKでEC2をデプロイする

https://qiita.com/Brutus/items/bba6a49a1a05c3277673

Amazon EC2 でウェブアプリケーションをデプロイする

https://aws.amazon.com/jp/getting-started/guides/deploy-webapp-ec2/module-one/

環境確認

cdk --version
1.117.0 (build 0047c98)

プロジェクト作成

cdk init app --language typescript

パッケージのインストール

npm i @aws-cdk/aws-ec2 @aws-cdk/aws-iam @aws-cdk/aws-s3-assets cdk-ec2-key-pair

EC2インスタンスを生成するコード

cdk-ec2-stack.ts

import * as cdk from '@aws-cdk/core';

import * as ec2 from '@aws-cdk/aws-ec2'        // Allows working with EC2 and VPC resources
import * as iam from '@aws-cdk/aws-iam'            // Allows working with IAM resources
import * as s3assets from '@aws-cdk/aws-s3-assets' // Allows managing files with S3
import * as keypair from 'cdk-ec2-key-pair'        // Helper to create EC2 SSH keypairs
import * as path from 'path';                       // Helper for working with file paths

export class CdkEc2Stack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Look up the default VPC
    
    const vpc = ec2.Vpc.fromLookup(this, "VPC", {
      isDefault: true
    });

    // Create a key pair to be used with this EC2 Instance
    const key = new keypair.KeyPair(this, "KeyPair", {
      name: "cdk-keypair",
      description: "Key Pair created with CDK Deployment",
    });
    key.grantReadOnPublicKey; 

    // Security group for the EC2 instance
    const securityGroup = new ec2.SecurityGroup(this, "SecurityGroup", {
      vpc,
      description: "Allow SSH (TCP port 22) and HTTP (TCP port 80) in",
      allowAllOutbound: true,
    });

    // Allow SSH access on port tcp/22
    securityGroup.addIngressRule(
      ec2.Peer.anyIpv4(),
      ec2.Port.tcp(22),
      "Allow SSH Access"
    );

    // IAM role to allow access to other AWS services
    const role = new iam.Role(this, "ec2Role", {
      assumedBy: new iam.ServicePrincipal("ec2.amazonaws.com"),
    });

    // IAM policy attachment to allow access to 
    role.addManagedPolicy(
      // AWS Systems ManagerはAWS でインフラストラクチャを表示および制御するために使用できる AWS のサービス
      iam.ManagedPolicy.fromAwsManagedPolicyName("AmazonSSMManagedInstanceCore")
    );

    // Look up the AMI Id for the Amazon Linux 2 Image with CPU Type X86_64
    const ami = new ec2.AmazonLinuxImage({
      generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2,
      cpuType: ec2.AmazonLinuxCpuType.X86_64,
    });

    // Create the EC2 instance using the Security Group, AMI, and KeyPair defined.
    const ec2Instance = new ec2.Instance(this, "Instance", {
      vpc,
      instanceType: ec2.InstanceType.of(
        ec2.InstanceClass.T2,
        ec2.InstanceSize.MICRO
      ),
      machineImage: ami,
      securityGroup: securityGroup,
      keyName: key.keyPairName,
      role: role,
    });  

  }
}

デプロイする環境を設定する

cdk-ec2.ts

#!/usr/bin/env node
import 'source-map-support/register';
import * as cdk from '@aws-cdk/core';
import { CdkEc2Stack } from '../lib/cdk-ec2-stack';

const app = new cdk.App();
new CdkEc2Stack(app, 'CdkEc2Stack', {
  /* If you don't specify 'env', this stack will be environment-agnostic.
   * Account/Region-dependent features and context lookups will not work,
   * but a single synthesized template can be deployed anywhere. */

  /* Uncomment the next line to specialize this stack for the AWS Account
   * and Region that are implied by the current CLI configuration. */
  // env: { account: process.env.CDK_DEFAULT_ACCOUNT, region: process.env.CDK_DEFAULT_REGION },

  /* Uncomment the next line if you know exactly what Account and Region you
   * want to deploy the stack to. */
  env: {account: 'XXXXXXXXXXXX', region: 'ap-northeast-1'},

  /* For more information, see https://docs.aws.amazon.com/cdk/latest/guide/environments.html */
});

以下のコマンドでCloudFormationのテンプレートがCDKのコードから生成できるか確認する

cdk synth

(参考)cdk コマンドの機能を 実際に叩いて理解する 【 AWS CDK Command Line Interface 】

https://dev.classmethod.jp/articles/aws-cdk-command-line-interface/

結果

error TS2345: Argument of type 'this' is not assignable to parameter of type 'Construct'.

このエラーが出るのは、以下が原因らしい

The reason we get the “Argument of type is not assignable to parameter of type Construct” error in CDK is because we have different versions of CDK packages in the same CDK project.

https://bobbyhadz.com/blog/aws-cdk-not-assignable-to-type-construct

とりあえず一括更新

npm install -g npm-check-updates
ncu
ncu -u

次はこのエラーが出た

Argument of type ‘this’ is not assignable to parameter of type ‘Construct’.

どうも「cdk-ec2-key-pair」のバージョンが合わないようなので、この記事を参考に試してみる

https://dev.classmethod.jp/articles/build-ec2-key-pair-with-aws-cdk/

import * as cdk from '@aws-cdk/core';
import * as ec2 from '@aws-cdk/aws-ec2';        // Allows working with EC2 and VPC resources
import * as iam from '@aws-cdk/aws-iam';            // Allows working with IAM resources
// import * as s3assets from '@aws-cdk/aws-s3-assets'; // Allows managing files with S3
// import * as keypair from 'cdk-ec2-key-pair';        // Helper to create EC2 SSH keypairs
// import * as path from 'path';                       // Helper for working with file paths
import { CfnOutput, RemovalPolicy, Token } from '@aws-cdk/core';

export class CdkEc2Stack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    // Look up the default VPC
    
    const vpc = ec2.Vpc.fromLookup(this, "VPC", {
      isDefault: true
    });

    // Create a key pair to be used with this EC2 Instance
    // キーペア作成
    const cfnKeyPair = new ec2.CfnKeyPair(this, 'CfnKeyPair', {
      keyName: 'test-key-pair',
    })
    cfnKeyPair.applyRemovalPolicy(RemovalPolicy.DESTROY)

    // キーペア取得コマンドアウトプット
    new CfnOutput(this, 'GetSSHKeyCommand', {
      value: `aws ssm get-parameter --name /ec2/keypair/${cfnKeyPair.getAtt('KeyPairId')} --region ${this.region} --with-decryption --query Parameter.Value --output text`,
    })
    // Security group for the EC2 instance
    const securityGroup = new ec2.SecurityGroup(this, "SecurityGroup", {
      vpc,
      description: "Allow SSH (TCP port 22) and HTTP (TCP port 80) in",
      allowAllOutbound: true,
    });

    // Allow SSH access on port tcp/22
    securityGroup.addIngressRule(
      ec2.Peer.anyIpv4(),
      ec2.Port.tcp(22),
      "Allow SSH Access"
    );

    // IAM role to allow access to other AWS services
    const role = new iam.Role(this, "ec2Role", {
      assumedBy: new iam.ServicePrincipal("ec2.amazonaws.com"),
    });

    // IAM policy attachment to allow access to 
    role.addManagedPolicy(
      // AWS Systems ManagerはAWS でインフラストラクチャを表示および制御するために使用できる AWS のサービス
      iam.ManagedPolicy.fromAwsManagedPolicyName("AmazonSSMManagedInstanceCore")
    );

    // Look up the AMI Id for the Amazon Linux 2 Image with CPU Type X86_64
    const ami = new ec2.AmazonLinuxImage({
      generation: ec2.AmazonLinuxGeneration.AMAZON_LINUX_2,
      cpuType: ec2.AmazonLinuxCpuType.X86_64,
    });

    // Create the EC2 instance using the Security Group, AMI, and KeyPair defined.
    const ec2Instance = new ec2.Instance(this, "Instance", {
      vpc,
      instanceType: ec2.InstanceType.of(
        ec2.InstanceClass.T2,
        ec2.InstanceSize.MICRO
      ),
      machineImage: ami,
      securityGroup: securityGroup,
      keyName: Token.asString(cfnKeyPair.ref),
      role: role,
    });  

  }
}

次はこのエラー

This CDK CLI is not compatible with the CDK library used by your application. Please upgrade the CLI to the latest version.
(Cloud assembly schema version mismatch: Maximum schema version supported is 13.0.0, but found 20.0.0)

CDKのバージョンが古いようです

cdk --version
1.117.0 (build 0047c98)

これでCDKをアップデート

ncu -g aws-cdk
ncu itself cannot upgrade global packages. Run the following to upgrade all global packages:

npm -g install aws-cdk@2.37.1

ようやくcdk synthが成功しました

デプロイ

今どこのアカウントにつながっているのか確認

aws sts get-caller-identity

CDK を初めて使用するリージョンやアカウントでは cdk bootstrap する

cdk bootstrap aws://123456789012/us-east-1

https://aws.amazon.com/jp/getting-started/guides/setup-cdk/module-two/

デプロイコマンドを実行する

cdk deploy

これで指定したアカウント、リージョンにEC2インスタンスが生成される

EC2に接続

AWS Systems ManagerSession Managerセッションの開始でEC2にアクセスできる

「AWS Systems Manager/パラメータストア」でローカルからSSH接続するためのキーを取得可能

インスタンス削除

以下のコマンドを実行

cdk destroy

備考

  • 「@aws-cdk/core」は古いので「aws-cdk-lib」を使用した方がいい
  • 既存の環境からcdkのコードを生成したい場合は「https://former2.com/」が便利

(参考) CloudFormer2を使ってリソースを抽出してみた

https://zenn.dev/mid480/articles/aws-cloudformer2

コメントを残す

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