マイクロサービスを量産するための技術基盤

ogp

はじめに

こんにちは、enechainのApplication Platform Deskでエンジニアをしているendoです。

Application Platform Deskは、全プロダクトが横断で抱える課題を解決するチームです。 今回は社内でのプロジェクト開発の爆速化を行うためのプロジェクト、Instant Universe Projectについて紹介します。

Instant Universe Project とは

マイクロサービスを順調に量産してそれぞれのサービスがつながっていった結果、宇宙のようなサービスマップになりますようにという思いから生まれたプロジェクトです。

プロジェクトの作成から開発に入るまでのフローを整備し、プロジェクトの自動生成を行うことで開発スピードを上げてサービスを量産するための基盤を作成することを狙って立ち上がりました。

プロジェクト発足の技術的背景

enechainではスピーディに次々と新しいサービスが生まれてはリリースされています。

その中で、以下のような課題が浮かび上がってきました。

  • 新しくサービスを作る時の初期準備に毎回コストがかかる
  • 各サービスに利用される技術(言語等)の統一感がなくなり、ガバナンスが効きにくくなっていく
  • 各サービスで統一したい処理(ロガー等)の統一感がなくなり、ガバナンスが効きにくくなっていく
  • ガバナンスを効かせようとするとCTOや基盤チームのレビューコストが跳ね上がってしまう

これらの課題を解決し、新規プロジェクトのスタートを簡略化できなかというところから本プロジェクトが始まりました。

実装

Instant Universe Project では、上述の課題に対して以下のようなアプローチをとっています。

  • 全社の標準構成に則ったボイラープレートの実装
  • Terraform や Kubernetes manifest の自動生成による開発環境自動構築の仕組み (generator) の実装
  • ボイラープレートをベースに、上記環境にコード基盤まで自動で整える仕組みの開発

これらを実際に作っていく中で最も重視したのは、インフラ部分に関して いつでも捨てられる ことを念頭に置いて作ることです。

immutableなコードを自動生成できるようになることで、TerraformやK8sに慣れていないメンバーでも安全なインフラ環境を作成できるようになります。 また、再生成可能な作りにすることで、最新の設定を各サービスに反映していくなどのガバナンスも効かせやすくなったり、一括で特定のライブラリを導入することも容易になります。

最初に描いた全体フロー

最初に描いた全体像は下記の図のようなものです。

開発環境生成フロー

  1. アプリ開発チームのエンジニアが、新規プロジェクト立ち上げのためのterraformの設定(GitHubやGoogle GroupsのTerraform設定)PRをgeneratorにて作成する
  2. SREチームがレビューし、足りない項目があった時は手作業で修正する
  3. SREチームのレビューが済んだらマージ & terraform applyする
  4. ボイラープレートをベースに、プロジェクトのリポジトリ(kubernetes manifest、golangのリポジトリ)が自動生成される
  5. アプリ開発チームのエンジニアが、generator コマンドを用いて kubernetes manifest に job や worker などを追加する

この手順にすることでkubernetes manifestに詳しくない人でも社内での標準設定に則ったmanifestを作ることができるため、SREチームと開発チームでPR作成やレビューにかかる時間を大幅に短縮できると考えました。

kubernetes manifestの構成に変更があった時もSREチームや私達のチームがgeneratorをメンテナンスするため、開発チームは意識しなくても推奨設定のPRを作成できるようになります。

また、再生成可能な作りにすることで大幅な変更があった場合には今の設定を捨てて再生成すればいいというところも大きな利点になります。

生成するインフラ構成

manifestでは下記図のようなBFF、Frontend、Backendの三構成をベースにした作りを標準構成にします。

インフラ図

Istioを用いたサービスメッシュについても検討しましたが、今現在稼働しているインフラ構成を再作成しないといけないこともあり慎重に作り込まないといけないため、初期構成では見送り、上記の構成にすることにしました。

認証認可はBFFで行い、セキュリティ向上と共に各サービスが必要以上に特定のサービスに依存しなくても良い状態を作れるようにします。

FrontendからBFFの通信はconnect-go、BFFからBackendはgRPCを使っているため基本的にprotobufを使ったインターフェースで通信を行うようにします。

※ BFFからBackendでconnect-goを使っていないのは、今のインフラ構成ではL7レイヤーのLBを導入していないためクライアントサイドLBで負荷分散を行わないといけないのですが、クライアントサイドLBは執筆時点ではβ版しか存在せず、導入を見送っているためです。

Terraformの自動生成

Terraform の generator を運用するためには、Terraform関連の設定を一つのリポジトリで管理していた方がアップデートなどの運用が楽になるため、モノレポ構成にして一元管理することにしました。

generator で自動生成が可能なのは以下の Terraform です。

  • プロジェクトのGitHubリポジトリ
  • GCPプロジェクト
  • CloudSQL
  • PubSubなど、サービスで追加したいもの

CloudSQL の生成時には Secret Manager へのパスワード登録が必要となります。

