CloudFormationの管理を楽にする

娘にぞっこんアラサーエンジニアのpataijiです。

アラサーという言葉を初めて自分に使ったのでドキドキしています。

先日開催されたSpeeeKaigi#3 でCloudFormationのテンプレート管理をなんとかする、「Cloudruler」を紹介しました。

↓ SpeeeKaigi#3 についてはこちら tech.speee.jp

当日のスライド

speakerdeck.com

CloudFormationを使用している方にはそれなりに共感いただけると思うのですが、テンプレートファイルの管理ってかなり大変じゃないですか?

最近では、SAMのおかげで簡単にサーバーレスアプリケーションを作ることが出来るようになりましたが、VPC、EC2、RDS等をCloudFormationで管理する大変さは変わりません。

テンプレートをYAMLで書けるようになり、JSONしか対応していなかった頃と比べるととても良くなったなぁとは思うものの、どうしても冗長な記述が生まれがちですし、何より記述量が多い。

さらに初見殺しなのは、ドキュメントをしっかり読み込まないとRDS一つ用意するのにも苦労する繊細なリソース群。

公式のテンプレートスニペットやWeb上に公開されているテンプレート達を見ては感じるベストプラクティスはどれですか感。

そんな迷えるCloudFormation使い(私)を救うべく、Cloudrulerを作りました。

Cloudrulerが提供する機能はざっくり以下の2つです。

  • Rulerというスニペット機能
  • Pluginによるスニペットの配布と利用

Rulerというスニペット機能

RulerとはChefでいうCookbookのようなものです。

Rulerとしてスニペットを定義しておくとTemplateから簡単に呼び出すことが出来ます。

以下にサンプルを示します。

$ tree
.
├── Gemfile
├── rulers
│   ├── subnet.yml.erb
│   └── vpc.yml.erb
└── templates
    └── sample.rb
rulers/vpc.yml.erb
# vpc: VPC
---
Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: <%= @cidr %>
      EnableDnsSupport: true
      EnableDnsHostnames: true
  InternetGateway:
    Type: AWS::EC2::InternetGateway
  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: !Ref VPC
      InternetGatewayId: !Ref InternetGateway
  RouteTablePublic:
    Type: AWS::EC2::RouteTable
    DependsOn: AttachGateway
    Properties:
      VpcId: !Ref VPC
  RoutePublic:
    Type: AWS::EC2::Route
    DependsOn: AttachGateway
    Properties:
      RouteTableId: !Ref RouteTablePublic
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: !Ref InternetGateway
rulers/subnet.yml.erb
# subnet: Subnet
---
Resources:
  Subnet:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: !Ref <%= @vpc %>
      AvailabilityZone: <%= @availability_zone %>
      CidrBlock: <%= @cidr %>
      MapPublicIpOnLaunch: true
templates/sample.rb
description 'This is a sample template.'

vpc = ruler :vpc do
  @cidr = '10.0.0.0/16'
end

ruler :subnet, resource_name_suffix: 'PublicA' do
  @vpc = vpc.resources.vpc
  @availability_zone = 'ap-northeast-1a'
  @cidr = '10.0.1.0/24'
end

ruler :subnet, resource_name_suffix: 'PublicC' do
  @vpc = vpc.resources.vpc
  @availability_zone = 'ap-northeast-1c'
  @cidr = '10.0.2.0/24'
end
実行

上記のようなファイルを用意した後、コマンドを実行するとCloudFormationのテンプレートファイルに展開します。

$ cloudruler dump templates/sample.rb
---
AWSTemplateFormatVersion: '2010-09-09'
Description: This is a sample template.
Resources:
  VPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.0.0/16
      EnableDnsSupport: true
      EnableDnsHostnames: true
  InternetGateway:
    Type: AWS::EC2::InternetGateway
  AttachGateway:
    Type: AWS::EC2::VPCGatewayAttachment
    Properties:
      VpcId: VPC
      InternetGatewayId: InternetGateway
  RouteTablePublic:
    Type: AWS::EC2::RouteTable
    DependsOn: AttachGateway
    Properties:
      VpcId: VPC
  RoutePublic:
    Type: AWS::EC2::Route
    DependsOn: AttachGateway
    Properties:
      RouteTableId: RouteTablePublic
      DestinationCidrBlock: 0.0.0.0/0
      GatewayId: InternetGateway
  SubnetPublicA:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: VPC
      AvailabilityZone: ap-northeast-1a
      CidrBlock: 10.0.1.0/24
      MapPublicIpOnLaunch: true
  SubnetPublicC:
    Type: AWS::EC2::Subnet
    Properties:
      VpcId: VPC
      AvailabilityZone: ap-northeast-1c
      CidrBlock: 10.0.2.0/24
      MapPublicIpOnLaunch: true

Rulerの良いところは、冗長な記述を排除できるところにあります。

例えば上記の例ですと2つのSubnetを用意していますが、Rulerとして定義してあるので、設定の異なる部分のみをDSLとして記述するだけで事足ります。

また、よく使うリソースの組み合わせをRulerとして定義することで、複雑なAWSのリソース群を構造化出来ます。

上記の例では、VPCとInternetGatewayの設定をRulerとして定義しています。

新たにチームに加わったメンバーは簡単なDSLを記述するだけで標準的なVPCを構築できますし、いざとなればRulerとして構造化されたリソースを紐解くことも可能です。

Rulerを適切に使用することで、DRYにテンプレートを実装可能となり、さらに学習コストを下げることが出来るようになります。

Pluginによるスニペットの配布と利用

ItamaeのRecipeのように、作成したRulerをPluginとして簡単に配布することができます。

社内の他チームに提供することはもちろん、公開されたPluginを再利用することで車輪の再発明を防ぐことが可能になります。

と、自信をもって書くことが出来ればよかったんですが、例によって時間が足りずPluginに関しては現在未実装です。。。

この辺りは私が開発を担当しているプロダクトでドッグフーディングを続けながら、せこせこ改善していこうと思います。

ということで、Cloudrulerの人柱になりIssueを切ってくれる、そんな方に会える日に向け日々是精進。