守るインフラの課題は「運営サービスの可用性の向上」

高橋拓也氏:『ペパボが求める「守って攻める」インフラとは?』という題名で発表します。今回のアジェンダはこのようになっています。

まずは自己紹介させてください。僕は高橋拓也と申します。インフラエンジニアで、技術部技術基盤チームに所属しています。自宅にはサーバーをたくさん置いていて、こんな感じです。

さっそく守るインフラについて話していきたいと思います。解決したい課題は「運営サービスの可用性をさらに上げていきたい」というものです。今のGMOペパボのサービスインフラは、だいたいこんな感じで積まれているものが多いです。黄色の部分は事業部のエンジニアが運用していて、赤い部分は技術部やプラットフォームグループなどの横断チームが運用しています。

それぞれのレイヤーで、さまざまな活動を行って可用性を高く保とうとがんばっています。ただここの赤い部分、「OpenStack」「Nyah」の部分が何らかの障害によって使用できなくなった場合、黄色の部分にその影響が波及してネットワーク通信ができなくなることが稀にあります。

その場合、赤い部分の人たちがトラブルシューティングや復旧作業をやって、黄色い部分の人たちは為す術がなく祈るしかない状態になります。プラットフォーム起因による大規模障害時での「プラットフォームの復旧を祈るしかない」という状態をなくし、最悪の状況下でもサービス提供を継続できる状態を作るのが「守るインフラ」の目的です。

では、どういったことを定義しましょうかというところで、「ユーザーのアクセスに対し、期待される水準で正常に返答できる環境を提供することに対して商業的に合理的な最大限の努力をするインフラ」と定義づけました。この「商業的に合理的な最大限の努力」は「AWS」で使われている言葉で、僕の好きな言葉です。サービス品質向上幅と消費コストは正比例しない関係です。無限にコストをかけたらサービス品質も無限に向上するかといったら、そういうわけではないですし、コストをかけられる総量も決まっています。

また、これはあまり語られないことだと思うんですが、品質向上は一定ラインで頭打ちすることがあります。それはアーキテクチャのボトルネックだったり、ネットワーク帯域のボトルネックだったり、いろいろな問題が作用して発生します。極端な例としては、このように日本にのみDC(データセンター)がある場合、日本が沈没してしまったらサービスも終わってしまいます。

ハイブリッドクラウド利用による解決と新たな課題

これを踏まえてやるべきことは、この2つだと考えます。「コスト対品質向上効率を左の図のように最大化する」「ボトルネックを排除し、右の図のように品質の上限を常に上げ続ける」です。

守るインフラを実現するために、下のスライドのような状態になってしまっているとお話ししましたが、パブリッククラウドを併用してそれを解決しようと今がんばっています。これはハイブリッドクラウドと呼ばれる構成です。

「障害点が地理的にも異なるサイトに存在するため、完全に分割されること」「パブリッククラウドにはプライベートクラウドが持ちえない利用したい機能が多くあること」そして「商用サービスである以上、障害に強い面があること」。この3つの観点により、ハイブリッドクラウドを利用するのがよいのではないかと思っています。

AWSとプライベートクラウドを専用線でつなぎました。これは、任意のテナントとVPCがL3で接続可能になったということです。プライベートクラウドはAWSの豊富な機能と可用性を手に入れました! バンザーイ! やったー! パチパチ。

しかし、立ちはだかる大きな壁がありました。AWSをなかなか活用できません。既存のサービスにAWSをうまく組み込むのがなかなかどうして難しいのでした。イニシャルの学習コストなど、さまざまなコストの面であったり、サービスのアーキテクチャの面であったり、いろいろな問題がありました。新規プロジェクトはAWSを活用したものも多いんですが、既存の環境にはこういった課題があります。

それらをエンジニアリングで解決していきます。先ほどの図です。このようにパブリッククラウドを一部分だけ活用します。既存の構成をガラッと変えなくても、一部だけ適用できる範囲はあります。可用性を大幅に向上できないとしても、プライベートクラウドの絡むリスクを少しでも分散できるのなら利用する価値はあると思います。今回は、プライベートクラウドを拡張するモジュールとしてAWSを利用できる実装を行いました。

「カラーミーショップ」導入事例

事例を紹介をします。LB(ロードバランサ)をAWSで使いました。プライベートクラウドではソフトウェアロードバランサを提供しています。HAプロキシでHA構成が組まれたもので、シュッと簡単に作れるL4ロードバランサです。概ね利用に問題はなく正常に動くんですが、稀に死んでしまうことがあります。復旧まで時間がかかるケースも多く、サービスがそのLBに依存している場合、サービスが停止してしまうことが稀に発生します。

