0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

自作RailsアプリをAWS上に開発する 〜CloudFormationを用いた環境構築〜

Posted at

1. 概要

AWSサービスの一部にCloudFormationを用いて自作のRailsを公開するための環境を構築する。
長期間利用しない場合はCloudFormationスタックを削除することで、コストを抑える。
ECSのDokcerコンテナ上でRailsアプリを立ち上げ、RDS PostgreSQL上のデータベースと接続してアプリを稼働させる。

2. 使用するAWSサービス

RailsアプリをAWS上で稼働させるために、以下のAWSサービスを使用する。
なお、CloudFormationではなく手動作成したほうが運用性が高いもの、検証過程で作成済みであり、テンプレート化する必要がないものについてはテンプレート化の対象外としている。

  • VPC(CloudFormationで定義)
  • RDS(CloudFormationで定義)
  • ALB(CloudFormationで定義)
  • CloudFront(CloudFormationで定義)
  • ECS
  • Route53
  • ACM
  • IAM
  • SSM Parameter Store

3. 構成図

alcohol_構成図 (1).png

4. 構築方法

  • 大規模なシステムでは、AWSサービスの種別、ライフサイクル、依存度、開発部署、等様々な観点でCloudFormationテンプレートを分割したほうが運用保守する上で便利だが、今回構築するシステムの規模は小さいため、一つのテンプレートにまとめて定義する
  • CloudFormationで構築するAWSリソースの設定情報を整理したプロンプトを入力し、GitHub Copilotに読み込ませることで、テンプレートを作成した。
    詳細については以下の記事に整理している。

5. 構築方法

出来上がったテンプレートファイルは以下の通り。
ただしRailsアプリを稼働するためには、以下のテンプレートのみではアプリの実行環境は定義できないため、追加でECS、IAM等のサービスを手動構築する必要があるため注意。

app-stack.yml
AWSTemplateFormatVersion: '2010-09-09'
Mappings:
  DefaultVPCID:
    VPC:
      Id: vpc-XXXXXXXXXXXXXXXX
  DefaultIGWID:
    IGW:
      Id: igw-XXXXXXXXXXXXXXXX

