Remove TODO from readme
See GitHub issues.
This commit is contained in:
parent
7b6ce4f1bd
commit
afe415b9e1
2 changed files with 36 additions and 48 deletions
82
README.md
82
README.md
|
|
@ -21,19 +21,20 @@ Runboat has the following main components:
|
||||||
- A controller that performs the following tasks:
|
- A controller that performs the following tasks:
|
||||||
|
|
||||||
- monitor deployments in a kubernetes namespaces to maintain the in-memory database;
|
- monitor deployments in a kubernetes namespaces to maintain the in-memory database;
|
||||||
- on new deployments, trigger an initialization job to create the corresponding
|
- on new deployments, trigger an initialization job to check out the GitHub repo,
|
||||||
postgres database and install the addons in it;
|
install dependencies, create the corresponding postgres database and install the
|
||||||
|
addons in it;
|
||||||
- initialization jobs are started concurrently up to a configured limit;
|
- initialization jobs are started concurrently up to a configured limit;
|
||||||
- when the initialization job succeeds, scale up the deployment, so it becomes
|
- when the initialization job succeeds, scale up the deployment, so it becomes
|
||||||
accessible;
|
accessible;
|
||||||
- when the initializaiton job fails, flag the deployment as failed;
|
- when the initializaiton job fails, flag the deployment as failed;
|
||||||
- when there are too many deployments started, stop the oldest started;
|
- when there are too many deployments started, stop the oldest started;
|
||||||
- when there are too many deployments, delete the oldest created;
|
- when there are too many deployments, delete the oldest created;
|
||||||
- when a deployment is deleted, run a cleanp job to drop the database and delete
|
- when a deployment is deleted, run a cleanup job to drop the database and delete
|
||||||
all kubernetes resources associated with the deployment.
|
all kubernetes resources associated with the deployment.
|
||||||
|
|
||||||
When a deployment is stopped, the corresponding postgres database remains present, so
|
When a deployment is stopped, the corresponding postgres database and filesystem volume
|
||||||
deployments can restart almost instantly.
|
remains present, so deployments can restart almost instantly.
|
||||||
|
|
||||||
This approach allows the deployment of a very large number of builds which consume no
|
This approach allows the deployment of a very large number of builds which consume no
|
||||||
memory nor CPU until they are started. The number of started deployment can also be
|
memory nor CPU until they are started. The number of started deployment can also be
|
||||||
|
|
@ -45,6 +46,11 @@ resource-intensive part of the lifecycle of builds.
|
||||||
All state is stored in kubernetes resources (labels and annotations on deployments). The
|
All state is stored in kubernetes resources (labels and annotations on deployments). The
|
||||||
controller can be stopped and restarted without losing state.
|
controller can be stopped and restarted without losing state.
|
||||||
|
|
||||||
|
All the knowledge about *what* is deployed is in the
|
||||||
|
[src/runboat/kubefiles](./src/runboat/kubefiles) directory. The kubefile must implement
|
||||||
|
a specific contract to be managed by the runboat controller. This contract is described
|
||||||
|
in the [Kubernetes resources](#kubernetes-resources) section below.
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
For running the builds:
|
For running the builds:
|
||||||
|
|
@ -67,27 +73,6 @@ For running the controller (runboat itself):
|
||||||
The controller can be run outside the kubernetes cluster or deployed inside it, or even
|
The controller can be run outside the kubernetes cluster or deployed inside it, or even
|
||||||
in a different cluster.
|
in a different cluster.
|
||||||
|
|
||||||
## Developing
|
|
||||||
|
|
||||||
- setup environment variables (start from `.env.sample`, the meaning of the environment
|
|
||||||
variables is documented in [settings.py](./src/runboat/settings.py))
|
|
||||||
- create a virtualenv, make sure to have pip>=21.3.1 and `pip install -c
|
|
||||||
requirements.txt -e .[test]`
|
|
||||||
- run with `uvicorn runboat.app:app --log-config=log-config.yaml`
|
|
||||||
- api documentation is at `http://localhost:8000/docs`
|
|
||||||
- run tests with `pytest` (environment variables used in tests are declared in
|
|
||||||
`.env.test`)
|
|
||||||
|
|
||||||
## Running in production
|
|
||||||
|
|
||||||
`gunicorn -w 1 -k runboat.uvicorn.RunboatUvicornWorker runboat.app:app`.
|
|
||||||
|
|
||||||
One and only one worker process !
|
|
||||||
|
|
||||||
Gunicorn also necessary so SIGINT/SIGTERM shutdowns after a few seconds. Since we use
|
|
||||||
`run_in_executor`, SIGINT/SIGTERM handling does not work very well, and gunicorn makes
|
|
||||||
it more robust. https://bugs.python.org/issue29309
|
|
||||||
|
|
||||||
## Kubernetes resources
|
## Kubernetes resources
|
||||||
|
|
||||||
All resources to be deployed in kubernetes for a build are in
|
All resources to be deployed in kubernetes for a build are in
|
||||||
|
|
@ -128,36 +113,39 @@ resources:
|
||||||
- it removes the deployment finalizers and deletes resources matching the
|
- it removes the deployment finalizers and deletes resources matching the
|
||||||
`runboat/build` label after the cleanup job succeeded.
|
`runboat/build` label after the cleanup job succeeded.
|
||||||
|
|
||||||
## TODO
|
## Developing
|
||||||
|
|
||||||
Advanced prototype (min required to open the project):
|
- setup environment variables (start from `.env.sample`, the meaning of the environment
|
||||||
|
variables is documented in [settings.py](./src/runboat/settings.py))
|
||||||
|
- create a virtualenv, make sure to have pip>=21.3.1 and `pip install -c
|
||||||
|
requirements.txt -e .[test]`
|
||||||
|
- run with `uvicorn runboat.app:app --log-config=log-config.yaml`
|
||||||
|
- api documentation is at `http://localhost:8000/docs`
|
||||||
|
- run tests with `pytest` (environment variables used in tests are declared in
|
||||||
|
`.env.test`)
|
||||||
|
|
||||||
- plug it on a bunch of OCA and shopinvader repos to test load
|
## Running in production
|
||||||
|
|
||||||
MVP:
|
`gunicorn -w 1 -k runboat.uvicorn.RunboatUvicornWorker runboat.app:app`.
|
||||||
|
|
||||||
- better error handling in API (return 400 on user errors)
|
One and only one worker process is allowed at the moment (although nothing really bad
|
||||||
- more tests
|
should happen if there is more).
|
||||||
- look at other TODO in code to see if anything important remains
|
|
||||||
- basic UI (single page with a combo box to select repo and show builds by branch/pr,
|
|
||||||
with start/stop buttons)
|
|
||||||
- secure github webhooks
|
|
||||||
- deployment and more load testing
|
|
||||||
|
|
||||||
More:
|
Gunicorn also necessary so SIGINT/SIGTERM shutdowns after a few seconds. Since we use
|
||||||
|
`run_in_executor`, SIGINT/SIGTERM handling does not work very well, and gunicorn makes
|
||||||
|
it more robust. https://bugs.python.org/issue29309
|
||||||
|
|
||||||
- streaming build/log and build/init-log api endpoints
|
|
||||||
- shiny UI
|
## Configuration
|
||||||
- websocket stream of build changes, for a dynamic UI
|
|
||||||
- handle PR close (delete all builds for PR)
|
See environment variables examples in [Dockerfile](./Dockerfile),
|
||||||
- handle branch delete (delete all builds for branch)
|
[.env.sample](./.env.sample) and their documentation in
|
||||||
- create builds for all supported repos on startup (goes with sticky branches)
|
[settings.py](./src/runboat/settings.py).
|
||||||
- never undeploy last build of sticky branches
|
|
||||||
- configurable kubefiles directory
|
|
||||||
- even more tests
|
|
||||||
|
|
||||||
## Author and contributors
|
## Author and contributors
|
||||||
|
|
||||||
Authored by Stéphane Bidoul (@sbidoul).
|
Authored by Stéphane Bidoul (@sbidoul).
|
||||||
|
|
||||||
Contributions welcome.
|
Contributions welcome.
|
||||||
|
|
||||||
|
Do not hesitate to reach out for help on how to get started.
|
||||||
|
|
|
||||||
|
|
@ -184,7 +184,7 @@ def _render_kubefiles(deployment_vars: DeploymentVars) -> Generator[Path, None,
|
||||||
__package__, "kubefiles"
|
__package__, "kubefiles"
|
||||||
) as kubefiles_path, tempfile.TemporaryDirectory() as tmp_dir:
|
) as kubefiles_path, tempfile.TemporaryDirectory() as tmp_dir:
|
||||||
tmp_path = Path(tmp_dir)
|
tmp_path = Path(tmp_dir)
|
||||||
# TODO async copytree, or make this whole _runder_kubefiles run_in_executor
|
# TODO async copytree, or make this whole _render_kubefiles run_in_executor
|
||||||
shutil.copytree(kubefiles_path, tmp_path, dirs_exist_ok=True)
|
shutil.copytree(kubefiles_path, tmp_path, dirs_exist_ok=True)
|
||||||
template = Template((tmp_path / "kustomization.yaml.jinja").read_text())
|
template = Template((tmp_path / "kustomization.yaml.jinja").read_text())
|
||||||
(tmp_path / "kustomization.yaml").write_text(
|
(tmp_path / "kustomization.yaml").write_text(
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue