時系列データベースという概念をクラウドの技で再構築する

サーバ監視サービスMackerelにおいて開発中の、高解像度・長期間のサーバメトリック収集を実現するための新しい時系列データベースDiamondを紹介します。具体的には、Amazon ElastiCache、Amazon DynamoDB、Amazon S3を組み合わせ、Amazon Kinesis StreamsとAWS Lambdaによりコンポーネント間を接続した、階層構造のデータストアアーキテクチャの設計と実装を解説します。

2018/06/05 追記: この記事の内容をWSA研#2でより一般的なアーキテクチャレベルでの貢献として書き直しました。 サーバレス時代におけるヘテロジニアス時系列データベースアーキテクチャ - ゆううきブログ

はじめに

先日開催されたAWS Summit Tokyo 2017にて、「時系列データベースという概念をクラウドの技で再構築する」というタイトルで登壇しました。 この記事では、講演した内容に加えて、時間の限られた講演では触れられなかった内容を併せて議論します。

タイトルに時系列データベースとあるので、時系列データベースの話をもちろん書きます。しかし、AWS Summitでの発表ベースの記事なので、「AWS」を用いたシステム設計という切り口で話を進めます。 具体的には、Write-Intensive Application(書き込み要求が支配的となるアプリケーション)をAWS上で設計するための議論の土台になればと考えています。 時系列データベースは比較的単純なデータモデルを扱うため、よいモデルケースになるのではないかと思います。 時系列データベースとしての機能比較や実装の詳細についてはまた別の機会に紹介します。

背景

Mackerelでは、成長しつづけるサービスのスケーラビリティの確保と、データ量とI/Oがひと桁またはふた桁増加するような機能実現が求められています。

Mackerelの重要な機能のひとつに、メトリックのグラフ化機能があります。 開発中の新時系列データベースは、このグラフ化機能について、より高解像度でより長期間のメトリック収集と保持を実現しようとしています。 さらに、1つのグラフに1000以上のメトリックが含まれている状況でも高速に表示できるようにするなどの性能向上や、それ以外に、メトリックの異常検知など将来的な機能追加に対するワークロードに対して対応できるようにしたいと考えています。

Mackerelにおけるメトリックの収集とグラフ化の仕組みの概要は、以下の図のようになっており、前述の機能要求にとって、時系列データベースというコンポーネントが重要になってきます。

時系列データベースとはそもそも何でしょうか。時系列データベースとは、時系列データを扱うことに特化したデータベースであり、サーバモニタリングやIoTの文脈でのセンサーデータの収集のために使われます。有名な実装として、OpenTSDBInfluxDBGraphite などがあります。地味にみえて、多くの実装が存在し、学術研究論文になっているものもあります。id:rrreeeyyy さんの 時系列データベースに関する基礎知識と時系列データの符号化方式について - クックパッド開発者ブログ が詳しいので、一読することを薦めます。

Mackerelで運用している時系列データベースについては、Mackerelを支える時系列データベース技術 - ゆううきブログ の記事にまとめています。2年前の記事ですが、現状でも概ねこの通りの構成で運用しています。1台あたりピーク時で150k write IOPSを叩き出しており、サーバモニタリング向け時系列データベースの探究 / The study of time-series database for server monitoring - Speaker Deck で紹介したようにパッチをあててパフォーマンスを改善してきました。

ところが、MackerelのGraphite運用には、以下の4つの問題を抱えています。

まず、スケールアウトのための運用コストが大きいという問題です。書き込みI/Oのスケールアウト手法として、水平分割(sharding)が一般的です。Graphite自体にはconsistent-hashingにより、水平分割する仕組みがあります。しかし、シャードの増減により、ハッシュキーとノードのマッピングが変更されたときに、データを再配置するための仕組みはGraphite本体には実装されていないため、運用でカバーする必要があります。

次の問題は、データ保持期間を増やすと金銭的なコストが激増するというものです。前述したようにスケールアウトのための運用コストが大きいことから、書き込みI/Oをスケールアップするために、NANDフラッシュメモリを利用しています。非常に性能が高い一方で高価なハードウェアなので、容量単価が大きいという特徴があります。 したがって、データ保持期間を増やすと、ディスク上のデータ量が増加し、安価なハードウェアにのせることに比べてお金がかかることになります。 一般の解決策は、圧縮してディスクに格納するか、既に書き込まれたデータを低速で容量単価の小さいストレージに移動するような仕組みにすることです。 前者の圧縮については、1で紹介されている差分符号化やXOR符号化のテクニックをGraphiteに実装すれば、実現できそうではあります。しかし、これらのエンコーディングにより、ランダムアクセスできなくなるため、Graphiteのラウンドロビンデータベース構造とうまく噛み合うかがわからないところです。圧縮は基本的に、CPU負荷とトレードオフになるため、CPU負荷がボトルネックとなる可能性もあります。 後者のデータ移動については、Graphiteのラウンドロビンデータベースの、古いデータを新しいデータで上書きしていくという性質のため、別のストレージに効率よくデータを移動させることが難しく、データ構造を大きく変更する必要があります。

3つ目の問題は、データロスト耐性が低く、フル同期のための運用コストが大きいことです。アプリケーションから書き込みすると、Graphiteのメモリ上のキューにデータが非同期に書き込まれるため、サーバダウンによりキューの中身をロストしてしまいます。デュアルライトにより、別のサーバには書き込まれているので、そちらからデータを同期するなど、運用でカバーしなければなりません。これを解決するには、GraphiteにWAL(Write Ahead Log)を実装するなど、大きな変更を強いられます。

最後に、新規にメトリックが投稿されたときに、未来の領域をファイル作成時に確保するので、ディスク使用効率が低いという問題があります。これは2つめの問題と関連します。なぜこのようなデータ構造になっているかは http://graphite.readthedocs.io/en/latest/whisper.html?highlight=rollup#disk-space-efficiency に書かれています。このデータ構造は、コンテナのようなImmutable Infrastructureの概念と相性が悪く、非効率です。

これらの4つの現状の問題点と、冒頭に書いたような新しい機能要求を考慮すると、根本的なアーキテクチャの刷新が必要だと考えました。

既存の時系列データベース

まず、既存の時系列データベースの調査から始めました。Andreas Baderらのサーベイ論文2Open Source Time Series DB Comparison3にオープンソースの時系列データベース実装がまとめられています。

時系列データベースの概念

前述のサーベイ論文[^1]では、時系列データベースの定義は、以下のような性質を満たすDBMSのこととされています。

  • タイムスタンプ、値、属性(メトリック名など)で構成されるデータの行を格納できる
  • 時系列としてグループ化された複数の行を格納できる
  • データ行に対してクエリを発行できる
  • タイムスタンプまたは時間範囲をクエリに含められる

この定義を満たすものを実装するのはさほど難しくありません。しかし、実際には、分散/クラスタリング、Function、Rollup Aggregation(自動丸め)、タグ、複数のデータ解像度、クエリ言語などの時系列データベースにまつわる機能要求があります。 特に、今回のようなスケーラビリティを確保する目的であれば、分散/クラスタリングが重要になってきます。

時系列データベースの分類

時系列データベースのOSS実装は大きく2つの分類があると考えています。それは、他の汎用DBMS上に実装されたもの(TSDB on DBMS)と、時系列データベースに最適化したストレージエンジンをもつもの(TSDB standalone)です。 前者にあたるものは、例えば、OpenTSDBやKairosDBなどがあります。一方、後者にあたるものは、GraphiteやInfluxDB、Prometheusなどがあります。 前者のDBMSとして、HBase、Cassandra、Riak、ElasticsearchなどのいわゆるNoSQLが使用されます。もちろん、TimescaleDBのようにRDBMSであるPostgreSQLをベースにした実装も存在します。前述の時系列データベースとしての定義を満たすだけなら、ACID保証が必要ないので、NoSQLを利用するケースが多いようです。

時系列データベースを実装する側の視点でみると、TSDB on DBMSは、分散/クラスタリング機構を自前で実装せずにすむため、実装が楽というメリットがあります。一方で、TSDB standalineは分散/クラスタリング機構も実装しなければならないというデメリットがありますが、TSDB on DBMSと比較して時系列データベースに最適化できるというメリットがあります。

時系列データベースを運用する側の視点でみると、たいていのTSDB on DBMSはCassandraなどの分散システムとしての運用コストが高いといわれるDBMSを利用しており、一方で、TSDB standaloneは分散システムとしての信頼性を測るための実績が少ないといえます。実際には、製品ごとに細かくメリット・デメリットがありますが、大雑把にこのように認識しています。

さらに、Mackerelで採用するという視点でみると、既存の時系列データベースをそのまま採用するデメリットとして、Rollup Aggregationに対応していないものや、インタフェースが大きく変わるので変更コストがある、Mackerelの現在または将来のワークロードに対してスケールしない可能性があります。

新時系列データベースDiamondのアーキテクチャ

方針

