RailsアプリをKubernetes(GKE)上で運用した事例の紹介です。
1⼈でできる Docker/Kubernetes(GKE)を 使った新規サービス⽴ち上げ春⼭ 誠 Makoto HaruyamaDec, 4, 2018 Japan Container Days v18.12
View Slide
DeNAE-Commerce & Incubation Unit,Service Incubation Div.,Rerep Gr.SpringMT Spring_MT春⼭ 誠Makoto Haruyama
新規サービスを⽴ち上げあるある
⼈がいない時間がない新規サービス⽴ち上げあるある
サクッと作ってユーザーの反応⾒てなる早で…
⼈の問題と時間の問題をクリアして チャレンジしながら 新規サービスを⽴ち上げた話をお届けします
⼈の問題と時間の問題をクリアするために 最初に決めたこと
社内におけるRailsを利⽤したサービスの開発/運⽤の実績• ReRepのサービス構造と似ているサービスの実績もあり管理画⾯の作りやすさWebフレームワークに関しては慣れたものを採⽤して それ以外の部分でチャレンジするRuby on Railsの採⽤
https://speakerdeck.com/spring_mt/api-spec-driven-development-with-swagger開発の効率化についての話はこちらもどうぞ
過去のサービス運⽤で 課題に感じていたこと
インフラ構成の複雑さDeployフローの複雑さ(簡単だけどシンプルではない)サーバー側とインフラ側のつなぎ込み環境間の差分で起こるトラブル過去の運⽤で課題に感じていたこと
Deployフローを シンプルに簡単なインフラの構成管理サーバー側と インフラ側を疎結合に環境の差分をなくす
サーバー側とインフラ側の役割を整理してみる
サーバー側とインフラ側の役割を整理サーバー側の役割 インフラ側の役割• コード群の実⾏環境の運⽤• 実⾏環境同⼠の関係の定義• 永続化されているデータの管理• ビジネスロジックの実装 (永続化されているデータを⽤いてサービスの振る舞いを定義する)サーバー側で定義した振る舞いがインフラ上で動いている環境
サーバー側とインフラ側の役割を踏まえた 全体像
サーバー側 インフラ側本番環境検証環境 1検証環境 2
これってなんで今まで やらなかったんだっけ?
Dockerコンテナの管理Dockerコンテナを動かすためのホストの運⽤複数のコンテナを協調して動かすための仕組み
そこにKubernetesの登場Dockerコンテナのオーケストレーションツール• Dockerコンテナを管理する敷居が下がる
Docker/Kubernetesで効率を上げて 少⼈数でも開発/運⽤できそう!
Dockerでやっていること
Dockerイメージの構成
Dockerイメージの役割サーバー側の成果物• サービスの振る舞いに必要なものは全て含まれる• Dockerイメージは全ての環境で動作可能にする
Dockerイメージに含めるものサービスの振る舞いに必要なものはDockerイメージに⼊れる• 開発⾔語、ライブラリは全部同梱する• ruby• gem• grpcを使うためにglibcが必要なのでstretchベースを利⽤
全ての環境で同じ実⾏経路を通るようにする1つの環境で動けば他の環境でも動くようにしたい• 実⾏経路が違うと本番環境だけで起こるような障害も。。• 環境の差は設定によって表現するライブラリ(rubyだとgem)はDockerイメージの中に同梱NG OK
設定ファイル or 環境変数設定ファイル• サーバー側環境変数• インフラ側ファイル保存⽤のパケット名管理画⾯のレイアウトの⾊環境の識別⼦ MySQLのホストサービスの振る舞いに関係する設定をするサービスの振る舞いに関係ない設定をする秘匿情報Webサーバーのワーカー数データベース名外部サービスのアカウント情報
Railsでのconfig設定config.xの利⽤• config/application.ymlに設定を書く• config/application.rbで下記のように定義
設定ファイルの切り替えEntrykitのprehookを使って設定ファイルを切り替える
切り替えるためのスクリプト
Dockerイメージの作成と管理
Dockerイメージの作成と管理コードをpushする毎にDockerイメージを作る• Dockerイメージを作れないとリリースできないので毎回作りきる• ビルドは⼀回のみ作成したDockerイメージは全て保存する• いつでも使える状態で保存しておく
Docker RegistryGoogle Container Registryでホスト• お⾦があれば上限なし• 今だと300GBくらい⾷っている• 権限管理ができるのと権限管理とGKEの相性がよい
Dockerイメージの作成フロー ! " ςετ
Kubernetesでやっていること
KubernetesDockerコンテナのオーケストレーションツール• サービスディスカバリとロード・バランシング宣⾔的にかける設定とyamlで定義できる設定
KubernetesではやらなかったことStatefulSetsを使った状態を持つコンポーネントの管理• DB(MySQL)の⾃前運⽤• StatefulSetsを使って⾃分でMySQLのサーバーを⽴てて管理する場合の運⽤コストの⾼さとサービスの可⽤性の要件の兼ねあい• 今回はGCPのCloud SQLを採⽤(99.95%のSLOでの折り合いはつけている)
Kubernetesを実⾏する環境GKE(Google Kubernetes Engine)を採⽤• master nodeの管理(冗⻑構成もとってくれる)• stackdriverとの連携
構成
クラスタを分けて環境を作る前提として検証環境と本番環境はGCPのプロジェクトを分ける• なので、検証環境と本番環境のクラスタは分かれる• 検証環境もそれの揃えて環境ごとにクラスタを分けて管理• Kubernetesのバージョンアップの検証がしやすいメリットも
Kubernetesの設定について
環境の差分をなくす検証環境と本番環境でなるべく同じにしたいが• 環境の構成内容の質は変えたくないが、量は変えたい• 例: 検証環境ではPodの数を減らしたい(お⾦ないので、、)• 環境ごとに変えなければいけない設定だけを簡単に管理する
設定の差分Ingressのhost名の設定Deploymentのreplicaの数環境を分けるために作ったRRP_STAGEという環境変数• RRP_STAGEでDockerコンテナ起動時の設定の切り替えを⾏う
差分だけをうまく管理したいkustomize• 共通な設定を定義しつつ、overlayという機能で各環境毎の設定を上書き可能• Kubernetesのyamlのまま管理でき、Kubernetesの設定以上に覚えることがない
パッチの例recplicasの数に応じてHPAの設定やDeploymentで要求するresourceの値を変更Webサーバーのworker数はリソース状況をみてインフラ側で制御できるよう環境変数で管理
インフラ側の構成を簡単にKubernetesを最⼤限活かして置き換え• サービスディスカバリ/DNSの管理• Dockerコンテナの管理
livenessProbeアプリケーションが ⽣きているかだけの判断• Webサーバーでは処理はなく、 OKだけを返すだけのエンドポイントを⽤意• https://github.com/mirakui/rack-health
readinessProbeサーバーがリクエストを さばける状態か確認• Workerプロセスが専有されて いないかを確認するようにする• リクエストの処理をしていない idleのworker数が0になったらアクセスを受け付けられない状態とみなす• https://github.com/SpringMT/rack-readiness
Graceful shutdownlifecycleのpreStop• Gracefull shutdownを実現するために、サーバー側で採⽤しているWebサーバー(Unicorn)のshutdownの処理が⼊っている
Dockerコンテナの更新RollingUpdate• maxSurge、maxUnavailableは 反映完了するまでの時間との 兼ね合いで決める
GKEの設定
⾼可⽤性担保のためにnodeの⾃動修復マルチゾーン• master nodeのHA
権限管理ユーザーの権限管理• GCPのIAMのみで権限管理• クラスタ単位の権限管理はしていない• 検証環境と本番環境ではGCPのプロジェクトを分けて対応
限定公開クラスタを有効化Cloud SQLのPrivate IP対応が最近あり、限定公開クラスタを利⽤することに切り替え• CloudSQLProxyのSidecarコンテナを全て排除でき、Jobの終了時やGracefull shotdown時のSidecarコンテナを落とす処理が不要に• クエリダイジェスト取りやすくなった
承認済みネットワークの設定承認済みネットワーク• 社内gatewayサーバーのみからアクセスできるdeployサーバー(GCE)を⽤意し、deployサーバー上でしかkubectlを実⾏できない• 社内gatewayサーバーにttyrecが仕込んであり、監査⽤にログが残る• ただしWebコンソールでCloudShellを⽴ち上げるとkubectlで打てる• AuditLogからアクセスを監視して、承認済みネットワーク以外からのアクセスがあったらslackに通知
Preemptible VM検証環境では全てPreemptible• コストダウン• 環境が常にディスポーザブルであることの確認• GCP上に余剰インスタンがなければ⽴ち上がらなくなるので気をつけて使いましょう
Cluster Auto Scalingクラスタオートスケーリングが検証環境ではon、本番環境ではoff• スケールアップ/ダウンするときにサービス断の可能性がある• まだ解消されていないぽいです
stackdriver custom metricsidleなworker数をstackdriver custom metricsを使って監視• worker数が枯渇するとリクエストがさばけなくなる• rack-server_statusというgemでidleなworker数を取得• https://github.com/SpringMT/rack-server-status-to-sd
Kuberenetes上で Railsを動かすための⼯夫
DBスキーマの管理DBスキーマを適⽤するコマンド実⾏を⾏うPodを⽤意• スキーマ適⽤コマンドを打つためにPodを⼀つ⽤意し、そこのPod経由でコマンドを打つ• 柔軟にコマンドを打ちたい• ターミナル上で結果を確認したい• dry-run -> applyの流れ• このPodはPod単体で管理せず、Deploymentで管理
idleなworker数ベースのHPAworkerが枯渇 = サービス⽌まっている• CPUでも設定しているが、CPUが⾼くない状態でもworkerの枯渇はあり得る
ログログは標準出⼒へ• stackdriverで回収し、export• exportされた後、pub/sub -> dataflowを経由してBQに⼊れたりしています
環境構築
環境構築の現状クラスタ作成はWeb Consoleから。。。• 「既存クラスタのクローンを作成する」テンプレートが楽ちんkubectl create secretを何回か打ってkustomize build | kubectl apply -fサーバー側のセットアップ終わったらDNSに設定追加でDONE
ローカルでの開発
ローカルでKubernetesは⽴ち上げないhttps://speakerdeck.com/spring_mt/api-spec-driven-development-with-swagger
負荷試験
負荷試験簡単なシナリオを作って想定の10倍のリクエストを投げる• 簡単に下記をチェック• HPAの発動チェック• 負荷試験中の再起動実験• slow queryのチェック
Docker&Kubernetesで やっていること
Dockerイメージを Kubernetesクラスタに反映させるフロー
ここまでくれば!あとはDockerイメージをKubernetesの環境に投げ込む
Dockerイメージの反映kubectl set imageを使ってDocker imageを⼊れ替え• kubectl set image deployment• kubectl set image cronjobs --allDB schemaの適⽤• kubectl exec -it rerep-db-schema-pod -c rerep-db-schema --bundle exec rake db_schema:applyこれらをラップしたコマンド作っている
検証環境への反映ローカルから反映• 開発者がいいタイミングで反映している• CDはしていない• QA中の場合はテストチームと連携して反映している
反映されているDeploymentの状況slack上で 確認できる
本番環境検証環境と本番環境でGCPのプロジェクトが別れている• Docker registryも分かれているこの2つの環境を⾏き来できるのはDockerのイメージのみ
本番環境へのイメージを移⾏gcloudコマンドでGCPのプロジェクトを跨いで移⾏• gcloud container images add-tagあとはdeployサーバーからsandboxと同じコマンドを打つだけ• CDはまだできていない
反映後の監視パフォーマンスはstackdriver traceなどで確認エラーログはslackに流している
実績
これららの取り組みによる実績コードの差によるバグ• 1件:デバッグ機能をoffにする条件分岐構成の差によるバグ• なし
まとめ
⼀⼈でできたDocker/Kubernetesの役割を整理して導⼊したところ効率が上がり、結果、⼀⼈でもサーバー/インフラの開発/運⽤をすることができています。
https://techcon.dena.com/2019/
ありがとうございました!
ちなみに…
お話できなかったことデータの運⽤周り分析環境について
データの運⽤
ReRepでのデータの管理運営が⽤意するデータ• ミッション• 説明⽂• 画像ユーザーが作成するデータ• ミッションクリアのログ• アクティビティログ
運営が⽤意するデータReRepではサービスのコンテンツはサービス運営側が⽤意運⽤が⽤意するデータを環境に依存せず管理することで、データも含めて環境の差異をコントロール• データの⾃動⽣成や反映はエンジニア以外の⼈でもできる
もしご興味のある⽅がいらっしゃいましたら のちほどぜひお声掛けください!