Resources:
  # VPC Resources
  AlcoholPubSubnet01:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !FindInMap [DefaultVPCID, VPC, Id]
      CidrBlock: 172.31.0.0/27
      AvailabilityZone: ap-northeast-1a
      Tags:
        - Key: Name
          Value: alcohol-pub-subnet-01

  AlcoholPubSubnet02:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !FindInMap [DefaultVPCID, VPC, Id]
      CidrBlock: 172.31.0.32/27
      AvailabilityZone: ap-northeast-1c
      Tags:
        - Key: Name
          Value: alcohol-pub-subnet-02

  AlcoholPrvSubnet01:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !FindInMap [DefaultVPCID, VPC, Id]
      CidrBlock: 172.31.0.64/27
      AvailabilityZone: ap-northeast-1a
      Tags:
        - Key: Name
          Value: alcohol-prv-subnet-01

  AlcoholPrvSubnet02:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !FindInMap [DefaultVPCID, VPC, Id]
      CidrBlock: 172.31.0.96/27
      AvailabilityZone: ap-northeast-1c
      Tags:
        - Key: Name
          Value: alcohol-prv-subnet-02

  AlcoholRouteTablePub:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !FindInMap [DefaultVPCID, VPC, Id]
      Tags:
        - Key: Name
          Value: alcohol-routetbl-pub

  AlcoholRouteTablePrv:
    Type: AWS::EC2::RouteTable
    Properties:
      VpcId: !FindInMap [DefaultVPCID, VPC, Id]
      Tags:
        - Key: Name
          Value: alcohol-routetbl-prv

  AlcoholRoutePub:
    Type: AWS::EC2::Route
    Properties:
      RouteTableId: !Ref AlcoholRouteTablePub
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !FindInMap [DefaultIGWID, IGW, Id]

  AlcoholSubnetRouteTableAssociationPub01:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref AlcoholPubSubnet01
      RouteTableId: !Ref AlcoholRouteTablePub

  AlcoholSubnetRouteTableAssociationPub02:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref AlcoholPubSubnet02
      RouteTableId: !Ref AlcoholRouteTablePub

  AlcoholSubnetRouteTableAssociationPrv01:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref AlcoholPrvSubnet01
      RouteTableId: !Ref AlcoholRouteTablePrv

  AlcoholSubnetRouteTableAssociationPrv02:
    Type: AWS::EC2::SubnetRouteTableAssociation
    Properties:
      SubnetId: !Ref AlcoholPrvSubnet02
      RouteTableId: !Ref AlcoholRouteTablePrv

  AlcoholSGALB:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: ALB security group
      VpcId: !FindInMap [DefaultVPCID, VPC, Id]
      Tags:
        - Key: Name
          Value: alcohol-sg-alb

  AlcoholSGECS:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: ECS security group
      VpcId: !FindInMap [DefaultVPCID, VPC, Id]
      Tags:
        - Key: Name
          Value: alcohol-sg-ecs

  AlcoholSGRDS:
    Type: AWS::EC2::SecurityGroup
    Properties:
      GroupDescription: RDS security group
      VpcId: !FindInMap [DefaultVPCID, VPC, Id]
      Tags:
        - Key: Name
          Value: alcohol-sg-rds

  AlcoholSGALBIngressHTTP:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref AlcoholSGALB
      IpProtocol: tcp
      FromPort: 80
      ToPort: 80
      CidrIp: 0.0.0.0/0

  AlcoholSGALBIngressHTTPS:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref AlcoholSGALB
      IpProtocol: tcp
      FromPort: 443
      ToPort: 443
      CidrIp: 0.0.0.0/0

  AlcoholSGALBEgress:
    Type: AWS::EC2::SecurityGroupEgress
    Properties:
      GroupId: !Ref AlcoholSGALB
      IpProtocol: tcp
      FromPort: 80
      ToPort: 80
      DestinationSecurityGroupId: !Ref AlcoholSGECS

  AlcoholSGECSIngress:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref AlcoholSGECS
      IpProtocol: tcp
      FromPort: 80
      ToPort: 80
      SourceSecurityGroupId: !Ref AlcoholSGALB

  AlcoholSGECSEgress:
    Type: AWS::EC2::SecurityGroupEgress
    Properties:
      GroupId: !Ref AlcoholSGECS
      IpProtocol: tcp
      FromPort: 5432
      ToPort: 5432
      DestinationSecurityGroupId: !Ref AlcoholSGRDS

  AlcoholSGECSEgressHTTPS:
    Type: AWS::EC2::SecurityGroupEgress
    Properties:
      GroupId: !Ref AlcoholSGECS
      IpProtocol: tcp
      FromPort: 443
      ToPort: 443
      CidrIp: 0.0.0.0/0

  AlcoholSGECSEgressSMTP:
    Type: AWS::EC2::SecurityGroupEgress
    Properties:
      GroupId: !Ref AlcoholSGECS
      IpProtocol: tcp
      FromPort: 587
      ToPort: 587
      CidrIp: 0.0.0.0/0

  AlcoholSGRDSIngress:
    Type: AWS::EC2::SecurityGroupIngress
    Properties:
      GroupId: !Ref AlcoholSGRDS
      IpProtocol: tcp
      FromPort: 5432
      ToPort: 5432
      SourceSecurityGroupId: !Ref AlcoholSGECS

  # RDS Resources
  AlcoholRDSSubnetGroup:
    Type: AWS::RDS::DBSubnetGroup
    Properties:
      DBSubnetGroupDescription: Subnet group for RDS
      SubnetIds:
        - !Ref AlcoholPrvSubnet01
        - !Ref AlcoholPrvSubnet02
      DBSubnetGroupName: alcohol-subnet-group

  AlcoholRDSInstance:
    Type: AWS::RDS::DBInstance
    Properties:
      DBInstanceIdentifier: alcohol-rds
      AllocatedStorage: 20
      DBInstanceClass: db.t3.micro
      Engine: postgres
      MasterUsername: postgres # ユーザー名は適宜変更してください
      MasterUserPassword: password # パスワードは適宜変更してください
      DBSubnetGroupName: !Ref AlcoholRDSSubnetGroup
      VPCSecurityGroups:
        - !Ref AlcoholSGRDS
      PubliclyAccessible: false
      AvailabilityZone: ap-northeast-1a
      DBName: Alcohol_production

  # ALB Resources
  AlcoholTargetGroup:
    Type: AWS::ElasticLoadBalancingV2::TargetGroup
    Properties:
      Name: alcohol-target-group
      Port: 80
      Protocol: HTTP
      VpcId: !FindInMap [DefaultVPCID, VPC, Id]
      TargetType: ip

  AlcoholALB:
    Type: AWS::ElasticLoadBalancingV2::LoadBalancer
    Properties:
      Name: alcohol-alb
      Subnets:
        - !Ref AlcoholPubSubnet01
        - !Ref AlcoholPubSubnet02
      SecurityGroups:
        - !Ref AlcoholSGALB

  AlcoholALBListenerHTTP: #リスナーはECSサービス作成時/作成後に手動設定するためダミーのリスナーを設定しておく
    Type: AWS::ElasticLoadBalancingV2::Listener
    Properties:
      LoadBalancerArn: !Ref AlcoholALB
      Port: 8080
      Protocol: HTTP
      DefaultActions:
        - Type: forward
          TargetGroupArn: !Ref AlcoholTargetGroup

  # CloudFront Resources
  AlcoholCloudFrontDistribution:
    Type: AWS::CloudFront::Distribution
    Properties:
      DistributionConfig:
        Origins:
          - DomainName: alb.stop-deisui.com
            Id: alcohol-alb-origin
            CustomOriginConfig:
              HTTPPort: 80
              HTTPSPort: 443
              OriginProtocolPolicy: match-viewer
        Enabled: true
        DefaultCacheBehavior:
          TargetOriginId: alcohol-alb-origin
          ViewerProtocolPolicy: redirect-to-https
          AllowedMethods:
            - GET
            - HEAD
            - OPTIONS
            - PUT
            - POST
            - PATCH
            - DELETE
          CachedMethods:
            - GET
            - HEAD
          ForwardedValues:
            QueryString: false
          CachePolicyId: 83da9c7e-98b4-4e11-a168-04f0df8e2c65 #UseOriginCacheControlHeaders
          OriginRequestPolicyId: 216adef6-5c7f-47e4-b989-5492eafa07d3 #AllViewers
          ResponseHeadersPolicyId: 60669652-455b-4ae9-85a4-c4c02393f86c #SimpleCORS
        ViewerCertificate:
          AcmCertificateArn: !Sub arn:aws:acm:us-east-1:${AWS::AccountId}:certificate/XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX
          SslSupportMethod: sni-only
        Aliases:
          - XXXX.com

6. 結果

アプリの実行環境を構築できた。
扱ったことがないサービスを構築する場合は、初めに手動でリソースを立てて検証したほうがいいと思うが、慣れているサービスを利用するときはテンプレートで定義したほうが早い。便利!

0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?