Hatena::ブログ(Diary)

naoyaのはてなダイアリー

August 21, 2014

インフラの継続的デリバリー

事前に断っておくがここでいう「インフラ」はレイヤ的には OS より上の話。

少し前に GitHub 時代のデプロイ戦略 - naoyaのはてなダイアリー で、GitHub を介したデプロイを実践しているということを紹介した。普段の開発を Pull Request ベースでやっているので、デプロイもまた Pull Request を契機に実行させると色々捗る、という話。

このプラクティスの対象領域をインフラにまで拡大してみました、というのが今回の話。

DNS レコードを Pull Request を merge した契機に自動で更新

AWS を利用している場合、ドメインの管理も Amazon Route 53 を使うといろいろと都合がいい。

Route 53 での DNS レコードの更新はこれまでブラウザから操作していた。これだと誰がいつ作業したかわからないし履歴もトラックしづらい。また変更確定前に事前レビューするのにも向いてない。

そこで roadworker を使う。roadworker は Route 53 の DNS レコード設定を ruby の DSL で書けるようにするツール。裏では Route 53 と API で通信する。

roadworker を使うと、以下のようにレコードを Ruby のファイルで書ける。(GitHub から引用)

hosted_zone "winebarrel.jp." do
  rrset "winebarrel.jp.", "A" do
    ttl 300
    resource_records(
      "127.0.0.1",
      "127.0.0.2"
    )
  end

  rrset "winebarrel.jp.", "MX" do
    ttl 300
    resource_records(
      "10 mx.winebarrel.jp",
      "10 mx2.winebarrel.jp"
    )
  end
end

こうして「DNSレコードの現在の状態」がコードになったので、あとはいつも通り Git と GitHub のフローに乗せることができる。ファイルの更新には Pull Request を使い、コードレビューする。万歳。

更に、Route 53 への設定の適用すなわち roadworker の実行は CircleCI に任せる。Pull Request が master に merge されたら自動で roadwork コマンドを実行するようにする。テストフェーズで dry run するようにすれば、万が一 Ruby コードが壊れていてもそれを検知できる。

dependencies:
  pre:
    - bundle install:
        timeout: 600

test:
  post:
    - bundle exec roadwork --dry-run --apply

deployment:
  master:
    branch: master
    commands:
      - bundle exec roadwork --apply

実行を CircleCI に任せれば (Git にファイルの更新履歴が残るだけでなく) 実行履歴のログも残せるし、ステータスを Slack に通知するのも簡単。

DNS レコードを書き換える、というと「えーと、どうやるんだっけ? インフラ担当お願い」ということになりがちだが、これで、前例に倣って Pull Request を投げて merge するだけですべてが実行される、ということになった。

以上は最近 KAIZEN platform Inc. に入社した glidenote さんのお仕事である。グッジョブ

Chef の適用も CircleCI 経由で、そして ChatOps

アプリケーションのデプロイを Pull Request をマージするタイミングで実行するという考え方を DNS 変更にも適用したのが先の例。同様に「もう Chef でのインフラの変更も全部同じようにやっちゃえよ」ということで mdoi がやったった。

(ここでは簡易的に master に merge したらと書いているけど、実際にはデプロイ用のブランチが別にあったりとちょっと設計は異なる)

Chef のクックブックのサーバーへの適用には knife-solo を使っているが、それを CircleCI に実行させる。CircleCI には ssh の秘密鍵をセキュアに渡せる仕組みがあるので、認証周りの心配も特に必要ない。CircleCI に実行を任せることで、毎回の実行ログをそのまま残せるのは先の DNS の例に同じくで、とても良い。

インフラに実際にコードを適用するのは、クックブック変更 Pull Request の merge 契機だとさすがにアグレッシブすぎるので、冒頭でも紹介した以前の記事に同じく、デプロイ用の Pull Request を使う方法を採用している。インフラに最新のクックブックを適用したいな、と思ったら deployment/qa-proxy など、デプロイ用のブランチに Pull Request を作って merge する。すると CircleCI が動き出して対象システムに Chef 適用を始める。

ここまで来たら、例によって ChatOps。

インフラへの変更適用もチャットからやってしまえばよい。これで、複数の担当者が同時にインフラに適用する、なんてことも自然と防ぐことができる。

インフラを自動で更新なんていうとえらくリスクの高いことをやっているように聞こえるが、実際には手元で knife solo していたのを CircleCI に実行させているだけであり、このプロセスに移行することによるリスクの増化はない。

