CloudFormation初心者がとりあえず実行してみたい時のチュートリアル

CloudFormation初心者がとりあえず実行してみたい時のチュートリアル:


はじめに

この記事はLIFULL Advent Calendar2018その2の22日目の記事です。

AWSでインフラ構築をしたことはあるけど、CloudFormationという単語はなんとなく避けておりました。

ですが、意を決して取り組んでみると思いの外簡単・便利だったので、とりあえず言葉だけ知っていて試してみたいと思っている方向けに、簡単に実行できるチュートリアルを作りました。

※テンプレートの説明は反響があれば別記事で書こうと思います。


CloudFormationを試す

今回、CloudFormation(CFNと略すらしいです)を使って構築するインフラ構成は下図のようなシンプルなものにしました。



構成図.png



準備

まず、AWSをcliで実行するためのインストールを行います。

$ sudo easy_install pip 
$ sudo pip install awscli 
$ aws --version 
次に、AWSコンソール上でアクセスキーを発行し、下記の通り登録を行います。

$ aws configure --profile cfn 
AWS Access Key ID [None]: 発行したアクセスキー 
AWS Secret Access Key [None]: 発行したシークレットアクセスキー 
Default region name [None]: ap-northeast-1 
Default output format [None]: 
また、インスタンスを作成する際に必要なキーペアをsampleという名前で作成してダウンロードしておきます。


テンプレートファイル

テンプレートファイルは、ページ下部のものをコピーしてください。(行数がすごいですが殆どサブネット関連の定義の繰り返しだったりします)

下記のコマンドでローカルからcfnを実行します。

※file://のパスはテンプレートを配置した場所によって異なります

$ ls -al 
total 24 
-rw-r--r--  1 shodak  shodak  10170 12 22 17:59 sample-template.yml 
$ aws cloudformation create-stack --stack-name sample --template-body file://sample-template.yml --profile cfn 
下記のリンクから実際にスタックが実行されているところが見れると思います。
https://ap-northeast-1.console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks

構成図の通りにできているかと思います。

試しにbastionサーバーとapplicationサーバーにsshログインしてみます。

※面倒なので.ssh/configに下記の設定を追加しました。

~/.ssh/config
Host sample-bastion 
  User ec2-user 
  HostName 18.182.92.135 
  Port 22 
  Identityfile ~/.ssh/sample.pem 
 
Host sample-application 
  User ec2-user 
  HostName 172.31.254.253 
  Port 22 
  Identityfile ~/.ssh/sample.pem 
  ProxyCommand ssh -W %h:%p sample-bastion 
