このサイト作った時のCloudFormation-JSON

2022-5月-29 - 読み終える時間: 15 分

このサイトは非常にシンプルな構成で、AWS環境でEC2インスタンス1つにグローバルIPを割りあててそのままインターネットに公開している。

インスタンスタイプはt3a.nanoを使い、これは1hで0.0067USD@東京(月間5USDちょい)という低価格。

しかしオレゴンリージョンであればさらに0.0047USDに下がるという事で、東京リージョンからオレゴンリージョンに移設した。昨日。

東京リージョンで取得したAMIをオレゴンリージョンにコピー。EIPを新たに取得して、下方のCFnコードでスタック作成する。

便宜上jsonファイルは3つに分けている。

  1. alterworks-aws-stack1-vpc.json (無課金部分)
  2. alterworks-aws-stack2-iam.json (無課金グローバル部分)
  3. alterworks-aws-stack3-instance.json (お金かかるやつ)

メンテナンス性は気にしていないが、実際面このシンプル構成だと全部作り直しで障害復旧とかできるので問題なかろう、である。

あとついでにIPv6対応してみた。IPv6設定で非常に有用な参考サイト 【備忘録】CloudFormationで IPv6 対応のVPCとサブネットを作る【CFn】 - サーバーワークス

それぞれのjsonコードが以下のような感じ。(使っていない設定も入っているが、気にしない)

  • alterworks-aws-stack1-vpc.json

