MogileFSをバックエンドとしたPrivate S3の作り方

70
GMO Pepabo, Inc. Ryo kuroda @lamanotrama 2015/08/29 3回ペパボテックカンファレンス MogileFS をバックエンドとした Private S3の作り方

Transcript of MogileFSをバックエンドとしたPrivate S3の作り方

GMO Pepabo, Inc. Ryo kuroda @lamanotrama

2015/08/29 第3回ペパボテックカンファレンス

MogileFS をバックエンドとしたPrivate S3の作り方

黒田 良 @lamanotrama> 技術基盤チーム > インフラ担当

前半 (自分) • 全体アーキテクチャ • インフラ

後半 (@hiboma) • APIアプリケーション

前半アジェンダ> 何故Private S3? > アーキテクチャ > 大規模MogileFSの運用 > Gatewayの仕組み > データインポート

何故Private S3

全社的にサービスインフラを オンプレミスから Private Cloud(Open Stack)に移行

課題

静的コンテンツの保存、配信> 主に画像 > 容量がそれなりに大きい > 各サービスがそれぞれ違った仕組みで独自に構築している > Nyah(IaaS)上に各サービスが再構築するのは非効率

> 可用性 > スケーラビリティ > 構築、運用コスト

→ 求められる大統一オブジェクトストレージサービス

ペパボのオブジェクトストレージと言えば

30days Album

30days Album> 2008年リリース > 大規模分散オブジェクトストレージ > perl製のMogileFSを使用 > 総容量: 750TB > 累計オブジェクト数: 22億

高いデータ耐久性、稼働率> 7年間でデータロストは一回(4個) > (不幸なレア条件が重なったため。鋭意システム改善中!)

> 計画メンテを除いたサービスダウンはほぼ無い > (以前は不安定な時期もありました)

vs OpenStack SwiftOpenStackにもオブジェクトストレージを提供するコンポーネントはあるが…

> 大規模分散オブジェクトストレージを安定運用するのは甘くない > 30days AlbumのMogileFSは十分に安定している

最初からS3互換APIを備えているというメリットはあるが、長い目でみるとそこの開発コストは十分相殺されると考えた。

vs AWS S3フルマネージドのS3でいいじゃん?

> 容量や転送量のコスト面でオンプレの方が明らかに優位 > 同程度の規模だと容量課金のみで数百万円/月

> 長年のノウハウ蓄積によってMogileFSの運用コストはかなり下がった

名称ペパボストレージ

名称ペパボストレージ

Bayt

アーキテクチャ

30days

30days + Bayt

Bayt

1. gateway> Nginx + ngx_mruby > インターネット、インターナルからリクエストを受ける > http(s)://<bucket_name>.hitmitsu.no.domain/ > http://bayt.30d.lan/<bucket_name>/

> apiにproxy > apiだけでは出来ないあれこれ(後ほど)

2. api> Rails + Unicorn > mogilefsd、メタデータdbとのやりとり > 詳細は後半で

この2つを作れば 基本的にはOK

と、その前に 既存システムコンポーネントの

強化、安定化

安定稼働しているとはいえ、全社的に使うには心もとない部分もある

メトリクスの充実化、可視化

storageサーバの高集積化自作サーバ期など、紆余曲折を経て 今は/dev/sdarまであるみっしり筐体がメイン

DB(MySQL)サーバのリプレース> 2台→3台 (総入れ替え) > MySQL5.1→MySQL5.5 > MHA導入

短時間のダウンタイムを許容できるなら2台でもいけなくはない。 が、メンテナンス性がとにかく悪い。

mogilefsdクラスタの強化負荷が高くなるのは明白なのでスペックアップ&台数++

問題発生

mogilefsdがスケールしないmogilefsdはマスタープロセスからワーカを生やすpreforkモデル

\_ mogilefsd \_ mogilefsd [monitor] \_ mogilefsd [replicate] \_ mogilefsd [replicate] \_ mogilefsd [replicate] \_ mogilefsd [replicate] \_ mogilefsd [queryworker] \_ mogilefsd [queryworker] \_ mogilefsd [fsck] \_ mogilefsd [fsck] \_ mogilefsd [reaper] \_ mogilefsd [delete] …

mogilefsdがスケールしない子が少ないうちは大丈夫

mogilefsdがスケールしない増やすと親が子からのメッセージに応答しなくなる(約700プロセスを境に)

❌ ❌❌

mogilefsdがスケールしないスループットが大幅に低下。 困った。

❌ ❌❌

mogilefsdがスケールしない親に気合をいれてみた。 renice -20 -p 親

❌ ❌❌

mogilefsdがスケールしない元気でた。