「Merge pull request」ボタンに作用を集約させる

こうして、システム構成の変更などの作用を PullRequest + CircleCI によるオペレーションに集約させる、というのはなかなか良いプラクティスである。

単に Pull Request を送って変更しましょうね、だけでも十分に恩恵はあるのだけど、実際に何かしらの変更実行のトリガが「Merge pull Request ボタンを押す」というボタンに紐づけられると意識しなくても自然と Pull Request を送っておこうという考え方になる。DNS に変更を加えたい → Pull Request をマージしたら (※ 実際には master に変更があったら) 変更処理が自動で行われる → じゃ、プルリク作るか、という具合。

こうして結果的に、何をやるにも緑のボタンを押すだけ、すなわちワンクリップデプロイの仕組みが構築できた。Infrastructure as Code を推し進めて、インフラも CI して、ワンクリックデプロイ ─ 継続的デリバリーの実践である。

August 15, 2014

BigQuery と Google の Big Data Stack 2.0

先日、有志で集まって「BigQuery Analytics」という書籍の読書会をやった。その名の通り Google BigQuery について書かれた洋書。

BigQuery を最近仕事で使い始めたのだが、BigQuery が開発された背景とかアーキテクチャーとかあまり調べもせずに使い始めたので今更ながらその辺のインプットを増やして以降と思った次第。

それで、読書会の第1回目は書籍の中でも Overview に相当するところを中心に読み合わせていった。それだけでもなかなかに面白かったので少しブログにでも書いてみようかなと思う。

BigQuery の話そのものも面白いが、個人的には Google のインフラが書籍『Google を支える技術』で解説されたものが "Big Data Stack 1.0" だとして、BigQuery は Big Data Stack 2.0 の上に構築されており、更に Google 内部ではとっくに Big Data Stack 3.0 に移行してる (しつつある?) みたいな話に強く興味を持った。(まあ、3.0 は論文にも何にも発表されてないので、そういうニュアンスのみしか嗅ぎ取れないのではあるが)

Google BigQuery

Google BigQuery は、一言でいうと「超でかいデータをSQLで数秒で解析できるクラウドサービス」。

f:id:naoya:20140815185813p:image

例えば fluentd なんかで毎日ログを送りつけておいて、溜まった 数百GB とか数TB、あるいは数PB とかになったデータに SQL を投げるとちゃんと結果が返ってくる、そういうもの。いわゆるビッグデータ基盤である。裏側では当然分散処理が行われていて、Google の持つ大量のコンピュータとディスク、それから高速なネットワークによってそれが処理されている。

もっと知りたいという方は hadoop - Googleの虎の子「BigQuery」をFluentdユーザーが使わない理由がなくなった理由 #gcpja - Qiita あたりを参照すべし。

なぜ大きなデータを秒単位で処理できるかというと、それがまさに BigQuery Analytics の本題なのだがざっくりは

  • SQL は高度に並列化できる言語 (基本、シーケンシャルに処理するしね)
  • RDBMS のようにインデックスを作るわけではなく、基本フルスキャンする
  • そのフルスキャンに伴う I/O を分散処理するために大量の HDD を用意して、それを大量のサーバーに接続してクラスタリング (もちろん、スケールアウトの発想で)
  • データをそのクラスタ内でカラムナー形式で保持しつつ分散させて保存しておき、SQL が来たらそれを並列処理化して I/O を散らす

みたいな感じである。より詳しくは・・・とそこが書籍の本題でありその理解は今後の読書会を通じて行われる予定、といって誤魔化す。

こういうアーキテクチャになってるので、BigQuery に対するクエリのレスポンス速度はデータサイズに比例しない。例えば 100GB のデータに対して 3sec かかったクエリが、対象が 1TB になっても 5sec で収まるとか、そういう特性を持っている。

Google BigQuery の製品ポジション / MPP の盛り上がり

この、SQL を並列分散処理してビッグデータを数秒で解析しましょう、という製品は何も BigQuery だけではない。

OSS の実装であれば Facebook が開発して OSS になった Presto、それから Cloudera Impala などがある。この辺は、Hadoop クラスタにアドオンする形で利用すると、Hadoop クラスタに溜め込んだデータを SQL 並列処理できるようになってる。クラウドサービスでいえば (自分は詳しくないし、結構特性には違うらしいが) Amazon Redshift なども同様のカテゴリのサービスのようだ。それから、以前にこのブログでも紹介した TreasureData はもともと Hive + Hadoop を基礎にしたサービスだったがその後 Presto をアドオンすることで同カテゴリのサービスにバージョンアップしている。

