TVerインフラアーキテクチャの現在地
TVerのクラウドインフラチームでインフラ周りを担当しています西尾です。 前回までは直近で行っていた施策をご紹介していましたが、今回はもっと根本的なTVerの動画配信のインフラについてどうしようとしているかについて書いていければと思っています。
現在のTVerインフラアーキテクチャについて
現在の動画配信については今までに何度かその構成について触れましたが、主にAWS上でALB・ECSを主軸としたサービスを利用して稼働しています。 この構成についてはこれから移行する次世代構成との説明をわかりやすく区別するために、ここからはTVerアーキ1.0と仮称します。

では何故今のこのTVerアーキ1.0の構成からわざわざ変えるのかというと現在の構成では幾つかの問題を抱えていました。
サービス拡大により顕在化した問題
お陰様でTVerを皆様に提供し始めて今年で10周年となりその間に視聴ユーザーも右肩上がりで増えていきました。 その中でシステム構成や運用上で幾つかの問題点が積み上がって来ました。
- Prewarmingの問題(事前暖気)
- 急激な地上波からの流入によるトラフィック増(枠切れ問題)
- リリース方式、カナリアリリースの簡略化
- 開発環境の増加による運用コスト、費用の増加問題(多面化多すぎる問題、新規環境構築の高速化)
など主に上記のような問題が出てきました。 ではこれらについては一つ一つ説明して行きます。
Prewarming(事前暖気)に関連する問題
これについては過去に取り上げています。 今年の春にLCUの一般提供を開始したタイミングでALBのPrewarming費用が急激に増えた事が発端となりました。 それまでALBのLCUを一時的に増やすことで予見される急激なトラフィック増に対応していました。 これに関しては事前暖気が必要で人的な運用コストの問題でなんとかしようと考えていましたが、なかなか手が付かない状態でしたが、費用問題が新しく出たことで本腰を入れて対応が必要になりました。 この発端により運用コストと費用を下げるためにNLBを選択する流れとなりました。 ここではその内容について詳しくは触れませんが、ALBをNLBとNginx Routerに移行することで事前暖気の運用を無くし、そのタイミングで必要な数のLCUでスケールが行われることで費用を抑えることを目的とした構成変更を行いました。 そしてこの取り組みは既存の構成から移行したアーキになりましたのでTVerアーキ1.5と呼ぶことにしました。

