Argoでkubernetesのジョブ管理を導入してみた
先日作った下記のサイトですが小さいながk8sでジョブを動かしてます。
ジョブの構成は
- BTCの情報を収集
- 学習&予測
- スコアリング
の3種類で1 -> 2-> 3の順番に依存があります。で、2の部分は当然アルゴリズムを増やすと増えますし並列実行したくなりますね。 とりあえずはKNNしか入れてなかったのでシンプルにk8sのcronだけで作ってたのですが、流石に管理が面倒なので決定木のアルゴリズムを追加したのに合わせてジョブ管理ツールを導入するすることにして見ました。
今回使ったのは下記のArgo workflowというk8sネイティブのワークフローエンジンです。
JenkinsやRundeckなど比較的手になじんだツールを使おうかとも思ったのですが、折角なのでk8sネイティブで新気鋭のこいつを使うことにしました。 いろんな設定が出来るんですが今回は単純にDAGで依存を付けただけです。
gist9327b361396b07a8e0040adcf6c24ce7
するとargo-uiからは以下のようなワークフローで確認できます。
簡単ですね。
現時点ではArgo workflow自体はスケジューリングをサポートしてないのでそちらはk8sのcronジョブでjessesuen/argocli
をベースに上記のyamlファイルをコンテナ内に入れてargo submit
させることで対応しています。
k8sをベースに作成してしてあるのでargoコマンドじゃ無くてそのままkubectlも使えたり、CPUやメモリのリソース制限やボリュームなどもそのまま利用できるので今後に結構期待のツールです。
まとめ
今回はとりあえず依存実行が欲しかったので入れただけですが、このツール自体は今後色々野心的なところを狙っていきそうなので期待大です。 テキストなのでDockerで管理しやすいのもGoodですね。
一方で、現時点ではargo-uiでは純粋に実行結果を見ることしかできなくて、実行前のネットワークの確認もできなかったり、1ファイルに書くというフォーマットでは、人間がわかる範囲で管理するのは大規模ジョブだと厳しいのかな、とも思ったり増します。 まあ、シェルかなんかで組み立てるなりやりようはありそうなのですけどね。何れにしても個人で使うには十分役立ちそうな感じです。
それではHappy Hacking!
参考
流行りの技術を集めてビットコインの予想サイトを作ってみた
最近、ビットコインが久しぶりに80万円を超えて調子が良いですね!
そう言う訳でと言う訳では無いのですがビットコインの予想サイトを作ってみました。
最近、特に自分のサービスを運用にしてなかったので新し目の技術をHello World 以上には使えてないなー、てのが最大の動機です。 と言う訳で不必要にいろんな技術を使っています。
- バッチはk8sベースで作成
- 予測エンジンはk8sベースのバッチとしてskleanで作成。I/FをObject Storageにしてアプリ全体とは疎結合に。
- バックエンドはFaaSを試したかったのでCloud Functions
- フロントエンドはVue.js + Chart.jsで作成してFirebase Hostingにデプロイ。AjaxもJQueryとか使わずにFetchAPIで。
と行った感じです。FaaSを使ってると言ってもまだそのまま叩いてるだけで、circuit breakerとかも入れて無いのでこの辺もおいおい。 今までのキャッチアップが足らなすぎて、些細な事にハマって結構時間を費やしてしまったので備忘録としてそのうちまとめよう。一応、バッチに関しては下記にちょっとメモを書いてる
しかし、GCPでまとめてるとはいえ、色んなサービスを使ってるのでデプロイや管理が面倒。 なんと無く、監視も面倒な予感がするのでその辺の知見が貯まるといいな。統合管理的なものはなんかある気がするし。
ちなみにこのサイト自体は予測アルゴリズムを増やして行って胡散臭い予想屋サイトとしてのエクスペリエンスを高めていきたい!
それではHappy Hacking!
僕の考えた最強のDB for 会員むけシステム
ソシャゲとかその他C2Bな会員向けシステムにとって最強のDBはどういうのだろうか? とTwitterでつらつら考えてたのでブログにもまとめ直してみる。
SparkやHDFSみたいにデータのあるところで処理出来るDBでかつトランザクションを曲がりなりにもサポートしたものってどういうのがあるんだろ? ソシャゲとか会員系サービスって極論会員毎に専用のDB作って全部ストアドで処理すれば無限にスケールするよなー、と思いながら
— 紅月さん@がんばらない (@koduki) August 17, 2018
理想的なイメージは1会員で1DBを割り当てて全てストアドプロシージャで処理すること。 自分でユーザIDとかでシャーディングすればできなくは無い気がする。
こんな事が出来ると嬉しい
- テーブルのレコード単位で細かくロックを制御する必要は不要でテーブルを超えてユーザID単位でロックが掛かって欲しい
- データをDBサーバやアプリサーバに取得する処理が無駄なのでストアド的(というかイメージはSpark)にデータがあるストレージで処理して欲しい
- 上記を効率的に実現するためにユーザID単位のデータは全て同じストレージに居て欲しい。あとマスタテーブルは全てのストレージに居て欲しい
- ユーザ単位でロックを掛けると一部の処理は少し長めのとある処理より優先したい時はあるのでトランザクションを割り込ませて既存ロジックは再実行したい
- そうは言っても集計処理はしたいのでHANAがしてるみたいに分析が得意なDBにリアルタイム連携したい
- インサートやデリートでインデックスのロックとか他のレコードに影響を与えないで欲しい。
でもって以下のことは許容できる
- 極端な低レイテンシーは要らない。ビジネスロジック混みで数百ms(もちろんロジック次第では数秒)程度で良い。
- 強い一貫性の保証は同一ユーザIDのものだけで良い
- 分析用DBへの連携は非同期で数秒程度の差分があっても大丈夫。どうせ集計だし
- where句は無くても良い。キーアクセスだし。
- ユーザ自体が瞬時に大量に増えた時にユーザ登録処理速度が低下するのは仕方ない。普通無いだろうし。
今の所イメージに一番近いのはAzureのCosmos DBの気がする。
GoogleのCloud Spannerはストアドは無いみたいだし。まあ、ストアド無くてもFunctionsとかで処理すれば関連するデータが同じストレージにあってJOINペナルティとかが無いならあまり問題にならないかも。ドキュメントDBだとユーザーの下が無限に増えるからストアド的なのが無いとやはり厳しいだろうけど。
ユーザ単位で処理を考えるとやっぱりドキュメントDBやオブジェクトDBのがしっくり来るなぁ。 基本的にはユーザ単位でアトミックでロックやトランザクションが効けば良くてデータが同じ箇所に集中してる必要があるとすると、データモデルはリレーショナルよりはオブジェクトモデルのが物理実体とも近いから作りやすそうだし。
○○なユーザを抽出って処理とかでユーザを跨ぐことはあるけどそれって結局抽出した後に集計するかユーザ単位に処理するかなので、 集計ならDWHで集計で良いし、最終的にユーザ単位の処理なら会員数分の並列で良い気がする。
こういう特製のデータベースってなんか無いだろうか?
自分で作るならsqliteあたりを包んだdockerコンテナを作ってユーザ毎にコンテナ作製して、ルーティングアプリを手前に置いてgRpcで通信すれば良さそう。 それならデータ量が多いユーザは別なPodへ移動させるとかも出来るから1ユーザーが1台のマシンのストレージを超える(インメモリでも数百GB、SSDとかならTBクラス))容量にならない限りは、この方式でスケールするから普通のシステムなら破綻はしなさそう。 その場合、DWHへの連携はトリガーを書きまくれば良いのかな?
ただ、詰まるところシャーディングだからテーブルスキーマの変更はちょいめんどそうかも。
でも、スキーマ変更をローリングでして困るケースも実はあんまり無い気がするので万能選手を期待しなければ結構良い感じになる気がしてきた。
まとめ
システムがデカくなるとデータが増えて処理性能が落ちるんだけど、本来ならばほとんどの処理は横にスケールする筈だよなぁ、と思って自分の理想の仕組みを考えてみました。
全く同じものは世になかったとしても、一回考えると今後の技術要件を探る時には役立ちそうですし。特にクラウド系分散DBは似たような課題をクリアしようとしてのものな気がするし。
それではHappy Hacking
nodejsの"nobody" does not have permission to access the dev dir
gypなライブラリをDockerでnpmからインストールする時に-g
付けてグローバルに出そうとすると下記のエラーが出て正常にインストールが出来なかった。
gyp WARN EACCES user "nobody" does not have permission to access the dev dir "/usr/lib/node_modules/firebase/node_modules/grpc/.node-gyp/10.5.0" gyp WARN EACCES attempting to reinstall using temporary dev dir "/usr/lib/node_modules/firebase/node_modules/grpc/.node-gyp"
同じ問題には下記でも出てたみたいで、--unsafe-perm
にしてやれば良いみたい。
というわけで以下のような形でDockerfileを作ればOK.
RUN npm --unsafe-perm -g install ...
しかし、面倒ね。