LoginSignup
96
77

More than 5 years have passed since last update.

AWS SAMを使う前にCloudFormationテンプレートを書こう

Last updated at Posted at 2019-01-23

はじめに

AWSでサーバレスの開発をするにはSAMを使うという記事や話を聞いたことがある人は多いと思います。じゃあ、自分もSAMでやってみようと思ってやってはみたものの、SAMのテンプレートが書けない!って挫折した人が少なからずいると思います。私もその一人でした:scream::scream::scream:。おそらく、そのような人は、AWS CloudFormation のテンプレートを書いたことがない人だと思います。
実は、SAMのテンプレートは、CloudFormationテンプレートの拡張です。AWS SAM Template Basicsに、このように書かれています。

AWS SAM templates are an extension of AWS CloudFormation templates. That is, any resource that you can declare in an AWS CloudFormation template you can also declare in an AWS SAM template. In addition, you can use the additional resource types provided by AWS SAM—for instance, the resources described in Declaring Serverless Resources—as shortcuts for some components of your serverless application.

Google翻訳してもらうと、こうなります。

AWS SAMテンプレートは、AWS CloudFormationテンプレートの拡張です。つまり、AWS CloudFormationテンプレートで宣言できるリソースであれば、AWS SAMテンプレートでも宣言できます。さらに、AWS SAMが提供する追加のリソースタイプ(サーバーレスリソースの宣言で説明されているリソースなど)を、サーバーレスアプリケーションの一部のコンポーネントのショートカットとして使用できます。

また、このすぐ下にもこのように記述があります。

For an introduction to AWS CloudFormation templates, see Learn Template Basics.

Learn Template Basicsのリンク先が、CloudFormationのページにリンクが貼ってあるのです。CloudFormationのテンプレートが書ければ、SAMのテンプレートもかけるでしょう!ということで、AWS SAMを使う前にCloudFormationテンプレートを書こうと題して、私が、CloudFormationのテンプレートを書き始めた時のことを纏めてみました。

事前にやっておくこと

まずは以下のページを読んで雰囲気をつかみましょう

権限があることを確認しよう

  • AWSアカウントの管理をしてない人は管理者に確認しましょう。もし、権限がもらえない場合はここで終了です:no_good_tone2:
  • 権限については、BlackBeltの82〜84スライドを参照しましょう

テンプレートを記述する環境を整えます

インストールする必要があるもの

  • AWS CLI
  • VS Code
    • 別のエディタでもよいですが、みんなが使っていると思うので。。。
  • VS Code 拡張機能:CloudFormation
    • 完全に対応しているわけではありませんが、ある程度のことはやってくれますので私は重宝してます。 image.png

そのほかにやっておくこと

  • CloudFormationで管理したいサービスをConsole(GUI)で弄っておきましょう。一度も触ったことがないサービスをCloudFormationのテンプレートを書くのは難しいと思います。
  • CloudFormationのテンプレートは、YAMLもしくはJSONで記述できますが、YAMLのほうが書きやすいと思います。もし、YAMLの書式を知らない場合はぐぐっておきましょう。

まず簡単に作れるサービスから書いてみる

  • 準備ができたら、まずはテンプレートを書いてみましょう。Lambda FunctionをCloudFormationテンプレートで記述するとちょっと面倒です。なので、まずはS3のように簡単に作れるサービスから記述するとよいと思います。(どのサービスも最初に細かい設定をするとどれもめんどいです。そこを誤解しないでくださいね)

  • VSCodeで新規ファイルを作成し、言語モードをYAMLにしておきます。もしくは、sample.ymlで保存しておきます。

  • VSCodeにstartと入力します。そうすると、以下のように機能拡張が書いてくれます。
    image.png

  • Resourcesに下にカーソルを移動させ、インデントした後で、s3と入力します。
    image.png

このように候補が出てくるので、s3-bucketを選択します。そうすると、以下のようになります。機能拡張さまさまです。

image.png

  • 初回なのでまずは必須のところだけにしてみます
template.yml
AWSTemplateFormatVersion: 2010-09-09
Description: >
  Sample template 
Resources: 
  s3Bucket:
    Type: AWS::S3::Bucket
    Properties: 
      AccessControl:  BucketOwnerFullControl
      BucketName: (ここは一意になる名前を入力)

機能拡張は、Bucketnameで書き出されますが、BucketNameが正解なのでご注意ください。

デプロイしてみます

デプロイは簡単です。

