LoginSignup
3
0

More than 1 year has passed since last update.

[AWS CDK] Private Subnetで運用するBatchコンピューティング環境(EC2タイプ)を構築した

Last updated at Posted at 2020-08-24

概要

CDKを用いて,AWS Batchのコンピューティング環境(EC2起動タイプ)を,インターネットとの通信経路を持たないVPCで起動する方法をまとめました.

Batchのコンピューティング環境は,ECSクラスタとして作成されます.なので,ECSクラスタが展開できるVPC環境を準備してあげればOKです.

なぜそんなことをしたのか?

Batchで高負荷な計算処理(シミュレーション)を行う環境1を構築していたのですが,セキュリティ上の理由から,「インターネット経由の通信が存在しない環境でで」との要件があったためです.

検証環境

  • CDK 1.59.0, Typesccript
  • 東京リージョン (ap-northeast-1) 2

VPC Endpointを設置する

NAT GatewayやInternet Gateway等との通信経路が一切ないSubnetを選択しても,コンピューティング環境の作成自体は正常に終了します(してしまいます).

しかし,この状態では,ECSのコントロールプレーンやECRリポジトリとの通信もできず,コンピューティング環境を利用することができません.

そこで,必要なプライベート通信経路を確保するため,VPC Endpointを設置します.

必要なVPC Endpointは,下記のとおりです.

  • ECS コントロールプレーンとの通信経路

    3つのInterface endpointが必要です(公式ドキュメントはこちら).

    • com.amazonaws.ap-northeast-1.ecs-agent
    • com.amazonaws.ap-northeast-1.ecs-telemetry
    • com.amazonaws.ap-northeast-1.ecs
  • ECR リポジトリとの通信経路

    2つのInterface endpointとS3 gateway endpointが必要です(公式ドキュメントはこちら).

    • com.amazonaws.ap-northeast-1.ecr.dkr
    • com.amazonaws.ap-northeast-1.ecr.api
    • com.amazonaws.ap-northeast-1.s3
  • (用途によって) CloudWatch Logsとの通信経路

    CloudWatch Logsへログを流したい場合には,追加で下記のInterface endpointも設置してください(公式ドキュメントはこちら).

    • com.amazonaws.ap-northeast-1.logs

CDKで実装する

それでは,上述の環境をCDKで構築していきたいと思います.

Importするモジュール

import ec2 = require('@aws-cdk/aws-ec2');
import batch = require('@aws-cdk/aws-batch');

VPC

まずは,VPCを作成します.今回は,インターネットとの通信経路を持たないVPCを作成するので,
VPCコンストラクタに,下記のように引数を与えます.

const vpc = new ec2.Vpc(this, 'vpc', {
        cidr: "10.0.0.0/16", // ここは環境に応じて変更してください
        maxAzs: 3, // EC2を分散配置する際の,最大AZ数を指定する
        subnetConfiguration: [{
            cidrMask: 18, // ここは環境に応じて変更してください
            name: 'for-batch-compute-env',
            subnetType: ec2.SubnetType.ISOLATED, // ISOLATEDを指定する
        }]
    });

subnetTypeにISOLATEDを指定することがポイントです.こうすると,NAT Gatewayを設置しないVPCを構築できます.

(他にPRIVATEPUBLICを指定できますが,これらはNAT Gatewayを設置する構成となります.)

Security Group, Subnet Selection

次にEC2用のセキュリティグループを設定します.今回は,同一VPC内のみの通信を許可しました.

const securityGroup = new ec2.SecurityGroup(
        this, 'batch-compute-env-sg',
        {
            vpc: vpc,
            allowAllOutbound: true,
            description: `For batch compute environment.`,
            securityGroupName: `for-batch-compute-environment`
        });
securityGroup.addIngressRule(
    ec2.Peer.ipv4(vpc.vpcCidrBlock),
    ec2.Port.allTraffic(),
    `Allow inside security group`
);

後ほど用いる,サブネット選択の変数も定義しておきます.

const subnetSelection: ec2.SubnetSelection = {
    subnetType: ec2.SubnetType.ISOLATED, onePerAz: true
};

VPC Endpoint

VPCを作成したら,必要なVPC endpointを設置していきます.CDKでは,専用のコンストラクタがあるので,VPC endpoint設置も簡単です.

S3向けのendpointのみgateway endpointでコンストラクタが違うので注意してください.

