メドピア開発者ブログ

集合知により医療を再発明しようと邁進しているヘルステックカンパニーのエンジニアブログです。読者に有用な情報発信ができるよう心がけたいので応援のほどよろしくお願いします。

Ruby v3.1.0のSegmentation faultに遭遇した話

こんにちは。サーバーサイドエンジニアの三村です。

保険薬局と患者さまを繋ぐ「かかりつけ薬局」化支援アプリ kakariやその姉妹サービスである患者接点を資産化する診療予約システム かかりつけクリニック支援サービス kakari for Clinicの開発を担当しています。

目次

はじめに

kakariをRuby v3.1.0にアップグレードする作業をしていたところSegmentation faultに遭遇したので、bugs.ruby への報告や再現コード作成などの経緯をまとめました。

賢い方法では無い部分も多々ありますが、温かい目で見守ってください。

bugs.rubyのissueはこちらです。

bugs.ruby-lang.org

f:id:t_mimura:20220119185723p:plain
bugs.ruby issue

※ Ruby本体の実装の話は出てきません。

現象

kakariでRuby v3.1にアップデートをしたら、CircleCIで実行しているRSpecでたまにSegmentation faultが発生するようになりました。

f:id:t_mimura:20220119185413p:plain
CircleCIログ

以下のような状態でした。

  • ActiveDecoratorの内部処理で発生
  • 複数回発生
  • エラー箇所は1箇所ではない
  • 再実行すると直る

bugs.rubyに報告

何はともあれ、Segmentation faultはRubyのバグなので報告します。 が、原因分からず再現コードも全然整理出来ていなかったので報告を躊躇いました。 そんなときに便利なruby-jp Slack

f:id:t_mimura:20220117233548p:plain
ruby-jp Slackでの相談の様子

温かく受け入れてくれそうだったので、安心してissueを作成することが出来ました。https://bugs.ruby-lang.org/issues/18489

issue起票当時は再現コードを整理する余裕がなかったので少しでも情報量を多くしようと思い、遭遇したSegmentation faultのログを複数個添付しました。

原因究明までの道のり

環境依存の問題かどうかを切り分け

これまでCircleCIでのみ再現していたので別の環境でも発生するのかをまず切り分けました。

ローカル開発環境(Docker Desktop for Mac)で複数回RSpecを全件実行し、無事に?再現することが確認出来ました。 Docker Image( cimg/ruby:3.1.0-browsers を利用 )依存ならまだしもCircleCI環境依存だった場合は原因究明までの試行錯誤が恐ろしく大変だったので一安心。

エラー発生ファイルの特定

特定のrequest specで再現することがすぐに判明出来ました。 が、このrequest specを単体で何回も実行しても再現しないことからファイルの読み込み順依存の問題であることも同時に分かり悲しみ。(ファイルの読み込み順問題よくありますよね)

specの実行順をランダムから定義順に変更

specは config.order = :random が指定されランダム順に実行されるようになっていたので、これを defined に変更し読み込み順を定義順にしました。 この状態でも本問題が再現することが確認できたのはかなりラッキーでした。 「randomの場合でのみたまに遭遇」みたいな状態だったらseed固定などもう一工夫必要になり面倒で諦めていたかもしれません。

因果関係のあるテストを特定

ここからは地道な試行錯誤の繰り返しです。

以下のspec群から本問題に関係のあるものを特定していきます。

$ tree -L 1 spec/
spec/
├── controllers
├── decorators
├── helpers
├── lib
├── mailers
├── models
├── push_notifiers
├── requests
├── serializers
├── system
├── uploaders
├── validators
└── workers

まずは試行時間の短縮の為に重たいspecを除外を試みました。 特にテスト数の多いmodelsと一つ一つが重たいsystemsを除外しました。 幸いこれらを除外しても変わらずSegmentation faultは再現できたのもラッキー。

脱Docker Desktop for Mac

この後もひたすらspecを実行しまくることが想像できたので少しでもspec実行時間を短くするように先に工夫しました。

kakariではDocker Desktop for Macを利用してローカル開発環境を構築しています。 が、これは色々な要因で重いことが有名ですね(詳細は割愛)。

ということで、脱Docker Desktop for Macを試みました*1。 (恒例の)mysql2のbuildでエラーになるなどちょいハマりポイントはあったものの、すんなり対応出来ました。 真面目に計測したわけではないですが、1.5~2倍くらい早くなった気がします。(かなりうろ覚えなので気になる方はご自身でお確かめください。)

MySQL -> SQLiteに変更

次にMySQLからSQLiteに変更をしました。

本事象は十中八九データベースは無関係だろうと予想していました。 MySQLが重たいわけではないですがSQLiteにすることでインメモリーなデータベースを利用することができる ( database: ':memory:' こんなやつ ) のでspecの並列実行が容易になりました。

基本的にDBの差異はActiveRecordが吸収しているのでadapterを切り替えるだけで済みました。 一部、外部キー制約やindex周りの挙動の違いはあったものの取り上げるほどのものはありませんでした。 (というか本事象と無関係だろうと思い脳死でコメントアウトしたりして対応していました。)

↓はイメージですが、こんな感じの頭の悪い方法でspecを並列実行することが出来ました。

f:id:t_mimura:20220117234303p:plain
spec並列実行の様子
※ iTerm2の画面分割と「Broadcast Input to All Panes in Current Tab」を利用

再現コードの特定

上記の工夫のおかげもあり、因果関係のあるファイルを数個に特定することができたのでミニマムな再現コードの調査に切り替えました。 特に「request specでのみ再現」という状況が色々と面倒だったので何とかシンプルなRubyスクリプトコードを書けないかを模索。

数行のRubyスクリプトコードで再現したりしなかったりする状態までたどり着いたものの、再現有無の条件が全く分かりませんでした。 が、唐突に「GCか?」と思いついたため試しに GC.start を差し込んでみたところめでたく再現しました。

ここから先は簡単で、ActiveDecoratorを利用して書かれた再現コードをplainなRubyコードに変換するだけです。 ActiveDecoratorのコードは予め目を通していたお陰でここは数分で出来ました。

その結果出来た再現コードがこちらです。

M = Module.new
Object.new.extend(M)
GC.start
M.include(Module.new)

二日くらい費やした結果、美しく短い再現コードを作れた時は若干の感動がありました。

再現コード報告

早速「再現コード作れたよ」と追加報告です。

「ActiveDecoratorでSegmentation fault発生」という状況から一気にシンプルな再現コードに飛躍してしまったので「ActiveDecoratorをこんな感じに使ったら再現するよ」というのを添えてコメントしたのは我ながら親切ポイントです。

そして、再現コードをコメントしてから僅か2時間足らずでn0kadaさんが修正PRを作成してくれました。(流石だ)

