インフラ部のyoshiminとsue445です。
内部向けのイベントとしてパフォーマンスチューニングコンテストをGCPで構築し開催したので、そのときに得られた知見を紹介します。
イベントの概要について
あらかじめ用意されたWebサイトのコードなどを変更してパフォーマンスチューニングをするといった内容で、競技者1チームあたり3台のインスタンスが提供される(うち1台はスペックが異なる)といった内容でした。
参加チームは13チームの約30名でした。
CDK for Terraformについて
社内でクラウドのプロジェクトを管理する際は原則としてはTerraformで管理するようにしているのですが、今回のプロジェクトについては長期的に管理していく目的ではないので実験的にCDK for Terraform (以下CDKTF) を採用しました。
言語についてはGoなどでも軽く検証をしてみたのですが少し触ってみてTypeScriptでやるのが一番ハマりにくそうだったのでTypeScriptで書くことにしました。
CDKTFの良かった点
エディタなどによる自動補完などが効き、似たようなリソースを複数作るときにも通常のFor文などで作れるのが便利でした。
またGCEのインスタンスの公開鍵のインポート処理をTypeScriptとして自然に組みこめたのは便利でした。
競技環境
PackerとAnsibleでGCEのイメージを作成し、そのイメージからチームごとに必要な台数とスペックで起動しました。
イメージの中の状態をテストするには作ったイメージからVMを起動する必要があって大変だったのでPacker実行時にServerspecで簡単なテストを実行しています。
余談ですが https://github.com/unifio/packer-provisioner-serverspec (Packer実行時にServerspecでテストをするためのプラグイン)がPacker 1.8に対応していなかったのでパッチを投げています。
各参加者毎に自分のチームのVMだけにsshできるようにする制御はGCEのインスタンスメタデータを利用しています。
VM に SSH 認証鍵を追加する | Compute Engine ドキュメント | Google Cloud
事前に参加者からGitHubのアカウントを回収しておいて、GitHubに登録されている公開鍵を各チームのVMのインスタンスメタデータに登録して環境構築を行いました。
ポータルサイト
ポータルサイトはCloudRunで構築することで競技中でアクセスが多く発生するときだけ自動的にスケールするように構築することができました。
DBとしてはCloudSQL(MySQL) で動かしましたが、今回は参加者は30名程度だったため、運営前日にdb-custom-2-3840
にしておくだけで十分でした。
ベンチマーカー
競技環境へ負荷をかけるワークロードにはGKEを採用しました。GKE Autopilotを使うかどうか悩んだのですが、Google CloudのSAの方に確認したところAutopilot環境ではノードのサイズなどが自動的に決まってしまうので、ベンチマーカーをなるべく公平な環境で実行させるために通常のGKE環境で n2-standard-4
のノードで1ノード内に1Podずつ立つような構成で構築しました。競技にかかる料金をできる限り抑えるため、競技開始1時間前にノードプールをpreemptibleから通常のノードにし、競技終了後はまたpreemptibleにしました。
最初はCloud NATを配置し限定公開クラスタでやっていたのですが、準備中にベンチマークを試してみたところうまく負荷がかけきれない問題があったため、パブリッククラスタとして構成しなおしました。
クラスタへのmanifestの適用については実験的に Cloud Deploy を採用しました。ArgoCDなどを構築するなどに比べると楽でしたが、大規模なマニフェストを管理するわけでもなくデプロイフローも複雑なものではなかったのでGitlab CIでkustomizeなどを実行するなどでもシンプルでよかった気はしました。
ベンチマーカーについては当初Podが使用しているCPU使用率でスケールできるだろうという想定だったのですが、実際に環境ができて実験していると思ったよりベンチマークをかけたときにCPUを使いきれないということがわかったので、実行待ちのキュー情報をクラウドモニタリングのカスタム指標に登録し、それを使ってPod数を変更するようにしました。
--- apiVersion: autoscaling/v2 kind: HorizontalPodAutoscaler metadata: name: bench-hpa spec: scaleTargetRef: apiVersion: apps/v1 kind: Deployment name: bench-deployment minReplicas: 2 maxReplicas: 13 metrics: - type: External external: metric: name: custom.googleapis.com|benchmark_queue_waiting target: type: AverageValue averageValue: 1
この仕組みを実装しておいたことでイベント当日の運用ではminReplicasを一度手動調整するぐらいですみました。
まとめ
今回のイベントでは、かなりの台数を構築することになるので前日準備は大変だと考えていましたが、実際には前日の午前中に準備ができてしまい、スムーズにイベントを開催することができました。
当日の運営についても予期しないオペレーションを多少することにはなりましたが、大きなトラブルなく参加者に楽しんでもらうことができました。
インフラ部では、Google Cloudを使いこなしてこのようなイベントのための構成を考えるエンジニアを募集しています。