Merge pull request #141 from sbidoul/add-start-stop-modes
Add start and stop deployment modes
This commit is contained in:
commit
ab984e1da6
3 changed files with 50 additions and 11 deletions
16
README.md
16
README.md
|
|
@ -104,15 +104,21 @@ kubernetes cluster, or even a different one, depending on your taste.
|
|||
|
||||
All resources to be deployed in kubernetes for a build are in
|
||||
[src/runboat/kubefiles](./src/runboat/kubefiles). They are gathered together from a
|
||||
`kustomization.yaml` jinja template that leads to three possible resource groups
|
||||
`kustomization.yaml` jinja template that leads to 5 possible resource groups
|
||||
depending on a `mode` variable in the jinja rendering context:
|
||||
|
||||
- `deployment` creates a kubernetes deployment with its associated resources (pvc,
|
||||
service, ingress, ...);
|
||||
- `initialization` creates a job that creates the database;
|
||||
- `cleanup` creates a job that drops the database;
|
||||
service, ingress, ...).
|
||||
- `initialization` creates a job that performs installation and initializes the database;
|
||||
- `start` updates the resources before scaling up the deployment to 1. This can be
|
||||
useful to scale up other resources that must only be present while the main
|
||||
deployment is running.
|
||||
- `stop` updates the resources after initialization and before scaling down the
|
||||
deployment to 0. This can be useful to scale down other resources that must
|
||||
only be present while the main deployment is running.
|
||||
- `cleanup` creates a job that perform cleanup before tearing down all resources.
|
||||
|
||||
Besides the three modes, the controller has limited knowledge of what the kubefiles
|
||||
Besides the 5 modes, the controller has limited knowledge of what the kubefiles
|
||||
actually deploy. It expects the following to hold true:
|
||||
|
||||
- the `runboat/build` label is set on all resources, with the unique build name as
|
||||
|
|
|
|||
|
|
@ -138,6 +138,8 @@ class DeploymentMode(str, Enum):
|
|||
deployment = "deployment"
|
||||
initialize = "initialize"
|
||||
cleanup = "cleanup"
|
||||
start = "start"
|
||||
stop = "stop"
|
||||
|
||||
|
||||
class DeploymentVars(BaseModel):
|
||||
|
|
@ -260,6 +262,7 @@ async def delete_deployment_resources(build_name: str) -> None:
|
|||
@sync_to_async
|
||||
def kill_job(build_name: str, job_kind: DeploymentMode) -> None:
|
||||
# TODO delete all resources with runboat/build and runboat/job-kind label
|
||||
assert job_kind in (DeploymentMode.initialize, DeploymentMode.cleanup)
|
||||
batchv1 = client.BatchV1Api()
|
||||
batchv1.delete_collection_namespaced_job(
|
||||
namespace=settings.build_namespace,
|
||||
|
|
|
|||
|
|
@ -195,12 +195,6 @@ class Build(BaseModel):
|
|||
build_settings,
|
||||
)
|
||||
await k8s.deploy(kubefiles_path, deployment_vars)
|
||||
await github.notify_status(
|
||||
commit_info.repo,
|
||||
commit_info.git_commit,
|
||||
GitHubStatusState.pending,
|
||||
target_url=None,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
async def deploy(cls, commit_info: CommitInfo) -> None:
|
||||
|
|
@ -211,6 +205,12 @@ class Build(BaseModel):
|
|||
await cls._deploy(
|
||||
commit_info, name, slug, job_kind=k8s.DeploymentMode.deployment
|
||||
)
|
||||
await github.notify_status(
|
||||
commit_info.repo,
|
||||
commit_info.git_commit,
|
||||
GitHubStatusState.pending,
|
||||
target_url=None,
|
||||
)
|
||||
|
||||
async def start(self) -> None:
|
||||
"""Start build if init succeeded, or reinitialize if failed."""
|
||||
|
|
@ -218,6 +218,12 @@ class Build(BaseModel):
|
|||
_logger.info(f"Ignoring start command for {self} that is {self.status}.")
|
||||
return
|
||||
_logger.info(f"Starting {self} that was last scaled on {self.last_scaled}.")
|
||||
await self._deploy(
|
||||
self.commit_info,
|
||||
self.name,
|
||||
self.slug,
|
||||
job_kind=k8s.DeploymentMode.start,
|
||||
)
|
||||
await self._patch(desired_replicas=1)
|
||||
|
||||
async def stop(self) -> None:
|
||||
|
|
@ -226,6 +232,12 @@ class Build(BaseModel):
|
|||
return
|
||||
_logger.info(f"Stopping {self} that was last scaled on {self.last_scaled}.")
|
||||
await self._patch(desired_replicas=0)
|
||||
await self._deploy(
|
||||
self.commit_info,
|
||||
self.name,
|
||||
self.slug,
|
||||
job_kind=k8s.DeploymentMode.stop,
|
||||
)
|
||||
|
||||
async def undeploy(self) -> None:
|
||||
# To undeploy, we delete the deployment. Due to the finalizer, the deletion
|
||||
|
|
@ -246,6 +258,12 @@ class Build(BaseModel):
|
|||
self.slug,
|
||||
job_kind=k8s.DeploymentMode.deployment,
|
||||
)
|
||||
await github.notify_status(
|
||||
self.commit_info.repo,
|
||||
self.commit_info.git_commit,
|
||||
GitHubStatusState.pending,
|
||||
target_url=None,
|
||||
)
|
||||
|
||||
async def initialize(self) -> None:
|
||||
"""Launch the initialization job."""
|
||||
|
|
@ -300,6 +318,12 @@ class Build(BaseModel):
|
|||
# is restarting, and is notified of existing initialization jobs.
|
||||
return
|
||||
_logger.info(f"Initialization job succeded for {self}, ready to start.")
|
||||
await self._deploy(
|
||||
self.commit_info,
|
||||
self.name,
|
||||
self.slug,
|
||||
job_kind=k8s.DeploymentMode.stop,
|
||||
)
|
||||
if await self._patch(init_status=BuildInitStatus.succeeded):
|
||||
await github.notify_status(
|
||||
self.commit_info.repo,
|
||||
|
|
@ -314,6 +338,12 @@ class Build(BaseModel):
|
|||
# restarting, and is notified of existing initialization jobs.
|
||||
return
|
||||
_logger.info(f"Initialization job failed for {self}.")
|
||||
await self._deploy(
|
||||
self.commit_info,
|
||||
self.name,
|
||||
self.slug,
|
||||
job_kind=k8s.DeploymentMode.stop,
|
||||
)
|
||||
if await self._patch(init_status=BuildInitStatus.failed, desired_replicas=0):
|
||||
await github.notify_status(
|
||||
self.commit_info.repo,
|
||||
|
|
|
|||
Loading…
Reference in a new issue