1人でできる
Docker Kubernetes(GKE)を
使った新規サービス立ち上げ / Docker and Kubernetes(GKE) for new services

Aa777465acd82d13333678f3fc082c59?s=47 Spring_MT
December 04, 2018

1人でできる
Docker Kubernetes(GKE)を
使った新規サービス立ち上げ / Docker and Kubernetes(GKE) for new services

RailsアプリをKubernetes(GKE)上で運用した事例の紹介です。

Aa777465acd82d13333678f3fc082c59?s=128

Spring_MT

December 04, 2018
Tweet

Transcript

  1. 1⼈でできる
 Docker/Kubernetes(GKE)を
 使った新規サービス⽴ち上げ 春⼭ 誠 Makoto Haruyama Dec, 4, 2018

    Japan Container Days v18.12
  2. DeNA E-Commerce & Incubation Unit, Service Incubation Div., Rerep Gr.

    SpringMT Spring_MT 春⼭ 誠 Makoto Haruyama
  3. 新規サービスを⽴ち上げあるある

  4. ⼈がいない 時間がない 新規サービス⽴ち上げあるある

  5. None
  6. ⼈がいない 時間がない 新規サービス⽴ち上げあるある

  7. サクッと作ってユーザーの反応⾒てなる早で…

  8. None
  9. ⼈の問題と時間の問題をクリアして
 チャレンジしながら
 新規サービスを⽴ち上げた話をお届けします

  10. ⼈の問題と時間の問題をクリアするために
 最初に決めたこと

  11. 社内におけるRailsを利⽤したサービスの開発/運⽤の実績 • ReRepのサービス構造と似ているサービスの実績もあり 管理画⾯の作りやすさ Webフレームワークに関しては慣れたものを採⽤して
 それ以外の部分でチャレンジする Ruby on Railsの採⽤

  12. https://speakerdeck.com/spring_mt/api-spec-driven-development-with-swagger 開発の効率化についての話はこちらもどうぞ

  13. 過去のサービス運⽤で
 課題に感じていたこと

  14. インフラ構成の複雑さ Deployフローの複雑さ(簡単だけどシンプルではない) サーバー側とインフラ側のつなぎ込み 環境間の差分で起こるトラブル 過去の運⽤で課題に感じていたこと

  15. Deployフローを
 シンプルに 簡単なインフラの構成管理 サーバー側と
 インフラ側を疎結合に 環境の差分をなくす

  16. サーバー側と インフラ側の役割を整理してみる

  17. サーバー側とインフラ側の役割を整理 サーバー側の役割 インフラ側の役割 • コード群の実⾏環境の運⽤ • 実⾏環境同⼠の関係の定義 • 永続化されているデータの管理 •

    ビジネスロジックの実装
 (永続化されているデータを⽤いて サービスの振る舞いを定義する) サーバー側で定義した振る舞いがインフラ上で動いている 環境
  18. サーバー側とインフラ側の役割を踏まえた
 全体像

  19. サーバー側 インフラ側 本番環境 検証環境 1 検証環境 2

  20. これってなんで今まで
 やらなかったんだっけ?

  21. Dockerコンテナの管理 Dockerコンテナを動かすためのホストの運⽤ 複数のコンテナを協調して動かすための仕組み

  22. Deployフローを
 シンプルに 簡単なインフラの構成管理 サーバー側と
 インフラ側を疎結合に 環境の差分をなくす

  23. そこにKubernetesの登場 Dockerコンテナのオーケストレーションツール • Dockerコンテナを管理する敷居が下がる

  24. サーバー側 インフラ側 本番環境 検証環境 1 検証環境 2

  25. Deployフローを
 シンプルに 簡単なインフラの構成管理 サーバー側と
 インフラ側を疎結合に 環境の差分をなくす

  26. Docker/Kubernetesで 効率を上げて
 少⼈数でも開発/運⽤できそう!

  27. Dockerでやっていること

  28. Deployフローを
 シンプルに 簡単なインフラの構成管理 サーバー側と
 インフラ側を疎結合に 環境の差分をなくす

  29. Dockerイメージの構成

  30. Dockerイメージの役割 サーバー側の成果物 • サービスの振る舞いに必要なものは全て含まれる • Dockerイメージは全ての環境で動作可能にする

  31. Dockerイメージに含めるもの サービスの振る舞いに必要なものはDockerイメージに⼊ れる • 開発⾔語、ライブラリは全部同梱する • ruby • gem •

    grpcを使うためにglibcが必要なのでstretchベースを利⽤
  32. 全ての環境で同じ実⾏経路を通るようにする 1つの環境で動けば他の環境でも動くようにしたい • 実⾏経路が違うと本番環境だけで起こるような障害も。。 • 環境の差は設定によって表現する ライブラリ(rubyだとgem)はDockerイメージの中に同梱 NG OK

  33. 設定ファイル or 環境変数 設定ファイル • サーバー側 環境変数 • インフラ側 ファイル保存⽤の

    パケット名 管理画⾯のレイア ウトの⾊ 環境の識別⼦ MySQLのホスト サービスの振る舞いに 関係する設定をする サービスの振る舞いに 関係ない設定をする 秘匿情報 Webサーバーの ワーカー数 データベース名 外部サービスのア カウント情報
  34. Railsでのconfig設定 config.xの利⽤ • config/application.ymlに設定を書く • config/application.rbで下記のように定義

  35. 設定ファイルの切り替え Entrykitのprehookを使って設定ファイルを切り替える

  36. 切り替えるためのスクリプト

  37. Dockerイメージの作成と管理

  38. Dockerイメージの作成と管理 コードをpushする毎にDockerイメージを作る • Dockerイメージを作れないとリリースできないので毎回作りきる • ビルドは⼀回のみ 作成したDockerイメージは全て保存する • いつでも使える状態で保存しておく

  39. Docker Registry Google Container Registryでホスト • お⾦があれば上限なし • 今だと300GBくらい⾷っている •

    権限管理ができるのと権限管理とGKEの相性がよい
  40. Dockerイメージの作成フロー  ! "      

       ςετ   
  41. Kubernetesでやっていること

  42. Deployフローを
 シンプルに 簡単なインフラの構成管理 サーバー側と
 インフラ側を疎結合に 環境の差分をなくす

  43. Kubernetes Dockerコンテナのオーケストレーションツール • サービスディスカバリとロード・バランシング 宣⾔的にかける設定とyamlで定義できる設定

  44. Kubernetesではやらなかったこと StatefulSetsを使った状態を持つコンポーネントの管理 • DB(MySQL)の⾃前運⽤ • StatefulSetsを使って⾃分でMySQLのサーバーを⽴てて管理する 場合の運⽤コストの⾼さとサービスの可⽤性の要件の兼ねあい • 今回はGCPのCloud SQLを採⽤(99.95%のSLOでの折り合いはつけ

    ている)
  45. Kubernetesを実⾏する環境 GKE(Google Kubernetes Engine)を採⽤ • master nodeの管理(冗⻑構成もとってくれる) • stackdriverとの連携

  46. 構成

  47. クラスタを分けて環境を作る 前提として検証環境と本番環境はGCPのプロジェクトを分 ける • なので、検証環境と本番環境のクラスタは分かれる • 検証環境もそれの揃えて環境ごとにクラスタを分けて管理 • Kubernetesのバージョンアップの検証がしやすいメリットも

  48. Kubernetesの設定について

  49. 環境の差分をなくす 検証環境と本番環境でなるべく同じにしたいが • 環境の構成内容の質は変えたくないが、量は変えたい • 例: 検証環境ではPodの数を減らしたい(お⾦ないので、、) • 環境ごとに変えなければいけない設定だけを簡単に管理する

  50. 設定の差分 Ingressのhost名の設定 Deploymentのreplicaの数 環境を分けるために作ったRRP_STAGEという環境変数 • RRP_STAGEでDockerコンテナ起動時の設定の切り替えを⾏う

  51. 差分だけをうまく管理したい kustomize • 共通な設定を定義しつつ、overlayという機能で各環境毎の設定を上 書き可能 • Kubernetesのyamlのまま管理でき、Kubernetesの設定以上に覚え ることがない

  52. パッチの例 recplicasの数に応じてHPAの設定 やDeploymentで要求する resourceの値を変更 Webサーバーのworker数はリ ソース状況をみてインフラ側で制 御できるよう環境変数で管理

  53. インフラ側の構成を簡単に Kubernetesを最⼤限活かして置き換え • サービスディスカバリ/DNSの管理 • Dockerコンテナの管理

  54. livenessProbe アプリケーションが
 ⽣きているかだけの判断 • Webサーバーでは処理はなく、
 OKだけを返すだけのエンドポイントを⽤意 • https://github.com/mirakui/rack-health

  55. readinessProbe サーバーがリクエストを
 さばける状態か確認 • Workerプロセスが専有されて
 いないかを確認するようにする • リクエストの処理をしていない
 idleのworker数が0になったらアクセスを受け付けられない状態 とみなす

    • https://github.com/SpringMT/rack-readiness
  56. Graceful shutdown lifecycleのpreStop • Gracefull shutdownを実現するために、サーバー側で採⽤している Webサーバー(Unicorn)のshutdownの処理が⼊っている

  57. Dockerコンテナの更新 RollingUpdate • maxSurge、maxUnavailableは
 反映完了するまでの時間との
 兼ね合いで決める

  58. GKEの設定

  59. ⾼可⽤性担保のために nodeの⾃動修復 マルチゾーン • master nodeのHA

  60. 権限管理 ユーザーの権限管理 • GCPのIAMのみで権限管理 • クラスタ単位の権限管理はしていない • 検証環境と本番環境ではGCPのプロジェクトを分けて対応

  61. 限定公開クラスタを有効化 Cloud SQLのPrivate IP対応が最近あり、限定公開クラス タを利⽤することに切り替え • CloudSQLProxyのSidecarコンテナを全て排除でき、Jobの終了時や Gracefull shotdown時のSidecarコンテナを落とす処理が不要に •

    クエリダイジェスト取りやすくなった
  62. 承認済みネットワークの設定 承認済みネットワーク • 社内gatewayサーバーのみからアクセスできるdeployサー バー(GCE)を⽤意し、deployサーバー上でしかkubectlを実 ⾏できない • 社内gatewayサーバーにttyrecが仕込んであり、監査⽤に ログが残る •

    ただしWebコンソールでCloudShellを⽴ち上げるとkubectl で打てる • AuditLogからアクセスを監視して、承認済みネットワー ク以外からのアクセスがあったらslackに通知
  63. Preemptible VM 検証環境では全てPreemptible • コストダウン • 環境が常にディスポーザブルであることの確認 • GCP上に余剰インスタンがなければ⽴ち上がらなくなるので気を つけて使いましょう

  64. Cluster Auto Scaling クラスタオートスケーリングが検証環境ではon、本番環境 ではoff • スケールアップ/ダウンするときにサービス断の可能性がある • まだ解消されていないぽいです

  65. stackdriver custom metrics idleなworker数をstackdriver custom metricsを使って 監視 • worker数が枯渇するとリクエストがさばけなくなる •

    rack-server_statusというgemでidleなworker数を取得 • https://github.com/SpringMT/rack-server-status-to-sd
  66. Kuberenetes上で
 Railsを動かすための⼯夫

  67. DBスキーマの管理 DBスキーマを適⽤するコマンド実⾏を⾏うPodを⽤意 • スキーマ適⽤コマンドを打つためにPodを⼀つ⽤意し、そこのPod経 由でコマンドを打つ • 柔軟にコマンドを打ちたい • ターミナル上で結果を確認したい •

    dry-run -> applyの流れ • このPodはPod単体で管理せず、Deploymentで管理
  68. idleなworker数ベースのHPA workerが枯渇 = サービス⽌ まっている • CPUでも設定しているが、CPUが ⾼くない状態でもworkerの枯渇は あり得る

  69. ログ ログは標準出⼒へ • stackdriverで回収し、export • exportされた後、pub/sub -> dataflowを経由してBQに⼊れたりして います

  70. 環境構築

  71. 環境構築の現状 クラスタ作成はWeb Consoleから。。。 • 「既存クラスタのクローンを作成する」テンプレートが楽ちん kubectl create secretを何回か打って kustomize build

    | kubectl apply -f サーバー側のセットアップ 終わったらDNSに設定追加でDONE
  72. ローカルでの開発

  73. ローカルでKubernetesは⽴ち上げない https://speakerdeck.com/spring_mt/api-spec-driven-development-with-swagger

  74. 負荷試験

  75. 負荷試験 簡単なシナリオを作って想定の10倍のリクエストを投げる • 簡単に下記をチェック • HPAの発動チェック • 負荷試験中の再起動実験 • slow

    queryのチェック
  76. Docker&Kubernetesで
 やっていること

  77. Deployフローを
 シンプルに 簡単なインフラの構成管理 サーバー側と
 インフラ側を疎結合に 環境の差分をなくす

  78. Dockerイメージを
 Kubernetesクラスタに反映させるフロー

  79. ここまでくれば! あとはDockerイメージをKubernetesの環境に投げ込む

  80. Dockerイメージの反映 kubectl set imageを使ってDocker imageを⼊れ替え • kubectl set image deployment

    • kubectl set image cronjobs --all DB schemaの適⽤ • kubectl exec -it rerep-db-schema-pod -c rerep-db-schema -- bundle exec rake db_schema:apply これらをラップしたコマンド作っている
  81. 検証環境への反映 ローカルから反映 • 開発者がいいタイミングで反映している • CDはしていない • QA中の場合はテストチームと連携して反映している

  82. 反映されているDeploymentの状況 slack上で
 確認できる

  83. 本番環境 検証環境と本番環境でGCPのプロジェクトが別れている • Docker registryも分かれている この2つの環境を⾏き来できるのはDockerのイメージのみ

  84. 本番環境へのイメージを移⾏ gcloudコマンドでGCPのプロジェクトを跨いで移⾏ • gcloud container images add-tag あとはdeployサーバーからsandboxと同じコマンドを打 つだけ •

    CDはまだできていない
  85. 反映後の監視 パフォーマンスはstackdriver traceなどで確認 エラーログはslackに流している

  86. 実績

  87. これららの取り組みによる実績 コードの差によるバグ • 1件:デバッグ機能をoffにする条件分岐 構成の差によるバグ • なし

  88. まとめ

  89. Deployフローを
 シンプルに 簡単なインフラの構成管理 サーバー側と
 インフラ側を疎結合に 環境の差分をなくす

  90. ⼀⼈でできた Docker/Kubernetesの役割を整理して導⼊したところ効 率が上がり、結果、⼀⼈でもサーバー/インフラの開発/運 ⽤をすることができています。

  91. https://techcon.dena.com/2019/

  92. ありがとうございました!

  93. ちなみに…

  94. お話できなかったこと データの運⽤周り 分析環境について

  95. データの運⽤

  96. サーバー側とインフラ側の役割を整理 サーバー側の役割 インフラ側の役割 • コード群の実⾏環境の運⽤ • 実⾏環境同⼠の関係の定義 • 永続化されているデータの管理 •

    ビジネスロジックの実装
 (永続化されているデータを⽤いて サービスの振る舞いを定義する) サーバー側で定義した振る舞いがインフラ上で動いている 環境
  97. ReRepでのデータの管理 運営が⽤意するデータ • ミッション • 説明⽂ • 画像 ユーザーが作成するデータ •

    ミッションクリアのログ • アクティビティログ
  98. 運営が⽤意するデータ ReRepではサービスのコンテンツはサービス運営側が⽤意 運⽤が⽤意するデータを環境に依存せず管理することで、 データも含めて環境の差異をコントロール • データの⾃動⽣成や反映はエンジニア以外の⼈でもできる

  99. もしご興味のある⽅がいらっしゃいましたら
 のちほどぜひお声掛けください!

  100. ありがとうございました!