Webサービスをデータセンター移行するときに必要となる技術要素

クラウドへの移行を含むデータセンター(以下DC)移行事例を基に、WebサービスをDC移行するための基本的な技術要素を紹介します。 最近、社内で大規模なDC移行を実施しつつあり、DC移行とはなにかをメンバーへ共有するための文章でもあります。 ちなみに、この記事はHosting Casual Talks #4の発表内容を書き下ろしたものです。

続きを読む

AnsibleとDockerによる1000台同時SSHオペレーション環境

1000台同時SSHオペレーション環境を構築するにあたって、手元のローカル環境の性能限界の問題を解決するために、オペレーションサーバをSSHクライアントとすることによりSSH実行を高速化した。実行環境としてDocker、レジストリとしてAmazon ECR(EC2 Container Registry)を用いて、ローカル環境とオペレーションサーバ環境を統一することにより、オペレーションサーバの構成管理の手間を削減した。

はじめに

3年前に Ansible + Mackerel APIによる1000台規模のサーバオペレーション - ゆううきブログ という記事を書いた。 この記事では、ホストインベントリとしてのMackerelと、並列SSH実行にすぐれたAnsibleを組み合わせ、オペレーション対象のホスト情報をプログラマブルに管理する手法を紹介した。また、工夫点として、並列SSH実行する上でのパフォーマンスチューニングやレガシーOSでの対応について紹介した。

しかし、並列度をあげるとforkするプロセスの個数が増えてローカル環境のリソースをくいつぶすという問題があった。加えて、並列度が小さいと実行終了まで待たされるという問題があった。 さらに、ローカル環境のOSやハードウェア性能が人によって異なるため、ローカル環境を統一して整備する手間があった。特に毎日利用する用途ではないため、利用頻度に対する整備コストが大きかった。

そこで、ローカルから対象ホスト群に接続するのではなく、オペレーションサーバをクライアントとして対象ホスト群に接続する仕組みに変更した。 これにより、スケールアップが容易になり、普段利用しているサーバ構成管理ツールを用いて、複数ユーザが同じ環境を利用できるようになった。 オペレーションサーバを対象ホスト群と同じデータセンター内に配置すれば、SSHクライアントと対象ホスト群とのレイテンシが小さくなるため、実行速度が向上する可能性があるというメリットもある。

しかし、playbookの開発にはオペレーションサーバではなくローカル環境を用いるため、ローカル環境とオペレーションサーバ環境の差異を小さくできるほうがよい。 そこで、Dockerを用いて、ローカルとオペレーションサーバ共通の環境を構築する。

アーキテクチャと実装

アーキテクチャ

アーキテクチャを図1に示す。 図1: アーキテクチャ

単一サーバから命令を各サーバへ送信するPull型のイベント送信モデルになる。 ローカル -> オペレーションサーバ -> 対象ホストの流れに沿ってSSHログインする。 オペレーションサーバ上では、並列SSHツール(Ansible)が起動し、記述したplaybookにしたがい、オペレーションを実行する。 対象ホスト一覧は、ホストインベントリ(Mackerel)のAPIから取得し、フィルタ(Ansibleのfilter)により、除外パターンを記述できる。 Ansibleそのものとplaybook、スクリプトなどが入ったDockerイメージをコンテナリポジトリ(ECR)にPUSHし、オペレーションサーバ上でPULLしておく。

ヘルパースクリプト

運用観点では、オペレーションサーバのホスト名、Dockerイメージ名、コンテナ名などを覚えてオペレーションはしたくない。 そこで、ヘルパースクリプト yuuki/ansible-operation-helper を参考のため公開している。これは社内事情を吸収するための層になるため、汎用的ではなく、そのまま動くわけではない。

  • Makefile: でDockerイメージのビルド、ECRへのプッシュ、オペレーションサーバへのデプロイ、オペレーションサーバが動作するかどうかチェックするテストのタスクを定義している。
  • bin/on_local_container: ローカルのDockerコンテナ上で引数指定したコマンドを実行する。
  • bin/on_remote: オペレーションサーバにSSHしつつ、引数指定したコマンド実行する。
  • bin/on_remote_container: オペレーションサーバ上のDockerコンテナにて、引数指定したコマンドを実行する。
  • libexec/mackerel.rb: Mackerel用のAnsible Dynamic Inventory。

工夫

オペレーションサーバ越しのroot権限実行

一斉にOSのパッケージを更新したいなど、コマンドをroot権限で実行したいことはケースはたくさんある。 Ansibleでは、Becomeにより、対象ホストにてコマンドをsudo/suを用いて、インタラクティブパスワード入力でroot権限実行できる。 しかし、たいていはsudoerの秘密鍵がローカルにあるため、オペレーションサーバ経由で対象ホストにsudoerとしてログインするにはひと工夫必要になる。 *1

オペレーションサーバ上には当然sudoerの秘密鍵を配置するわけにはいかないため、今回はagent forwardingを用いた。 agent forwardingにより、オペレーションサーバ上のssh-agentプロセスがUNIXドメインソケットを提供し、オペレーションサーバ上のSSHクライアントがそのソケットから認証情報を読み出し、対象ホストへのSSH接続を認証する。