このTVerアーキ1.5構成は既存の問題に対しての段階的なリアーキとなり、その他課題になっていた問題をまとめて解決出来るものではありませんでした。 ただNginxを挟んだことで別ラインで行っていたTVer落ちないプロジェクトをここで取り組むことが出来ました。
TVer落ちないプロジェクト(補足)
これは事の発端が前回の話で上がりましたDBメンテナンスによりサービス断が発生するので、それに対して根本的な取り組みをしようというのがこのプロジェクトの主旨になります。 DBにアクセス出来ない場合はアプリケーション側でどうにかするのが手段としてありますが、ただ今回の場合は各アプリケーションにフォールバックの変更を入れるのでは無く、また要件として一律に対応できる部分もありましたので、このプロジェクトではDBアクセス出来ない場合は個別にアプリケーションで対応せずにインフラ側でどうにかするという選択になりました。 要件として一律に対応とありますが、これは下記のように許容出来る部分がありました。
そのため、これを実現するためにNginx + Lua + Redis構成を取ることでDBが落ちた場合でも少し古い情報ですが返す事ができるようになったのでサービスを継続的に提供出来るようになりました。 ただこの構成はまだQAテストが十分ではないので現段階ではまだ本番運用に入っていません。 しかし来年初めには本番運用を行う事ができると思いますので、皆様により安定したサービス提供を行えるようになるのではないかと期待しています。
新しいインフラアーキテクチャへの道
これまでにTVerアーキ1.0/1.5の構成について取り上げましたが、ここからは来年から順次実施されるリアーキについて話をして行きます。 これはPrewarming以外の問題点についても真剣に取り組み問題点を解決することを目指した新しいインフラ環境になりこれがTVerアーキ2.0環境と呼ばれるものになります。 TVerアーキ2.0の説明に入る前に先程の現状の問題点で取り上げていない部分について説明して行きます。
急激な地上波からの流入によるトラフィック増(枠切れ問題)
これはTVerのサービスでずっと課題となっていました問題になります。 地上波コンテンツの放送終了に伴い、TVer側に一気にユーザーが来ることで急激に負荷が上がることがあります。 今年で現在までで一番インパクトがあった枠切れは、それまでの視聴ユーザーが短時間(1分以内)に15倍ぐらいまで増えたコンテンツがありました。 現在までこのような枠切れにどのように対応しているかと言いますと、人気で枠切れの可能性があるコンテンツに関してはコンテンツの配信チームから情報をインフラ側に提供してもらい、その見積もりユーザー数から事前にインフラリソースをスケールすることで対応してきました。 これに関しては費用もかかりますが、何よりも人的な事前のスケーリング作業を行う必要があり、運用コストがかかっていました。
*事前のスケール作業の効率化は日々取り組みとしてやっており、一から全てのリソースをぽちぽち実施するということは流石にありません。またここで増やすリソースはLBのLCU以外のコンテナサービスやDBのレプリカの追加を対象としています。
そのため、このような事前作業を無くし運用負荷を下げるための施策が求められていました。
リリース方式、カナリアリリースの簡略化
大きな修正が入ったリリースを安定的に実施したいので、カナリアリリースについては弊社でも行っていました。 ただこのカナリアリリースについてはそこまで簡略化がされていなく、しかもこのリリースはALBの機能を利用して実現していましたのでNLB移行した事で部分的に出来なくなってしまいました。 そのためカナリアリリース出来るようにNginx側で実装することで一応それらしいリリースは出来るようにしましたがこの方式には問題点もありました。 それはこの方式のカナリアリリースの割合調整を行う場合は動的に実施することができず、Nginx Routerの入れ替えが必要になり、また実際リリースを行う開発者の体験が悪くこの方式はいつまでも取り入れる方式では無いと最初から分かっていました。
開発環境の増加による運用コスト、費用の増加問題(多面化多すぎる問題、新規環境構築の高速化)
複数の開発環境があることは珍しく無いと思いますが、弊社でも開発環境は複数存在しDevXX系と呼ばれて同時進行で機能開発を進めるために必須となっています。 ただこれに関しては、丸々環境が存在するので費用もかかり、まただからと言って必要な時に必要な環境を直ぐに作れるかというとそうでもなかったりします。 インフラに関してはTVerのサービスはCDKを利用しているのでコード化はしていますが、それはあくまで一つの機能の中で個別に定義している形となります。 そしてTVerのサービスに関しては複数のコンポーネントが協調して動いていますが、ただそれらはコードのレポジトリやCDKのスタックも違ったりして1箇所で集権的に管理されておらず、その上全てが自動的に協調してdeployできる状態にもなっていません。 そのため新規の環境構築するために自動化を一時期取り組んでいましたが、全ての自動化が難しく手作業も混在して環境構築に現状時間がかかっています。
*それでも昔は1週間とか1環境の追加にかかっていましたが、1.5日ぐらいに短縮はされています。
またTVerサービスをちゃんと動かすためには複数のコンポーネントが必要であり、それが問題を複雑化しています。
新環境の要件
上記のように複数の課題があり、それを踏まえてTVerアーキ2.0ではこれだけは譲れない解決すべき問題と目指すべきスケール目標を設定しました。
- LB・コンテナのスケールの短縮(1分以内) Must
- 限定的なリソースの事前増強 Must
- 多面化環境構築の高速化 Should
- 選択的なリリース方式 Should