調査の内容を踏まえて、既存の時系列データベースを採用せずに、Amazon DynamoDBなどのAWSマネージドサービスを採用し、マネージドサービス上に独自の時系列データベースアプリケーションを実装するという方針にしました。 マネージドサービスを採用したのは、時系列データベースの分散/クラスタリング機構に必ずついてまわるデータベースの検証・運用コストを削減するためです。はてなでは、特定ベンダーのロックインをなるべく避けるという技術選択方針がありますが、今回は、Mackerelの成長速度や将来の機能要求を考慮して、ある程度のロックインを受け入れることにしました。 独自に、TSDB on DBMSにあたるものを開発することにしたのは、ひとえにMackerelの要求を満たす実装がないか、要求を満たすかどうかの検証に時間がかかるためです。AWSマネージドサービス採用によりデータベースの検証/運用コストを削減できるので、その代わりの開発工数を確保できると考えました。

この大方針に沿って、Graphite運用の4つの問題点を解決できるか考えます。

まず、負荷分散の運用コストの解決です。前述したようにDynamoDBなどのフルマネージドサービスの利用により、運用コストを削減できます。水平分割のためのキーの設計を間違えなければ、お金を払った分だけI/Oスループットがスケールするので、検証も比較的楽になります。 ところが、DynamoDBのI/O課金が高いため、今のMackerelのI/Oを工夫せずにDynamoDBに向けるとインフラコストが大きく増加します。 したがって、個々のデータポイントを別々に書き込むのではなくまとめて書き込み、I/Oコストを下げる必要があります。 最終的には、前段にElastiCache(Redis)を配置し、ライトバックキャッシュ(講演ではバッファと呼んだ)として利用することにしました。

次に、データ保持期間についての解決です。DynamoDBのディスク容量課金は感覚的には安く感じましたが、1分解像度のデータを年単位で保持しようとすると、そこそこのコストがかかります。 S3のコストはスタンダードストレージでもDynamoDBの1/10程度に収まるので、ここでコストを浮かせておけば、他の機能拡充にコストをあてられるため、なるべくS3を使いたいと考えました。 とはいえ、S3のレイテンシはDynamoDBに比べて1桁以上大きいかつ、DynamoDBよりも内部的なパーティションあたりのスループットが低い可能性があります(要確認 リクエスト率およびリクエストパフォーマンスに関する留意事項 - Amazon Simple Storage Service)。 Mackerelの場合、古い高解像度データはほとんど参照されないという参照局所性があるので、参照回数が小さいデータの表示は多少遅くてもよいという性質があります。 そこで、この性質を利用し、ホットデータをDynamoDB、コールドデータをS3に配置することでコスト最適化することを考えました。

この時点で既に、階層型データストアアーキテクチャになることが決定しています。

3つ目に、データロスト耐性の向上です。これは簡単で、メモリ上のキューではなく、ディスク書き込みするメッセージキューを採用することです。OSSなら、KafkaやRabbitMQなどがこれにあたり、AWSでは、Amazon Kinesis Streamsになります。内部的な実装としてはキューではないと思いますが、キューのように利用できます。Kinesis Streamsは直近の24時間分のレコードをディスクに保存し、投稿したレコードをLambda functionの引数に渡すことも簡単です。Kafkaほどレイテンシが低いわけではないそうですが、どのみちMackerelのデータポイントはインターネットごしに投稿されるので、もともとユーザに反映されるまのでレイテンシが大きいので、無視できる程度のレイテンシの差だと考えました。キューというよりは、Using logs to build a solid data infrastructure (or: why dual writes are a bad idea) - Confluentに書かれているように、アプリケーションレベルのWAL(Write Ahead Log)を前段に配置していると捉えてもよいかもしれません。

最後に、ディスク使用効率の向上です。容量問題はS3の利用で解決できるので、ラウンドロビンデータベース構造にする必要がなく、未来の領域を確保することはしません。 圧縮や符号化については、RedisやDynamoDB上でレコード単位で圧縮しようとすると、レコードに対するデータポイントの更新時に、レコード内のデータを全て読み込んでからデータポイントを更新し、レコードの内容を差し替えるということをしなければならないため、余分なread I/Oとネットワーク帯域を圧迫する可能性があります。OSのファイルのようなseekできるストレージであれば、必要な分だけ読み出せるので、効率が良いと考えます。(しかし、これを書きながら、データサイズが小さくなっているのだから、ネットワーク帯域はさほど気にならない可能性もあるということに思いあたりました。)

さらに、時系列データを読み出すコンポーネントをMicroservicesとして開発しています。Graphite互換のインタフェースを実装し、新システム移行時のインタフェース変更コストを小さくしています。1つのクエリに1000以上のメトリックが含まれることがあるため、各メトリックのタスクを並行処理できるように、軽量スレッドでI/O多重化できるGo言語を実装言語として選択しました。

設計

前節の方針を元に、新時系列データベースのアーキテクチャの設計の概要を以下にまとめます。

  • 金銭コスト最適化のために参照局所性を利用する。データ参照頻度に応じて適切なデータストアへデータを移動させる
    • ホットデータをDynamoDB、コールドデータをS3に配置
    • ライトバックキャッシュのストレージとしてElastiCache(Redis)を利用
    • DynamoDBのTTL機能によりシームレスにデータ移動
  • Kinesis Streamsに対して先行ログ書き込みし、データロスト耐性と耐障害性の向上させる
  • Graphite互換インタフェースにより、各ストレージからデータ取得するWebアプリケーションを実装する

アーキテクチャ図を以下に示します。

このように複数のデータストアを組み合わせる場合、データをシンプルな手法で移動させるためのアイデアが必要です。 2017年2月にDynamoDBがTTLサポートされました。 TTLがexpireしたレコードをDynamoDB Triggers経由でLambda functionに渡すことができるため、簡単に古いデータをS3へ配置することができます。

この機能がリリースされたとき、ちょうどデータ移動の仕組みに困難さを感じていたところでした。当時は、タイムウィンドウごとにDynamoDBのテーブルを用意して、古いタイムウィンドウテーブルをテーブルごとDataPipelineによりS3にエクスポートすることを考えていました。いわゆる、MySQLで日時カラムに対してパーティションを切り、古いパーティションをパーティションごとDROPするという手法に近いと思います。 テーブルファイルがS3に配置されても、巨大なテーブルファイルに対してクエリするのは現実的ではないため、テーブルファイルをレコード単位に分割してS3に保存し直すような手間のかかる処理が必要でした。 テーブル単位による管理を強いられるため、アイテム単位で細かくデータ配置を制御したくなったときに、どうしようもなくなるという問題もありました。

古くなったデータを別のストレージに移動したいというのは一般的な要求なので、データベースのTTLとイベント通知というサーバーレスアーキテクチャらしい仕組みは、汎用的に利用できるアーキテクチャだと考えています。(2018/05/04追記: TimeFuzeアーキテクチャ構想 - 処理とデータとタイマーを一体化したデータパイプライン - ゆううきブログ として一般化して提案しました。)

実装

実装についての詳細は、スライドを参照してください。時系列データベース固有の話になります。Redis/DynamoDB上のスキーマ設計、Redisによるライトバックキャッシュ、Graphite互換アプリケーションのI/O多重化について簡単に紹介しています。

考察

Write-Intensive Applicationとして、例えばログ収集や、チャットメッセージングなどがあります。ログやチャットメッセージと違い、メトリックのデータポイントは固定長のデータなので、データ構造を最適化しやすいという特徴があります。したがって、可変なデータを書き込むアプリケーションの場合、時系列データベースでは考えなくてよかったようなデータ構造の工夫が必要かもしれません。

サービスの仕様変更により、データ構造を変更したくなったとき、3箇所にデータを保持していると、それぞれ変更を加えなければいけないというデメリットがあります。これについては、場合によっては、今あるデータ構造に追加の変更をするよりは、前段のKinesis Streamsから別のストレージに最適な構造で書き込むことも考えられます。

3層構造のデータストアアーキテクチャを提案しましたが、必ずしも3層にする必要はないと思います。ディスク使用が少なければElastiCacheとDynamoDB、書き込みI/Oが少なければ、DynamoDBとS3、readレイテンシを気にしなければ、RedisとS3というように、2層で対応できることもあるでしょう。 ちょうど手元のマシンでRAM+SSD+外部ストレージで大抵のことが事足りるように、3層あれば多くの状況でコスト最適化できると考えています。

DynamoDBにはDAXというライトスルーキャッシュが最近実装されました。もし、DAXにライトバックキャッシュが実装されれば、DiamondアーキテクチャのうちRedisの層は不要になるかもしれません。

その他、運用の観点で、スナップショットバックアップについては、ElastiCache自体にバックアップ機構があり、DynamoDBでは前述のDataPipelineによるS3への定期バックアップが可能であり、S3上のファイルは一旦作成されたら基本的に更新しないので、スナップショットバックアップはそれほど必要ないと考えています。