修正確認

その後、issue上で 「Does https://github.com/ruby/ruby/pull/5455 fix it?」と聞かれてしまったので確認するしかありません。

Rubyをcloneして自前でビルドするのは初めてだったので不安がありましたが、実際にはruby/rubyのREADME手順通りにコマンド打つだけで大きなハマりどころもなくすんなり出来ました。 強いて言えばopensslのパス設定が必要だったかな程度です。あまり覚えていないくらい些細な問題でした。

上記の「脱Docker Desktop for mac」をしておいたのも地味に良かったです。

ruby-jpで相談していたところ、 k0kubunさんのブログ を紹介してもらいとても参考になりました(ありがとうございます!!) ※ 特に「ビルドしたrubyをrbenvから使うには」の所は便利

というわけで、大した苦労もなく無事に修正確認できました。

work around

無事に修正PRもマージされたとは言え流石にheadなrubyコードを利用するわけにはいかないので別途回避する方法を模索します。

これに関しては再現コードの特定が既に出来ているため簡単な話で、以下のような(不適切な形で)ActiveDecoratorを利用している箇所の修正するだけで済みました。

let!(:user) do
-  build(:user).extend UserDecorator
+  ActiveDecorator::Decorator.instance.decorate(build(:user))
end

本事象が発生していたのはspecのみで、実際のプロダクトコードでは同様の事象はなさそうでした。

まとめ

  • Rubyを触り始めて6年近く経ちますが、初めて Ruby本体 にまともな貢献が出来たかなと実感できとても良い経験でした。
  • ruby-jp Slackで気軽に相談できたのがとても有り難かったです。感謝感謝です。
  • 自分のコミットではないにしろ、ほぼ同等のものが「テストコード」としてRubyに入ったの嬉しい。
  • 褒められたの嬉しい。
    f:id:t_mimura:20220117235023p:plain
    ruby-jp Slackで褒められた様子

おまけ

無事にkakariはRuby v3.1.0にアップグレードすることができました。 本件は色々とありましたが、それ以外に必要な対応は殆どなくRubyの後方互換性の高さに感謝です。

以上です。 もし「Segmentation faultに遭遇して困った」なんて時に本記事が参考になれば幸いです。


メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら

https://medpeer.co.jp/recruit/entry/

■開発環境はこちら

https://medpeer.co.jp/recruit/workplace/development.html

*1:今回の調査中だけの話です

Ruby × jemallocのすすめ

集合知プラットフォーム事業部・エンジニアの榎本です。コロナ禍の運動不足を解消すべく筋肉体操で筋トレを続けてますが、上腕三頭筋がいい感じに成長しており継続の大切さを身に沁みて実感しております。

f:id:toshimaru-medpeer:20220113141210j:plain

目次

TL;DR(三行要約)

  • jemalloc でRubyアプリのメモリ効率改善
  • jemalloc でRubyアプリのパフォーマンス改善
  • jemalloc の導入も簡単

Rubyアプリケーションのメモリ肥大化問題

Ruby on RailsなどのRubyアプリケーションを運用する上で、メモリ使用量の肥大化に頭を悩ませた方は多くいらっしゃるのではないでしょうか。

下記は典型的なRailsアプリケーションのメモリ使用量のグラフです。メモリの使用量が対数関数のグラフのように時間とともに100%に近づいていく様子が見て取れます。

f:id:toshimaru-medpeer:20220112085652p:plain
Railsアプリケーションのメモリの使用率の増加

この問題の素朴な対処法としては、しきい値を定義して定期的にworkerプロセスを再起動してやることです。実際にそれを実現するためのgemがいくつか存在します。

しかし puma_worker_killer の README 冒頭で注意喚起されているとおり、頻繁な再起動はCPUリソースを消費させパフォーマンス劣化の要因にもなることから、あくまで応急処置であるべきです。メモリ肥大化の根本的な原因となっているコードがあるのであれば、それをきちんと調査し修正・対応すべきでしょう。

jemalloc を使ってみる

こういったメモリの肥大化・断片化がなぜ起こるのか、それにどう対処すべきかについては書籍・『Complete Guide to Rails Performance』(ちなみに本書は弊社で行っている分科会で取り上げた書籍の1冊です)の中で詳しく解説されています1

細かい話は本を読んでいただくとして、本書の中ではRubyアプリケーションのメモリ使用を効率化する方法として、メモリアロケーターを jemalloc に切り替える方法が紹介されています。

前置きが少し長くなってしまいましたが、本記事では jemalloc を実際にプロダクション投入してみた結果とともに jemalloc について紹介したいと思います。

jemalloc とは?

jemalloc とは Meta(旧・Facebook)社が中心となって開発されているメモリアロケーターです2。その特徴として、メモリの断片化の回避とスケーラブルな並行性サポートを謳っています。

github.com

jemalloc で改善するのか?

気になるのは jemalloc 導入によって実際にメモリ使用率は改善するのか?というところです。

検索してみるとすぐに jemalloc 導入で実際にメモリの使用量が改善したという事例がいくつか見つかりました。

またこちらのベンチマークによると、メモリだけではなくパフォーマンスも10%程度 jemalloc によって向上することが示されています。

CRuby 2.5.0 jemalloc tcmalloc increase w/ tcmalloc increase w/ jemalloc
Median Throughput 175.13 req/sec 197.49 req/sec 183.33 req/sec 4.68% 12.77%

jemalloc の設定方法

Rubyはデフォルトのメモリアロケーターとして、 glibc malloc を使います。ではどのようにメモリアロケーターをデフォルトから jemalloc に切り替えることができるのでしょうか?

--with-jemalloc オプションをつけてRubyをコンパイルする方法もありますが、一番手軽な方法は 環境変数 LD_PRELOAD を設定することです。このLD_PRELOADに jemallocのsoファイルのパスを指定してやればOKです。

具体例を示しましょう。下記は alpineベースのRuby dockerイメージにおける jemalloc 設定方法になります(マルチステージビルドを使って jemalloc のインストールを行っていることに注意してください)。

FROM ruby:X.X.X-alpine as base
...
FROM base as jemalloc
RUN wget -O - https://github.com/jemalloc/jemalloc/releases/download/5.2.1/jemalloc-5.2.1.tar.bz2 | tar -xj && \
    cd jemalloc-5.2.1 && \
    ./configure && \
    make && \
    make install
...
COPY --from=jemalloc /usr/local/lib/libjemalloc.so.2 /usr/local/lib/
ENV LD_PRELOAD=/usr/local/lib/libjemalloc.so.2
...

jemalloc インストール後、ENV命令にてLD_PRELOADにsoファイルのパスを指定しています。この状態でRubyアプリケーションを起動すれば、Rubyのメモリアロケーターは jemalloc に切り替わります。

