Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.
普通のRailsアプリを
Dockerで本番運用する知見
2017/08/19 RejectKaigi 2017 @zaru
@zaru
さくらば ひろゆき
最近の個人活動報告
最近の活動の紹介
ブラウザにプッシュ通知できるライブラリ webpush (gem)
- 最近マストドンにマージされた
URLをQRコードに変換するMacアプリ LightningQR
GitHubの通知をするMacアプリ NotifyHub
...
アンケート✋
Dockerを
使ったことがある人✋
Dockerを
導入している人✋
Dockerを本番に
導入している人✋
今日のゴール
RailsをDockerで運用するための
知見が互いに集まる状態
今日の流れ
- Docker本番運用状況
- Docker気持ちいいポイント
- Rails + Dockerの壁
- Docker + k8s + GKEおまけ
Docker本番運用状況
Docker本番運用状況
AWS ECS
- 1サービスを本番運用
GCP GKE
- 3サービスを本番運用
- プルリク単位のSTG環境を動的に作るサービス運用
drone.io
- 分散rspecのためにDockerコンテナを利用
プルリク単位で
ステージング環境を
自動でつくる
Dockerを頑張る
時代は終わった…
気がする!
かも
Docker開発の
気持ちいいところ
気持ちいいポイント1
すぐ立ち上がるのが
気持ちがいい
Vagrantは
「よっこらしょ」
Dockerは「よっ」
vagrant / docker 比較
起動時間
vagrant up 50sec
docker-compose up 15sec
VM立ちあげるのと、コンテナ立ち上げるのでは違うのは当然だ
けど、毎日やる作業だからこそ高速にしたい気持ちがある...
気持ちいいポイント2
気楽に作れるのが気持ちがいい
Chef
色んなファイルに
コードを書いてる
Docker
たった一つのDockerfile
1コンテナ1プロセスだからシンプル
- アプリケーションに直接必要なものしか書かない
- nginxやMySQLなどは公式イメージが使える
- ChefやItamaeはOS全体の設定が必要
- 冪等性の意識や、ローカル本番の差…保守…
気持ちいいポイント3
kubernetesが気持ちがいい
Dockerの本番環境を
模索していた
ちょっと前の僕
「Dockerつらい… 」
kubernetesに出会った僕
「なにこれ便利、楽しい!」
kubernetes + GKEの簡単便利なところ
- GKEがOSやkubernetesの面倒を見てくれる
- クラスタ作成からデプロイまで簡単なコマンドで完結
$ gcloud container clusters create examp...
さくっとkubernetesの関係。
serviceとdeployment、podとcontainerの関係がわかればきっと
kubernetesはきっと簡単。
kubernetesのYAMLについて
YAML地獄になるかと思ったけど、docker-compose構成に似た
感じでシンプルに作れる。最低限以下のようなYAMLファイルでい
ける。
- deployment.yaml
- service.y...
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: example
spec:
replicas: 1
template:
metadata:
labels:
appl...
起動が早い
気楽に作れる
kubernetesが便利
Dockerは
気持ちがいい
でも…
本番でRailsをDockerで
動かすにはいくつかの壁が
壁を取り除く⚒
マイグレーションの壁
1/5
いつどこでどうやって?
いくつかの方法
基本は新しいマイグレーションファイルが含まれたRailsのDocker
イメージに rails db:migrate コマンドを実行するコンテナをデプロ
イ前に実行する。
どこから実行するか
- GKEの場合:Google Cl...
steps:
# 略
- name: 'gcr.io/cloud-builders/gcloud'
entrypoint: 'bash'
args:
- '-c'
- |
gcloud container clusters get-creden...
ジョブの状態を監視するスクリプト
while true; do
status=`kubectl get pods --selector=job-name=migrate 
-o jsonpath='{.items[*].status
.cont...
秘匿情報・環境変数の壁
2/5
管理が面倒くさい
面倒くさい理由
秘匿情報をgitに含めたくないし意識したくない(Dockerに限った
話じゃない)。
たくさんの環境変数をCIやマネージドサービスに、それぞれ登録
して回るのがつらい。ツールがあってもつらい。なるべくコードでシ
ンプルに管理した...
秘匿情報は暗号化して管理する
secrets.ymlや.env.productionを暗号化して起動時に復号化
- rails5.1のencrypted secretsを使う
- AWS・GCP KMSを使う
- yaml_vaultを利用する...
cronの壁
3/5
いくつかの方法
- crondコンテナを立てる
- sidekiq-cronを使う
- kuroko2などのジョブスケジューラを使う
- AWS CloudWatch Events + LambdaでECS Taskを叩く
- GAE sche...
リソース監視の壁
4/5
リソース監視の監視
- AWS ECSのメトリクスはざっくりしている
- mackerelコンテナが手軽で良い感じ
- kubernetesはcAdvisorが標準であるので、これを利用
- prometheus + grafanaがサクッと動...
ログの壁
5/5
ログの取得
kubernetes + GKE
- 開発時にログを見るならsternが最高
- StackDriver Logging -> BigQuery
ECS
- CloudWatch logs -> lambda -> S3 -> At...
これで快適に
Rails + Docker
ライフが
すごせますね
ところで
他におすすめの
方法があります
今まで紹介した壁はHerokuでは
存在しないし、構築する手間もな
い(PaaS)、アプリケーションに集
中できてスケールもできる。
AddOnも豊富で拡張性もある。コ
ストはまぁ多少はるかもだけど保
守コストが低いので大変良い。
最高
Heroku使おう
とはいえ
ユースケースに応じて選択すれば良いのでは?
- AWSやGCPと連携する利便性を優先したい
- VPC内で完結させたい
- デプロイタイミングを細かくハンドリングしたい
- postStartなどで起動時の処理を行いたい
- ミドルウ...
ツールや流行りに流されず、自分
たち作っているプロダクトの価値
最大化に向けて、エンジニアとし
てどんな道を取るべきなのかで判
断すれば良いと思います。
おまけ
Multi Stage buildで軽量に
Docker CE 17.05からサポートされたMulti Stage buildを使って
Railsイメージを軽量にできる。
image 通常 Multi Stage build
ruby:2.4....
FROM ruby:2.4.1-alpine3.6 as builder
RUN apk update && apk upgrade && apk add --update
build-base 
libxml2-dev 
libxslt-de...
kubernetesでSSL
kube-legoを使うとIngressと連携して、簡単にLet's Encrypt証明
書の取得と設定が完了する
$ kubectl create -f ./k8s/ingress.yaml
$ kubectl ...
Docker for Macファイル同期遅い問題
CE17.05で cachedフラグに対応したことでreadが改善された
cachedなし cachedあり マウントなし
ab (Requests per second) 50 73 80
d...
kubernetesでゼロダウンタイムデプロイ
ゼロダウンタイムでローリングアップデートする例
- コンテナは1つしか使わない最小構成の例
kind: Deployment
spec:
replicas: 1
strategy:
rolling...
僕のkubernetes Rails構成例
5/7
6/7
kubernetes オートスケール
Horizontal Pod Autoscaling・Cluster Autoscalerを設定
- Podはすぐ立ち上がる・ノードは30秒くらいかかる
- 最小起動数は予測できるトラフィックに合わ...
GCBで並列ステップ
CloudContainerBuilderでは並列ステップが可能。つまりテストを
分散して実行することができる。
steps:
- name: gcr.io/cloud-builders/gcloud
id: 'A'
- ...
まとめ
まとめ
- Dockerは軽くて気軽に作れて気持ちがいい
- サーバやミドルウェアを気にしなくてすむ
- kubernetes GKEがとても良い
- CloudContainerBuilderも良い
- DevとOpsの距離が近くなる
- H...
docker stop $(docker ps -a -q)
ありがとうございました
質疑想定集
なんでDocker使うんですか?
- 開発環境が作りやすい/OSやミドルウェアの保守が面倒
なんでHeroku使わないんですか?
- Herokuだけで完結しにくい部分がある(VPCの中でやりたいと
かAWSの各サービスとの連携と強...
質疑想定集
AWSでkubernetesは?
- そういうツールがいくつかあるので、それを使えばGKEと同じ
ようなノリでkubernetesをAWSで使える
コストはどれくらいですか?
- プロダクションに耐えうる最小構成をGKEで作ると、月...
質疑想定集
VPS使ってやった方がよくないですか?
- 自分でサーバ構築したり面倒見たりする手間を考えると
Dockerとkubernetesでやりたい気持ち
なにか失敗したな、ミスったなみたいな話はありますか?
- 開発環境の話ですが、ミスっ...
普通のRailsアプリをdockerで本番運用する知見
普通のRailsアプリをdockerで本番運用する知見
普通のRailsアプリをdockerで本番運用する知見
普通のRailsアプリをdockerで本番運用する知見
Upcoming SlideShare
Loading in …5
×

普通のRailsアプリをdockerで本番運用する知見

20,295 views

Published on

RejectKaigi2017 at speee

Published in: Technology
  • Hello! Get Your Professional Job-Winning Resume Here - Check our website! https://vk.cc/818RFv
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

普通のRailsアプリをdockerで本番運用する知見

  1. 1. 普通のRailsアプリを Dockerで本番運用する知見 2017/08/19 RejectKaigi 2017 @zaru
  2. 2. @zaru さくらば ひろゆき
  3. 3. 最近の個人活動報告
  4. 4. 最近の活動の紹介 ブラウザにプッシュ通知できるライブラリ webpush (gem) - 最近マストドンにマージされた URLをQRコードに変換するMacアプリ LightningQR GitHubの通知をするMacアプリ NotifyHub seedを自動で作ってくれる seedbuilder (gem) パフォーマンス計測のCIサービス raysCI 開発中 最近スクラムマスターやってます
  5. 5. アンケート✋
  6. 6. Dockerを 使ったことがある人✋
  7. 7. Dockerを 導入している人✋
  8. 8. Dockerを本番に 導入している人✋
  9. 9. 今日のゴール
  10. 10. RailsをDockerで運用するための 知見が互いに集まる状態
  11. 11. 今日の流れ - Docker本番運用状況 - Docker気持ちいいポイント - Rails + Dockerの壁 - Docker + k8s + GKEおまけ
  12. 12. Docker本番運用状況
  13. 13. Docker本番運用状況 AWS ECS - 1サービスを本番運用 GCP GKE - 3サービスを本番運用 - プルリク単位のSTG環境を動的に作るサービス運用 drone.io - 分散rspecのためにDockerコンテナを利用
  14. 14. プルリク単位で ステージング環境を 自動でつくる
  15. 15. Dockerを頑張る 時代は終わった…
  16. 16. 気がする!
  17. 17. かも
  18. 18. Docker開発の 気持ちいいところ
  19. 19. 気持ちいいポイント1
  20. 20. すぐ立ち上がるのが 気持ちがいい
  21. 21. Vagrantは 「よっこらしょ」
  22. 22. Dockerは「よっ」
  23. 23. vagrant / docker 比較 起動時間 vagrant up 50sec docker-compose up 15sec VM立ちあげるのと、コンテナ立ち上げるのでは違うのは当然だ けど、毎日やる作業だからこそ高速にしたい気持ちがある。 なぜかVagrant環境がぶっ壊れることがあった…。 発症する人しない人がいて原因究明が非常につらい。
  24. 24. 気持ちいいポイント2
  25. 25. 気楽に作れるのが気持ちがいい
  26. 26. Chef 色んなファイルに コードを書いてる
  27. 27. Docker たった一つのDockerfile
  28. 28. 1コンテナ1プロセスだからシンプル - アプリケーションに直接必要なものしか書かない - nginxやMySQLなどは公式イメージが使える - ChefやItamaeはOS全体の設定が必要 - 冪等性の意識や、ローカル本番の差…保守…
  29. 29. 気持ちいいポイント3
  30. 30. kubernetesが気持ちがいい
  31. 31. Dockerの本番環境を 模索していた ちょっと前の僕 「Dockerつらい… 」
  32. 32. kubernetesに出会った僕 「なにこれ便利、楽しい!」
  33. 33. kubernetes + GKEの簡単便利なところ - GKEがOSやkubernetesの面倒を見てくれる - クラスタ作成からデプロイまで簡単なコマンドで完結 $ gcloud container clusters create example --num-nodes=3 $ gcloud docker -- push gcr.io/${PROJECT_ID}/${IMAGE}:${TAG} $ kubectl create -f ./k8s/deployment.yaml
  34. 34. さくっとkubernetesの関係。 serviceとdeployment、podとcontainerの関係がわかればきっと kubernetesはきっと簡単。
  35. 35. kubernetesのYAMLについて YAML地獄になるかと思ったけど、docker-compose構成に似た 感じでシンプルに作れる。最低限以下のようなYAMLファイルでい ける。 - deployment.yaml - service.yaml - ingress.yaml - migrate_job.yaml (*) まとめることもできるけど、分割したほうが運用しやすい
  36. 36. apiVersion: extensions/v1beta1 kind: Deployment metadata: name: example spec: replicas: 1 template: metadata: labels: application: rails spec: containers: - image: gcr.io/${PROJECT_ID}/${IMAGE_RAILS}:${TAG} name: rails ports: - containerPort: 3000 command: ["bundle", "exec", "rails", "s", "puma", "-b", "0.0.0.0", "-p", "3000", "-e", "production"]
  37. 37. 起動が早い 気楽に作れる kubernetesが便利
  38. 38. Dockerは 気持ちがいい
  39. 39. でも…
  40. 40. 本番でRailsをDockerで 動かすにはいくつかの壁が
  41. 41. 壁を取り除く⚒
  42. 42. マイグレーションの壁 1/5
  43. 43. いつどこでどうやって?
  44. 44. いくつかの方法 基本は新しいマイグレーションファイルが含まれたRailsのDocker イメージに rails db:migrate コマンドを実行するコンテナをデプロ イ前に実行する。 どこから実行するか - GKEの場合:Google Cloud Container Builder(GCB) - ECSの場合:各種CIからhako oneshot (*) db:migrateは使わないという方はスキップ
  45. 45. steps: # 略 - name: 'gcr.io/cloud-builders/gcloud' entrypoint: 'bash' args: - '-c' - | gcloud container clusters get-credentials example --zone asia-northeast1-a apt-get update && apt-get -y install gettext envsubst < ./k8s/k8s_job.yml | kubectl create -f - - name: 'gcr.io/cloud-builders/gcloud' entrypoint: 'bash' args: - './k8s/migration_status_check.sh' - name: 'gcr.io/cloud-builders/gcloud' entrypoint: 'bash' args: - '-c' - | gcloud container clusters get-credentials example --zone asia-northeast1-a kubectl delete jobs/migrate GCBのdb:migrate設定例 ジョブ作成 ジョブ監視 ジョブ削除
  46. 46. ジョブの状態を監視するスクリプト while true; do status=`kubectl get pods --selector=job-name=migrate -o jsonpath='{.items[*].status .containerStatuses[?(@.name=="rails")] .state.terminated.reason}'` if [ "$status" = "Completed" ]; then break fi if [ "$status" = "Error" ]; then echo "migration error." 1>&2 break fi sleep 2 done
  47. 47. 秘匿情報・環境変数の壁 2/5
  48. 48. 管理が面倒くさい
  49. 49. 面倒くさい理由 秘匿情報をgitに含めたくないし意識したくない(Dockerに限った 話じゃない)。 たくさんの環境変数をCIやマネージドサービスに、それぞれ登録 して回るのがつらい。ツールがあってもつらい。なるべくコードでシ ンプルに管理したい。 settings.ymlや.envなどで静的に書いて、RAILS_ENV のみで切 り替えられるようにする。
  50. 50. 秘匿情報は暗号化して管理する secrets.ymlや.env.productionを暗号化して起動時に復号化 - rails5.1のencrypted secretsを使う - AWS・GCP KMSを使う - yaml_vaultを利用する # GCP KMSの暗号化のコマンド例 $ gcloud kms encrypt --plaintext-file=.env.production --ciphertext-file=.env.production.enc --location=global --keyring=example-keyring --key=example-key
  51. 51. cronの壁 3/5
  52. 52. いくつかの方法 - crondコンテナを立てる - sidekiq-cronを使う - kuroko2などのジョブスケジューラを使う - AWS CloudWatch Events + LambdaでECS Taskを叩く - GAE schedule task + Functionsでkubectlを叩く - kubernetes CronJobを使う(まだアルファ) 項目 crond sidekiq-cron ジョブスケジューラ CloudWatch / GAE 機能性 ✕ ✕ ◯ ✕ コード化 △ ◯ ✕ △ 汎用性 △ ✕ ◯ ✕ スケール ✕ ◯ ◯ ◯ コスト ◯ △ ✕ ◯
  53. 53. リソース監視の壁 4/5
  54. 54. リソース監視の監視 - AWS ECSのメトリクスはざっくりしている - mackerelコンテナが手軽で良い感じ - kubernetesはcAdvisorが標準であるので、これを利用 - prometheus + grafanaがサクッと動く - github: giantswarm/kubernetes-prometheus
  55. 55. ログの壁 5/5
  56. 56. ログの取得 kubernetes + GKE - 開発時にログを見るならsternが最高 - StackDriver Logging -> BigQuery ECS - CloudWatch logs -> lambda -> S3 -> Athena その他 - papertrailやlogDNAなど
  57. 57. これで快適に Rails + Docker ライフが すごせますね
  58. 58. ところで
  59. 59. 他におすすめの 方法があります
  60. 60. 今まで紹介した壁はHerokuでは 存在しないし、構築する手間もな い(PaaS)、アプリケーションに集 中できてスケールもできる。 AddOnも豊富で拡張性もある。コ ストはまぁ多少はるかもだけど保 守コストが低いので大変良い。
  61. 61. 最高
  62. 62. Heroku使おう
  63. 63. とはいえ ユースケースに応じて選択すれば良いのでは? - AWSやGCPと連携する利便性を優先したい - VPC内で完結させたい - デプロイタイミングを細かくハンドリングしたい - postStartなどで起動時の処理を行いたい - ミドルウェアを徹底的にチューニングしたい - どうしても譲れないレイテンシがある - 小さいアプリをコンテナで詰めこみたい - 保守コスト vs インフラコスト
  64. 64. ツールや流行りに流されず、自分 たち作っているプロダクトの価値 最大化に向けて、エンジニアとし てどんな道を取るべきなのかで判 断すれば良いと思います。
  65. 65. おまけ
  66. 66. Multi Stage buildで軽量に Docker CE 17.05からサポートされたMulti Stage buildを使って Railsイメージを軽量にできる。 image 通常 Multi Stage build ruby:2.4.1-slim-stretch 287MB 153MB ruby:2.4.1-alpine 246MB 189MB Goと違ってライブラリの依存関係とかを把握していないと動かな いケースとか出てきそう… 1/7
  67. 67. FROM ruby:2.4.1-alpine3.6 as builder RUN apk update && apk upgrade && apk add --update build-base libxml2-dev libxslt-dev linux-headers mysql-dev nodejs WORKDIR /app COPY Gemfile ./Gemfile COPY Gemfile.lock ./Gemfile.lock RUN bundle install --jobs 4 COPY . . FROM ruby:2.4.1-alpine3.6 ENV LANG ja_JP.UTF-8 COPY --from=builder /usr/local/bundle /usr/local/bundle RUN apk update && apk upgrade && apk add --update mysql-dev nodejs WORKDIR /app COPY . .
  68. 68. kubernetesでSSL kube-legoを使うとIngressと連携して、簡単にLet's Encrypt証明 書の取得と設定が完了する $ kubectl create -f ./k8s/ingress.yaml $ kubectl apply -f k8s/kube-lego/example/gce/lego 2/7
  69. 69. Docker for Macファイル同期遅い問題 CE17.05で cachedフラグに対応したことでreadが改善された cachedなし cachedあり マウントなし ab (Requests per second) 50 73 80 docker-syncは同期がコケる事があるのでオススメしません MacからLinuxに移行すると幸せになるかも 3/7
  70. 70. kubernetesでゼロダウンタイムデプロイ ゼロダウンタイムでローリングアップデートする例 - コンテナは1つしか使わない最小構成の例 kind: Deployment spec: replicas: 1 strategy: rollingUpdate: maxSurge: 1 maxUnavailable: 0 type: RollingUpdate template: spec: containers: - image: gcr.io/${PROJECT_ID}/${IMAGE}:${TAG} readinessProbe: httpGet: path: / port: 9292 initialDelaySeconds: 15 timeoutSeconds: 5 4/7
  71. 71. 僕のkubernetes Rails構成例 5/7
  72. 72. 6/7 kubernetes オートスケール Horizontal Pod Autoscaling・Cluster Autoscalerを設定 - Podはすぐ立ち上がる・ノードは30秒くらいかかる - 最小起動数は予測できるトラフィックに合わせる - ノード数はデプロイ時のPod数も考慮に入れる $ kubectl autoscale deployment pod_name --cpu-percent=70 --min=1 --max=3 $ gcloud container clusters update cluster_name --enable-autoscaling --min-nodes=3 --max-nodes=20
  73. 73. GCBで並列ステップ CloudContainerBuilderでは並列ステップが可能。つまりテストを 分散して実行することができる。 steps: - name: gcr.io/cloud-builders/gcloud id: 'A' - name: gcr.io/cloud-builders/gcloud id: 'B' waitFor: - '-' - name: gcr.io/cloud-builders/gcloud id: 'C' waitFor: - '-' - name: gcr.io/cloud-builders/gcloud id: 'LAST' 何を待つかを指定 “-” だと何も待たない ID名を入れると、該当ステッ プが終わるまで待つ 7/7
  74. 74. まとめ
  75. 75. まとめ - Dockerは軽くて気軽に作れて気持ちがいい - サーバやミドルウェアを気にしなくてすむ - kubernetes GKEがとても良い - CloudContainerBuilderも良い - DevとOpsの距離が近くなる - Heroku、もっと使っていこ
  76. 76. docker stop $(docker ps -a -q) ありがとうございました
  77. 77. 質疑想定集 なんでDocker使うんですか? - 開発環境が作りやすい/OSやミドルウェアの保守が面倒 なんでHeroku使わないんですか? - Herokuだけで完結しにくい部分がある(VPCの中でやりたいと かAWSの各サービスとの連携と強めたいとか) - レイテンシが無視できないサービスもある
  78. 78. 質疑想定集 AWSでkubernetesは? - そういうツールがいくつかあるので、それを使えばGKEと同じ ようなノリでkubernetesをAWSで使える コストはどれくらいですか? - プロダクションに耐えうる最小構成をGKEで作ると、月額1 万〜1万5000円くらい。Herokuよりちょっと高いくらい
  79. 79. 質疑想定集 VPS使ってやった方がよくないですか? - 自分でサーバ構築したり面倒見たりする手間を考えると Dockerとkubernetesでやりたい気持ち なにか失敗したな、ミスったなみたいな話はありますか? - 開発環境の話ですが、ミスってボリューム消してデータベース の中身が消えました

×