Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
令和時代のRails運用
Tomohiro Hashidate
May 13, 2020
Programming
34
13k
令和時代のRails運用
https://shuuu-mai.connpass.com/event/173794/
Tomohiro Hashidate
May 13, 2020
Tweet
Share
More Decks by Tomohiro Hashidate
See All by Tomohiro Hashidate
ReproのImport/Exportを支えるサーバーレスアーキテクチャ
joker1007
1
830
Ruby on Rails on Lambda
joker1007
13
8.3k
Sidekiq to Kafka ストリームベースのmicro services
joker1007
4
8k
TracePointから学ぶRubyVM
joker1007
0
1.3k
What a cool Ruby-2.7 is !
joker1007
2
500
How to extend TracePoint
joker1007
2
230
†Ruby黒魔術経典†
joker1007
14
5.3k
Cassandraの活用事例とパフォーマンス特性
joker1007
3
790
Pragmatic Monadic Programming in Ruby
joker1007
4
10k
Other Decks in Programming
See All in Programming
Git Rebase
bkuhlmann
10
1.2k
フロントエンドで 良いコードを書くために
t_keshi
3
1.6k
%q is for Quine
koic
0
400
監視せなあかんし、五大紙だけにオオカミってな🐺🐺🐺🐺🐺
sadnessojisan
2
1.4k
Hasura の Relationship と権限管理
karszawa
0
170
爆速の日経電子版開発の今
shinyaigeek
2
560
状態ってなに?🙃
taro28
0
260
10年以上続くプロダクトの フロントエンド刷新プロジェクトのふりかえり
yotahada3
2
320
SHOWROOMの分析目的を意識した伝え方・コミュニケーション
hatapu
0
230
はてなリモートインターンシップ2022 インフラ 講義資料
hatena
4
2.1k
はてなリモートインターンシップ2022 Web API 講義資料
hatena
0
150
Amazon QuickSightのアップデート -re:Invent 2022の復習&2022年ハイライト-
shogo452
0
210
Featured
See All Featured
A better future with KSS
kneath
230
16k
Embracing the Ebb and Flow
colly
75
3.6k
GraphQLとの向き合い方2022年版
quramy
20
9.8k
Three Pipe Problems
jasonvnalue
89
8.9k
Automating Front-end Workflow
addyosmani
1351
200k
Fashionably flexible responsive web design (full day workshop)
malarkey
396
63k
What’s in a name? Adding method to the madness
productmarketing
12
1.9k
KATA
mclloyd
12
9.7k
How GitHub (no longer) Works
holman
298
140k
We Have a Design System, Now What?
morganepeng
37
5.9k
A designer walks into a library…
pauljervisheath
199
16k
4 Signs Your Business is Dying
shpigford
171
20k
Transcript
令和時代のRails 運⽤ @joker1007
self.inspect @joker1007 Repro inc. CTO 最近は専らKafka を触っており、実は余りRails を触っていない。 という訳でインフラ寄りの話をします。
から来ました。
コンテナが⼀般化した現代のRails 運⽤の話 弊社は3 年以上前からproduction でのコンテナ運⽤を採⽤している。
話すこと コンテナに⾄るまでの歴史 Rails のDocker イメージ作成 2020 年版 コンテナ化した時のベストプラクティス 弊社で作ったgem の紹介
話さないこと コンテナとは何か k8s 関連
はじめに: インフラ管理の歴史を振り返る 何故コンテナが使われているのか
太古: ⼿順書 暖かみのある⼿作業での構築。 ⼿順書に書かれていないことを実⾏すると怒られる。 流⽯にRails の現場では⾒なかった。
古代: シェルスクリプト ⼿順書をスクリプトにまとめたもの。 メンテされている内は良いが、現状と乖離すると⾯倒なことになる。 既に構築済みのサーバを変更するには使えない。 ⼿作業による変更を反映させて後の作業に利⽤するぐらい。
中世: chef, ansible 等の構成管理ツール DSL によるサーバの⾃動構成を⾏うツールを利⽤する。 構築後の変更もコードによって管理できる。 適⽤後の状態を安定に保つために、コードを羃等にする必要がある。 ( 何度適⽤しても同じ結果になる様にする)
Infrastracture as Code の始まり。 しかし、羃等なコードを保つのがかなり難しい。 また、未知の状況から設定を作り込む負荷が⾼め。
近代: ゴールデンイメージ クラウド環境が⼀般化し、インスタンスイメージとインスタンスを必要に応じて作り 直すことが可能になった。 packer 等のツールを使うことでイメージ構築を簡易化し常に0 から作り直すことで、羃 等性を意識しなくて良くなる。 インスタンスを容易に破棄出来る様になった。 Disposable
Infrastracture の始まり。
現代: コンテナ アプリケーションコードとミドルウェア等のサーバ構成のためのコンポーネントを丸 ごとパッケージ化する。 VM より⼩さいオーバーヘッドで、いくつもアプリケーションを独⽴させて動かせる様 になり、リソース効率が上昇。 アプリケーションに必要なインフラだけを管理すれば良くなり、⼿元の環境で production とほぼ同等の環境が再現可能に。
ゴールデンイメージより遥かにフィードバックのサイクルが早く、アプリケーション と⼀体で扱える。
Rails のDocker イメージ作成 1 buildkit を使ったモダンなRails アプリケーションイメージの構成⽅法を紹介する。 # syntax =
docker/dockerfile:experimental 後述するマウントキャッシュの活⽤のため冒頭に記述しておく
Rails のDocker イメージ作成 2 余計なレイヤーキャッシュ削除の⼯夫をしなくて済む様にnodejs はmulti stage ビルドで ⼊れる #
Node.js ダウンロード⽤ビルドステージ FROM ruby:2.6.5 AS nodejs WORKDIR /tmp # Node.js のダウンロード RUN curl -LO https://nodejs.org/dist/v12.14.1/node-v12.14.1-linux-x64.tar.xz RUN tar xvf node-v12.14.1-linux-x64.tar.xz RUN mv node-v12.14.1-linux-x64 node
Rails のDocker イメージ作成 3 FROM ruby:2.6.5 # nodejs をインストールしたイメージからnode.js をコピーする
COPY --from=nodejs /tmp/node /opt/node ENV PATH /opt/node/bin:$PATH # アプリケーション起動⽤のユーザーを追加 RUN useradd -m -u 1000 rails RUN mkdir /app && chown rails /app USER rails # yarn のインストール RUN curl -o- -L https://yarnpkg.com/install.sh | bash ENV PATH /home/rails/.yarn/bin:/home/rails/.config/yarn/global/node_modules/.bin:$PATH # ruby-2.7.0 でnew した場合を考慮 RUN gem install bundler
Rails のDocker イメージ作成 4 WORKDIR /app # Docker のビルドステップキャッシュを利⽤するため #
先にGemfile を転送し、bundle install する COPY --chown=rails Gemfile Gemfile.lock package.json yarn.lock /app/ RUN bundle config set app_config .bundle RUN bundle config set path .cache/bundle # mount cache を利⽤する RUN --mount=type=cache,uid=1000,target=/app/.cache/bundle bundle install && \ mkdir -p vendor && \ cp -ar .cache/bundle vendor/bundle RUN bundle config set path vendor/bundle RUN --mount=type=cache,uid=1000,target=/app/.cache/node_modules bin/yarn install --modules-folder .cache/node_modules && \ cp -ar .cache/node_modules node_modules COPY --chown=rails . /app RUN --mount=type=cache,uid=1000,target=/app/tmp/cache bin/rails assets:precompile # 実⾏時にコマンド指定が無い場合に実⾏されるコマンド CMD ["bin/rails", "s", "-b", "0.0.0.0"]
コンテナ化した時の設定値の扱いについて イメージ管理を簡単にするためには設定値をイメージに含めたくはない。 環境毎の差異は外部から注⼊するとイメージが⼀つで済む。
基本: 環境変数化 # database.yml の例 production: &default adapter: mysql2 encoding:
utf8mb4 charset: utf8mb4 collation: utf8mb4_bin pool: 5 timeout: 5000 username: <%= ENV["MYSQL_USERNAME"] || "app" %> password: <%= ENV["MYSQL_PASSWORD"] || "password" %> host: <%= ENV["MYSQL_HOST"] || "127.0.0.1" %> port: <%= ENV["MYSQL_PORT"] || "3306" %>
環境変数の限界 秘匿情報をどこで管理するのかの問題は無くならない。 参照権限の管理も必要になる。
KeyManagementService(KMS) の利⽤ AWS やGCP 等のクラウド環境であればIAM と統合された暗号鍵管理の仕組みが利⽤で きる。 アクセス権限がIAM で管理できるため、⾃分でマスターキー等を管理する仕組みが必 要無い。
S3 にKMS で暗号化した設定ファイルを配置する aws s3 cp --sse aws:kms --sse-kms-id <key-arn>
configs/secretdata.yml s3://myapp-configs/secretdata.yml
起動時に秘匿情報を取得するラッパー #!/bin/bash set -xe # AWS はファイルのメタデータとして暗号化情報を記録してあるため、何も指定せずに復号化しつつ取得できる # 鍵に対するアクセス権限が無ければ、エラーになる aws
s3 cp s3://myapp-configs/secretdata.yml configs/secretdata.yml # exec を経由してプロセスを丸ごとRails のものに置き換える # シェルの⼦プロセスとして起動してしまうとシグナルの管理が煩雑になる exec bin/rails s -b 0.0.0.0
Parameter Store の活⽤ AWS ならKMS と連携したParameter Store やSecure Manager が利⽤できます。
⾃分は起動時にAPI を叩いて環境変数に設定するラッパーツールを書いたりしました。 https://github.com/joker1007/prmstore-exec
ログ出⼒とエラー管理 コンテナを活⽤する様になると基本的にサーバにログインしたりローカルストレージ を利⽤することは⾮推奨になります。 コンテナが状態を持つとDisposable では無くなります。 なので、ログ出⼒をどこに出すか考える必要があります。
Logging Driver Docker のログドライバはコンテナアプリケーションの標準出⼒、標準エラー出⼒から ログを読み取ります。 なので、Rails のログを標準出⼒に出せる様にしておく必要があります。 # config/environments/production.rb #
省略 # Prepend all log lines with the following tags. # config.log_tags = [ :subdomain, :uuid ] config.logger = ActiveSupport::Logger.new($stdout) $stdout.sync = true # sync を有効にしないと、バッファリングされてログが⼀定量溜まらないと出⼒されない
最終出⼒先 cloudwatch logs 等のログ管理サービスを利⽤するのが現代的。 Kibana を活⽤するためにElasticSearch に転送することもある。 弊社ではfluentd のログドライバを使ってfluentd の集約サーバに転送し、そこからS3
や papertrail 等に転送している。
エラートラッキング エラートラッキングのためのツールは以前から活⽤されてきたが、最近は⾃前でホス トするより外部サービスに頼るケースが多い。 sentry やrollbar 等が流⾏っている印象がある。
デプロイ コンテナとオーケストレーションサービスが⼀般化し、SSH でファイルを転送すると いう形式ではなくなった。 イメージをリポジトリに登録しておき、デプロイはオーケストレーションのAPI を叩い たり、k8s の設定を変更するという形になった。 弊社ではECS を利⽤しているのでcapistrano
のプラグインを⾃作してデプロイとイメー ジビルドをcap コマンドに統合した。 https://github.com/reproio/capistrano-dockerbuild https://github.com/reproio/ecs_deploy
運⽤コマンド実⾏ 利⽤しているオーケストレーションサービスに依って詳細は異なるが、API を叩いて特 定のコンテナイメージにコマンド引数を渡し起動することは⼤抵可能である。 弊社の例だと、ECS を利⽤しているのでタスク定義の更新、API リクエスト、ログ出⼒ のpolling 、結果の取得までを⾃動でやってくれるgem を作って運⽤している。
https://github.com/reproio/wrapbox AWS だとFargte を利⽤することで、必要になった時だけリソースを確保してコマンド 実⾏が可能になった。 現在はバッチ処理の実⾏等で活⽤している。
テストの並列実⾏ コンテナ化の恩恵としてテストを並列実⾏することが容易になった。 先に紹介したgem の様な任意のコマンドをオーケストレーションクラスタで実⾏する ツールがあれば、引数をコントロールするだけで任意の並列数でテストが実⾏可能に なる。 テスト実⾏の単位ごとにRDB を分けるのも容易い。 弊社ではFargate Spot
を使って32 並列でテストを実⾏している。
最後に宣伝 今⽇話した様な内容も含んだRails 本、パーフェクトRails の第⼆版が著者陣により執筆 中です。 まだ発売⽇は未定ですが、近⽇発売できると良いなあという状況です。 発売されたらよろしくお願いします。