信頼性の高いサービス運用のための5つの要素

さて少し遅れてしまったのですがSRE 2 Advent Calendar 2018の23日目です。

SREでどんな事をしているというより、どういうポリシーで信頼性を実現するか、という観点でまとめてみました。 SRE観点で運用改善をしていく! と言っても闇雲にやると「何やってるの?」になりがちなので。 まだ自分の中でもはっきりとしたものがある訳ではないのですが、やはり言語化してまとめ無いとフワフワしたままなので書いてみた感。 内容的に技術ポエムの方にしようかとも思ったのですが結局こちらに。

概要

サービスの運用にとって最も重要なことはサービスの信頼性を維持/向上させることです。 そのためには以下の5つの要素を意識した改善をし続けていくことが重要です。

  • 回復性の設計
  • Isolation
  • トイルの撲滅
  • 可視化
  • モニタリング

サービスの信頼性を保つための5つの基本要素

高い回復性の実現

安定運用を実現するために最も重要なのは回復性(Realizability)の高いシステムの実現です。 回復性の高いシステムとは、障害が起こることを前提に素早く復旧しユーザに影響を見せないシステムをさします。 例えばリアルタイムシステムであれば100ms, バッチであれば数分でTake over/Re-runが実現できるのであればシステム障害の影響をユーザが感じることはありません。 最も顕著な例はHP NonStopnのプロセスペアです。アクティブ系が落ちても瞬時にスタンバイにテイクオーバーすることでシステム全体としての高い信頼性を実現しています。

システムが落ちないこはももちろん重要な指標ですが、MTTRを極小化して回復性の設計をアプリケーション、インフラ、及び運用手順により作り込むかがサービスの信頼性につながります。 理由の一つに技術の進歩のみならクラウド時代に突入しシステムが壊れる事が前提となっているためです。これはインフラの耐久性が落ちた訳ではなく大量のリソースを管理するため確率の問題です。 よってオンプレであっても同様の状態にあります。

Isolation

回復性を実現するためにはシステムごとのIsolationを高くする必要があります。障害の影響範囲が大きければ必然的に復旧時間が伸びる可能性が高いためです。 また、高いIsolationを持つシステムはポータビリティに優れシステムの部分的な入れ替えをしやすいためフレキシブルな運用も実現しやすくなります。 そのため、ミドルウェアやライブラリのバージョンアップをより低いリスクで実現する事ができるようになり、セキュアで効率的なシステムを保ち続ける事ができます。

これは仮想化のような集約基盤を使わないことを意味しません。 むしろ、仮想化特にDockerのようなコンテナ技術を積極的に利用する事でマシンからアプリケーションの独立ができ任意のマシンで動作可能なポータビリティを実現できます。

トイルの撲滅

高いIsolationを実現するとシステムが分散され複数のシステムを運用することとなり運用コストが増えてしまいます。 また、そうで無くてもサービスの成長と共にシステムは増え運用コストは増大していきます。 このような状態で高い回復性を持つシステムを構築するには、トイルを撲滅しシステムの数と運用コストの比例関係を無くすことが重要です。

トイルとは具体的には以下の状況を満たすものを言います。

  • 手作業であること
  • 繰り返されること
  • 自動化できること
  • 戦術出来であること
  • 長期的な価値を持たないこと
  • サービスの成長に対して比例的に増えること

これらはサービスが小さいうちは問題になりませんが、サービスが成長しシステムが増えていくにつれて多くの問題を引き起こします。リリース作業とか分析のための定期的なデータ抽出とかはといるの典型でしょう。 特に繰り返される手作業はスピード感を損ない回復性に致命的な影響を与えるのみならず障害の原因となります。大規模障害の多くはシステムの故障ではなくオペレーションミスによって引き起こされることは珍しくありません。 トイルを撲滅するために自動化や運用プロセスの見直しを進めることでシステムの堅牢性を高めると共に運用負荷の比例的な上昇も削減することができます。

可視化の徹底

あらゆる改善は計測から始まります。可視化されてない状態では改善することはもちろん現状を把握することもできてないからです。 特にシステムの信頼性に直結するレイテンシやエラーは運用のKPIそのものであり、これらのメトリクスは必ず可視化されている必要があります。

また、上記のKPIを改善するためにトラフィックやシステムリソースの利用率などのメトリクスも可視化されている必要があります。 重要性を判断する観点でアプリケーションログから業務的なメトリクスを可視化することも必要です。そのためログは機械が読みやすいフォーマットで出すことが非常に重要です。 さらにほとんどのシステムはDB/ファイル連携またはRPCにより連携しているので、分散トレーシングやData Lineageも意識した可視化が重要になってきます。

適切なモニタリング

可視化は人間向けにメトリクスを表現するのが中心になりますが、モニタリングはシステムによるアクションを含んだ要素です。 何らかのメトリクスが閾値を越えるとされるアクションのことをさします。モニタリングは下記に分類できます。

  • ページ(アラート): 即時対応が必要
  • チケット: 業務時間または数日以内に対応が必要
  • ロギング: 対応は不要。記録だけ残し性能分析や監査のために利用