さらに、Lambda functionの実装にバグがあるとデータロストの危険性がないかについては、前段のKinesis Streamsに24時間(追加コストで1週間)データ保持されるので、原理上はそこからリカバリできるはずです。functionの実行がエラーになるケースでは、functionの実行がリトライされます。ただしこれには、functionの実行がべき等である必要があります。Diamondの場合、RedisとDynamoDBのデータ構造がタイムスタンプをキーとしたハッシュマップになっているので、データポイントの書き込みはべき等になっています。

Diamondアーキテクチャのデメリットとして、構成要素が多いことが挙げられます。Kinesis streamsもあわせると、4つのデータストアを併用することになります。一般に構成要素の数が増加すると運用コストも増加しますが、マネージドサービスの利用やCloudFormationのようなInfrastructure As Codeの利用により、運用・管理コストを抑えられると考えています。 しかし、Diamond自体のモニタリングは複雑になるため、モニタリング手法もあわせて提案する必要があると考えています。

資料

プレゼンテーション資料

参考文献

あとがき

「時系列データベースという概念をクラウドの技で再構築する」というタイトルは、少年ジャンプで連載中の食戟のソーマの第115話で、主人公 幸平創真の「親子丼という概念をフレンチの技で再構築する」という台詞から拝借したものです。 主人公は定食屋のせがれで、定食屋としての技術の限界を超えるため、フランス料理の技術を学び、日本の庶民の料理である親子丼を抽象化して、フレンチの技を用いて再構成するというお話になっています。 自分では、この話をとても気に入っていて、今回、ちょうど同じように、時系列データベースの構成要素を取り出し、マネージドサービスやサーバレスアーキテクチャなどのクラウドならではの技術を用いて再構築していると感じ、このタイトルをつけました。

今回話をしたかったのは、単に使っているOSSを列挙するようなものや込み入った実装の話ではなく、アーキテクチャの話です。 最近、アーキテクチャと実装の違いについて考えているのですが、まだあまりよい答えをもっていません。少なくともいえるのは、アーキテクチャには汎用性があり、実装するソフトウェアだけでなく他のソフトウェアにも通用するなにかがあるということです。 アーキテクチャの観点では、Webアプリケーションは参照局所性にあわせて複数のデータストアを併用するのは昨今では当たり前なので、今回のようなTTL + Lambda Functionのようにそこにもっとサーバレスというかイベント駆動な考え方を持ち込み、体系化できないかということを考えていたりします。

Mackerelでは、時系列データベース以外にも、おもしろいソフトウェアアーキテクチャを実現できるチャンスがまだまだたくさんあります。僕の場合は、最近は機械学習を支える効率のよいシステムやグラフDBのアーキテクチャに興味があります。 はてなでは、アーキテクチャを設計・実装し、本番投入し、運用まで持っていくことに興味があるエンジニアを募集しています。

また、今年のはてなインターンでは、Mackerelやはてなのインフラストラクチャを支えるシステムを開発できる、「大規模システムコース」と「クラウドサーバ管理システムコース」があります。 はてなサマーインターン2017

追記


  1. 時系列データベースに関する基礎知識と時系列データの符号化方式について - クックパッド開発者ブログ

  2. Andreas Bader, Oliver Kopp, Michael Falkenthal. “Survey and Comparison of Open Source time Series Databases”. In proceedings of BTW 2017.

  3. Open Source Time Series DB Comparison

matsumotoryさんの博士学位論文公聴会に参加し、見て聞いて考えたこと

先日、京都大学で開かれた id:matsumoto_r さんの博士学位論文公聴会に参加してきた。

博士学位論文公聴会というものを、そもそも僕はあまりよく知らなかった。とりあえず、博士の学位を取得するための最後のステップと認識している。厳密には、この後にもいろいろあるらしいのだが、その日のうちに学位取得の合否が決定され、晴れてmatsumotoryさんが合格された様子をその場でみることができた。本当におめでとうございます。

発表内容について

博士論文や当日の発表スライドはそのうちmatsumotoryさんが公開されると思う。発表内容自体は、当たり前だけど、以下の予備審査のスライドとほぼ同等のものだった。

Webサーバの高集積マルチテナントアーキテクチャに関する研究 / Studies on Highly Integrated Multi-Tenant Architecture for Web Servers // Speaker Deck

matsumotoryさんの研究内容のストーリー全体を俯瞰する発表を聴くのは、今回が初めてだった。 これまで、個々の要素、例えば、mod_mruby/ngx_mrubyやmod_process_securityなどは多少理解していたつもりだったものの、その背景には大きなストーリーがあり、それぞれの要素がどのように配置されているのかといった論理構造が浮かび上がってくるようだった。 同じITシステムの運用にたずさわっていても異なるコンテキストをもつ僕が、自然と論理構成を理解できて、その後の質疑応答の内容もほぼすべて理解できた。これは大きなことだと思う。

発表の冒頭にもあるように、対象となるシステムは、事業者がアプリケーションを制御できない状況設定におけるアーキテクチャの提案となっている。僕が普段相手にしているシステムは、事業者がアプリケーションを制御するのが当たり前になっている。自社で開発しているサービスをデプロイし、運用する事業形態だ。

これは僕にとって発表を聴く直接のメリットがないようにみえるが、その逆で、適応領域が異なるほうが、むしろ抽象的なアーキテクチャを議論するヒントになりやすい。 実際、これのおかげで、この前のIPSJ-ONEにおける発表では、matsumotoryさんが提唱されているなめらかなシステムとの対比から様々なヒントを掴み、自分の思考の枠組みを一歩超えるような体験ができた。

さらに、matsumotoryさんの貢献の一つである「Webサーバの高集積マルチテナント方式の基本概念と課題を体系的に整理」をみて、ITシステムの運用というのは、そもそも体系からつくらないといけない分野であることを再認識できた。 そして、自分が過去に書いた以下の記事では、事業者が制御可能な前提でのシステム運用の体系を作りたかったのではないかと思うようになってきた。

僕がこのようなことを考えていることそれ自体が、matsumotoryさんの貢献でもある気がする。

質疑応答について

質疑応答は1時間弱くらい続いていたかもしれない。あのmatsumotoryさんが若干怯えた様子で、応答されていたのをみて、博士課程の予備審査にいってきました - 人間とウェブの未来 に書かれていることを思い出した。

入学資格審査や中間発表では、研究の突っ込んだ話は当然のこと、「アカデミックはどこにあるのか」「普遍的な学術的貢献はなんなのか」「工夫なのかアイデアなのか」といったように非常に抽象度が高く、汎用性・一般性に基づいた質疑が飛び交います。

博士課程の予備審査にいってきました - 人間とウェブの未来

特にセキュリティの観点で、厳しい質問があった。それ以外にも、高集積というアイデアはWebホスティング以外にも適用できないか、これからのLinuxに必要な機能はなにかといった、抽象的な質問が飛び交っていた。

参加するからにはどうにか自分もそのレベルで、なにか今後のmatsumotoryさんの研究活動に貢献できるような質問をしようと久々に発表を聴きながら頭をひねって、以下のような質問をした。

  • 第2章と第3章で提案されているアーキテクチャについて、chroot以外にLinux Namespacesを用いてよりセキュアなシステムにすることは可能か
  • Linuxのアーキテクチャに依存したアーキテクチャならば、Linux自体のアーキテクチャの限界に引きずられた結果、提案されている高集積マルチテナントアーキテクチャの息が短くなることはないか。他のOS前提でのアーキテクチャのほうが、高集積マルチテナントに有利になることはないか。

これらの質問は、実装よりアーキテクチャで解決するという最近の自分の関心事から端を発している。 また、最近社内で輪読している詳解システム・パフォーマンスにて、Solarisが登場する場面が多く、普段さわっている実装がどこまでLinux依存なのかといったことを考えていたためである。

この文脈では、スレッド単位での制御がOSレベルで可能なアーキテクチャであればよくて、カーネル内部でのプロセス表現として知られているtask_struct構造体は、実体としてはスレッドを表現しているはず(要確認)なので、Linuxのアーキテクチャの限界にはおそらくあたらないのではということを軽くあとで会話した。この話はちょうど、輪読会でも議論した。詳解システム・パフォーマンス 3章「オペレーティングシステム」メモ - ゆううきメモ

ところで、その日のmatsumotoryさんのツイートによると僕が強烈な質問をしたことになっていて、おもしろかった。優しく見守った結果のはずなんですよ。

アウトプットについて

エンジニアのアウトプットとは何なのかということを最近というかずっと考えていて、今回、公聴会に参加して、一つの考えがまとまった。

普段からウェブエンジニアのブログ、プレゼン、OSSをみる機会は非常に多いのだけれど、「知識」と「経験」に関するアウトプットに恵まれている一方で、「思考」に基づいたアウトプットが少ないのではないかと感じている。つまり、「知ったこと」と「やったこと」そのもののブログやプレゼンは多いのだけど、自分で問いを立てて「考えたこと」を表現することがあまり重視されない傾向にあるのかもしれない。これは単に数あるアウトプットから僕がその人の考えを読み取れていないだけという可能性もある。