Agent forwarding should be enabled with caution. Users with the ability to bypass file permissions on the remote host (for the agent's Unix-domain socket) can access the local agent through the forwarded connection. An attacker cannot obtain key material from the agent, however they can perform operations on the keys that enable them to authenticate using the identities loaded into the agent.

https://linux.die.net/man/1/ssh

agent forwardingは、セキュリティポリシー上、問題ないか確認した上で利用したほうがよいと考えている。 上記のssh(1)のmanにも書かれているように、攻撃者がagentにロードされた認証情報を使って、オペレーションすることができてしまう。*2 例えば、インターネットに公開された踏み台サーバ上でagent forwardingを用いることは好ましくない。

ヘルパーツールでは、agent forwardingをむやみに利用しないように、on_remoteラッパー実行時のみ、 forwardingを有効するために、-Aオプションを用いている。参考

rawモジュールとscriptモジュールのみの利用

本格的なサーバ構成管理をするわけではないため、シェルスクリプトを実行できれば十分だ。 Ansibleにはrawモジュールscriptモジュールがあり、シェルスクリプトを実行できる。 rawモジュールとscriptモジュールのメリットは、対象ホスト上のPython環境に左右されずにオペレーションできることだ。 例えば、Ansible 2.4からPython 2.4/2.5のサポートが切られた*3ため、CentOS 5ではepelからpython 2.6をインストールして使うなどの手間が増える。Ansible 2.4 upgrade and python 2.6 on CentOS 5

Ansibleの実行ログのGit保存

どのサーバに対してオペレーションしたかを記録するため、ログをとっておくことは重要だ。 CTO motemenさんの furoshiki2を用いて、Ansibleのコマンド実行ログをGit保存している。 作業ログと履歴をシンプルに共有できる furoshiki ってツールを書いた - 詩と創作・思索のひろば 前述の on_remote_container 内でansible-playbookの実行に対して、furo2コマンドでラップするだけで使える。

まとめと今後の課題

AnsibleとDockerを用いて、オペレーションサーバ経由で、大量のサーバに同時SSHオペレーションする環境の構築例を紹介した。 アーキテクチャと、アーキテクチャを実現するOSS、ヘルパーツールに加えて、3つの工夫として、agent forwardingによる権限エスカレーション、raw/scriptモジュールの利用、furoshiki2によるログのGit保存がある。

並列SSHすることが目的であれば、Ansibleはややオーバーテクノロジーといえるかもしれない。 具体的には、YAMLにより宣言的に記述されたplaybookや、各種Ansibleモジュールは今回の用途では不要であり、これらの存在は余計な学習コストを生む。 そこで、シンプルな並列SSHコマンド実行ツールとして、最近発見したorgalorgに着目している。 サーバとの接続に対してプロセスをforkするAnsibleと異なり、orgalorgはgoroutineを用いるため、より高速な動作を期待できる。 しかし、現時点では、パスワードありsudo実行、ssh agent forwardingに対応していない*4ことと、AnsibleのPatterns機能が、ホスト管理上非常に便利なため、今のところはAnsibleを利用している。

*1:LinuxユーザとSSH鍵の管理ポリシーにより、とりえる手段がかわってくるため注意

*2:鍵の中身そのものを取得はできないとのこと

*3:https://github.com/ansible/ansible/issues/33101#issuecomment-345802554

*4:これぐらいならコントリビュートできそう

2017年のエンジニアリング振り返り

はてなに入社して4年経った。

2017年のエンジニアリング活動を一言でまとめてみよう。

時系列データベースの開発にはじまり、なぜかIPSJ-ONEで登壇し、その後IPSJ-ONEでの構想をベースにはてなシステム構想を考え始め、ウェブサイエンス研究会でストーリーとしてまとめ上げつつ新たな可能性に気づき、それを実践していく場としてウェブシステムアーキテクチャ(WSA)研究会を立ち上げた。

一方で、仕事では、昨年の振り返りに書いているように、エンジニアとしての専門性を発揮する機会が薄れてきたという問題意識が、いよいよ深刻な課題へと変貌したように感じている。それも残念ながら自分一人だけの問題ではなくなってきた。 この課題をエンジニアリングそのものではなく、人間のスケールアウトでは解決できない、組織アーキテクチャの課題であると捉えている。 組織アーキテクチャの課題を解くための鍵は、今のところ「未来を定義する」「未来に向かって集中して取り組める環境をつくる」ことだろうと仮定している。 前者の未来については前述のシステム構想があり、後者の方法論として今年実践する機会のあったプロジェクトマネジメントがある。

したがって、来年は、今年構想したビジョンを技術と組織の両輪を回し、実現し始める、ということが目標になる。 そしてその裏には、エンジニア個人としては技術を作る技術をやっていきたいと思いつつ、生活時間の大半である業務の課題はマネジメントであるというギャップをどう埋めて一つのストーリーとしていくかが重要になるだろう。

ここまで、いきなりまとめに入ったのだけれど、2017年に力を注いだ各トピックについて細かく振り返ってみる。

  • 時系列データベースの設計・開発・運用
  • 学術研究のアプローチとの出会いとビジョンの構想
  • プロジェクトマネジメント
  • アウトプット

時系列データベースの設計・開発・運用

開発した時系列データベース(TSDB)は、運用にのることに成功し、今のところクリティカルな問題を起こすことなく動いている。実装・運用面では、同僚のid:itchynyさん、id:astj さん、id:kizkoh さんの力によるところが大きい。

このTSDBのオレオレ実装を、半年毎日コード書いて頑張っていたのだけど、リリース前に疲弊しまくって睡眠もうまくとれなくなってしまったので、途中までになってしまった。https://github.com/yuuki/diamondb/ 個人でやるプロジェクトとしては、ひと通り動くまでに時間がかかりすぎ、細かくロードマップを引きづらかったので、サーベイを続けて、新たな課題を発見し、その課題を小さく解決する手法を編み出したい。

TSDBの開発は、大きな成果だと思っており、この知見を横展開するために、より汎用的なアーキテクチャにできないかと考えたのが、TimeFuzeアーキテクチャ構想だ。

時系列データベースに限らず、大規模な計算機システムのモニタリングを支えるデータ処理アーキテクチャが好きなので、今後のライフワークとしていきたい。

学術研究のアプローチとの出会いとビジョンの構想

突然だけど、id:matsumoto_r (まつもとりー)さんの昨年の振り返りをみてみよう。

さらに、id:y_uuki さんとは今年1年非常に仲良くさせていただいて、12月はなぜか毎週会って何かイベントごとをこなすようなぐらい、企業・アカデミア方面で関わることが多かったように思います。いつか、企業とアカデミアの両方の要素を含む新しい研究会みたいなものを一緒に作っていけるといいな、ぐらいに一方的に信頼しており、色々と今年は無茶をお願いしましたが、できるだけその無茶をちゃんと責任をもってサポートできるようにしたいと思います。

エンジニア・研究者とはどうあるべきか - 2016年振り返りと新生ペパボ福岡基盤チームの紹介 - 人間とウェブの未来

今年は、まつもとりーさんのおかげもあって、学術研究コミュニティとの関わりが深くなった年だった。 前述の 高度に発達したシステムの異常は神の怒りと見分けがつかない - IPSJ-ONE2017 - ゆううきブログ に始まり、まつもとりーさんの5年間の挑戦の最後を見届け matsumotoryさんの博士学位論文公聴会に参加し、見て聞いて考えたこと - ゆううきブログペパボ・はてな技術大会では考えたビジョンをみてもらって、自分なりにウェブシステム全体をみてストーリー化し、それに対して議論していただいて、最後は「企業とアカデミアの両方の要素を含む新しい研究会」としてウェブシステムアーキテクチャ研究会を一緒に立ち上げることができた。

その中で気づいたのは、学術研究のアプローチにより、ウェブシステムの分野におけるある種の限界を突破できるかもしれないということ。 ここでの限界というのは、同じことの繰り返しで積み上げによる進化をしていないじゃないか感と、シリコンバレーの巨人の西洋技術を取り入れるだけで自分たちの存在価値とはなんなのだろう感を指している。 それらに対するアプローチは既にあり、前者は体系化、後者は徹底したサーベイと自分なりの思考からの新規性ということになる。 このあたりのよもやまについてはTwitterにあれこれ書いていた

ちなみに、学術研究のアプローチを企業でのエンジニアリングに導入することで何が起きるかについては、まつもとりーさんの下記の2つの記事にすべて書かれている。*1

なにより重要なのは、そもそもなにがやりたいのかという自分の欲求と、それが実現したらどんな世界になるのかをイメージすることだとまつもとりーさんは何度もおっしゃっていた。*2 前者はともかく後者はまあいいんじゃないと思いがちだし、実際何度もそう思った。 特に現場の泥臭い運用をやっていれば、なおさらそう思う。 しかし、前者だけであれば個人の趣味でしかないので、食べていくために仕事をしないといけないとなると費やせる時間は限られる。 そこで、欲求が世界にどう作用するかを考えることで、やりたいことを仕事にできる...はず*3

こういうことをずっと考えていた1年だった。 こうしてちょっとずつ自分なりの道をつくりつつあるのも、まつもとりーさんのおかげだなあとしみじみ思います。いつもありがとうございます。

そういえば、同じように同僚の id:masayoshi にも僕のほうからいろいろ無茶を投げつけたのだけど、彼は僕よりもアカデミックのアプローチに精通していたり、技術力も上なのでもっと無茶振りしていこうと思った。来年こそはなんとかしたいねいろいろと。

プロジェクトマネジメント

時系列データベース開発とクラウド移行のプロジェクトを丸ごと任された結果、物事を前に進めるための条件というものがあることを体感で理解したように思う。 これをウェブオペレーションチームの一部で実践しはじめ、小さな範囲でうまくできそうだということがわかってきたので、来年はチームというか部署全体で適用していきたい。 これらについては、まだアウトプットしていないのでどこかでアウトプットしたい。daiksyさんの薦めで、RGST2018に応募していたのだけど、残念ながら選考で落ちてしまった。

SREの分野のマネジメントって、SRE本以外に世の中に知見があまりなく、逆にチャンスだと思うが、自分が追求することではないと思っているので、誰かこれをはてなで追求したい人がいないかを探している。

アウトプット

OSS

以前開発していたdrootが、[capze](https://github.com/yuuki/capze]とともにオンプレミス上の大きめのサービスで稼働しはじめ、明らかになったバグを修正したりしていた。

アーキテクチャ設計に関わった GoとMySQLを用いたジョブキューシステムを作るときに考えたこと - ゆううきブログ では、id:tarao さんにより Fireworq として実装され、公開された。今、1200 starsとかになっていてすごい。

ブログ

登壇内容をベースにそれをできるかぎりしっかり文章にまとめるということをやり続けている。 なぜかというと、アウトプットのスケーラビリティを非常に強く重視していて、登壇資料はあくまで当日その場のためのものであり、文章として後に残すことが自分のためにも重要だと考えているためだ。 最小のインプットで最大のアウトプットが鉄則。

登壇

過去最多の11本。とはいっても、数とかどこで登壇したかは問題ではなく、何を考え何を話したか、それぞれの登壇に何かしらの挑戦があったかが重要だと思う。

あとがき

エンジニアとしてやりたいことと、仕事で実際にやっていることとの乖離が大きくなってきた。 そもそも、仕事ではだいたいその場しのぎの解決しかできず、あとは家に帰ってがんばるということがこれまでほとんどではなかったかとすら思う。 世の中のすごいエンジニアもみんなそんなもので、もっとたくさんのプライベート時間を費やしているか、技術力が圧倒的だから少ない時間できれいに解決できるに違いない、自分はまだまだなのだという気持ちでいたのだけど、どうやら必ずしもそういうわけではなさそうだと感じはじめた。 人が増えれば解決するはずだと、信じていたが脆くもその願望が打ち砕かれつつある。サーバ増やしてもスケールしないのと同じでアーキテクチャの問題。

乖離を埋めるためには、どうしたらいいのか。 技術力を発揮するというより、組織やプロジェクトをマネジメントすることが必要だと自分で導出してしまったため、矛盾しているような気もする。 マネジメント、あれほどやりたくないと言っていたのだけど、それが課題となればやるしかない。 マネジメントといっても、人と調整したり協調したりすることはあまり得意ではない*4ため、自分の資質にしたがい、ビジョンとか戦略をつくって、それを達成するアーキテクチャを考え、アイディアをだして、最上志向だから不得手な部分は仲間(にどんどん任せていくというようにしてやっていきたい。

自分の技術力向上については、WSA研を目安に研究志向でアイデアをOSSとして実現しつつ、より高みを目指したアウトプットとして論文を書いていきたい。

最後にid:tomomiiさんの縁側トーク 道をつくるを載せておき、来年また思い出せるようにしておく。tomomiiさんに道の概念を話してもらってから、自分の道とはなにかということを頭のなかでずっと考えている気がする。

*1:前者は僭越ながらはてなブログ大賞に選出させていただきました。

*2:イメージすることについては、以前書いた記事で紹介させていただいた、イメージできることを実践するを連想する。

*3:本当はもうすこし深い意味があると思うのだけど、現状はこういう理解でいる

*4:id:dekokun に任せる!

TimeFuzeアーキテクチャ構想 - 処理とデータとタイマーを一体化したデータパイプライン

この記事は第1回ウェブシステムアーキテクチャ(WSA)研究会の予稿です。

cronのようなタイムスケジューラーにより、定期的に実行されるバッチ処理の課題を解決するアーキテクチャを最近考えている。 この記事では、単一のタイムスケジューラによるcronベースの手法に代えて、データに対してタイマーと処理を仕込むことでスケールさせやすい構造にできないか、という提案を試みる。

はじめに

Webサービスにおいて、リクエストに対してHTMLのレスポンスを返却する以外のワークロードの多様化が進んでいる。 最近であれば、機械学習による時間周期による大規模なデータ処理が求められることも多い。 その他、月次の課金バッチ処理や、ランキングの定期更新など、一定の時間間隔で任意の処理を実行したいケースは多い。

このような定期的なデータ処理パターンは、SRE本[Bet17]の25.1節「パイプラインのデザインパターンの起源」にて、データパイプラインと定義されるデザインパターンに分類できる。

データ処理に対する旧来のアプローチは、データを読み取り、希望する何らかの方法でそのデー タを変換し、新しいデータを出力するプログラムを書くというものでした。通常こういったプログラムは、cron のような定期スケジューリングを行うプログラムの制御の下でスケジュール実行されました。このデザインパターンはデータパイプラインと呼ばれます。 「SRE サイトリライアビリティエンジニアリング ――Googleの信頼性を支えるエンジニアリングチーム」

データパイプライン処理を実現する一般的な方式は、特定サーバ上のcronなどのタイムスケジューラーにより、バッチ処理を実行させる方式である。

一般のデータパイプラインの欠点として、25.3節「定期的なパイプラインパターンでの課題」にて、期限内に実行が終わらないジョブ、リソースの枯渇、処理の進まないチャンクとそれに伴う運用負荷が挙げられている。 この記事では、一般のデータパイプラインの課題は以下の4つであると仮定する。

  • a) データ量増大にあわせたスケーリング運用の難しさ
  • b) バッチ処理途中のエラー処理の難しさ
  • c) タイムスケジューラそのものの運用の煩雑さ
  • d) 実行頻度設定の柔軟性の低さ

一般のデータパイプラインの課題を、データと処理とタイマーを一体化するアーキテクチャにより解決できると考えている。 提案するアーキテクチャでは、データに紐付いたタイマーがジョブを起動する。 これにより、一般手法と比較し、スケーラブルかつ細かい粒度で制御しやすいデータパイプライン処理ができる。 起爆装置と爆薬とタイマーを一体化した時限信管(Time Fuze)に似ていることから、このアーキテクチャを「TimeFuzeアーキテクチャ」と名付けてみた。

課題aについては、最初から並行処理を前提としたアーキテクチャにより解決できる。 課題bについては、バッチ処理ではなくレコード単位でジョブ定義することにより解決できる。 課題cについては、データストアのTTLによりスケジューラホストが不要となる。 課題dについては、タイマー設定の粒度をレコード単位で設定することで解決できる。

以前開発した時系列データベースアーキテクチャ[yuu17]では、特性の異なる3種類の分散データストアを組み合わせ、古いデータを遅いディスクへ徐々に逃していくことにより、性能とコストを最適化した。データストア実装として、インメモリDB(Redis Cluster)、オンディスクDB(Amazon DynamoDB)、オブジェクトストレージ(Amazon S3)を採用している。 このアーキテクチャを考える上で重要なのは、どのようにデータを移動させるかということだった。 前述の一般的な手法により、データレコードを走査し、一定以上古いタイムスタンプをもつレコードを読み出し、次のデータストアへ書き込むという素朴な手法をまず考えた。 時系列データベースのアーキテクチャでは、これをデータストアのレコード単位のTTLを利用して解決した。 具体的には、データストアに書き込むときに、レコードに対してTTL(Time To Live)を設定し、TTLが期限切れになったタイミングで、トリガーを起動し、期限切れレコードを別のデータストアへ書き込む。 実装として、DynamoDB StreamsとLambda Triggersの組み合わせ[dyn01]とDynamoDBのTTL[dyn02]を利用し、DynamoDBからS3へデータを移動させた。 これにより、パイプライン処理を、バッチ処理ではなく、レコード単位のイベント駆動型処理に置き換えられた。