ただ、この環境変数はDockerイメージ全体のソフトウェアに影響するグローバルな設定なので、設定して問題ないかはきちんとステージング環境などで動作確認・検証しましょう。

jemalloc をプロダクション導入してみた結果

実際に本番環境で稼働するRailsアプリケーションに jemalloc を適用させてみました。その結果をご紹介します。

下記は sidekiq (v6.3)の jemalloc 導入前後一週間のメモリ使用率の比較です。青い線が導入後のメモリ使用率、点線が導入前のメモリ使用率となっております。

f:id:toshimaru-medpeer:20220112092451p:plain
sidekiq jemalloc化 before(点線)/after(青線)

少しわかりにくいのですが、平均して5%程度メモリの使用率が改善したことが確認できました。しかし、先に紹介した改善事例のようにグラフにはっきりと改善が現れると期待していたので、正直なところ少し期待外れ感は否めませんでした。

パフォーマンスについてはどうでしょうか? 下記はRailsアプリケーション(Rails v6.1, Webサーバーはunicorn)のレイテンシーのグラフです。上から順に p99, p95, p90のレイテンシーとなっています。

f:id:toshimaru-medpeer:20220112092844p:plain
Railsアプリケーションのjemalloc化 before/after

こちらはグラフにはっきりとした改善(10-20%程度のレイテンシーの改善)が現れました。Dockerfile を少しイジっただけでこれだけのパフォーマンスが改善したのは、期待以上の結果と言えます。

まとめ

Rubyのメモリアロケーターを jemalloc に切り替えることで、アプリケーションコードの変更なしにメモリ使用およびパフォーマンスを改善できました。

導入もさほど難しくないので、Rubyアプリケーションのメモリおよびパフォーマンスにお困りの方は一度試してみてはいかがでしょうか。

おまけ:jemalloc についてMatzに聞いてみた

弊社の技術アドバイザリーとしてMatzさんがおりますので、Matzさんにもjemalloc について見解を伺ってみました。

Q. jemalloc コアチーム的にどう考えている?

  • どのアロケーターでパフォーマンス向上するかは、アプリケーションの特性次第。一概にどれがいいとは言えないと思う
    • jemalloc に変える提案も来た3が、Rubyとして取り込む予定はない
    • LD_PRELOADでメモリアロケーターを変更できる口は用意してあるので、変更したい場合はそちらを使ってほしい
  • Ruby として jemalloc を推奨することはしないが、Railsアプリケーションでメモリがボトルネックになりやすいということは理解しているので、改善は進めている。すでに入れた変更だと下記のようなもの。
    • 世代別GC
    • インクリメンタルGC
    • Object Compaction
  • Rubyとして推奨はしないがコミュニティの中で jemalloc のほうが良さそうだといった知見が公開されるのは大歓迎である

メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら

https://medpeer.co.jp/recruit/entry/

■開発環境はこちら

https://medpeer.co.jp/recruit/workplace/development.html

RubyWorld Conference 2021 にプラチナスポンサーとして出展しました!(Matzの後日談つき)

サーバーサイドエンジニアのミナトです。 医師とMRをつなぐコミュニケーションツールとなるMedPeer Talk というサービスの担当をしています。

昨年の 12/16に開催された RubyWorld Conference(RWC) に、メドピアはプラチナスポンサーとして参加しました。

f:id:minato_nkmr:20220108062103p:plain
RWC2021スポンサーセッション(メドピア)

スポンサーセッションはこちらからご覧いただけます!

当日は、GALIMO を利用したオンライン会場でブース出展もいたしました。

f:id:minato_nkmr:20220108062207p:plain
RWC2021スポンサーブース

この記事では技術的な内容がほとんどないのですが、RWCを振り返ってみた内容をまとめてみました。

個人的にRWCは比較的ビジネス寄りの発表が多いイメージがありました。 ですが、今年の発表ではメソッドオブジェクトの理解を深めるような技術寄りの話からRubyコミュニティについての話まで幅広くあり、改めてRubyの多様な側面を見れました。

Rubyコミュニティという軸でみたRWC2021

プログラミング未経験者でも利用できるSmalrubyをベースとして作成されたツールのセッションがありました。このツールを利用する方の中でRubyそのものに深く入り込んでいくという人は少ないのかも知れません。ですが、こういったプログラミング自体の敷居を下げていくきっかけとしてRubyが利用されていくということで、社会にRubyが入り込んでいくことが増えてくるのではと思いました。

アフリカでのRubyエンジニア育成のセッションRailsチュートリアル×遠隔学習のセッションを聞き、未経験からRubyを利用したエンジニアとして成長していく過程でこういったエコシステムが存在することで、Rubyコミュニティが形成されていくのだとも感じました。

私が一番共感してしまったのは、リンカーズ株式会社さまの「Railsバージョンを倍にした」セッションでした。 なぜ技術的負債が溜まってしまったのかという考察から、どうやってリファクタリングを進めていったのかという具体的なお話の中で、

  • MVC全部遷宮
  • テストカバレッジ0→95%まで上げた
  • 3ヶ月の動作確認
  • 負債を溜めないための仕組み

などなど、聞いている中で大変だったんだな…すごくわかる…といった部分が随所にありました。 Rubyを利用しているからこそ共感できるこういったものが、松田さんの発表「Me and My Ruby Friends」にあったような「Rubyを利用していることで芽生える友情」に育っていくのかなとも思いました。

Matzさん後日談

弊社ではMatzさんを技術顧問として毎月1回オンラインMTGをさせていただいております(エンジニアにとっての福利厚生ですね!)。

そのMTGの中でMatzさんに、特に印象に残ったセッションはどれでしたか、とお聞きしたところ松田さんの「Me and My Ruby Friends」とのことでした。他にもいくつか挙げていただいていましたが、全部は書ききれないので省略しました。

このセッションの感想をお聞きする中で、

「純粋に技術だけの話をすると投資しているリソースのサイズによってしまう。例えばV8エンジンにはどうやっても勝てない。しかし、RubyはRWCのようなものだったり、RubyKaigiのような多様なコミュニティがある。良いコミュニティ作るという意味では Ruby はなかなか良いのではと思っている」

と仰っていました。 私自身はJava、PHP、Rubyと変遷してきた中でのRubyコミュニティの多様さを本当に感じます。

他にも、

  • 当日の朝にmrubyのバグレポートが来ていて、開会〜キーノートの間に準備をしていると見せかけてデバッグして 5min前にcommitしていたこと
  • オンラインカンファレンスは「オフラインでできてた廊下でちょっと話したりとかフラッとブースに立ち寄ったりが難しいよね。副音声とか面白いかもね」

といった面白いこぼれ話も聞けました。

まとめ

