Fluent Bitにmruby Filter Pluginを追加し、フィルタ処理をmrubyで書けるようにする

Fluent Bitという、IoT・組み込み向けのCで書かれた軽量なFluentdがある。Cloud Native Meetup Tokyo #1 で存在を知ったのだが、知ったときに「mruby組み込めそうだな」と思ったのである。Cなので、プラグインを書いて組み込む場合は自分でビルドする必要があるが、mrubyでプラグインを書いて動的に読み込めるならさらに便利になるかもしれない(Goでプラグインを書くこともできるし、Lua Filter Pluginが既にあるが)。ということで興味を持っていたのだけどRubyKaigiなどでばたばたしており、仙台から戻った翌日くらいから少しずつFilter Pluginとして組み込んで昨日くらいにプロトタイプが動いた。Cを書くのが10年ぶりくらいで大変だったけど、楽しかった。

動作光景

なにはともあれどう動くのかを見てみる。まず、以下のようなtest.rbを用意する。fooメソッドの引数はこの3つで固定で、lua filter pluginと同じ。受け取ったレコードを加工して返す。

次にconfigファイル。filter pluginとしてmrubyを指定して、読み込むスクリプトファイルと実行するメソッドを設定している。

そして、これを実行すると、加工されたレコードがstdoutに出力されていることがわかる。

もちろん、このようなプラグインをCで書くこともできるが、mrubyで書けると便利だろう。

mruby Filter Pluginのメリット

FluentdはRubyでプラグインが書ける。また、DigdagやEmbulkでもRubyを使える(EmbulkはjRubyだっけ)。となるとFluent BitでもRubyが使えると、Rubyを書く人にとってうれしい。プラグイン部分を実行ファイルの外に置けるのも利点だろう。修正の度にビルドしなくてもよいというのはありがたいのではないか。mrbgemsの資産を使えるのも結構便利かもしれない(利用する際にビルドして組み込む必要があるが)。

mruby Filter Pluginのデメリット

mrubyなので、Rubyと違う部分でつまづくことはあるだろう。デメリットか、というとそこまででもないと思うけど。パフォーマンスはどうなんだろうか。測定してみないとわからないが、さすがにCで書いたプラグインに比べると遅くなるか?パフォーマンスが必要な場合はCやGoで書く、という手が使えるのでそこまでデメリットでもなさそう。Lua Filter Pluginと比べるとどうか?という話もある。

実装

Filter Pluginにはcb_init、cb_filter、cb_exitという3つのコールバックがある。fluent-bitの起動時にcb_initでmrb_stateを初期化、スクリプトの読み込みとロードを行う。cb_filterではスクリプト内のメソッドを呼び出して、Parser Pluginから渡されたレコードを処理する。cb_exitではmrb_stateを終了するなど、後片付けを行うという流れになるだろう。filter部分でmrb_stateの初期化やスクリプトの読み込みなどを行うことも可能だが、オーバーヘッドとなるのでinitで行うのがよいだろう。

コード全体はこのdiffを参照。

cb_mruby_init

initはそんなにややこしくない。コメントの通り。

cb_mruby_filter

大まかな流れは以下の3ステップ。

  1. messagepack形式のレコードが引数として渡されるので、これをmrb_value(mrubyのvalur)であるvalueやdouble型のタイムスタンプ、文字列型のタグに変換する。
  2. 次に、設定ファイルで指定したスクリプト内のメソッドを呼び出し、value、タイムスタンプ、タグを引数として渡す。
  3. mrb_valueであるメソッドの実行結果などを次のプラグインに渡すためにmessagepackに変換する。

messagepackをmrb_valueに変換するのがmsgpack_obj_to_mrb_value。書きかけで、文字列とマップ以外も実装する必要があるが、雰囲気は伝わるか。

スクリプトが返すmrb_valueをmessagepackに変換する。

cb_mruby_exit

closeしたりfreeしたりする。

個人の感想です

mrubyの組み込み自体はすんなりできた。Fluent Bitのビルドまわりやプラグインの仕組みが綺麗で、開発開始時点でほぼつまづかなかった(cmakeまわりで少し悩んだ)し、何もしない新しいプラグインを追加するだけならすぐにできた。ミドルウェアにmrubyを組み込む方法も非常に参考になった。苦戦したのはmessagepackからmrubyへの変換、その逆の所。おそらく一番苦戦するだろう、と思っていたが予想通りだった。とはいえ、Cに慣れていて、いきなり組み込み始めるのではなくある程度mrubyとmsgpackまわりを事前に調べていればそこまで苦戦はしないのではないかな。

