はてなのサービスの開発環境
2014/02/07 Hatena Engineer Seminar #4	

id:astj
アジェンダ
• 自己紹介	

• 開発環境の整備	

• はてなブックマーク - vagrant	

• はてなブログ - plackup	

• Conclusion
id:astj	

github: astj /Twitter: @ast_j
はてなサマーインターン2013	

はてな新卒エンジニア(2014/04入社)	

はてなブログ(とか)担当	

ブックマーク => ガールズ => ブログ => …
and more…
BrandSafeはてな
• Perl / Elasticsearch / JavaScript	

• ブックマーク 開発環境のメンテナンス(vagrant etc.)	

• B!KUMA メインエンジニア (~2015/01)	

• http://bkuma.hatena.ne.jp/
LET'STALK !
• はてなのエンジニア生活	

• 1年目いろいろ	

懇親会でぜひ
はてなのサービスの開発環境
Hatena Engineer Seminar #2
https://speakerdeck.com/aereal/vagrant-to-chef-detukuruhatenabutukumakufalsekai-fa-huan-jing
開発環境
• サーバを起動し動作確認・開発	

• デザイナーの手元にも整備	

• テストコードの実行環境	

• (調査スクリプトなどの動作環境)	

• (less, typescript などの自動コンパイル)
• 開発者のマシン上で直接実行	

• plenv, carton...	

• 環境を仮想マシン内に構築	

• Vagrant	

• 複雑/レガシーな環境への対応性	

• パフォーマンスオーバーヘッド
• Vagrantによる複雑/レガシーな環境の仮想化	

• はてなブックマーク	

• ホストマシン上で直接動作する環境	

• はてなブログ
はてなブックマーク
Hatena Engineer Seminar #2
https://speakerdeck.com/aereal/vagrant-to-chef-detukuruhatenabutukumakufalsekai-fa-huan-jing
はてなブックマーク
• サービス開始(2005/02)	

• リニューアル(2008/11)
関連サービス
BrandSafeはてな
関連サービス
BrandSafe一部のコードがブックマーク内に共存
はてなブックマーク
• perl 5.8.8	

• Ridge(自社製WAF)	

• MoCo(自社製ORM)	

• apache mod_perl2
はてなブックマーク
• TypeScript (部分的)	

• less (部分的)
gulp
...=>grunt=>gulp
はてなブックマーク
• apache + nginx	

• MySQL	

• memcached	

• Elasticsearch (2014/06~)	

• (内製サブシステム)
本番サーバ構成
• CentOS	

• chef	

• rpm	

• 社内でrpmをビルド・ホスティング	

• CPAN モジュール	

• etc...
PRODUCTION
mod_perl
MySQL memcached
(misc subsystems)Elasticsearch
worker
本番サーバ構成
nginx proxyapache proxy
開発環境
• "コマンド一発で環境が立ち上がる"	

• gulp, アプリケーション, memcached, ...	

• 複数のプロセスをProcletで管理	

• "foreman for perl"
my $proclet = Proclet->new(!
color => $opts->{color},!
);!
!
$proclet->service(!
tag => 'app',!
code => sub {!
Ridge::Daemon->run('Hatena::Bookmark', +{!
root => $RootDir,!
port => $opts->{port},!
fast => $opts->{fast},!
verbose => $opts->{verbose},!
reboot_on_reload => $opts->{reboot},!
});!
},!
);!
!
$proclet->service(!
tag => 'gulp',!
code => sub {!
exec qw(script/tools/node node_modules/.bin/gulp devel);!
},!
);!
!
$proclet->run;
BUT...
• CPAN モジュールの複雑な依存関係	

• cpanm --installdepsだけで わない	

• 古いCPANモジュールを使い続ける必要性	

• 多様な手元環境	

• OS X,Windows, Linux(Debian)...
cpanm trouble!!
• cpanm --installdepsではうまく依存管理できない	

• テストが落ちることが分かっているモジュール	

• 厳密にバージョンロックできない	

• Carton導入?	

• もうCPANにない古いモジュール	

• 本番では使わない
仮想マシン化・プログラマブルなセットアップ
• VM(など)による仮想環境の構築	

• VirtualBox (,VMWare, Docker...)	

• Chef でプログラマブルなセットアップ	

• "秘伝のVMイメージ"の回避へ
Vagrant box
Ubuntu cloud images	

http://cloud-images.ubuntu.com	

!
• Vagrant ready・信頼性	

• 必然的にaptベースの構成管理
Chef cookbook
ミドルウェアの導入	

perlのビルド	

cpanモジュールの導入
cpanm trouble!!
• cpanm --installdepsではうまく依存管理できない	

• テストが落ちることが分かっているモジュール	

• 厳密にバージョンロックできない	

• Carton導入?	

• もうCPANにない古いモジュール	

• 本番では使わない
再掲
cpanm Workaround
backpanにしかないモジュールを先に入れる	

cpanm --installdepsで大まかに える	

厳密にバージョンロックするモジュールは後から
cpanm Workaround
backpanにしかないモジュールを先に入れる	

cpanm --installdepsで大まかに える	

厳密にバージョンロックするモジュールは後から
セットアップ&起動
$ git clone git://HOGE/dev-Hatena-Bookmark.box	

