Sneak Preview of Kabinet #11
Replies: 1 comment
-
Following up on our dicussion on the January 24: We decided to go for an container backend as an App, which would allow to more easily integrate multile backends as well as to allow these backends to spwn container on vastly different resources (e.g. cluster). We especially were focussed on adressing the scenaiours where no "outside-in" communication is possible, which lead to the idea of using an arkitekt app as the backend. Down is a potential implementation of such an App. from arkitekt import register, startup, background
import asyncio
import docker
from typing import List, Dict, Any, Optional
from fakts import get_current_fakts
docker_api = docker.from_env()
class Container:
"""Fake Container Class
This would be a model in the database.
And gotten through graql
"""
pulled: bool = False
status: bool = False
pass
@register
async def pull_container(container: Container) -> Container:
"""A function that is called on startup
When the app starts into a run loop, this function is called
to initialize the app.
"""
print("Pulling Container")
await asyncio.sleep(20)
await container.set_pulled() # in the database
return container
@register
async def start_container(container: Container) -> Container:
"""A function that is called on startup
When the app starts into a run loop, this function is called
to initialize the app.
"""
print("Starting Container")
await container.set_started() # in the database
return container
@register
async def stop_container(container: Container) -> Container:
"""A function that is called on startup
When the app starts into a run loop, this function is called
to initialize the app.
"""
print("Stopping Container")
await container.set_stopped() # in the database
return container
@register(ephemeral=True) #this is not implemented yet, but would mean that
# we won't save the result of this function in the database for provenance
async def inspect_logs(container: Container) -> List[str]:
"""A function that is to inspect the logs of a container"""
print("Stopping Container")
logs = await container.inspect_logs()
return logs
@startup
async def x():
"""A function that is called on startup
When the app starts into a run loop, this function is called
to initialize the app.
"""
print("hello")
running_containers = {}
# We need to check if there are any running containers on each
# startup. If there are, we need to add them to the running_containers
return running_containers
@background
async def syncer(context: Dict[str, Any]):
"""A function that is called on startup
When the app starts into a run loop, this function is called
to initialize the app.
This part will try to sync the local state with the webinterface
and allow the user to inspect
Here we check for new containers that are started and add them to
the webinterface if they are not already added.
and runs in the background as an asyncio task
"""
while True:
containers = docker_api.api.containers.list()
for container in containers:
# Here we should update the container state on the webinterface
# so that the user can see the state of the container, we
# can cache the state here and only update the state if it
# has changed
pass
sync_interval = await get_current_fakts().get("docker.sync_interval")
# Here we have one of the use cases for fakts
# We can get the sync interval from the fakts store
# Which allows use to remotely configure the sync interval
await asyncio.sleep(sync_interval) # This needs to This implementation utilizes the new features of background tasks and startup taks, that allows our backend to continuously update the database (and therefore the frontend) with information about its containers. (Containers will be linked to the app that creates them and only this app can update the state of the container). Utilizing this, we could also now easily create "workflow setup tasks", that would call this app, to run the containers, and once they are started the workflow could start, and as a clean up the containers could be stopped. The biggest hurdle with this in the current state is that we would need a really reliable message protocol between the apps and rekuest (which is already quite stable, but needs to be improved). One big advantage again is that "everything is an app" and all of the services would remain stateless. Any thoughts? |
Beta Was this translation helpful? Give feedback.
-
This discussion is thought as a place to discuss potential implementations and ideas around an "App Store" Interface and UX.
Objective
The current iteration of port is limited in its ability to provide user friendly installations and to let users install the best and optimized
app installation for their underlying hardware (e.g. using an optimized cuda build instead of a cpu build, if there is a graphic card
present, or use a rocm container). The new port version should address this, while providing an adequate abstraction to also allow
different container backends (kubernetes (cluster deployment) or docker (local deployment) seamlessly.
Conceptual Implementation
With the new kabinet server we introduce an App Store like interface to arkitekt. It helps to browse apps on Software Repositories and allows users to install these apps on connected container backends (Apps that can deploy containers). For multi hardware and container tech support we introduce "Flavours" of apps. Flavours represent differently packaged releases of apps, that allow to provide
different docker or other OCI images for different hardware configuration. Which flavour gets deployed depends on the BackendApp configuration and chosen backend, and is (configurabily abstracted away from the user). Developers can specfiy which hardware each images best runs on by specifying "Selectors", which represent a matching strategy for fitting the right image to the underlying hardware. While Selectors resemble closely nodeAffinity and nodeSelectors in Kubernetes, and can be used to defined these in a Port Implementation backed by Kubernetes guarenteeing correct node placements, they also find their equivalent in a docker based system, where flavours that cannot be
matched to the hardware will be ignored in favour of functional.
The building of a flavour is integrated in the Arkitekt CLI (>=0.7.0a5), through the pattern of different builders
which contain their own Dockerfile and selector config.
Creates a default builder
arkitekt port init -f "CUSTOM_FLAVOUR_NAME"
Now creates a custom flavour builder with its own builder in
.arkitekt/flavours/FLAVOUR_NAME/
that can specifythe selectors and Dockerfiles
Will now build all (or selected) docker images associated with the flavours
Allows to publish the docker containers to dockerhub and will create a "deployments.yaml" file that can be pushed
to github to create a repository of the app.
Additionaly when packaging app plugins, an inspection of the defined nodes within the
application will be performed and provided with the metatadata of the deployment. This association will then
allow to search all provided nodes within a repo, no matter if the app is actually installed or run.
Preliminary UI
The new UI should show a little bit more App Store like features like Features Apps and Nodes. This new
UI is currently only available in Widgeto (which is the codename for the new Orkestrator App built around Shadcn/ui
Screencast.from.22-01-24.17.00.04.webm
Also we should probably include some default repositories inside a standard arkitekt installation.
Linked Issues
#10
Beta Was this translation helpful? Give feedback.
All reactions