それでは上記について一つ一つ取り上げて行きたいと思います。
LB・コンテナのスケールの短縮(1分以内)
地上波からの流入は短時間(1分以内)にそれまでの何倍もの流入があります。 この時間はとても重要でアクセス出来ないユーザーが発生しますと、せっかく続きをTVerで視聴しようとしたのに見れないと大きな失望を与えてしまいます。 そのため現在は事前に枠切れがわかるものに関しましては、リソースを事前に増やすことでその問題に対応しています。 しかし、全ての枠切れで大きなアクセスが来るかは不明確な部分もあり、リソースを適切に運用できているというと必ずしもそうではありません。 また枠切れ以外の急激なトラフィック増、例えば近年ではリアルタイムでネットでバズる事で意図しない短時間のユーザー増も考えられます。 それらに対応するために、LBは短時間でスケール出来るNLBを選び、その後ろにあるサービス群(コンテナサービス)に関しても1分以内に起動からサービス提供まで行える状態になることを譲れない要件としました。 現在のTVerアーキ1.0/1.5ではECSのfargateを利用していますが、これをEKS(Auto Mode)に移行することにしました。 当初はEKSにすることで実際この要件を満たすかどうか半信半疑でしたが、POCや負荷試験を通してバルーンPodなどと組み合わせれば1分以内に起動することが出来るということがわかり、本格採用に至りました。
TVerアーキ1.0/1.5 ECS(fargate) Taskの起動から、runningになりアプリケーションの初期化、リッスン状態になるまでにおおよそ1〜2分の時間を要する
TVerアーキ2.0 EKS(Auto Mode) Podの確保、立ち上げからのアプリケーションの初期化、リッスン状態になるまでにおおよそ50秒〜60秒に収まる
ただしこの比較はあまりフェアじゃ無いものであり、ECSであれば最近出ましたECS マネージドインスタンスで比較した方がより速い起動になると思います。 ただ今回に関しては、NLB構成にしたことでNginxと協調出来るルーティング構成がよくEKSの場合Ingress controllerでその機能を補えるということで当初のままで行くことにしました。
*ただここからその後、NGINX Ingress Controller以外の他の選択をする必要に迫られると思いませんでした。 ただ今回に関してはまだ次の移行先はまだ未定なのでNGINX Ingress Controllerのままで構成は説明して行きます。
限定的なリソースの事前増強
現在まで実施しているリソースの事前スケールが全てEKSを採用することで無くなるということは実は期待していません。 ただ事前に増やす必要がある規模は通常時のリソースの2倍にすることが最も多く、その増強運用のオペレーションが無くなるだけでかなり運用負荷が下がることを想定しています。 そのため、ものすごいアクセス増が見込まれるコンテンツに関しては心理的な安全も確保したいので手動でリソース増強を今まで通りに実施しようと思っています(この場合通常時のリソースの4〜10倍の間)。 ただこの頻度に関しては年に数回とかに収まると想定しています。
多面化環境構築の高速化
現在開発環境はECSのクラスターを含め、その開発面と同じ数のセットで倍増しています。 EKSにすることで、開発は同じEKSクラスターに共有して存在しその中でサービスとして分離された状態にすることでリソースの管理をしやすく、コストも抑えるようにします。 ただしセキュリティーやリソースの分離を鑑みて、またあまりクラスターが多すぎるとkubernetesの更新作業も面倒になるので下記のように環境を分けなるべく運用負荷を上げないようにしました。

選択的なリリース方式
カナリアリリースなどを実施する上でそれを実際に行うのは開発者側であり、開発者がいつでもリリースしやすい体験で行えるのが望ましいです。 今回のEKS環境のリソースデリバリーはArgoを採用していますので、Argo Rolloutsを利用することでカナリアリリースは実現できます。 それは現在のNginxでやっている加重方式よりはやりやすくなると期待しています。
*Argo以外の製品もありますが、Istioなどのサービスメッシュを必要とするのでまだ弊社ではそれには手を出していないので選択外となりました。
また当初はArgo Rolloutsに関してはLBなどとは連携せずに、純粋にPod数単位でユーザートラフィックを分散させようと思っています。 これは相乗りで動くことでLB IngressとArgo Rolloutsとの対応が1対1になるか不明なのもあります。
まとめ
まだこのTVerアーキ2.0構成に関しては走り始めたばかりです。 開発環境でECSからEKSにサービスを移して機能試験や負荷試験を実施した段階なので、まだまだやることは山積しています。 その上Ingressの移行問題も出てきたのでやることはさらに増えてはいますし、またこのリアーキに関してはコンテナオーケストレーションなどの製品の選定で終わるものでもなく更に裏にあるDBなども対象に含んでいます。 ではそれでも前に進んでやるかと問われますと、増え続けるユーザーに安定的にサービスを提供し、落ちないTVerを目指すために必要な過程だと捉えています。