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.

パフォーマンス計測Ciサービスを作って得た知見を共有したい

368 views

Published on

Rails Developers Meetup #5
@zaru

Published in: Technology
  • Be the first to comment

パフォーマンス計測Ciサービスを作って得た知見を共有したい

  1. 1. パフォーマンス計測CIサービスを 作って得た知見を共有したい Rails Developers Meetup #5 2017-09-28 @zaru
  2. 2. @zaru 株式会社ベーシックCTO
  3. 3. 株式会社ベーシック
  4. 4. 最近の活動 ブラウザにプッシュ通知できるライブラリwebpush (gem) 最近マストドンにマージされた URLをQRコードに変換するMacアプリLightningQR GitHubの通知をするMacアプリNotifyHub seedを自動で作ってくれるseedbuilder (gem) スクラムマスター コードを音にしたり、ドット絵にしたり、リズムゲームにしたり
  5. 5. 今日話したいこと raysCI について GitHub Apps について Docker / kubernetes について 個人開発プロジェクトについて
  6. 6. raysCI
  7. 7. 個人で開発している パフォーマンス計測をするCIサービス プルリクを作ったら自動でMasterとPRブランチのベンチマーク ベンチマークの種類 ApacheBench ヘッドレスブラウザ First paint DOM content load assets network (HAR) stackprof (gem)
  8. 8. 開発中の画面
  9. 9. Railsのみサポート 将来的には他の言語やフレームワークに対応したい プライベートベータ 近いうちにオープンベータへ 計測に使ったビルド時間の従量課金を予定 その他、予定している機能 Viewレンダリング結果のdiff ステージング環境自動構築 プロダクション環境への定期パフォーマンスチェック
  10. 10. GitHub Apps
  11. 11. OAuth Apps とGitHub Apps
  12. 12. OAuth Apps (従来のもの) はユーザに対してインストール ユーザが削除されたりリポジトリへの権限を失うと消える アクセストークンはユーザが取り消さない限り永久有効 GitHub Apps はリポジトリに対してインストール 正確にはリポジトリのオーナー(Organization やUser)に インストールして、配下のリポジトリに付与するようなイメージ アクセストークンの有効期限は1時間 GitHub Apps のOAuth も可能 こちらはユーザ情報を取得するために使う(限定的) マーケットプレイスに出せる
  13. 13. OAuth Apps ではbot がコメントするためには実ユーザになりすます GitHub Apps は一人格としてコメントできる OAuth したユーザの代わりにもコメントできる
  14. 14. 人に依存しないサービス連携! 業務では非常に嬉しい気持ち
  15. 15. マーケットプレイス
  16. 16. GitHub 上でアプリをインストール・決済できる 提供者は売上の25%をGitHub に献上 決済の仕組みを作らなくて済むので楽? でもAPIのコールバックとかで、ある程度開発は必要 登録する条件 250人以上にインストール済み<厳しい セキュリティ審査や申請ドキュメントなど結構たいへんそう… アクセスログとか保持する基盤とか全部そろえて説明できる資料 とか
  17. 17. GitHub Appsの作り方 とても簡単
  18. 18. アクセストークンとAPI 秘密鍵を使ってJWTに署名して生成(有効期限最大10分) JWTを使ってアクセストークンを取得(有効期限1時間) アクセストークンで各種APIにアクセス(一部のAPIのみ)
  19. 19. JWT コード例 private_pem = File.read(path_to_pem) private_key = OpenSSL::PKey::RSA.new(private_pem) payload = { iat: Time.now.to_i, exp: Time.now.to_i + (10 * 60), iss: <GitHub App ID> } jwt = JWT.encode(payload, private_key, "RS256")
  20. 20. JWTのexpireに注意 最大で10分の有効期限を指定できる なぜか10分ぴったり指定すると、時々未来の日付だよと怒られる 8分にしても怒られる時がある 10分も必要ないと思うので、5分程度で運用したほうが良さ気
  21. 21. GitHub Apps のOAuth
  22. 22. GitHub Apps にもユーザ情報を取得するOAuth がある 取得できるユーザの情報は限定されている ユーザ名やID・アバター 公開設定のEmail 非公開の場合はnull /user/emails にはアクセスできない 将来的には取得できるようになるっぽいが… インストール済みリポジトリ/ Public リポジトリ インストールしてないPrivate リポジトリは取得できない リポジトリの検索などはできない
  23. 23. ユーザ中心のサービスは向いてない…
  24. 24. GitHub Apps のAPI
  25. 25. 現時点で全てのAPIにアクセスできるわけではない 少しずつ解放される様子 9月21日にも66個のAPIが解放されている もし要望があるならフォーラムに投稿すると早くなるかも? Request support for additional endpoints for Integrations リポジトリ検索ができないのがつらい
  26. 26. GitHub Enterpriseでの利用
  27. 27. GitHub Enterprise v2.11 で利用可能になるアナウンス しかしv2.11 のリリースノートには記載なし…
  28. 28. GitHub Apps で気をつける所
  29. 29. Webhook は取りこぼさないように 取りこぼすとデータをロストしてしまう 一応、設定画面から再送処理は可能だが…現実的ではない タイムアウトや例外などで死なないようにする 例えばsidekiq などに逃がす 将来的にはエラーを通知する仕組みを用意してくれるっぽい パーミッションの変更はなるべくしない 変更後、ユーザが承認しないと反映しない すごく分かりにくいUIなので気が付きにくい…
  30. 30. 通知も何もなく、ひっそりとSettingsにあるだけ メールでの通知はしてくれる
  31. 31. GitHub Apps のインストール導線
  32. 32. 不親切な流れになってしまう サービスページ(インストール誘導) → GitHubのインストール承認ページ → インストール完了 → 終了(github.comのまま…) インストール後、サービスページに自動で戻らない 理想なのはOAuth Appsのような流れ サービスサイトでちゃんとフローを案内する必要がある(厳しい) 要望は出ていて検討中らしいので改善されるかもしれない マーケットプレイス中心の導線設計なのかも
  33. 33. Privateリポジトリ一覧が取れないので、他のリポジトリに 追加インストールするのもGitHubページ上でないとできない サービスサイトとGitHub App設定画面を行ったり来たり 追加/削除自体はAPIでできるが…
  34. 34. GitHub Apps ローカル開発
  35. 35. ローカルでWebhook 受け取る方法 ngrok で外部に解放 無料だと起動のたびにホスト名が変わるので面倒 nginx でproxy サーバをたてる ルータでポートフォワーディングが必要 payload の例があるので、curl などで叩く https://developer.github.com/v3/activity/events/types/
  36. 36. upstream http_backend { # server example.ngrok.io; # ngrokの場合 server 10.0.0.10:3000; # ローカルのグローバルIP keepalive 128; } server { location / { proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Host $http_host; proxy_set_header X-CSRF-Token $http_x_csrf_token; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $http_host; # proxy_set_header Host example.ngrok.io; # ngrokの場合 proxy_redirect off; proxy_http_version 1.1; proxy_set_header Connection ""; proxy_pass http://http_backend/; } }
  37. 37. Docker
  38. 38. CI, どうやってアプリを動かすか
  39. 39. CIは、ユーザのアプリ毎・ビルド毎に分離した動作環境が必要 今ならDockerが良い気がする どうやってDockerビルド/ コンテナ管理しよう? CIサービス自体もDockerで動かしたい Docker in Docker docker.sock 共有 自前ビルドサーバ+ オーケストレーション kubernetes + GCP Container Builder
  40. 40. Docker in Docker
  41. 41. jpetazzo/dind
  42. 42. マトリョーシカのようにコンテナ内でコンテナを起動 Dockerのprivilegedオプションを利用してDockerを操作
  43. 43. 良い点 階層構造なので綺麗で管理しやすい 悪い点 パフォーマンス privilegedオプションで怖い ボリュームが残ってしまう そもそも制作者自身があまり推奨していない Using Docker-in-Docker for your CI or testing environment? Think twice.
  44. 44. docker.sock 共有
  45. 45. ホストの/var/lib/docker.sock を共有する 階層構造はなく、単にホストのDockerエンジンにアクセスできる
  46. 46. 良い点 普通にDockerを使っているようなものなのでシンプル ビルドキャッシュも簡単に使える 悪い点 コンテナ内から他のコンテナが丸見え… 内部利用限定なら良いかもしれない
  47. 47. 自前ビルド+ オーケストレーション
  48. 48. つらい
  49. 49. kubernetes + GCP Container Builder
  50. 50. コンテナの管理はkubernetesに全部任せる ビルドはGCP Container Builderに全部任せる
  51. 51. 超絶楽
  52. 52. いつどれくらいコンテナが立てられるか予測できない GKE + k8sならコンテナ作成時にリソースが不足していたら自動で ノードを起動してくれる(オートスケール) リトライ処理やライフサイクルなど機能が豊富 複雑になりがちなビルドステップどうしよう… Container Builder自体が簡易CIみたいなもの 簡単にステップを記述でき、公式で用意してあるイメージが便利 (gitコンテナ・dockerコンテナ・gcloudコンテナなど) 悪い点 Container Builderがビルドキャッシュをサポートしていない 毎回フルビルドなので時間がかかる
  53. 53. ところで GKE + kubernetes かHeroku か
  54. 54. 細かくコントロールとビルドをするならGKE + kubernetes kubernetesだけやってればOKな感じある 小規模/シンプルなアーキテクチャならHerokuオススメ むしろHerokuライクなサービスが主流に…なってほしい 詳しくは普通のRailsアプリをDockerで本番運用する知見を
  55. 55. CI, 計測の仕方
  56. 56. 計測の流れ Container Builder にビルド依頼 ビルドコンテナがAppコンテナに計測用のコードを仕込む Gem le やinitializer / environment など ビルドコンテナがk8s デプロイファイルを作成 k8s にデプロイ 計測コンテナがApp の立ち上がりを待機 計測開始 計測後、CIコンテナにレポート送信 Pod を削除して終了
  57. 57. CIサービスを作るのに使った小技
  58. 58. appコンテナ起動時にDB作成/インポートを行う 正直、力技…どうにかしたい command: - "sh" - "-c" - > bundle exec rails db:create && bundle exec rails db:schema:load && bundle exec rails db:seed && bundle exec rails db < import.sql && bundle exec rails s -p 3000 -b 0.0.0.0
  59. 59. k8s で、コンテナ起動前と終了時にコマンド実行できる spec: containers: - name: lifecycle-demo-container image: nginx lifecycle: postStart: exec: command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/sha preStop: exec: command: ["/usr/sbin/nginx","-s","quit"]
  60. 60. k8s で、share dirを作成して各コンテナでファイル共有
  61. 61. k8sのボリュームは以下の3種類 EmptyDir HostDir GCEPersistentDisk / awsElasticBlockStore EmptyDir とHostDir は永続化されない。Pod 内で一時的に使いたいな らEmptyDir、ホスト側でも使いたいならHostDir、永続化したいのな ら外部ストレージのGCEPersistentDisk。 raysCI ではベンチマーク結果や、設定ファイルなどをEmptyDir に格納 して利用。
  62. 62. resources を指定してリソースを固定する resources: requests: # 最低限 cpu: 200m memory: 512M limits: # 最大 cpu: 200m memory: 512M ちゃんと指定しないとパフォーマンスがかなりブレる 1CPUに対しての割合を指定する。 0.1 は 100m m はミリコアと読んだりする メモリ使用が指定量を超えたらPod が死ぬ(再起動) CPU は指定量を超えたら水平オートスケールする(設定が必要)
  63. 63. 環境変数・秘匿情報について env: - name: FOO_KEY # 普通の環境変数 value: "foo value" - name: SECRET_KEY # 秘匿情報 valueFrom: secretKeyRef: name: secret_name key: secret_key k8sクラスタに接続できるなら誰でも閲覧可能 秘匿情報はsecrets API 経由で取得するようにする
  64. 64. Container Builder のローカル開発 GoogleCloudPlatform/container-builder-local ローカルで動かせる いちいちdocker push とかしなくて済む 気の済むまでビルドデバッグ可能
  65. 65. 個人開発プロジェクトについて
  66. 66. raysCI の開発ステータス 5月15日開発開始/ 約70日間の開発 1日平均2 時間程度/ 累計で約142 時間の開発 業務でやったら1ヶ月くらい?
  67. 67. とにかく 個人開発のプロジェクトは 頓挫しやすい
  68. 68. 今のところうまくいってる 僕の開発スタイル
  69. 69. 毎日コードを書く 土日にまとめてやると状態を忘れがち 習慣にする まずはPCの前に座る これだけで継続しやすい 自分を甘やかすことも必要 夜ご飯のビール は飲んでもいい(1本まで) 今日はなんにもしないで映画見る、など コードを捨てるのを躊躇しない 作ってみて知見を得たら再度作り直す 妥協を積み重ねたコード、さわるのつらい
  70. 70. モチベーションの作り方
  71. 71. 業務とリンクしやすい領域を作る 相互作用で実益があると継続しやすく、お賃金が上る?! 「この問題進研ゼミでやったやつだ」 サービスを作りきるまでの余計な壁を取り払う 新しい技術にふれるのが目的なら離れていても問題ないが… その場合は短期決戦にしぼったほうが良い 小さいミニアプリを大量に作るとか
  72. 72. 何のために作るのかを明確にする お金のため 技術習得のため 課題解決のため 目的が明確になると、何を優先して、何を捨てるのか 判断ができてストレスが減る
  73. 73. 途中経過をなんでも良いからアウトプットする 完成してからアウトプットでは道程が長い 改善の参考になるフィードバックがあるかも 手に入った知見はその場でアウトプット
  74. 74. 「やるぞ」駆動 Twitterにやる気はなくても「やるぞ」とつぶやく 自然とやる気が出てくる
  75. 75. 公開に到達するために
  76. 76. ゴールを大きくしすぎない 小さく始めて素早く公開できる仕様にする やらないことを決める 対象ユーザの範囲を限定する なにかを妥協する 例えば完璧なテストコードや管理画面 raysCI はDocker 環境のみに対応、今はRails だけビルドできるように 制限を加えることで作りやすくなる。ある程度は拡張できるように事前 設計するけど、まだ見えない未来に投資しすぎない。
  77. 77. まとめ GitHub Apps は作るのは簡単だけど、発展途上中 Docker自前でやるならkubernetes ContainerBuilder が優秀すぎて泣く 個人開発は習慣化と実益をとれるようにする 小さく作って、早く公開できるようにする
  78. 78. ありがとうございました。 docker stop $(docker ps -a -q)

×