とりとめもなく書いてしまいましたが、今回のRWCではRubyコミュニティ、OSSとしてのあり方、ビジネスとしての可能性の広さを改めて感じることができた1日でした。

最後になりますが、今回のRWCを開催・運営してくださったスタッフの皆様ありがとうございました!


メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら

https://medpeer.co.jp/recruit/entry/

■開発環境はこちら

https://medpeer.co.jp/recruit/workplace/development.html

『medpeer.jp 開発を加速させるエンジニアリング施策』をKaigi on Rails 2021で話しました

こんにちは、DCP事業部エンジニアの榎本です。普段の業務ではMedPeer Channelの開発を担当しています。

メドピアはKaigi on Rails 2021にRubyスポンサーとして参加し、そのスポンサーLT枠にて 『medpeer.jp 開発を加速させるエンジニアリング施策』という発表をしてきました。

今日はその内容を補足するとともに改めて本テックブログでも紹介したいと思います。

medpeer.jp の rails stats

medpeer.jp (医師専用コミュニティサイト「MedPeer」のことです)自体は2007年にローンチしたサービスで、サービスの歴史としては10年以上(もうすぐ15年!)続くサービスです*1

サービスイン当時の開発言語はPHPでしたが、2016年に medpeer.jp のRails化が開始されました。Rails化をスタートさせてから既に5年が経過しており、Railsのコードベースも巨大になりつつあります。

2021年10月時点の medpeer.jp の rails stats 取得してみました。その結果が下記です。

$ rails stats
+----------------------+--------+--------+---------+---------+-----+-------+
| Name                 |  Lines |    LOC | Classes | Methods | M/C | LOC/M |
+----------------------+--------+--------+---------+---------+-----+-------+
| Controllers          |  29336 |  22890 |     547 |    3078 |   5 |     5 |
| Helpers              |    861 |    676 |       0 |     114 |   0 |     3 |
| Jobs                 |   1412 |   1164 |      49 |     166 |   3 |     5 |
| Models               |  64144 |  43039 |    1218 |    4945 |   4 |     6 |
| Mailers              |    599 |    483 |      26 |      59 |   2 |     6 |
| JavaScripts          |    665 |    292 |       0 |      51 |   0 |     3 |
| JavaScript           |  22963 |  15936 |       0 |    1234 |   0 |    10 |
...(以下略)...

そんな巨大な medpeer.jp 開発を支えるエンジニアリング的な工夫をいくつか紹介したいと思います。

コンテナベースの開発環境

もはや常識となったdockerコンテナ開発ですが、弊社も例に漏れずdockerコンテナをベースとして開発しています。

ローカル開発環境

ローカル開発環境は dip を利用しています。

dip とは Docker Compose をラップしたコマンドラインツールです。これを利用することで複雑な docker compose コマンドを大幅にショートカットできます。例えばmedpeer.jp 開発の場合、 Rails Server の起動は dip rails s とすれば立ち上がるように設定しています。

dip に関しては下記の翻訳記事が詳しいのであわせてご参照ください。

techracho.bpsinc.jp

QA環境

medpeer.jp 開発チームではQA環境という環境を用意しています。QA環境は何かというとブランチ単位のプレビュー環境のことです。

GitHub Pull Request 上で /deploy-qa とコメントをすると GitHub Actions でデプロイジョブが走り、当該ブランチがQA環境へデプロイされる仕組みになっています。

f:id:toshimaru-medpeer:20211026141513p:plain
PRコメントでQA環境へと自動デプロイされる様子

ステージング環境・プロダクション環境

ステージング環境、プロダクション環境ともにECSを使ってインフラを構築しています。また、メインとなるRails AppのサーバーはAWS Fargate を使って構築しています。

ちなみに medpeer.jp だけでなくメドピア会社全体としてECSを採用しており、弊社のSRE・侘美がECS勉強会を開催したときの資料は下記になります。

フィーチャートグル

flipper というgemを使いフィーチャートグルを実現しています。

今まで巨大な長命のフィーチャーブランチを頑張ってメンテし、リリースタイミングでドカンと危険なビッグバンリリースを発動させていたのですが、このフィーチャートグルの仕組みが導入されたことにより、ビッグバンリリースを回避することができるようになりました。

f:id:toshimaru-medpeer:20211026141600p:plain
flipper-ui によるフィーチャートグル制御UI

Railsアプリケーション設計

巨大なRailsアプリケーションコードをメンテナブルにする工夫は各社いろいろアプローチあると思いますが、弊社は PORO (Plain Old Ruby Objects) のアプローチを使うことが多いです。

POROに関しては弊社の技術顧問である willnet さんが下記記事で紹介しておりますので、よければご覧ください。

tech.medpeer.co.jp

tech.medpeer.co.jp

また、フォームオブジェクトのアプローチについても下記記事で解説しておりますのであわせてどうぞ。

tech.medpeer.co.jp

CI/CD

medpeer.jp の CI/CDですが、CIサービスとして CircleCI + GitHub Action を利用しており、CDは主に GitHub Action を利用しています。

中でも GitHub Actions + GitHub Deployment の仕組みが便利で、GitHub ネイティブのデプロイ通知が見れたり、Activeなデプロイメントステータスが GitHub UI 上でさっと確認できるのが便利です。

f:id:toshimaru-medpeer:20211026143514p:plain
GitHub Deployment 通知

f:id:toshimaru-medpeer:20211026143600p:plain
Active な Production Deployment の確認

これに関して詳しくは、弊社SRE・正徳が発表した資料がありますので、下記資料をご覧ください。

Rails Upgrade 戦略

スムーズなRails Upgradeのために、複数RailsバージョンでCIを実行しています。つまり、現行バージョンに加えて次のRailsバージョンでCI上を動かすことで、次のバージョンでも正しく動くことをCIで担保しています。

これに関しても正徳が発表した資料がありますので、詳しくは下記資料をご覧ください。

技術負債・今後の課題

medpeer.jp は長年運用しているサービスですので、もちろん技術負債もあります。具体的には下記のようなものです。

  • まだRails 6.0(年内には Rails 6.1 にアップグレード予定)
  • 残存するPHPコードベース
  • PHPから移植した古いRailsコード
  • マイクロサービスっぽいアーキテクチャの残滓

現状はこれらの技術負債に対して、きれいにできるところからきれいにしていき徐々に減らしていっているという段階です。

Kaigi on Rails に参加してみて

前年度の Kaigi on Rails にも私は参加していましたが、間違いなく去年よりカンファレンス特有の"ワイワイ感"が演出できていたように感じます。

そのワイワイ感を演出するのに一役買っていたのは reBakoであったと思います。雑談テーブルで開発者同士がいろいろ話していたり、登壇者が登壇後QAテーブルでいろいろ質問に受け答えをしていたりして盛り上がっていました。

