Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Service Weaver で始める モジュラー モノリス、 そしてマイクロサービスへ

Service Weaver で始める モジュラー モノリス、 そしてマイクロサービスへ

GoogleCloudPlatformJapan

June 19, 2024
Tweet

More Decks by GoogleCloudPlatformJapan

Other Decks in Business

Transcript

  1. Proprietary + Confidential Legacy Modern モジュール性が低い: 高度に結合されたビジネ ス ロジックとモノリシック アーキテクチャ

    モジュール性が高い: 結合度の低いビジネス ロジックとマイクロ サービス アーキテクチャ モジュール性
  2. Proprietary + Confidential On-premise server Cloud delivery platform Legacy Modern

    弾力性が低い: 自己管理型の スケーリングとインフラ 弾力性が高い: オンデマンドの スケーリングとインフラ 弾力性
  3. Hosted / managed virtual machines (OS) Fully-managed container platforms (GKE,

    Cloud Run) Legacy Modern ポータビリティが低い: セルフマネージド OS、 ライブラリ、依存関係 ポータビリティが高い: 依存関係管理の簡素化 ポータビリティ
  4. Plan Code Test Release Deploy Maintain Build 2010s Plan Code

    Test Release Maintain Build Deploy 理想 Shift Left Outer loop Inner loop 短縮される outer loop サイクル タイム Time Spent Platform Developer Roles “You build it, you run it.” - Platform 理想としてはサイクル タイムが短縮されるはず ※ マネージド環境を利用すると、より短縮可能 (本セッションでは言及しない)
  5. 理想 Plan Code Test Release Maintain Build Deploy 現実 Shift

    Left Plan Code Test Release Build Deploy 計画の長期化 テスト責務の肥 大化 オペレーションの 複雑化 Maintain インシデント対 応の長期化 Time Spent Platform Developer Roles inner loop の長期化 Developer の さらなる責務 現実に見られるイノベーション能力の低下
  6. テスト責務の 肥大化、複雑化 マイクロサービス環境に おけるコードのテストと デバッグが難しい 事前計画、 設計の長期化 マイクロサービス環境の計 画と設計などに多くの時間 を費やしてしまう

    開発オーバーヘッドの 肥大化 ローカル、ステージング、本 番環境間でのアプリの 移植性が、アプリ開発の 課題になる インシデント対応の長 期化 十分な可観測性ツールが 不足しており、頻繁な サービス停止発生に繋がる Developer の苦悩
  7. 2023 年 3 月 1 日に Google が発表した 分散アプリケーションを作るための フレームワーク(公式ブログ、GitHub)

    モジュラー モノリスとして書いた アプリケーションをマイクロ サービス としてデプロイできる Service Weaver とは Write your application as a modular binary. Deploy it as a set of microservices. Service Weaver is a programming framework for writing and deploying cloud applications. https://serviceweaver.dev/
  8. • コアライブラリ ◦ ネイティブ データ構造とメソッド呼び出しのみを使用して、アプリケーションを単一のモ ジュラー バイナリとして記述できる Go 言語で書かれた ライブラリ、アプリケーションを書く際に利用する

    • デプロイヤー(ローカル、GKE、Kube、SSH [実験的]) ◦ アプリケーションのランタイム トポロジを構成し、それを一連の マイクロサービスとしてデプロイする ◦ ローカルは、Single process / Multi process をサポート Service Weaver は大きく以下の 2 つから構成される
  9. Service Weaver 概念図 コアライブラリ デプロイヤー ローカルや GKE に デプロイ 単一のモジュラー

    バイナリ として書いたコード モジュールごとに独立したラン タイムで実行される https://opensource.googleblog.com/2023/03/introducing-service-weaver-fra mework-for-writing-distributed-applications.html
  10. Application type Rock interface { … } type Paper interface

    { … } type Scissors interface { … } ローカルで実行 モジュラー バイナリとして記述 // Components … Rock Paper Scissors 相互に呼び出し合うコンポーネントの集合体 内部構造:アプリケーションを Service Weaver に 対応させるためのコードジェネレータ (エンコーディングやスタブなどの生成)
  11. Application 分散させて実行 Rock Paper Scissors Scissors Rock Paper type Rock

    interface { … } type Paper interface { … } type Scissors interface { … } // Components … 相互に呼び出し合うコンポーネントの集合体 内部構造:アプリケーションを Service Weaver に 対応させるためのコードジェネレータ (エンコーディングやスタブなどの生成) モジュラー バイナリとして記述 ローカルで実行
  12. Application // Cache component definition. type Cache interface { Put(ctx

    context.Context, key, value string) error ... } どうコンポーネントを定義するか? • Go interface として定義
  13. Application // Cache component definition. type Cache interface { Put(ctx

    context.Context, key, value string) error ... } // Cache component implementation. type cache struct { weaver.Implements[Cache] // to weavify the component data map[string]string } func (c *cache) Put(_ context.Context, key, value string) error { c.data[key] = value return nil } どうコンポーネントを実装するか? • Go の構造体を定義 • 実装を埋め込む weaver.Implements[T] どうコンポーネントを定義するか? • Go interface として定義
  14. Application // Cache component definition. type Cache interface { Put(ctx

    context.Context, key, value string) error ... } // Cache component implementation. type cache struct { weaver.Implements[Cache] // to weavify the component data map[string]string } func (c *cache) Put(_ context.Context, key, value string) error { c.data[key] = value return nil } /////////////////////////////////////////////////////////////////// type app struct { weaver.Implements[weaver.Main] // to make app the main component cache weaver.Ref[Cache] // to get a reference to Cache } インスタンス化、実行するには? • weaver.Ref[T] は、コンポーネントへの ハンドルを返す どうコンポーネントを実装するか? • Go の構造体を定義 • 実装を埋め込む weaver.Implements[T] どうコンポーネントを定義するか? • Go interface として定義
  15. Application // Cache component definition. type Cache interface { Put(ctx

    context.Context, key, value string) error ... } // Cache component implementation. type cache struct { weaver.Implements[Cache] // to weavify the component data map[string]string } func (c *cache) Put(_ context.Context, key, value string) error { c.data[key] = value return nil } func main() { ctx := context.Background() // Run the app. err := weaver.Run(ctx, func(ctx context.Context, app *app) error { … } } /////////////////////////////////////////////////////////////////// type app struct { weaver.Implements[weaver.Main] // to make app the main component cache weaver.Ref[Cache] // to get a reference to Cache } インスタンス化、実行するには? • weaver.Ref[T] は、コンポーネントへの ハンドルを返す • weaver.Run(...) でアプリを実行する どうコンポーネントを実装するか? • Go の構造体を定義 • 実装を埋め込む weaver.Implements[T] どうコンポーネントを定義するか? • Go interface として定義
  16. Application // Cache component definition. type Cache interface { Put(ctx

    context.Context, key, value string) error ... } // Cache component implementation. type cache struct { weaver.Implements[Cache] // to weavify the component data map[string]string } func (c *cache) Put(_ context.Context, key, value string) error { c.data[key] = value return nil } func main() { ctx := context.Background() // Run the app. err := weaver.Run(ctx, func(ctx context.Context, app *app) error { cache := app.cache.Get() err := cache.Put(ctx, “mykey”, “myvalue”) … } } /////////////////////////////////////////////////////////////////// type app struct { weaver.Implements[weaver.Main] // to make app the main component cache weaver.Ref[Cache] // to get a reference to Cache } コンポーネントの呼び出し方は? • シンプルなメソッド呼び出し インスタンス化、実行するには? • weaver.Ref[T] は、コンポーネントへの ハンドルを返す • weaver.Run(...) でアプリを実行する どうコンポーネントを実装するか? • Go の構造体を定義 • 実装を埋め込む weaver.Implements[T] どうコンポーネントを定義するか? • Go interface として定義
  17. How to deploy? [serviceweaver] binary = "./game" // Rock Paper

    Scissors app config. $ go run . # Run in a single process. シンプルな設定ファイル • バイナリを指定するだけ 単一バイナリをリリース
  18. How to deploy? [serviceweaver] binary = "./game" // Rock Paper

    Scissors app config. $ go run . # Run in a single process. $ weaver multi deploy weaver.toml # Run in multiple processes. シンプルな設定ファイル • バイナリを指定するだけ 単一バイナリをリリース
  19. How to deploy? [serviceweaver] binary = "./game" // Rock Paper

    Scissors app config. $ go run . # Run in a single process. $ weaver multi deploy weaver.toml # Run in multiple processes. 単一バイナリをリリース シンプルな設定ファイル • バイナリを指定するだけ • デプロイ毎
  20. How to deploy? [serviceweaver] binary = "./game" // Rock Paper

    Scissors app config. $ go run . # Run in a single process. $ weaver multi deploy weaver.toml # Run in multiple processes. // Deployments config. [ssh] locations_file = "./ssh_locations.txt" 単一バイナリをリリース デプロイ コマンド for • ローカル環境 • 複数のマシン シンプルな設定ファイル • バイナリを指定するだけ • デプロイ毎
  21. How to deploy? [serviceweaver] binary = "./game" // Rock Paper

    Scissors app config. // Deployments config. [ssh] locations_file = "./ssh_locations.txt" $ go run . # Run in a single process. $ weaver multi deploy weaver.toml # Run in multiple processes. $ weaver ssh deploy weaver.toml # Run in the cluster. 単一バイナリをリリース デプロイ コマンド for • ローカル環境 • 複数のマシン シンプルな設定ファイル • バイナリを指定するだけ • デプロイ毎
  22. How to deploy? [serviceweaver] binary = "./game" [gke] regions =

    ["us-west1", "us-east1"] listeners.game = {is_public = true, hostname = "game.example.com"} // Deployments config. [ssh] locations_file = "./ssh_locations.txt" // Rock Paper Scissors app config. $ go run . # Run in a single process. $ weaver multi deploy weaver.toml # Run in multiple processes. $ weaver ssh deploy weaver.toml # Run in the cluster. 単一バイナリをリリース デプロイ コマンド for • ローカル環境 • 複数のマシン • カスタム GKE デプロイヤー ◦ マルチリージョン ◦ 安全なロールアウト(Blue/Green) ◦ ルーティング ◦ カスタム リソースの管理 シンプルな設定ファイル • バイナリを指定するだけ • デプロイ毎
  23. How to deploy? [serviceweaver] binary = "./game" // Deployments config.

    [ssh] locations_file = "./ssh_locations.txt" // Rock Paper Scissors app config. $ go run . # Run in a single process. $ weaver multi deploy weaver.toml # Run in multiple processes. $ weaver ssh deploy weaver.toml # Run in the cluster. $ weaver gke deploy weaver.toml # Run in GKE. [gke] regions = ["us-west1", "us-east1"] listeners.game = {is_public = true, hostname = "game.example.com"} 単一バイナリをリリース デプロイ コマンド for • ローカル環境 • 複数のマシン • カスタム GKE デプロイヤー ◦ マルチリージョン ◦ 安全なロールアウト(Blue/Green) ◦ ルーティング ◦ カスタム リソースの管理 シンプルな設定ファイル • バイナリを指定するだけ • デプロイ毎
  24. How to deploy? appConfig: weaver.toml repo: docker.io/your_docker_id listeners: - name:

    game public: true // kube.yaml $ go run . # Run in a single process. $ weaver multi deploy weaver.toml # Run in multiple processes. $ weaver ssh deploy weaver.toml # Run in the cluster. $ weaver gke deploy weaver.toml # Run in GKE. 単一バイナリをリリース シンプルな設定ファイル • バイナリを指定するだけ • デプロイ毎 デプロイ コマンド for • ローカル環境 • 複数のマシン • カスタム GKE デプロイヤー ◦ マルチリージョン ◦ 安全なロールアウト(Blue/Green) ◦ ルーティング ◦ カスタム リソースの管理 • 任意のマネージド K8s 環境
  25. How to deploy? appConfig: weaver.toml repo: docker.io/your_docker_id listeners: - name:

    game public: true resourceSpec: requests: memory: "64Mi" cpu: "250M" // kube.yaml $ go run . # Run in a single process. $ weaver multi deploy weaver.toml # Run in multiple processes. $ weaver ssh deploy weaver.toml # Run in the cluster. $ weaver gke deploy weaver.toml # Run in GKE. 単一バイナリをリリース シンプルな設定ファイル • バイナリを指定するだけ • デプロイ毎 デプロイ コマンド for • ローカル環境 • 複数のマシン • カスタム GKE デプロイヤー ◦ マルチリージョン ◦ 安全なロールアウト(Blue/Green) ◦ ルーティング ◦ カスタム リソースの管理 • 任意のマネージド K8s 環境
  26. How to deploy? appConfig: weaver.toml repo: docker.io/your_docker_id listeners: - name:

    game public: true resourceSpec: requests: memory: "64Mi" cpu: "250M" scalingSpec: minReplicas: 2 maxReplicas: 12 // kube.yaml $ go run . # Run in a single process. $ weaver multi deploy weaver.toml # Run in multiple processes. $ weaver ssh deploy weaver.toml # Run in the cluster. $ weaver gke deploy weaver.toml # Run in GKE. 単一バイナリをリリース シンプルな設定ファイル • バイナリを指定するだけ • デプロイ毎 デプロイ コマンド for • ローカル環境 • 複数のマシン • カスタム GKE デプロイヤー ◦ マルチリージョン ◦ 安全なロールアウト(Blue/Green) ◦ ルーティング ◦ カスタム リソースの管理 • 任意のマネージド K8s 環境
  27. How to deploy? appConfig: weaver.toml repo: docker.io/your_docker_id listeners: - name:

    game public: true resourceSpec: requests: memory: "64Mi" cpu: "250M" scalingSpec: minReplicas: 2 maxReplicas: 12 storageSpec: volumes: - name: my-volume persistentVolumeClaim: claimName: my-pvc volumeMounts: - name: my-volume mountPath: "/app/data" // kube.yaml $ go run . # Run in a single process. $ weaver multi deploy weaver.toml # Run in multiple processes. $ weaver ssh deploy weaver.toml # Run in the cluster. $ weaver gke deploy weaver.toml # Run in GKE. 単一バイナリをリリース シンプルな設定ファイル • バイナリを指定するだけ • デプロイ毎 デプロイ コマンド for • ローカル環境 • 複数のマシン • カスタム GKE デプロイヤー ◦ マルチリージョン ◦ 安全なロールアウト(Blue/Green) ◦ ルーティング ◦ カスタム リソースの管理 • 任意のマネージド K8s 環境
  28. How to deploy? appConfig: weaver.toml repo: docker.io/your_docker_id listeners: - name:

    game public: true resourceSpec: requests: memory: "64Mi" cpu: "250M" scalingSpec: minReplicas: 2 maxReplicas: 12 storageSpec: volumes: - name: my-volume persistentVolumeClaim: claimName: my-pvc volumeMounts: - name: my-volume mountPath: "/app/data" // kube.yaml $ go run . # Run in a single process. $ weaver multi deploy weaver.toml # Run in multiple processes. $ weaver ssh deploy weaver.toml # Run in the cluster. $ weaver gke deploy weaver.toml # Run in GKE. $ weaver kube deploy kube.yaml # Generates k8s deployment. 単一バイナリをリリース シンプルな設定ファイル • バイナリを指定するだけ • デプロイ毎 デプロイ コマンド for • ローカル環境 • 複数のマシン • カスタム GKE デプロイヤー ◦ マルチリージョン ◦ 安全なロールアウト(Blue/Green) ◦ ルーティング ◦ カスタム リソースの管理 • 任意のマネージド K8s 環境
  29. How to deploy? appConfig: weaver.toml repo: docker.io/your_docker_id listeners: - name:

    game public: true resourceSpec: requests: memory: "64Mi" cpu: "250M" scalingSpec: minReplicas: 2 maxReplicas: 12 storageSpec: volumes: - name: my-volume persistentVolumeClaim: claimName: my-pvc volumeMounts: - name: my-volume mountPath: "/app/data" // kube.yaml $ go run . # Run in a single process. $ weaver multi deploy weaver.toml # Run in multiple processes. $ weaver ssh deploy weaver.toml # Run in the cluster. $ weaver gke deploy weaver.toml # Run in GKE. $ weaver kube deploy kube.yaml # Generates k8s deployment. $ kubectl apply -f <generated>.yaml># Run in GKE, EKS, AKS, on-prem. 単一バイナリをリリース シンプルな設定ファイル • バイナリを指定するだけ • デプロイ毎 デプロイ コマンド for • ローカル環境 • 複数のマシン • カスタム GKE デプロイヤー ◦ マルチリージョン ◦ 安全なロールアウト(Blue/Green) ◦ ルーティング ◦ カスタム リソースの管理 • 任意のマネージド K8s 環境
  30. How to deploy? appConfig: weaver.toml repo: docker.io/your_docker_id listeners: - name:

    game public: true resourceSpec: requests: memory: "64Mi" cpu: "250M" scalingSpec: minReplicas: 2 maxReplicas: 12 storageSpec: volumes: - name: my-volume persistentVolumeClaim: claimName: my-pvc volumeMounts: - name: my-volume mountPath: "/app/data" // kube.yaml $ go run . # Run in a single process. $ weaver multi deploy weaver.toml # Run in multiple processes. $ weaver ssh deploy weaver.toml # Run in the cluster. $ weaver gke deploy weaver.toml # Run in GKE. $ weaver kube deploy kube.yaml # Generates k8s deployment. $ kubectl apply -f <generated>.yaml># Run in GKE, EKS, AKS, on-prem. Telemetry Prometheus Jaeger Grafana 単一バイナリをリリース シンプルな設定ファイル • バイナリを指定するだけ • デプロイ毎 https://github.com/ServiceWeaver/weav er-kube/tree/main/examples/telemetry デプロイ コマンド for • ローカル環境 • 複数のマシン • カスタム GKE デプロイヤー ◦ マルチリージョン ◦ 安全なロールアウト(Blue/Green) ◦ ルーティング ◦ カスタム リソースの管理 • 任意のマネージド K8s 環境
  31. How to deploy? appConfig: weaver.toml repo: docker.io/your_docker_id listeners: - name:

    game public: true resourceSpec: requests: memory: "64Mi" cpu: "250M" scalingSpec: minReplicas: 2 maxReplicas: 12 storageSpec: volumes: - name: my-volume persistentVolumeClaim: claimName: my-pvc volumeMounts: - name: my-volume mountPath: "/app/data" // kube.yaml $ go run . # Run in a single process. $ weaver multi deploy weaver.toml # Run in multiple processes. $ weaver ssh deploy weaver.toml # Run in the cluster. $ weaver gke deploy weaver.toml # Run in GKE. $ weaver kube deploy kube.yaml # Generates k8s deployment. $ kubectl apply -f <generated>.yaml># Run in GKE, EKS, AKS, on-prem. Telemetry Prometheus Jaeger Grafana CI / CD Pipelines Cloud Build Argo CD Jenkins 単一バイナリをリリース デプロイ コマンド for • ローカル環境 • 複数のマシン • カスタム GKE デプロイヤー ◦ マルチリージョン ◦ 安全なロールアウト(Blue/Green) ◦ ルーティング ◦ カスタム リソースの管理 • 任意のマネージド K8s 環境 シンプルな設定ファイル • バイナリを指定するだけ • デプロイ毎
  32. How is it deployed? プロセス (Microservices と同義) component Rock component

    Paper component Scissors Rock Paper モジュラー バイナリ Scissors
  33. How is it deployed? component Rock component Paper component Scissors

    Rock Paper weaver libraries アプリとランタイ ム間の相互作用 を管理 Scissors weaver libraries プロセス (Microservices と同義) モジュラー バイナリ
  34. How is it deployed? component Rock component Paper component Scissors

    Rock Paper weaver libraries ランタイム Local, SSH, GKE, EKS, AKS, etc. デプロイヤー Scissors weaver libraries アプリとランタイ ム間の相互作用 を管理 プロセス (Microservices と同義) モジュラー バイナリ
  35. 可観測性の向上 func (c *cache) Put(_ context.Context, key, value string) error

    { c.Logger().Info(“Add”, “key”, key, “value”, value) c.data[key] = value return nil } ロギング • 各コンポーネントにはそれぞれロガーが関連付けられています • 構造化ログ:ログの閲覧、追跡、検索、フィルタリングが可能 $ weaver gke logs --follow $ weaver gke logs ‘app==“cache” && level==”info” $ … ...
  36. 可観測性の向上 var putCount = weaver.NewCounter(“put_count”, “Number of Put ops.”) func

    (c *cache) Put(_ context.Context, key, value string) error { c.data[key] = value putCount.Add(1.0) return nil } メトリクス • カウンター、ゲージ、ヒストグラム • フレームワーク メトリクスを含む ... ...
  37. 可観測性の向上 func main() { … // Create an otel handler

    to enable tracing. otelHandler := otelhttp.NewHandler( http.DefaultServeMux, “http”) http.Serve(lis, otelHandler) } トレーシング • OpenTelemetry に依存 • 有効にすると、すべての HTTPリクエストとコンポーネントのメソッド呼び出しが自動的に トレースされます ... ...
  38. 可観測性の向上 $ weaver gke profile cache # CPU profile. $

    weaver gke profile –-type=heap cache # Heap profile. $ … プロファイリング • 個々のプロセスをプロファイルし、単一のプロファイルに集約します • アプリ全体のパフォーマンスを把握できます ... ...
  39. Runners 異なる通信のランナーを提供 • weavertest.Local • weavertest.Multi • weavertest.RPC Fakes コンポーネントの実装を

    stub で提供可 • weavertest.Fake テストのサポート機能 import ( ... "github.com/ServiceWeaver/weaver" "github.com/ServiceWeaver/weaver/weavertest" ) type fakeClock struct { now int64 } func (f *fakeClock) Now(context.Context) (int64, error) { return f.now, nil } func TestClock(t *testing.T) { for _, runner := range weavertest.AllRunners() { fake := &fakeClock{100} runner.Fakes = append(runner.Fakes, weavertest.Fake[Clock](fake)) runner.Test(t, func(t *testing.T, clock Clock) { now, err := clock.UnixMicro(context.Background()) if err != nil { t.Fatal(err) } if now != 100 { t.Fatalf("bad time: got %d, want %d", now, 100) } }) } } ...
  40. 理想 Plan Code Test Release Maintain Build Deploy 現実 Shift

    Left Plan Code Test Release Build Deploy 計画の長期化 テスト責務の肥 大化 オペレーションの 複雑化 Maintain インシデント対 応の長期化 Time Spent Platform Developer Roles inner loop の長期化 Developer の さらなる責務 【再掲】現実に見られるイノベーション能力の低下
  41. 計画から実装までのアジリティを高める モジュール化されたビ ジネスロジックを記述 Hybrid monolith Distributed monolith Microservices マイクロ サービスの

    計画、実装、デプロイ Without Service Weaver Service Weaver モノリスの計画、 実装、デプロイ Deploy 開発の 抽象化
  42. イノベーション能力を強化させる Hybrid monolith Distributed monolith Microservices Without Service Weaver Service

    Weaver 低レイテンシ、かつ モジュール性が高い gRPC, http, tcp gRPC, http, tcp 低レイテ ンシ モジュール 性が高い
  43. 製品の品質向上 Hybrid monolith Distributed monolith Microservices Without Service Weaver Service

    Weaver コンポーネント毎に 単体テストを 作成 ロジックをデバッグ 統合処理を実行 シミュレーション Local Staging サービス毎に 単体テストを 作成 サービス毎に 統合テストを 作成 E2E テストを実行 サービス毎に セットアップと 実行 サービス毎に セットアップと 実行
  44. 製品の品質向上 改善 Admin Developer Roles Plan Code Test Build Service

    Weaver Developer Maintain Deploy Plan Code Test Release Build Deploy 現実 Maintain 統合 QA デバッグ 実験、試作 欠陥とインシデントに 費やす時間を削減 包括的なローカル テストで、テストの 手間を軽減 Unit & Integration
  45. すべての Google Cloud 開発者、技術者、学生のための メンバーシップ プログラム! 知る 多彩なコンテンツで 最新情報が学べる 高める

    学習プログラムで スキルアップできる つながる キャリアや年齢を超えた 仲間と交流できる cloud.google.com/innovators ご登録はこちら メンバー特典 メンバー登録受付中! コミュニティ オンライン学習プラットフォーム「 Google Cloud Skills Boost 」を活用でき るよう、毎月 35 クレジットが無料で付与されます。
  46. Innovators Live Japan デベロッパー・エンジニア向けのセッションを ライブ配信でお届け! https://goo.gle/GCI-LIVE-JP Google Cloud のメンバーやユーザーが、 Google

    Cloud やデベロッパー界隈で注目のトピックについて、トークを繰り広げます。 データベース・ データ分析・ AI/ML サーバーレス・コンテナ 監視・ オブザーバビリティ・ SRE Game Community スタートアップ ウェビナー ご登録はこちら