娘にぞっこんアラサーエンジニアのpataijiです。
アラサーという言葉を初めて自分に使ったのでドキドキしています。
先日開催されたSpeeeKaigi#3 でCloudFormationのテンプレート管理をなんとかする、「Cloudruler」を紹介しました。
↓ SpeeeKaigi#3 についてはこちら tech.speee.jp
当日のスライド
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を切ってくれる、そんな方に会える日に向け日々是精進。