副作用mogilefsdサーバがコンスタントに高負荷で落ちる。

1. 稀に子の調子がわるくなり、親から殺される 2. 新しく生まれた子は-20の子なので-20 3. 過負荷で不安定になる 4. 更に子が死ぬ 5. -20っ子がモリモリ増える 6. もう無理

過剰なやる気

mogilefsd起動直後と、その後もこまめにcronで親子のnice値の面倒をみることで解決。 (もうちょい綺麗になんとかしたい…)

DB刺さる問題1. MySQL5.5化以来、コンスタントにDBが刺さる(デッドロック)

2. 負荷がじりじり上がる 3. MHAマネージャからのヘルスチェックがコケて、自動でマスターフェイルオーバー

4. 復旧

入れててよかったMHA…とか言ってる場合ではない。

雑に解決> クエリの実行計画が変わったことで、元々使われていなかったindexが使われるようになったことが原因 > mogilefs.file_to_replicate nexttry

> 要らんからdrop

色々調査、検証したけど長くなるので省略…

既存の画像配信の品質向上Bayt GWの仕組みと共通するため、まずは既存(30days)の画像配信周り(Nginx)の改善。

> Keep Alive (client - nginx - unicorn) > Last-Modifiedヘッダ取り回しのバグ修正 > TLSオプティマイズ > upstream、reproxyのフォールバック設定見直し > storage(WebDAV)サーバのメモリバッファ上限引き上げ、worker数の調整

等などで、 30%程度高速化。レスポンスタイム、スループットの安定化。

@cubicdaiya さんの資料が大変参考になりました。 https://speakerdeck.com/cubicdaiya/nginxfalsepahuomansutiyuningu

gateway

(再度構成図)

実URLへのreproxy処理

gw

api

storage

実URLへのreproxy処理

GET http://mybucket.domain/a/b.jpg

GET http://192.168.1.3/a/b.jpg Host: mybucket.domain

gw

api

storage

実URLへのreproxy処理

X-Accel-Redirect: /reproxy X-Reproxy-URL: http://192.168.1.4/dev1/123.fid http://192.168.1.6/dev8/123.fid

gw

api

storage

実URLへのreproxy処理

gw

api

storage

GET http://192.168.1.4/dev1/123.fid

実URLへのreproxy処理

gw

api

storage

実URLへのreproxy処理

gw

api

storage

GET http://192.168.1.6/dev8/123.fid

実URLへのreproxy処理

gw

api

storage

1. apiへproxy

2. 内部リダイレクトとproxy

3. 2つ目のURLへフォールバック

ややこしいけど便利

apiに届かなかった場合のエラードキュメント

S3互換にしないとクライアントで困る。 bodyだけでなくstatus codeも。

ngx_mruby の活用

Serverヘッダ変更Server: Bayt で帰ってくるとかっこいい。(add_headerディレクティブでは変更できない)

リクエストUUID(ぽいもの)の発行Railsまで届かなかった場合でもclient、gw、apiでユニークなリクエストIDを共有する為にgwで発行。

apiでHMAC認証をskipさせるヘッダを付与

特定の条件を満たすリクエスト > internalリクエスト

> 認証未対応のクライアントからの特定バケットへのリクエスト

(S3とは関係ないBayt独自仕様)

ngx_mrubyのオーバーヘッドほぼ無い(実質的に問題にならない)

リクエストトータルで掛かった時間

(mrubyの処理が介在しない)upstreamへのリクエストのみで掛かった時間

太らない活発な開発。劇的改善。@matsumotory ++ (スパイクはNginxと関係ないバッチ処理によるもの)

ngx_mruby v1.12.14

既存データのimport

S3互換なので> 既存のS3クライアント実装をそのままつかえる

> 某サービスの場合だと画像サーバ上のデータpathをそのまま s3cmd sync

DBメンテ祭りimport検証中に発覚した問題への対応。

> ETag(md5値)保存用のカラム追加 > インデックスの追加 > path(object key)カラムのサイズを255→512に変更 > pathをcase sensitiveにする為にcollationを変更

約9億レコードのテーブルへのALTERで最長25時間。 MHAのオンラインマスター切り替えを利用したメンテナンスで 全てサービスダウンタイムは無し。

粛々とインポート、移行> 適当な単位でCDNからのOrigin指定を切り替え > 3TB、1億オブジェクトを移行済

絶賛安定稼働中

今後> 全サービスのデータを移行 > マルチロケーション(DC)化 > ディザスタリカバリ > サービスエンドポイントの冗長化

> 動的画像リサイズ機能 > URLパス、クエリパターンで動的にリサイズ、配信

以上。後半に続く。 API編 by @hiboma