のちに、TTLを用いたデータパイプラインアーキテクチャを時系列データベース以外のデータパイプラインに適用できないかを考えた。 例えば、機械学習の学習モデルの定期更新や、マルチテナント環境における大量のSSL/TLS証明書[mat17]の定期更新などがある。 以降では、TimeFuzeアーキテクチャの詳細と実装手段、アプリケーション適用について議論する。

提案手法

TimeFuzeアーキテクチャ

TimeFuzeアーキテクチャの動作フローを以下の図に示す。

DataSourceはデータパイプラインの読み出し側を指し、DataDestinationは書き出し側を指す。 TriggerはDataSourceレコード単位のパイプライン処理を実行する。

まず、DataSourceに対して、Triggerを実行したい時刻を表すTTLと共にデータレコードを書き込む。 次に、TTLの期限切れ(expire)を検知し、Triggerに期限切れしたレコードを渡す。 さらに、Triggerが渡されたレコードをもとに所定の処理を実行し、DataDestinationに対して、結果を書き込む。 Triggerでは、その他のAPIやデータストアからデータを取得することもある。 DataDestinationは、DataSourceと同一のデータストアでもよい。 前述の学習モデルの更新や証明書更新の例では、DataSourceとDataDestinationは同一のデータストアを利用することを想定している。

TimeFuzeのメリット

TimeFuzeアーキテクチャには以下のメリットがある。

  • a) 並行処理を前提としたアーキテクチャであり、スケールさせやすいこと
  • b) エラーからの回復処理が容易であること
  • c) タイムスケジューラとバッチ処理のためのホストもしくはクラスタの構築・運用が不要であること
  • d) レコード単位でタイマーをセットするため、ジョブの実行頻度をレコード単位で調整可能

a) について、バッチ処理の場合、マルチコア・マルチホストスケールさせるまたはI/O多重化するための並行処理実装を開発者に要求する。 TimeFuzeでは、レコード単位でトリガー処理を記述するため、スケールさせやすい。 b) について、TimeFuzeでは、1レコード分の処理を書けばよいため、エラー発生時にリトライする場合、どこまで処理を終えたかを記録するといった回復処理のための実装が必要がない。

TimeFuzeの実装

実装として、Amazon DynamoDBとAmazon Lambdaを利用する例と、Redisを利用する例をあげる。

Amazon DynamoDBおよびAmazon Lambda

Amazon DynamoDBは、フルマネージド型のNoSQLデータベースサービスである。 Amazon Lambdaは、任意のイベントを入力として任意の処理をFunctionとして登録しておくと、イベント発火を契機にFunctionを呼び出せる。 これらを組み合わせ、DynamoDB上のレコードに対する登録、更新、削除のイベントを契機に、Lambda Functionをトリガーとして実行できる。 DynamoDBはTTLをサポートしており、TTL expiredイベントを契機にLambda Functionを実行できる。

DynamoDBをDataSourceとして、トリガー処理にLambdaを利用することで、TimeFuzeアーキテクチャを素直に実装できる。

Redis

Redisは多彩なデータ構造をもつインメモリDBであり、昨今のWebアプリケーションのデータストアの一つとして、広く利用されている。 RedisはKeyspace通知[rednot]機能をもち、キーに対するイベントをPub/Subにより、購読者にメッセージ通知できる。 Keyspace通知を利用し、DynamoDB同様にトリガー処理を実現できる。

ただし、実運用のためのトリガー処理を実現するには、イベント通知以外に、通知するイベントの永続化とイベントを受信し処理するトリガーの実装が必要となる。 Redis自体は、後者の2つをサポートしないため、アプリケーション開発者が汎用的に利用できる実装を提示したい。

そこで、以前筆者が開発したジョブキューシステム[yuu14]Fireworq[gitfir]に着目する。 Fireworqでは、ジョブの永続化をサポートし、所定のインタフェースを満たしていれば任意の言語で開発したWebアプリケーションサーバに対してジョブ実行を依頼できる。 RedisのKeyspace通知とFireworqを組み合わせることにより、メッセージの永続化をサポートしつつ、任意の言語によるトリガー処理を実現できる。 ただし、RedisにKeyspace通知を受信し、Fireworqへ投稿するコンポーネントを新たに実装する必要がある。

TimeFuzeの具体的なアプリケーションへの適用

自分の最近の業務経験から、時系列データの異常検知と大規模SSL/TLS証明書管理アプリケーションへのTimeFuzeアーキテクチャの適用を考えた。

時系列データの異常検知

機械学習をWebサービスに導入すると、最新の投稿データに追従するために、定期的に学習モデルを更新することがある。 TimeFuzeにより、DataSource上のモデルの更新処理をTriggerとして登録し、モデル更新時にTTLをセットして再書き込みすることにより、データパイプラインとして機能する。

時系列データによる異常検知では、収集したメトリック系列もしくはメトリック系列の集合に対して、学習モデルを構築する。 学習モデル構築後に収集されるメトリックに対応するため、学習モデルを定期的に更新する必要がある。

このアプリケーションにTimeFuzeアーキテクチャを適応することを考える。 学習モデルを更新するのみで、学習モデルを他のデータストアに移動させる必要はないため、DataSourceとDataDestinationは同一のデータストアとなる。 各学習モデルのレコードにTTLを設定し、Triggerが外部データストアからメトリックを取得し、学習処理を実行したのちにDataDestinationに対して上書き更新する。

大規模SSL/TLS証明書管理

ブログサービスやレンタルサーバーサービスのようなマルチテナント環境[pep17]にて、大量のSSL/TLS証明書を管理し、数ヶ月ごとに更新するケースがある。Let's Encrypt[letenc]の場合、証明書の期限は3ヶ月となる。

[mat17]では、サーバ証明書と秘密鍵をWebサーバ上のファイルシステムに格納するのではなく、データベースに格納し動的取得するアーキテクチャが提案されている。 データベース上の証明書と秘密鍵を定期的に更新するために、TimeFuzeアーキテクチャを適用することを考える。 各ドメインに対する証明書および秘密鍵のレコードにTTLを設定し、Triggerが証明書を再取得し、DataDestinationへ上書きする。 Let's Encryptの場合、ACMEプロトコルにより証明書を自動発行できる。

考察

TimeFuzeの適用条件

現在のところ、TimeFuzeの適用条件は、y_uukiの経験に頼っており、明らかでない。*1 既存のデータパイプラインアプリケーションの課題をサーベイし、適用条件を整備することは今後の課題である。 現段階では、以下のデメリットにあてはまるケースに加えて、少なくともデータレコード数が一定以上大きくなければメリットを享受しづらいことがわかっている。

TimeFuzeのデメリット

TimeFuzeアーキテクチャはあらゆるデータパイプラインに適用できるわけではない。

アーキテクチャレベルでは、Triggerがレコード単位でジョブを実行するため、DataSource上の複数のレコードをマージする必要がある処理をしづらいというデメリットがある。 従来手法であれば、DataSource上のレコードをグループ化して読み出し、マージ処理することは容易である。 一方、TimeFuzeアーキテクチャでは、マージする必要がないように最初から1つのレコードにまとめて書き込む必要がある。

さらに、実装レベルでは、TTLを利用することのデメリットとして、データの一貫性と、ジョブ実行タイミング制御の困難性がある。 前者では、レコードが削除されてから更新されるまでレコードを参照できない期間があり、アプリケーションに工夫を要求する。 後者は、TTLの期限切れを過ぎてから実際に削除されるまでのディレイが大きいと、開発者が意図したタイミングよりも遅れてジョブが実行されることがありえる。 DynamoDBのTTL実装の場合、ベストエフォートベースでTTL期限切れ以降2日以内に削除することを目指している[dyn03]

TimeFuzeのデメリットの解決

TTLのデータの一貫性の問題は、TTLをタイマーとして利用するのではなく、設定した時刻を経過したイベントのみを発行し、レコードを削除しない機能をデータストアに組み込むことで解決できる。

ジョブ実行タイミング制御の問題は、RedisやCassandraなどTTLをサポートしたデータベース実装を調査し、ディレイ時間を計測する必要がある。

アーキテクチャレベルの課題について、リレーショナルモデルのようなデータレコード間の関係の概念を導入することにより、複数のレコードを前提としたアーキテクチャへ昇華できるかもしれない。 *2

むすび

データパイプライン処理は、Webサービス開発ではよく採用されるデザインパターンである。 単一のタイムスケジューラによる従来手法では、レコード数に対するスケーラビリティ・エラー回復処理・サーバ運用効率・ジョブ実行頻度の細かい粒度での制御に課題があった。 そこで、この記事では、処理とデータとタイマーを一体化したTimeFuzeアーキテクチャを提案し、従来手法の課題の解決を構想した。 さらに、時系列データベースアーキテクチャ、時系列データの異常検知、大規模SSL/TLS証明書管理の各アプリケーションへの適用可能性を示した。

今後の取り組みとして、既存のデータパイプラインの課題をサーベイし整理し、既存データストア実装のTTLディレイ時間の調査、TTLではなくTime to Eventを既存のデータストアへ組み込むことを考えている。

参考文献

発表スライド

発表時のフィードバック

  • TimeFuzeアーキテクチャの適用条件について (matsumotoryさん)
  • 関係性の概念の導入について (monochromeganeさん)
  • モバイルエージェントとの関連について (61503891さん)
  • 適応的なパラメータ決定ポイントについて (matsumotoryさん、syu_creamさん、suma90hさん)

あとがき

提案するアーキテクチャ名がTimeFuze(時限信管)であることにはそれなりの意味があります。 表題を考えていたときに、まつもとりーさんのFastContainerアーキテクチャ構想を眺めていました。 FastContainerってかっこいいしずるいみたいな感じです。 自分もかっこいい名前にするぞ、とあれこれ考えました。 最初はDataCronやData-Driven Cronといった名前を考えていました。 このような名前であれば、この分野の人であればなんとなく想像はつきそうであるものの、多義的な用語になりそうだったため、あまりピンときていませんでした。 このアーキテクチャに対して、なんとなく時限爆弾っぽいイメージとARMORED COREの近接信管のイメージをもっていたため、ググってみると、TimeFuze(時限信管)という用語があることを知りました。 Wikipediaによると信管は、「起爆時期を感知する機能」「所望の時期以外では絶対に起爆させないための安全装置」「安全装置の解除機構」「弾薬の起爆装置」の4つの機能が統合された装置だそうです。 ここで、このアーキテクチャのアイデアって、「データ」「処理」「タイマー」の一体化ではないかということに思いあたりました。 記事中では、しれっとでてくるこの表現ですが、この表現のおかげで、最終的にはデータが意思を持って動いて欲しい(by takumakumeさん)という話まで発展させることができました。 そうすると自分の中でのFastContainerの見方がかわってきました。 FastContainerは現在のところプロセスに着目されていますが、データ処理に着目する発想もあるんじゃないかと考えました。 議論では、さらに関係性の概念やモバイルエージェントの関連など、さらにTimeFuzeを深めるための着想をいただき、ひさびさにおもしろい、楽しいと思いました。