この辺の話は Hadoop Conference Japan 2014 での tagomoris さんの発表スライド Batch processing and Stream processing by SQL が詳しい。

資料の内容を軽くサマリする。

SQL ベースのビッグデータ解析基盤は大きく分類すると

  • Large Batch
  • Short Batch
  • Stream Processing

の3に分類される。それぞれ

  • Large Batch : 安定して巨大なデータをバッチ処理できるが、実行時オーバーヘッド大きい (そのためちょいちょいクエリを変えては投げる目的 ・・・ アドホッック クエリには向いてない)
  • Short Batch : Large Batch の安定性と規模性を多少犠牲にしつつ、実行時オーバーヘッドが数秒 (つまりアドホック クエリに向いている)
  • Stream Processing : ストリームに流れるデータをリアルタイム処理。バッチではない

というもの。対応する代表的な実装は

  • Large Batch ・・・ Hive + Hadoop
  • Short Batch ・・・ Presto / Impala etc.
  • Stream Processing ・・・ Twitter Storm / Norikra

などとなってる。この Short Batch のユースケースに含まれる実装は昨今 MPP (Massively Parallel Processing) 系クエリエンジンと呼ばれていて、ビッグデータ界隈では今もっともホットなトピック・・・であると、Hadoop Conference に出てみて自分はそう感じた。

そして、Google の BigQuery は元々 Google 内部で開発された Dremel というクエリエンジンが基になっている。その Dremel がまさにこの MPP 系クエリエンジンに相当する類で、BigQuery はそれにストレージを加えて公開サービスにしたものだと現時点では理解している。(BigQuery は背後にそびえるクラスタ群が超大規模なので、Short Batch に分類されるとはいえ Large Batch も包含するようなサービスではある。)

OSS 系の流れからいくと、Hadooop + Hive で SQL でビッグデータを解析するというソリューションが盛り上がったが、MapReduce はタスク起動時のオーバーヘッドが大きくアドホッククエリの分析には向いてない、そこをカバーするために Presto や Impala が出てきてみたいな流れだと思う。

Big Data Stack 2.0

それで、冒頭の Big Data Stack 2.0 である。BigQuery は Google の Big Data Stack 2.0 の上に構築されている、らしい。書籍によれば。

そもそも Big Data Stack 1.0 とは、GFS, MapReduce, BigTable などの「Google を支える技術」のことである。MapReduce などが論文で発表されたのが 2004 年とかだった。あれから 10 年経った結果、Google 内部は書籍を読む限りは Big Data Stack 2.0 にまで進化している 。(そして現在進行系では 3.0 に至っているようなこともチラホラ見える。)

その Big Data Stack 2.0 の主要コンポーネントは以下である。説明文は読書会で hakobera さんがサマリしてくれたテキストから引用する。

  • Colossus
    • GFS の後継 (の分散ファイルシステム?)。詳細は未発表。
  • Megastore
    • Paxos アルゴリズムにより、複数データセンターでの一貫性のある Read/Write を実現した NoSQL DB。Bigtable 上に構築されている。
  • Spanner
    • Megastore + データに地域制約(どのデータセンターに所属するか)を付与することができる。
  • FlumeJava
    • MapReduce のパイプライン処理を簡単に書けるようにしたフレームワーク
  • Dremel
    • 分散 SQL クエリエンジン。BigQuery の核となるアーキテクチャ。ストレージに依存しない。

これらの実装は概ね Big Data Stack 1.0 の上に構築されているらしい。そしてこれも hakobera さんテキストからの引用なのだが

  • Big Data Stack 1.0 は、Datacenter を1つのサーバとして扱う技術群
  • Big Data Stack 2.0 は、複数 Datacenter を1つのサーバとして扱う技術群

という風に (乱暴には) まとめられる。こうして世界に分散しているデータセンターを、プログラマからみた場合は 1つのサーバーとして扱えるような形で抽象化したのが Google の Big Data Stack 2.0 だそうだ。

ご存知のように Big Data Stack 1.0 をリファレンスにでてきた OSS が Hadoop や HDFS、HBase 等々だったように、この Big Data Stack 2.0 を参考にしたと思われる OSS 実装も当然出てきていて、それらが Apache Crunch や Presto、Impala ・・・というのが昨今の状況。Google が論文などでそのあらましを発表するころには、Google 内部は次の世代の実装に移行しているというのが過去のパターンなので、そこから Google 内部はもはや Big Data Stack 3.0 なのでは? と推測される ─ といった具合である。