今後について

思いつきで実装を始めたので、プロトイタイプができて結構満足してしまった… Fluent Bit自体をちゃんと使ってみて、必要そうなら機能提案する、というところか。どのくらい需要があるのだろうか?

KubernetesのNamespaceをRuby DSLで管理できないか試してみた

普段、KubernetesのNamespaceはNamespace毎にyamlファイルを用意し、kubectl applyコマンドでディレクトリを指定して更新したりしている。しかし、この方法だとyamlを削除してもKubernetes側のリソースは更新されず、不便だなと感じていた。そこで、codenize.toolsのようにRuby DSLを使ったNamespace管理を試してみた。作ったツールはtakaishi/heyaだ。

まず、以下のようにNamespaceが存在しているとする。

ここで、以下のようなHeyafileを用意する。

heyaコマンドをドライ・ランする。Namespaceの新規作成、削除、ラベルの更新などを確認できる。

ドライ・ランオプションを外して実行。

Namespace一覧を見ると、Heyafileで定義した通りになっていることがわかる。

普段codenize.toolsを使っているので、Ruby DSLで定義した通りにKubernetes側の状態が収束してくれるのはなじみのある動きでわかりやすい。UserやRBACなども同じように管理できるとおもしろいかもしれないなー。

と、ここまでやってみて、applyコマンドに–pruneオプションがあることに気づいた。まだアルファ版という状態だが、これを使えばマニフェストにないリソースを削除してくれるようだ…これでいいのではないか?

Hashicorp VaultのPKI Secerts Engineを試す

HashicorpのVaultはPKI(Public Key Infrastructure、公開鍵基盤)として利用できるらしい。今回はRoot CAの作成、サーバー証明書の作成、クライアント証明書の作成と失効を試した。間違ってたらゴメンなさい。Vaultについての概要はWEB+DB PRESS Vol.104に記事が書かれているので読むとよさそう。

準備

Vaultのバージョンはv0.10.1。macOS用のバイナリをダウンロードして、PATHの通った場所に置いた。

curlはHomwbrewでインストールし、opensslを使うようにしている。

Homebrewでcurlをインストールした時のコマンド。

nginxもHomebrewでインストールした。

Vault serverサーバーの初期化・ログイン

まずはvault serverを用意する。ファイルで諸々を設定。バックエンドにはファイルを使うことにした。また、vaultのAPIをTLSなしで利用できるようにしておく。

シュッと起動。

ターミナルの別セッションを開いて、initからのunseal、login。このあたりは長いので実行コマンドだけ。

これで利用準備が整った。

Root CAの作成

まずはRoot CAを作るのだが、vaultでPKIを有効にする必要がある。vault secrets enableコマンドを使う。

これで、PKIタイプのsecretとしてalpacaができた。

Generate Root APIを使ってRoot CAを作る。

certificate endpoint / crl distribution points などを設定する。set url apiを使う。

Root CAまわりはこれでOK。

SSLサーバー証明書を作る

まず、Create Role APでロールを作る。

Generate Certificate API でCertificateを作る。Private Keyは保存されないので、コマンド実行後に出力されたものを自分で保存しておくこと。certificateとprivate_keyに対応するvalueをファイルに保存する。alpaca.repl.info.crt と alpaca.repl.info.keyとする。

nginxに設定する

nginx.confを用意する。ssl_certificateとssl_certificate_keyに先ほど作成したcertificateとprivate_keyを設定する。

nginxを起動して…

alpaca.repl.infoでnginxにアクセスできるよう、hostsに追記しておく。

ここで、curlを使ってアクセスしてみる。nginxで設定したサーバー証明書の検証ができないので、以下のようなエラーとなる。

insecureオプションをつけて検証しないようにするとアクセスできる。

ここで、Root CAのcertificateをca.pemとして用意し、–cacertオプションで指定する。これにより、サーバー証明書の検証を行うことができ、アクセスできる。

クライアント証明書で認証する

認証したい。まずは認証に失敗してアクセスできないことを確認する。nginx.confに設定を追加する。ここではca.pemはRoot CAのcerfiticateを使っている。

アクセス不可になることを確認する。

クライアント用の証明書と秘密鍵を作る。サーバー証明書を作った時と同様、ロールを作成して証明書を作る。

certificateとprivate_keyをファイルに保存し、curlの–certと–keyオプションで指定することでアクセスに成功する。

クライアント証明書を失効させてみる

認証で使うのだから、何かあったときには失効させたい。revoke certificate APIがあって、これを使えば失効させられる。