一方で企業ブース出展側でいうと、一見さんが入りやすいような雰囲気作りをするのに課題を感じました。リアルのブース出展だとフラッと立ち寄ってくれる方がいらっしゃったり、こちらからノベルティを渡しに行ったりとある程度インタラクションが発生する機会がありますが、オンラインだとなかなかブースの中までは呼び込むのにハードルを感じました。このあたりは再度 reBako 出展する機会があればいろいろ工夫したいところです。

f:id:toshimaru-medpeer:20211026145841p:plain
reBako会場

最後になりますが、とても素敵な"Kaigi"を開催してくださった Kaigi on Rails 2021スタッフの皆様、ありがとうございます!


メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら

https://medpeer.co.jp/recruit/entry/

■開発環境はこちら

https://medpeer.co.jp/recruit/workplace/development.html

AWS Config + Athena + QuickSightによる複数AWSアカウント横断でのセキュリティ状態の可視化

CTO室SREの侘美です。最近は社内のセキュリティ対策関連を生業にしております。
今回は最近進めていた社内のAWSアカウントのセキュリティ可視化がある程度形になったので記事にしたいと思います。

課題:多数のAWSアカウントのセキュリティをチェックしたい

サイバー攻撃が増加している昨今、AWSなどのPaaS環境においても構築時にセキュリティの観点で注意すべき点がいくつもあります。 例えば、不必要なサーバー/ポートがインターネットに公開されていないか、アカウントにMFAが設定されているか、等々実施しておきたいセキュリティ対策は多岐にわたります。

弊社では、AWSを用いてインフラを構築する際にセキュリティ上守るべきルール集を、インフラセキュリティポリシーというドキュメントを定義しています。 しかし、あくまでドキュメントベースなので、実際にこのドキュメントに書かれたルールに準拠した構成になっているかどうかのチェックは手作業で実施しなければならない状態でした。

また、サービスも年々増加しており、現在では約40のAWSアカウントを6名のSREで管理している状態であり、今後すべてのアカウントのセキュリティまわりをSREが手動でチェックしていくのは現実的ではありません。

さらに、現在はSREが中心に行っているインフラの構築/運用も各サービスチームへ徐々に移譲している途中であり、これらのセキュリティルールのチェックの自動化の必要性が上がってきました。

対策:セキュリティルール準拠状態の可視化

幸いAWSにはこういった課題を解決するためのサービスがいくつもあります。

これらサービスを最大限活用し、社内のセキュリティポリシーで定義したルールへの準拠状態を可視化することを目標としました。

要件の整理

今回構築したアーキテクチャは以下の要件を元に作成しています。

  • どのアカウントがどの程度セキュリティルールに準拠できているかがわかりやすく可視化できる
  • できればフルマネージド
  • Organizationにアカウントが増えてもメンテナンス不要で自動で対応される
  • リソースの自動修復は現状考えていない

構成の検討

上記の要件を満たす構成を検討していく課程で、悩んだ・ハマったポイントをいくつかご紹介します。

AWS Config vs Security Hub

Organization配下のアカウント全体に対して、リソースがルールに準拠した設定になっているかをチェックするサービスとして、AWS ConfigAWS Security Hubがあります。

AWS Configは「AWSが提供する151(2021/09/08現在)のマネージドルール」または「自身でLambda関数で実装したカスタムルーム」を使い、リソースのルールへの準拠状態をチェックすることができます。

また、AWS Organizationsにも対応しており、Organization配下の全アカウントに一括でルールを作成することができます。 ただし、アカウント横断でルール準拠状態を閲覧する方法は無いため、別途何らかの方法で可視化する必要があります。

Security Hubはセキュリティチェックの自動化とセキュリティアラートの一元化を主眼においたサービスです。 いくつか提供されているベストプラクティスを選択し、そのベストプラクティスに含まれるルールへの準拠がチェックされます。

f:id:satoshitakumi:20210915154330p:plain
マネジメントコンソールにおけるSecurity HubのUI

こちらもOrganizationsに対応しており、配下のアカウントすべてを横断的にチェックすることができます。

Security Hubなら比較的少ない工数でOrganization配下のアカウントに対して横断的にチェックを実行できます。しかし、提供されたベストプラクティスのルール集でのチェックなので、今回実現したい社内のセキュリティポリシーに準拠しているかというチェックとは少しズレてしまいます。 また、ビューも固定なので「どのアカウントがセキュリティ的に弱いか」等を即座に判断するのは難しいです。

AWS Configはマネージドルールが豊富であり、社内でチェックしたい項目に合わせて柔軟に対応できそうです。 アカウント横断でのビューは無いため、何らかの方法で用意する必要があります。

弊社では既にSecurity Hubを全アカウントで有効化し、重要なセキュリティ項目に関しては適宜チェックし修正する運用を行ってはいましたが、今回はより柔軟なルールと求めているデータを可視化できるという点を優先し、AWS Configを採用することにしました

QuickSight vs Elasticsearch Service

AWS Configを採用したので、アカウント横断の評価結果をいい感じに可視化する仕組みを別途用意する必要があります。

AWS Configは各リソースの評価状態をスナップショットログとして定期的にjson形式でS3に出力することができるので、このログを利用して可視化を行います。 スナップショットログは可視化のために一箇所に集めたいため、以下の図のような構成をとることで1つのS3バケットに全アカウント分集約しています。

f:id:satoshitakumi:20210915154439p:plain
Organization配下のアカウントへのConfigの設定とスナップショットの集約

上記のような方法でS3に格納されたログを可視化するソリューションはいくつも存在します。 AWS上で実現するメジャーな方法としては、「S3 → Athena → QuickSight」や「S3 → Lambda → Elasticsearch Service → Kibana」のような構成があげられます。 後者はSIEM on Amazon Elasticsearch Serviceというソリューションとして知られています。

f:id:satoshitakumi:20210915154628p:plain
代表的な2パターンの可視化方法

どちらの構成にもメリット・デメリットは存在しますが、今回は以下の理由からQuickSightを利用する構成を採用することにしました。

  • IAMと連携したユーザー管理の容易性
  • インスタンス管理の有無
  • データ取り込み部分の実装コスト
  • レポートメール機能

AWS Config マネージドルールの選定

2021/09/08時点で151のマネージドルールが提供されています。 docs.aws.amazon.com

ルール自体は「ルートユーザーのアクセスキーが存在しないこと」等様々な項目が用意されています。

この中からチェックしたい項目をピックアップし、 またセキュリティ以外の観点でもバックアップ、削除保護、可用性の観点などで設定が推奨していきたいルールもいくつかピックアップしました。
今回は合計で68ルールを採用しています