自分はこの分野を見てまわるのはそれこそ Google を支える技術から初期の Hadoop ぐらい、Big Data Stack 1.0 の頃で止まっていたので、それからしばらく時間が経ってこんな状況になっていたとは、改めて Google はすごい企業だという感想を抱くにいたったのは当然のこと、とても面白く読めた。ずっとこの分野を追っていた人にとっては何を今更という話なのかもしれないが、面白さあまってブログにまとめるイマココである。

ま、人の会社の話なんだけどね。Google の威を借る naoya。

8/30 の YAPC::Asia では、BigQuery Analytics をもう少し読み進めた後のサマリと、実際に BigQuery をプロダクションで利用してみてのユースケースや感想などを含めて発表できたらと思っている。

急ぎで書いたので誤字脱字や乱暴な解説がいつも以上に多いと思うが、ご勘弁を。

余談

ちなみにこの辺をみて『Google を支える技術II』の出版が待たれる! と声を大にして言おうとおもったら『サーバー/インフラを支える技術』もなんとかしろ、という神の声が聞こえてきた。編集さん、アジェンダなかなか書かなくてごめんなさい・・・。

August 09, 2014

Deploy to Heroku / Webアプリケーションのポータビリティ再び

Heroku の新機能で Heroku Button が出た。

見るよりも、触る方が早い。以下のボタンを押すと md2inao をあなたの Heroku アカウントにデプロイして、動かすことができる。

Deploy

ボタンを押すと以下のような画面が出て、Deploy to Free を押すと直ちにデプロイが始まる。

f:id:naoya:20140809115416p:image:w480

GitHub からソースコードが Heroku にデプロイされて、Web アプリケーションが動く。

f:id:naoya:20140809115417p:image:w480

ご満悦。

このボタンを README.md に置いておけば、Webアプリケーションを自分で動かしたいなと思ったユーザーが、自分自身の環境で好きな時にそれをデプロイして使うことができる。

f:id:naoya:20140809123734p:image

すなわち、Heroku Button で、URI を介した Web アプリケーションの交換が可能になった。

Heroku Button

Heroku Button を有効にするための前提は割とシンプルで

  • GitHub にソースを置く
  • Heroku にデプロイできる形式で構成しておく ( Ruby なら Gemfile とか Rack とか Procfile とかそういう話 )
  • app.json を書く
  • デプロイボタンを設置

というもの。app.json は

{
  "name": "md2inao",
  "env": {
    "BUILDPACK_URL": "https://github.com/naoya/heroku-buildpack-perl.git#cpanm-with-psgi"
  }
}

こういう JSON ファイル。app.json Schema を見るといろいろパラメータを指定できるけれども、シンプルなアプリならほとんど記述は要らない。md2inao は Perl 製で、buildpack が必要なのでそれだけ環境変数で指定した。

Deploy to Heroku ボタンのリンク先は https://heroku.com/deploy だが、このエンドポイントを叩くとリファラ (もしくはクエリパラメタの template に指定された URL) にある app.json を読み取り、ソースコードをデプロイする。

Pull Request と Heroku Button

Heroku Button が面白いのは、ソースコードのレポジトリを GitHub を前提にしている点。

app.json に明示的にレポジトリURL を書かない場合、app.json の URL はリファラから動的に決定される。GitHub の場合は Pull Request やコミットハッシュ毎に URL が付く。なので README.md にデプロイボタンを置いて app.json のレポジトリURLを空にしておけば、それだけで第三者が (master だけでなく) 任意のブランチの任意のコミットを選んで Heroku にデプロイできるようになる。

以下は、サンプルアプリケーションのあるコミットをデプロイした例。ハッシュ値が付いてるのがわかる。

f:id:naoya:20140809123937p:image

よって Pull Request ベースで Web 開発をしてるときに、ちょっとこの Pull Request の動作確認をしたいなと思ったら、その Pull Request のブランチの Heroku Button をおしてデプロイして動作させるということが可能になっている。

app.json があったら、Pull Request のスレッドに自動的に Heroku Button が表示されるとかそういう改修を、GitHub (やどっかのサービス) がやってくれることを期待したい。

Immutable Infrastructure / Webアプリケーションのポータビリティ

