こんにちは、GMOアドマーケティングのmizkichです。
アドテクなマイクロサービスをGCPのKubernetesで運用しています。
Alpine Linux 上のRubyにはライブラリなどに欠けがあるらしく、Google Cloud Datastoreがまともに動作しません。
「require ‘google/cloud/datastore’」の行を書いただけでSegmentation Faultが発生し、コンパイルエラーになります。
この問題を解決したので、方法を共有します。
失敗例
GCP公式に書かれている書き方だと失敗します。
1 2 |
FROM ruby:2.6.4-alpine3.10 RUN bundle install |
1 |
gem "google-cloud-datastore" |
1 2 3 4 |
task :test_datastore => :environment do |_| require 'google/cloud/datastore' PROJECT = Rails.application.config.database_configuration[Rails.env]["project_id"].freeze datastore = Google::Cloud::Datastore.new project_id: PROJECT |
Alpine Linux環境だと、「require ‘google/cloud/datastore’」付近で以下のエラーが発生します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
rails aborted! LoadError: Error loading shared library ld-linux-x86-64.so.2: No such file or directory (needed by /usr/local/bundle/gems/grpc-1.23.0-x86_64-linux/src/ruby/lib/grpc/2.6/grpc_c.so) - /usr/local/bundle/gems/grpc-1.23.0-x86_64-linux/src/ruby/lib/grpc/2.6/grpc_c.so /usr/local/bundle/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:291:in `require' /usr/local/bundle/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:291:in `block in require' /usr/local/bundle/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:257:in `load_dependency' /usr/local/bundle/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:291:in `require' /usr/local/bundle/gems/grpc-1.23.0-x86_64-linux/src/ruby/lib/grpc/grpc.rb:20:in `<top (required)>' /usr/local/bundle/gems/grpc-1.23.0-x86_64-linux/src/ruby/lib/grpc/errors.rb:15:in `require_relative' /usr/local/bundle/gems/grpc-1.23.0-x86_64-linux/src/ruby/lib/grpc/errors.rb:15:in `<top (required)>' /usr/local/bundle/gems/grpc-1.23.0-x86_64-linux/src/ruby/lib/grpc.rb:17:in `require_relative' /usr/local/bundle/gems/grpc-1.23.0-x86_64-linux/src/ruby/lib/grpc.rb:17:in `<top (required)>' /usr/local/bundle/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:291:in `require' /usr/local/bundle/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:291:in `block in require' /usr/local/bundle/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:257:in `load_dependency' /usr/local/bundle/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:291:in `require' |
Alpineで「ld-linux-x86-64.so(glibc)」が不足するのは割と情報があり、このDockerfileで解決できます。
すると、今度は以下のエラーが発生するようになりました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
/usr/local/bundle/gems/google-protobuf-3.9.2-x86_64-linux/lib/google/protobuf/any_pb.rb:17: [BUG] Segmentation fault at 0x0000000000019266 ruby 2.6.4p104 (2019-08-28 revision 67798) [x86_64-linux-musl] -- Control frame information ----------------------------------------------- c:0097 p:---- s:0476 e:000475 CFUNC :msgclass c:0096 p:0022 s:0472 e:000471 CLASS /usr/local/bundle/gems/google-protobuf-3.9.2-x86_64-linux/lib/google/protobuf/any_pb.rb:17 c:0095 p:0007 s:0469 e:000468 CLASS /usr/local/bundle/gems/google-protobuf-3.9.2-x86_64-linux/lib/google/protobuf/any_pb.rb:16 c:0094 p:0034 s:0466 E:002040 TOP /usr/local/bundle/gems/google-protobuf-3.9.2-x86_64-linux/lib/google/protobuf/any_pb.rb:15 [FINISH] c:0093 p:---- s:0463 e:000462 CFUNC :require c:0092 p:0008 s:0458 e:000457 BLOCK /usr/local/bundle/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:291 c:0091 p:0068 s:0455 e:000454 METHOD /usr/local/bundle/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:257 c:0090 p:0011 s:0448 e:000447 METHOD /usr/local/bundle/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:291 c:0089 p:0013 s:0442 e:000441 TOP /usr/local/bundle/gems/googleapis-common-protos-types-1.0.4/lib/google/rpc/status_pb.rb:6 [FINISH] c:0088 p:---- s:0439 e:000438 CFUNC :require c:0087 p:0008 s:0434 e:000433 BLOCK /usr/local/bundle/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:291 c:0086 p:0068 s:0431 e:000430 METHOD /usr/local/bundle/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:257 c:0085 p:0011 s:0424 e:000423 METHOD /usr/local/bundle/gems/activesupport-5.2.3/lib/active_support/dependencies.rb:291 c:0084 p:0013 s:0418 e:000417 TOP /usr/local/bundle/gems/grpc-1.23.0-x86_64-linux/src/ruby/lib/grpc/google_rpc_status_utils.rb:16 [FINISH] c:0083 p:---- s:0415 e:000414 CFUNC :require |
成功例
結論から書くと、下記の設定で動きます。
1 2 3 4 |
FROM ruby:2.6.4-alpine3.10 RUN CFLAGS="-Wno-cast-function-type" \ BUNDLE_FORCE_RUBY_PLATFORM=1 \ bundle install |
1 2 3 4 5 |
gem "grpc", "1.23.0", platforms: ["ruby"] gem "googleapis-common-protos", "1.3.9", platforms: ["ruby"] gem "google-gax", "1.7.1", platforms: ["ruby"] gem "google-protobuf", "3.9.2", platforms: ["ruby"] gem "google-cloud-datastore", "1.6.0", platforms: ["ruby"] |
1 2 3 4 |
task :test_datastore => :environment do |_| require 'google/cloud/datastore' PROJECT = Rails.application.config.database_configuration[Rails.env]["project_id"].freeze datastore = Google::Cloud::Datastore.new project_id: PROJECT |
Segmentation faultに対応するBug Reportが有り対処法も書かれていますが、それだけではDatastoreは動きませんでした。
google-gax , google-protobuf , google-cloud-datastore の三つについても、 BUNDLE_FORCE_RUBY_PLATFORM を用いてプラットフォームに依存しない強制的なインストールを行う必要がありました。
まとめ
Google製のライブラリが、Google製のOSで動かないってどうなってるんだと思うのですが、動くようになって良かったです。
同様の問題で困っている人の助けになれば幸いです。
Full Stack Engineer @ GMO AD Marketing, Inc.
DMP(Data Management Platform)の開発運用担当してます。
(Java x Ruby x Kubernetes x BigQuery x Hazelcast x etc)
マイブームは犬と車と登山とスノボ。