言葉にこだわった結果、抽象化が進み、他の技術や研究と結び付け、新たな着想を得ることができる、というのがここで言いたかったことでした。

あとがきは以上です。wsa研自体の振り返りは別記事として書きます。

*1:発表後の質疑にて、matsumotoryさんに指摘されたところ

*2:発表後の質疑にて、monochromeganeさんに指摘されたところ

ウェブシステムの運用自律化に向けた構想 - 第3回ウェブサイエンス研究会

はてなエンジニア Advent Calendar 2017の2日目です。 昨日は、id:syou6162 さんによるAWS Lambda上で鯖(Mackerel)の曖昧性問題を機械学習で解決しよう - yasuhisa's blogでした。

この記事は、人工知能学会 合同研究会2017 第3回ウェブサイエンス研究会の招待講演の内容を加筆修正したものです。 講演のテーマは、「自然現象としてのウェブ」ということでそれに合わせて、「自然のごとく複雑化したウェブシステムの運用自律化に向けて」というタイトルで講演しました。 一応、他の情報科学の分野の研究者や技術者に向けて書いているつもりですが、その意図がうまく反映されているかはわかりません。

※ 2018/01/29追記: 本文中で費用を最小にすることが目的としていますが、最近では、費用も制約条件であり、変更速度を最大にする最適化問題というほうがしっくりくるようになりました。変更速度がどんどん大きくなり、そもそも人が変更するのではなく計算機が変更しはじめるのが、Experimentable Infrastructureです。これを突き詰めていくと、人間の発想をすぐ計算機に反映できる状態になります。その結果、人間の発想そのものが何か変化するではないかということが最近の興味です。)

概要

ウェブシステムの運用とは、信頼性を制約条件として、費用を最小にする最適化問題であると考えています。 費用を最小にするには、システム管理者の手を離れ、システムが自律的に動作し続けることが理想です。 クラウドやコンテナ技術の台頭により、ウェブシステム運用技術の自動化が進んでおり、自律化について考える時期になってきたと感じています。 自律化のために、観測と実験による「Experimentable Infrastructure」という構想を練っています。 Experimentable Infrastructureでは、監視を超えた観測器の発達、実験による制御理論の安全な導入を目指しています。

1. ウェブシステムの信頼性を守る仕事

ここでのウェブシステムとは、ウェブサービスを構成する要素と要素のつながりを指しており、技術要素とは「ブラウザ」「インターネットバックボーン」「ウェブサーバ」「データベース」「データセンター内ネットワーク」などのことを指します。 特に、データセンター内のサーバ・ネットワークおよびその上で動作するウェブアプリケーションを指すことがほとんどです。 総体としてのウェブというよりは、単一組織内の技術階層としてのシステムに焦点をあてています。

ウェブシステムの最も基本的な機能として、「信頼性」があります。 信頼性を守る役割は「Site Reliability Engineer(SRE)」が担います。 SREはウェブ技術者界隈で市民権を得ている概念であり、Googleのエンジニアたちによって書かれた書籍「Site Reliability Engineering」[Bet17]に詳細が記されています。

信頼性にはいくらかの定義のしようがあります。 [Bet17]では[Oco12]の定義である「システムが求められる機能を、定められた条件の下で、定められた期間にわたり、障害を起こすことなく実行する確率」を採用しています。 信頼性というとつい100%を目指したくなりますが、信頼性と費用はトレードオフなため、信頼性を最大化するということはあえてしません。

さらに、信頼性をたんに担保することが仕事なのではなく、費用を最小化することが求められます。 この記事では、費用=コンピューティングリソース費用 + 人件費用 + 機会費用 *1としています。 SREは費用をエンジニアリングにより削減できます。例えば、コンピューティングリソース費用はソフトウェアの実行効率化、人件費用と機会費用はソフトウェア自動化などにより削減できます。 以上より、SREの仕事のメンタルモデルは、「目標設定された信頼性*2 *3を解くことであると言い換えられると考えます。 特にSREでは、定型作業(トイルと呼ばれる)を自動化し、スケールさせづらい人間ではなくコンピュータをスケールさせることが重要な仕事となります。

一般の人々からみれば、ウェブシステムは、十分自律動作していると言えます。 内部的に障害が発生したとしても、人々は何もせずとも、障害から回復し普段通りサービスを利用できます。 ただし、その裏では、信頼性を担保するために、数多くの人間の手作業や判断が要求されているのが現実です。 人間がなにもしなければ、およそ1週間程度*4で信頼性は損なわれることもあります。

我々のゴールは、最終的にコンピュータのみでシステムを運用可能な状態にすることです。 IOTS2016の開催趣旨が、このゴールを端的に言い表しています。

インターネット上では多種多様なサービスが提供されている。このサービスを提供し続け、ユーザに届けることを運用と呼ぶ。サービスが複雑・多様化すれば運用コストは肥大する。このコストを運用担当者の人的犠牲により「なんとか」してしまうことが「運用でカバーする」と揶揄される。日本では大規模構造物を建造する際に、破壊されないことを祈願して人身御供 (人柱) を捧げる伝統があるが、現在のインターネットの一部はこのような運用担当者の人柱の上に成立する前時代的で野蛮な構造物と言うことができる。

運用担当者を人柱となることから救う方法の一つが運用自動化である。運用の制御構造における閾値を明らかにすることにより、人は機械にその仕事を委託することができる。機械学習や深層学習により、この閾値を明らかにすることをも機械に委託することが可能となることも期待される。不快な卑しい仕事をやる必要がなくなるのは、人間にとってひじょうな福祉かもしれないが、あるいはそうでないかもしれない。しかし機械に仕事を委託することにより空いた時間を人間が他のことに使うことができるのは事実である。

本シンポジウムは、インターネットやネットワークのサービスの運用の定量的な評価を通じて、積極的に制御構造を計算機に委託することで人間の生産性を向上させ社会全体の収穫加速に結びつけることを目的とする。

IOTS2016 開催の趣旨より引用 http://www.iot.ipsj.or.jp/iots/2016/announcement

2. ウェブシステム運用の現状

国内のウェブシステムの運用技術の変遷

2010年以前は自作サーバ時代[rx709]でした。 秋葉原でパーツを購買し、組み立てたサーバをラックに手作業で配置していました。 自作だと壊れやすいこともあり、冗長化機構やスケールアウト機構など信頼性を高める基礎機能が浸透しました。[ito08] のちにベンダー製サーバやクラウドへ移行が進みます。 このころから、XenやKVMなどのハイパーバイザ型のサーバ仮想化技術の台頭により、徐々にサーバをモノからデータとして扱う流れができはじめます。

クラウド時代

2011年にAWS東京リージョンが開設され[awshis]、有名ウェブ企業が移行しはじめます[coo15]。 クラウドの利用により、必要なときにすぐにハードウェアリソースが手に入り、従来の日または月単位のリードタイムが一気に分単位になりました。 さらに、単にハードウェアリソースが手に入るだけでなく、クラウドのAPIを用いて、サーバやデータベースをプログラムから作成することが可能になりました。 これを利用し、負荷に応じて自動でサーバを増やすなどの動的なインフラストラクチャを構築できるようになってきました。

コンテナ型仮想化技術

2013年のDocker[doc13]の登場により、ソフトウェアの動作環境を丸ごとパッケージ化し、さまざまな環境に配布できるようになりました。 コンテナ型仮想化技術そのものは古くから存在しますが、Dockerはコンテナの新しい使い方を提示しました。 コンテナ環境は、ハイパーバイザ環境と比べてより高速に起動する*5ため、より動的なインフラストラクチャの構築が可能になりました。

この頃より、Immutable Infrastructure[imm13][miz13][mir13][sta13]またはDisposable Infrastructureの概念が登場し、サーバを使い捨てるという発想がでてきました。

サーバレスアーキテクチャ

2015年ごろから、サーバレスアーキテクチャ[mar16] [nek16]という概念が登場しました。 これは本当にサーバがないわけではなく、サーバの存在を意識しなくてよいような状態へもっていくためのアーキテクチャと技術選択を指します。

サーバレスアーキテクチャでは、具体的なサーバやコンテナの存在を意識することなく、抽象化された複数のサービスを組み合わせて、ビジネスロジックを実装するようになります。 ここでのサービスは、フルマネージドサービスと呼ばれることが多く、データベースサービス(Amazon DynamoDB、Google BigQueryなど)、CDNサービス(Akamai、Amazon Cloudfrontなど)、Functionサービス(AWS Lambda、Google Function)などを指します。 理想的なフルマネージドサービスは、裏側にあるサーバの個数や性能ではなく、APIの呼び出し回数や実行時間、データ転送量といったよりアプリケーションに近い単位でスケーリングし、課金されます。 ウェブサービス事業者がこれらの抽象層を実装するというよりは、クラウドベンダーがサービスとして提供しているものを利用することがほとんどです。

Site Reliability Engineering(SRE)の登場

2015年から日本のウェブ業界にSREの概念が浸透し始めました[mer15]。 SREにより、ウェブシステムの「信頼性」を担保するエンジニアリングという、何をする技術やエンジニアなのかがはっきり定義されました。 それまでは、システム管理者、インフラエンジニアや下回りといったざっくりした用語で何をする技術で何をする人なのかが曖昧な状態であることに気付かされました。 トレードオフである信頼性を損なわずに変更の速度の最大化する*6上で、ソフトウェアエンジニアリングを特に重視しているのも特徴的です。

SRE自体は技術そのものではなく、SREによりウェブシステムの運用分野に、体系的な組織開発・組織運用の概念が持ち込まれたことが、大きな変化だと考えています。

変遷まとめ

昔はハードウェアを調達し、手作業でラッキングしていました。 現在では、サーバの仮想化技術の発達とアプリケーション動作環境パッケージングの概念、さらにサーバレスアーキテクチャの考え方とサービスの浸透により、よりダイナミックで抽象的なインフラストラクチャが構築可能になりました。 このように、インフラストラクチャがソフトウェアとして扱いやすくなり、ソフトウェアエンジニアリングを重視した組織文化の浸透と合わさり、この10年でソフトウェアによる運用自動化が大幅に進んできたと言えます。

しかし、これでめでたしめでたしかというとそういうわけではありません。

3. ウェブシステム運用の課題

本当は怖いウェブシステム運用

このテーマについては、今年のIPSJ-ONEにて「高度に発達したシステムの異常は神の怒りと見分けがつかない」[yuu17]で話しました。

ウェブシステムでは、異常が発生しても原因がわからないことがあります。 原因がわからず再現させることも難しい場合、システムの振る舞いがまるで「自然現象」に感じられます。*7 自動化が進んでいるからこそ、不明であることが異常に対する「恐怖」をうみます。 これは、システムに対する変更が安全かどうかを保証することは難しいためです。 その結果、振る舞いの解明に多くの時間をとられたり、わざと自動化を避けて、人間の判断をいれようとします。