{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "alterwoeks.tokyo env template. alterworks-aws-stack1-vpc",

  "Parameters" : {
    "APPParam" : {
      "Type" : "String",
      "Default" : "alterwoeks.tokyo",
      "Description" : "eg. URL."
    }
  },

  "Resources" : {
    "AWTvpc" : {
      "Type" : "AWS::EC2::VPC",
      "Properties" : {
        "CidrBlock" : "192.168.4.0/24",
        "EnableDnsSupport" : "true",
        "EnableDnsHostnames" : "true",
        "InstanceTenancy" : "default",
        "Tags" : [
        {
          "Key" : "Name",
          "Value" : "AWTVPC"
        },
        {
          "Key" : "APP",
          "Value" : { "Ref" : "APPParam" }
        }
        ]
      }
    },
    "AWTvpcCidrBlock": {
      "Type": "AWS::EC2::VPCCidrBlock",
      "Properties": {
          "VpcId": { "Ref" : "AWTvpc" },
          "AmazonProvidedIpv6CidrBlock": true
      }
    },
    "AWTSubnetAZa63pub" : {
      "Type" : "AWS::EC2::Subnet",
      "Properties" : {
        "AssignIpv6AddressOnCreation" : "true",
        "AvailabilityZone" : "us-west-2a",
        "CidrBlock" : "192.168.4.0/26",
        "MapPublicIpOnLaunch" : "true",
        "Tags" : [
        {
          "Key" : "Name",
          "Value" : "AWT-Subnet0-63pub"
        },
        {
          "Key" : "APP",
          "Value" : { "Ref" : "APPParam" }
        }
        ],
        "VpcId" : {"Ref" : "AWTvpc"},
        "Ipv6CidrBlock": {
          "Fn::Sub": [
            "${VpcPart}${SubnetPart}",
            {
              "VpcPart": {
                "Fn::Select": [
                  0,
                  {
                    "Fn::Split": [
                      "00::/56",
                      {
                        "Fn::Select": [
                          0,
                          {
                            "Fn::GetAtt": [
                              "AWTvpc",
                              "Ipv6CidrBlocks"
                            ]
                          }
                        ]
                      }
                    ]
                  }
                ]
              },
              "SubnetPart": "01::/64"
            }
          ]
        }
      },
      "DependsOn" : "AWTvpcCidrBlock"
    },
    "AWTSubnetAZa127pri" : {
      "Type" : "AWS::EC2::Subnet",
      "Properties" : {
        "AvailabilityZone" : "us-west-2a",
        "CidrBlock" : "192.168.4.64/26",
        "MapPublicIpOnLaunch" : "false",
        "Tags" : [
        {
          "Key" : "Name",
          "Value" : "AWT-Subnet64-127pri"
        },
        {
          "Key" : "APP",
          "Value" : { "Ref" : "APPParam" }
        }
        ],
        "VpcId" : {"Ref" : "AWTvpc"}
      }
    },
    "AWTRouteTable1" : {
      "Type" : "AWS::EC2::RouteTable",
      "Properties" : {
        "Tags" : [
        {
          "Key" : "Name",
          "Value" : "AWT-RouteTable1"
        },
        {
          "Key" : "APP",
          "Value" : { "Ref" : "APPParam" }
        }
        ],
        "VpcId" : {"Ref" : "AWTvpc"}
      }
    },
    "AWTRoute1" : {
      "Type" : "AWS::EC2::Route",
      "Properties" : {
        "DestinationCidrBlock" : "0.0.0.0/0",
        "GatewayId" : { "Ref" : "AWTigw" },
        "RouteTableId" : { "Ref" : "AWTRouteTable1" }
      },
      "DependsOn" : "AWTigw"
    },
    "AWTRoute2" : {
      "Type" : "AWS::EC2::Route",
      "Properties" : {
        "DestinationIpv6CidrBlock" : "::/0",
        "GatewayId" : { "Ref" : "AWTigw" },
        "RouteTableId" : { "Ref" : "AWTRouteTable1" }
      },
      "DependsOn" : "AWTigw"
    },
    "AWTRouteTable2" : {
      "Type" : "AWS::EC2::RouteTable",
      "Properties" : {
        "Tags" : [
        {
          "Key" : "Name",
          "Value" : "AWT-RouteTable2"
        },
        {
          "Key" : "APP",
          "Value" : { "Ref" : "APPParam" }
        }
        ],
        "VpcId" : {"Ref" : "AWTvpc"}
      }
    },
    "AWTRouteTableAssoc1" : {
      "Type" : "AWS::EC2::SubnetRouteTableAssociation",
      "Properties" : {
        "RouteTableId" : {"Ref" : "AWTRouteTable1"},
        "SubnetId" : {"Ref" : "AWTSubnetAZa63pub"}
      }
    },
    "AWTRouteTableAssoc2" : {
      "Type" : "AWS::EC2::SubnetRouteTableAssociation",
      "Properties" : {
        "RouteTableId" : {"Ref" : "AWTRouteTable2"},
        "SubnetId" : {"Ref" : "AWTSubnetAZa127pri"}
      }
    },
    "AWTSGtoOffice" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "GroupName" : "AWTtoOffice",
        "GroupDescription" : "for My access",
        "SecurityGroupIngress" : [
        {
          "CidrIp" : "133.200.193.160/32",
          "Description" : "My outbounds IPv4",
          "FromPort" : "0",
          "IpProtocol" : "-1",
          "ToPort" : "65535"
        },
        {
          "CidrIpv6" : "2404:7a80:c1a0:3800::/64",
          "Description" : "My outbounds IPv6",
          "FromPort" : "0",
          "IpProtocol" : "-1",
          "ToPort" : "65535"
        }
        ],
        "SecurityGroupEgress" : [
          {
            "CidrIp" : "192.168.4.0/24",
            "Description" : "Internal outbounds IPv4",
            "FromPort" : "0",
            "IpProtocol" : "-1",
            "ToPort" : "65535"
          }
        ],
          "Tags" :  [
        {
          "Key" : "Name",
          "Value" : "AWTtoOffice"
        },
        {
          "Key" : "APP",
          "Value" : { "Ref" : "APPParam" }
        }
        ],
        "VpcId" : {"Ref" : "AWTvpc"}
      }
    },
    "AWTSG1" : {
      "Type" : "AWS::EC2::SecurityGroup",
      "Properties" : {
        "GroupName" : "AWTSG1",
        "GroupDescription" : "for main-group",
        "SecurityGroupEgress" : [
        {
          "CidrIp" : "0.0.0.0/0",
          "Description" : "outbound IPv4 80",
          "FromPort" : "80",
          "IpProtocol" : "tcp",
          "ToPort" : "80"
        },
        {
          "CidrIp" : "0.0.0.0/0",
          "Description" : "outbound IPv4 443",
          "FromPort" : "443",
          "IpProtocol" : "tcp",
          "ToPort" : "443"
        },
        {
          "CidrIpv6" : "::/0",
          "Description" : "outbound IPv6 80",
          "FromPort" : "80",
          "IpProtocol" : "tcp",
          "ToPort" : "80"
        },
        {
          "CidrIpv6" : "::/0",
          "Description" : "outbound IPv6 443",
          "FromPort" : "443",
          "IpProtocol" : "tcp",
          "ToPort" : "443"
        },
        {
          "CidrIp" : "0.0.0.0/0",
          "Description" : "outbound IPv4 80 udp",
          "FromPort" : "80",
          "IpProtocol" : "udp",
          "ToPort" : "80"
        },
        {
          "CidrIp" : "0.0.0.0/0",
          "Description" : "outbound IPv4 443 udp",
          "FromPort" : "443",
          "IpProtocol" : "udp",
          "ToPort" : "443"
        },
        {
          "CidrIpv6" : "::/0",
          "Description" : "outbound IPv6 80 udp",
          "FromPort" : "80",
          "IpProtocol" : "udp",
          "ToPort" : "80"
        },
        {
          "CidrIpv6" : "::/0",
          "Description" : "outbound IPv6 443 udp",
          "FromPort" : "443",
          "IpProtocol" : "udp",
          "ToPort" : "443"
        }
        ],
        "SecurityGroupIngress" : [
        {
          "CidrIp" : "192.168.4.0/24",
          "Description" : "All inbounds VPC",
          "FromPort" : "0",
          "IpProtocol" : "-1",
          "ToPort" : "65535"
        },
        {
          "CidrIp" : "0.0.0.0/0",
          "Description" : "inbound IPv4 80",
          "FromPort" : "80",
          "IpProtocol" : "tcp",
          "ToPort" : "80"
        },
        {
          "CidrIp" : "0.0.0.0/0",
          "Description" : "inbound IPv4 443",
          "FromPort" : "443",
          "IpProtocol" : "tcp",
          "ToPort" : "443"
        },
        {
          "CidrIpv6" : "::/0",
          "Description" : "inbound IPv6 80",
          "FromPort" : "80",
          "IpProtocol" : "tcp",
          "ToPort" : "80"
        },
        {
          "CidrIpv6" : "::/0",
          "Description" : "inbound IPv6 443",
          "FromPort" : "443",
          "IpProtocol" : "tcp",
          "ToPort" : "443"
        },
        {
          "CidrIp" : "0.0.0.0/0",
          "Description" : "inbound IPv4 80 udp",
          "FromPort" : "80",
          "IpProtocol" : "udp",
          "ToPort" : "80"
        },
        {
          "CidrIp" : "0.0.0.0/0",
          "Description" : "inbound IPv4 443 udp",
          "FromPort" : "443",
          "IpProtocol" : "udp",
          "ToPort" : "443"
        },
        {
          "CidrIpv6" : "::/0",
          "Description" : "inbound IPv6 80 udp",
          "FromPort" : "80",
          "IpProtocol" : "udp",
          "ToPort" : "80"
        },
        {
          "CidrIpv6" : "::/0",
          "Description" : "inbound IPv6 443 udp",
          "FromPort" : "443",
          "IpProtocol" : "udp",
          "ToPort" : "443"
        }
        ],
        "Tags" :  [
        {
          "Key" : "Name",
          "Value" : "AWTSG1"
        },
        {
          "Key" : "APP",
          "Value" : { "Ref" : "APPParam" }
        }
        ],
        "VpcId" : {"Ref" : "AWTvpc"}
      }
    },
    "AWTSG1Egress1" : {
        "Type": "AWS::EC2::SecurityGroupEgress",
        "Properties": {
            "Description": "inMySG",
            "DestinationSecurityGroupId": {"Fn::GetAtt" : ["AWTSG1","GroupId"]},
            "FromPort": 0,
            "GroupId": {"Fn::GetAtt" : ["AWTSG1","GroupId"]},
            "IpProtocol": "-1",
            "ToPort": 65535
        }
    },
    "AWTSG1Ingress1": {
        "Type": "AWS::EC2::SecurityGroupIngress",
        "Properties": {
            "Description": "inMySG",
            "FromPort": 0,
            "GroupId": {"Fn::GetAtt" : ["AWTSG1","GroupId"]},
            "IpProtocol": "-1",
            "SourceSecurityGroupId": {"Fn::GetAtt" : ["AWTSG1","GroupId"]},
            "ToPort": 65535
        }
    },
    "AWTigw" : {
      "Type" : "AWS::EC2::InternetGateway",
      "Properties" : {
        "Tags" :  [
        {
          "Key" : "Name",
          "Value" : "AWT-igw"
        },
        {
          "Key" : "APP",
          "Value" : { "Ref" : "APPParam" }
        }
        ]
      }
    },
    "AWTigwAttach" : {
      "Type" : "AWS::EC2::VPCGatewayAttachment",
      "Properties" : {
        "VpcId" : { "Ref" : "AWTvpc" },
        "InternetGatewayId" : { "Ref" : "AWTigw" }
      }
    }
  },
  "Outputs" : {
    "EXPAWTvpc" : {
      "Description" : "Export AWTvpc",
      "Value" : { "Ref" : "AWTvpc" },
      "Export" : {"Name" : {"Fn::Sub": "${AWS::StackName}-vpc" }}
    },
    "EXPAWTSGtoOffice" : {
      "Description" : "Export SGtoOffice",
      "Value" : { "Ref" : "AWTSGtoOffice" },
      "Export" : {"Name" : {"Fn::Sub": "${AWS::StackName}-SGtoOffice" }}
    },
    "EXPAWTSG1" : {
      "Description" : "Export SG1",
      "Value" : { "Ref" : "AWTSG1" },
      "Export" : {"Name" : {"Fn::Sub": "${AWS::StackName}-SG1" }}
    },
    "EXPAWTSubnetA" : {
      "Description" : "Export SubnetA",
      "Value" : { "Ref" : "AWTSubnetAZa63pub" },
      "Export" : {"Name" : {"Fn::Sub": "${AWS::StackName}-SubnetApub" }}
    },
    "EXPAWTSubnetB" : {
      "Description" : "Export SubnetB",
      "Value" : { "Ref" : "AWTSubnetAZa127pri" },
      "Export" : {"Name" : {"Fn::Sub": "${AWS::StackName}-SubnetApri" }}
    }
  }
}
  • alterworks-aws-stack2-iam.json
{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "alterworks.tokyo env template. alterworks-aws-stack2-iam",

  "Parameters" : {
    "NameParam" : {
      "Type" : "String",
      "Default" : "AWTTagEditRole",
      "Description" : "eg. Role name."
    },
    "APPParam" : {
      "Type" : "String",
      "Default" : "alterwoeks.tokyo",
      "Description" : "eg. URL."
    }
  },

  "Resources" : {
    "AWTTagRole" : {
      "Type" : "AWS::IAM::Role",
      "Properties" : {
        "AssumeRolePolicyDocument": {
          "Version" : "2012-10-17",
          "Statement": [ {
            "Effect": "Allow",
            "Principal": {
               "Service": [ "ec2.amazonaws.com" ]
            },
            "Action": [ "sts:AssumeRole" ]
          } ]
        },
        "Description" : "Tag Edit Role",
        "Path" : "/",
        "RoleName" : "AWTTagEditRole",
        "Tags" : [
        {
          "Key" : "Name",
          "Value" : { "Ref" : "NameParam" }
        },
        {
          "Key" : "APP",
          "Value" : { "Ref" : "APPParam" }
        }
        ]
      }
    },
    "AWTTagPolicy" : {
      "Type" : "AWS::IAM::Policy",
      "Properties" : {
        "PolicyDocument" : {
          "Version": "2012-10-17",
          "Statement": [
          {
            "Effect": "Allow",
            "Action": [
              "ec2:Describe*",
              "ec2:CreateTags",
              "ec2:DeleteTags"
            ],
            "Resource": "*"
          }
          ]
        },
        "PolicyName" : "AWTTagEditPolicy",
        "Roles" : [ "AWTTagEditRole" ]
      },
      "DependsOn" : [ "AWTTagRole" ]
    },
    "AWTprofile" : {
      "Type" : "AWS::IAM::InstanceProfile",
      "Properties" : {
        "InstanceProfileName" : "AWTTagEditRole",
        "Path" : "/",
        "Roles" : [ "AWTTagEditRole" ]
      }
    }
  }
}
  • alterworks-aws-stack3-instance.json
{
  "AWSTemplateFormatVersion" : "2010-09-09",
  "Description" : "alterworks.tokyo env template. alterworks-aws-stack3-instance",

  "Parameters" : {
    "NameParam" : {
      "Type" : "String",
      "Default" : "AWT1",
      "Description" : "as hostname."
    },
    "ServerNameParam" : {
      "Type" : "String",
      "Default" : "input-Japanease-server-name",
      "Description" : "as Japanease server name"
    },
    "APPParam" : {
      "Type" : "String",
      "Default" : "alterwoeks.tokyo",
      "Description" : "as URL"
    },
    "EndpointParam" : {
      "Type" : "String",
      "Default" : "ec2.us-west-2.amazonaws.com",
      "Description" : "as URL"
    }
  },

  "Resources" : {
    "AWTInstance1" : {
      "Type" : "AWS::EC2::Instance",
      "Properties" : {
        "AvailabilityZone" : "us-west-2a",
        "BlockDeviceMappings" : [
        {
          "DeviceName" : "/dev/xvda",
          "Ebs" : { "DeleteOnTermination" : "true", "Encrypted" : "false", "VolumeSize" : "8", "VolumeType" : "gp2" }
        }
        ],
        "EbsOptimized" : "true",
        "IamInstanceProfile" : "AWTTagEditRole",
        "ImageId" : "<自己所有AMI-ID>",
        "InstanceInitiatedShutdownBehavior" : "stop",
        "InstanceType" : "t3a.nano",
        "Monitoring" : "false",
        "NetworkInterfaces" : [
        {
          "AssociatePublicIpAddress" : "false",
          "DeleteOnTermination" : "true",
          "Description" : "AWTENI1",
          "DeviceIndex" : "0",
          "GroupSet" : [
          {
            "Fn::ImportValue" : { "Fn::Sub" : "alterworks-aws-stack1-vpc-SGtoOffice" }
          },
          {
            "Fn::ImportValue" : { "Fn::Sub" : "alterworks-aws-stack1-vpc-SG1" }
          }
          ],
          "PrivateIpAddress" : "192.168.4.16",
          "SubnetId" : { "Fn::ImportValue" : { "Fn::Sub" : "alterworks-aws-stack1-vpc-SubnetApub" } }
        }
        ],
        "Tags" : [
        {
          "Key" : "Name",
          "Value" : { "Ref" : "NameParam" }
        },
        {
          "Key" : "ServerName",
          "Value" : { "Ref" : "ServerNameParam" }
        },
        {
          "Key" : "APP",
          "Value" : { "Ref" : "APPParam" }
        }
        ],
        "Tenancy" : "default",
        "UserData" : { "Fn::Base64" : { "Fn::Join" : [ "", [
          "#cloud-config\n",
          "#vim:syntax=yaml\n",
          "users:\n",
          "# A user by the name `ec2-user` is created in the image by default.\n",
          "  - default\n",
          "  - name: amaster\n",
          "    gecos: 'amazonLinux2 master'\n",
          "    groups: wheel\n",
          "    sudo: ['ALL=(ALL) NOPASSWD:ALL']\n",
          "    ssh-authorized-keys:\n",
          "    - ssh-rsa <自前のauthorized_keysに登録するやつ>\n",
          "    lock_passwd: true\n",
          "chpasswd:\n",
          "  list: |\n",
          "    ec2-user:password-DUMMYuser\n",
          "# In the above line, do not add any spaces after 'ec2-user:'.\n",
          "write_files:\n",
          "  - path: /etc/cloud/cloud.cfg.d/80_disable_network_after_firstboot.cfg\n",
          "    content: |\n",
          "      # Disable network configuration after first boot\n",
          "      manage_resolv_conf: false\n",
          "      network:\n",
          "        config: disabled\n",
          "  - path: /tmp/awscli-def.config\n",
          "    content: |\n",
          "      \n",
          "      \n",
          "      us-west-2\n",
          "      json\n",
          "ssh_deletekeys: true\n",
          "packages:\n",
          "  - expect.x86_64\n",
          "runcmd:\n",
          "  - hostnamectl set-hostname ",{ "Ref" : "NameParam" },"\n",
          "  - aws configure < /tmp/awscli-def.config\n",
          "  - AWS_AVAIL_ZONE=$(curl http://169.254.169.254/latest/meta-data/placement/availability-zone)\n",
          "  - AWS_REGION=${AWS_AVAIL_ZONE::-1}\n",
          "  - AWS_INSTANCE_ID=$(curl http://169.254.169.254/latest/meta-data/instance-id)\n",
          "  - AWS_ENDPOINT=",{ "Ref" : "EndpointParam" },"\n",
          "  - ROOT_VOLUME_IDS=$(aws --endpoint-url https://$AWS_ENDPOINT/ ec2 describe-instances --region $AWS_REGION --instance-id $AWS_INSTANCE_ID --output text --query Reservations[0].Instances[0].BlockDeviceMappings[0].Ebs.VolumeId)\n",
          "  - aws --endpoint-url https://$AWS_ENDPOINT/ ec2 create-tags --resources $ROOT_VOLUME_IDS --region $AWS_REGION --tags Key=Name,Value=",{ "Ref" : "NameParam" },"\n",
          "  - aws --endpoint-url https://$AWS_ENDPOINT/ ec2 create-tags --resources $ROOT_VOLUME_IDS --region $AWS_REGION --tags Key=APP,Value=",{ "Ref" : "APPParam" },"\n",
          "disable_root: true\n"
        ]]}}
      }
    },
    "AWTInstance1EIPAssoc": {
        "Type": "AWS::EC2::EIPAssociation",
        "Properties": {
            "EIP": "54.245.2.180",
            "InstanceId": {"Ref" : "AWTInstance1"}
        }
    }
  }
}

今回はここまで