半年ほど前に ポータブルなWebアプリケーション - naoyaのはてなダイアリー に、Immutable / Disposable Infrastructure の概念によって Web アプリケーションがポータブルになり、結果的に、Web アプリケーションが交換できるようになるのではないかという話を書いた。

Heroku Button を見て、そういえばそんなことを書いたな、ということを思い出した。

ご存知の通り、Heroku のバックエンドはコンテナベースの仮想化環境よって設計されていて、コードを push するたびに古いコンテナは廃棄されて新しいコンテナにアプリケーションがデプロイされる。Immutable Infrastructure そのものである。

常に廃棄されることを前提に Web アプリケーションを構成するには、Web アプリケーションに含まれる外部ライブラリなどの各種依存関係なが宣言的に明記されていなければならない。そのために Gemfile や Procfile などがある。この辺りのプラクティスは The Tweleve-Factor App などにまとまっている。

結果的に、Immutable であるという制約が Web アプリケーションの実行環境にポータビリティを与える・・・というのが先のエントリで書いたこと。この辺の話は Immutable Infrastructureが開発プロセスに与える影響 というカンファレンス発表でも話した。

Heroku Button は、その典型的なユースケースだと言える。

Docker や Docker Hub などの普及が進むと、次は Heroku という特定ベンダのインフラ環境に縛られない、同様のユースケースが実現されていくのは間違いない。

というわけで Heroku Button はとってもクール、である。

May 12, 2014

Sqwiggle が良いという話、またはリモートでアジャイル開発をどう進めるか

KAIZEN platform Inc. は、新しい働き方をいろいろ試してみようという会社でそのひとつにリモートワークがある。リモートワークの良さあるいは良くないところについては、以前に Rebuild.fm の ep.32 でも話した。

ちかごろは、オンラインミーティングのための道具、情報共有のための道具もクラウドサービスがたくさんあるので、その辺を使って工夫すれば一昔前に比べてだいぶリモートワークも現実的になってきている。実際、KAIZEN には大阪からリモートワークしている人とか、最近リモートワークを前提に都内から鎌倉に引っ越したメンバーなんかもいる。

リモートワークとアジャイル開発

HipChat、Google Hangout や Qiita Team なんかを使うことで、日常の会話、ミーティングや情報共有についてはもともと特に困ったこともあまりなかった。特に Qiita Team での情報共有はチームビルディングにおいて重要な一幕だった・・・という話も Rebuild でしたっけかな。

ただ、アジャイル開発という文脈でいったときに「どうするべ?」ということが幾つかあった。

その際たるものが「全員同席」。まあ全員同席はアジャイルで必ずやらなければいけないこと (・・・そもそも必ずやらなきゃいけないことなんてないとは思うんだけど)、ではないのだけど、リモートワークだとどうしてもその辺りのコミュニケーションが希薄になりがちで、チームビルディングという観点では課題だなと思っていた。

例えば、ちょっとした仕様の確認とか、あるいは雑談のために Google Hangout を使ってオンラインミーティングしようとすると HipChat で以下の様なやりとりが行われたりする。

naoya 「@ngs ちょっと確認したいことあるんだけど Hangout いい?」
ngs「なんでしょう」
naoya「あのモジュールのあそこの実装なんだけど」
ngs「あー、あそこは @funami がよく知ってます」
naoya「なるほど、じゃあ @funami も Hangout」
naoya「@funami さんーん」
naoya「・・・いないね」
ngs「いないですね」
funami 「あ、ごめん、チャットみてなかった」
naoya 「おうおう、じゃ Hangout はじめましょ」
ngs 「url どこですかー」
naoya 「ちょっと待ってね・・・はいこれ」
funami 「なんか You're not allowed っていわれる」
naoya 「あれれ」

これで 10分 かかる。経験がある人はわかると思うが、これ、実際はなかなかにイライラする。誰が悪いわけでもないのでそのイライラをぶつける先もない。

これがリモートワークでなければ、その場でいるかどうか確認してその場でちゃちゃっと話合って終われるんだけど、リモートだとなかなかそうもいかない。そしてこの 10 分がめんどくさいので、チャット上でやりとりして実際には10分話せば終わることを30分も1時間もかけてやりとりしたりする、なんてことになりがちである。(結果的にテキストで記録が残る、というところはよいのだけど)

Sqwiggle

