creasty/rid
rid - Run commands in container as if were native. Stress-free dockerized development environment finally arrived
https://github.com/creasty/rid
こんにちは、Wantedly でエンジニアをしている竹野(@Altech_2015)です。先日行われた Rails Developer Meetup 2018 にて、Wantedly におけるマイクロサービスの事例について紹介させていただきました。
Wantedly では、2016年に開発を始めた Wantedly People においてマイクロサービス・アーキテクチャを採用しています。この発表では、この Wantedly People がどのような構成で出来ているかを網羅的に紹介すると共に、現在進めているサービス横断的なアーキテクチャ変更についても触れました。
発表内容は網羅性はあった反面あまり具体的に踏み込んだ紹介ができず、いくつか質問をいただくことになりました。この記事では、スライドに加えていくつかの補足をしようと思います。
セッションでも少し触れた開発環境のセットアップについてより具体的な質問をいただきました。
Q. セッションテーマとちょっとずれた質問ですが、「Dockerの薄いラッパー」って具体的にどんなものなんでしょう? シェルやMakefileでサブコマンド、みたいなのがよくあるユースケースかと思っているのですが何かツールとか作られてますか?
特に数多くの言語・ミドルウェアを利用していると、パッとある service をローカルで立ち上げて変更すると言ったことが難しくなります。そのために Docker を開発環境でも利用しているのですが、Docker による開発はハマりどころが多く、開発効率を上げたいということに対して必ずしも上手く解決ができません。
この対処として弊社では rid = run-in-docker という小さなコマンドライン・ツールを Go で作って利用しています。
具体的に、Wantedly People の全ての service は rid bootstrap
でセットアップが行われ、rid server start でサーバーが立ち上がります。bootstrap は
Docker イメージの取得からコンテナ立ち上げ、コンテナ内での bootstrap 処理(bundle install
など)を行います。bootstrap script は Docker コンテナ内で行われるため、環境依存性がありません。
また、rid <command>
のように prefix を付けることで立ち上げている Docker コンテナ内でコマンドが実行されます。Ruby の bundler の bundle exec
のような雰囲気で使えるので、殆ど Docker を意識することはありません。実際、最近ジョインしたメンバーは Docker の知識がありませんでしたが rid を使って問題なく開発できていました。
rid bootstrap # セットアップ
rid server # サーバー立ち上げ
rid rails c # コンテナ内でのコマンド実行例
rid の詳しい解説記事は以前刊行された Wantedly Tech Book 2 にしかないのですが、近々作者の @creasty がウェブでも書いてくれると思います :)
service の数が多いことによる厳しさについての質問もありました。
Q. Wantedly Peopleの方はかなりサービス数多いと思うんですが 今振り返ってみてサービスの分け方は成功したと思いますか? また、運用してみてサービス数が多いことによるつらみみたいなのはありますか?
serviceの分け方は全体としては成功したと思っています。セッションの中でも少し触れていますが、serviceの分割を目的にはせず、これまでの Wantedly Visit での開発経験なども踏まえた上でドメインとして別れていると良いだろうという部分を分割しています。例えば、サービス内での通知機構はそのような事例です。ただ、次節で触れるように Golang の service が持つ責務は開発する中で少し調整されました。
また、時間の都合で発表では触れられませんでしたが、仕組みとしては Kubernetes も運用しているインフラチームが自動化によって継続的に対処しています。例えば、次のスライドの後半では「トイル」という概念と共に、service 数に対して O(n) となるような作業を自動化する話が出てきますが、Wantedly People のアーキテクチャはこのような活動に支えられています。
扱う範囲を詰め込んだために失敗事例などリアルな話ができなかったのは少し心残りなので、ここで一つ紹介させてください。
実は、発表したスライドの中に出てくる CardScanner という service は、当初 DB を持った汎用的な API サーバーとしての責務も含めていました(その為リポジトリ名は people-go となっています、色々なものを Go で書いていこうという勢いが感じられますね)。しかし、開発を続ける中で、テーブルをそのまま API にするようなものは Rails サーバーの方に実装され、people-go は殆どその用途では使われませんでした。
この辺りの背景を検討したところ、Golang で ActiveRecord を持つ Rails のように次々とテーブルを作っていって、対応するモデルの CRUD API を実装していくことは少し難しいことが分かったので、それ以降 Golang は責務が明確で小さい service に利用するようにしました。
このように、Wantedly では Rails に限らずそれぞれの問題領域に適した技術を採用できる環境を整えて、サービスを作っています。このためときには自分でレールを敷くことも必要ですが、それも含めて一緒に考えていけるエンジニアを募集しています。