#何この記事
CloudFormationでそれなりな規模の構成を作成することになったので、困って調べて分かったことをつらつらと書いていって後で見直せるようにした記事。なので自分用メモの色が強いです。が、たまたま記事を見て解決になったら良いかなともちょっと思います。
そんな性質の記事なのでふとした瞬間に増えたり減ったりします。
#CloudFormationとは
AWSの公式ドキュメントかQiitaでCloudFormationタグを漁ってください
#Tips
スタックを小分けにする際の1案
今はいくつか方法がありますが、1案として。
- 共通のIDを決定し、Parametersに設定してスタック作成時に入力をする
- 同じスクリプトを使って2つ以上の環境を作成する際、共通のIDを各インスタンスの名前に利用すると楽
- 他のスタックで必要そうな情報を
Outputs
に記載してエクスポート - 他のスタックでエクスポートした情報は
Fn::ImportValue
と!Sub
を用いてインポート
例 VPC作成
Parameters:
ProjectId:
Description: "Project name id."
Type: String
AllowedPattern: '^[a-zA-Z0-9-/:-@\[-\`\{-\~]+$'
ConstraintDescription: "InvalidValue[ProjectId]"
Resources:
MyVPC:
Type: "AWS::EC2::VPC"
Properties:
CidrBlock: "10.0.0.0/16"
EnableDnsSupport: true
EnableDnsHostnames: true
InstanceTenancy: "default"
Tags:
- Key: "Name"
Value: !Sub "${ProjectId}-vpc"
Outputs:
MyVPC:
Value: !Ref MyVPC
Export:
Name: !Sub "${ProjectId}-vpc"
例 SecurityGroup作成
Parameters:
ProjectId:
Description: "Project name id."
Type: String
AllowedPattern: '^[a-zA-Z0-9-/:-@\[-\`\{-\~]+$'
ConstraintDescription: "InvalidValue[ProjectId]"
Resources:
MySecurityGroup:
Type: "AWS::EC2::SecurityGroup"
Properties:
VpcId: {"Fn::ImportValue": !Sub "${ProjectId}-vpc"}
GroupName: !Sub "${ProjectId}-sg"
GroupDescription: "pass ssh from specific IP"
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: "x.x.x.x/32"
Tags:
- Key: Name
Value: !Sub "${ProjectId}-sg"
Parametersとの文字結合
Fn::Join
の方がネット上のノウハウ的に多いけど、せっかく新しいFn::Sub
ができたんだし使っていきましょ
Fn::Sub
${Param}
でParam
パラメータの文字列が展開される。
複雑な文字結合の場合はListを作成すると楽。
1つ目に、生成する文字列
2つ目に、生成する文字列に対してマッピングする変数定義
(たぶん例を見た方が早い)
例
簡単な結合
MyParam=testparam
と設定した状態でtestparam-instance
という文字列を作成
!Sub "${MyParam}-instance
複雑な結合
DBEngine=postgres
DBVersion=9.6.3
と設定した状態でpostgres9.6
という文字列を作成
!Sub
- ${DBEngine}${DBVersion1}.${DBVersion2}
- DBEngine: !Ref DBEngine
DBVersion1: !Select [0, !Split [".", !Ref DBVersion] ]
DBVersion2: !Select [1, !Split [".", !Ref DBVersion] ]
Joinの場合より可読性も高い(と思う)
Policy作る時は基本的には管理ポリシーを作成
CFnに限った話ではないですが、インラインポリシーではなく管理ポリシーを作りましょうという話。
インラインポリシー : AWS::IAM::Policy
Role/User/Groupと1対1の関係。作成した後に別のエンティティにアタッチできない
管理ポリシー : AWS::IAM::ManagedPolicy
ポリシーは単体で存在し、複数のエンティティにアタッチできる
##IAMRoleをEC2につけたい
InstanceProfileを作成してIAMRoleとEC2をつなげる必要がある。
AWSコンソールからはInstanceProfileを意識せずアタッチできるので気づきにくい。
例 (抜粋 parametersで指定して!Refで参照してるところもあります)
Resources:
MyRole:
Type: "AWS::IAM::Role"
Properties:
RoleName: "my-role"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- "ec2.amazonaws.com"
Action: "sts:AssumeRole"
Path: "/"
MyInstanceProfile:
Type: "AWS::IAM::InstanceProfile"
DependsOn: MyRole
Properties:
InstanceProfileName: "my-instance-profile"
Path: "/"
Roles:
- !Ref MyRole
MyEC2:
Type: "AWS::EC2::Instance"
DependsOn: MyInstanceProfile
Properties:
ImageId: !Ref MyEC2AmiId
IamInstanceProfile: !Ref MyInstanceProfile
NetworkInterfaces:
- AssociatePublicIpAddress: true
DeviceIndex: "0"
PrivateIpAddress: "10.0.0.250"
SubnetId: !Ref MySubnet
GroupSet:
- !Ref MySecurityGroup
InstanceType: !Ref MyEC2Type
KeyName: !Ref EC2KeyPair
Tags:
- Key: "Name"
Value: "MyEC2"
RDSのセキュリティグループ
AWS::RDS::DBInstance
のPropertiesにセキュリティグループ関連のものは二つ
DBSecurityGroups
VPCSecurityGroups
ちなみにどちらも指定することはできない。
DBSecurityGroups
DB用に独自にSecurityGroupを作成して反映したい場合
VPCSecurityGroups
AWS::EC2::SecurityGroup
をアタッチする場合
こちらの方が利用シーンは多そう
DBParameterGroup, DBSubnetGroupのName
AWS::RDS::DBParameterGroup
AWS::RDS::DBSubnetGroup
の名前が現時点では設定できなさそう・・・?
AWSのドキュメントにも名前を設定するプロパティはなさげ。
aws-cliで作成する場合は名前設定する用のプロパティあるのに。
ちなみに作成すると論理IDとランダム文字列が結合した名前が生成されて設定されます。
ELBのLogを保管する先のS3のBucketPolicy
これもCFnに限った話ではないですが。
ELBのログ出力を設定する場合(AccessLoggingPolicy
プロパティにて設定)、S3にログファイルを吐くのは特定のAWSアカウントなので、それを許可するようS3のBucketyPolicyを設定する必要があります。
詳しくはこのあたり
AWS - Classic Load Balancer のアクセスログの有効化 - ステップ 2: S3 バケットにポリシーをアタッチする
例 (抜粋, ap-northeast-1リージョンの場合)
Resources:
ELBLogS3:
Type: "AWS::S3::Bucket"
Properties:
BucketName: "hogehoge-server-log"
ELBLogS3BucketPolicy:
Type: "AWS::S3::BucketPolicy"
DependsOn: ELBLogS3
Properties:
Bucket: !Ref ELBLogS3
PolicyDocument:
Version: "2012-10-17"
Id: "ELBLogS3BucketPolicy"
Statement:
- Sid: "ELBLogWriteAccess"
Action:
- "s3:PutObject"
Effect: "Allow"
Resource: !Sub "arn:aws:s3:::${ELBLogS3}/AWSLogs/${AWS::AccountId}/*"
Principal:
AWS: "arn:aws:iam::582318560864:root"