これらをセキュリティ、コスト、パフォーマンス、バックアップ、削除保護の5つに分類し、それぞれの接頭詞(例:セキュリティなら security- )を決めた上で、ConfigのOrganization Config Ruleとして社内の全AWSアカウントへ登録しました。 接頭詞をルールを作成する際の名前に指定することで、スナップショット中のルール名から何の目的で導入したルールかを判別可能にし、ダッシュボードで可視化する際に「セキュリティルールに非準拠であるリソース数」のような表示も可能にしています。

最終的なアーキテクチャ

今回構築したアーキテクチャの全体像がこちらになります。

f:id:satoshitakumi:20210915154524p:plain
全体のアーキテクチャ

弊社ではAWS上のリソースはTerraformで管理しています。 また、Terraform CloudでStateの管理やapplyの実行を行っています。

Terraform Cloudのトリガー機能とWorkspace間のoutput参照機能を利用することで、Organizationを管理しているTerraformが出力する、アカウント一覧に変更があった場合、Log AccountのAthenaのテーブル定義を管理しているTerraformを実行するといった連携が可能になります。(詳細は後述します)

この手のダッシュボードでは、能動的な閲覧のみで運用を続けていると、閲覧するメンバーが固定化され仕組みが風化していく懸念があります(体験談)。 そこで、QuickSightの機能で定期的にダッシュボードをレポートとして送信することで、関与するメンバーが定期的に閲覧してくれるように試みています。

ハマりポイント:AthenaのProjection Partition

S3に保存したConfigのスナップショットに対してAthenaでクエリを実行するためにテーブルを作成する必要があります。 その際のテーブル定義で一部ハマった箇所があったのでご紹介します。

前提:Partition Projectionの型

Athenaのテーブル設定の一つの項目に、パーティションという概念があります。 パーティションを簡単に説明すると、S3のキー中のどの位置にどのような変数が含まれるかを設定し、SQL中でその値を指定することでスキャン対象となるS3上のオブジェクトを限定することができます。

例えば、S3バケットのキーに /AWSLogs/111111111111/Config/ap-northeast-1/2021/9/1/ConfigSnapshot/ のように日付が含まれる場合、日付部分をパーティションとして登録することで、 WHERE date = '2021/9/1' のようなクエリを実行できるようになります。 大量のオブジェクトがあるS3に対してパーティションを適切に設定せずにAthenaでクエリを実行するとコストがかかったりエラーが発生したりするのでAthenaを使う上では必須のテクニックとして知られています。

パーティションの設定方法にはいくつか種類があります。

  1. Hive形式のキーを利用する
  2. ADD PARTITION クエリを実行する
  3. Projection Partitionを利用する

各方法の細かい違いに関しては公式ドキュメントを参照していただくのが良いかと思います。

今回はConfigのスナップショットが対象になるため、1のHive形式のキーではないのでこの方法は使えません。 2と3で迷い、AWSのSAやプロフェッショナルの方とディスカッションさせていただき、 Projection Partitionを利用する方が良さそうという結論 に至りました。

議論のポイントとなったのは、S3オブジェクトのキーに含まれるアカウントID部分をProjection Partitionのどの型で表現するかという点です。 Projection Partitionでサポートされる型には、 Enum, Integer, Date, Injected の4種があります。

参考:Supported Types for Partition Projection - Amazon Athena

アカウントIDは12桁の数字なので、 Enum, Integer, Injected が候補となります。 それぞれの特徴は以下のようになっています。

  • Enum : テーブル定義時に取りうる値を列挙する。検索時の指定は任意。
  • Integer : テーブル定義時に取りうる値の範囲を指定する。範囲が広すぎる場合検索クエリがタイムアウトする。検索時の指定は任意。
  • Injected : テーブル定義時に値の指定は不要でキーに含まれる値を自動的に判定してくれる。検索時の指定は必須

AWSアカウントは任意のタイミングで増減するため、できれば現存するアカウントを列挙し指定するようなパーティションの設定は避けたいです。これはAWSアカウントをOrganizationに追加した際に特にメンテナンスすることなく可視化用のダッシュボードに反映されて欲しいからです。

そうなると、 Injected 型が候補になってきますが、検索時に値の指定が必須となってしまうため、アカウント横断で検索するようなクエリを実行できなくなってしまうため却下となります。

Integer 型なら12桁の整数も対象なので、これで条件を満たせると思い、実際にPartition Projectionを設定してAthenaから検索クエリを実行してみました。 ところが、検索クエリがタイムアウトしてしまいました。 Integer 型の取りうる範囲の指定を調整して何度か実験したところ、12桁のAWSアカウントの範囲を値域として指定すると範囲が広すぎるためかタイムアウトとなることがわかりました。

課題:アカウントの増減への対応

ということで、 Enum 型でテーブル定義時に現存するOrganization配下のアカウントを列挙する必要がでてきました。 この Enum 型でのPartition Projectionを設定した状態での検索クエリの挙動は特に問題なく、想定している結果を得ることができました。 つまり、このEnum 型の場合、Organization配下にAWSアカウントが増えた場合に如何に自動でPartition Projectionの定義にアカウントIDを反映するかという課題が残ります。 (Partition Projectionの変更はテーブル作成後でも実行できます)

対策:TerraformのRemote Stateの活用

この課題を解決するにあたり、弊社で利用しているTerraform Cloudの機能を利用するのが最もスマートであることに気づきました。

Terraform CloudはHashiCorp社が提供している、Terraformの実行環境です。指定したブランチに反映されたTerraformのコードを使い自動でapplyを実行してくれます。 弊社ではAWSのリソースはTerraformで管理しており、SREが管理する全てのTerraformのリポジトリをTerraform Cloud上でapplyしています。 また、Organization配下にアカウントを新規に開設する場合も、Terraformで実装しています。 今回のConfigやAthenaに関しても同様です。

Terraform Cloudを利用すると、あるworkspaceの出力( output )を別のworkspaceから参照するRemote State機能を利用することができます。

参考: Terraform State - Workspaces - Terraform Cloud and Terraform Enterprise - Terraform by HashiCorp

また、特定のworkspaceのapplyが完了したのをトリガーに、別のworkspaceのapplyをキックすることが可能です。

参考: Run Triggers - Workspaces - Terraform Cloud and Terraform Enterprise - Terraform by HashiCorp

つまり、以下のような構成にすることで、Organizationにアカウントが追加された場合に自動でAthenaのProjection Partitionの設定を変更することが可能になります。

  • Organizationを管理するTerraform Workspaceにて、アカウントの一覧を output で出力する
  • AthenaのPartition Projectionを構築するTerraform Workspaceにて、上記のアカウント一覧を参照して Enum 型の値に設定する
  • Organizationを管理するTerraform Workspaceが実行されたら、Athenaを管理するTerraform Workspaceのapplyが実行されるように、Run Triggerを設定する