実際、異常のパターンは様々です。 講演では、以下の2つの例を話しました。

  • ハードウェアのキャパシティにはまだ余裕があるにもかかわらず、1台あたりの処理能力が頭打ちになり、自動スケールするが自動スケールしない別のコンポーネントが詰まるケース
  • データベース*8のアクティブ・スタンバイ構成*9において、ネットワーク分断により、確率的にどちらかのマスターにデータが書き込まれ、データの一貫性を損失するケース

前者は、自動化していても自動で復旧できず、後者は自動化したがゆえに新たな問題が発生したケースです。 書籍「Infrastructure As Code」[kie17]では、1.3.5節 オートメーション恐怖症にて、"オートメーションツールがどういう結果を生むかについて自信が持てないため、オートメーションツールに任せきりになるのは怖かった。"と書かれています。

ウェブシステムの複雑性

ここまできて、なぜウェブシステムは自然現象のように感じられるか、複雑さの要因はなにかについて、体系的に整理し、分析しようと真剣に考えたことはありませんでした。 そのための最初の試みとして、自分の経験を基に以下の3点を挙げてみます。

  • ソフトウェア依存関係の複雑さ
  • 分散システムとしての複雑さ
  • 入力パターンの複雑さ

ソフトウェア依存関係の複雑さ

ウェブシステムは、多数のソフトウェアの重ね合わせにより構成されます。 言語処理系、OS、ドライバ、共有ライブラリ、ミドルウェア、アプリケーションライブラリ、アプリケーションなどです。 さらに、これらがネットワーク越しに接続され、さまざまなプロトコルにより通信します。

このような状況では、ソフトウェアの依存関係や組み合わせの問題が発生します。 具体的にはバージョンアップ問題やプロトコル互換問題、依存地獄問題[yuu15]などを指します。

例えば、あるソフトウェアをバージョンアップすると、そのソフトウェアに依存したソフトウェアが動作しなくなることがあります。 データベースのバージョンアップにより、プロトコルなどの仕様変更に追従していないアプリケーションが動作しなくなるなどは典型的な例でしょう。 動作したとしても、性能が低下し障害につながるということもあります。

分散システムとしての複雑さ

信頼性のあるウェブシステムは、基本的に分散システムとして構成されています。 複数のノードが相互に通信するということは、単純にノードやリンクが増加すればするほど、システムとしては複雑になります。 さらに、分散システムは、ハードウェア故障、ネットワークの切断・遅延といった物理的制約がある中で、信頼性を担保しなければいけません。 部分的な故障を許容しつつ、自動でリカバリする仕組みは複雑です。 分散システムの難しさについて書かれた文献として、「本当は恐ろしい分散システムの話」[kum17]が非常に詳しいです。

入力パターンとしての複雑さ

ウェブシステムの入力パターン(ワークロード)は一定でもなければ、ランダムでもないことがほとんどです。 ただし、サービスの特性により、朝はアクセスは少ないが、夜に向けてアクセスが徐々に増加するといった一定の傾向はあります。 大まかな予測はできることがあるものの、むずかしい。 人間、検索クローラ、スパマーなどの活動に応じてシステムへの入力パターンは突発的に変化します。これは、制御工学でいうところの外乱に相当します。 実際、この突発的な変化が障害の原因になることはよくあります。

入力パターンの突発的変化(外乱)は、人間や社会の変化によることもあるため、システム側での予測は困難です。

システムの複雑さの度合い

複雑さを分析するのは、要因に加えて度合いの評価も必要です。 度合いについてもせいぜいサーバ台数やサービス数程度でしかみてきませんでした。

そもそも一般的に複雑さをどう定義しているかについて、複雑性科学の書籍[mel11]を参考にしました。 [mel11]には、複雑さについての一般的な定義はなく、これまでいくつかの指標が提案されたことが書かれていました。 提案された指標は、サイズ、エントロピー、アルゴリズム情報量、論理深度、熱力学深度、計算能力、統計的な複雑性、フラクタル次元、階層度がありました。 この中で、比較的ウェブシステムに当てはめやすいのは、サイズと階層度です。

前述の分散システムとしての複雑さに対して、サイズと階層度*10の概念を適応してみます。

サイズについては、例えば、はてなのシステムサイズは以下のようなものです。GoogleやAmazonであれば、おそらくこの100~1000倍の規模でしょう。

  • サービス数: 100+ (内部向け含む)
  • ロール数: 1000+
  • ホスト数: 1000+
  • プロセス/スレッド数: 10000+
  • SRE数*11: 10人弱

階層度を特に入れ子のレベルによって定義した場合、プログラム実行単位については10年前であれば例えば以下のようになります。

  • レベル1: プロセス/スレッド
  • レベル2: サーバ (複数のプロセスの集合体)
  • レベル3: ロール (クラスタやロードバランサ配下のサーバ群)
  • レベル4: サービス: (ロールまたはマイクロサービスの集合体)
  • レベル5: プラットフォーム: (複数のサービスの集合体)
  • レベル6: ウェブ

一方、現在であれば例えば以下のようになります。 ただし、サーバレスアーキテクチャを採用していれば、レベル1~3までは無視できる一方で、マイクロサービスなど層を増やす変化もあります。

  • レベル1: プロセス/スレッド
  • レベル2: コンテナ
  • レベル3: サーバ (複数のプロセスの集合体)
  • レベル4: ロール (クラスタやロードバランサ配下のサーバ群)
  • レベル5: マイクロサービス
  • レベル6: サービス: (ロールまたはマイクロサービスの集合体)
  • レベル7: プラットフォーム: (複数のサービスの集合体)
  • レベル8: ウェブ

実際には、複雑さを評価するためには、複雑さの要因ごとに複数の指標と複数の観点をもつ必要があると考えます。 ウェブシステムがどのような複雑さをもつのか、特に他分野の方に伝えるには、SREの分野では、蓄積が不足していると感じます。

4. ウェブシステムの自律運用へのアプローチ

ここまで、ウェブシステム運用技術の変遷とウェブシステムの複雑さについて書いてきました。 ここでは、これらを踏まえ、課題を解決するためのビジョンである観測と実験による「Experimentable Infrastructure」について述べます。

観測

前述の運用技術の進歩により、インフラストラクチャが抽象化され、プログマブルかつシンプルに扱えるようになってきました。 しかし、要素数を増やす方向へ技術が進んでいるため、依然としてシステム全体の挙動を人が理解することが難しいと感じます。 したがって、系全体の精緻な理解を助ける観測器が必要です。

ここでの観測とは、ウェブシステムの「過去と現在」の状況を人間またはコンピュータが自動的かつ継続的に把握することです。 20年近く前からサーバ・ネットワークを「監視」するためのツール*12が開発されてきました。

従来や現在の監視ツールは、サーバに対する定期的なpingやメトリックの時系列グラフ化をサポートしています。 しかし、これだけでシステムの振る舞いを分析できるかというとそうではありません。 監視ツールを頼りにしつつも、SREはシステムのネットワークグラフ構造を調べ、ログを眺め、アプリケーションコードをgrepし、脳内でシステムに対してどのような変更があったかを思い出すといったことをやっています。

このように、まだまだ監視ツールだけではわからないことがあるのが現状です。 従来の監視はもちろん、ログやイベントデータの収集に加えて、構成要素と要素間の関係の把握などが求められます。*13

自分が開発に関わっているサーバ監視サービスであるMackerel[mac]については、[yuu17-2]に書いています。Mackerelには世の中のウェブシステムの観測結果が集約されているデータベースとしてとらえると解析対象としておもしろいんじゃないかと思います。

制御

システムが自律的に動作し続けるためには、システムの異常を自動で制御する必要があります。

ナイーブな制御

例えば、クラウドの台頭によりサーバの生成と廃棄がプログラマ化されたため、メトリックの変動に応じてサーバの個数や性能を自動調整できます。 さらに、なんらかの理由により不調なプロセスやサーバをすぐ捨てて、新しいものを生成することも可能です。 現在では、このあたりがウェブシステムの現場で浸透中の制御になるかと思います。 しかし、制御のためのパラメータはエンジニアの経験を元に値を設定しており、制御がうまく動くかどうかはエンジニアの技芸に頼っていると言えます。 ナイーブな自律制御のままでは、すべての課題はクリアできません。

待ち行列による制御

よくあるアイデアの一つに、待ち行列理論の利用があります。情報ネットワークの分野では、よく利用されている理論です。 ウェブシステム全体と、サブシステムをそれぞれ入れ子構造の待ち行列としてモデル化できます。 待ち行列解析により、到着分布と処理分布を観測しつづけることで、必要なコンピューティングリソースを割り出し、自動的にリソースを配分し続けられます。 例えば、最も簡単なリトルの法則を応用すると、[myu16]のように中期的なキャパシティプランニングに利用できます。

しかし、待ち行列理論の課題は、仮定する分布の範囲外の予測のできない突発的な外乱に対応しづらいことです。 到着分布は、前述したように入力の複雑さにより、予測することは難しいでしょう。 さらに、到着分布が予測可能であっても、ネットワークのパケット処理とは異なり、ウェブシステムでは、処理の重たい入力とそうでない入力の差が大きい*14ため、処理分布が予測できない可能性もあります。

外乱は事業機会となることがあるため、分布から外れた異常値だからといって無視はできないという事情があります。 そこで、最近はフィードバック制御に着目しています。*15

フィードバック制御

フィードバック制御は、大規模で複雑なシステムを、たとえシステムが外乱に影響を受けようとも、あるいは、限られた資源を有効利用しつつ、その性能を保って動作させるための手法です。 [phi14]より引用

フィードバック制御に着目した理由は、制御対象はブラックボックスであり、中身は不明でよいという点です。 これは、SREがアプリケーションの中身を知らずに観測結果だけをみて障害対応する様子に似ていると感じました。 待ち行列理論ではできないダイナミクスを扱えるのも特徴です[ohs13]。 現実のウェブシステムでは、解析的にモデルを導出するのは難しいため、パラメータの決定には「実験」による計測が必要です。

ウェブシステムに対して、フィードバック制御の導入イメージは例えば、以下のようなものです。 制御入力は、明示的に変更可能なパラメータです。例えばサーバの台数やサーバのキャッシュメモリ量などがこれに相当します。 制御出力は、制御対象パラメータです。例えば、応答時間やエラーの数などになります。 制御出力を監視し続け、目標値から外れたら制御入力を変更し、元に戻すような操作を、システムモデルに基づいて行います。 具体的には、制御入力に対して伝達関数を適用し、制御出力を得ます。 ただし、伝達関数の同定やチューニングは、実システムで応答をみる必要があります。

ただし、ここで述べているのは古典的な制御理論の話であり、単一入出力しか扱えません。 実際には、複数の入力と出力を扱ったり、階層的なシステムに対する制御をやりたくなるでしょう。 そちらは、現代制御理論やポスト現代制御理論と呼ばれる発展的な理論の範疇のようです。

制御理論をウェブシステムの運用に組み込む研究には、[jen16]などがあります。 [jen16]は、データベースクラスタ内のサーバのスケーリングについて、フィードバック制御、強化学習、パーセプトロン学習の3つの手法を比較しています。 さらに、フィードバック制御(PID制御)をApache Sparkのバックプレッシャー機構に組み込む実装もあります[spapid]

