Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

DeNA E-Commerce & Incubation Unit, Service Incubation Div., Rerep Gr. SpringMT Spring_MT 春⼭ 誠 Makoto Haruyama

Slide 3

Slide 3 text

新規サービスを⽴ち上げあるある

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

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

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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

Slide 12

Slide 12 text

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

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

サーバー側とインフラ側の役割を整理 サーバー側の役割 インフラ側の役割 • コード群の実⾏環境の運⽤ • 実⾏環境同⼠の関係の定義 • 永続化されているデータの管理 • ビジネスロジックの実装
 (永続化されているデータを⽤いて サービスの振る舞いを定義する) サーバー側で定義した振る舞いがインフラ上で動いている 環境

Slide 18

Slide 18 text

サーバー側とインフラ側の役割を踏まえた
 全体像

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

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

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

Dockerでやっていること

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

Dockerイメージの構成

Slide 30

Slide 30 text

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

Slide 31

Slide 31 text

Dockerイメージに含めるもの サービスの振る舞いに必要なものはDockerイメージに⼊ れる • 開発⾔語、ライブラリは全部同梱する • ruby • gem • grpcを使うためにglibcが必要なのでstretchベースを利⽤

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

設定ファイル or 環境変数 設定ファイル • サーバー側 環境変数 • インフラ側 ファイル保存⽤の パケット名 管理画⾯のレイア ウトの⾊ 環境の識別⼦ MySQLのホスト サービスの振る舞いに 関係する設定をする サービスの振る舞いに 関係ない設定をする 秘匿情報 Webサーバーの ワーカー数 データベース名 外部サービスのア カウント情報

Slide 34

Slide 34 text

Railsでのconfig設定 config.xの利⽤ • config/application.ymlに設定を書く • config/application.rbで下記のように定義

Slide 35

Slide 35 text

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

Slide 36

Slide 36 text

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

Slide 37

Slide 37 text

Dockerイメージの作成と管理

Slide 38

Slide 38 text

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

Slide 39

Slide 39 text

Docker Registry Google Container Registryでホスト • お⾦があれば上限なし • 今だと300GBくらい⾷っている • 権限管理ができるのと権限管理とGKEの相性がよい

Slide 40

Slide 40 text

Dockerイメージの作成フロー  ! "          ςετ   

Slide 41

Slide 41 text

Kubernetesでやっていること

Slide 42

Slide 42 text

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

Slide 43

Slide 43 text

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

Slide 44

Slide 44 text

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

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

構成

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

Kubernetesの設定について

Slide 49

Slide 49 text

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

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

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

Slide 52

Slide 52 text

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

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

Graceful shutdown lifecycleのpreStop • Gracefull shutdownを実現するために、サーバー側で採⽤している Webサーバー(Unicorn)のshutdownの処理が⼊っている

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

GKEの設定

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

承認済みネットワークの設定 承認済みネットワーク • 社内gatewayサーバーのみからアクセスできるdeployサー バー(GCE)を⽤意し、deployサーバー上でしかkubectlを実 ⾏できない • 社内gatewayサーバーにttyrecが仕込んであり、監査⽤に ログが残る • ただしWebコンソールでCloudShellを⽴ち上げるとkubectl で打てる • AuditLogからアクセスを監視して、承認済みネットワー ク以外からのアクセスがあったらslackに通知

Slide 63

Slide 63 text

Preemptible VM 検証環境では全てPreemptible • コストダウン • 環境が常にディスポーザブルであることの確認 • GCP上に余剰インスタンがなければ⽴ち上がらなくなるので気を つけて使いましょう

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

stackdriver custom metrics idleなworker数をstackdriver custom metricsを使って 監視 • worker数が枯渇するとリクエストがさばけなくなる • rack-server_statusというgemでidleなworker数を取得 • https://github.com/SpringMT/rack-server-status-to-sd

Slide 66

Slide 66 text

Kuberenetes上で
 Railsを動かすための⼯夫

Slide 67

Slide 67 text

DBスキーマの管理 DBスキーマを適⽤するコマンド実⾏を⾏うPodを⽤意 • スキーマ適⽤コマンドを打つためにPodを⼀つ⽤意し、そこのPod経 由でコマンドを打つ • 柔軟にコマンドを打ちたい • ターミナル上で結果を確認したい • dry-run -> applyの流れ • このPodはPod単体で管理せず、Deploymentで管理

Slide 68

Slide 68 text

idleなworker数ベースのHPA workerが枯渇 = サービス⽌ まっている • CPUでも設定しているが、CPUが ⾼くない状態でもworkerの枯渇は あり得る

Slide 69

Slide 69 text

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

Slide 70

Slide 70 text

環境構築

Slide 71

Slide 71 text

環境構築の現状 クラスタ作成はWeb Consoleから。。。 • 「既存クラスタのクローンを作成する」テンプレートが楽ちん kubectl create secretを何回か打って kustomize build | kubectl apply -f サーバー側のセットアップ 終わったらDNSに設定追加でDONE

Slide 72

Slide 72 text

ローカルでの開発

Slide 73

Slide 73 text

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

Slide 74

Slide 74 text

負荷試験

Slide 75

Slide 75 text

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

Slide 76

Slide 76 text

Docker&Kubernetesで
 やっていること

Slide 77

Slide 77 text

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

Slide 78

Slide 78 text

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

Slide 79

Slide 79 text

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

Slide 80

Slide 80 text

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 これらをラップしたコマンド作っている

Slide 81

Slide 81 text

検証環境への反映 ローカルから反映 • 開発者がいいタイミングで反映している • CDはしていない • QA中の場合はテストチームと連携して反映している

Slide 82

Slide 82 text

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

Slide 83

Slide 83 text

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

Slide 84

Slide 84 text

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

Slide 85

Slide 85 text

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

Slide 86

Slide 86 text

実績

Slide 87

Slide 87 text

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

Slide 88

Slide 88 text

まとめ

Slide 89

Slide 89 text

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

Slide 90

Slide 90 text

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

Slide 91

Slide 91 text

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

Slide 92

Slide 92 text

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

Slide 93

Slide 93 text

ちなみに…

Slide 94

Slide 94 text

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

Slide 95

Slide 95 text

データの運⽤

Slide 96

Slide 96 text

サーバー側とインフラ側の役割を整理 サーバー側の役割 インフラ側の役割 • コード群の実⾏環境の運⽤ • 実⾏環境同⼠の関係の定義 • 永続化されているデータの管理 • ビジネスロジックの実装
 (永続化されているデータを⽤いて サービスの振る舞いを定義する) サーバー側で定義した振る舞いがインフラ上で動いている 環境

Slide 97

Slide 97 text

ReRepでのデータの管理 運営が⽤意するデータ • ミッション • 説明⽂ • 画像 ユーザーが作成するデータ • ミッションクリアのログ • アクティビティログ

Slide 98

Slide 98 text

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

Slide 99

Slide 99 text

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

Slide 100

Slide 100 text

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