// Create VPC Endpoints for ECS
new ec2.InterfaceVpcEndpoint(
    this, `vpce-ecs-agent`, {
    service: ec2.InterfaceVpcEndpointAwsService.ECS_AGENT,
    open: true,
    privateDnsEnabled: true,
    vpc: vpc,
    subnets: { subnetType: ec2.SubnetType.ISOLATED },
    securityGroups: [securityGroup]
});
new ec2.InterfaceVpcEndpoint(
    this, `vpce-ecs-telemetry`, {
    service: ec2.InterfaceVpcEndpointAwsService.ECS_TELEMETRY,
    open: true,
    privateDnsEnabled: true,
    vpc: vpc,
    subnets: { subnetType: ec2.SubnetType.ISOLATED },
    securityGroups: [securityGroup]
});
new ec2.InterfaceVpcEndpoint(
    this, `vpce-ecs`, {
    service: ec2.InterfaceVpcEndpointAwsService.ECS,
    open: true,
    privateDnsEnabled: true,
    vpc: vpc,
    subnets: { subnetType: ec2.SubnetType.ISOLATED },
    securityGroups: [securityGroup]
});

// Create VPC Endpoints for ECR
new ec2.InterfaceVpcEndpoint(
    this, `vpce-ecr-docker`, {
    service: ec2.InterfaceVpcEndpointAwsService.ECR_DOCKER,
    open: true,
    privateDnsEnabled: true,
    vpc: vpc,
    subnets: { subnetType: ec2.SubnetType.ISOLATED },
    securityGroups: [securityGroup]
});
new ec2.InterfaceVpcEndpoint(
    this, `vpce-ecr`, {
    service: ec2.InterfaceVpcEndpointAwsService.ECR,
    open: true,
    privateDnsEnabled: true,
    vpc: vpc,
    subnets: { subnetType: ec2.SubnetType.ISOLATED },
    securityGroups: [securityGroup]
});

new ec2.GatewayVpcEndpoint(
    this, `vpce-s3`, {
    service: ec2.GatewayVpcEndpointAwsService.S3,
    vpc: vpc,
    subnets: [subnetSelection],
});

Batch Computing環境

VPCの準備ができたらBatchコンピューティング環境を作成していきます.


const computeEnv = new batch.ComputeEnvironment(this, 'cluster', {
    computeEnvironmentName: `my-batch-cluster`,
    enabled: true,
    managed: true,
    computeResources: {
        type: batch.ComputeResourceType.ON_DEMAND,
        // spotインスタンスを使いたいときはSPOTを指定
        // type: batch.ComputeResourceType.SPOT,
        instanceTypes: [new ec2.InstanceType("t3small")], // インスタンスタイプ
        vpc: vpc, // 先ほど作成したVPC
        vpcSubnets: subnetSelection, // Isolated subnetを指定
        securityGroups: [securityGroup], // インスタンスのセキュリティグループを指定
        minvCpus: 0, // min VCPU数を指定
        desiredvCpus: 0, // desired VCPU数を指定 (minとmaxの間の値)
        maxvCpus: 4, // max VCPU数を指定
        // 特定のAMIを指定したい場合はAMI IDの変数も与えます.
        // image: new ec2.GenericLinuxImage({ 'ap-northeast-1': "AMI-ID" }),
    }
});

注意点

  • VPCエンドポイントは,利用状況に関わらず立てておくだけで料金が発生します.ECSクラスタ(EC2タイプ)では,最低6つのエンドポイントが必要で,そこそこの金額になります.お試しする際は,終わったら全てのリソースを削除することをお忘れなく!
  • 本番で運用する際には,コストに見合うかの判断が大切ですね.状況によっては,セキュリティを担保する他の方法を検討したほうが良さそうです.
  • EFSなど他のサービスも使用したい場合は,それぞれに対応したエンドポイント設置などの対応が必要です.

参考

Fargate起動タイプでは,必要なエンドポイントを減らせるようです.詳しくは,こちらのウェブサイトをご参照ください(分かりやすくまとまっており,私も助かりました).

ソースコード

GitHub(準備中)


  1. 合計で数千vCPUのクラスタを初めて動かしたときは,「今まで数日かかっていた計算が,こんなに早く終わるのか!!」という興奮と,「終わったらちゃんとスケールインされるよね...??」という心配とで,ドキドキでした. 

  2. 他のリージョンで展開したい場合は,適宜リージョン名を読み替えていただければと思います. 

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0