実験

待ち行列にせよ、フィードバック制御にせよ、機械学習的なアプローチにせよ、実システムの応答結果を継続的に得ることが必要です。 おそらく、統一的なモデルなどはなく、システムやサブシステムごとに異なるモデルとなると考えています。

しかし、単純に平常時のシステムを観測し続けるだけでは、良好な制御モデルが得られない可能性があるのではないかと考えています。 というのは、システムごとのモデルとなると、過去に限界値や異常値に達したデータの数が少ないため、学習データが足りない可能性があります。 *16 特に新システムであればデータはゼロなので、本番環境の蓄積データだけでは、制御パラメータを決定できません。

ワークロードのない状態では、例えば1台あたりのサーバの限界性能というのは実際に限界まで負荷をかけないとわからないことが多いでしょう。 素朴に考えると、手動で実験してデータをとることになってしまいます。

そこで、実験の自動化を考えます。 システムには日々変更が加えられるため、継続的な実験が必要であり、手作業による実験は人手が必要で結局長続きしないためです。

分散システムの自動実験の概念としてNetflixが提唱するChaos Engineering[cha17]があります。 Chaos Engineeringは、本番環境にて故意に異常を起こす逆転の発想です。 例えば、サーバダウンなどわざと異常を起こすことで、システムが異常に耐えられるのかをテストし続けます。 Chaos Engineering自体は、先に述べたように制御モデルのパラメータ推定についての言及はありませんが、ビジョンの構想に大きく影響を受けました。*17

しかし、一般に言われていることは、本番環境で異常を起こしたり、限界まで負荷をかけるのは不安であるということです。 実際、書籍「Chaos Engineering」[cas17]では、監視の環境整備、異常時の挙動の仮説構築、実験環境での手動テスト、ロールバックなどの基盤を整えた上で十分自信をもった状態で望むようにと書かれています。 したがって、実験そのものは自動化されていても、まだまだそれに至るまでに人間による判断を多く必要とするようです。

ここで、クラウドやコンテナ技術など限りなく本番に近い環境をオンデマンドに構築する技術が発達してきていることを思い出します。 自分の考えでは、実験環境を高速に作成することで安全に実験を自動化する技術を突き詰め、効率的にデータを取得し、パラメータを決定するというアプローチを考えています。*18

これら以外に手動で実験するケースについても、実験という概念に内包し扱おうしています。 動作テスト、負荷テスト、パラメータチューニング(OSやミドルウェアのパラメータ)などです。*19

Experimentable Infrastructure

以上のような観測と実験の自動化アプローチには、近代科学の手法の自動化であるというメタファーが隠されています。

書籍「科学哲学への招待」[noe15]に近代科学の歴史とともに、仮説演繹法について紹介されています。

  • (1) 観察に基づいた問題の発見 (観測)
  • (2) 問題を解決する仮説の提起
  • (3) 仮説からのテスト命題の演繹
  • (4) テスト命題の実験的検証または反証 (実験)
  • (5) テストの結果に基づく仮説の受容、修正または放棄

仮説演繹法のループを高速に回し、自律的に変化に適応し続けるシステムを「Experimentable Infrastructure」と呼んでいます。 コンピュータに仮説の提起のような発見的な手法を実行させるのはおそらく難しいと思います。 しかし、ウェブシステムの観測と実験により判明することは、世紀の大発見ということはなく、世の中的には既知のなにかであることがほとんどなので、仮説提起をある程度パターン化できるのではないかと考えています。

5. 自律運用の壁とウェブサイエンス

仮に前述のアプローチがうまくいったとしても、さらにその先には壁があります。 自律運用の壁は、「ハードウェアリソース制約」と「予想できない外乱の大きな変化」です。

前者は、予め用意したリソースプールでさばける以上の負荷には耐えられないことです。 クラウドにも上限は存在します。

後者は、サーバの増加などには必ずディレイが存在するため、外乱の大きさによっては、フィードバックが間に合わないケースもありえます。 これについては、以下のようにウェブサイエンスの研究成果である状態予測をフィードフォワード制御に利用するといったアイデアもあるかもしれません。

自発的に発展するサービスの特徴を捉え、例えば、Web サービスが今後発展していくのか、元気をなくしていくのか、そうした状態予測を目指し、自律的な人工システムのダイナミクスを捉える普遍的な方法論をつくり、自然科学としての人工システム現象という分野の確立を目指している。

106 人 工 知 能 31 巻 1 号(2016 年 1 月)「ウェブサイエンス研究会(SIG-WebSci)」 発足

自律運用

ここまでの「自律」の定義は「自動修復」「自律運用」でした。 自律運用では、与えられた制約条件=信頼性 を満たすように自律動作することを目指しています。 信頼性を自律的に満たせれば、費用のうち人件費はある程度削減できます。 しかし、信頼性の条件設定、アーキテクチャの決定、ソフトウェアの効率化などは依然として人の仕事です。

自律開発

自律運用に対して、自律開発*20という考え方があります。 これは、この記事の文脈では例えば、自律的に費用を最小化するようなシステムを指します。

自律開発には、進化・適応の概念が必要であり、分散システムアーキテクチャの設計・改善やソフトウェア効率改善の自律化などを含みます。 おそらくソフトウェア進化の研究[oom12]などで進んでいる分野だと思います。

運用から解放されたその先

ここまではウェブシステムの運用という工学的モチベーションの話でした。

IPSJ-ONEの記事[yuu17]にて、以下のような宿題がありました。

しかし、最終的に自分のやっていることが世界にとってどういう意味があるかということを加えるとよいという話もあったのですが、ここは本番では組み込めなかった部分です。自動化されて、運用から解放されて、遊んで暮らせるようになるだけなのか?という漠然とした疑念はありました。科学の歴史をみてみると、例えば未知であった電気現象を逆に利用して、今ではコンピュータのような複雑なものを動かすことができるようになっています。そこからさらにメタなレイヤで、同じようなことが起きないかといったことを考えているのですが、これはこれからの宿題ということにします。

いまだにこの宿題に対する自分の中の答えはありませんが、ウェブサイエンス研究会発足の文章を拝読して、ぼんやりと基礎科学の貢献という道もあるのだなと思いあたりました。 人の手を介さずに動き続けるウェブシステムを探究することで、複雑な系に対する統一的な法則を発見し、基礎科学へ貢献できないかどうかといったことを考えながら、老後を過ごすのも、昔からシステムが好きな自分にとってよいのかもしれません。

ネットワークの技術階層を含む Webの存在そのものを新しい「自然現象」として捉え、例えば、その「生態系」としての構造を明らかにすることで、普遍的なダイナミクスやパターンを明らかにし、従来の自然科学・人文科学の考えを発展させることを目指している。

106 人 工 知 能 31 巻 1 号(2016 年 1 月)「ウェブサイエンス研究会(SIG-WebSci)」 発足

6. 議論

講演後にいただいた質問や議論から、SREの分野は、まだまだサイエンスというより、エンジニアの技芸の上に成り立っているなと感じました。

例えば、以下のようなデータ解析の内容をSREの分野で書かれた文献を今のところ僕は知りません。

  • ウェブシステムの複雑さの定義と解析
  • ウェブシステムの階層構造の変化の解析
  • ウェブシステムの階層ごとの到着分布、処理分布の解析
  • ウェブシステムの自律度合いの定義と解析
  • 異常のパターン分析と体系化

これは、以下の2点が要因としてあると考えています。

  • SREとデータ解析の関心やスキルセットのミスマッチ
  • データ収集が困難
    • 数年前までは、自社システムを自社内で観測してデータを溜め込んでいるだけであったため、多数のウェブシステムの情報をまとめて解析することができなかった

後者については、Mackerelを持っていることは強みなので、うまく活用していきたいと思います。 このようなデータ解析の観点でみると、観測には前述した項目よりもっと先があることを想起させられます。

7. まとめ

ウェブシステムの運用は、ここ10年で自動化が進んでおり、物理的な世界からソフトウェアの世界になってきました。 ウェブシステムは複雑ではあるが、現代のところコンピュータだけで自律した系ではありません。 ウェブシステムという人工物を自然のように振る舞わせ、人間を運用から解放したいというのが最終的な目標です。

参考文献

発表スライド

あとがき

そもそも、ウェブサイエンス研究会に招待していただいたきっかけは、IPSJ-ONE 2017 高度に発達したシステムの異常は神の怒りと見分けがつかない - IPSJ-ONE2017 - ゆううきブログ の登壇にてご一緒した鳴海先生に声をかけていただいたことです。 さすがに、場違いではとも思いました。というのも、僕が実際やっていることは、時系列データベースの開発であったり、10年前から続くウェブシステムの運用効率化などであり、技芸であって科学ではない*21からです。 しかし、はてなシステムを構想するにあたって、地に足がついてなくてもいいから、無理やり未来を考えるいい機会になると捉え、登壇を引き受けさせていただきました。 今回の研究会のテーマは、「自然現象としてのウェブ」ということで、本当に何を話したらよいかわからないテーマで相当苦戦しましたが、その結果、IPSJ-ONE登壇で考えたことの言語化を進められました。*22 途中、妄想のような話もあり、他の分野の専門家からみれば眉をひそめるような表現もあるかもしれませんが、一度考えたことを言語化しておくことでまた次のステップに進めると考えています。

普段はどうしても目の前の課題に熱中しがちで、未来のことを考えようとはなかなか思いません。 概念や思想だけではなかなかそれを取り入れようとは考えず、それを実現するソフトウェアなりハードウェアが目の前にあらわれ使える状態になってはじめて目を向けることになります。 例えば、AWSもDockerもないと仮定して、Immutable Infrastructureの考え方に触れたとしても、到達までの道筋がすぐにはみえないため、諦めて考えないようにしてしまいそうです。

発表後に、研究会の幹事である橋本先生に、技術者はどこまで先を考えているものなのか、と質問をいただきました。 少なくとも、日本のウェブの技術者界隈で、未来の技術ビジョンを設定し、それに進もうとしている様子が外からみえることはなかなかありません。 ペパボ研究所が掲げるなめらかなシステム *23が僕の知る唯一の例です。 Real Worldでは、一歩前に進むだけでも本当に様々な問題が起き、とにかく目の前のことを倒すことが求められるので、とても未来どころではなくなるというのが現状かもしれません。

未来を考えるのは、研究者の場合は当たり前に求められるという印象があります。 しかし、SREの分野では、研究者のコミュニティが他と比べて未発達なようにも思います。 近い分野である情報ネットワークに関しては、日本でも様々な研究会がありますが、僕の知る限りでは、日本では直接的にSREの分野を扱う研究会は存在しないようです。*24

