mod_mrubyとngx_mrubyのRPMリポジトリをpackagecloudに作った

マネージドクラウドのチームにJOINして、1ヶ月たちました。

ツイートから周りからは「楽しそうですね」と勘違いされているようですが、アーキテクチャや技術スタックのキャッチアップに大変な毎日を送っています。楽しいです。

Webサーバに機能を追加するということ

ところで、広く知られていることですが、マネージドクラウドではngx_mrubyがかなり活用されています。

何をもって活用されていると言えるのかは要出典ですが、NGINXが単なるWebサーバではなく「別の機能を持った何か」に見えるくらいには使われています。

「Webサーバに機能を追加する」という感覚は一般的なWebアプリケーションの上で生きてきた自分としては新鮮で、「最近のフレームワークは例えばMiddlewareというような階層構造で機能を付与するものがあるが、その一部をさらにその外に移譲しても良いんだ」という面白さがありました。

思えば、AWSでサーバーレスアーキテクチャを構築する上でも、機能を

  • CloudFrontのLambda@Edgeに持たせるのか
  • API Gatewayに持たせるのか
  • HTTPリクエストから発火したAWS LambdaのFunctionに持たせるのか
    • さらにそのFunction内のmiddyで多層化されている
  • はたまたバックのDynamoDBのストリームからイベント発火したAWSLambdaに持たせるのか

と、機能を持たせる場所というのがシステム全体のアーキテクチャを考える上で重要で、できれば選択肢が多いほうがより構成の選択肢が増えるのは実感としてわかっていました。

「もしかして、これは、そこまで規模の大きくないWebアプリケーションを開発する上でも、アーキテクチャとして『Webサーバに機能を追加する』という選択肢を持っていたら強いのでは?」

と思って、PHPカンファレンス福岡2018に「プログラマブルWebサーバ -Webサーバに機能を追加してみよう-」というタイトルで応募しました。

そして、不採択でした。残念。

mod_mruby / ngx_mrubyというレイヤー

mod_mrubyやngx_mrubyというレイヤー、GMOペパボではMiddleware Configuration as Codeと呼ばれて活用されています。

なんだか新しい、とっつきづらいもののように聞こえるのですが、作者の @matsumotory から聞いてちょっとおもしろかったことがあります。

mod_mrubyのApacheへの組み込まれ方は、実はmod_phpと同じだそうです。

Apacheが実行する(主に)Webアプリケーション用のインタプリタとして使われることを目的としているのか、Apacheの処理のさまざまな箇所でフックやフィルタように動かす用のインタプリタとして使われることを目的としているのかの違いだけです。

「mod_phpと同じだ」とか、途端に親近感がわきます。

とはいえ自前ビルドは技術採用のハードルになる

mod_mrubyもngx_mrubyもApacheやNGINXに組み込みます。

そうすると、「Webサーバも自前ビルドなのか?」「そうでなくてもmod_mrubyやngx_mrubyも自前ビルドなのか?」となり、運用を考えると躊躇してしまいます。

自前ビルドより yumapt-get を使いたいです。よね?

そういったわけでRPMリポジトリを作ってみました。

作ったRPMリポジトリ

今回作ったRPMリポジトリの要件は以下です。

  • ターゲットはCentOS7とCentOS6
  • ApacheCentOS公式のRPMリポジトリhttpd、NGINXはNGINX公式のRPMリポジトリのnginxが使えること
    • かなり重要。今運用しているシステムの構成に追加採用できる可能性が飛躍的にあがる
  • 全自動でhttpd、nginx、mod_mruby、ngx_mrubyのリリースを検知し、その組み合わせのRPMをビルドし使えるようにすること
    • パッケージメンテナの負荷をゼロに。RPMリポジトリがなくならない限り更新されていきます。

そのために、mod_mrubyとngx_mrubyの以下の機能をあきらめています。

  • mrbgemの追加ビルド
  • ngx_mrubyのTCPロードバランシング機能