問いを立てて思考した結果は、なんらかの新規性を持っているように思う。 例えば自分の身の回りだと、mizzyさんのServerspecや、同僚であるitchynyさんのsjsp Mackerelにおけるフロントエンドのパフォーマンス改善の取り組み - Hatena Developer Blog であったり、はてなで採用されている実装のないフレームワーク ぼくのかんがえたさいきょうのうぇぶあぷりけーしょんふれーむわーく - YAPC Asia 2011 であったりする。 これらに比べればずっと小さな成果だけれども、自分の場合だと Dockerとchrootを組み合わせたシンプルなコンテナデプロイツール - ゆううきブログ がこれに該当する。

今回の公聴会では、知識と経験をベースに思考を重ねたアウトプットをストーリーとしてみることができた。 そして、このようなアウトプットこそがエンジニアを大きく成長させるようなアウトプットだと確信するようになった。

自分で考えたことというのは、後ろ盾がない状態なので、人にみせるには勇気がいる。 しかし、小さな成果でもよいから、それを乗り越えて、その人らしいアウトプットをみれるとうれしくなる。 これから、自分もこういったアウトプットを志していきたい。

あとがき

matsumotoryさんのことは、自分のブクマを振り返ってみると、5年ほど前から存じ上げていたようだった。 5年前というのはちょうど、人間とウェブの未来 - Linuxエンジニアを辞めて大学院に入学しました の記事にあるように、大きな挑戦をされた年だった。

一方そのころの僕は、はてなでアルバイトし始め、ほそぼそとブログを書き始めた年で、その年の振り返りに

最後のやつ,いつも読んでるブログの,"人間とウェブの未来"の中の人にブクマしてもらえて,おおー ってなった. 忘年した2012年の記憶を掘り起こして忘年意味ないみたいな感じになった - ゆううきブログ

というようなことを書いて喜んでいたようだった。

その翌年は、大学院を中退し、そのままはてなに入社したのだけれども、そのときも、以下のような言葉をかけていただいたのをよく覚えている。

大学院の修了に失敗し、新卒入社にも失敗しました - ゆううきブログ

こんなに怒られるような寛容でない場所は辞めても良いと思う。ブログを見る限りこの方を必要とする企業は沢山あると思うので頑張って欲しい。

2013/11/21 14:05
(しかし、この記事は雑すぎて、新卒入社(4月入社)には失敗しただけではてなには入社しているということを伝える気のない書き方だった。このときは、会社の印象が悪化するのを気にして、はてなっていう単語を出さないように勝手に気遣った記憶がある。)

そこから気づけば、レンサバの常識を覆す「なめらかなシステム」に挑む──運用技術を学術研究して実際のサービスへ適用 - はてなニュース のように一緒にインタビューを受けたり、IPSJ-ONEでバトンを渡していただいたりした 高度に発達したシステムの異常は神の怒りと見分けがつかない - IPSJ-ONE2017 - ゆううきブログ

振り返ってみると、同じ組織に属したことはないし、直接お会いした機会はこれまでせいぜい6,7回程度しかない。 親炙と私淑という言葉を最近知ったのだけど、もともと私淑していたところを徐々に親炙するようになった、よい意味でインターネット的な関係といえるかもしれない。

以上のような背景のもとに、matsumotoryさんの一つの挑戦の集大成をみることができて、なんだかうれしくなってこの日記を書いた。

高度に発達したシステムの異常は神の怒りと見分けがつかない - IPSJ-ONE2017

名古屋大学で開催されたIPSJ-ONE2017 で登壇しました。 IPSJ-ONEというのは、情報処理学会の各研究会から選ばれた日本の若手トップ研究者17人が集まり、自身の研究を高校生でもわかるように発表するイベントです。 1000人ぐらい入る講堂で、しかもニコニコ生放送で配信されるというとても大掛かりなイベントです。

ちなみに、昨年は、同じ研究会からの推薦で、 id:matsumoto_r (matsumotory) さんが登壇されています。 IPSJ-ONE 2016で登壇してきた - 確実に時代は変わってきている #ipsjone - 人間とウェブの未来

発表

「高度に発達したシステムの異常は神の怒りと見分けがつかない」という、一見何の話かわからないやばそうな話なんですが、大真面目に話してきました。

スライドを以下に公開しています。ただ、スライドだと何の話をしているかおそらくわからないので、ニコ生のタイムシフト試聴でたぶん一週間くらいは動画をみれるようです。 http://live.nicovideo.jp/watch/lv289955409#6:40:12 (その後におそらくアーカイブされるはず?)

IPSJ-ONEの趣旨として、登壇者個人の成果や考えを表に出すことを求められており、実際には会社やチームでやっていることの中で、僕個人がやっていることについて話をしたつもりです。

5分の発表なので、10秒レベルで無駄を削って、エッセンスのみを抽出しました。特に、一般の方がわかるような内容であることに最重視しており、専門用語を使わないように徹底しました。

内容と補足

補足を追加した内容を以下に書き留めておきます。

インターネットのシステムは、24時間365日動き続けることが求められている一方で、人手による運用でカバーしている部分がたくさんあります。 これをどうにかしたいと思って、全自動化へ向けて頑張るんですが、全然うまくいきません。 なぜうまくいかないのか。それは、自動化に対する恐れがあると考えています。 実際に現場では、このオペレーションを自動化したいけど、本番にいれるのはかなり検証つまないと怖いよね、というような話を頻繁にしています。 もちろん、開発工数がとれないとか別の次元の話もありますが、怖さを取り除くまでに手間がかかると言い換えることもできます。

なぜそんなに恐れるのか。今のインターネットのシステムは、極めて高度に発達しており、生物/自然を連想するような複雑な系をなしています。 この自然は普段はおとなしいですが、時として天災のような異常となって我々人間に襲いかかってきます。 情報システムの場合は、システム障害ですね。 このような異常が発生するために、人は未知に対する恐れを抱いてしまいます。 これに似た構造があり、古来より人々は、例えば神話のような世界で、未知の異常を神の怒りと表現していました。 実際には、雷や地震といった災害になるかと思いますが、今ではこれらの現象が神様の仕業だと考えることは少ないように思います。 そのギャップを埋めたものは何かと考えたときに、思い浮かんだのが、「観測」でした。

「観測」することで、わからないものがわかるようになった事例はたくさんあります。 情報システムの世界では、「観測」にあたるものを監視と呼びます。 監視というのは、人間でいうところの健康診断に似ていて、人間の場合は、体重とか血圧とかその他もっと細かいメトリックを計測しチェックします。 ウェブサービスのような情報システムの場合は、CPU利用率とかメモリ使用量とかそういったものになります。 これらの情報をなるべく頻繁に大量に集めるためには、専用のデータベースが必要です。いわゆる時系列データベースというものになります。

このデータベースの課題として、お金と性能というトレードオフに取り組んでいます。 観測により、自然科学の観測のような世紀の大発見があるわけではなく、ソフトウェアのバグだとかリソースが足りないとか、相対的に価値の低いものしか得られないので、お金が重要になってきます。 発表では、簡単にアイデアを紹介していますが、より具体的には サーバモニタリング向け時系列データベースの探究 / The study of time-series database for server monitoring // Speaker Deck をみてください。(ところで、ここからさらに発展した内容を5月にそれっぽい舞台で発表することになっています。)

さて、観測の次にやりたいことがあり、それは「実験」です。要は、コンピュータシステムの未知について、科学のアプローチを実施しようというような考えです。 実験というのは、Netflixの Chaos Engineering から連想しています。 ただし、Netflixの一連のツール群を使っているという話はあまり聞きません。本番に導入するにはやはりハードルが高いと感じています。 そこで、観測して得たデータを使って、システムモデルを構築し、シミュレーションのような安全な手段で、システム特性を明らかにし、弱点などをシステム本体にフィードバックするというビジョンを考えました。 ここは本当にジャストアイデアの段階で、例えばモデルって具体的になんですかと言われても答えられません。今のところ、フィードバック制御の理論あたりからヒントを得られないかと考えています。

このようなシステムを作って、人間をコンピュータの未知への恐れから解放したい、そう考えています。

神の怒りというのは、比喩ではありますが、単なる比喩ではなく話の根幹となるような話作りを意識しました。 観測と実験という概念は、最初から考えていたわけではなく、神の怒りからの連想ゲームから、うまく情報システムに落とし込める概念を見つけられたと思っています。

ipsjoneとは関係なく、昨年matsumotoryさんが発表されたなめらかなシステムとは違うものを提案しようとずっと考えていました。 (なめらかなシステムについては レンサバの常識を覆す「なめらかなシステム」に挑む──運用技術を学術研究して実際のサービスへ適用 - はてなニュース)