そこで、ウェブシステムアーキテクチャ研究会、(#wsa研)というものを立ち上げようとしています。 第1回は京都開催にもかかわらず、全員発表型で10人以上の参加者が既に集まっています。 今回の講演の準備をするにあたって、我々の分野で未来を議論するための既存の枠組みや土台があまりないことを改めて実感しました。*25 WSA研では、未来を考えるために、現状を体系化し、そこから新規性や有用性を追求していこうと思います。

*1:発表時には機会費用を含めていませんでしたが、機会費用を大幅に増加させて前者2つを削減できるため、この記事では含めました

*2:厳密にはService Level Objective(SLO)))を制約条件として、費用を最小にする最適化問題」((信頼性と費用はトレードオフであり、信頼性を定期的に見直す必要があります。高すぎる信頼性のために想定より費用が最小化できないとなれば、例えば四半期ごとに信頼性目標を下げるといった運用が必要です

*3:[Bet17]では、「サービスのSLOを下回ることなく、変更の速度の最大化を追求する」という表現になっています。今回は、自分自身のメンタルモデルに近い、費用の最小化という表現を選択しました。

*4:これはサービスによって大きく異なります。 これまで運用してきたサービスの肌感覚では、1週間程度。運が良くて1ヶ月程度。

*5:実質OSのプロセスの起動

*6:前述の信頼性を維持し費用を最小化するという話

*7:#wakateinfraの中でも、超常現象などと呼んでいました

*8:ここではMySQLとPostgreSQLを想定

*9:ここでは、VRRPによるクラスタリングを想定

*10:書籍「システムの科学」[her99]の第8章 階層的システム

*11:実際の職種名はWebオペレーションエンジニア

*12:NagiosやZabbixなど

*13:6. 議論 にてさらなる観測の可能性について記述

*14:いわゆる地雷URLなど

*15:[yuu17-3]でも紹介した

*16:異常検知であれば平常時だけを知っておけば問題なさそうだが、その他のアプローチの場合はどうか

*17:書籍[cas17]では、奇しくもフィードバック制御の伝達関数の話が例としてでてくるが、予測モデルを構築することは困難なので、実験しましょうということが書かれているのみでした。

*18:本番環境の負荷の再現が壁になるだろうとは思います。

*19:パラメータチューニングの自動化については、おもしろい例[mir13-2]があります。

*20:おそらく一般的に使われている言葉がソフトウェア工学の世界などにあるかもしれません

*21:John Allspaw、Jesse Robbins編、角 征典訳,ウェブオペレーションーーサイト運用管理の実践テクニック,オライリージャパン より引用

*22:発表自体は、タイムコントロールに久々に大失敗して、途中スライドスキップして残念な感じになってしまいましたが、この記事で補完できればと思います。

*23:研究所なので技術者界隈とは呼ばないかもしれません

*24:海外ではUSENIXのLISAやSREconなどがあります

*25:SRE本は本当に稀有な存在

サーバ「管理」ツールとしてのMackerelの起源

この記事は、SaaSのサーバ監視サービスMackerelを起源を遡り、そこから現在の姿に至った経緯をはてな社内のエンジニアに共有するためのものです。 なお、ここに書かれていることは、Mackerel開発チームの公式見解ではありません。

概要

Mackerelは、もともとは2007年ごろに開発されたはてなの社内のサーバ管理ツールであり、動的なインフラストラクチャに対応するために、現在でいうところのInfrastructure As Codeを目指したものです。 そこから2013年にSaaSのサービスとして開発され、コードベースとアーキテクチャは全く新しくなり、監視機能を備え、サーバ「監視」サービスと呼ばれるようになりました。 しかし、はてな社内では、プログラマブルなAPIを備えたサーバ「管理」サービスとして、Mackerelを中心にしたインフラストラクチャを構築しています。 Mackerelの起源は、サーバ「監視」というよりはむしろサーバ「管理」にあったということをここに書き残します。

社内Mackerelの誕生

社内Mackerelは、はてな前CTOのstanakaさんを中心に2007年ごろに開発が始まりました。 社内Mackerelのコードベースは、mackerel.ioのそれとは全く別のものであり、社内Mackerelにしかない機能もあれば、Mackerelにしかない機能もあります。 しかし、共通する思想はあり、その思想は現代のインフラストラクチャ管理にも通ずるものであると考えています。

はてなでは、2007年前後にXen Hypervisorによるサーバ仮想化技術が導入[1]され、物体としてのサーバに加えて、データとしてのサーバを管理し始め、人手による管理コストが増大しました。 具体的には、サーバの増減に合わせて、人がIPアドレス管理表を更新したり、ホスト名やIPアドレスが記載された各種設定ファイルを更新して回るとといった手間が増えたことを指します。

これらについて、全体のサーバ数が少ないかつ、個数の増減頻度が小さければ、人手による管理にもコストはかかりません。 一方で、クラウド環境のように、データとしてサーバを扱うのであれば、プログラマブルに管理するためのデータベースが必要です。 そこで、社内Mackerelが誕生しました。

このように、社内Mackerelはサーバ監視というより、プログラマブルなインフラストラクチャ管理を目指したツールでした。 実際、社内Mackerelのことをサーバ「監視」ツールではなく、サーバ「管理」ツールと呼んでいました。

社内Mackerelの特徴

構成レジストリ

社内Mackerelの主な管理単位は、「ホスト」であり、ホスト名やIPアドレスはもちろんOSの種別やCPU数、メモリ量などのソフトウェア、ハードウェア情報も含みます。 加えて、ホストは以下の属性情報を持ちます。

  • 「サービス」「ロール」
  • ホストステータス ('working', 'standby', 'maintenance', 'poweroff', 'destroyed')
  • 拠点、ラック、電源、ネットワークなど

これらはビューとして人が参照するだけでなく、REST APIにより各種ツールと連携し、インフラストラクチャ要素の情報を一元化しています。 具体的には、以下のように各種ツールのパラメータを、MackerelのAPI経由で動的取得し、ホスト名やIPアドレスの多重管理を防いでいます。

  • 1: 死活監視ツールの設定ファイルの自動生成[2]
  • 2: 内部DNSのゾーンファイルの自動生成
  • 3: デプロイツールからのデプロイ対象ホストの動的取得
  • 4: 構成管理ツール(Chef)の適用cookbookを対象ホスト名から動的解決

1について、サーバ監視のうち、死活監視についてはNagiosを利用します。同一ロールであれば、同じ監視設定を流用できることと、ホストステータスがworking以外に変更すれば監視を外すといった動的なプラットフォームに適した運用が可能になります。1 2について、ホスト単位のレコード以外に、ロール名ベースのDNSラウンドロビン用FQDNとVIP用FQDNがあり、サービスディスカバリに利用します。 3について、Capistranoでホスト名を静的に設定したところをAPIによりロール名だけ設定しておけば、対象にデプロイできます。ホストステータスをmaintenanceにしておけば、デプロイ対象から外れます。 4について、ホスト名を与えれば、ホストに紐付いたロールから適用するcookbookを自動解決できるようになります。

このようなツールは、CMDB[3]に似ていますが、資産管理機能は含みません。 どちらかといえば、書籍「Infrastructure As Code」[4] 3.4節 構成レジストリに近いものです。 構成レジストリは、インフラストラクチャ要素についての情報集積庫であり、書籍では、構成レジストリと例として、Zookeeper/Consul/etcdや、Chef Server/PuppetDB/Ansible Towerなどが挙げられています。

メトリックの時系列グラフ

社内Mackerelには、前述の構成レジストリ機能に加えて、メトリックのクローリングと、メトリックを時系列グラフ表示する機能があります。 メトリッククローリングはPrometheusなどと同様にPull型のアーキテクチャであり、クローラーがOSの基本メトリックはSNMP、MySQLなどのミドルウェアについてはミドルウェアのプロトコルでメトリックを取得し、RRDtoolに保存します。

社内Mackerelの時系列グラフ機能の実装については、過去の発表資料[5]で詳しく説明しています。

今から振り返ると、メトリックの収集、保存、可視化については、Repiarableにするために、専用のツールに任せ、ビューだけ統合したほうが良かったと考えています。 社内Mackerelの開発開始が2007年より、もう少し後であれば、Collectd[6]で収集し、Graphite[7]に保存するといった選択肢もありました。

メトリックに限らず、当時Nagiosには使いやすいAPIがなく強引な手段で統合している実装をみると、Infrastructure As Codeを志向しようには世の中が追いついていなかった様が伺えます。

SaaSとしてのMackerelへ

2013年にMackerelの開発が始まり、2014年に正式リリースされました。 SaaSとして提供するにあたって、グラフツールではないため、メトリックに着目するより、「ホスト」に着目するといった主要な思想は、社内Mackerelから引き継がれました。他にも以下の要素が引き継がれました。

  • サービス・ロールの概念
  • ホストステータスと監視のon/offとの連動
  • 統合されたホスト管理とメトリックグラフビュー

特にサービス・ロールはMackerelの中心概念であり、社内Mackerelとほとんど同じものです。 私見ですが、サービス・ロールは、人間が決定しなければいけないラベル付けだと考えています。 インフラストラクチャに紐づくラベルは多種多様ですが、大きく分類すると、自動で付与できるものと、それ以外の人が判断して付与するものがあります。 自動で付与できるものは、OS、ハードウェア、ネットワーク、インストールされたミドルウェア、クラスタ内の役割などの情報です。 一方で、どのサービスのホストなのか、どのロールなのかといったことは、人間が最初に決めて付与しなければなりません。自動で決定できるとしても、人間が与えたルールにしたがい決定することが多いと思います。2 このラベルを用いて、リポジトリのディレクトリ構成を管理していることもあります。[8]

以上のように引き継がれた機能がある一方で、ラックや仮想ホストの管理など、クラウド時代にそぐわない機能は削ぎ落とされました。 逆に、死活監視やメトリック監視、外形監視機能は統合されました。

メトリックの収集と時系列グラフについては、SaaSとして提供するために、NAT超えを意識し、Pull型ではなく、Push型のアーキテクチャになっています。 ホストにインストールされたmackerel-agentのリクエストを[9][10]に書いた時系列データベースに格納します。

このように、Mackerelは監視機能をひと通り備えているため、サーバ「監視」サービスと銘打っていますが、その起源は、サーバ「管理」サービスです。 実際、サーバ「管理」ツールとしてのMackerelをうまく活用していただいている例[11]があります。 このブログでも、AnsibleのDynamic Inventoryとの連携[12]やServerspecとの連携[13]など、サーバ「管理」ツールとしてのMackerelをいくつか紹介しています。

その他のサーバ「管理」ツール

社内Mackerelと同じサーバ管理ツールは、他にもあり、ここでは、Collins、Yabitzなどを紹介します。

Collins

Collins[14]はTumblrで開発されているインフラストラクチャ管理ツールです。

Collinsの特徴は、Assetsベースのデータモデルです。Assetsはなんでもよく、事前設定されているものはServer Node、Rack、Switch、Router、Data Centerなどです。 さらに、このAssetsオブジェクトに対して、キーバリュー形式のTagsを付与できます。Tagsはハードウェア情報などユーザが管理できないものはManaged,外部自動化プロセスから動的に設定されるものはAutomated、ユーザによって設定されるものはUnmanagedというように3種類のタイプを持ちます。

このように、Collinsは抽象的なデータ表現により各種インフラストラクチャ要素を管理しており、具体的なデータ表現をもつ社内Mackerelとは対照的です。

Yabitz

Yabitz[15]は、旧ライブドアで開発されたホスト管理アプリケーションです。READMEでは、「ユーザ(多くの場合は企業)が保有するホスト、IPアドレス、データセンタラック、サーバハードウェア、OSなどの情報を管理するためのWebアプリケーション」と説明されています。 機能一覧を見るかぎり、社内Mackerelによく似ています。

いずれのソフトウェアも、死活監視機能やメトリック可視化機能は備えておらず、構成レジストリとしての役割に専念しているという印象です。 他にも、Zabbixのホストインベントリなどがサーバ管理機能にあたると思いますが、Zabbixはあまりに機能が多いので、よく知らずに言及することを控えました。

これからのサーバ「管理」ツール

昨今のインフラストラクチャの進化は激しく、従来のサーバ・ネットワーク機器といった管理単位よりも、さらに動的な要素やそもそもサーバとしての体裁をなしていないインフラストラクチャを管理していく必要があります。

コンテナやマネージドサービスの台頭により、管理の単位はもはやサーバだけではなく、プロセス、クラスタ、Functionなどに置き換わりつつあります。 実際、[9]のアーキテクチャの管理では、Lambda FunctionやDynamoDB Tableなどがホストとして登録されています。

サーバ構築と運用コストが激減し、インフラストラクチャ要素をデータのように扱えるようになってきた結果、マイクロサービスやサーバレスアーキテクチャのような要素同士の関係がより複雑になりやすいアーキテクチャが広まってきました。このようなアーキテクチャのもとでは、1つ1つの要素を管理するというより、関係そのものを管理する必要がでてくると考えます。 ネットワークグラフをTCPコネクションを追跡して可視化する実験[16]に既に取り組んでいました。

さらに、関係性の管理というとまず可視化が思い浮かびます。しかし、人がみて判断するその先として、関係性を表現したグラフ構造をAPIで操作することにより、システムの自動化につなげられないかを考えています。例えば、自動化が難しいレイヤとしてキャパシティプランニングやコストプランニングがあります。書籍「SRE サイトリライアビリティエンジニアリング」[17]の18章「SRE におけるソフトウェアエンジニアリング」にて、サービスの依存関係とパフォーマンスメトリックなどを入力として、キャパシティプランニング計画を自動生成するソフトウェアが紹介されています。 サービスの依存関係を管理するのが普通は大変で、書籍によると執筆時点では人間が設定を書いているように読めます。しかし、関係性のグラフ構造をプログラマブルに操作できるのであれば、プランニングを自動化しやすくなると思います。

参考文献


あとがき

先日、はてなWebオペレーションチームのテックリード - Hatena Developer Blog にて、Mackerelチームとの研究会をやるという話を書きました。 モニタリング研究会では、モニタリングの過去・現在・未来をテーマに、まず過去を知ることから始めており、その一環としてMackerelの源流をまとめました。

Mackerelのサーバ監視以外の「管理」の側面と「管理」と「監視」を統合し何ができるのかという点については、まだ十分に伝えられていないと思っています。 Mackerel本について、mattnさんに書いていただいた書評(Big Sky :: 「Mackerel サーバ監視[実践]入門」を読んだ。)に

これは本書で知ったのですが、どうやら はてな社は Mackerel をホスト管理としても使っている様で、数千いるサーバのロールをうまくラベリングして運用されているとの事でした。

とあり、このような運用手法を伝えていきたいですね。

このように、人の脳やExcelでは管理しきれない未知を明らかにするという観点で、「管理」や「監視」といった概念が組み合わさって、「観測」となり、その先にどのようなインフラストラクチャをつくっていくかをこれからやっていきます。


  1. mackerel2という社内Mackerelの改良版では、タグという概念で、複数のロールをさらに集約し、同じ設定で監視できるようになっています。これは、ロールはMySQL

  2. 例えば、サービスごとにネットワークレンジが決まっているなど。

コスト効率の悪いLambdaアプリケーションの性質に関する考察

概要

Lambdaは100msの実行時間単位でオンデマンドに課金されるため、立ち上げっぱなしのEC2インスタンスよりも、料金が安くなる可能性があることが一般に知られている。 しかし、以下の性質を満たすアプリケーションでは、EC2インスタンス上に構築したケースと比較して、Lambda上に構築したほうがコスト効率が悪くなるのではないかと考察してみた。

  • Lambda functionの実行時間のうち、ネットワークI/O時間が支配的である
  • Lambda functionの実行終了を同期的に待たなければならない
  • 複数のレコードをLambda functionの引数に渡すことができない

Lambdaの基本コスト構造

まず、Lambdaのコスト構造を把握する。 Lambdaの料金表[1]によると、「functionに対する合計リクエスト数」と「functionの合計実行時間」に応じて料金が発生する。

後者の合計実行時間は、静的に割り当てたメモリ量により100ミリ秒単位の価格が異なる。 したがって、実際にコストを試算するときは、前述の2つの料金項目に、「静的割り当てメモリ量」を加えた3つの料金項目があると考えるとよい。 LambdaのPricing Calculator[2]もそうなっている。

LambdaとEC2の時間あたりのランニングコスト比較

LambdaとEC2の時間あたりのランニングコストを比較する。 functionの平均実行時間を料金単位と同等の100msと仮定して、1時間分つまり18000リクエストしたあたりのコストを、代表的なメモリ量別に算出すると以下のようになる。

  • 128MB: $0.015/hour
  • 832MB: $0.056/hour
  • 1536MB: $0.097/hour

このうち、「functionに対する合計リクエスト数」料金については、$0.0072であり支配的ではない。

EC2 ap-northeast-1の料金表[3]から、Lambdaと同じ論理2コア[4]の代表的なインスタンスの1時間あたりのコストを以下のようになる。

  • t2.medium: $0.0608/hour
  • t2.large: $0.1216/hour
  • m4.large: $0.129/hour
  • c4.large: $0.126/hour

LambdaのFAQ[5]にあるように、メモリ割り当て量に対してCPU性能が比例することから、EC2インスタンスとの直接的な比較は難しいが、だいたい同程度かEC2が少々割高であることがわかる。

Lambdaに不向きなアプリケーション性質

アプリケーション例

前述のように、LambdaとEC2のランニングコストにそれほど差はないことを考えると、EC2よりも細かい粒度で消費コンピューティングリソースを制御できるLambdaのほうが有利なケースは、数多くあり得る。

一方で、例えば、次のようなアプリケーションをLambda functionとして実装することを考えてみる。 画像URLを渡すと、画像をフェッチし、特定の画像変換を実行するような画像変換プロキシを考える。 このプロキシに対して、多数のユーザがブラウザからリクエストするようなユースケースを想定する。 レスポンスは同期的に画像を返す必要があるため、以下の図のようにAPI GatewayをLambdaの前段に挟むことになる。 その場合、実際はさらに前段にCDNを挟むことになるだろう。

|-----------------------------------------------------------|
|                                      internet             |
| --> (CDN) --> API Gateway --> Lambda --------> image file |
|                                                           |
|-----------------------------------------------------------|

このようなアプリケーションは、以下の2点でコスト的に不利になる。 まず、Lambda function内でインターネット経由で画像をフェッチするため、function実行時間の料金は嵩みがちになる。 画像フェッチ処理と画像変換処理を並行実行し、実行時間を削減することも難しい。 次に、I/O多重化により、1回のfunction実行において、同時画像フェッチ数を増やし、同じ実行時間料金での処理効率を高めることも難しい。 なぜなら、ユースケース上、同じHTTPリクエストに複数の画像URLを含められず、functionの引数に複数の画像URLを渡せないためだ。

一方、EC2インスタンス上で同じようなアプリケーションを実装すると以下の図のようになる。

|----------------------------------------------------------|
|                                    internet              |
| --> (CDN) --> ALB(or NLB) --> EC2 ----------> image file |
|                                                          |
|----------------------------------------------------------|

EC2実装では、インスタンス上でWebサーバが動作する。Lambda実装とは異なり、複数のリクエストを1つのインスタンスで並行して受け付け、I/O多重化できる。 もちろん、1スレッドで動作するシリアルモデルなWebサーバであれば、同時に1つのリクエストしか受け付けられないが、古典的なWebサーバであっても並行モデルを採用していることがほとんどである。5 したがって、EC2実装(Webサーバ実装)では、同じランニングコストに対して、複数の画像をフェッチできることになり、Lambda実装と比較してコスト効率がよい。

アプリケーション例のコスト試算例

実際、コストがどの程度になるのかという感覚を掴むために、仮のパラメータで試算をしてみる。

平均実行時間 1000ms、平均リクエスト数 1000req/sとなるケースを考える。 一番小さいメモリ割り当て量である128MBのとき、月額は約$6000となる。 実行時間を小さくするために、メモリ割り当て量をN倍に増やしCPU性能を大きく設定すると、画像変換処理は速くなるが、ネットワークI/O部分の時間はかわらないため、実行時間は1/Nにはならない。 平均リクエスト数が10倍であれば、コストは10倍になり、平均リクエスト数が1/10であればコストも1/10になる。

この計算例を軸に、見覚えのあるアプリケーションの負荷パラメータをあてはめて、比例計算すると、だいたいのコスト感覚をつかめると思う。

考察

以上の例から一般化し、コスト観点でLambdaに不向きなアプリケーション性質は以下のようになるという考察をしてみた。

  • 1: Lambda functionの実行時間のうち、ネットワークI/O時間が支配的である
  • 2: Lambda functionの実行終了を同期的に待たなければならない
  • 3: 複数のレコードをLambda functionの引数に渡すことができない

3について、単にバルク処理できるエンドポイントを生やすだけで解決するのであれば、問題にならない。 1と3について、ネットワークI/O時間が支配的であっても、1レコードの処理をI/O多重化し、実行時間を小さくできるのであれば問題にならない。 さらに、2.と3.については、非同期でよいということであれば、Kinesis Streamsのようなキューを挟めば、Lambda function側でレコードを複数同時に処理し、I/O多重化できる。

しかし、コスト的に不利な性質のアプリケーションであっても、Lambdaの採用により初期構築の手間とその後の運用の手間を大幅に削減しやすいため、実際にコストを試算してみて採用可否を判断することが望ましい。 前述のLambda実装では、CDNのキャッシュヒット率を向上させることで解決できるなど、アーキテクチャ全体でコストを抑えれば問題ないケースもある。

LambdaのようなFaaSにおいて、実時間ではなく、CPU時間で課金するモードがあればおもしろいかもしれない。

今回の話は、Lambdaアーキテクチャの問題ではなく、Lambdaのコストモデルの問題といえる。 EC2上でLambdaのようなものを自前で運用したとして、同じインスタンス上に複数のfunctionコンテナが動作する状態と、マルチプロセスモデルのWebサーバが動作している状態とでは、ランニングコストあたりの集積度という観点ではさほど変わらない。

あとがき

このような性質をもつアプリケーションが現実にどれくらいあるかわからないが、実際、Lambdaでコスト試算してみると高くなったという話を社内で聞いたので、少し一般化してこのような考察をしてみた。 これを社内wikiで共有して人気だったので、社外共有することにした。 最近は、はてなWebオペレーションチームのテックリード - Hatena Developer Blog にあるようにアーキテクチャ相談をしているため、その活動の一環ということになる。

参考文献