- バックエンドエンジニア
- アナリスト
- 内部統制(J-SOX)
- Other occupations (8)
- Development
- Business
- Other
はじめに
こんにちは、技術本部ML・データ部MLOpsブロックの鹿山(@Ash_Kayamin)です。先日、20個の開発環境APIを用意し、各APIをリクエストに応じて動的に起動できる仕組みをKnative Servingを用いて構築しました。
この記事ではKnative Servingを利用した背景と、利用方法、はまりどころ、利用によって得られたコスト削減効果についてご紹介します。なお、今回はKubernetesクラスタのバージョンとの互換性の都合でKnativev1.3.1を利用しました。2022/9現在の最新バージョンはv1.7.1になりますのでご注意ください。
課題:20個の異なる開発環境APIを低コストで提供したい
ZOZOTOWNには20個の開発環境が存在し、それぞれが独立して開発できるように、20環境分の独立したAPIを提供する必要がありました。MLOpsブロックがGKEクラスタ上で提供するAPIも例外ではありません。しかしながら、単純に20環境を常に起動しておくとノードの費用が嵩んでしまいます。
解決策:Knative Servingを用いて、リクエストに応じて動的にAPIサーバーを起動する仕組みを導入する
今回の開発対象は開発環境のAPIであり、高いサービスレベルは求められていません。初回リクエストの処理に時間がかかっても問題なく、リクエスト数も少ないです。また、APIサーバーはコンテナ化されており、GKEクラスタ上で動いています。これらの前提から、コンテナ化されたAPIサーバーをリクエストに応じて動的に起動する仕組みを導入して、リクエストがない時のAPIサーバー費用を削減することを検討しました。
Google Cloud上でコンテナ化したAPIサーバーを動的に起動し、APIを提供する方法には、大きく分けてCloud Run、Cloud Run For Anthos、GKEクラスタ上でKnative Servingを動かすの3通りがあります。次に、それぞれの概要・メリット・デメリットについてご説明します。
Google Cloud上でAPIコンテナを動的に起動する方法の比較
Cloud Run
Google Cloudが提供するマネージドなコンテナサービスです。後述するKnative Servingをベースに作られています。用意したエンドポイントへのリクエストに応じて事前に定義したDocker ImageからAPIサーバーを起動してリクエストを処理し、レスポンスを返すことができます。
メリット
- Docker Imageを用意し、起動するAPIの定義・アクセス設定等を行えば即座に利用できる
- HTTPリクエスト以外にもさまざまなイベントをトリガーにコンテナを起動できる
- ゾーン障害への冗長性がデフォルトで備わっている
- コンテナ、Knative Serving関連のログ、メトリクスをCloud Logging、Cloud Monitoringで簡単に取得できる
- TerraformでCloud Runのインスタンスを定義・デプロイできる
デメリット
- 既存のKubernetesマニフェストからTerraform定義を生成・更新しなくてはいけない
- 既存のGKEクラスタとはネットワーク構成が異なり、Shared VPCとのIngress、Egress通信を可能にするための構成が追加で必要となり複雑
Cloud Run For Anthos
Google Cloudが提供するマネージドなKnativeサービスです。Anthosを利用しているGKEクラスタ上にマネージド、かつサポート付きのKnativeを構築し、Knativeが提供する機能を全て利用可能です1。
メリット
- GKEクラスタ上で他のAPIと同じように扱える
Kubernetesマニフェストを用いて管理できる
同じコマンドラインツールを用いて、確認・操作ができる
既存のAPIと同じネットワーク・権限を利用できる
- Knative周りの挙動・エラーについてGoogle Cloudからのサポートを受けられる
デメリット
- 有料かつクラスタ設定の変更が必要なAnthosの利用が必須
- Anthos Service Mesh(マネージドなIstio)の導入が必要
Knative Serving
Kubernetesオペレーターの一種であるKnativeの一部分であるKnative ServingをGKEクラスタ上で動かします。Knative Servingの機能を用いて、用意したエンドポイントへのリクエストに応じて事前に作成したDocker ImageからAPIサーバーを起動してリクエストを処理し、レスポンスを返します。
メリット
- GKEクラスタ上で他のAPIと同じように扱える
Kubernetesマニフェストを用いて管理できる
同じコマンドラインツールを用いて、確認・操作ができる
既存のAPIと同じネットワーク・権限を利用できる
- Knative ServiceのNetwork layerを自由に選択できる(Istio、Contour、Kourier)
デメリット
- Knative Servingのインストール・運用・バージョンアップを自前で行わなくてはいけない
- Knative Servingのメトリクスを取得するためには、追加のセットアップをしてCloud Monitoringにメトリクスを送る等する必要がある
今回は次の理由からGKEクラスタ上でKnative Servingを動かす方針としました。
- 既存APIと同じGKEクラスタ上で動かすことによって、ネットワークや権限周りの構成、Kubernetesマニフェストを共通化して認知負荷を下げたい
=> Knative Serving,Cloud Run for Anthosの優先度が上がる
- 有料かつクラスタ設定の変更が必要なAnthosや、導入・運用コストが高いIstioを利用したい強い理由がない
=> Cloud Run for Anthosの優先度は下がる
- 提供する開発環境APIでは運用初期からの高いサービスレベルは求められていない
=> Cloud Run、Cloud Run for Anthosの高いサービスレベルは不要で、Knative Serving自前運用のリスクは許容できる
Knative Servingとは
Knavite ServingはKnativeを構成するコンポーネントの1つです。KnativeはKubernetes上でのServerless、 Event drivenなアプリケーションの構築をサポートするKubernetesオペレーターです。KnativeはServing、Eventingの2つのコンポーネントから構成されます。
ServingはKuberentes上でのServerless Containerの実現をサポートします。Serverless Containerとは何らかのイベント(HTTPリクエスト等)に応じてコンテナ化されたアプリケーションを0台の状態から起動、必要に応じて複数台にスケールし、処理を行う環境のことを指します。
ServingはServerless Container実現に必要なネットワーク周りの設定や処理、0台からのコンテナのオートスケール、コンテナのバージョン管理周りの処理を自動化してくれます。これによってユーザーは簡単にKubernetes上にServerless Containerを利用したサービスを実現できます。
EventingはKubernetes上でのHTTPリクエストを用いたイベントのPub/Subの実現をサポートします。Serving、Eventingの具体的な活用例については公式に構成図付きのサンプルが用意されているのでそちらをご覧ください。
今回、HTTPリクエストを受けて、リクエストのホスト名に応じたAPIサーバーを0台の状態から起動、または複数台にスケールし、処理を行ってレスポンスを返す仕組みを実現するために、Knative Servingを利用しました。
以下の図は、Knative Servingを用いて実現した環境を図解したものです。
Knative Servingの主要なコンポーネント
Knative Servingには代表的なカスタムリソースとしてService・Route・Configuration・Revision・Ingressが存在します。それぞれの役割を以下に示します。Serviceリソースを作成すると、その他のリソースはKnative Servingのカスタムコントローラーによって自動的に生成されます。Serviceリソースを通じて各種機能を利用するのが基本ですが、個別にConfiguration、 Route等を定義して挙動を制御することも可能です。
続きはこちら