これは ドリコム Advent Calendar 2016 の1日目です

自己紹介

こんにちはインフラストラクチャー部のsue445(末吉)です。

ドリコムのインフラストラクチャー部は数人いて、そのうち僕はサーバに関係することはアプリからインフラまでだいたいやってます。

良く言えば「フルスタックエンジニア」で、悪く言えば「ワンオペ」ですw

今はレガシーな社内アプリのリプレイスをやっています

  • Ruby 2.1.2 -> 2.3.1
  • Rails 4.0.0 -> 5.0.0.1
  • Debian Lenny -> CentOS 7.2
  • capistrano 2系 -> 3系
  • Bootstrap 2系 -> 3系
  • resque -> sidekiq

ドリコムのインフラCIについて

先日とある勉強会に誘われてしゃべる機会があったので、その時のスライドを公開したいと思います

ドリコムのインフラCI from Go Sueyoshi (a.k.a sue445)

表紙以外は当日使ったのと全く同じです

補足

スライドに書ききれなかった補足情報です

タグについて

AWSではタグ、IDCFではユーザデータとして、VMに対して任意のデータを設定できますが、下記のようなものを利用しています

名前 説明 備考
env 本番かステージングなど production, staging など、おおよそRailsアプリであればだいたい

RAILS_ENV

に対応しています
service サービス名
roles インスタンスの役割
(*1)
daemons 起動したいcollectdのdaemonの種類 memcached, mysql, nginx, redis, unicorn

(*2)
numbering ナンバリング 01-01, 01-02
consul_server_addr consul serverのIPアドレス 11.22.33.44

  • (*1)

    : roleの種類

    • web : nginxをインストールしてユーザからのリクエストを受けるrole。弊社ではこのwebサーバでRailsアプリが動いています
    • db : MySQLでデータを永続化するrole
    • cache : memcachedなどキャッシュ用途のrole
    • kvs : redisを動かすrole
    • job :

      Sidekiq

      のジョブを動かすrole。nginxが動いていない以外はwebと構成は同じ
    • all : web + job + db + kvs + cache のオールインワン(全部入り環境)です。ステージング用のアプリや小さい社内アプリなどでよく使われる
    • consul_server : consul serverを起動するrole
    • build : stretcherでデプロイする時に

      bundle install



      assets:precompile

      を実行してアプリをtarに固める環境

  • (*2)

    : daemons

    • memcachedやunicorn用のcollectdの設定ファイルを配置することでメトリクスを社内の監視サーバに送信しています

hostnameについて

service, env, roles, numbering, 自分自身のIPアドレスを組み合わせることでhostnameをレシピで設定しています

  • 例)app1-web-01-01-11x22x33x44, app1staging-db-12x34x56x78
  • productionをhostnameに含めていないのは、ほとんどのサーバが本番サーバにあたるのでわざわざつける必要がないため
  • serviceとenvの間にハイフンがないのは、productionをhostnameに含めないルールだとserviceとenvの間にハイフンを入れると別の監視ツールでsplitした時にproductionかそれ以外かで場合分けが必要になるため

当日の質問とその回答

itamae実行は1回でもよかったのでは?

当初は1回のitamaeの実行で全てのプロビジョニングが完結するようにしていたのですが、

  • serviceやroleはサービスインする時に初めて付与するものなので、CI実行時には自分がどのserviceやroleを付与されているか分からない
  • itamaeを1回にするとロール毎にイメージを作成する必要があるが、それだとイメージが大量に作られて管理が大変になる

    • roleが1つだけならいいんだけど、web+job, kvs+cacheなどの組み合わせとかも考慮すると必要なイメージが無限になる

ため、管理するイメージをなるべく少なくするためにこのような仕組みにしました。(作成時期によってイメージはいくつも作られるが、最新のイメージは常に1つ)

またタグを付与してイメージ起動する時にsystemdでitamae-bootstrapというserviceを実行して2回目のitamaeを実行されるようになっていますが、一度タグを付与して起動してしまえばそれ以降は再起動してもitamae-bootstrapが実行されないようになっています。

サーバ作る時に毎回タグつけるの手間では?

手動でタグを付与するのはサーバを最初に作る1回だけなのでそんなに手間ではないです。(だいたいが社内アプリや開発サーバなどサーバの台数が増減しないサーバ)

本番環境に投入されているアプリはオートスケーリング時に自動的にタグを付与しているので人間が頻繁にタグを設定しているということはないです。

レシピ増えた時の管理の工夫

弊社では下記のようなディレクトリ構成でレシピを管理しています

  • bootstrap.rb

    • cookbooks/

      • system/ : システムが必要としているレシピ

        • 00-SELiniux/
        • 00-user/
        • 10-package/
        • 20-hostname/
        • NetworkManager/
        • collectd/
        • monit/
        • などなど
      • service/ : サービスが必要としているレシピ

        • consul/
        • memcached/
        • nginx/
        • percona_server/
        • などなど
  • apps/

    • app1/ : アプリ固有のレシピ

      • cookbooks/

        • system/
        • service/

  • ルートの bootstrap.rb を起点にitamaeを実行

    • 実行順は上のディレクトリ図の順番(cookbooks/system/ -> cookbooks/service/)
  • system配下、servoce配下のディレクトリを名前順に自動で

    include_recipe

    して実行
  • 実行したいレシピは基本的に順番に依存しないようになってるが、どうしても実行順を制御したい場合はディレクトリ名に

    00-

    ,

    10-

    などをつけることにより先に実行している
  • apps/ 配下に、アプリによって個別に適用したいレシピを配置

    • アプリ名はタグのserviceから取得している

レシピ適用後に手動オペレーションが発生する場合はどうしてる?

セキュリティパッチなどは

Rundeck

から既存の複数サーバに対してコマンド実行しています

今の弊社の運用だと既存サーバは基本的に作り直したりはしないですが、オートスケーリング対象サーバだとオートスケーリングを利用してベースイメージを新しくすることはあります

例)10台のインスタンスで運用している時

  1. セキュリティパッチを当てた状態でイメージを作成
  2. オートスケーリングのサーバ台数の上限を一時的に2倍(インスタンス20台)にする
  3. 新しいベースイメージでインスタンス10台立ち上がる
  4. 全部でインスタンスが20台になった後でオートスケーリングの上限を10台に戻せば古いもの10台が止まる
  5. 最終的に新しいベースイメージのインスタンスが20台出来上がる

レシピ自体修正した場合は都度最新のイメージ作っています

最後に

ざっくりとですがitamaeとJenkinsを利用した弊社のインフラCIについて紹介しました。

実はインフラCI以外にも、IDCFでZabbixを利用したオートスケーリングの仕組みやconsul + stretcherによるデプロイなど今回書ききれなかった新しい仕組みたくさんありますので、それはまた後続の人がきっと書いてくれるでしょう!