AWS“から”オンプレミス“に”

松浦庸介氏(以下、松浦):SRE部の松浦から「WebRTCの配信システムをAWSからオンプレミスに切り替えている話」ということで発表したいと思います。

まず、簡単に自己紹介をしたいと思います。2020年の5月に入社して、それ以来WebRTCのリアルタイム配信システムの開発や運用を担当している、松浦と言います。本日はよろしくお願いします。

まずこのタイトル、みなさん「AWS“から”オンプレミス“に”」というところ、気になってる方がいるんじゃないかと思います。

これ「AWS“に”オンプレミス“から”じゃないか」と思っている方もいるかもしれませんが、実は本当に「AWS“から”オンプレミス“に”」移行している話になります。その経緯などを含め、説明していきたいと思います。

WebRTC配信システムの特徴

まず、WebRTC配信システムの特徴から説明したいと思います。WebRTCの配信システムは、送信者から送られてくるストリームをリアルタイムで配信するもので、低遅延性を求められます。そしてもう1つ、送信者と受信者の関係が1対nになるため、受信トラフィックよりも送信トラフィックのほうが多い特徴があります。

そして、1送信者あたりの受信者は、多くても10人未満。まれに多いこともありますがが、基本的には10人未満と非常に少ないため、CDNを利用して分散させることも難しい特徴があります。

もともと、このシステム自体はFlashを使って配信していました。しかし、ご存知の方も多いと思いますが、2020年に完全終了しました。そこで、WebRTCベースの配信システムへ刷新するということがありました。

開発当初として懸念がありました。それは、WebRTCという未知の領域を扱うため、開発がどうしても手探りになってしまうところです。どういうコーデックを使うのか、どんなソフトを使うのか、サーバーのスペックどのくらいか。非常に不確実性が高く、こういったケースではオンプレは使いづらく、EC2を使って起動しています。

そのサーバーが現在どうなっているかというと、2021年7月現在で、通常用途のサーバーがc5.12xlargeが8台、ピークで1台あたり750Mbpsぐらいのトラフィックが出るものになってます。

詳しい方だと「ストリーム配信だったらc5aのほうがいいんじゃないの?」と思った方もいるかもしれませんが、実はこのソフトウェア、実はEPYC系ではぜんぜんパフォーマンスが出ないものだったので、Intel CPUを使っています。

導入が進むにつれて増えるコストをできれば削減したい

2020年の4月ぐらいから導入を始めました。そして12月ぐらいにかけて、右肩上がりにコストが増えています。導入が進むにつれて、コストが増えてくのは当然ではあります。

とはいえ、なんとかしてコストは削減したいという話があり、Cost Explorerを使って調べてみました。

前のスライドで、2020年12月から1月にかけて、実はガクッと下がっています。なぜかというと、サーバーをCentOS7からCentOS8に変えた影響によるものです。

これはソフトウェアの開発元も気がつかなかった仕様で、CentOS7では非常にパフォーマンスが劣化することがあり、OSを切り替えています。この時の調査した話とかも、それはそれとしておもしろい話ではありますが、今回は時間の関係上省略します。

では、そのコストはCost Explorerで分析するとどうなっているのかが、スライドのグラフです。下の青い部分がデータの転送量で、上の赤い部分がその他EC2やS3などのコストになります。

実際に見てみると、通信費用が75パーセントも占めていたことがわかりました。転送料の単価は段階的に安くなって、150TB以上では最も安くなりますが、月間の転送量はそれをはるかに超える量あったことが原因でした。

一応EC2の料金表に、「1ヶ月の転送量500TB超える人はお問い合わせください」とあるので、非常に多い場合は交渉もできるようではありますが、我々はそういう手をとりませんでした。

さて、このグラフをご覧ください。2019年とちょっと古いですが。

オンプレネットワークの活用。これは何かというと、DMMは対外で400Gbpsのネットワークを保有しているため、非常に契約帯域も大きいと。それによって、bpsあたりの単価も相当安くなっています。このリソースをぜひ使ってみたいとなりました。

