-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #750 from jmikedupont2/patch-1
Update architecture.md
- Loading branch information
Showing
1 changed file
with
64 additions
and
64 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,108 +1,108 @@ | ||
# Architecture | ||
|
||
Currently only available in Japanese. | ||
## Overview | ||
|
||
## 概要 | ||
NeoShowcase is a PaaS (Platform as a Service) that traP members (users) can use. | ||
Here, PaaS refers to a service that runs applications on behalf of users just with the source code of the application and a minimal configuration. | ||
Users manage the source code of their applications on Git and push it to services like GitHub or Gitea. | ||
NeoShowcase automatically detects updates and builds applications according to user settings. | ||
|
||
NeoShowcaseはtraP部員(ユーザー)が利用できるPaaS(Platform as a Service)です。 | ||
ここでのPaaSとは、ユーザーが動かしたいアプリケーションのコードと少しの設定を持ち込むだけで、PaaSがアプリケーションをユーザーの代わりに動かすサービスをいいます。 | ||
ユーザーはGit上で自身のアプリケーションのコードを管理し、GitHubやGiteaなどのサービスにそれをpushすることで、NeoShowcaseが更新を自動で検知し、ユーザーの設定に従ってビルドを行いアプリケーションを動かします。 | ||
One of the major design principles of NeoShowcase is the "reconciliation loop" (also known as the reconciliation pattern, synchronization, eventual consistency, etc.). | ||
This is heavily influenced by the processing method of Kubernetes controllers (in fact, NeoShowcase can also be considered a Kubernetes controller). | ||
In contrast, there is an "event-driven" design, where internal processes are triggered by user actions or external events, and perform some processing which may fire more events. | ||
However, event-driven designs can become complex when events are lost during communication or when processes triggered by events fail or crash. | ||
In contrast, the "reconciliation loop" periodically monitors the system's state and performs "reconciliation" only when it is not in the desired state. | ||
|
||
NeoShowcaseの大きな設計思想の一つに"reconciliation loop"というものがあります(reconciliation pattern, synchronization, eventual consistencyなどとも)。 | ||
これはKubernetesのcontrollerの処理方法に大きく影響を受けています(実際、NeoShowcase自身も一種のcontrollerと呼べるはずです)。 | ||
対比されるものに"イベント駆動"(event-driven)な設計があり、これはユーザーのアクションや外部のイベントなどにより内部のプロセスが起動し、何らかの処理を行い、またさらに必要に応じてイベントを発火するものです。 | ||
しかし、通信中にイベントが失われたり、イベントによって起動された処理が失敗したりクラッシュしたりすると、それのリトライ処理や失敗の処理の方法が複雑になったりします。 | ||
対して"reconciliation loop"では、あるプロセスは一定時間ごとにシステムの状態を監視し、現在の状態が望むものでなかった場合のみ、望む状態になるように処理 "reconciliation" を行います。 | ||
イベント駆動に対して少し計算量は多くなる傾向にありますが、複雑なリトライ処理を考える必要はなく、各プロセスは自身が担当する状態のみを理想状態に持っていくことだけを管理すればよくなるため、処理が簡単になります。 | ||
While the event-driven approach tends to have slightly higher computational overhead, it eliminates the need for complex retry logic. | ||
Each process only needs to bring its responsible state to the desired state, making the logic simpler. | ||
|
||
各コンポーネントは自身の"reconciliation loop"を持っています。 | ||
Each component has its own "reconciliation loop." | ||
|
||
- controller/repository_fetcher: 3分毎またはイベント発生時に、DBからリポジトリ一覧とアプリ一覧を取得、アプリそれぞれが指定するgit refに対応する最新のcommit hashを取得、DBにその値を保存します。 | ||
- これはArgoCDの更新方法に影響を受けています | ||
- > Argo CD polls Git repositories every three minutes to detect changes to the manifests. https://argo-cd.readthedocs.io/en/stable/operator-manual/webhook/ | ||
- controller/continuous_deployment/build_registerer: 3分毎またはイベント発生時に、まだビルドが行われていない(DBにビルド情報がqueueされていない)アプリをリストアップし、必要なビルド情報をDBに"queued"として保存します。 | ||
- controller/continuous_deployment/build_starter: 3分毎またはイベント発生に、接続されているbuilderに次にqueueされたビルドを行うよう指示します。 | ||
- controller/continuous_deployment/build_crash_detector: 1分毎に、builderがクラッシュまたは応答しなくなった場合にそれを検知し、該当ビルドを失敗として記録します。 | ||
- controller/continuous_deployment/deployments_synchronizer: 3分毎またはイベント発生時に、"起動しているべき"アプリそれぞれに対して最新のビルドが終了したかチェックし、その場合はbackendとssgenにsynchronizationを依頼します。 | ||
- controller/backend: dockerまたはk8sのシステムに接続し、実際にコンテナの起動やネットワークの管理を行います。"起動しているべき"アプリの設定一覧を受け取り、実際のシステムの状態がそれと一致するようにコンテナの起動/削除やルーティングを行います。また、ss-genが設定した配信サーバーへルーティングも行います。 | ||
- ss-gen: 3分毎またはイベント発生時に、静的サイトのファイルをStorageからダウンロードし、配信可能なように配置します。 | ||
- controller/repository_fetcher: Every 3 minutes or when an event occurs, it retrieves a list of repositories and applications from the database, fetches the latest commit hash corresponding to the git ref specified by each application, and stores that value in the database. | ||
- This is influenced by the way ArgoCD updates. Argo CD polls Git repositories every three minutes to detect changes to the manifests. https://argo-cd.readthedocs.io/en/stable/operator-manual/webhook/ | ||
- controller/continuous_deployment/build_registerer: Every 3 minutes or when an event occurs, it lists applications that have not been built yet (no build information queued in the database) and saves the necessary build information in the database as "queued." | ||
- controller/continuous_deployment/build_starter: Every 3 minutes or when an event occurs, it instructs connected builders to process the next queued build. | ||
- controller/continuous_deployment/build_crash_detector: Every 1 minute, it detects whether the builder crashed or became unresponsive and records the corresponding build as a failure. | ||
- controller/continuous_deployment/deployments_synchronizer: Every 3 minutes or when an event occurs, it checks whether the latest build has completed for each application whose desired state is "running" and, if so, requests synchronization with backend and ssgen. | ||
- controller/backend: It connects to Docker or Kubernetes and manages the actual containers and network. It receives a list of applications whose desired state is "running" and ensures that the actual system state matches it by starting/terminating containers and configuring routing. It also handles routing to the static file server configured by ss-gen. | ||
- ss-gen: Every 3 minutes or when an event occurs, it downloads static site files from storage and arranges them for delivery. | ||
|
||
以上のように、各コンポーネントは自身が担当する状態のみを監視しそれに専念することで、全体としてはfailureに強いシステムを構築できます。 | ||
In this way, each component monitors only the state it is responsible for and focuses on bringing it to the desired state, resulting in a system that is robust against failures. | ||
|
||
## コンポーネント | ||
## Components | ||
|
||
### traefik-forward-auth | ||
|
||
https://github.com/traPtitech/traefik-forward-auth | ||
|
||
[traefik proxy](https://doc.traefik.io/traefik/) のforward auth middlewareを利用して、ユーザー認証を行います。 | ||
This component performs user authentication using the forward auth middleware of the traefik proxy. | ||
|
||
基本的に、 | ||
It is a simple HTTP server that performs the following: | ||
|
||
- 認証済みなら200 OK | ||
- softの場合は `/_oauth/login` でログイン可能 | ||
- 未認証なら設定されたOAuth/OIDCの認証を行うために307 Temporary Redirect | ||
- OAuth2リクエストではprompt=noneを最初に試すため、認可画面は(ルートドメインごとに)最初の一度だけしか現れない | ||
- If authenticated, return 200 OK. | ||
- In the case of "soft" authentication, login is possible at `/_oauth/login`. | ||
- If not authenticated, perform a 307 Temporary Redirect to carry out OAuth/OIDC authentication set in the configuration. | ||
- It first attempts "prompt=none", so the authorization screen should only appear once per root domain. | ||
|
||
のみを行うHTTPサーバーです。 | ||
細かい挙動はREADMEを見てください。 | ||
For detailed behavior, please refer to the README. | ||
|
||
### Gateway (ns-gateway) | ||
|
||
ユーザーがフロントエンド(dashboard)から直接操作する部分です。 | ||
HTTP/1.1上で既存のproxy認証を利用しつつ、型付きの安全な通信を行うため、[Connect · Simple, reliable, interoperable. A better gRPC.](https://connect.build/) を使用しています。 | ||
This is the part where users operate directly from the front-end (dashboard). | ||
It uses [Connect](https://connect.build/) to perform typed communication while using existing proxy authentication on HTTP/1.1. | ||
|
||
Gatewayというと多数のmicroserviceをまとめるAPI Gatewayがよくありますが、そこまで複雑なAPIでもないため、Gateway自身が全てのAPI操作を担っています。 | ||
|
||
リクエストを受け取り、ControllerやDB、Storageから各種必要な情報を読取ったり、書き込みます。 | ||
Controllerに向けてイベントも発火しますが、このイベントが万が一抜け落ちてもcontroller内部のreconciliation loopによりシステムは自動的に自身の状態を回復します。 | ||
Normally, "API Gateways" often refer to components that aggregate multiple microservices, NeoShowcase's Gateway handles all API operations by itself since NeoShowcase's API is not that complex. | ||
It reads and writes various necessary information from the Controller, DB, and storage. | ||
It also triggers events to the Controller, and even if these events were to be missed, the system would automatically recover to its desired state through the Controller's internal reconciliation loop. | ||
|
||
### Controller (ns-controller) | ||
|
||
NeoShowcaseのコアとなる部分です。 | ||
DBに記述された状態を各サブコンポーネントが監視し、望む状態へと持っていき、最終的にアプリのデプロイを行います。 | ||
Core of NeoShowcase | ||
|
||
It monitors the state in the database, and each subcomponent brings it to the desired state and eventually deploys the application. | ||
|
||
重要なサブコンポーネントの機能は上の記述を参照してください。 | ||
For the functionality of important subcomponents, please refer to the description above. | ||
|
||
### Builder (ns-builder) | ||
|
||
Controllerからビルドの指示を受け取り、実際にOCI Image(docker image)のビルドを行います。 | ||
Receives build instructions from the Controller and performs the build of OCI Images (Docker images). | ||
|
||
現在、ビルド方法は5種類存在します。 | ||
Currently, there are six types of build methods: | ||
|
||
- Runtime (buildpack): [Cloud Native Buildpacks · Cloud Native Buildpacks](https://buildpacks.io/) を用いてruntimeアプリのビルドを行います。一般的なアプリであればzero configでビルドすることも可能です。herokuでも使われているやつです。 | ||
- Runtime (command): ベースイメージ、ビルド時と起動時のコマンド(シェルスクリプト)をそれぞれ直接記述する方式です。 | ||
- Runtime (dockerfile): Dockerfileを指定してビルドする方式です。上2つよりカスタマイズ性が高くなります。 | ||
- Static (command): ベースイメージ、ビルド時のコマンド(シェルスクリプト)、ビルド成果物(artifact)が生成されるパスをそれぞれ直接指定し、静的サイトをビルドする方式です。 | ||
- Static (dockerfile): Dockerfileを指定して静的サイトをビルドする方式です。上のcommand方式よりカスタマイズ性が高くなります。 | ||
- Runtime (buildpack): It uses [Cloud Native Buildpacks](https://buildpacks.io/) to build runtime applications. It can build most common applications with zero config. It's also used in Heroku. | ||
- Runtime (command): This method directly specifies the base image and the commands (shell scripts) for building and running during build. | ||
- Runtime (dockerfile): This method specifies a Dockerfile for building. It offers higher customization than the previous two methods. | ||
- Runtime (buildpack): It uses [Cloud Native Buildpacks](https://buildpacks.io/) and a specified output path to build static applications. | ||
- Static (command): This method directly specifies the base image, build-time command (shell script), and the path where build artifacts are generated, to build static sites. | ||
- Static (dockerfile): This method specifies a Dockerfile for building static sites. It offers higher customization than the command-based approach. | ||
|
||
それぞれのビルド方法に従ってビルドを行い、生成されたイメージをregistryにpushします。 | ||
It performs builds according to each build method and pushes the generated images to the registry. | ||
|
||
### Static-Site Generator (ns-ssgen) | ||
|
||
静的サイトのビルド成果物ファイルを配置し、配信を行うように設定します。 | ||
It places the build artifacts of static sites and configures them for delivery. | ||
|
||
apache httpd, nginx, caddyなどの静的配信プロセスに対して設定を行うように拡張できます。 | ||
It can be extended to configure settings for static delivery processes like Apache HTTPD, Nginx, Caddy, etc. | ||
|
||
### Migrator (ns-migrate) | ||
|
||
データベースのマイグレーションを行います。 | ||
Goのコードすら無く、[sqldef](https://github.com/k0kubun/sqldef) を実行するスクリプトからのみなります。 | ||
Performs database migrations. | ||
Migrator consists of a single shell script that executes [sqldef](https://github.com/k0kubun/sqldef). | ||
|
||
マイグレーション時はまず新旧バージョン両方にcompatibleなスキーマを定義し、先にsqldefを実行してスキーマを変更します。 | ||
その後、手動もしくはコード内から必要なデータを補完していくことで、ゼロダウンタイムでの移行が可能になります。 | ||
If possible, you should first define a schema that is compatible with both the old and new versions. | ||
Then, run this migrator to make schema changes. | ||
Afterward, migrate the necessary data manually or from within the code to perform zero-downtime migration. | ||
|
||
もっとも、NeoShowcaseのアプリ自体はcontrollerの介入が無くても動き続けるため、NeoShowcase自身のHigh Availabilityを保証しなくて良い場合はスキーマがbackwards-compatibleなマイグレーションを行う必要は無いです。 | ||
However, since NeoShowcase's gateway works fine with a short controller downtime, you don't necessarily have to perform migrations that are backward-compatible. | ||
|
||
## 各種バックエンドとの対応 | ||
## Compatibility with Various Backends | ||
|
||
NeoShowcaseは特定のクラウドに依存しないよう、traefikをベースに設計されています。 | ||
各種クラウドのIngress Controllerに対応させることも理論上は可能ですが、実装が多くなって辛いと思います。 | ||
NeoShowcase is designed to be cloud-agnostic, based on traefik. While it's theoretically possible to adapt it to various cloud's Ingress Controllers, implementing it extensively can become challenging. | ||
|
||
| | Docker(traefik) | K8s(traefik) | K8s(Cloud) | | ||
| | Docker(traefik) | K8s(traefik) | K8s(Cloud, not implemented) | | ||
|-----------|-------------------------|---------------------------------------|----------------| | ||
| ルーティング | traefik docker provider | traefik CRD provider | Ingress (未実装) | | ||
| 証明書取得 | traefik Let's encrypt | traefik Let's encrypt or cert-manager | クラウドによる | | ||
| 部員認証 | traefik middleware | traefik middleware | クラウドによる | | ||
| ネットワークの分離 | docker network | NetworkPolicy | クラウドによる | | ||
| コンテナ | docker container | StatefulSet など | StatefulSet など | | ||
| Routing | traefik docker provider | traefik CRD provider | Ingress | | ||
| Certificate Acquisition | traefik Let's encrypt | traefik Let's encrypt or cert-manager | Depends on cloud | | ||
| Member Authentication | traefik middleware | traefik middleware | Depends on cloud | | ||
| Networking | docker network | NetworkPolicy | Depends on cloud | | ||
| Container | docker container | StatefulSet etc. | StatefulSet etc. | |