🌊

コンテナ上でfluent-plugin-generateコマンドを実行する

2023/01/22に公開

Fluentdプラグインgemを作りたい

Fluentdプラグインを自作してgemとしてパッケージングしたい場合、Fluentd実践入門ではfluent-plugin-generateコマンドを使う方法とbundle gemコマンドを使う方法が紹介されている。
特にFluentdプラグインの内部構成にあまり詳しくない場合は、fluent-plugin-generateコマンドを使えば必要なファイルを自動で生成してくれるので開発に着手しやすく楽できる。

しかし、fluentd(正確にはtd-agent)をdebパッケージでインストールした場合はfluent-plugin-generateコマンドはインストールされない。別の方法でセットアップする必要がある

Docker上でコマンドを実行したい

fluent-plugin-generateコマンドを利用するために必要なセットアップとして、ソースコードからビルドする方法かgemとしてインストールする方法がある。どちらを用いてもよいがfluentd自体の開発をしたいわけではないのでgemを使ってインストールするのが楽そう。

だが、それ以外の方法としてdockerで実行してしまう方法もある。DockerHubで公開されている fluent/fluentdのコンテナイメージには、fluent-plugin-generateコマンドも含まれている。
これを使えばgemとしてインストールしなくてもよいのではと考えた。

fluent-plugin-generateコマンドを実行する

inputプラグインawesomeを作成するためのコマンドとして以下のように実行し、カレントディレクトリに生成ファイルを出力してみる。

$ docker run -it --rm -v $(pwd):/work -w /work fluent/fluentd:v1.15-1 fluent-plugin-generate input awesome
/usr/lib/ruby/3.1.0/fileutils.rb:243:in `mkdir': Permission denied @ dir_s_mkdir - fluent-plugin-awesome (Errno::EACCES)
	from /usr/lib/ruby/3.1.0/fileutils.rb:243:in `fu_mkdir'
	from /usr/lib/ruby/3.1.0/fileutils.rb:221:in `block (2 levels) in mkdir_p'
	from /usr/lib/ruby/3.1.0/fileutils.rb:219:in `reverse_each'
	from /usr/lib/ruby/3.1.0/fileutils.rb:219:in `block in mkdir_p'
	from /usr/lib/ruby/3.1.0/fileutils.rb:211:in `each'
	from /usr/lib/ruby/3.1.0/fileutils.rb:211:in `mkdir_p'
	from /usr/lib/ruby/gems/3.1.0/gems/fluentd-1.15.3/lib/fluent/command/plugin_generator.rb:42:in `call'
	from /usr/lib/ruby/gems/3.1.0/gems/fluentd-1.15.3/bin/fluent-plugin-generate:5:in `<top (required)>'
	from /usr/bin/fluent-plugin-generate:25:in `load'
	from /usr/bin/fluent-plugin-generate:25:in `<main>'

これだけだとパーミッションエラーになる。fluentdコンテナはfluentユーザで動作するので、書き込み権限がなくファイル出力できない。
これを解決するためにカレントディレクトリのモードを777にして誰でも書き込めるようにして試してみる。

$ chmod 777 .
$ docker run -it --rm -v $(pwd):/work -w /work fluent/fluentd:v1.15-1 fluent-plugin-generate input awesome
License: Apache-2.0
	create Gemfile
/usr/lib/ruby/gems/3.1.0/gems/fluentd-1.15.3/lib/fluent/command/plugin_generator.rb:137:in ``': No such file or directory - git (Errno::ENOENT)
	from /usr/lib/ruby/gems/3.1.0/gems/fluentd-1.15.3/lib/fluent/command/plugin_generator.rb:137:in `user_name'
	from (erb):41:in `template'
	from /usr/lib/ruby/3.1.0/erb.rb:905:in `eval'
	from /usr/lib/ruby/3.1.0/erb.rb:905:in `result'
	from /usr/lib/ruby/gems/3.1.0/gems/fluentd-1.15.3/lib/fluent/command/plugin_generator.rb:80:in `template'
	from /usr/lib/ruby/gems/3.1.0/gems/fluentd-1.15.3/lib/fluent/command/plugin_generator.rb:53:in `block (2 levels) in call'
	from /usr/lib/ruby/3.1.0/pathname.rb:571:in `block in find'
	from /usr/lib/ruby/3.1.0/find.rb:49:in `block (2 levels) in find'
	from /usr/lib/ruby/3.1.0/find.rb:48:in `catch'
	from /usr/lib/ruby/3.1.0/find.rb:48:in `block in find'
	from /usr/lib/ruby/3.1.0/find.rb:43:in `each'
	from /usr/lib/ruby/3.1.0/find.rb:43:in `find'
	from /usr/lib/ruby/3.1.0/pathname.rb:571:in `find'
	from /usr/lib/ruby/gems/3.1.0/gems/fluentd-1.15.3/lib/fluent/command/plugin_generator.rb:45:in `block in call'
	from /usr/lib/ruby/gems/3.1.0/gems/fluentd-1.15.3/lib/fluent/command/plugin_generator.rb:43:in `chdir'
	from /usr/lib/ruby/gems/3.1.0/gems/fluentd-1.15.3/lib/fluent/command/plugin_generator.rb:43:in `call'
	from /usr/lib/ruby/gems/3.1.0/gems/fluentd-1.15.3/bin/fluent-plugin-generate:5:in `<top (required)>'
	from /usr/bin/fluent-plugin-generate:25:in `load'
	from /usr/bin/fluent-plugin-generate:25:in `<main>'
