多分わかりやすいCloudFormation入門とチュートリアル

多分わかりやすいCloudFormation入門とチュートリアル:

Serverのリソース管理(WebサーバーとかDBサーバーとかのマシン管理)ってみなさん何で管理していますか?

  • Ansible
  • AWS CLI(Shell)
  • etc....
色々あると思いますが、AWSを使用しているならばCloudFormationも一つの選択です。

ただCloudFormationをいざ始めてみようとすると

  • ドキュメントの量が膨大
  • 謎のyml記法がある(DSL的な)
とかで億劫になって敬遠されがちかと思うのでこれさえ覚えおけば使えるよ!!ってのをまとめてみました。


対象者

  • AWSを使っている
  • CloudFormationってナニソレ美味しいの?って人
  • サーバーのリソース管理方法を選んでいる人


事前に必要なもの

  • aws cli

    • macな方は黙って brew install awscli と打とう


やらないこと

  • ポチポチとGUIでCloudFormationを作らない


CloudFormationでまず知っておくことその1 スタック



スタックって何?


簡単にいうとサービス単位とかでAWSリソースを管理する単位のことです。

例でいうとWEBサービスを作りたいと思った時に大抵の場合下記のような構成になると思います。

(最近はDockerっていう選択もありますが)

  • WEBサーバー(EC2)
  • DBサーバー(RDS)
  • ロードバランサー(ELB)
もう少し細かいところまでだと

  • セキュリティグループ
  • Route53
  • etc....
これらを管理する塊のことです。(各リソースユニットを管理する塊)


CloudFormationでまず知っておくことその2 エクスポート



エクスポートとは?


先程のスタックでサービス単位で管理をするとどのサービスでも共通して使用するものがあると思います。

例として

  • 共通のセキュリティグループ
  • VPC
CloudFormationは原則としてスタック間での共有はできません。

(例: スタックAで定義したセキュリティグループはスタックBで重複管理することはできません)

これを実現するためにはエクスポート機能を使用して値をエクスポートして共有します。

プログラム的に言うとグローバル変数を宣言するイメージに近いです。


WEBサーバー x DBサーバー を作るチュートリアル

よくある構成パターンですね。

かつ今回はテスト環境と本番環境で別々のリソース管理をしてみましょう。


ディレクトリを掘る

{path/to/dir} はお好みのディレクトリを指定してください。

cd {path/to/dir} 
mkdir -p cf-tutorial/parameters 
touch cf-tutorial/template.yml 
touch cf-tutorial/parameters/{production,testing}.json 
echo '[]' >> cf-tutorial/parameters/{production,testing}.json 


リソースを定義するためのTemplateを書く

管理するAWSリソースを定義するテンプレートです。(yml)

まずはこんな形のymlを用意しましょう

template.yml
AWSTemplateFormatVersion: '2010-09-09' 
Description: cf tutorial stack 
Parameters: 
# Parameters以下に変数を定義する 
Resources: 
# Resources以下に管理したいResourceを管理する 
Outputs: 
# エクスポートしたい値を書く 


Parameters (変数)

そのまんまです。

ではサービス名でも定義してみましょう

(抜粋)template.yml
Parameters: 
  Prefix: 
    Type: String 
    Default: testing 
    Description: Prefix Name 
 
  ServiceName: 
    Type: String 
    Default: cf-tutorial 
型指定とDefault値を指定できます。

詳しいオプションは

公式ドキュメント Parametersを参照してください。


Resouces

EC2やRDS、セキュリティグループ等AWSで使うサービスの定義をすべてしていきます。

ではまずはWEBサーバーを作成するにあたってのAWSリソースで最低限必要なものは下記です。

  • SecurityGroup
  • EC2
これを定義していきましょう

(抜粋)template.yml
Resources: 
  Ec2SecurityGroupApp: 
    Type: "AWS::EC2::SecurityGroup" 
    Properties: 
      GroupName: !Sub "${Prefix}_${ServiceName}_app" 
      GroupDescription: "web server security group" 
      VpcId: 
         "{your VPCID}" 
      SecurityGroupIngress: 
        - IpProtocol: tcp 
          FromPort: 80 
          ToPort: 80 
          CidrIp: "0.0.0.0/0" 
      Tags: 
        - Key: Name 
          Value: !Sub "${Prefix}_${ServiceName}_app" 
 
  Ec2InstanceServer: 
    Type: "AWS::EC2::Instance" 
    Properties: 
      AvailabilityZone: "ap-northeast-1c" 
      # AmazonLinuxを指定しています 
      ImageId: "ami-06cd52961ce9f0d85" 
      InstanceType: "t2.micro" 
      KeyName: "your キーペア名" 
      SecurityGroupIds: 
        - !Ref Ec2SecurityGroupApp 
      BlockDeviceMappings: 
        - DeviceName: /dev/xvda 
          Ebs: 
            VolumeSize: 8 
            VolumeType: gp2 
      Tags: 
        - Key: Name 
          Value: !Sub "${Prefix}_${ServiceName}_app" 