そんな折り、たまたま 8 Helpful Online Tools To Keep Your Company On Track という記事を読んだ。これは Buffer を作ってる人たちがどうやってリモートワークしてるかという話。Buffer はなかなか面白い働き方をしているらしい。

この中で紹介されていた Sqwiggle というツールが、まさに先の問題解決をしてくれた。あるいは、今後してくれそう。

Sqwiggle を起動すると、カメラが有効になってこんな感じで Sqwiggle を立ち上げてるチームメンバーが一覧になる。

f:id:naoya:20140512114229p:image

Sqwiggle は常にストリームをしてるわけじゃなくて、定期的に画像のスナップショットをサーバーに送ってる。そのスナップショットがときどき更新されて、この一覧がでる。

この一覧にいるメンバーと口頭で何か話したいことがあると思ったらどうするか。相手の写真をタップするだけ。すると、その瞬間からセッションが始まる。セッションをはじめるよという呼びかけみたいなのは一切なくって、タップしたら音がなって、いきなり相手と会話が始められる状態になる。

常時カメラで相手の状況が映し出されてるので、相手がいる/いないの確認がいらないし、Hangout を始める時の招待とか url のやりとりとかそういうのも一切必要ない。会話の途中で、その会話にもう一人追加したいとおもったらその人もタップすれば3人での会話になる。

使用感としては Hangout でのミーティングは会議室に移動してよいしょで会議を始める感じで、Sqwiggle は隣にいる同僚にちょっとちょっと、と話しかけるような感じに近い。

最初 Sqwiggle を使い始めたときは、常時カメラで写されてるということでプライバシーのこととか、割り込みしやすいというのでリモートワークの利点がとかいろいろ心配していたけどその辺は実際やってみると普段はほとんど気にならない。まあ、自分は Sqwiggle を ON にしてるのを忘れて画面の前で着替えをしたことがあるが、致命傷にはならなかったw そのうち放送事故が起こるかも知れないが、まあそれはそうなったらそのときだ。

どちらかといえば、リモートワークにありがちな、自己管理できなくてついついさぼってしまうみたいな問題をも Sqwiggle は解決してくれるところが非常によい。周りに誰かいる、というような感覚でリモートワークに望めるので適度な緊張感が得られる。怠惰な自分には、それがとてもありがたい。

Daily Standup やスプリント計画、KPT

こんな感じで全員同席で進めていってるときのチーム感は Sqwiggle によって結構解消されつつある。

KAIZEN のワークフローだとリリースデプロイの直前 QA なんかで頻繁にエンジニア同士でも確認事項が発生するのだけど、普段チャットでやってるところ、次回はその辺も Sqwiggle を駆使してコミュニケーションを厚めにやってみようかなんて話をしている。

ちなみにアジャイル開発、というかスクラムでいくと他のプラクティスをどう実践してるかというと、以下の感じである。

  • Daily Standup は、毎朝時間を決めて固定の Hangout URL に集まるようにしている。Sqwiggle は残念ながら大人数でのリモートチャットをサポートしてないのと、議事録用のスクリーンシェアができないため。時間になると Hangout にみんな集まってきてちゃちゃっとその日のやることを共有して、議事メモがすぐに Qiita Team に上がる。
  • スプリント計画は、実は厳密にはあまりやってない。やってるのはタイムボックスを決めて、2週間毎に前後のプロジェクト進行をスプリント単位で確認するくらい。自分の経験上、受託開発とかもうちょっとカチっとした開発では QCD における Delivery ・・・ つまりはスケジュールの優先度が非常に高いので見積もり精度を上げるためにもスプリント計画を厚めにやるんだけど、365日開発し続ける SaaS 系サービスだとこの辺はゆるくやってるくらいが丁度いいと思ってる。がっつりやりすぎて疲れてしまうことより、ゆるくても長く続けて常にタイムボックスを意識して進められるくらいが良いかなと思う。
  • 一方、KPT は日時を決めてしっかりやっている。スクラムマスターがその日までにオンライン上で KPT を集めておいて、その時間帯に Hangout で集まってミーティングをする。アジャイル開発においては、定期的に開発プロジェクトを見直し自分たちのやり方が間違っていないか、おかしなところがあったらそこをどう直していくかということが何よりも大切で、KPT はそのための良い機会になっている。

人の問題と、技術の問題

顧問として携わりはじめた昨年夏ぐらいから時間が経って、改めてみてみるといろんなプロセスが改善されて (KAIZEN だけに。) 安定した開発ができるようになってきたと思う。

