CloudFormation初心者がとりあえず実行してみたい時のチュートリアル
CloudFormation初心者がとりあえず実行してみたい時のチュートリアル:
この記事はLIFULL Advent Calendar2018その2の22日目の記事です。
AWSでインフラ構築をしたことはあるけど、CloudFormationという単語はなんとなく避けておりました。
ですが、意を決して取り組んでみると思いの外簡単・便利だったので、とりあえず言葉だけ知っていて試してみたいと思っている方向けに、簡単に実行できるチュートリアルを作りました。
※テンプレートの説明は反響があれば別記事で書こうと思います。
今回、CloudFormation(CFNと略すらしいです)を使って構築するインフラ構成は下図のようなシンプルなものにしました。
まず、AWSをcliで実行するためのインストールを行います。
次に、AWSコンソール上でアクセスキーを発行し、下記の通り登録を行います。
また、インスタンスを作成する際に必要なキーペアをsampleという名前で作成してダウンロードしておきます。
テンプレートファイルは、ページ下部のものをコピーしてください。(行数がすごいですが殆どサブネット関連の定義の繰り返しだったりします)
下記のコマンドでローカルからcfnを実行します。
※file://のパスはテンプレートを配置した場所によって異なります
下記のリンクから実際にスタックが実行されているところが見れると思います。
https://ap-northeast-1.console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks
構成図の通りにできているかと思います。
試しにbastionサーバーとapplicationサーバーにsshログインしてみます。
※面倒なので.ssh/configに下記の設定を追加しました。
bastionサーバーにログインできたので、applicationサーバーも試します。
applicationサーバーにもログインでき、外部にも疎通していることが確認できました。
一通り確認したらstackを削除しましょう。
stackを削除することで、cloudformationによって生成されたリソースが全て削除されるため、お試しで環境を作りたい時に撤収が捗ります。
※今回実行したサンプルテンプレート
cfnで何かのリソースを定義したい時は、公式のリファレンスをみつつ、具体例が欲しいところはググって調べています。
sampleのテンプレートではパラメータを活用していなかったり、NACLの定義のところが冗長だったりするので、もっと簡潔にかけるようにこれから努力したいと思います。
はじめに
この記事はLIFULL Advent Calendar2018その2の22日目の記事です。AWSでインフラ構築をしたことはあるけど、CloudFormationという単語はなんとなく避けておりました。
ですが、意を決して取り組んでみると思いの外簡単・便利だったので、とりあえず言葉だけ知っていて試してみたいと思っている方向けに、簡単に実行できるチュートリアルを作りました。
※テンプレートの説明は反響があれば別記事で書こうと思います。
CloudFormationを試す
今回、CloudFormation(CFNと略すらしいです)を使って構築するインフラ構成は下図のようなシンプルなものにしました。
準備
まず、AWSをcliで実行するためのインストールを行います。$ sudo easy_install pip $ sudo pip install awscli $ aws --version
$ 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]:
テンプレートファイル
テンプレートファイルは、ページ下部のものをコピーしてください。(行数がすごいですが殆どサブネット関連の定義の繰り返しだったりします)下記のコマンドでローカルから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 ~]$
$ 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>
一通り確認したら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の定義のところが冗長だったりするので、もっと簡潔にかけるようにこれから努力したいと思います。
コメント
コメントを投稿