残念ながら僕は名前を付けられませんでしたが、観測と実験というのをテーマにこれからやっていこうと思います。

いただいた反応

別分野の研究者の方からおもしろかった、スライドがよいとフィードバックいただいたのはうれしいですね。 その他、また聞きですが研究者の方から、一番おもしろかった、我々は神の怒りと戦っていかねばならん、というようなコメントをいただいたと伺っています。 システムビジョンにも共感の声があり、思った以上に伝わっているという手応えを得ることができました。

登壇に至るまで

さて、そもそもなんでお前がそんな場所で発表しているんだという話ですね。 僕はそもそも研究者どころか、修士課程を中退しています。 そこからはてなに入社し、いわゆる現場で運用をやっているエンジニアをやっています。今月にEOLを迎えるCentOS 5の撤退みたいな10年前のシステムを相手にすることもやっていたりしました。 技術者としての実績はそれなりに積んでいるつもりですが、アカデミアにおける実績はほとんどありません。なぜこんな人間が採択されたのかは、今だによくわかっていません。

きっかけは、昨年の登壇者である matsumotory さんに、昨年の6月ごろに、IPSJ-ONEというものがあるので、登壇しないかと声をかけていただいたことです。そのときは、雑にいいですよみたいなことを言っていました。 そのときは、いつもの話で大丈夫と言われた記憶があるのですが、ある意味いつもの話ではあるものの、とんでもない無茶振りであることが後々わかってきます。 その頃はIPSJ-ONEというものがどういうものかあまりわかっておらず、matsumotory さんがちょっと前に登壇したやつぐらいの認識でした。 家に帰って改めて2016年の動画をみていたら、おいおいこれなんか違うやつなんじゃない?、そもそもトップの研究者が集まるとか書いてるじゃんって思いはじめて、その話を忘れていた11月ごろに、matsumotory さんから声がかかってきました。

今、声をかけていただいたDMを見直してみると、めちゃめちゃ大風呂敷を広げた上で、それを回収するみたいな方法で頑張ったのでそれがよさそうと書かれていて、本当にその通りになって笑ってしまいました。加えて、y_uukiが一番得意でかつ、そこに本番までに+アルファできるようなものを提案できると最高とも書かれていました。これも、僕の認識ではその通りになっていて、結果的に、DiamonDBの実装に加えて、観測と実験によるフィードバックループを回すというアプローチの紹介ということになりました。

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

そこから、IOT研究会のほうで講演をしないかとという話になったので、招待講演させていただくことになりました。その経緯はブログに書いています。 情報処理学会でウェブオペレーション技術について招待講演した話 - ゆううきブログ

ipsjoneの5分は、僕の発表経験でも3本の指に入る大変さだったので是非頑張ってくださいとも書かれていました。はい、がんばりましたよ。最初は、そんなに大変なことがわかっていなかったのですが、準備を進めるたびに、とにかく大変であることがわかってきました。僕の感覚では、6ヶ月連続200users以上のブログ書いたり、1000usersのブログ書くよりはるかに大変でした。

何が大変だったのか。今までのアウトプットは、自分がやったこととやったことを汎用的な視点で捉えるだけで済みました。 しかし、今回は逆に未来を描いて、自分がやっていることに紐付けるという、頭が痛くなるような手法でした。 しかも、それを一般向けかつLTで伝えることは、余分なものを削ぎ落として、専門家だからこそ難しく書きたくなるようなことを削っていく作業になりました

さらに、僕は自身のテーマというものが、そもそも固まっているわけではありませんでした。ざっくりWebオペレーション技術、SREといった職種/分野の専門性を高めているという程度で、会社の仕事とはまた別の軸で何をやりたいのか、ということを発表準備を通してつくろうとしていました。 テーマがなければ実績もないわけで、実績がある研究者はいいな〜と思いながら、matsumotoryさんの去年のスライドをみると、それまで積み上げてこられた実績が1ページにさくっと書いているだけで、あとはこれからやっていくことが書かれていました。

ようやく、matsumotoryさんの無茶振り具合がわかってきて、初見ハードモードで放り込まれたような気分になっていきました。matsumotoryさんには感謝しています。

ところでこれはトークが採択されたときのmatsumotoryさんの様子です。

f:id:y_uuki:20170321233516p:plain

あとがき

スライドだけみると、なんてことのない単なるライトニングトークにみえるかもしれませんが、その裏でいろいろと試行錯誤したことを記しておきたかったという気持ちで、この記事を書きました。

前述したように、最もこだわったことは、一般の方にちゃんとわかるように話をするということです。 見て動くような内容であれば、工夫をこらさなくてもなんとなく伝わります。我々がいつもやっているような、見えないものをどう伝えるのか、ということを深く考えさせられました。

実は、事前に社内の勉強会で発表したときは、驚くほど無反応でした。だいたい予想はしていたものの、考えすぎて全然だめなのかなーと思って、かなり落ち込んでいました。

しかし、そこから5分の制約を相手に、ボツスライドのほうが多くなるぐらいブラッシュアップを繰り返して、何度も練習して、全然専門家じゃないはずの両親がニコ生で発表をみていて、内容がわかった、わかりやすかったと言ってもらえたことで、発表してよかったと思えるようになりました。

フィードバックの数で言えば、普段書くブログのほうが圧倒的に多いです。しかし、普段のブログや発表はコンテキストを共有しているので、フィードバックが多いのは当たり前です。ちょうど id:Soudai さんが書かれているように、アウェーの舞台で伝えることに向き合った結果、伝えることの難しさ/うれしさを再確認できました。

敢えてアウェーで戦う事に意味があるって話 - そーだいなるらくがき帳

最後になりますが、ipsjone運営委員の皆様のご尽力には頭が上がりません。1回目を立ち上げるのももちろん大変なことだったと思いますが、その後「継続」することは、立ち上げ時の苦労とはまた異なる種類の苦労をされたのだろうと、「運用」を生業とする者としてご推察します。本当にありがとうございました。

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

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

3年というのは節目と言われる。働き方や考え方の軸が多少変わってきたように思う。 技術観点では、仕事が少しつまらなくなっていた時期があった。 技術的におもしろいことより、つまらないことのほうが優先度が高くなってしまうというよくあるやつだと思う。 もしくは、おもしろいところまで到達できずに、仕事としては十分な成果になってしまうということもあった。

去年の振り返りに、来年はコードを書くと書いていて、多少はできたものの実感としてはあまりできていない。これからのオペレーションエンジニア/SREは、ソフトウェアエンジニアリングによる問題解決ができないと時代に取り残されてしまうという危機感がある。

技術的挑戦を続けていくためには、自分だけでなく、周囲の環境も変えていかないといけないと思い、マネジメントし始めたり、リーダーシップをとったり、直接的な採用活動をするような局面が増えてきた。 それはそれで自分でやると言ってやっていることだし、悪くはないのだけど、これ自分でやっていればアウトプットもできるのになと思いながら、任せないといけないことも多かった。 慣れないことをやっていると、大したことやってなくても疲れるもので、アウトプット活動が止まってしまった時期もあった。

一時的にそういった期間があることは仕方ない、いつも最高の環境があるわけじゃないので、意識的に環境に作用できるようになれれば、それは自分の強みになると言い聞かせてきた。 最終的には、社内外の期待をかけてくださる方々にいくつかのきっかけをいただいて、来年は技術的に挑戦できる年になるという気持ちで年を越せそうだ。 サーバモニタリング向け時系列データベースの探究 / The study of time-series database for server monitoring // Speaker Deck に書いた設計を自分の代表的プロダクトにすべく、プライベートリポジトリでちまちまとコードに落とし込んでいたりする。 このあたりは、今年大変仲良くしていただいたid:matsumoto_rさんと、あとはMackerelチームのプロデューサーである id:sugiyama88 さんのおかげだ。

振り返ってみると、今年は次の挑戦のための土台づくりに専念した年かもしれない。

成長

内在的な技術的成長は多少はあったものの、アウトプットにつながっていないものは成長とみなさないことにしているので、今年は技術的成長があまりなかったといえる。

あえていえば、実際の運用で導入したKeepalivedのシンタックスチェッカーや今書いているソフトウェアの要素であるGraphiteの式のパーザーなど、これまで書けなかったタイプのコードを書けるようになった。トークナイザーとYACCを書いてるだけはあるけど。

あとは、はてなのこれまでのスタックにはないようなアーキテクチャを構築する機会がいくつかあり、アーキテクチャで解決するという手持ちの札が増えてきたように感じる。

技術以外の成長では、多少マネジメントをしたり、プロジェクト管理みたいなことを覚え始めた。SRE本の第18章"Software Engineering in SRE"にも書かれているが、インフラの領域でも、ソフトウェアエンジニアリングを本格的にやるなら、サービス開発のプロジェクト知見も必要なので、役に立つと思う。周囲の方々の助けもいただいて、多少の手応えもつかめた。