$ ls
fluent-plugin-awesome
$ ls fluent-plugin-awesome/
Gemfile  LICENSE

今度はディレクトリの作成および一部ファイルの生成は成功しているが、gitのエラーになっている。
ソースコードを確認してみると、gitコマンドを実行してgitユーザ名を取得しようとしている。コンテナ上ではgitがインストールされていないので、このコマンドの実行に失敗している。

これを解決するためにgitをインストールしたコンテナイメージを準備して実行してみる。
具体的なDockerfileとして以下のようなものを準備する(alpineベースだと面倒なのでdebianベースに変更した)。

FROM fluent/fluentd:v1.15-debian-1

USER root
RUN apt update \
    && apt-get install -y git
USER fluent

その上でコンテナイメージをビルドして再度fluent-plugin-generateコマンドを実行する。

$ docker build -t fluent-plugin-generate .
(実行結果省略)
Successfully tagged fluent-plugin-generate:latest
$ docker run -it --rm -v $(pwd):/work -w /work fluent-plugin-generate fluent-plugin-generate input awesome
License: Apache-2.0
	create Gemfile
	create README.md
	create Rakefile
	create fluent-plugin-awesome.gemspec
	create lib/fluent/plugin/in_awesome.rb
	create test/helper.rb
	create test/plugin/test_in_awesome.rb
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint: 
hint: 	git config --global init.defaultBranch <name>
hint: 
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint: 
hint: 	git branch -m <name>
Initialized empty Git repository in /work/fluent-plugin-awesome/.git/

ブランチ名に関するhintは出力されているが、プラグイン開発に必要なファイルは無事生成されている。
とはいえ、ディレクトリパーミッションを変更したり、コンテナイメージのビルドを実行したりと面倒。どうせプラグイン開発・テストを実行するためにrubyの開発環境は必要なので、gemでインストールするのが早い。

$ gem install fluentd
Fetching fluentd-1.15.3.gem
Successfully installed fluentd-1.15.3
Parsing documentation for fluentd-1.15.3
Installing ri documentation for fluentd-1.15.3
Done installing documentation for fluentd after 2 seconds
1 gem installed
$ fluent-plugin-generate input awesome
(以下省略)

まとめ

  • fluentdプラグイン開発にはfluent-plugin-generateコマンドを利用する
  • コンテナ上でfluent-plugin-generateコマンドを実行しようとすると権限や依存関係を解消する必要があり面倒
  • コンテナ上でコマンド実行する方法は諦めてgemで環境構築した方がよい

Discussion