失効できたが、これだけだとまだアクセスできる。CRLをnginxが参照していないためである。

API経由でcrl.pemを取得する。

見てみると、失効したシリアルナンバーである”37:d2:7c:db:c6:cf:ad:cd:21:00:5c:a6:63:2d:5b:51:f1:e2:71:87″がrevoked certificatesに含まれていることがわかる。

nginxに設定を追加して、crlを見るようにする。

再度アクセスを試みるが、bad requestとなり、繋がらなくなることがわかる。

ひとまず動いたぞ!という記録だが、結構使えそうだなあという感触を得た。Kubernetesのような、いろんなコンポーネントがバシバシ証明書を必要とする環境で役立ちそうである。今回は証明書の配置を手動で行ったが、Consul Templateと組み合わせて自動配布、なんてこともできるので夢が広がるなあ。また、中間CAを扱うこともできるようなので、そちらも試しておきたい。

LINE Developer Meetup #32 で アクセス頻度予測を用いてサーバーを自動増減する「計画的スケーリング」の話をしました

2018年4月24日に開催されたLINE Developer Meetup #32 で、こんなこともあろうかと、サーバーは予め増やしておいた 〜アクセス頻度予測を用いてサーバーを自動増減する「計画的スケーリング」のその後〜というタイトルで登壇しました。

去年ペパボ研究所のメンバーである三宅さんと一緒に取り組んだ内容と、今年に入ってからトライした改善活動について紹介する、という内容です。残念ながら改善した結果が登壇までに出せず、ズコーというオチになってしまったのですが…

補足:自動ビルドしたイメージのベリファイ方法について。自動ビルドしたイメージが壊れていると目も当てられないので、ちゃんとベリファイしましょうという話をしたのですが、肝心のベリファイ方法について触れていませんでした。今のところ2つの方法でベリファイしていて、まずはサーバー内の各種プロセス(unicornやtd-agent、mackerel-agent、etc…)が正常に動いているかのチェック。これは、Consulのヘルスチェック機能を用いています。次に、そのイメージから起動したサーバー上のアプリケーションに、外からアクセスできることのチェック。サーバー内部のチェックだけではなく、外部からもチェックするという2段構えをとっています。

今回登壇するために初めて福岡に来たり、思わぬ所で繋がりがあったりと大変楽しい体験ができました!

minikubeを使ってローカルでKubernetes v1.9.4を動かす(2018年4月版)

会社で検証用のKubernetes環境を作った。それとは別に、手元でも試せるようにしておきたいのでminikubeを使って用意する方法を記録しておく。

バージョン

各ソフトウェアのバージョンは以下の通り。

  • macOS: High Sierra 10.13.4
  • VirtualBox: 5.2.10 r122088 (Qt5.6.3)
  • minikube: v0.25.2
  • kubernetes: v1.9.4

minikubeをインストールする

2018年04月21日現在ではminikubeの最新バージョンはv0.26.1なのだが、これだとKubernetesのv1.9.4が起動しなかった。そのため、v0.25.2を使う。Release v0.25.2 · kubernetes/minikube から実行ファイルをダウンロードし、実行可能パスに置く。実行権限も付与する。

macOSの場合、Kubernetesを動かす環境としてHyperkit / xhyve / VirtualBox / VMWare Fusion を使える。おそらく、VirtualBoxをインストールしている人が多いと思うので、VirtualBoxを使う。

以下のように、minikubeとclusterがRunningになっていればOK。

kubectlからminikube環境に接続する

kubectlから確認する。kubectlは接続先のクラスターや認証情報を「コンテキスト」という単位で管理している。minikube startすると、以下のように、minikubeコンテキストを使う状態となっているはず(他のコンテキストは人によって異なる)。

minikubeというノードがあり、ReadyとなっていればOK。

デモ環境を動かす

何か動かしてみたい。今回はmicroservices-demo/microservices-demoを動かしてみよう。

Podが全て起動するのを待つ。状態は以下のようにして確認しよう。

全Podが起動状態となったら、以下のコマンドを実行する。ブラウザで靴下のショップページが開くはずだ。

minikube環境を停止する

最後に、minikube環境を停止して、終わり。

 

追記

というコメントをいただいたのでbootstrapperオプションを指定した所、minikube v0.26.1でもkubernetes v1.9.4を起動することができた。すぱぶらさんありがとうございます!

入門 Kubernetes

入門 Kubernetes

posted with amazlet at 18.04.21
Kelsey Hightower Brendan Burns Joe Beda
オライリージャパン
売り上げランキング: 2,839