Codenize.tools を使ったインフラ管理について

以下は2016-12-19に会社(Fablic, inc.)の技術ブログinFablicに投稿した記事(http://in.fablic.co.jp/entry/2016/12/19/123807)になります。
inFablicが閉鎖され閲覧ができなくなってしまったため、会社の了承を取った上で転載しております。

元記事にリンクを貼っていただいていた方に対しては大変お手数ですが、こちらにリンクし直していただければ幸いです。


この記事は Fablic Advent Calendar 19日目の記事です。

こんにちは、Fablicでサーバーサイドエンジニアをやっている yutadayo です。

今回は AWS の環境設定をコードで管理できる Codenize.tools の紹介と弊社での運用事例についてご紹介しようと思います。

インフラのコード化について

みなさんは、infrastructure as code を進めるにあたってどういうツールを使っていますでしょうか。 AWSの構成管理は CloudFormation や 最近では Terraform などが注目を集めているようですね。

弊社では chef でサーバの設定やデプロイをしていますが、AWSの操作は Management Console でポチポチしている部分も多かったので、既存の環境をコードで管理できる Codenize.tools を導入してみました。 導入する前は下記のような悩みを感じていました。

  • Management Console で行った操作の履歴を残すのが困難
  • 操作する際の心理的安全の欠如
  • 大量の設定をするときにポチポチ設定が面倒、時間がかかる
  • インフラ構成変更の依頼フローが統一されていない

これらの悩みをツールの導入によって、解決したいなと考えていました。

Codezine.tools について

Cookpadwinebarrelさんがメンテナンスされている、AWSDSLの記述で管理できるツール群です。

既に本番環境で稼働しているAWSの設定を管理したいと思っていたので、特別なセットアップや用意をしなくても、 簡単に導入できるという点で、大変魅力的でした。

また、Codenize.tools はどのツールも、簡単かつ直感的に使うことができ、生成されたコードも、Githubで管理できるので、上記のような問題も解決できると考えました。

弊社では RoadwokerPiculetRadiosonde など複数のツールを使っています。

導入

Codenize.tools を見れば、ほとんどのことが記載されていますし、 各AWSサービスを扱うのに必要なポリシー設定がされているアカウントがあれば、すぐにでも導入が可能です。

例)Roadworker

RoadworkerはRoute53の管理を行うツールです。

$ bundle exec roadwork -e -o Routefiles/example.jp.route --target-zone "^example.jp"
Export Route53 to `Routefiles/example.jp.route`

-e オプションを指定して、既存の環境設定をDSLとして出力できます。 出力された、ファイルの中身は下記のようになっています。

# -*- mode: ruby -*-
# vi: set ft=ruby :
hosted_zone "example.jp." do
  rrset "example.jp.", "A" do
    ttl 3600
    resource_records(
      "xx.xx.xxx.xxx"
    )
  end
end

--dry-run コマンドを使って、事前に適応内容を調べることができます。 上記のファイルの resource_records を更新して、コマンドを実行すると下記のようなログが流れます。

$ bundle exec roadwork -a --dry-run
Apply `Routefile` to Route53 (dry-run)
Update ResourceRecordSet: example.jp. A (dry-run)
  resource_records:
    -[{:value=>"変更前IP"}]
    +[{:value=>"変更後IP"}] (dry-run)
No change

冪等性が保証されているので、Route53がすでに定義ファイル通りの設定の場合は何も変更は行われません。

$ bundle exec roadwork -a
Apply `Routefile` to Route53
No change

Codenize.tools は Roadworker 以外にも沢山ありますが、どのツールもコマンドのインターフェイスは 統一されていて、基本的な操作の流れは変わらないので、非常に扱いやすいのも魅力です。

ディレクトリ構成

一つのAWSアカウントで複数の運営サービスを管理されている場合や、運営サービス毎にAWSのアカウントを分けている場合があるかと思います。 いずれにせよ、exportしたときのファイルが膨大になってしまうので、弊社では運営サービス毎にexportするディレクトリを分けて運用しています。

f:id:yutadayo:20161218205044p:plain

RoadworkerやPiculetで出力されるファイルはホストやリージョンによって設定を分けた方が見やすいので、 ファイルを分割し、Routefile内で他のファイルをrequireする構成にしています。

# -*- mode: ruby -*-
# vi: set ft=ruby :

Dir::glob('./Routefiles/*.route').each do |file|
  require file
end

また、使用時には AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY環境変数に設定しないといけないのですが、 AWSアカウントやAWSサービス毎に毎回変更するのは面倒です。

この問題には direnv を導入し、各ディレクトリに .envrc を設定することで 該当ディレクトリに移動すると、必要な環境変数が設定されるようにしています。

.envrc の中身は下記のようになっています。

export AWS_ACCESS_KEY_ID='xxxxxx'
export AWS_SECRET_ACCESS_KEY='xxxxxx'

運用について

Github上にCodezine.toolsで生成されるコードを管理するリポジトリを用意し、構成変更を行う際は issue を作り、変更差分の Pull Request を出してもらうフローで運用しています。ワークフローは下記のように行われます。

  1. インフラの設定変更の依頼をGithubでissue立て
  2. 設定変更の修正をPull Request
  3. Pull Requestをレビュー(dry-run)して問題がなければマージ
  4. masterブランチに merge して、本番環境に適応

f:id:yutadayo:20161218192043p:plain

Elasticsearchなど複数のEC2インスタンスクラスタを組んだりする際に、インスタンス全てに監視の設定をポチポチしていくのは大変な辛さがあったのですが、コードで管理しているので、既存の設定をコピーできて作業が大変楽になりました。

運用後の効果

変更内容の履歴が残る

スタートアップではインフラ専門のエンジニアの確保はなかなか難しく、運用が属人化しやすいと感じています。 問題と感じていた構成変更はGitでコードとして管理されるようになったので、いつ誰がどのように変更を行ったかが diff や履歴を追うことで分かるようになりました。

オペレーションフローができた

Slack上でのチャットやMTGでの依頼ベースで運用していたインフラの構成変更に、Github Pull Request を用いて運用できるフローができたのは良かったと思っています。また、変更の適応もコマンドを実行するだけなので、オペミスを防止することができます。

運用効率の向上

大量の設定をポチポチしながら変更していた運用も、既存コードのコピーで済ますことができ、開発効率が向上しました。

おわりに

上述の悩みは、Codenize.tools の導入で解決することができました。 しかし、各コマンドの適応作業は今の所、エンジニアが手動でコマンドを実行しているので、今後はPull Request がマージされたタイミングでの自動適応を行なって完全な自動化をしていきたいと思っています。

また、Terraform 0.7 のリリースから 既存リソースの import 機能が提供されるようになっているので、 部分的に代替となるツールの選定も進めていきたいなと思っています。

最後に、これほど便利なツールを提供してくださってる winebarrel さんをはじめとした開発者の皆様に心からお礼を申し上げます。