nginxのデフォルト画面を表示するCloudFormationのテンプレートファイル(yml)
今の現場でAWSを触っている& AWS 認定ソリューションアーキテクト–アソシエイトの資格も取得した!
けれどゼロからVPCとかサブネットとかEC2構築してって言われたら、まだ戸惑いそう……
てことで、自分のスキルの確立のために、
AWSの勉強の復習として、
CloudFormationのテンプレートファイルを作成することにしました。
(完全に備忘録です)
CloudFormationとは
AWS CloudFormation は Amazon Web Services リソースのモデル化およびセットアップに役立つサービスです。リソース管理に割く時間を減らし、AWS で実行するアプリケーションにさらに注力できるようになります。使用するすべての AWS リソース (Amazon EC2 インスタンスや Amazon RDS DB インスタンスなど) を記述するテンプレートを作成すれば、AWS CloudFormation がお客様に代わってこれらのリソースのプロビジョニングや設定を受け持ちます。
つまりは、
テンプレートさえあれば、AWSのリソースのプロビジョニングや設定完成できるよーっていう話。
構成
VPC
Subnet : Private×3, Public×3(リージョンごとに一つずつ作成、備忘録として作成したので何もリソースを配置していない場所もある)
internet gateway
NAT gateway
ALB
EC2
→Maintenance用にPublic Subnetに1台
→WEBサーバをPrivate Subnetに2台(リージョンは別)
テンプレート本体
私はコメント書けるので(現場でもこちらだったので)ymlで書いてます。
Github(今後も追加していきたいところ)
AWSTemplateFormatVersion: "2010-09-09" Description: Memorandum of setting up AWS environment # EC2のページでKeyは作成しておくこと Parameters: WebKeyName: Description: The EC2 Key Pair to allow SSH access to the instance Type: AWS::EC2::KeyPair::KeyName ManagedKeyName: Description: The EC2 Key Pair to allow SSH access to the instance Type: AWS::EC2::KeyPair::KeyName SSHAccessSourceIP: Type: String # # NetworkAclはデフォルトにするものと仮定 # Resources: # ------------------------------------------------------------# # VPC # ------------------------------------------------------------# MyVPC: Type: AWS::EC2::VPC Properties: CidrBlock: 10.0.0.0/16 Tags: - Key: Name Value: MyVPC # InternetGateway Create InternetGateway: Type: AWS::EC2::InternetGateway Properties: Tags: - Key: Name Value: test-igw # IGW Attach InternetGatewayAttachment: Type: AWS::EC2::VPCGatewayAttachment Properties: InternetGatewayId: !Ref InternetGateway VpcId: !Ref MyVPC # ------------------------------------------------------------# # Subnet # ------------------------------------------------------------# # Public Subnet # Subnet Public1a PublicSubnet1a: Type: AWS::EC2::Subnet Properties: AvailabilityZone: ap-northeast-1a CidrBlock: 10.0.110.0/24 VpcId: !Ref MyVPC Tags: - Key: Name Value: test-public-subnet-1a # Subnet Public1c PublicSubnet1c: Type: AWS::EC2::Subnet Properties: AvailabilityZone: ap-northeast-1c CidrBlock: 10.0.120.0/24 VpcId: !Ref MyVPC Tags: - Key: Name Value: test-public-subnet-1c # Subnet Public1d PublicSubnet1d: Type: AWS::EC2::Subnet Properties: AvailabilityZone: ap-northeast-1d CidrBlock: 10.0.130.0/24 VpcId: !Ref MyVPC Tags: - Key: Name Value: test-public-subnet-1d # Private Subnet # Subnet Private1a PrivateSubnet1a: Type: AWS::EC2::Subnet Properties: AvailabilityZone: ap-northeast-1a CidrBlock: 10.0.10.0/24 VpcId: !Ref MyVPC Tags: - Key: Name Value: test-private-subnet-1a # Subnet Private1c PrivateSubnet1c: Type: AWS::EC2::Subnet Properties: AvailabilityZone: ap-northeast-1c CidrBlock: 10.0.20.0/24 VpcId: !Ref MyVPC Tags: - Key: Name Value: test-private-subnet-1c # Subnet Private1d PrivateSubnet1d: Type: AWS::EC2::Subnet Properties: AvailabilityZone: ap-northeast-1d CidrBlock: 10.0.30.0/24 VpcId: !Ref MyVPC Tags: - Key: Name Value: test-private-subnet-1d # ------------------------------------------------------------# # NAT Gateway AZ:A # ------------------------------------------------------------# # ELPIP for NAT Gateway NATGatewayAEIP: Type: AWS::EC2::EIP Properties: Domain: vpc # NAT Gateway NATGatewayA: Type: AWS::EC2::NatGateway Properties: AllocationId: !GetAtt NATGatewayAEIP.AllocationId # memo : Only one setting SubnetId: !Ref PublicSubnet1a # ------------------------------------------------------------# # RouteTable # ------------------------------------------------------------# # Public RouteTable1a PublicRouteTable1a: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref MyVPC Tags: - Key: Name Value: test-public-route-1a # Public RouteTable1c PublicRouteTable1c: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref MyVPC Tags: - Key: Name Value: test-public-route-1c # Public RouteTable1c PublicRouteTable1d: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref MyVPC Tags: - Key: Name Value: test-public-route-1d # Private RouteTable1a PrivateRouteTable1a: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref MyVPC Tags: - Key: Name Value: test-private-route-1a # Private RouteTable1c PrivateRouteTable1c: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref MyVPC Tags: - Key: Name Value: test-private-route-1c # Private RouteTable1d PrivateRouteTable1d: Type: AWS::EC2::RouteTable Properties: VpcId: !Ref MyVPC Tags: - Key: Name Value: test-private-route-1d # ------------------------------------------------------------# # Routing # ------------------------------------------------------------# # Public # PublicRoute1a PublicRoute1a: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PublicRouteTable1a DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway # PublicRoute1c PublicRoute1c: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PublicRouteTable1c DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway # PublicRoute1d PublicRoute1d: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PublicRouteTable1d DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway # Private # PrivateRoute1a PrivateRoute1a: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PrivateRouteTable1a DestinationCidrBlock: 0.0.0.0/0 NatGatewayId: !Ref NATGatewayA # PrivateRoute1c PrivateRoute1c: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PrivateRouteTable1c DestinationCidrBlock: 0.0.0.0/0 NatGatewayId: !Ref NATGatewayA # PrivateRoute1c PrivateRoute1d: Type: AWS::EC2::Route Properties: RouteTableId: !Ref PrivateRouteTable1d DestinationCidrBlock: 0.0.0.0/0 NatGatewayId: !Ref NATGatewayA # ------------------------------------------------------------# # RouteTable Associate # ------------------------------------------------------------# # PublicRouteTable Associate Subnet1a PublicSubnet1aRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnet1a RouteTableId: !Ref PublicRouteTable1a # PublicRouteTable Associate Subnet1c PublicSubnet1cRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnet1c RouteTableId: !Ref PublicRouteTable1c # PublicRouteTable Associate Subnet1d PublicSubnet1dRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PublicSubnet1d RouteTableId: !Ref PublicRouteTable1d # PrivateRouteTable Associate Subnet1a PrivateSubnet1aRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PrivateSubnet1a RouteTableId: !Ref PrivateRouteTable1a # PrivateRouteTable Associate Subnet1c PrivateSubnet1cRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PrivateSubnet1c RouteTableId: !Ref PrivateRouteTable1c # PrivateRouteTable Associate Subnet1d PrivateSubnet1dRouteTableAssociation: Type: AWS::EC2::SubnetRouteTableAssociation Properties: SubnetId: !Ref PrivateSubnet1d RouteTableId: !Ref PrivateRouteTable1d # ------------------------------------------------------------# # SecurityGroup # ------------------------------------------------------------# # Managed ManagedSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Managed EC2 GroupName: Managed SecurityGroup VpcId: !Ref MyVPC Tags: - Key: Name Value: managed-sg # Rule SecurityGroupIngress: - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: !Ref SSHAccessSourceIP ManagedWebSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: Managed Web EC2 GroupName: Managed Web SecurityGroup VpcId: !Ref MyVPC Tags: - Key: Name Value: managed-web-sg # Rule SecurityGroupIngress: - IpProtocol: tcp FromPort: 22 ToPort: 22 CidrIp: 10.0.110.0/24 WebSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: web and ssh GroupName: web-sg VpcId: !Ref MyVPC Tags: - Key: Name Value: web-sg # Rule WebSecurityGroupIngress: Type: AWS::EC2::SecurityGroupIngress Properties: IpProtocol: tcp FromPort: 80 ToPort: 80 SourceSecurityGroupId: !GetAtt ALBSecurityGroup.GroupId GroupId: !GetAtt WebSecurityGroup.GroupId # ALB ALBSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: ALB GroupName: ALB SecurityGroup VpcId: !Ref MyVPC Tags: - Key: Name Value: alb-sg # Rule SecurityGroupIngress: - IpProtocol: tcp FromPort: 80 ToPort: 80 CidrIp: 0.0.0.0/0 - IpProtocol: tcp FromPort: 443 ToPort: 443 CidrIp: 0.0.0.0/0 SecurityGroupEgress: - IpProtocol: tcp FromPort: 80 ToPort: 80 DestinationSecurityGroupId: !Ref WebSecurityGroup # ------------------------------------------------------------# # EC2 # ------------------------------------------------------------# # Maintenance ManagedInstanceA: Type: AWS::EC2::Instance Properties: InstanceType: t2.micro ImageId: ami-0a1c2ec61571737db SecurityGroupIds: - !Ref ManagedSecurityGroup SubnetId: !Ref PublicSubnet1a KeyName: !Ref ManagedKeyName Tags: - Key: Name Value: Maintenance ManagedInstanceEIP: Type: AWS::EC2::EIP Properties: Domain: vpc InstanceId: !Ref ManagedInstanceA # Web WebInstanceA: Type: AWS::EC2::Instance Properties: InstanceType: t2.micro ImageId: ami-0a1c2ec61571737db SecurityGroupIds: - !Ref WebSecurityGroup - !Ref ManagedWebSecurityGroup SubnetId: !Ref PrivateSubnet1a KeyName: !Ref WebKeyName Tags: - Key: Name Value: Web-A UserData: !Base64 | #!/bin/bash sudo yum -y update sudo amazon-linux-extras install -y nginx1.12 sudo service nginx start WebInstanceC: Type: AWS::EC2::Instance Properties: InstanceType: t2.micro ImageId: ami-0a1c2ec61571737db SecurityGroupIds: - !Ref WebSecurityGroup - !Ref ManagedWebSecurityGroup SubnetId: !Ref PrivateSubnet1c KeyName: !Ref WebKeyName Tags: - Key: Name Value: Web-C UserData: !Base64 | #!/bin/bash sudo yum -y update sudo amazon-linux-extras install -y nginx1.12 sudo service nginx start # ------------------------------------------------------------# # Target Group # ------------------------------------------------------------# TargetGroup: Type: AWS::ElasticLoadBalancingV2::TargetGroup Properties: VpcId: !Ref MyVPC Name: web-tg Protocol: HTTP Port: 80 HealthCheckProtocol: HTTP HealthCheckPath: / HealthCheckPort: traffic-port HealthyThresholdCount: 2 UnhealthyThresholdCount: 2 HealthCheckTimeoutSeconds: 5 HealthCheckIntervalSeconds: 10 Matcher: HttpCode: 200 Tags: - Key: Name Value: web-tg TargetGroupAttributes: - Key: "deregistration_delay.timeout_seconds" Value: 300 - Key: "stickiness.enabled" Value: false - Key: "stickiness.type" Value: lb_cookie - Key: "stickiness.lb_cookie.duration_seconds" Value: 86400 Targets: - Id: !Ref WebInstanceA - Id: !Ref WebInstanceC Port: 80 # ------------------------------------------------------------# # Internet ALB # ------------------------------------------------------------# InternetALB: Type: AWS::ElasticLoadBalancingV2::LoadBalancer Properties: Name: WebALB Tags: - Key: Name Value: WebALB Scheme: internet-facing LoadBalancerAttributes: - Key: deletion_protection.enabled Value: false - Key: idle_timeout.timeout_seconds Value: 60 SecurityGroups: - !Ref ALBSecurityGroup Subnets: - !Ref PublicSubnet1a - !Ref PublicSubnet1c ALBListener: Type: AWS::ElasticLoadBalancingV2::Listener Properties: DefaultActions: - TargetGroupArn: !Ref TargetGroup Type: forward LoadBalancerArn: !Ref InternetALB Port: 80 Protocol: HTTP
少し補足
今回のテンプレートはParametersはあまり設定しない方針です。
コメントに書いているように、EC2にアクセスするためのKeyは先に作成してください。
SSHAccessSourceIPは、Maintenanceサーバにアクセスすることができる唯一のIPとして設定します。
VPC, SubnetのIP(CIDR)の設定は適宜変更してください。
ちょっと他でみないのは、WEBサーバとしてたてたEC2のUserDataの部分でしょうか。
UserData: !Base64 | #!/bin/bash sudo yum -y update sudo amazon-linux-extras install -y nginx1.12 sudo service nginx start
AWSだとnginxはyum
ではなく、amazon-linux-extrasnginx
でインストールしなければなりませんでした。
ここでnginxをstartさせておくことで、(EC2にSSH接続しなくても)ALBで指定されたDNSにアクセスしてnginxのデフォルト画面が表示されます。
おわりに
NAT gatewayが接続されていないPrivate Subnetだとyum
が動かなかったり、
Private SubnetにWEBサーバおくにはALBが必要になったり……テンプレートファイル書くだけでかなりの復習になりました!!
今度は無料で動かせる範囲のLambdaの構築とかしたいです。
以上です!