ここで「DMMは、クラウドに全部寄せる方針じゃないの?」と思った方もいるかもしれませんが、実はそんなことはありません。オンプレのほうがよければ、積極的に使っていく方針をとってます。

移行先のオンプレサーバーの概要と費用試算

移行先のオンプレサーバーの概要です。DMMでは、VMware Integrated OpenStack + NSX-Tというプライベートクラウド基盤を自社に持ってます。

今回はベアメタルで払い出してもらうということもできましたが、手っ取り早いのでプライベートクラウド基盤を使っています。スペックも、ソケットあたりのコア数が若干少ないという違いはありますが、EC2とあまり変わらないスペックのサーバーです。

費用試算をしてみると、(スライドを指して)上がオンプレ、下がAWSの費用となっています。これで見るともう一目瞭然です。オンプレのほうがずっと安くなっています。

費用試算をしたところ、サーバーのコストはオンプレのほうが若干高かったということがありました。

これがなぜかというと、Savings Planを使っているというのもあるし、オンプレのサーバーがまだまだどのくらいになるかわからないので、かなり構成見積もりを保守的にしていることが原因でした。とはいえ、稼働が安定してくれば、まだまだ下げられる余地はあるかなと見ています。

一方で、ネットワークコストはオンプレのほうが95パーセント安い。合計すると、半額以下になることになります。コストが半額になのなら移行するしかありませんね、というかたちになりました。

とはいえ、もちろんクラウドが悪いというわけではありません。クラウドで調達すると、サーバーの調達が非常に早いです。そしてもう1つ、物理機材の在庫はあまり気にしなくても、APIで追加削除は簡単です。

このシステムの稼働当初はスペックの想定が難しかったため、EC2のメリットも大きかったですが、安定してくると、このメリットは逆にあまり活かせなくなってきた経緯があります。

アプリの改修方法

では、実際にアプリをどう改修するのか、という話をしていきたいと思います。

まず、切り替えのハードルとして、配信サーバーと配信サーバーが使うAPIが、同じVPCにあることを前提としていました。まず、配信サーバーがコールするAPIがInternal ALB配下にあり、配信サーバーの管理用のAPIが、プライベートIPアドレス経由でリクエストされてるという仕様です。

APIという単語が2種類出てきてちょっと紛らわしいですが、いったん整理していきたいと思います。単にAPIと言った場合は、配信サーバーが認証の時に使ったりする、WebフックのAPI。管理APIと言ったら、配信ソフトに実装されている、配信の管理するためのコントロールAPIと認識してもらえればと思います。

(スライドを指して)これが、現在の通信構成です。通信を完全にVPC内で完結することが前提となっていて、1つのVPC内にWebRTCサーバーとECSのコンテナがあるかたちになります。

このあとオンプレ側に配信サーバーを構築するには、2種類構成が考えられます。1つがSite-to-Site VPNとかDirect Connectを使って、VPC自体を拡張する方法。もう1つは、配信サーバーとAPIの通信をグローバルにするという方法です。今回は、Bのグローバルにするほうを選んでいます。これは、構成がシンプルになること、機材の冗長化などの心配がいらないことがメリットです。

そしてもう1つ、これは将来的な話にはなりますが、DataPacketのような、ネットワークが安いベアメタルホスティングなどを導入したくなっても、使いやすいのがメリットとして考えられます。

そして今回の改修のポイントですが、まずAPIをInternal ALBからInternet ALBに変更し、管理用のAPIを前段のnginxでHTTPS終端させて、インターネットからつなげるようにすることです。全サーバーで一気に切り替えるのは難しいため、新旧の通信が混在する時期があるというポイントになります。

これが切り替え中の構成です。左のほうがデータセンター、真ん中が先ほどのVPCになります。一部のサーバーはデータセンターにあり、一部のサーバーはVPCにあります。