LB自体もソフトウェアで構成されているため、継続的にアップデートする必要があります。脆弱性対応や機能追加やバグ修正など、バージョンアップがけっこう大変だったりもします。

これらの背景を踏まえ、「Octavia」(OpenStack で提供されるLBaaS(LB as a Service))とは別の仕組みを利用してリスク分散を図りたいという思いから「Elastic Load Balancer」を使うことになりました。詳細は割愛するんですが、L4ロードバランサのネットワークロードバランサ(NLB)と、L7ロードバランサのアプリケーションロードバランサ(ALB)の2種類が存在します。今回はL4LBの代替なのでNLBを利用しました。

カラーミーショップでの導入事例です。カラーミーショップはネットショップ作成サービスで、ECを運用するための各種機能を提供しています。。パソコンに詳しくない方でも、自社ECサイトを運営できます。

簡単な図はこうなっています。LBが受けてその先のSSL終端プロキシがいったん受けて、後ろにある各サービスに対してリクエストを送るという構成です。この構成の場合、LBが利用不能になるとサービス全体が利用できなくなります。この状態をこうすることで解決します。この場合、LBが利用不能でもNLBを使うことでサービスを継続できます。

NLBやDXが利用不能な場合でも、Octaviaを使うことでサービスが継続できます。Route53によるヘルスチェックと、ラウンドロビンによって定常時は10パーセントだけNLBにリクエストが誘導されます。これはコスト削減の一環です。この環境を本番環境に導入しました。ショップ閲覧機能の入り口と、ショップオーナーが使う管理画面の入り口の2ヶ所に適用して、現在も安定して稼働しています。

NLBの構築と運用方法

NLBの構築と運用の方法について説明します。今でも大変なのに、また新しく作るのはもっと大変なので、構築と運用コストを限りなくゼロにしたい思いました。そこで、「Kubernetes Custom Controller」を利用して構築運用自動化APIを作りました。Kubernetes Custom Controllerは「Kubernetes」に任意の動作を拡張できる機能です。

NLBの構築フローを説明します。Octavia LBを特定するIdentifierである、uuidをパラメータに構築をトリガーして、Octavia APIにLBの構成情報を問い合わせします。NLB構築システムが、LBのリスナー、メンバー、インスタンスのIPなどの情報を手に入れたあと、それらの情報をもみくちゃにして、NLBの定義情報を作成してAWSにAPIを叩いてNLBを構築します。

次は、NLBのターゲットの変更フローを説明します。Octaviaにメンバーが追加されました。終端プロキシがたくさん増えます。NLB構築システムは一定間隔でAPIに構成情報を問い合わせているので、返却された構成情報に差分が生じることがあります。その差分を基にNLBのターゲットを追加する動きを行います。ここでのポイントは、サービス運用者がAWSを一切触らずにNLBの運用が完結するということです。

自動化システムの導入によって、NLB構築の際に必要な作業が大幅に少なくなり、NLBの運用がゼロになりました。ゼロになったんです。少ない手順でAWSを活用した可用性向上が可能になりました。バンザイ。

プライベートクラウド「Nyah」の未来

守るインフラがこれからどうなっていくのかを説明します。僕が作った言葉ですが、Nyahは「ハイブリッドクラウドプラットフォーム」になっていきます。今までNyahは、あくまでプライベートクラウドでした。それが今後はパブリッククラウドを透過的に利用できるプラットフォームになっていきます。

例えば以下のような体験を提供しようと思っています。OctaviaでLBを作ったら、いつの間にNLBができるとか、NKEでKubernetesクラスタを作ったら、いつの間にかEKSができるとか、プラットフォーム障害が起こってもユーザーは何も感じることなく、サービス障害が起こらないとか、そういった体験を提供しようと考えています。

守るインフラのまとめです。手詰まりの状態を作らないように、AWSのハイブリッドクラウドを使って、現在プラットフォームを進化させています。長年運用されているシステムも見捨てずに、恩恵を受けられる構成を目指しています。LBを第一弾として適用をしました。今後はさらに境界をなくすことに尽力します。ということで守るインフラはおしまいです。

攻めるインフラの課題は「可用性を保った開発サイクルの高速化」

次は、攻めるインフラです。「可用性を維持したまま開発サイクルを爆速にしていきたい」という課題があります。どういうことかというと、「たぶん動くと思うからリリースしようぜ」というものをリリースできるようにするということです。

ステージングで確認して、本番に出すのはよくやると思うんですが、ステージングでうまくいっても本番でうまくいく保証はありません。「とりあえず本番に出してみる」をできる限りプラットフォームでサポートしつつ、可能にするのを目指します。

「ローリングリリース」と「本番環境の家畜化」で可用性を目指す