全体のアーキテクチャから抜粋すると、以下の部分がこの仕組を表しています。

f:id:satoshitakumi:20210915154734p:plain
Terraform Cloudによるアカウント追加時のAthenaテーブル定義の自動更新

テーブル定義は最終的に以下のTerraformコードにより作成しました。

resource "aws_glue_catalog_table" "config" {
  name          = "aws_config"
  owner         = "hadoop"
  database_name = aws_glue_catalog_database.config.name

  table_type = "EXTERNAL_TABLE"

  parameters = {
    EXTERNAL = "TRUE"

    "projection.enabled"          = "true"
    "projection.account.type"     = "enum"
    "projection.account.values"   = join(",", values(data.terraform_remote_state.root.outputs.accounts)) # Remote Stateで別WorkspaceからアカウントIDの配列を参照
    "projection.region.type"      = "enum"
    "projection.region.values"    = "ap-northeast-1,us-east-1"
    "projection.dt.type"          = "date"
    "projection.dt.range"         = "2021/4/1,NOW"
    "projection.dt.format"        = "yyyy/M/d"
    "projection.dt.interval"      = "1"
    "projection.dt.interval.unit" = "DAYS"
    "projection.itemtype.type"    = "enum"
    "projection.itemtype.values"  = "ConfigHistory,ConfigSnapshot"
    "storage.location.template"   = "s3://<your bucket name>/<prefix>/AWSLogs/$${account}/Config/$${region}/$${dt}/$${itemtype}"
  }

  partition_keys {
    name = "account"
    type = "string"
  }

  partition_keys {
    name = "region"
    type = "string"
  }

  partition_keys {
    name = "dt"
    type = "string"
  }

  partition_keys {
    name = "itemtype"
    type = "string"
  }

  storage_descriptor {
    location      = "s3://<your bucket name>/<prefix>/AWSLogs"
    input_format  = "org.apache.hadoop.mapred.TextInputFormat"
    output_format = "org.apache.hadoop.hive.ql.io.IgnoreKeyTextOutputFormat"

    ser_de_info {
      serialization_library = "org.openx.data.jsonserde.JsonSerDe"
      parameters = {
        "serialization.format"                 = "1"
        "case.insensitive"                     = "false"
        "mapping.arn"                          = "ARN"
        "mapping.availabilityzone"             = "availabilityZone"
        "mapping.awsaccountid"                 = "awsAccountId"
        "mapping.awsregion"                    = "awsRegion"
        "mapping.configsnapshotid"             = "configSnapshotId"
        "mapping.configurationitemcapturetime" = "configurationItemCaptureTime"
        "mapping.configurationitems"           = "configurationItems"
        "mapping.configurationitemstatus"      = "configurationItemStatus"
        "mapping.configurationitemversion"     = "configurationItemVersion"
        "mapping.configurationstateid"         = "configurationStateId"
        "mapping.configurationstatemd5hash"    = "configurationStateMd5Hash"
        "mapping.fileversion"                  = "fileVersion"
        "mapping.resourceid"                   = "resourceId"
        "mapping.resourcename"                 = "resourceName"
        "mapping.resourcetype"                 = "resourceType"
        "mapping.supplementaryconfiguration"   = "supplementaryConfiguration"
      }
    }

    skewed_info {
      skewed_column_names               = []
      skewed_column_value_location_maps = {}
      skewed_column_values              = []
    }

    number_of_buckets = -1

    columns {
      name = "fileversion"
      type = "string"
    }

    columns {
      name = "configsnapshotid"
      type = "string"
    }

    columns {
      name       = "configurationitems"
      parameters = {}
      type       = "array<struct<configurationItemVersion:string,configurationItemCaptureTime:string,configurationStateId:bigint,awsAccountId:string,configurationItemStatus:string,resourceType:string,resourceId:string,resourceName:string,ARN:string,awsRegion:string,availabilityZone:string,configurationStateMd5Hash:string,configuration:string,supplementaryConfiguration:map<string,string>,tags:map<string,string>,resourceCreationTime:string>>"
    }
  }
}

可視化した内容

最後にQuickSightで構築したダッシュボードの一部を紹介します。(一部加工しております)

f:id:satoshitakumi:20210915184242p:plain
作成したダッシュボードの一部

主に、「次にテコ入れすべきAWSアカウントの特定」や「全体的に実践できていないルール = 社内にノウハウがないルール」の特定などに利用する想定で作成しております。

課題

今回構築した構成の中で課題として残っている部分もあるので掲載しておきます。

  • QuickSightのリソースのほとんどがTerraformに対応してない
    • SQLのみリポジトリ管理している状態で、aws providerの対応待ち
  • 特定のリソースを除外する対応が難しい
    • タグでの除外とかができれば嬉しいが現状はできない

まとめ

Organization配下のAWSアカウントのルールへの準拠状態を、AWS Config + Athena + QuickSightで可視化することができました。 これで今後AWSアカウントが増加したり、各アカウントの管理をサービス開発チームへ移譲していってもある程度のガバナンスが効いた状態を担保することができるようになったかと思います。


メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら

https://medpeer.co.jp/recruit/entry/

■開発環境はこちら

https://medpeer.co.jp/recruit/workplace/development.html

iOSDC Japan 2021にダイアモンドスポンサーとして登壇しました

f:id:ichi6161:20210930144331p:plain

エンジニアの市川です。 メドピアでは保険薬局と患者さまを繋ぐ「かかりつけ薬局」アプリ「kakari」のiOS開発を担当しています。 2021年9月17日~19日に開催されたiOSDC japan2021にて、スポンサーセッションとして登壇し、kakariのiOS開発について話しました! 企業としては、今年で4回目、ダイアモンドスポンサーとしては3回目の協賛参加となりましたが、セッションへの登壇は初めてでした。 登壇の内容も含め、イベントのレポートをしたいと思います。

発表内容
アプリ間連携で薬局・クリニックのユーザー体験価値を最適化した話~MedPeer iOS開発~

かかりつけ薬局支援サービス「kakari」と、去年リリースした姉妹アプリである、かかりつけクリニック支援サービス「kakari for Clinic」のアプリ間で、ユーザー情報連携を簡単にできるようにした実装について紹介しています。 FirebaseのDynamicLinkを使った実装の話です。


資料 speakerdeck.com

※資料内にデモ動画を載せていますが埋め込み資料内だと動画が再生されません。 iOSDC Japan 公式YouTube www.youtube.com