この間は、VPC内のWebRTCサーバー、Internal ALBにローカルのドメインで接続し、データセンターにあるものは、グローバルの、普通のFQDNを使っています。この場合、ECSのほうからどちらかのAPIを叩くかによって、首振りが必要になります。

(スライドを指して)最終形としてはこんな感じです。VPCの中にはWebRTCサーバーがなくなり、データセンターにすべて移行します。こうなるとInternal ALBはもういらなくなり、全部PublicなALBを使って通信するかたちになります。

配信サーバーの管理用APIの話ですが、こちらはすでに配信サーバーがTCPの443ポートでWebSocket、TURN-TCP、TURN-TLSを行っています。管理APIには認証がないので、nginxでIPアドレス制限をかけてあげる必要があります。

WebSocketなどの一般公開される通信はもちろん、IPアドレス制限はできないので、管理APIだけIPアドレス制限をかけてあげる必要があります。ただ、TURNと管理APIのパスが同じで管理APIだけIPアドレス制限をかけられなかったので、今回は管理APIのポートを違うものにしています。

切り替え中の課題の解決法

切り替え期間中、新旧混在する期間中特有の課題して、APIと管理APIが、ローカル経由とグローバル経由のものが混在することです。この時、配信サーバーを管理するためのデータベースに登録されてるIPアドレスが、プライベートかどうかで、管理用APIのURLを変える実装をとっています。

具体的には、(スライドの)上にあるようにプライベートIPアドレスが入ってる場合は、プライベートIPアドレスをURLに指定し、グローバルIPアドレスが入ってる場合は、そのIPアドレスにひもづくFQDNに対してリクエストするかたちになっています。

具体的な例を説明したいと思います。データベースには、サーバー1とサーバー2が登録されていて、それぞれIPアドレス、FQDNが登録されています。1のほうは、プライベートIPアドレス、2のほうは、グローバルIPアドレスが登録されているかたちです。

1のほうは、プライベートIPアドレスが登録されているので、管理用 APIのURLは10の20のなんたらというかたちで接続し、2のほうはグローバルIPアドレスが想定されているので、APIのURLはFQDNで指定するかたちで通信します。

話は変わりますが、IPアドレスがプライベートIPアドレスかどうか判定するのは、けっこう面倒くさいという課題があります。特にクラスBとかは、若干マッチングを工夫しないとできないというのがあります。今回、我々はロングIPアドレスという形式を使っています。

スライド32

ロングIPアドレスについてと切り替えの予定

ここはもう余談にはなりますが、IPアドレスは普通はドットで区切った形式を使うのが一般的ですが、各オクテットを256進数とみなして10進変換すると、ロングIPアドレスという形式になります。

これを使うメリットとしては、CIDRの判定が整数同士の比較演算できることになります。さらに豆知識的にはなりますが、MySQLのserver-idも実は32bit符号なし整数なので、ロングIPアドレスをそのまま使うと設定の手間が省けて非常に便利です。

PHPで実装してたので、こんな感じのコードで判定しています。真ん中のほうにある、if $iplong >=のところで、一番上からクラスA、クラスB、クラスCのプライベートIPアドレスの判定する構造になっています。

切り替えはどうなってますか、というところですが、現在、APIの改修を今絶賛QAテストを行っているところで、8月の頭からは切り替えが始められればいいなと思っています。

今後もオンプレとクラウドを適材適所で使い分けする

では最後にまとめとなります。我々DMMはオンプレのリソースも潤沢なので、今後も適材適所に使い分けていきたいと思っています。特に、リソースが安定していて通信が多いシステムは、オンプレを使うメリットがあるので、オンプレを使っていきます。

一方で、APIサーバーのように起動停止がしやすいシステムなどは、積極的にクラウド、基本的にAPIサーバーとかであれば、コンテナに寄せていくことをメインに考えています。

このように、オンプレとクラウドをうまく使い分けながら、サービスを提供していけるように努めていきたいと考えてます。

私の発表は以上となります。ありがとうございました。