そして、今年一番の収穫は、ストーリーをつくるという意識かもしれない。 ストーリーというとプレゼンのようなものを連想する。もちろんプレゼンも含むのだけど、もっとこう自分の技術の取り組みのストーリーみたいなものを考えるようになった。 普通のエンジニアである僕がなぜか来年に登壇することになったIPSJ-ONEの演題を考えたり、研究会での登壇があったり、あとまだ公開されていない何かのためにまつもとりーさんの論文や口頭発表、ブログを読み返したことが影響している。 博士課程では、複数回のジャーナルを通して、最後にそれらをまとめるということをやるようなので、その手法にも影響を受けている 博士課程の予備審査にいってきました - 人間とウェブの未来, NAKAHARA-LAB.NET 東京大学 中原淳研究室 - 大人の学びを科学する: 博士論文とは「構造を書くこと」である!?。 自分のストーリーがあれば、次に何を勉強するかも決まってくる。 僕のように瞬発力とか手の速さで勝てない凡人は、ひたすら考えて、自分のやってきたこと、これからやることを繋いでいくしかない。

アウトプットまとめ

いつものようにブログやOSS活動を振り返る。

ブログ

いつものブログに加えて、今年から技術メモとしてGitHubにちまちまとメモを残していたりする。

順位 エントリ
1位 Linuxサーバにログインしたらいつもやっているオペレーション - ゆううきブログ
2位 ウェブアプリケーション開発に新言語を採用したときにインフラで考えたこと - ゆううきブログ
3位 Googleが数千台もある10年前のLinuxディストリをライブアップグレードした話 - ゆううきブログ
4位 自作Linuxコンテナの時代 - ゆううきブログ
5位 インフラエンジニアがGo言語でオペレーションツールを書くことについて - Hatena Developer Blog
6位 2015年の心に残った技術エントリ - ゆううきブログ
7位 ISUCON予選突破を支えたオペレーション技術 - ゆううきブログ
8位 2016年ウェブオペレーションエンジニアの新卒研修 - Hatena Developer Blog
9位 情報処理学会でウェブオペレーション技術について招待講演した話 - ゆううきブログ
10位 2016年はてなWebオペレーションエンジニアのアウトプット - Hatena Developer Blog
11位 ウェブオペレーションエンジニアになるまでの思い出 - ゆううきブログ
12位 リモートワークにおけるSlack Call活用と終業15分前の雑談 - Hatena Developer Blog
13位 nginxのステータスコード444 · yuuki/yuuki
14位 nginxのステータスコード499 · yuuki/yuuki
15位 Keepalivedのシンタックスチェッカ「gokc」を作った - ゆううきブログ
16位 リバースプロキシのコンフィグテスト

合計 8000 users+くらい。

発表

合計8件。

OSS

f:id:y_uuki:20161231215324p:plain

Graphiteへのパフォーマンス改善PR。

go-sql-driver/mysqlのMySQL 4.0対応をして、MySQLプロトコルの知見を深めたりした。 https://github.com/yuuki/go-sql-driver-mysql

他には、ISUCON6予選の出題側としてGo実装とインフラまわりの手伝いをやったりした。

まつもとりーさんの振り返り にも書いていただいているように、今年はペパボさんのエンジニアの方々と交流させていただくことが多く、大変刺激になりました。 はてなの技術力が非常に高いと称していただいていますが、僕としてはどちらかというと我々はまだまだだなあと思っていて、ペパボさんの取り組みは、前へ進む勢いを感じさせられるというか、一本筋が通ってみえるというかそんな気がしています。 我々はまだ場当たり的に問題を解決していってて、このままではいけないと思い、はてなシステムについて考えてたりしている。

あとがき

他のエンジニアの方々の振り返りを眺めていて、たぶん自分より若い人の台頭がすごいなあと感心している。

悔しいので、負けないようにがんばろう。

今年もお世話になりました。来年もよろしくお願いします。

ウェブオペレーションエンジニアになるまでの思い出

書籍「ウェブオペレーション」の中で、「ウェブオペレーションは技芸であり科学ではない」*1という言葉がある。 実際、その通りだと思う。 しかし、技芸というのはどうやって学べばよいのか。 教科書のようなトップダウンな知識体系を構築しようと試みようとしても、どうしても特定の組織に依存したり、特定の技術スタックに依存してしまう。

現時点では、体系立てて学ぶというより、やはりボトムアップに学ぶしかないと考えている。 「ウェブオペレーション」の内容も、基本はストーリー仕立てのエッセイ集になっているのは、そういうことだろう。

Hatena Engineer Seminar #7では、もともとウェブオペレーションの学び方の話をしようと思っていたが、前述のような事情で、自分(id:y_uuki)の場合の学んできたことを例として挙げることにした。 ウェブオペレーションエンジニアの前提となるスキルセットの作り方の一例として紹介する。LT資料なので勢い重視なのは許してほしい。

大学1年からLinuxを触り始めたときからはじまり、C言語を学び、ネットワークプログラミングを学び、アルバイトで巨大なCのプロジェクトをgdbを駆使してトレースしたり、はてなインターンにいったり、研究でSIMDとかGPUとかネットワークスタックとか触ってたり、はてなアルバイトでMackerelの前身を作ったり、子どものころを振り返ってみてシステムっぽいものが好きだったり、といった内容の話をした。

ウェブオペレーションエンジニアになった動機の一つに、教科書に書いてあるような古典的な知識が現場で活用されていることがおもしろいと感じていたことがある。 例えば、書籍「大規模サービス技術入門」*2では、MySQL(MyISAM)のテーブルファイルをあらかじめcatで読ませて、OSのページキャッシュにのせることで暖機運転がわりにする手法に感心したのを今でもよく覚えている。 このような考え方は、自分の技術スキルの方向性にも影響しており、2015年Webサーバアーキテクチャ序論 - ゆううきブログ自作Linuxコンテナの時代 - ゆううきブログ などに表れている。

わざわざ語るような大層な経験はなく、ごく平凡な来歴だなと思う一方で、アウトプットだけは人並み以上にやってきたという自負がある。ちまちましたことでも続けていれば、それなりの何かにはなるものだ。 もし今回の話に共感するところがあり、ウェブオペレーションやSREという技術領域に興味をもってもらえたなら、うれしく思う。

ちなみに僕の場合は、自然科学実験みたいな物理作業をとにかくやりたくなくて情報科学科に入ったので、「モノ」としてのサーバやネットワーク機器にあまり興味がないけど、なんとかやっていけている。

あわせてよみたい

同僚にはこういう変な人もいる。

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

*2:伊藤 直也、田中 慎司,[Web開発者のための]大規模サービス技術入門 ―データ構造、メモリ、OS、DB、サーバ/インフラ (WEB+DB PRESS plusシリーズ), 技術評論社

情報処理学会でウェブオペレーション技術について招待講演した話

情報処理学会インターネットと運用技術研究会が主催されているIOTS2016という研究会で、「サーバモニタリング向け時系列データベースの探究」というタイトルで招待講演をしてきました。

講演のきっかけ

インターネットと運用技術研究会(以下IOT研究会)というのは僕にとっては id:matsumoto_r さんが所属されている研究会です。 matsumotoryさんが、ちょうど2年前のアドベントカレンダーで書いた僕の記事に日本語だとIPSJのIOTは分野的にもインターネットの運用技術が含まれるので興味深い論文が沢山あると思う とコメントしていただいたのが最初に研究会の存在を知るきっかけだったと思います。 そのときはそんなものもあるのかと思ってちょっとプログラムを眺めた程度でした。 しかし、まさかその2年後にこうして招待していただくことになるとはもちろん思っていませんでした。 id:MIZZYさんがserverspecの論文をだされた研究会でもあります。

きっかけは、今年の6月ごろです。 やはりmatsumotoryさんに講演とは別件のとあるびっくり無茶振りを受けました。 そして、少し前にIOT研究会へいくつかの資料を提出したところ、次のIOTS2016で講演してくれという話をいただきました。 IOTSがどんなものかわかってなかったのですが、査読付きで1年で1番大きな研究会であり、matsumotoryさんがそこで招待講演できるの羨ましいとおっしゃっていたので、じゃあやります、と答えました。

講演内容

講演するにあたって、当たり前のことですが、まず伝えたいことを考えました。 IOTS2016の開催案内をみてみると、「運用でカバーする」、「運用担当者の人柱の上に成立する前時代的で野蛮な構造物」、「不快な卑しい仕事をやる必要がなくなるのは、人間にとってひじょうな福祉かもしれないが、あるいはそうでないかもしれない」といったなかなか興味深いセンテンスが散りばめられていることに気づきました。 研究者と技術者という、コンテキストが異なるものの、同じ運用技術に携わっているという前提があります。 そこで、ウェブサービスの運用の世界で実際に起きていることと生の課題を伝えようと思いました。

これを伝えるための話作りには、いくつかの案がありました。 ひとつは、そのまま「ウェブサービスの運用の世界」といったタイトルで、ウェブオペレーションを概観する話をするというもの、もうひとつは、時系列DBやコンテナ型仮想化など特定の技術の話をするというものです。