当初は、まずはいろいろ教科書通りにやってみようということでスプリント計画そのほかをみっちりやったりもしてたが、やっぱりこれは違うねと感じたところは KPT で Problem にあげて、やらないことはやらない、緩く崩すところは崩すということをしながら今のスタイルに落ち着いている。

ところで昨晩から「ピープルウェア」という本を読んでいる。ソフトウェア開発の名著なんだけど、今ままで読んだことがなくて、たまたま知り合いのブログで感想があがってたのをきっかけに読み始めた。これの第一章から早速なかなか面白いことが書いてある。

実際のところ、ソフトウェア開発上の問題の多くは、技術的というよりは社会学的なものである

さもありなん。

技術の問題というのは、案外正解を導きやすい。コンピュータは、こうしたらこうなるというのにちゃんと答えを出してくれるし、どちらのやり方が良いかというのに結論を出しやすい。

一方、人間の問題は、そのやり方が本当に正しいのかどうかが見極めにくい。ものによっては半年とか一年後くらいになってようやく結果がわかることなんていうのも多い。時間が経過しすぎてどのアクションがその結果に繋がったのかという因果関係がはっきりしないことも多い。

だから、ソフトウェア開発の人間はついつい (解決の道筋が見えやすい) 技術的な問題にばかりフォーカスしがち、というようなことがピープルウェアには書いてあって、そうだよねえと思いながら読んでいる。

Daily Standup をリモートでどうやるかとか、リモートでも気軽に雑談できるような環境を整えることにリソースを割き続けるとか、そういうことは社会学的な問題だと思っている。一方、先日書いたような GitHub を使ったデプロイフローなんかは社会学的側面もありつつ基本は技術的な問題である。

人の問題が解決されてチームが良い状態になると、今度は技術の問題がボトルネックになる。せっかく迅速に開発してるのにリリース作業や QA に時間がかかりすぎる、とか。実際 KAIZEN では一時期リリースの品質に問題があったのでコミュニケーションを取って QA をしっかりやるようになったのだが、そうしたところ今度は人手での作業が多すぎてつらい感じになったので、E2E テストを書いて全部自動化することによってそのボトルネックを解消した、なんて典型例があった。

逆に技術的な問題ばかりを解決しても、コミュニケーションがボトルネックになって、だれそれの了解が得られないからリリースできないとかそういうことが起こる。

人と技術の問題を両面からバランスよく解きほぐしていくのが、昨今のソフトウェア開発におけるチームビルディングのコツなんではないか、と思っている。

追記

ちなみにリモートワークと書くと時折誤解を招くので、捕捉しておく。

リモートとはいっても、100% リモートワークしましょうということではなくて写真にも映ってる通りオフィスはある。オフィスに行くか行かないかは自分で決めるようになっている。対面でしたほうがよいミーティングがある日はオフィスにいくしそうでないなら自宅、あるいはカフェかどこかでやる。いい大人なんで、その辺は自分たちで判断しましょうね、お互い信頼してれば大丈夫だよね、ってな感じの仕組みになっている。

もちろん対面でやった方が早いと思うことはたくさんあるけど、本当にそれは対面じゃないとできないのかというところをまずは疑ってみないことには、新しい働き方を追求するということはできない。結果的にそれで会議を減らす、非同期に作業することができれば全体の効率が上がるわけで、そこで思考停止しない・・・ということが大切だと思う。

May 02, 2014

GitHub 時代のデプロイ戦略

少し前までアプリケーションのデプロイと言えば capistrano などをコマンドラインから叩いてデプロイ、みたいなことをやっていたが、最近は少し様子が違うのでそのやり方、KAIZEN platform Inc. での事例を紹介する。

GitHub のイベントを契機に CI as a Service にデプロイを担当させる

GitHub で Pull Request を送って開発するのが前提になっているのは以前にも紹介した。

最近は Travis CI や CircleCI などに代表される CI (Continuous Integration) as a Service があって、CI も自分たちで環境を構築しなくてもクラウドに任せることができる。KAIZEN では CircleCI を積極的に使っている。

f:id:naoya:20140502194857p:image

これらの CI as a Service は基本的に GitHub と連携することが前提になってて、Github に差分を push するとそれを契機にインテグレーションテストを実行してくれたりする。

で、CI という文脈でいくとこの自動テストの実行が主なユースケースとして想像されやすいのだけど、CI as a Service にはそのテストの実行が終わったあとのデリバリーの機能もある。

