LivekitをGKEで動かす
2024-09-21
#目次
- はじめに
- Livekitとは
- システム構成
- 準備
- ネットワークとファイアウォールの設定
- GKEのクラスタを作成
- Helm Chartで各種コンポーネントのデプロイ
- Livekitのサンプルアプリを動かす
- 参考リンク
- まとめ
#はじめに
今回は、LivekitをGKEで動かす方法について紹介します。
#Livekitとは
LiveKit is an open source project that provides scalable, multi-user conferencing based on WebRTC. It's designed to provide everything you need to build real-time video audio data capabilities in your applications.
出典:Livekit
Livekitは、WebRTCをベースにしたスケーラブルなマルチユーザー会議を提供するオープンソースプロジェクトです。リアルタイムのビデオオーディオデータ機能をアプリケーションに組み込むために必要なすべてを提供するように設計されています。
Google ChatやZoomのようなビデオ会議アプリケーションを作成するための基盤として利用できます。
各種言語に対応したSDKも豊富に提供されています。
- Web
- React Components
- JavaScript
- Unity (WebGL)
- Native
- Swift Components
- Swift
- Android Components
- Android
- Flutter
- React Native
- Rust
- Unity
- Server
- Go
- Node
- Ruby
- Kotlin/Java
- Python
- PHP
この他にも、動画を入力にしてWebRTCで配信したり、配信されている動画や音声を録画、録音する機能も提供されています。
昨今では、ChatGPTでLivekitが利用されているということで、注目されています。
#システム構成
デモ用に構築するので、シンプルな構成で構築します。
システム構成図
- GKE
- コストを抑えるために、1ノードのみのクラスタを作成します。
- preenptibleノードを利用します。
- cloudflare tunnel
- GKE上にデプロイします。
- Redis
- GKE上にデプロイします。
- standaloneモードでデプロイします。
- Livekit Server
- GKE上にデプロイします。
- STUN/TURN
- Livekit Serverのデフォルトでは、GoogleのSTUNサーバを利用します。
- ※GoogleのSTUNサーバは、開発用途のみで利用することとされているので、本来は別途立てたほうが良いですが、今回はデモが終わったら破棄するので、利用します。
- Livekit WebApp
- この記事ではデプロイせず、Livekitのサンプルアプリをローカルで動かしてGKE上のLivekit Server経由でビデオチャットを行います。
#準備
今回のソースコードは、こちらにあります。
https://github.com/cloudandbuild/livekit-gke
必要なツールのリストを記載します。
- .tool-versions
helm 3.14
helmfile 0.164.0
sops 3.8.1
age 1.1.1
kubectl 1.28
kubectx 0.9
k9s 0.27
jq 1.7.1
terraform 1.7
direnv 2.34.0
gcloud 493.0.0
miseを使って、必要なツールをインストールします。
mise install
前提として、cloudflareとgoogle cloudのアカウントを持っていることです。
#ネットワークとファイアウォールの設定
#Cloudflare Tunnel
CloudflareのコンソールからZero Trust
を選択し、TunnelsからCreate Tunnel
を選択。
作成したTunnelのToken
を取得しておきます。
Public Routeには、適当なドメインとそれに紐づくGKE側のサービスを指定します。
例えば以下のように。
- Livekit APIドメイン(livekit-api.example.com):
http://livekit-server.livekit.svc.cluster.local
- Livekit WebAppドメイン(livekit-webapp.example.com):
http://livekit-webapp.livekit.svc.cluster.local
#Google Cloud
事前にGoogle Cloudのプロジェクトを作成してあることが前提です。
gcloudで対象プロジェクトを設定します。
gcloud config set project [PROJECT_ID]
VPCを事前に作成する必要があります。default
を使う場合は不要ですが、public_subnetを作成する必要があります。また、GKEのpodsのIPアドレス範囲を指定できるようsecondary rangeを設定しておきます。
また、LivekitのFirewallのドキュメントを参考に、以下のファイアウォールルールを設定します。
resource "google_compute_firewall" "allow-livekit" {
name = "${var.env}-allow-livekit"
network = var.vpc_name
allow {
protocol = "tcp"
ports = ["7881"]
}
allow {
protocol = "udp"
ports = ["50000-60000"]
}
source_ranges = ["0.0.0.0/0"]
}
terraformを適用すると、GKEのクラスタが作成されます。
cd terraform/demo/base
terraform init
terraform apply
#GKEのクラスタを作成
ポイントは、public subnetを指定することです。Livekitは、Hostネットワークを利用して直接インターネットに接続するためです。商用にデプロイを検討するとpublic subnetのnode poolとprivateのnode poolを両方作っておき、publicに置く必要のあるワークロードだけを配置することが、セキュリティ上、望ましいです。
locationには、リージョンではなくゾーンまで指定するとZonalクラスターが作成されます。冗長性などを考慮する場合はリージョナルクラスターを作成すると良いでしょう。
以下は、terraformでGKEのクラスタを作成する例です。
- variables.tf
variable "project" {
description = "The project ID for the network"
type = string
}
variable "env" {
}
variable "location" {
description = "The location for the network"
type = string
}
variable "network" {
description = "The network name"
type = string
}
variable "public_subnet" {
description = "The public subnet name"
type = string
}
variable "cluster_secondary_range_name" {
description = "The name of the secondary range for the cluster"
type = string
}
- main.tf
resource "google_service_account" "default" {
account_id = "service-account-id"
display_name = "Service Account"
}
resource "google_container_cluster" "primary" {
name = "${var.env}-livekit-gke-cluster"
location = var.location
network = var.network
subnetwork = var.public_subnet
ip_allocation_policy {
cluster_secondary_range_name = var.cluster_secondary_range_name
}
deletion_protection = false
# We can't create a cluster with no node pool defined, but we want to only use
# separately managed node pools. So we create the smallest possible default
# node pool and immediately delete it.
remove_default_node_pool = true
initial_node_count = 1
}
resource "google_container_node_pool" "primary_nodes" {
name = "${var.env}-node-pool"
location = var.location
cluster = google_container_cluster.primary.name
node_count = 1
node_config {
machine_type = "e2-medium"
preemptible = true
# Google recommends custom service accounts that have cloud-platform scope and permissions granted via IAM Roles.
service_account = google_service_account.default.email
oauth_scopes = [
"https://www.googleapis.com/auth/cloud-platform"
]
}
}
terraformを適用すると、GKEのクラスタが作成されます。
cd terraform/demo/infra
terraform init
terraform apply
kubectlを使えるよう、credentialを設定します。
gcloud container clusters get-credentials demo-livekit-gke-cluster --zone asia-northeast1-c --project [PROJECT_ID]
#Helm Chartで各種コンポーネントのデプロイ
ここまでで、GKEのクラスタが作成されました。
ここからは、Helm Chartを使って各種コンポーネントをデプロイします。
helmでは、環境変数で値を渡して設定を行います。
.envrcに以下のように設定します。
export HF_CF_TUNNEL_TOKEN=<cloudflare tunnel token>
export HF_REDIS_PASSWORD=<redis password>
export HF_LK_API_KEY=<your apikey>
export HF_LK_API_SECRET=<your api secret>
direnvを使って、環境変数を読み込みます。
direnv allow
helmfileを使って、デプロイします。
helmfile -e demo apply
#Redis
以下、valuesの例です。
- values.yaml
global:
redis:
password: {{ requiredEnv "HF_REDIS_PASSWORD" | quote }}
architecture: standalone
#Livekit Server
- values.yaml
replicaCount: 1
# Suggested value for gracefully terminate the pod: 5 hours
terminationGracePeriodSeconds: 18000
livekit:
# port: 7880
# Uncomment to enable prometheus metrics
# prometheus_port: 6789
log_level: info
rtc:
use_external_ip: true
# default ports used
port_range_start: 50000
port_range_end: 60000
tcp_port: 7881
redis:
address: redis-headless.redis.svc.cluster.local:6379
# db: 0
# username:
password: {{ requiredEnv "HF_REDIS_PASSWORD" | quote }}
# use_tls: true
# one or more API key/secret pairs
# see https://docs.livekit.io/guides/getting-started/#generate-api-key-and-secret
keys:
{{ requiredEnv "HF_LK_API_KEY" }}: {{ requiredEnv "HF_LK_API_SECRET" | quote }}
注意点
Livekitのhelm chartでは、secretを使っていないので、ConfigMapに直接設定しています。
そのため、Redis のパスワードやAPIキーなどが平文でConfigMap設定されてしまいます。
本番環境でデプロイする場合は、Livekitの設定ファイルをシークレットで管理するよう別途helm chartを作成するのがよいでしょう。
#Cloudflare Tunnel
フロントエンドからLivekitにアクセスするため、Livekit APIを公開する必要があります。
Google CloudのLoadBalancerとNEGを使っても良いですが、最近は使い勝手のよいcloudflare tunnelを使ってTLS終端をすることが多いです。DNSの伝搬もすぐに反映されるのが、気に入っています。
valuesは以下のように設定します。Tokenのみ設定するだけで動くので、簡単です。
cloudflare:
tunnel_token: {{ requiredEnv "HF_CF_TUNNEL_TOKEN" | quote }}
#Livekitのサンプルアプリを動かす
LivekitはSDKとそのExampleが豊富に提供されています。
ここでは、Next.jsを使ったサンプルアプリを動かします。
git clone https://github.com/livekit/components-js.git
cd components-js
pnpm install
examples/nextjs/.env.local
ファイルを作成して、以下のように設定します。
- examples/nextjs/.env.local
LK_API_KEY=<your apikey>
LK_API_SECRET=<your api secret>
NEXT_PUBLIC_LK_TOKEN_ENDPOINT=/api/livekit/token
NEXT_PUBLIC_LK_SERVER_URL=wss://livekit-server.example.com
サンプルアプリを起動します。
pnpm run dev:next
疎通確認を行います。
これは、ブラウザでhttp://localhost:3000
にアクセスして、ビデオチャットができることを確認します。スクリーンの共有もできます。
ローカルで疎通確認しましたが、exampleのアプリは、Next.jsで構成されているので、これのNode.jsのDockerイメージを作って、GKEにデプロイして、cloudflare tunnelのRoute設定をしてあげるとインターネット上からアクセスできるようになります。
サンプルアプリをGKEにデプロイする部分は、この記事では割愛します。
#参考リンク
#まとめ
今回は、LivekitをGKEで動かす方法について紹介しました。
商用で動かすには、セキュリティや冗長性などを考慮する必要がありますが、デモやプロトタイプを作るには、このような構成で十分です。
また、STUN/TURNサーバなども別途立てる必要がありますが、今回はGoogleのSTUNサーバを利用しました。
Livekitのセルフホストは、結構難易度が高いので、LiveKit CloudというSaaSを利用するのも一つの手です。
ChatGPTのようなマルチモーダルなアプリケーションで音声による会話や、カメラによる画像の入力を行う場合には、Livekitは非常に便利ですから、今後も注目していきたいです。