最終的には後者にしました。 ちょうど時系列DBのアーキテクチャ刷新に取り組んでいるため、成長するサービスとスケーラビリティといういかにもウェブオペレーション技術っぽい話ができます。 自分がまだ大学にいた頃から取り組んでいたことであり、時系列DBの話をすることは自分がこれまでがんばってきた技術の話をすることにもなります。 さらに、研究会なのだから、論文にできそうなテーマならなおよいはずと思って、最新の取り組みを紹介したかったというのもあります。

だいたい話すことは決まっていたものの、ストーリー化することには苦労していて、2日くらい前にインフラチームの同僚何人かに見せたら反応が芳しくなかったので、同僚の意見を取り入れて、大幅にスライドを書きかえました。 無意識に研究発表的なスライドっぽくつくってしまっていた気がします。 トップダウン視点ではなく、自分視点に置き換えていって、アーキテクチャの説明はすべて図にしました。 会社としてというよりは個人として招待されたと思っているので、結果として自分視点になってよかったと思います。

matsumotoryさんには、見事に上記の意図をすべて汲み取っていただきました。

講演の導入には、まず異なるコンテキストのすり合わせをしようと思って、開催案内を引用させていただきました。 不快な卑しい仕事というのは、書籍Site Reliability Engineeringに書かれている"toil"に相当し、Googleでさえtoilからは逃れられていないが、toilではないエンジニアリングに価値を置いていると伝えました。 toilを消すことは、最近のエンジニアのコンテキストにおいても重要であり、そのような研究活動には価値があるということを暗にお伝えしたつもりです。

発表スライド

発表スライドを以下に貼っておきます。 あとで読む資料としてはまとまりがない点についてはご容赦ください。

若いと言われるが実際若くて平成生まれとか、IOTSの開催案内を会社の全体朝会で紹介したら社員のみんなが大喜びだったとか、アルバイト時代になんか癒やしとか言われてだまされてRRDtoolのCPANモジュールつくってたとか、入社するころにはRRDtoolは若者にはふさわしくないことがわかってきたとか、いつものように調子よくしゃべってたら笑いもとれたので、話をしていて楽しかったです。 以下のスライドがハイライトです。

講演を終えて

僕のことをご存知の方は、3年前に大学院を中退したことを覚えておられるかもしれません。 単に特定の環境とあわなかっただけというだけかもしれません。しかし、自身の体験だけでなく、社会人になってからも、大学の研究室で苦しんでいる学生たちの声を何度か聞くこともありました。 このこともあって、研究活動そのものはともかくとして、大学や研究室といった環境に強いネガティブな感情を今だにもっています。

今回の件は、大学から離れ、現場のエンジニアとしてがんばってきた成果をアカデミックな場で話すよい機会でした。 幸いなことに、思った以上に「話が通じる」という感覚を得られ、うれしく思いました。 もちろん、何を言ってるのかさっぱりだと思われた方も少なくはないでしょうが。 他の発表でもAmazon RedshiftとかKibana、Graphana、Elasticsearchなど見慣れた単語がとびかっていたので、安心感があります。

一方で、大学関係のシステムの運用を対象とした話がやはり多く、それらについてそれほど興味があるわけではありませんでしたが、おもしろく聴けた発表がいくつかありました。 特に柏崎先生の発表はとにかくいきおいのあるスライドというかこれは本当に学会発表か?と思うほどでした。 @hirolovesbeer さんの異常検知の話は質問したところ、イベントネットワーク以外にもサーバのログの異常検知にも使える可能性があるとのこと。

これ使えるなーと思ったものが論文優秀賞をとられていて、エンジニアの視点でよいものがちゃんと評価されるんだなと感じました。

ウェブオペレーションやSREに関する学術研究発表があればもっとおもしろく感じるだろうなと思います。 というのは、最近のウェブエンジニア界隈を眺めていて、それは本当に有用なのか、新しいおもちゃを使わされているだけになっているんじゃないかと疑問に思うことが増えてきて、真に有用な技術ってなんだろうなと考えたりすることがあるからです。

そういった考え方、アカデミックなアプローチで技術をつくるという方向性は自分の課題意識とマッチしているのではと思うことはあります。 博士過程へのお誘いもいただいたりしたのですが、前述のネガティブなイメージを払拭するのはすぐには難しいですね。 そもそも生半可な覚悟では社会人で博士号取得なんてできるわけないので、今後、「おもしろそう」「すごいことをやっていそう」「成長できそう」といった強いポジティブなイメージに転換できるかどうかが鍵になると思っています。

帰り際に、あのゆううきブログの中の人ですよね?と話かけていただいて、大学の中の人にまでリーチしているのかとちょっとびっくりしました。 大学を去ったその後に、大学の中の人に影響を及ぼしているというのは不思議な気分ですね。

この記事は、はてなエンジニアアドベントカレンダー2016の4日目の記事です。昨日は id:wtatsuru によるセキュリティ会の取り組みでした。 明日の担当は、buildersconで発表してきたばかりの id:shiba_yu36 です。

ISUCON予選突破を支えたオペレーション技術

ISUCONに参加する会社の同僚を応援するために、ISUCONの予選突破する上で必要なオペレーション技術を紹介します。 自分がISUCONに初出場したときに知りたかったことを意識して書いてみました。 一応、過去2回予選突破した経験があるので、それなりには参考になると思います。 といっても、中身は至って標準的な内容です。 特に、チームにオペレーションエンジニアがいない場合、役に立つと思います。

今年のISUCON6は開催間近で、まだ予選登録受付中です。

※ 文中の設定ファイルなどはバージョンやその他の環境が異なると動かなかったりするので必ず検証してから使用してください。

ISUCONでやること (Goal)

ISUCONでやることは、与えられたウェブアプリケーションをとにかく高速化することだけです。 高速化と一口に言っても、複数のゴールがあります。ウェブアプリケーションの場合は以下のようなものでしょう。

  • レスポンスタイムが小さい
  • スループット (req/s) が大きい
  • CPUやメモリなどリソース消費量が小さい

ISUCONでは、基本的にはレスポンスタイムを小さくすることを目指します。 これは実際のウェブアプリケーションにおいても、ユーザ体験に最も直結するレスポンスタイムを改善することが重要なので理にかなっています。

とはいっても、リトルの法則により、安定した系において、レスポンスタイムが小さくなれば、スループットは向上するため、レスポンスタイムとスループットは相関します。

リソース消費量の改善は、レスポンスタイムに寄与するというよりは、サーバ管理にまつわる人的または金銭的なコストを下げることに寄与します。 例えばメモリが余っているのに、メモリ使用量を削減しても、レスポンスタイムには影響しません。ただし、そういった無駄を省くことで、アプリケーションの処理効率がよくなり、結果としてレスポンスタイムが良くなることはあります。

ISUCONは、具体的には、以下のような要素で構成されていると考えます。

  • サーバを含む環境構築
  • OS・ミドルウェアの選択とチューニング
  • アプリケーションロジックとデータ構造の改善

ここでは、前者2つをオペレーションの領域、後者をプログラミングの領域とします。 必ずしも、オペレーション要員が必要ということはなく、あくまで領域なので、分担することも多いと思います。 自分の場合、過去2回とも、チームの構成上、オペレーションまわりはほぼ全部1人でやっていました。

ISUCONの考え方 (Principles)

自分が考えるISUCONの原則は、「オペレーション(System Engineering)で点を守り、 プログラミング(Software Engineering)で点をとる」です。

OS・ミドルウェアのチューニングが劇的な加点要素になることはあまりありません。 そのレイヤのチューニングはリソース消費量を小さくすることに寄与することが多いためです。

ただし、チューニングしていないために、劇的に性能が劣化することはあります。 例えば、InnoDBのバッファプールサイズを小さくしていると、データがメモリに乗り切らず、大量のディスクI/Oが発生し、スコアが大きく下がるはずです。

もちろん、アプリケーションロジックが薄いとそれだけOSやミドルウェアが仕事をする割合が大きくなるため、 OSやミドルウェアのチューニングによりスコアが伸びることはあります。

そうはいっても、基本的にスコアを伸ばす手段は、アプリケーションロジックとデータ構造の改善です。 これは実際のウェブアプリケーション開発の現場でも同じことが言えます。 雑な体感によると、パフォーマンスの支配率は、アプリケーションが8割、OS・ミドルウェアが2割程度(要出典)だと思っています。

ISUCONにおけるオペレーション

環境構築

予選の場合は、クラウド環境セットアップが必要です。ISUCON3、ISUCON4ではAWS、ISUCON5ではGCE、ISUCON6はAzureです。 アカウント作成やインスタンス作成がメインです。 当日のレギュレーションにも一応手順は記載されるはずですが、事前に触っておくと本番で混乱せずに済むと思います。

サーバログイン環境