セキュリティも考慮した結果、開発者であれば誰もが扱えてしまうツール(generator)にSecret Managerの操作権限を持たせるのは危険と判断しました。

そのため、CloudSQLを使う場合にはパスワードを事前にSecret Managerに登録する運用としています。

  sql_users = {
    $tf_microservice_name = {
      password = data.google_secret_manager_secret_version.db_password.secret_data
    }
  }

Kubernetes manifestの自動生成

enechainではKubernetes manifestの管理をkustomizeを用いて行っております。

当初の予定ではボイラープレートを想定していましたが、途中で路線変更を行いました。 kustomizeのmanifestもTerraformと同じくモノレポで管理し、generatorによる自動生成を可能にしています。

generateできる内容としては下記をターゲットにし、jobなどの必須ではないmanifestについてはappendできるようにします。

  • base manifest
  • overlay manifest
  • jobやworker用のmanifest

生成するフォルダ構成は下記のようにしてモノレポで管理し、generatorに与えたプロジェクト名以下に吐き出されるようにします。

追加でgenerateするjobなどを追加する場合にはdeplyoment.yamlと同じ階層に自動生成されていき、imageファイルなど最低限の項目を書き換えれば動作するようにします。

.
├── base
│   ├── backend
│   │   ├── configs
│   │   │   └── backend.env
│   │   ├── deployment.yaml
│   │   ├── kustomization.yaml
│   │   ├── pdb.yaml
│   │   └── service.yaml
│   ├── frontend
│   │   ├── configs
│   │   │   ├── frontend.env
│   │   │   ├── mime.types
│   │   │   └── nginx.conf
│   │   ├── deployment.yaml
│   │   ├── kustomization.yaml
│   │   ├── pdb.yaml
│   │   └── service.yaml
│   └── network
│       ├── frontendconfig.yaml
│       ├── kustomization.yaml
│       └── networkpolicy.yaml
└── overlays

開発途中のためまだスクリプトで生成している段階になりますが、実際に生成しているところは下記のようになります。

manifest generate

ボイラープレート

ボイラープレートでは、enechainで標準構成としている以下の技術スタックでコードテンプレートを提供します。 執筆時点ではBackendのボイラープレートのみを提供していますが、最終的には下記の範囲を提供する予定です。

  • BFF:Golang、Connect
  • Backend:Golang、gRPC
  • Frontend:React

ボイラープレートはci(lint, test, docker build, 脆弱性チェックなど)及びベースとなるサンプルコードのみのシンプルな構成にします。

そこから先は各プロジェクトに合わせて開発が進んでいくため再生成などは考えておらず、あくまで諸々のコードがいきなり動くよというところからスタートできるようにという観点で作っています。

ただし、デプロイ周りのCI/CDなど独自に変更してほしくはないところについてはそのまま使ってもらうことを推奨しています。

artifact registryにdeployするdocker imageを置く、build時にはこのreusable workflowを使うといったルールに関してはそのまま使うことを前提にして変更があった場合には追従してもらうように全体周知するようにします。

追従させる方法として他にもいい手法があると思いますが、各サービスで最適な方法なのかもわからないためまずはミニマムスタートで使ってもらい、その後最適な周知 or 反映手法を模索しながら進化させていく方向にしました。

この先の実装予定

今後はサービスメッシュ導入とBFFの自動生成を検討しています。

サービスメッシュ導入の目的としては認証認可やサーキットブレーカー、カオステストなどの実現を容易にするためです。

特に認証認可をここに組み込めれば各サービスでは認証認可を気にする必要がなくなったりします。

また、各サービスが瞬断した場合の試験や、社内での障害対応訓練を staging 環境で行えるようにして、いざ障害が発生した場合の対応を混乱せずにスムーズに行えると良いとも思っています。

次にBFFの自動生成ですが、これはメルカリ様からリリースされているgrpc-federationを使ってtemplateをenechain用にカスタマイズして使おうと思っています。

ここでも自動生成することで何か共通のライブラリを入れたいなどがあった場合に簡単にreplaceできるようになるのがメリットです。

ここまで用意できれば全体の殆どが自動的に作られるものになり、開発チームは自分のサービス開発に集中することができるようになると思っています。 最初の環境整備としてはここまでを考慮して、ステップを踏んで段階的にリリースできるようにと考えています。

終わりに

今回はマイクロサービスを量産するための基盤作りのプロジェクトを紹介させていただきました。

enechainではサービス開発のみではなく、100兆円規模のエネルギー市場を支えるサービスとなるため、未来の運用を見据えた基盤開発への投資も行っております。

Application Platform Deskでは、今回のような取り組みを始めとして、将来に向けて様々な仕組みやサービス基盤を作成しています。興味がありましたら、話を聞いてみるだけでも良いので、下記リンクからご応募ください。

enechainでは、日本のエネルギーインフラを支えるプロダクトを共に作っていける仲間を募集しています。

herp.careers herp.careers