これはITILのイベント管理におけるERROR/WARN/INFOと同様のものです。また、下位のイベントでも1分間に10回発生など閾値を超えた場合には上位のイベントとしてエスカレーションします。 特にページャー(オンコールの回数=アラート回数)は回復性に大きな影響を与えるのでKPIとして計測し、いかに削減していくかが重要になってきます。

適切なモニタリングとはまずイベントが上記の分類にしっかりとされているか否か、そしてそれが継続的にメンテナンスされているか(未知の問題から既知の問題になることでアラートからチケットに変わるのは本来は頻繁にある)が重要になります。

実現のための原則というかキーワード

本当はこれを原則集的なものにしたいのだけどそこまで体系化できてないので、とりあえず思ってることを単なに箇条書き。 多分アプリ観点としてはTwelve-Factor Appを守ってください、って感じかなー。

  • アプリケーションにIPアドレスなど環境依存の値を入れさせない(DNSとかhostsとかで名前をつけるか環境変数)
  • ログフォーマットやメトリクスを集めて後から分析する。人間のみやすさより機械の見易さ
  • Infrastructure as a Codeを積極的に活用する
  • ConfigurationはDB化し誰でもアクセス出来るようにする(担当者に聞かないとネットワークやサーバ設定が分からないを無くす)
  • GUIよりCLI、手順書よりスクリプトを徹底する
  • デプロイ単位が異なるものを同時にビルドしない
  • SLAが異なるものを同じ場所(OSやJVM, コンテナなどリソース管理の単位)にデプロイしない
  • ステートレスと冪等性を意識する
  • 長時間動くバッチは悪である。並列化等で対処できないかを考える
  • モジュールは小さく保ち起動速度を速くする

まとめ

実現のための手段は無限にありますし組織によって異なります。Dokcer化したり、モニタリングツール変えたり追加したり、マイクロサービス化してサーキットブレイカーを入れたりなどなど。 その作業を進める中でどういう効果があってそれをするかってのを今回記載したような観点で整理していけば説明しやすくなるんじゃ無いかなー、と。

それでは来年もHappy Hacking!

第四世代言語って知ってるか? - 古の次世代言語 4GL

ロストテクノロジー Advent Calendar 2018 14日目です。

皆さんは古の次世代言語 4GLをご存知でしょうか? 

我々が普段使ってるプログラミング言語は所詮第三世代言語、それに続く言語の次なる進化が第四世代言語です。

www.weblio.jp

第一世代言語機械語
第二世代言語アセンブラ
第三世代言語高級言語(手続き言語)
第四世代言語New

といった分類になります。 4GL自体の明確な定義は知らないのですが基本的には「機械が読むことを優先した言語ではなく、人間中心の言語へ」と言うコンセプトの元にエンドユーザ向けの言語であることが特徴です。

有名どころではRPGやEasyとかですかね?。ちゃんと現代にも生き残ってる代表格はSQLとRですね。 当時を知らないのでなんともなのですがエンドユーザ向けといってもコールセンターのオペレータが使うような想定ではなく、ベンダーではなくユーザ企業の電算部?の人たちを指してエンドユーザと呼んでるのではないかと推測されます。 なので、単純に生産性を高めるような方向性の言語も混じっていますし、SQLなんかが典型ですが手続き型のアンチテーゼとしての宣言型言語も比較的多い気がします。

闇に消えた4GLですが理由は寡聞にして知りません。まあキーワードである「エンドユーザ向け言語」すなわちEUC(End User Computing)自体が色々の課題と共に消えたので言葉として消えていったのかな、と。 その上で、生産性の向上は第3世代言語自体の進化で実施されてきたのではないかと。Rubyをはじめとしたスクリプト言語はかなり簡潔にかけるようになりましたし。

あと、そもそもDSLの一種だよね? と言う話もあり現代では同じような用途の言語はDSLと呼ばれるので表に出ることがないと言うのもあります。 仕様記述言語とかスキーマ定義言語とかクエリ言語系とかレイアウト系言語は当時なら4GLと呼ばれたのでHTMLやJSONなんかも4GLって呼べる気はします。

平成どころか昭和の技術じゃね? と言われそうですが平成の終わりに触ったので闇に消えることを祈って記事にしてみました。

それでは来年もHappy Hacking!

Oracle Code One 2018に参加してきました

JavaOneには結局ついぞ参加する機会がなかった私ですが、Oracle Code Oneになったのを契機にというかたまたまサンフランシスコ近辺に住んでるので参加してきました! 紆余曲折あって会社のブース展示とかの手伝いもしてたので、セッションを十全に回れた訳では無いですが、とても楽しかったです。