にライブのプレゼン動画が掲載されると聞いていますので、詳しくはそちらでもご覧いただけます。

 他のスポンサーセッションでは各企業さんの「エンジニアの働き方」や「開発体制」などについて話されているところも多かったですが、メドピアは視聴されているエンジニアの方々にとって何らかの技術還元になればと思い開発事例の話をしました。 kakariはコンセプトが明確で、ユーザー目線に立って、改良をし続けているサービスだと思います。 そこにプロダクト開発の面白さを感じているので、今回の登壇でkakariを紹介することができたのは、とても嬉しく思います。

f:id:ichi6161:20210930144957p:plain


スポンサーとしてのその他の取り組み ―ノベルティ―

iOSDC Japanは毎年豪華でたくさんのノベルティも注目されているようですが、今回メドピアからは宣伝フィルムでパッケージングしたペットボトルのミネラルウォーター(通称:Peerウォーター)と、ステッカーと、マスクケースをお送りしました。


f:id:ichi6161:20210930144917j:plain


マスクのノベルティは複数ありましたが、マスクケースはオンリーワンだったようです。 また、箱を開けてすぐに、公式パンフレット以外はPeerウォーターだけが目に入る位置にあり、宣伝効果は抜群?!ファーストビューは大事ですね。


f:id:ichi6161:20210930144937j:plain


医師と患者を支えるメドピアという会社のことをより広く知っていただくと共に、コミュニティを同じくする企業の皆さんとも知見を共有しあい、iOS開発技術の向上に貢献したいです。

まとめ
 イベント配信時のチャットで「来年こそはリアルで開催したい」と望むコメントが多く見られましたが、メドピアとしても来年のiOSDC Japanがリアルで開催されることを願いつつ、会社としてiOSエンジニアコミュニティにまた何か還元できるような技術力を培い、私個人としても「kakari」の事業をもっと発展させたいと思います。



メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら
https://medpeer.co.jp/recruit/entry/
■開発環境はこちら
https://medpeer.co.jp/recruit/workplace/development.html

今年もRubyKaigi Takeout 2021にプラチナスポンサーとして参加しました!

f:id:ryoheikurisaki:20210915104735p:plain サーバーサイドエンジニアの栗崎です。

『MedPeer』の製薬企業向けのサービスの開発を担当しています。

2021年9月9日~11日に RubyKaigi Takeout 2021 が開催されました。メドピアは今年で通算4回目のスポンサー参加となります。

私はRubyKaigi, RubyKaigi Takeoutに初めての参加でした。今回はメドピアのメンバーでSlackチャンネルを作り、「社内感想戦」をしながら視聴しました!

プラチナスポンサーとして

オンライン開催になったのは2020年に続き2回目ですが、今回もプラチナスポンサー💎として協賛しています。

スポンサー特典として15名分の招待枠がありました。

枠はすぐに埋まりましたが、メドピアでは技術研鑽活動の一環として経費でチケットを購入できるので、希望者は全員視聴しています。

Kaigi中には、プレゼンテーションの幕間に15秒の動画CMも(初制作)も流れました。

f:id:ryoheikurisaki:20210916191312p:plain

CMが流れた瞬間、コメントに「メドベア~」と入れてくださった方が複数いました。過去もこのキャラクターをあしらったノベルティを配っていたので、非公式キャラクターですが意外と認知されているようです。 これを機に、医師と患者を支えるメドピアという会社の存在をより多くの方に知っていただけたらと思います。

Kaigiのようす ー社内感想戦ー

3日間の開催期間中に計37セッションが行われていました。タイムテーブル上は2つのトラックにわかれていて、それぞれ視聴したものを専用Slackチャンネルでコメントしあいました。

社内感想戦で話題に挙がっていたことのひとつは、Rubyの型解析ツールの「The newsletter of RBS updates」のセッションについてでした。RBS導入のヒント、Ruby3.1に搭載予定のRBSの新機能のお話でした。

f:id:ryoheikurisaki:20210916191247p:plain

セッションでは、RBSの概要を始め、関連ツールの紹介、Ruby3.1搭載機能のお話しがされていました。また、課題の例として、Railsアプリケーションへの導入をお話されており、Railsアプリケーションでの型の導入について、社内のリポジトリで試してみたいといった会話などがありました。社内での導入も近いうちに行えたらなと思います!!

印象的だったこと

私が印象的だったのは、「The Art of Execution Control for Ruby's Debugger」のセッションでした。

普段のアプリケーション開発でも使用しているdebuggerについてのお話で、現在Rubyに標準添付されているdebuggerの lib/debug.rbを置き換える目的で新たなdebuggerである ruby/debug *1を作成されたお話でした。

infoコマンドでローカル変数の一覧が見れたり、backtraceコマンドで、どこでメソッド定義がされているかを見れたりと普段の開発業務の中でも便利になりそうなものが紹介されていました。 binding.breakは、自分がdebugしたい箇所にセットし、do: にコマンドを渡すだけで、渡したコマンドをdebugコマンドとして実行でき、わざわざブレークポイントで停止することなく実行でき便利だなと思いました。

f:id:ryoheikurisaki:20210915110339p:plain

また、社内Slackではstep backの機能についてもお話しされていましたね。debugしている箇所の前の状態がどういうローカル変数を持っているかどうかを調べるのに使えるようです。 これらの機能が、Visual Studio Codeのextensionとしても使うことができ、なお魅力的だなと感じました。

先日、Ruby on Rails7では、debuggerがbyebugに代わり、ruby/debugに置き換わったようです。*2

まとめ

今回のRubyKaigi Takeout 2021に参加して多くのことを感じました。

Rubyを使った多岐にわたる発表により、Rubyの世界の広さを知りました。 IDE、パフォーマンス、アップデート予定の機能、ツールライブラリ、データ処理、キーボードなど様々な発表が繰り広げられていました。正直、私個人にとっては難しい話も多かったですが、自分の技術スキルの立ち位置を知る機会になりました。

また、最前線で活躍されているRuby committer、馴染み深いGemのcommitter、海外で活躍されている有名企業のRuby commiterなど、グローバルカンファレンスでないと聞くことのできなさそうな方々の話を聞けたことはとても貴重な機会でした。

そして、カンファレンス内のチャット欄で親しみの込もったリアクション、最後のMatzさんのお話からもRubyコミュニティの温かさを随所に感じました😭

本格的にオンラインとなったのは今年からで、運営の方は動画配信も大変そうでしたが、来年も開催されるとの予告があったので是非参加したいです。 メドピアチームとしては今後もRubyコミュニティ・Rubyist仲間の皆様に貢献できるよう積極的に活動していきます!リアルイベントもいつかまた再開できたら… Rubyコミュニティの一員として、Rubyを駆使して、医療を再発明することに貢献したいと思います!!


メドピアでは一緒に働く仲間を募集しています。 ご応募をお待ちしております!

■募集ポジションはこちら

https://medpeer.co.jp/recruit/entry/

■開発環境はこちら

https://medpeer.co.jp/recruit/workplace/development.html