上から順番に説明していきます


Ec2SecurityGroupApp, Ec2InstanceServer (ResourceKeyName)

リソースの名前です。任意の名前をつけてください。


Type

なんのリソースを配置するかです。

名前がわからない場合はgoogleさんに「cloudformation EC2」とかでぐぐればgoogleさんが教えてくれます。


Properties:xxxxxxxx

指定したリソースのプロパティーです。プロパティがわからない場合は

cloudformation EC2」とかでぐぐればgoogleさんが教えてくれます。


!Sub,!Ref (CloudFormationの組込関数)

CloudFormationでは組込み関数が用意されています。

公式CloudFormation 組込み関数

書き方に少し癖があるのですが下記を覚えてしまえば難しくないです。


!{関数名}はショート記法

例えばショート記法を使わない場合でRefを使用したい場合だと

SecurityGroupIds: 
        - Fn::Ref: Ec2SecurityGroupApp 
 
と書きます。

:を段落区切りを表すyamlの場合この方式で書くと少々可読性が悪くなります。

なのでショート記法で書いている人のほうが多いです。


Ref

!Ref {パラメーター名} 
でパラメーターの値を参照できます。

!Ref {リソース名} 
で配置するリソースの返り値を取得できます。

リソース名の返り値は 「cloudformation EC2 リソース返り値」とかでぐぐれば.....

大概の場合リソースを参照したい場合は乱暴に

!Ref {リソース名} 
と宣言すればよしなに参照できます。


Sub

Parameterと文字列のテンプレートリテラルです。

文字列 + Parameterで値を作成したいときにつかってください。


実際に作ってみる

ではAWS cliを使ってCloudFormationを実際に動かしてみましょう。

ここまでのtemplateファイルは下記です。

template.yml

aws cloudformation create-stack \ 
--stack-name {任意のスタック名} \ 
--template-body file://`pwd`/template.yml \ 
--parameters file://`pwd`/parameters/testing.json 
もし一回目にエラーになった場合は2回目以降は下記です。

aws cloudformation update-stack \ 
--stack-name {任意のスタック名} \ 
--template-body file://`pwd`/template.yml \ 
--parameters file://`pwd`/parameters/testing.json 
EC2のGUIを確認してください。t2.microで {Prefix}-{ServiceName}_appというサーバーが立ち上がっているのが確認できます。

セキュリティグループもできていますね。


RDSを作成してみる

ここまでできたら要領は把握したのでRDSも作ってみましょう

(抜粋)template.yml
# RDSのセキュリティグループ 
  RdsSecurityGroupApp: 
    Type: "AWS::EC2::SecurityGroup" 
    Properties: 
      GroupName: !Sub "${Prefix}_${ServiceName}-rds" 
      GroupDescription: "dbserver security group" 
      VpcId: 
         "{your VPCID}" 
      SecurityGroupIngress: 
      - IpProtocol: tcp 
        FromPort: 3306 
        ToPort: 3306 
        SourceSecurityGroupName: !Sub "${Prefix}_${ServiceName}_app" 
      Tags: 
        - Key: Name 
          Value: !Sub "${Prefix}_${ServiceName}-rds" 
 
  RdsInstace: 
    Type: "AWS::RDS::DBInstance" 
    DeletionPolicy: Delete 
    Properties: 
      DBInstanceIdentifier: !Sub "${Prefix}-${ServiceName}-db" 
      AvailabilityZone: "ap-northeast-1c" 
      DBInstanceClass: "t2.small" 
      AllocatedStorage: 6 
      StorageType: gp2 
      VPCSecurityGroups: 
        - !Ref RdsSecurityGroupApp 
      Engine: MySQL 
      EngineVersion: 5.7.23 
      DBName: cf-tutorial 
      MasterUsername: cf-tutorial 
      MasterUserPassword: {your password} 
      Tags: 
        - Key: Name 
          Value: !Sub "${Prefix}_${TagServiceGroupName}-db-app-${CFVersion}" 
ここまでのtemplate.ymlは下記です
template.yml

ではコマンドを実行してみましょう。

aws cloudformation update-stack \ 
--stack-name {任意のスタック名} \ 
--template-body file://`pwd`/template.yml \ 
--parameters file://`pwd`/parameters/testing.json 
RDSとEC2が作成されてそれぞれのセキュリティグループが作成されています。


EC2のセキュリティグループに22番ポートが開いていなくてsshログインできないぽよ。。。。

困りましたね。。。

出来上がったEC2の内容を確認できません。

ですがセキュリティグループは慎重にやらないと事故のもとです。

そういった場合に便利なcreate-change-setというものがあります。


create change setとは?