mrbgemについては、もう少し知見が溜まったら、ゴールデンAMIならぬ「ゴールデンビルド」を決めてリリースしようと思います。

ngx_mrubyのTCPロードバランシング機能については、現時点ではNGINX自体のビルドオプションを変える必要があるため、なかなか難しそうです。

それでも十分強力なので、それなりの意義があると思っています。

作ったRPMリポジトリは以下です。

packagecloud.io

packagecloud.io

使い方

よくある外部RPMリポジトリの利用と同様に、RPMリポジトリの登録とインストールの2STEPになります。

RPMリポジトリの登録

packagecloud の機能をフル活用しているので、

mod_mrubyの場合は

$ curl -s https://packagecloud.io/install/repositories/k1low/mod_mruby/script.rpm.sh | sudo bash

ngx_mrubyの場合は

$ curl -s https://packagecloud.io/install/repositories/k1low/nginx-module-mruby/script.rpm.sh | sudo bash

で終わりです。

インストール

mod_mrubyの場合は

$ sudo yum install mod_mruby

ngx_mrubyの場合は

$ sudo yum install nginx-module-mruby

で終わりです。

モジュールの有効化

Apacheの場合は、confに

LoadModule mruby_module modules/mod_mruby.so

NGINXの場合は、eventディレクティブの前に

load_module modules/ndk_http_module.so;
load_module modules/ngx_http_mruby_module.so;

と追記すれば有効化されます。あとは使うだけです。

簡単ですね!

作ったときのはなし

以下は特に読む必要はないはなしです

実際に動いているCIのスクリプトは以下のリポジトリになります。

github.com

github.com

RPMパッケージを作るだけなのにそれなりに大変でした。

CentOSのGitやRubyのバージョンが古くて辛い

Rubyのバージョンが古くてpackage_cloud.gemがインストールできなかったり、Gitが古くてCircleCIがまともに動かなかったり、全然本流とは違うところで躓くことに。

そこはTwitterでCircleCIマスターの @kunit から直球の解法を教えてもらって、なんなく解決できました。ありがとうございました!

フィードフォースの皆さんありがとうございます!

CircleCIのScheduled Workflowが最高

今回作ったRPMリポジトリの「全自動化」はCircleCIのこの機能を知っていたからなのですが、もう最高です。

circleci.com

ようはcronでビルドを定期実行してくれるという機能です。うまく .circleci/config.yml を書ければいろいろな用途に使える機能なのでオススメです。

モジュールの利用にもSELinuxのポリシー設定が必要

RPMリポジトリからモジュールをインストールするだけではダメで、そのモジュールに適切にSELinuxのポリシーを設定する必要があるということを知りました。

/var/log/audit/audit.log を見たり、audit2allow で必要ポリシーを見つけたり、 ls -Z で他のモジュールとポリシーを比較したり、少しはSELinuxと仲良くなれたかもしれません。

NGINXのダイナミックモジュールのロードにはApacheのモジュールよりも一手間以上が必要

ngx_mrubyのダイナミックモジュールについては、ほぼ以下の記事で完結しています。本当にお世話になりました。

medium.com

実際に自分で手を動かしてみると、本当に面倒でした。

Dockerのバグ?にあたる。そしてCircleCIでは治っていない

やろうとしていたことはmod_mrubyのRPMビルドのために centos/7 イメージでhttpd-develを入れようとしただけなのですが、依存関係にあるhttpdがインストールされるときにエラーになるというものでした。

これは実は既に解決された問題のようで、ホストOS側のUbuntuでのAUFSの問題だったようです。

普通なら「じゃあホストOSのUbuntuを最新にしようか」ということになるかと思いますが、CircleCIのホストOSをいじれるわけはなく、仕方なくhttpdソースコードを取ってくるという形に変更しました。


たった2つのRPMリポジトリを実現するためだけに、なかなか大変でした。

リポジトリのパッケージ管理者の方には頭が上がりません。

なお

このRPMリポジトリの成果の一部はGMOペパボ福岡の有志開発合宿で作成されたものです。