例年であれば、/home/isucon 以下に必要なアプリケーション一式が入っています。

isuconユーザがもしなければ (useradd -d /home/isucon -m isucon) などで作成します。 さらに、/home/isucon/.ssh 以下に公開鍵認証するための公開鍵を設置します。 /home/isucon/.ssh/authorized_keysファイルを作成し、.sshディレクトリのパーミッションは700、authorized_keysファイルのパーミッションは600であることを確認します。(この辺のパーミッションがおかしいとログインできない) メンバー分のユーザを作成するのは面倒なので、共通ユーザ1つだけで問題ないと思います。

デプロイ自動化

Capistranoのような大げさなものは使わなくて良いので、以下のような雑スクリプトでデプロイを自動化しましょう。

やっていることはSlackへ開始デプロイ通知、git pull、MySQL、Redis、memcached、app、nginxの再起動、Slackへデプロイ完了通知ぐらいです。 MySQLやnginxもいれているのは、設定ファイルを更新したはいいが、再起動をし忘れるということがよくあるので、まとめて再起動してしまいます。 接続先のプロセスがしぬと、うまく再接続されない場合もなくはないので、再起動するのは原則バックエンドからが一応よいです。

リソース利用率把握とログの確認

ここでいうリソースとはCPU、メモリ、ディスクI/O、ネットワーク帯域などのハードウェアリソースを指します。 要はtopの見方を知っておきましょうということです。以前ブログに書いたので、参照してください。

冒頭でISUCONではレスポンスタイムを小さくするのがよいと述べました。とはいえ、リソース消費量を把握しておくことはボトルネック特定のヒントになるので重要です。 例えば、予選問題の初期状態ではMySQLのCPU負荷が支配的であることが多いかつディスクI/Oが高ければ、まずMySQLのバッファプールを増やしたり、クエリ改善が必要そうという程度のことはすぐわかります。 ISUCON4で話題になったCache-Controlの件も、ネットワーク帯域が限界であることにもっと早く気づいていれば、何かしら手は打てたかもと思います。(当時は思い込みでそこでボトルネックになってるとは思っていなかった。)

監視

去年のISUCONでは、自分たちのチームではMackerelの外形監視を使ってみました。 競技中に、アプリケーションのsyntax errorか何かで500でてるのに、ベンチマーカーを走らせてしまい、時間を無駄にしてしまうことがあります。 インターネット経由でポート80番が疎通できてさえいれば、アプリケーションが落ちていると、Mackerelの外形監視がすぐに通知してくれます。

MySQLデータサイズ確認

MySQLのデータサイズとして、テーブルごとのサイズや行数などを把握しておくと、クエリ改善の参考にできる。 行数が小さければ、多少クエリが悪くてもスコアへの影響は小さいため、後回しにできる。

mysql> use database;
mysql> SELECT table_name, engine, table_rows, avg_row_length, floor((data_length+index_length)/1024/1024) as allMB, floor((data_length)/1024/1024) as dMB, floor((index_length)/1024/1024) as iMB FROM information_schema.tables WHERE table_schema=database() ORDER BY (data_length+index_length) DESC;

アクセスログの解析

proxyでアクセスログを解析することにより、URLごとのリクエスト数やレスポンスタイムを集計できます。

解析には、tkuchikiさんのalpが便利です。 自分の場合は、適当な自作スクリプトを使っていました。https://gist.github.com/yuuki/129983ab4b02e3a646ad

isucon@isucon01:~$ sudo parse_axslog isucon5.access_log.tsv taken_sec
req:GET / HTTP/1.1 taken_sum:474.08 req_count:714 avg_taken:0.66
req:GET /footprints HTTP/1.1 taken_sum:58.378 req_count:198 avg_taken:0.29
req:GET /friends HTTP/1.1 taken_sum:27.047 req_count:238 avg_taken:0.11
req:POST /diary/entry HTTP/1.1 taken_sum:6.51 req_count:195 avg_taken:0.03
…

nginxでLTSVによるアクセスログをだすには、以下のような設定を去年は使いました。

log_format tsv_isucon5  "time:$time_local"
 "\thost:$remote_addr"
 "\tvhost:$host"
 "\tforwardedfor:$http_x_forwarded_for"
 "\treq:$request"
 "\tstatus:$status"
 "\tsize:$body_bytes_sent"
 "\treferer:$http_referer"
 "\tua:$http_user_agent"
 "\ttaken_sec:$request_time"
 "\tcache:$upstream_http_x_cache"
 "\truntime:$upstream_http_x_runtime"
 "\tupstream:$upstream_addr"
 "\tupstream_status:$upstream_status"
 "\trequest_length:$request_length"
 "\tbytes_sent:$bytes_sent"
 ;
access_log /var/log/nginx/isucon5.access_log.tsv tsv_isucon5;

MySQLスロークエリログの解析

MySQLのスロークエリログは、実行時間が閾値以上のクエリのログを吐いてくれるというものです。 最初は、long_query_time = 0 にして、全クエリのログをとります。もちろん、ログ採取のためのオーバヘッドはありますが、最終的にオフにすればよいです。

slow_query_log                = 1
slow_query_log_file           = /var/lib/mysql/mysqld-slow.log
long_query_time               = 0
log-queries-not-using-indexes = 1

pt-query-digestで集計するのが便利です。 https://gist.github.com/yuuki/aef3b7c91f23d1f02aaa266ebe858383

計測環境の整備

ログの解析については、前回のベンチマークによるログを対象に含めたくないため、ベンチマーク前に過去のログを退避させるようにします。

設定ファイルを変更したまま、プロセスの再起動を忘れることがあるので、ベンチマーク前に各プロセスを念の為に再起動させます。

チューニング

MySQL、nginx、redis、memcachedについては、特殊なお題でないかぎり、kazeburoさんのエントリの通りでよいと思います。 比較的スコアに効きやすいのは、静的ファイルのproxy配信、UNIXドメインソケット化あたりかなと思っています。

ただし、sysctl.confの設定内容反映については、Systemd バージョン 207と21xで注意が必要です。 具体的には、/etc/sysctl.conf が読まれず、/etc/sysctl.d/*.conf または /usr/lib/sysctl.d/*.conf が読まれるようです。 sysctl - ArchWiki

アプリケーションの把握

オペレーションばかりやってると意外と、何のアプリケーションか知らずに作業しているということがあります。 特に序盤は定例作業が多いので、一息つくまでにそれなりに時間をとられます。 その間に、アプリケーション担当が把握していて、把握していることが前提になるので、会話についていけないこともあります。

そこで、以下のようなことを最初に全員でやって認識を合わせるといった工夫をしたほうがよいです。

  • ウェブサービスとしてブラウザからひと通りの導線を踏んでみる
  • テーブルスキーマをみる
  • MySQLのコンソールに入ってデータの中身をみてみる
  • コードを読む

競技終了前のチェック

競技終了前になにか見落としがないかチェックします。

  • ディスクサイズに余裕があるか。運営サイドでベンチマークを回す時にログ出力でディスクがうまることがないとも限らない。ログを吐きまくってると意外とディスクに余裕がなくなっていたりするため、最後に確認する。
  • ページの表示は正常か。CSSがなぜかあたってないとかないか。
  • ログの出力を切る。アクセスログやスロークエリログ。
  • (厳密には競技終了30分〜60分の間ぐらい) OSごと再起動してもベンチマークが通るかどうか

参考文献

kazeburoさんの資料が非常に参考になります。何度も読みました。

昨年の予選のコードと設定ファイルは公開しています。https://github.com/yuuki/isucon5-qualifier 昨年の様子です。ISUCON 5予選で5位通過した話 - ゆううきブログ

発表資料

この記事は、京都.なんか#2 で発表した内容を元にしています。 準備・運営ありがとうございました! > id:hakobe932 / id:hitode909

どの発表もおもしろかったけど、個人的にはkizkohさんのRust&netmapの話がよくて、netmapは昔論文読んだりしたものの、全然使っていなかったので、実験的とはいえ実際にコード書いて動かしているのがとてもよいなと思いました。 というかこんなところで、netmapとかdpdkの話がでてくるのかとびっくりしました。

あとがき

今年もはてなから何チームか出場するとのことだったので、知見共有のために、これまでのISUCON出場経験をまとめてみました。

ISUCON当日に調べながらやっていては間に合わないので、今のうちに練習しておくことをおすすめします。 さらに、全体を把握するために、過去の問題を一人で解いてみることもおすすめします。

おもしろいのは、多少ISUCON特有のノウハウは混じっているものも、実際の現場でやっているようなことがほとんどだということです。 昨今では、ウェブアプリケーションが複雑化した結果、高速化の余地があったとしても、大きすぎる問題を相手にすることが多いため、ISUCONは手頃な環境で経験を積むにはもってこいの題材です。

さらに本戦出場して惨敗すると、人権をロストしたり、ヒカリエの塔からハロウィンでめちゃくちゃになった街に突き落とされるような体験が待っています。