蟹Oneを始めコミュニティイベントにも参加できましたし。 今回は事前の準備というかチェックが足らなかったので次の機会にはもっといろんなアフターイベントに計画的に参加しないとです。 f:id:pascal256:20181021194604j:plain

個別に色々面白いセッションはあったのですが、それは良い記事がたくさん出てるでしょうから他に譲るとして、キーノート含めて全体のコメントとしては以下になります。

  • DKは依然としてFree, OpenJDKでのリリースも計画通り進んでる系の内容がJVM系キーノート含めては多かった。Javaは依然としてフリー
  • 結果として初めて知る新機能見たいなのはオープンであるが故になかったけど、進み方とかが聞けてよかった。Record型も早く来て欲しい
  • Jakarata EEの話はあんまり無しだが、地味にEclipse GlassFish 5 RC1のリリースSPECjEnterprise® 2018 Web Profileが出たりと足回りは強化中
  • 反面、マイクロプロファイルネタは多かった気がする。マイクロサービスも。Helidonは面白そうなのでちょっと試してみる
  • クラウドはかなり推してた。Oracle Open Worldではもちろんだけど、CodeOneのKeynoteまでOracle Cloudが侵食してた
  • Graalの現状が聞けてよかった。native-image + JRubyも行けるようなので今度試してみる
  • JFR/JMCのオープンソース化/API化が熱い(これは多分完全に主観)

ざっとこんな感じでした。 個人的には個別のセッションが聞けたのはやっぱよかったですね。いつもはキーノートだけ中継で見てるので。 もうちょっとJakarata EEネタを聴きたかったけど反面マイクロサービス系の話を聞きながらやはり自分のイベントドリブンシステム/非同期ドリブンシステムの知見が足らなさ過ぎると感じたので要強化ポイント。

マイクロサービス自体も少なくとも仕事上で触ってるアプリでは今の所不向きだから使う想定は無いのだけど、ツールチェインや開発スタイルを取り入れれるものはあるだろうから、そろそろちゃんと手を出さねば...

あと、お金をちゃんと払うとLST版のEOSLが9年くらいと余りに長いので、どうやってJDKのバージョンを上げていくかが今後の課題になってくるかなー。 EOSLがもう少し短ければ「しかたがないから」を理由に新陳代謝が維持できたんだけど、ちゃんとサポートされてしまうなら別な方法を考えないと負債が貯まりそう。

それではHappy Hacking!

クラウドというかマイクロサービス

API First, First, First !!! Fintechやモバイルに本気で対応するための APIを中心とした最新アーキテクチャ

docs.microsoft.com

www.slideshare.net

www.slideshare.net

www.slideshare.net

us.wantedly.com

tech-lab.sios.jp

Argoでkubernetesのジョブ管理を導入してみた

先日作った下記のサイトですが小さいながk8sでジョブを動かしてます。

koduki.hatenablog.com

ジョブの構成は

  1. BTCの情報を収集
  2. 学習&予測
  3. スコアリング

の3種類で1 -> 2-> 3の順番に依存があります。で、2の部分は当然アルゴリズムを増やすと増えますし並列実行したくなりますね。 とりあえずはKNNしか入れてなかったのでシンプルにk8sのcronだけで作ってたのですが、流石に管理が面倒なので決定木のアルゴリズムを追加したのに合わせてジョブ管理ツールを導入するすることにして見ました。

今回使ったのは下記のArgo workflowというk8sネイティブのワークフローエンジンです。

argoproj.github.io

JenkinsやRundeckなど比較的手になじんだツールを使おうかとも思ったのですが、折角なのでk8sネイティブで新気鋭のこいつを使うことにしました。 いろんな設定が出来るんですが今回は単純にDAGで依存を付けただけです。

gist9327b361396b07a8e0040adcf6c24ce7

するとargo-uiからは以下のようなワークフローで確認できます。

f:id:pascal256:20180917095511p:plain

簡単ですね。

現時点ではArgo workflow自体はスケジューリングをサポートしてないのでそちらはk8sのcronジョブでjessesuen/argocliをベースに上記のyamlファイルをコンテナ内に入れてargo submitさせることで対応しています。

k8sをベースに作成してしてあるのでargoコマンドじゃ無くてそのままkubectlも使えたり、CPUやメモリのリソース制限やボリュームなどもそのまま利用できるので今後に結構期待のツールです。

まとめ

今回はとりあえず依存実行が欲しかったので入れただけですが、このツール自体は今後色々野心的なところを狙っていきそうなので期待大です。 テキストなのでDockerで管理しやすいのもGoodですね。

一方で、現時点ではargo-uiでは純粋に実行結果を見ることしかできなくて、実行前のネットワークの確認もできなかったり、1ファイルに書くというフォーマットでは、人間がわかる範囲で管理するのは大規模ジョブだと厳しいのかな、とも思ったり増します。 まあ、シェルかなんかで組み立てるなりやりようはありそうなのですけどね。何れにしても個人で使うには十分役立ちそうな感じです。

それではHappy Hacking!

参考