$ ./bin/server
$ vagrant up	

$ vagrant ssh script/bookmark.up
セットアップ&起動
$ git clone git://HOGE/dev-Hatena-Bookmark.box	

$ ./bin/server
$ vagrant up	

$ vagrant ssh script/bookmark.up
less/ts コンパイル (gulp)	

nginx proxy (一部/後述)	

アプリケーションプロセス
セットアップ&起動
$ git clone git://HOGE/dev-Hatena-Bookmark.box	

$ ./bin/server
$ vagrant up	

$ vagrant ssh script/bookmark.up
less/ts コンパイル (gulp)	

nginx proxy (一部/後述)	

アプリケーションプロセス
Proclet
app
MySQLmemcached
(misc subsystems)
Elasticsearch
(worker)
ローカル環境
nginx proxy
Ubuntu 開発用サーバ
app
MySQL memcached
(misc subsystems)Elasticsearch
(worker)
nginx proxy
PRODUCTION
MySQL memcached
(misc subsystems)Elasticsearch
worker
nginx proxy
開発用サーバ
LOCAL
app
apache proxy
app
MySQL Elasticsearch
(worker)
テストの実行
Ubuntu
Vagrant導入その後
"放っておくと壊れる"
• 古いUbuntu向けのaptリポジトリ提供終了	

• "apt-getできずミドルウェアが入らない"	

• Ubuntu base boxのバージョンを上げる	

• CPANモジュールの非互換変更	

• バージョン固定リストに追加
本番と別個に構成管理するコスト
PRODUCTION LOCAL
Distribution CentOS Ubuntu
Provisioning
chef	

(by op.)
chef	

(by dev.)
Package sys. yum apt
CPAN module
rpm	

(by op.)
(direct)
PRODUCTION LOCAL
Distribution CentOS CentOS ?
Provisioning
chef	

(by op.)
chef	

(by dev.)
Package sys. yum yum
CPAN module
rpm	

(by op.)
rpm
(by op.)
• chef official な CentOS base box の利用	

• https://github.com/chef/bento	

• 社内 rpm サーバの利用	

• cookbook の部分共用	

• まずはコピペから
他アプリケーションで試験導入
その後停滞中...
nginx proxy
http://b.hatena.ne.jp/XXX http://bkuma.hatena.ne.jp/YYY
PRODUCTION
apache proxy
application
/-/HOGE/YYY/XXXX
http://local.hatena.ne.jp:3000/XXX http://local.hatena.ne.jp:3000/-/HOGE/YYY
LOCAL (before)
/-/HOGE/YYY/XXXX
application
http://local.hatena.ne.jp:3000/-/HOGE/YYY
ローカルだとどのURL?
URLこれでいいのかわからん
共用エンドポイントうまく動かない
LOCAL (before)
nginx proxy
http://local.hatena.ne.jp:3000/XXX http://local.hatena.ne.jp:3200/YYY
/-/HOGE/YYY/XXXX
LOCAL (after)
application
LOCAL (after)
:smile:
• 手元マシンを選ばない環境構築の実現	

• 本番の環境に近づける	

• 継続的なメンテナンスの必要性	

• 本番環境との一部構成共通化に期待	

• あるいはアーキテクチャ自体の刷新...
• 招待ベータリリース(2011/11)	

• オープンベータ(2011/12)	

• 正式リリース(2013/01)
http://hatenablog.com/ http://blog.hatena.ne.jp/ http://YOU.hatenablog.com/
マルチドメイン
• perl 5.14.2	

• ぼくのかんがえたさいこうのフレームワーク	

• plack (Starlet + Start::Server)	

• Carton	

• less (grunt)
• nginx (+ aws ELB)	

• MySQL 5.5	

• Solr	

• memcached	

• redis
PRODUCTION
nginx proxy
plack app
MySQL
memcached redis
solr
worker
DNS
nginx proxy
plack app
MySQL
memcached redis
solr
worker
PRODUCTION
plack app
MySQL
memcached redis
(no solr)
worker
LOCAL
DNS nginx proxy DNS
NO VM
$ brew install mysql55 redis nginx phantomjs casperjs…	

$ script/setup
セットアップ
$ carton install	

$ mysql < db/schema.sql	

...
$ carton exec -- script/epicup
Proclet
plackup, nginx, dns,	

worker, redis, grunt...
http://hatenablog.com/ http://blog.hatena.ne.jp/ http://YOU.hatenablog.com/
http://e.local.hatena.com/ http://local.hatena.ne.jp/ http://YOU.e.local.hatena.com/
• "/etc/hosts にこれ書いて"でよいのか?	

• 動的に複数のドメインの展開	

• Net::DNS::Nameserver	

• /etc/resolver/
plack app
MySQL memcached redis
(no solr)
worker
nginx proxy
(no DNS)
Module Module Module
Module Module Module JavaScript
必要なコンポーネントを用いてテスト
$ carton exec -- prove -lvr t/
• 今のところうまくいっている	

• 導入するミドルウェアのバージョン?
Conclusion
• VMに依存しない環境志向	

• 複雑度によってはVMによる手間の削減	

• 複雑度の完全な封じ込みは未達成
Thanx!

はてなのサービスの開発環境