Travis CI: Deployment なんかを見るとよくわるのだけど、master に push したらそれをきっかけに Heroku にデプロイを行うとか、そういうことができる。

CircleCI のデプロイオプション

この CI as a Serivice のデプロイオプションは結構色々細かく設定できて、例えば「deployment/production という名前のブランチに変更が push されたらこれを実行する」なんて設定ができる。

設定はレポジトリに置いた circle.yml ファイルに記述する。例えば以下のような感じ。

deployment:
  production:
    branch: deployment/production
    commands:
      - ./script/assets_precompile.sh:
      - bundle exec cap production deploy:migrations:
          
  edge:
    branch: deployment/edge
    commands:
      - ./script/assets_precompile.sh:
      - bundle exec cap edge deploy:migrations:

これでリモートの deployment/production ブランチにコードを push するとそれを契機に production へデプロイが行われるし、deployment/edge なら edge へ、てな感じになる。

実際のデプロイは、(まだ Mutable Infrastructure なので) capistrano を実行している。

CircleCI にデプロイを実施させると、テストを実行してその結果が緑だったらデプロイさせるというようなこととか、デプロイのログが共有しやすくなるとか、キャンセルが簡単とかいろんなメリットを享受できる。

Pull Request でデプロイする

「ほうほう、なるほど。じゃあデプロイしたいときは master から deployment/production へ merge して、git push するのか」というところだけど、ここでもう一個工夫する。

デプロイしたくなったら、master から deployment/production へ Pull Request を作るんである。

f:id:naoya:20140502192450p:image

この Pull Request を merge すると、CircleCI がそれを検知して結果的に CircleCI 上でデプロイが走る。キャンセルしたいときは merge しないで close する。

なんで直接 push せずにわざわざ Pull Request にするかは、上の画面を見ればだいたいおわかりのとおり

  • デプロイの見える化
  • 何がデプロイされるかのコミットログの可視化

など本当にいろんな利点がある。

production デプロイの際には、この Pull Request のスレッドを使って QA の最終確認をしたりする。コミュニケーションが Pull Request 上に集約されることになるし、デプロイ直前の hotfix が行われたコミットなんかも全て見えるようになる。

今思うと、手元でエイヤで cap deploy の時は、このあたりのワークフローが全部暗黙知化していた。アプリケーションへの変更を Pull Request ベースにして色んなものが見えるようになるのと同じで、デプロイもまた Pull Request で改善できるところがたくさんある。

hubot へデプロイをお願いする

仕上げは、この Pull Request を作る方法である。つい先日までは Pull Request を GitHub 上でマニュアルで作っていたが、ここまできたら GitHub API を使って Pull Request 作成は自動化してしまえばい。

そして、日頃 HipChat を使ってるのだから、チャット上で hubot にデプロイをお願いしたら Pull Request を作ってくれる、とすれば「デプロイ始めまーす」みたいな宣言いらずで一石二鳥である。

というわけで作った。

f:id:naoya:20140502193558p:image

hubot にお願いするとデプロイ用 Pull Requet が作られて、CircleCI がデプロイしてくれる、そんなワークフローができあがった。万歳。

GitHub や * as a Service を前提にしたワークフローの時代

GitHub や CircleCI のようなサービスがあるという前提でワークフローを構築していくとこんな感じで工夫次第でいろいろ面白くできる。Web サービスと Web サービスを繋げて、さらにそこに自分たちの開発フローを組み込んで一つのフローとして完成すると、なかなかに爽快である。

この辺の開発は、もうこういったWebサービスのような、一見するとプログラム部品としては見えないようなものものも、開発のための一つのプログラマブルな部品であると認識できるかどうか、ライブラリやフレームワークと同じ類のものであるとフラットに見れるかどうかそういう感覚が要求されるように思う。

それは Web 2.0 で Web API だなんだと言われてきたころからあったことなのだけれども、その感覚が、フロントエンドだけではなくて、こうして開発プロセスのワークフローの組み上げににも適用できるようになったというのが、自分としては昨今この領域が面白く感じる理由のひとつでもある。

逆に言えば、こういう領域に開発リソースをうまく継続的に投資できるかどうかということが今後の開発組織のあり方として重要な要素だと思っていて、KAIZEN では会社が立ち上がった当初から CTO と話して "Developer Productivity" という、この手の仕事をミッションにしたチームを構成するようにしてきて、その形が固まってきたところ。それがこういう形で面白い成果に繋がっている、と思っている。