create stackやupate stackのようにtemplateやパラメーターをスタックに送信しますが

リソースの変更を行わずにリソース変更部分の差分を出してくれます。

dry-runをイメージしてもらえるとわかりやすいと思います。

では実際にやってみましょう。


EC2インスタンスにSSHポートを追加する

template.ymlに追記しましょう

(抜粋)template.yml
Resources: 
  Ec2SecurityGroupApp: 
    Type: "AWS::EC2::SecurityGroup" 
    Properties: 
      GroupName: !Sub "${Prefix}_${ServiceName}_app" 
      GroupDescription: "web server security group" 
      VpcId: 
        "{your VPCID}" 
      SecurityGroupIngress: 
        - IpProtocol: tcp 
          FromPort: 80 
          ToPort: 80 
          CidrIp: "0.0.0.0/0" 
        # 追加内容 
        - IpProtocol: tcp 
          FromPort: 22 
          ToPort: 22 
          CidrIp: "0.0.0.0/0" 
      Tags: 
        - Key: Name 
          Value: !Sub "${Prefix}_${ServiceName}_app" 
 
ここまでのtemplateです。

template.yml

awscliの create-change-set を実行します。

aws cli create-change-set

aws cloudformation create-change-set \ 
--stack-name {任意のスタック名} \ 
--change-set-name add-securitey-group-ssh \ 
--template-body file://`pwd`/template.yml \ 
--parameters file://`pwd`/parameters/testing.json 
AWS CloudformationのGUIのスタックの項目を開いてください。

変更セットの部分に先程実行した

change-set-name 
の項目が出てきます。



create-change-set


このリンクを開くとリソースの変更内容がでてきます。



create-change-set2


変更した内容がEC2のセキュリティグループだけなのがわかりますね。

では変更セットの詳細画面右上の実行ボタンを押して反映させてみましょう。

スタックの状況が

UPDATE_COMPLETE 
になったら正しく反映できています。


RDSに接続できるか確認してみましょう

ssh -i ~/.ssh/{your キーペア名} -p22 ec2-user@{Your IP Adress} 
sudo yum install -y mysql-devel 
mysql -u cf_tutorial -p -h {your rds host} 
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g. 
Your MySQL connection id is 9 
Server version: 5.7.23-log Source distribution 
 
Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved. 
 
Oracle is a registered trademark of Oracle Corporation and/or its 
affiliates. Other names may be trademarks of their respective 
owners. 
 
Type 'help;' or '\h' for help. Type '\c' to clear the current input statement. 
 
mysql> show databases; 
+--------------------+ 
| Database           | 
+--------------------+ 
| information_schema | 
| cf_tutorial        | 
| innodb             | 
| mysql              | 
| performance_schema | 
| sys                | 
+--------------------+ 
6 rows in set (0.00 sec) 
DBに入れました。


スタックの掃除をしてみましょう

これでCloudFormationの流れがつかめてきたと思います。

では最後にCloudFormationの削除を実行してみましょう。

CloudFormationで定義されたリソースの削除は非常に簡単にできます。

aws cloudformation delete-stack --stack-name {任意のスタック名} 
これだけです。

定義したリソースすべてをキレイサッパリ削除してくれます。

リソースの消し忘れがなくて良いですね!!


Parameterのオーバーライドによるtest環境,production環境を別々に作る

今まで作成したものはtest環境用のリソースです。

そこでproduction用に作るやり方を紹介します。

今回は一つのテンプレートで変数のみを変更して複数のenv環境を作るやり方です。


production.jsonを変更する

Prefixの値を上書きしましょう。

production.json
[ 
  { 
    "ParameterKey": "Prefix", 
    "ParameterValue": "production" 
  } 
] 
こうすることによって template.yml で定義されているParameter Prefixをオーバーライドすることができます。

コマンドはいままで --parametersで指定していた testing.jsonproduction.jsonに変更します。

コマンドは下記です。

(stack-nameはtesting環境と違う名前で登録してください。CloudFormationがtesting環境のリソースを上書きます)

aws cloudformation create-stack \ 
--stack-name {任意のスタック名} \ 
--template-body file://`pwd`/template.yml \ 
--parameters file://`pwd`/parameters/prodcution.json 
一つのテンプレートで複数環境ができました。


最後に

ちょっとドキュメントを読んだだけではわかりにくいCloudFormationですが

手を動かしてしまえば意外とシンプルです。

それでは楽しい?CloudFormationライフを!!

コメント

このブログの人気の投稿

投稿時間:2021-06-17 05:05:34 RSSフィード2021-06-17 05:00 分まとめ(1274件)

投稿時間:2021-06-20 02:06:12 RSSフィード2021-06-20 02:00 分まとめ(3871件)

投稿時間:2020-12-01 09:41:49 RSSフィード2020-12-01 09:00 分まとめ(69件)