こんにちは。
インフラ系の部署で既存インフラのコード化を進めています、戸田です。
5年待ったゲームの発売まであと64日で夜もねれません
先日AWS Loftにいってきましたので、そのことについて書こうと思います。
ペア構築とは
以前、ブログでも紹介されたペアプロをプログラミングではなく、ペアでAWSのインフラ構築をしてみようというものです。
ステータス
CloudFormation初心者の二人
戸田:AWS初心者 S3+CloudFrontの配信をしたことがある程度
ペア:2018年11月10日にソリューションアーキテクトを取得した。(※AWS Loftに行ったのは10月中旬)
ゴール
ALB+VPC+EC2を作成します。 構成に関しては、こんな感じです。
見た目簡単そうですね。 これをCloudformationを使って構築する予定です。
AWS Loftへ向かう
持ち物
- PC
- AWSのアカウントID(数字12桁)
- 身分証明書(名刺×2枚 や 運転免許証)
- クレジットカード
行き方
目黒駅の東口から徒歩1分のビルにあります。
アマゾン新目黒オフィス(目黒セントラルスクエア)に向かいます。
AWS Loftは、17階にありますので、17階までいくエレベーターの方にいきます。 (受付がありますが、スルーして大丈夫です!
AWS Loftの入場時間は、10時からですので、10時以降に警備員の方に 「AWS Loftにいきたいです」と説明すると通れます。
後は17階に行きます。
いやー、Amazon感あふれるエレベーターですね
入場
入場時に必要なものの紹介です。
初めての場合
- AWSのアカウントID(数字12桁) 会社で使っているものがあればそれで大丈夫です
- 身分証明書(名刺×2枚 や 運転免許証)
この時、名前やメールアドレスを登録します。
※会社のアカウントIDを設定した場合、会社の情報も記入します。
まだ二回目行ってないので、二回目以降で必要なものの詳細は分かりません。
他の方を記事を見ているとメールアドレスがあればよさそうですね。
カフェがありますが、クレジットカードのみの支払いとなります。
AWS Loftでペア作業
当日やったこと
- 現地集合
- CloudFormationに関する知識をBlackbeltを見て学ぶ
- サンプルを実際に動かしてみる
- VPCのCloudFormatinを作成
- お昼ごはん (お昼から戻ってくると結構席がいっぱい埋まってました。)
- 引き続きVPCのCloudFormatinを作成
- EC2のCloudFormationを作成
- クロススタック参照を使って、ymlファイルをそれぞれの用途ごとに分けて作成
- ALBのCloudFormationを作成。(ここで時間切れ)
実際作成したもの
ブログの最後に記載↓↓
感想
ペア作業
ペア作業に関しては、今回CloudFormationに関してほとんど知識のない二人でしたので、同じくらいのスピードで理解をすることができてよかったです。
たまにお互いの認識を合わせないと、間違った解釈のまま進んでいくので、疑問に思ったことはすぐ聞くようにしていました。
そのため、一人でやるよりも早く理解が進んだかもしれません。
コワーキングスペース
コワーキングスペースを初めて利用しましたが、とても作業がしやすい場所でした。
会社よりも集中できるというのは、本当でした。
作業するにあたり声は出して作業していましたが、他の利用者ももくもくとやって相談するといった形を取られていたので、問題はないと思います。
(うるさくない程度の声量にはしていたつもりです)
AWS Loft
AWS LoftにはAWSの社員(ソリューションアーキテクト持ち)の方がいらっしゃって、とても心強いと思いました。
今回は質問はしていませんが、AWS Loftに行った日は、Auroa/RDS MysqlのスペシャリストSAの方がいらっしゃいました。
(話を聞きたい領域のエンジニアさんがいらっしゃているかどうかはどこで確認できるんですかね?Twitter監視?ベストプラクティス教えてください。)
また何かAWS関連の作業をすることがあれば、行きたいと思います!
まとめ
AWS Loftでのペア作業はとてもいいものでした!!
- ペアで行う分、理解が早い
- 相談がすぐできる(ペアの方やAWSの方
- 会社よりも集中ができる などたくさんいい点がありました!!
以上となります。最後までご覧いただきありがとうございました。
(AWS Loftでこんな感じのカフェラテ飲めます。)
作成したもの
事前にEIPとACMを取得します。
実行順番はVPC→EC2→S3→ALB
となります。
VPC
AWSTemplateFormatVersion: 2010-09-09 Description: Create VPC and Security Groups Parameters: AZ1: Type: AWS::EC2::AvailabilityZone::Name Description: select availability zone AZ2: Type: AWS::EC2::AvailabilityZone::Name Description: select availability zone CidrCount: Type: Number Default: 32 Description: The number of CIDRs to generate. Valid range is between 1 and 4096. MinValue: 1 MaxValue: 32 CidrBits: Type: Number Default: 7 Description: The number of subnet bits for the CIDR. For example, CidrBits of "8" will create a CIDR with a mask of "/24". MinValue: 1 MaxValue: 32 ProjectName: Type: String Description: Project name for tag Stage: Type: String Description: Stage. for distinguish related Stack. (cf. test /development / production) ResourceName: Type: String Description: Prefix of resource name. Max 14 chars. MaxLength: 14 VpcCidr: Type: String Description: VPC CIDR Block AllowedPattern: ^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\/([0-9]|[1-2][0-9]|3[0-2]))$ Resources: VPC: Type: 'AWS::EC2::VPC' Properties: EnableDnsSupport: 'true' EnableDnsHostnames: 'true' CidrBlock: !Ref VpcCidr Tags: - Key: Project Value: !Ref ProjectName - Key: Name Value: !Sub "${ProjectName}-${Stage}" PublicSubnetA: Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref VPC CidrBlock: !Select [0, !Cidr [ !Ref VpcCidr, !Ref CidrCount, !Ref CidrBits]] AvailabilityZone: !Ref AZ1 Tags: - Key: Project Value: !Ref ProjectName - Key: Name Value: !Sub "${ProjectName}-${Stage}-A" PublicSubnetC: Type: 'AWS::EC2::Subnet' Properties: VpcId: !Ref VPC CidrBlock: !Select [2, !Cidr [ !Ref VpcCidr, !Ref CidrCount, !Ref CidrBits]] AvailabilityZone: !Ref AZ2 Tags: - Key: Project Value: !Ref ProjectName - Key: Name Value: !Sub "${ProjectName}-${Stage}-C" InternetGateway: Type: 'AWS::EC2::InternetGateway' Properties: Tags: - Key: Project Value: !Ref ProjectName - Key: Name Value: !Sub "${ProjectName}-${Stage}" VPCGatewayAttachment: Type: 'AWS::EC2::VPCGatewayAttachment' Properties: VpcId: !Ref VPC InternetGatewayId: !Ref InternetGateway PublicRouteTable: Type: 'AWS::EC2::RouteTable' Properties: VpcId: !Ref VPC Tags: - Key: Project Value: !Ref ProjectName - Key: Name Value: public PublicRoute: Type: 'AWS::EC2::Route' DependsOn: VPCGatewayAttachment Properties: RouteTableId: !Ref PublicRouteTable DestinationCidrBlock: 0.0.0.0/0 GatewayId: !Ref InternetGateway PublicSubnetRouteTableAssociationA: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref PublicSubnetA RouteTableId: !Ref PublicRouteTable PublicSubnetRouteTableAssociationC: Type: 'AWS::EC2::SubnetRouteTableAssociation' Properties: SubnetId: !Ref PublicSubnetC RouteTableId: !Ref PublicRouteTable PublicSubnetNetworkAclAssociationA: Type: 'AWS::EC2::SubnetNetworkAclAssociation' Properties: SubnetId: !Ref PublicSubnetA NetworkAclId: !GetAtt - VPC - DefaultNetworkAcl PublicSubnetNetworkAclAssociationC: Type: 'AWS::EC2::SubnetNetworkAclAssociation' Properties: SubnetId: !Ref PublicSubnetC NetworkAclId: !GetAtt - VPC - DefaultNetworkAcl ALBSecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: VpcId: !Ref VPC GroupDescription: "-" SecurityGroupIngress: - IpProtocol: tcp FromPort: 443 ToPort: 443 CidrIp: 0.0.0.0/0 InstanceSecurityGroup: Type: 'AWS::EC2::SecurityGroup' Properties: GroupDescription: Enable RDP access VpcId: !Ref VPC SecurityGroupIngress: - IpProtocol: tcp FromPort: '22' ToPort: '22' CidrIp: "自分がインターネットに出ていくグローバルIP"/32 - IpProtocol: tcp FromPort: '80' ToPort: '80' SourceSecurityGroupId: !Ref ALBSecurityGroup Tags: - Key: Name Value: !Sub ${ProjectName} Instance Outputs: VPCId: Description: VPC ID Value: !Ref VPC Export: Name: !Sub '${ResourceName}-VPCID' PublicSubnetA: Description: The subnet ID to use for public zone-a Value: !Ref PublicSubnetA Export: Name: !Sub '${ResourceName}-Subnet-A-ID' PublicSubnetC: Description: The subnet ID to use for public zone-c Value: !Ref PublicSubnetC Export: Name: !Sub '${ResourceName}-Subnet-C-ID' InstanceSecurityGroup: Description: The security group ID to use for server Value: !GetAtt - InstanceSecurityGroup - GroupId Export: Name: !Sub '${ResourceName}-SecurityGroupID' ALBSecurityGroup: Description: The security group ID to use for ALB Value: !GetAtt - ALBSecurityGroup - GroupId Export: Name: !Sub '${ResourceName}-alb-SecurityGroupID'
EC2
AWSTemplateFormatVersion: 2010-09-09 Description: Create EC2 Instance Parameters: AMIID: Type: AWS::EC2::Image::Id Description: AMI ID for Springboard Instance AZ1: Type: AWS::EC2::AvailabilityZone::Name Description: select availability zone AZ2: Type: AWS::EC2::AvailabilityZone::Name Description: select availability zone InstanceType: Type: String Description: must be a valid EC2 instance type. KeyName: Description: Name of an existing EC2 KeyPair to enable RDP access to the instances Type: 'AWS::EC2::KeyPair::KeyName' Description: must be the name of an existing EC2 KeyPair. ProjectName: Type: String Description: Project name for tag ResourceName: Type: String Description: Prefix of resource name. Max 14 chars. MaxLength: 14 Stage: Type: String Description: Stage. for distinguish related Stack. (cf. test /development / production) ElasticIP: Type: String Description: ElasticIP ID for Server Resources: EC2Instance: Type: 'AWS::EC2::Instance' Properties: DisableApiTermination: false InstanceInitiatedShutdownBehavior: stop ImageId: !Ref AMIID InstanceType: !Ref InstanceType SubnetId: Fn::ImportValue: !Sub "${ResourceName}-Subnet-A-ID" SecurityGroupIds: - Fn::ImportValue: !Sub "${ResourceName}-SecurityGroupID" KeyName: !Ref KeyName Tags: - Key: Name Value: !Sub "${ProjectName}-${Stage}" - Key: Stage Value: !Ref Stage - Key: Project Value: !Ref ProjectName IPAssoc: Type: 'AWS::EC2::EIPAssociation' Properties: InstanceId: !Ref EC2Instance AllocationId: !Ref ElasticIP Outputs: InstanceId: Description: InstanceId of the newly created EC2 instance Value: !Ref EC2Instance Export: Name: !Sub '${ResourceName}-ec2'
S3
AWSTemplateFormatVersion: "2010-09-09" Description: Create S3 bucket Parameters: ProjectName: Type: String Description: Project name for tag ResourceName: Type: String Description: Prefix of resource name. Max 14 chars. MaxLength: 14 Stage: Type: String Description: Stage. for distinguish related Stack. (cf. test /development / production) Mappings: S3Config: ap-northeast-1: "AccountId": "アカウントIDを入力してください" Resources: ELBLogBucket: Type: "AWS::S3::Bucket" Properties: BucketName: !Sub "${ProjectName}-${Stage}-alb" ELBLogBucketPolicy: Type: "AWS::S3::BucketPolicy" Properties: Bucket: !Sub "${ProjectName}-${Stage}-alb" PolicyDocument: Id: !Sub "AWSCFn-AccessLogs-Policy-${ProjectName}-${Stage}-alb-log" Version: "2012-10-17" Statement: - Sid: !Sub "AWSCFn-AccessLogs-Policy-${ProjectName}-${Stage}-alb-log" Effect: "Allow" Action: - "s3:PutObject" Resource: !Sub "arn:aws:s3:::${ELBLogBucket}/AWSLogs/${AWS::AccountId}/*" Principal: AWS: !FindInMap [ S3Config, !Ref "AWS::Region", AccountId ] Outputs: ELBLogBucket: Value: !Ref ELBLogBucket Export: Name: !Sub '${ProjectName}-${Stage}-alb-log'
ALB
AWSTemplateFormatVersion: "2010-09-09" Description: ALB Create Parameters: AcmCertificateArn: Type: String Description: ACM Certificate ARN for ALB Default: '' ProjectName: Type: String Default: 'Sample' Description: Project name for tag ResourceName: Type: String Description: Prefix of resource name. Max 14 chars. MaxLength: 14 Stage: Type: String Description: Stage. for distinguish related Stack. (cf. test /development / production) Conditions: HasAcmCertificateArn: !Not [!Equals [!Ref AcmCertificateArn, '']] Resources: TargetGroup: Type: 'AWS::ElasticLoadBalancingV2::TargetGroup' Properties: VpcId: { "Fn::ImportValue": !Sub '${ResourceName}-VPCID' } Name: !Sub "${ProjectName}-${Stage}" 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: !Sub "${ProjectName}-${Stage}" Targets: - Id: { "Fn::ImportValue": !Sub '${ResourceName}-ec2' } Port: 80 InternetALB: Type: 'AWS::ElasticLoadBalancingV2::LoadBalancer' Properties: Name: !Sub "${ProjectName}-${Stage}" Tags: - Key: Name Value: !Sub "${ProjectName}-${Stage}" Scheme: "internet-facing" LoadBalancerAttributes: - Key: "deletion_protection.enabled" Value: false - Key: "idle_timeout.timeout_seconds" Value: 60 - Key: "access_logs.s3.enabled" Value: true - Key: "access_logs.s3.bucket" Value: Fn::ImportValue: !Sub "${ProjectName}-${Stage}-alb-log" SecurityGroups: - Fn::ImportValue: !Sub "${ResourceName}-alb-SecurityGroupID" Subnets: - Fn::ImportValue: !Sub "${ResourceName}-Subnet-A-ID" - Fn::ImportValue: !Sub "${ResourceName}-Subnet-C-ID" ALBListener: Type: 'AWS::ElasticLoadBalancingV2::Listener' Condition: HasAcmCertificateArn Properties: DefaultActions: - TargetGroupArn: !Ref TargetGroup Type: forward LoadBalancerArn: !Ref InternetALB Port: 443 Protocol: HTTPS Certificates: - CertificateArn: !Ref AcmCertificateArn