CloudFormationで簡単に機械学習の開発環境を整える
はじめに
ちょっと検討をしてみようと思うたびに、VPC作ってSubnet作って、InternetGatewayとElasticIP取得して、NatGateway設置して・・
と単純なprivate, publicサブネットを置くだけでも何度もやると面倒くさい。
特に機械学習開発環境代わりに使うような場合は、複数AZにまたがるような可用性云々じゃなくて、検討用土台をさくっと作りたい。
でもSageMakerのNotebookインスタンスじゃ物足りないという人がいると思う。
構成図
前回も紹介したこれを自動で作ることにする。
●ポイント
- 踏み台サーバーでセキュリティ対策
- NATゲートウェイでPrivate環境でもソフトを更新可能
- さくっと検討用に使いたいのでOneZone構成
自分の練習用
はまりどころ
いろいろハマったけど、下記はその一例。参考になれば。
NATGatewayでのElasticIPの指定
IPアドレスではなくIDで指定するため、下記のように"Fn::GetAtt::"を使って指定している。
NATGateway: Type: AWS::EC2::NatGateway Properties: AllocationId: Fn::GetAtt: - ElasticIP - AllocationId
NATGatewayへのRoute
RouteでGatewayIdではなく、NATGatewayIdを使う必要あり。
PrivateRoute: Type: AWS::EC2::Route Properties: NatGatewayId: !Ref NATGateway
EC2のSecurityGroupの設定はリストで
SecurityGroupIdsのように、複数形になっているのでリストで渡すことをお忘れなく。
PrivateInstance: Type: AWS::EC2::Instance Properties: SecurityGroupIds: - !Ref PrivateSecurityGroup
yamlファイル全体はこちら
これをcloud formationに入れることで一発で踏み台サーバーと検討用のprivateサーバーを起動することが可能。 インスタンスのファミリーとかサイズは適宜変えるとよい。
AWSTemplateFormatVersion: "2010-09-09" Description: OneZone VPC/Subnet/EC2 Create Parameters: # 踏み台サーバーはAmazonLinux & t2.microで簡素に BationHostImageId: Type: AWS::SSM::Parameter::Value<String> Default: /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 BationHostInstanceType: Type: String Default: t2.micro # 機械学習用インスタンスはDeepLearning AMIを使って、実験用と高機能用などを用意 PrivateImageId: Type: String Default: ami-088585cfb750459af PrivateInstanceType: Type: String Default: m5.2xlarge AllowedValues : ["t2.micro", "m5.2xlarge"] # SSHでつなぐための接続元IP(自分のIP) MyIP: Description: IP address allowed to access EC2 Type: String Default: 0.0.0.0/32 # SSH用のKeyはすでにある前提 KeyName: Description: The EC2 Key Pair to allow SSH access to the instance Type: "AWS::EC2::KeyPair::KeyName" Default: .pem Resources: # ##################################### # VPC & IG # ##################################### VPC: Type: AWS::EC2::VPC Properties: CidrBlock: 10.5.0.0/16 EnableDnsHostnames: false EnableDnsSupport: true InstanceTenancy: default Tags: - Key: Name Value: my-vpc-stack InternetGateway: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: my-ig-stack InternetGatewayAttachment: Type: AWS::EC2::VPCGatewayAttachment Properties: InternetGatewayId: !Ref InternetGateway VpcId: !Ref VPC # ##################################### # Subnet & NAT # ##################################### PublicSubnet: Type: AWS::EC2::Subnet Properties: AvailabilityZone: "ap-northeast-1a" CidrBlock: 10.5.0.0/24 MapPublicIpOnLaunch: true Tags: - Key: Name Value: public-subnet-stack VpcId: !Ref VPC PrivateSubnet: Type: AWS::EC2::Subnet Properties: AvailabilityZone: "ap-northeast-1a" CidrBlock: 10.5.1.0/24 MapPublicIpOnLaunch: false Tags: - Key: Name Value: private-subnet-stack VpcId: !Ref VPC NatIP: Type: AWS::EC2::EIP Properties: Domain: vpc Tags: - Key: Name Value: nat-eip-stack NATGateway: Type: AWS::EC2::NatGateway Properties: AllocationId: Fn::GetAtt: - NatIP - AllocationId SubnetId: !Ref PublicSubnet Tags: - Key: Name Value: my-nat-stack # ##################################### # RouteTable & Routing # ##################################### PublicRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: rt-public-stack PublicRoute: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PublicRouteTable DestinationCidrBlock: "0.0.0.0/0" GatewayId: !Ref InternetGateway PublicRouteAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PublicRouteTable SubnetId: !Ref PublicSubnet PrivateRouteTable: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref VPC Tags: - Key: Name Value: rt-private-stack PrivateRoute: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PrivateRouteTable DestinationCidrBlock: "0.0.0.0/0" NatGatewayId: !Ref NATGateway PrivateRouteAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: RouteTableId: !Ref PrivateRouteTable SubnetId: !Ref PrivateSubnet # ##################################### # SecurityGroup # ##################################### PublicSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Allow SSH to BationHost GroupName: allow-ssh-to-bation-stack VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: !Ref MyIP PrivateSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Allow SSH from bation GroupName: allow-ssh-from-bation-stack VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: 22 ToPort: 22 SourceSecurityGroupId: !Ref PublicSecurityGroup # ##################################### # EC2 # ##################################### BationHost: Type: AWS::EC2::Instance Properties: ImageId: !Ref BationHostImageId InstanceType: !Ref BationHostInstanceType KeyName: !Ref KeyName NetworkInterfaces: - AssociatePublicIpAddress: "true" DeviceIndex: "0" SubnetId: !Ref PublicSubnet GroupSet: - !Ref PublicSecurityGroup Tags: - Key: Name Value: bation-host-stack EC2IP: Type: AWS::EC2::EIP Properties: InstanceId: !Ref BationHost Tags: - Key: Name Value: ec2-eip-stack PrivateInstance: Type: AWS::EC2::Instance Properties: ImageId: !Ref PrivateImageId InstanceType: !Ref PrivateInstanceType KeyName: !Ref KeyName SubnetId: !Ref PrivateSubnet SecurityGroupIds: - !Ref PrivateSecurityGroup Tags: - Key: Name Value: private-instance-stack # SSH接続用にPublicとPrivateのIPを出力しておくと便利 Outputs: PublicIP: Value: !GetAtt BationHost.PublicIp Description: Public IP of BationHost PrivateIP: Value: !GetAtt PrivateInstance.PrivateIp Description: Private IP of EC2 instance