aws cloudformation deploy --template-file template.yml --stack-name sample-s3-0121

テンプレートファイルとスタック名を指定するだけです。
これで問題がなければ、

Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - sample-s3-0121

と表示されます。ここで、バケットの一覧を確認してみると、作成できていることが確認できると思います。

テンプレートを書くために最低限知っておくべきこと

戻り値

サービスによっては、他サービスのARNを指定するようなことがあります。そのような場合は戻り値を使います。例えば、Lambda FunctionをRoleを指定するようなときは、Role: !GetAtt iamRole.Arnのように指定します。「iamRole」部は、論理 IDで指定したIDになります。
戻り値で何が取得できるのかは、AWS リソースプロパティタイプのリファレンスに記述があるので、そこを参照しましょう

組み込み関数

テンプレート内で関数を使うことができます。最低でも、!Sub!Ref!GetAttは使うことになると思います。

      # Lambda関数名が展開される
      LogGroupName: !Sub /aws/lambda/${lambdaFunction}

      # パラメータを取得する
      Bucket: !Ref LogBucket

      # 属性値を取得する
      DomainName: !GetAtt S3Bucket.DomainName

最初のうちはこの3つがわかっていればなんとかなると思います。

パラメータ

固有の値はテンプレートに書くべきではありません。再利用する際に変更が必要だし、Githubにあげた時などに事故につながることが考えられます。そのような値にはパラメータを使いましょう。

Parameters: 
  MyBucketName:
    Type: String 
  Environment:
    Type: String
    AllowedValues: 
      - dev
      - stg
      - prod
    Default: dev

このように定義を行い、

aws cloudformation deploy --parameter-overrides MyBucketName="hogehoge"

というようにパラメータを渡しましょう

ハマるポイントと解決策

ここまでできれば、後は、テンプレートをいろいろ書いてみるだけです!:sunglasses:
ここからは、私が書いた時にハマったポイントです。

初回のdeployからエラーとなり、テンプレートを更新してからdeployしたけど、以下のエラーが表示される

An error occurred (ValidationError) when calling the CreateChangeSet operation: Stack:arn:aws:cloudformation:ap-northeast-1:***:stack/sample-s3-0121/5ffdf040-1d69-11e9-9f4f-0ec110ab8a1e is in ROLLBACK_COMPLETE state and can not be updated.

こんな時は、stackを削除してからdeployしましょう。削除するには、aws cloudformation delete-stack --stack-name hogehogeで削除できます。

UPDATE_FAILEDになるけど、テンプレートのどこが悪いのかわからない

CloudFormationのステータスをコンソールから確認している場合、FAILになった理由は表示されるけど、どこが悪いのかわからないことがあります。よくあったのが、関数を多用していて、関数が処理された後のテンプレートは見れないためどこが悪いんだよ〜という場合です。このような時には、コマンドを叩いて、関数が処理されたテンプレートを確認しましょう。

aws cloudformation describe-stack-events --stack-name {stack名} | grep "UPDATE_FAILED"

grepをかけないと、ROLLBACKされた正しいテンプレートも表示されるので注意しましょう。

何を指定していいのかわからない

同じサービスで既に動かしているものがあれば、コマンドでconfigを表示してみるとわかると思います。例えば、ClooudFrontのテンプレートを書いていてわからない時には、aws cloudfront get-distribution-config --id hogehogeです。

それでもわからない場合は、以下は参照しましょう:upside_down:

  • 各サービスのAPIリファレンス
  • グーグル先生で検索
    • 検索すればいろいろとでてきます。それらを参照しましょう。

テンプレートのチェックがOKでも、FAILすることがある

テンプレートの文法がOKでも、deployした時にFAILすることがあります。そういうものです。

aws cloudformation validate-template --template-body file://template.yaml 

validate-templateに過度な期待をしないようにしましょう。

参照するページ

私がよく見るページをまとめました

リファレンス

サンプルやTips

更新情報

  • Release History
    • 日本語のページは更新が遅いようなので、最新情報は英語版のページで確認しましょう

最後に

CloudFormationテンプレートの書き始めるために必要な点だけまとめました。書き慣れてないうちは、試行錯誤が続くことがありますが、検索すればいろいろと出てきます。皆さんの情報を参考しつつ、根気よく書き続けましょう。

AWS CDK

まだ使ったことがありませんが、AWS CDKというものがあります。これにより、テンプレートを書く必要がなくなるかもしれませんね。。。

96
77
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
96
77