$ mv Downloads/sample.pem ~/.ssh/ 
# 鍵の権限変更を忘れずに 
$ chmod 400 ~/.ssh/sample.pem 
$ ssh sample-bastion 
 
       __|  __|_  ) 
       _|  (     /   Amazon Linux 2 AMI 
      ___|\___|___| 
 
https://aws.amazon.com/amazon-linux-2/ 
15 package(s) needed for security, out of 16 available 
Run "sudo yum update" to apply all updates. 
[ec2-user@ip-172-31-0-65 ~]$ 
bastionサーバーにログインできたので、applicationサーバーも試します。

$ ssh sample-application 
 
       __|  __|_  ) 
       _|  (     /   Amazon Linux 2 AMI 
      ___|\___|___| 
 
https://aws.amazon.com/amazon-linux-2/ 
[ec2-user@ip-172-31-254-103 ~]$ curl http://google.com 
<HTML><HEAD><meta http-equiv="content-type" content="text/html;charset=utf-8"> 
<TITLE>301 Moved</TITLE></HEAD><BODY> 
<H1>301 Moved</H1> 
The document has moved 
<A HREF="http://www.google.com/">here</A>. 
</BODY></HTML> 
applicationサーバーにもログインでき、外部にも疎通していることが確認できました。

一通り確認したらstackを削除しましょう。

stackを削除することで、cloudformationによって生成されたリソースが全て削除されるため、お試しで環境を作りたい時に撤収が捗ります。

※今回実行したサンプルテンプレート

sample-template.yml
AWSTemplateFormatVersion: 2010-09-09 
Description: Sample-template 
Resources: 
  VpcTemplate: 
    Type: AWS::EC2::VPC 
    Properties: 
      CidrBlock: 172.31.0.0/16 
      EnableDnsSupport: true 
      EnableDnsHostnames: true 
      InstanceTenancy: default 
      Tags: 
        - Key: Name 
          Value: sample 
  BastionEIP: 
    Type: AWS::EC2::EIP 
    Properties: 
      InstanceId: 
        Ref: BastionInstance 
      Domain: 
        Ref: VpcTemplate 
  NatGatewayEIP: 
    Type: AWS::EC2::EIP 
    Properties: 
      Domain: 
        Ref: VpcTemplate 
  IGW: 
    Type: AWS::EC2::InternetGateway 
    Properties: 
      Tags: 
        - Key: Name 
          Value: sample-igw 
  NatGateway: 
    Type: AWS::EC2::NatGateway 
    Properties: 
      AllocationId: 
        Fn::GetAtt: 
        - NatGatewayEIP 
        - AllocationId 
      SubnetId: 
        Ref: PublicSubnet1a 
      Tags: 
        - Key: Name 
          Value: sample-nat-gateway 
  VpcIgwAttach: 
    Type: AWS::EC2::VPCGatewayAttachment 
    Properties: 
      VpcId: 
        Ref: VpcTemplate 
      InternetGatewayId: 
        Ref: IGW 
  PublicSubnet1a: 
    Type: AWS::EC2::Subnet 
    Properties: 
      VpcId: 
        Ref: VpcTemplate 
      CidrBlock: 172.31.0.0/24 
      AvailabilityZone: ap-northeast-1a 
      Tags: 
        - Key: Name 
          Value: public-subnet-1a 
  PublicSubnet1c: 
    Type: AWS::EC2::Subnet 
    Properties: 
      VpcId: 
        Ref: VpcTemplate 
      CidrBlock: 172.31.1.0/24 
      AvailabilityZone: ap-northeast-1c 
      Tags: 
        - Key: Name 
          Value: public-subnet-1c 
  PrivateSubnet1a: 
    Type: AWS::EC2::Subnet 
    Properties: 
      VpcId: 
        Ref: VpcTemplate 
      CidrBlock: 172.31.254.0/24 
      AvailabilityZone: ap-northeast-1a 
      Tags: 
        - Key: Name 
          Value: private-subnet-1a 
  PublicSubnetRouteTable: 
    Type: AWS::EC2::RouteTable 
    Properties: 
      VpcId: 
        Ref: VpcTemplate 
      Tags: 
        - Key: Name 
          Value: public-igw 
  PrivateSubnetRouteTable: 
    Type: AWS::EC2::RouteTable 
    Properties: 
      VpcId: 
        Ref: VpcTemplate 
      Tags: 
        - Key: Name 
          Value: private-nat 
  PublicSubnetRouteTableAssociationA: 
    Type: AWS::EC2::SubnetRouteTableAssociation 
    Properties: 
      SubnetId: 
        Ref: PublicSubnet1a 
      RouteTableId: 
        Ref: PublicSubnetRouteTable 
  PublicSubnetRouteTableAssociationC: 
    Type: AWS::EC2::SubnetRouteTableAssociation 
    Properties: 
      SubnetId: 
        Ref: PublicSubnet1c 
      RouteTableId: 
        Ref: PublicSubnetRouteTable 
  PrivateSubnetRouteTableAssociationA: 
    Type: AWS::EC2::SubnetRouteTableAssociation 
    Properties: 
      SubnetId: 
        Ref: PrivateSubnet1a 
      RouteTableId: 
        Ref: PrivateSubnetRouteTable 
  RouteTableIGWAssociation: 
    Type: AWS::EC2::Route 
    Properties: 
      DestinationCidrBlock: 0.0.0.0/0 
      RouteTableId: 
        Ref: PublicSubnetRouteTable 
      GatewayId: 
        Ref: IGW 
  RouteTableNatGatewayAssociation: 
    Type: AWS::EC2::Route 
    Properties: 
      DestinationCidrBlock: 0.0.0.0/0 
      RouteTableId: 
        Ref: PrivateSubnetRouteTable 
      NatGatewayId: 
        Ref: NatGateway 
  AclPublic: 
    Type: AWS::EC2::NetworkAcl 
    Properties: 
      VpcId: 
        Ref: VpcTemplate 
      Tags: 
        - Key: Name 
          Value: public 
  AclPrivate: 
    Type: AWS::EC2::NetworkAcl 
    Properties: 
      VpcId: 
        Ref: VpcTemplate 
      Tags: 
        - Key: Name 
          Value: private 
  AclPublicInSsh: 
    Type: AWS::EC2::NetworkAclEntry 
    Properties: 
      CidrBlock: 0.0.0.0/0 
      Egress: false 
      Protocol: 6 
      PortRange: 
        From: 22 
        To: 22 
      RuleAction: allow 
      RuleNumber: 100 
      NetworkAclId: 
        Ref: AclPublic 
  AclPublicInHttp: 
    Type: AWS::EC2::NetworkAclEntry 
    Properties: 
      CidrBlock: 0.0.0.0/0 
      Egress: false 
      Protocol: 6 
      PortRange: 
        From: 80 
        To: 80 
      RuleAction: allow 
      RuleNumber: 200 
      NetworkAclId: 
        Ref: AclPublic 
  AclPublicInHttps: 
    Type: AWS::EC2::NetworkAclEntry 
    Properties: 
      CidrBlock: 0.0.0.0/0 
      Egress: false 
      Protocol: 6 
      PortRange: 
        From: 443 
        To: 443 
      RuleAction: allow 
      RuleNumber: 300 
      NetworkAclId: 
        Ref: AclPublic 
  AclPublicEphemeralIn: 
    Type: AWS::EC2::NetworkAclEntry 
    Properties: 
      CidrBlock: 0.0.0.0/0 
      Egress: false 
      Protocol: 6 
      PortRange: 
        From: 1024 
        To: 65535 
      RuleAction: allow 
      RuleNumber: 400 
      NetworkAclId: 
        Ref: AclPublic 
  AclPublicIn: 
    Type: AWS::EC2::NetworkAclEntry 
    Properties: 
      CidrBlock: 172.31.0.0/23 
      Egress: false 
      Protocol: -1 
      RuleAction: allow 
      RuleNumber: 500 
      NetworkAclId: 
        Ref: AclPublic 
  AclPublicOutSsh: 
    Type: AWS::EC2::NetworkAclEntry 
    Properties: 
      CidrBlock: 0.0.0.0/0 
      Egress: true 
      Protocol: 6 
      PortRange: 
        From: 22 
        To: 22 
      RuleAction: allow 
      RuleNumber: 100 
      NetworkAclId: 
        Ref: AclPublic 
  AclPublicOutHttp: 
    Type: AWS::EC2::NetworkAclEntry 
    Properties: 
      CidrBlock: 0.0.0.0/0 
      Egress: true 
      Protocol: 6 
      PortRange: 
        From: 80 
        To: 80 
      RuleAction: allow 
      RuleNumber: 200 
      NetworkAclId: 
        Ref: AclPublic 
  AclPublicOutHttps: 
    Type: AWS::EC2::NetworkAclEntry 
    Properties: 
      CidrBlock: 0.0.0.0/0 
      Egress: true 
      Protocol: 6 
      PortRange: 
        From: 443 
        To: 443 
      RuleAction: allow 
      RuleNumber: 300 
      NetworkAclId: 
        Ref: AclPublic 
  AclPublicEphemeralOut: 
    Type: AWS::EC2::NetworkAclEntry 
    Properties: 
      CidrBlock: 0.0.0.0/0 
      Egress: true 
      Protocol: 6 
      PortRange: 
        From: 1024 
        To: 65535 
      RuleAction: allow 
      RuleNumber: 400 
      NetworkAclId: 
        Ref: AclPublic 
  AclPublicOut: 
    Type: AWS::EC2::NetworkAclEntry 
    Properties: 
      CidrBlock: 172.31.0.0/23 
      Egress: true 
      Protocol: -1 
      RuleAction: allow 
      RuleNumber: 500 
      NetworkAclId: 
        Ref: AclPublic 
  AclPrivateInSsh: 
    Type: AWS::EC2::NetworkAclEntry 
    Properties: 
      CidrBlock: 172.31.0.0/23 
      Egress: false 
      Protocol: 6 
      PortRange: 
        From: 22 
        To: 22 
      RuleAction: allow 
      RuleNumber: 100 
      NetworkAclId: 
        Ref: AclPrivate 
  AclPrivateInHttp: 
    Type: AWS::EC2::NetworkAclEntry 
    Properties: 
      CidrBlock: 172.31.0.0/23 
      Egress: false 
      Protocol: 6 
      PortRange: 
        From: 80 
        To: 80 
      RuleAction: allow 
      RuleNumber: 200 
      NetworkAclId: 
        Ref: AclPrivate 
  AclPrivateInHttps: 
    Type: AWS::EC2::NetworkAclEntry 
    Properties: 
      CidrBlock: 172.31.0.0/23 
      Egress: false 
      Protocol: 6 
      PortRange: 
        From: 443 
        To: 443 
      RuleAction: allow 
      RuleNumber: 300 
      NetworkAclId: 
        Ref: AclPrivate 
  AclPrivateEphemeralIn: 
    Type: AWS::EC2::NetworkAclEntry 
    Properties: 
      CidrBlock: 0.0.0.0/0 
      Egress: false 
      Protocol: 6 
      PortRange: 
        From: 1024 
        To: 65535 
      RuleAction: allow 
      RuleNumber: 400 
      NetworkAclId: 
        Ref: AclPrivate 
  AclPrivateOutHttp: 
    Type: AWS::EC2::NetworkAclEntry 
    Properties: 
      CidrBlock: 0.0.0.0/0 
      Egress: true 
      Protocol: 6 
      PortRange: 
        From: 80 
        To: 80 
      RuleAction: allow 
      RuleNumber: 200 
      NetworkAclId: 
        Ref: AclPrivate 
  AclPrivateOutHttps: 
    Type: AWS::EC2::NetworkAclEntry 
    Properties: 
      CidrBlock: 0.0.0.0/0 
      Egress: true 
      Protocol: 6 
      PortRange: 
        From: 443 
        To: 443 
      RuleAction: allow 
      RuleNumber: 300 
      NetworkAclId: 
        Ref: AclPrivate 
  AclPrivateEphemeralOut: 
    Type: AWS::EC2::NetworkAclEntry 
    Properties: 
      CidrBlock: 0.0.0.0/0 
      Egress: true 
      Protocol: 6 
      PortRange: 
        From: 1024 
        To: 65535 
      RuleAction: allow 
      RuleNumber: 400 
      NetworkAclId: 
        Ref: AclPrivate 
  PublicSubnet1aAclAssociation: 
    Type: AWS::EC2::SubnetNetworkAclAssociation 
    Properties: 
      SubnetId: 
        Ref: PublicSubnet1a 
      NetworkAclId: 
        Ref: AclPublic 
  PublicSubnet1cAclAssociation: 
    Type: AWS::EC2::SubnetNetworkAclAssociation 
    Properties: 
      SubnetId: 
        Ref: PublicSubnet1c 
      NetworkAclId: 
        Ref: AclPublic 
  PrivateSubnetAclAssociation: 
    Type: AWS::EC2::SubnetNetworkAclAssociation 
    Properties: 
      SubnetId: 
        Ref: PrivateSubnet1a 
      NetworkAclId: 
        Ref: AclPrivate 
  BastionSecurityGroup: 
    Type: AWS::EC2::SecurityGroup 
    Properties: 
      VpcId: 
        Ref: VpcTemplate 
      GroupDescription: SG for Bastion 
      SecurityGroupIngress: 
        - IpProtocol: tcp 
          FromPort: 22 
          ToPort: 22 
          CidrIp: 0.0.0.0/0 
      Tags: 
        - Key: Name 
          Value: bastion-sg 
  ApplicationSecurityGroup: 
    Type: AWS::EC2::SecurityGroup 
    Properties: 
      VpcId: 
        Ref: VpcTemplate 
      GroupDescription: SG for Application 
      SecurityGroupIngress: 
        - IpProtocol: tcp 
          FromPort: 22 
          ToPort: 22 
          SourceSecurityGroupId: 
            Ref: BastionSecurityGroup 
      Tags: 
        - Key: Name 
          Value: bastion-sg 
  BastionInstance: 
    Type: AWS::EC2::Instance 
    Properties: 
      LaunchTemplate: 
        LaunchTemplateId: 
          Ref: BastionInstanceLaunchTemplate 
        Version: 
          Fn::GetAtt: 'BastionInstanceLaunchTemplate.LatestVersionNumber' 
      SubnetId: 
        Ref: PublicSubnet1a 
      Tags: 
        - Key: Name 
          Value: bastion 
  ApplicationInstance: 
    Type: AWS::EC2::Instance 
    Properties: 
      LaunchTemplate: 
        LaunchTemplateId: 
          Ref: ApplicationInstanceLaunchTemplate 
        Version: 
          Fn::GetAtt: 'ApplicationInstanceLaunchTemplate.LatestVersionNumber' 
      SubnetId: 
        Ref: PrivateSubnet1a 
      Tags: 
        - Key: Name 
          Value: application 
  BastionInstanceLaunchTemplate: 
    Type: AWS::EC2::LaunchTemplate 
    Properties: 
      LaunchTemplateData: 
        SecurityGroupIds: 
          - Ref: BastionSecurityGroup 
        InstanceInitiatedShutdownBehavior: stop 
        KeyName: sample 
        ImageId: ami-0a2de1c3b415889d2 
        Monitoring: 
          Enabled: false 
        CreditSpecification: 
          CpuCredits: standard 
        InstanceType: t2.micro 
        BlockDeviceMappings: 
          - DeviceName: /dev/xvda 
            Ebs: 
              VolumeSize: 8 
              VolumeType: gp2 
              DeleteOnTermination: true 
  ApplicationInstanceLaunchTemplate: 
    Type: AWS::EC2::LaunchTemplate 
    Properties: 
      LaunchTemplateData: 
        SecurityGroupIds: 
          - Ref: ApplicationSecurityGroup 
        InstanceInitiatedShutdownBehavior: stop 
        KeyName: sample 
        ImageId: ami-0a2de1c3b415889d2 
        Monitoring: 
          Enabled: false 
        CreditSpecification: 
          CpuCredits: standard 
        InstanceType: t2.micro 
        BlockDeviceMappings: 
          - DeviceName: /dev/xvda 
            Ebs: 
              VolumeSize: 8 
              VolumeType: gp2 
              DeleteOnTermination: true 


最後に

cfnで何かのリソースを定義したい時は、公式のリファレンスをみつつ、具体例が欲しいところはググって調べています。

sampleのテンプレートではパラメータを活用していなかったり、NACLの定義のところが冗長だったりするので、もっと簡潔にかけるようにこれから努力したいと思います。

コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)