どうすればいいかというところで、「ローリングリリース」と「本番環境の家畜化」を提案します。ローリングリリースはみなさん身に覚えがあると思います。本番環境の家畜化はどういうことかというと、本番として動作するAPI、フロントエンド、LBなどの環境一式を容易に構築できるようにするということです。

たくさん本番環境を作って、その内の1つをピックアップして、動作検証して、そしてリリースというサイクルにします。障害発生時は他の本番環境にロールバックできたり、複数の本番環境を同時にサービスインしてロードバランスできたりします。

利点は、ロールバックが速いことです。ロールバックするときにバチンと向き先を切り替えるだけなので、手法次第では数秒でロールバックが可能です。さらにサービス成長に寄与できます。ABテストしたり、カナリアリリースしたり、いろいろな手法を取り入れることが可能になります。ローリングリリースもこの家畜化で実現できると考えます。

欠点ですが、管理が複雑になります。1つの本番環境を運用するのも大変なので、その本番環境をたくさん運用できるのかといったら、おそらく人間じゃ無理です。なので人手を必要とせず、大量の本番環境をうまく管理する仕組みが絶対に必要だと考えます。そのためにはオーケストレーションプラットフォームが必要です。僕たちの代わりに面倒を見てくれる人が必要です。ここでは、マネージドサービスが充実していて社内外実績も豊富なKubernetesが最適だと思っています。

「Kubernetes」を本番環境の家畜化に活用する

Kubernetesを活用した本番環境の家畜化について説明します。このようにクラウドを跨いだ複数クラスタで、透過的に同一環境が動作するケースを考えてみます。この色の付いたボックスがユーザーのリクエストだと思ってください。Prodの上で冗長が行われています。

真ん中のクラスタが壊れたときは、上に乗っているProdは動けなくなり、紫のユーザーは残念ながら障害の影響を受けてしまいます。しかし他のユーザーは冗長されているので、アクセスできます。その上のものを何とかしてマイグレーションすることによって、利用するProdを変更して復旧させることができます。

アプリケーション更新は、指定した法則に則って更新するProdを選択する方法を取ります。例えば、まずはテストのProdで、そのあと影響の少ない順にアップデートするという法則が決定されると、テスト用Prodで更新を実行したあとに動作検証を行い、どんどん更新していきます。最終的には全部の更新が終わります。

Kubernetesのクラスタはどうやってアップグレードするのかというと、まずすべてのリクエストをどこかのProdにエビクションしてから、クラスタをアップグレードします。こうすることで、ユーザーに影響なくクラスタがアップグレードできます。最後にリクエストを再配置することで、正常に再稼働できます。

実現するうえで考えるべき3つのこと

これをどうやって実現するのかというところで、まずはこの3つを考えなきゃいけないと思っています。「Prodのライフサイクル管理とクラスタのライフサイクル管理」「ユーザーのリクエストのスケジューリング」「ハンドリング」の3点です。ライフサイクル管理には「Custom Controller」が最適だと思っているので、Custom Controllerを利用して実装を開始しました。

Prodの管理だけは現在、Custom Controllerで実装できています。kubectl create -f 〇〇.yamlなど、KubernetesのAPIを利用して作成できます。まだ実装できていないものはたくさんありますが、アプリケーションの更新もそのコントローラが自動で行っていて、人間が行わない環境ができています。

Kubernetesクラスタの管理は現在考え中ですが、可能ならすべてリソースで管理できる状態にしたいと思っています。行き着く先には、クラスタ自体の家畜化もあると思っています。Workload ClusterとControl Plane Clusterに分けて、1対Nの関係でクラスタをマルチで配置します。

Control Plane ClusterがWorkload Clusterのライフサイクルを管理することで、Workload Clusterをイミュータブルに管理できると思っています。これは今考え中です。ユーザーハンドリングの部分は、今のところあまりピンと来るアイデアがありません。今は神が降りてくるのを待っている感じです。

攻めるインフラと守るインフラで相乗効果を生み出す

攻めるインフラのまとめです。今後は、本番環境の家畜化で攻めていきます。ユーザー影響を最小化した開発サイクルを実現します。現在、人間のオペレーションをできる限り排除する実装をしています。攻めるインフラが守るインフラの実現にもつながっています。相乗効果を生み出してやっていきます。

守って攻めるインフラのまとめです。可能性をより高めるために試行錯誤を繰り返しています。現在はハイブリッドクラウド活用により、可用性を高める解決方法を模索しています。同時に事業の成長を加速できるインフラを目指しています。これはKubernetesとCustom Controllerを用いて解決しようと考えています。一緒にインフラを守って攻める仲間を募集中です。ご清聴ありがとうございました。