-
Notifications
You must be signed in to change notification settings - Fork 27
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
✨Run dynamic services via dynamic-sidecar (🏗️ OPS + CI action) #1887
✨Run dynamic services via dynamic-sidecar (🏗️ OPS + CI action) #1887
Conversation
Codecov Report
@@ Coverage Diff @@
## master #1887 +/- ##
========================================
+ Coverage 70.0% 76.1% +6.0%
========================================
Files 574 579 +5
Lines 21654 22147 +493
Branches 2082 2143 +61
========================================
+ Hits 15168 16854 +1686
+ Misses 6017 4713 -1304
- Partials 469 580 +111
Flags with carried forward coverage won't be shown. Click here to find out more.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In order to comply with osparc-simcore conventions, I highly recommend you to create this new service from one of our cookiecutters. You can always run it in a different folder and copy&paste the pieces you want. In any case, by just answering the questions , it would produce something with all little details correct
For aiohttp-based services we have this
https://github.com/ITISFoundation/cookiecutter-simcore-pyservice
For fastapi-base service (probably you need thisone) I started creating this (not completely finished but almost)
https://github.com/pcrespov/cookiecutter-simcore-py-fastapi
This comment has been minimized.
This comment has been minimized.
Regarding my above post, please comment, edit and contribute. I would like some feedback @pcrespov @sanderegg @mguidon |
This comment has been minimized.
This comment has been minimized.
I just read through your documentation. I think you are trying to solve too many problems at once. I would suggest to ignore the scheduling and the "bring the service to the data" aspects for now and concentrate on replacing the way we create dynamic services. Take for instance the sim4life application which currently consists of two docker images and make sure this works. I agree with Sylvain that for a starter, let the director create the sidecar service in the swarm and then the sidecar can spawn the dynamic services using the forwarded docker socket. |
And a question regarding |
I've previously checked with @Surfict and issuing a wildcard certificate for |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will define the concept of a service-sidecar which is nothing more then a service running as an interface between the oSPARC platform and dynamic service itself.
OK
The dynamic service will not have access to the services inside the oSPARC platform, it will be placed on a separate network together with the service-sidecar and a reverse proxy.
OK
The reverse proxy's job is to make the service visible from the outside world on address similar to: uuid.services.osparc.io removing the need of supporting /x/uuid and all the issues its issues
- Less intrusive: Avoids enforcing the dynamic services to serve in a specific base-url. Sometimes the service did not implement this as an option and we had to modify the service code!
- Access Layer: Can be used to add an auth access layer which is currently missing. This somehow needs to be connected with the auth module which is currently in the web-server (it is asking to have it’s own service!)
Setup
- I like more the pod pattern that SAN proposes. Essentially it performs a similar setup as you describe above but It seems to me more compact. Resources are reserved in one go and the ability to deploy like docker-compose for development/testing the dynamic-service in an equivalent context without having to deploy the entire osparc-simcore stack is very powerful. It would even allow integration tests during the submission workflow of new services into the platform.
- How would this setup handle a dynamic-service with multiple containers like s4l that has two containers? Or replicas of the same in case some service has the ability to scale up?
Running with sidecars
- This is the most important part since it will avoid modifying the code of dynamic services which IMO is priority 1!
- SAN definition is more compact: sidecar is responsible of start/stop the dynamic service, push/pull the state of the dynamic service, push/pull the data from the inputs/outputs using a shared volume, monitor the service, get the logs and push them to rabbit (although I could even imagine another sidecar for the logs)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please all new feature should have certain degree of quality testing !
I will continue reviewing ...
services/director-v2/src/simcore_service_director_v2/api/routes/dynamic_sidecar.py
Outdated
Show resolved
Hide resolved
services/director-v2/src/simcore_service_director_v2/api/routes/dynamic_sidecar.py
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some comments... but this is huge...5000 I think the record is broken ;) not possible to go with smaller PR?
Like adding the dynamic sidecar first, with tests, then connections inside the director-v2, etc??
services/director-v2/src/simcore_service_director_v2/modules/service_sidecar/entrypoint.py
Outdated
Show resolved
Hide resolved
services/director-v2/src/simcore_service_director_v2/modules/service_sidecar/entrypoint.py
Outdated
Show resolved
Hide resolved
services/director-v2/src/simcore_service_director_v2/modules/service_sidecar/entrypoint.py
Outdated
Show resolved
Hide resolved
services/director-v2/src/simcore_service_director_v2/modules/service_sidecar/monitor/core.py
Outdated
Show resolved
Hide resolved
services/director-v2/src/simcore_service_director_v2/modules/service_sidecar/monitor/core.py
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here some early comments
services/director-v2/src/simcore_service_director_v2/core/settings.py
Outdated
Show resolved
Hide resolved
services/director-v2/src/simcore_service_director_v2/models/domains/dynamic_sidecar.py
Outdated
Show resolved
Hide resolved
services/director-v2/src/simcore_service_director_v2/models/domains/dynamic_sidecar.py
Outdated
Show resolved
Hide resolved
services/director-v2/src/simcore_service_director_v2/models/domains/dynamic_sidecar.py
Outdated
Show resolved
Hide resolved
services/director-v2/src/simcore_service_director_v2/models/domains/dynamic_sidecar.py
Outdated
Show resolved
Hide resolved
...rector-v2/src/simcore_service_director_v2/modules/dynamic_sidecar/docker_compose_assembly.py
Outdated
Show resolved
Hide resolved
...rector-v2/src/simcore_service_director_v2/modules/dynamic_sidecar/docker_compose_assembly.py
Outdated
Show resolved
Hide resolved
...rector-v2/src/simcore_service_director_v2/modules/dynamic_sidecar/docker_compose_assembly.py
Outdated
Show resolved
Hide resolved
...rector-v2/src/simcore_service_director_v2/modules/dynamic_sidecar/docker_compose_assembly.py
Outdated
Show resolved
Hide resolved
...rector-v2/src/simcore_service_director_v2/modules/dynamic_sidecar/docker_compose_assembly.py
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
some more comments
services/director-v2/src/simcore_service_director_v2/modules/dynamic_sidecar/docker_utils.py
Outdated
Show resolved
Hide resolved
services/director-v2/src/simcore_service_director_v2/modules/dynamic_sidecar/docker_utils.py
Outdated
Show resolved
Hide resolved
services/director-v2/src/simcore_service_director_v2/modules/dynamic_sidecar/docker_utils.py
Outdated
Show resolved
Hide resolved
services/director-v2/src/simcore_service_director_v2/modules/dynamic_sidecar/docker_utils.py
Outdated
Show resolved
Hide resolved
services/director-v2/src/simcore_service_director_v2/modules/dynamic_sidecar/docker_utils.py
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The js part looks good to me 💪
packages/models-library/src/models_library/settings/services_common.py
Outdated
Show resolved
Hide resolved
packages/models-library/src/models_library/settings/services_common.py
Outdated
Show resolved
Hide resolved
services/director-v2/src/simcore_service_director_v2/modules/dynamic_sidecar/client_api.py
Outdated
Show resolved
Hide resolved
services/director-v2/src/simcore_service_director_v2/modules/dynamic_sidecar/client_api.py
Outdated
Show resolved
Hide resolved
...ices/director-v2/src/simcore_service_director_v2/modules/dynamic_sidecar/scheduler/events.py
Outdated
Show resolved
Hide resolved
# If the same message appears in the log multiple times in a row (for the same | ||
# service) something might be wrong with the service. | ||
logger.warning( | ||
"No container present for %s. Usually not an issue.", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not sure that warning is helpful in any ways... you said it takes 50 secs to start the sidecar, does that mean we will see this message 10 times for each services?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GetStatus.action()
will start running after CreateSidecars.action()
runs. Sometimes the containers are not present at that time, on the next iteration the containers are already there.
I wanted a warning message here to help with debugging (especially if something happens in production/staging)
Any suggestions for a better message are welcomed.
...ices/director-v2/src/simcore_service_director_v2/modules/dynamic_sidecar/scheduler/events.py
Outdated
Show resolved
Hide resolved
services/director-v2/tests/integration/02/test_dynamic_services_routes.py
Outdated
Show resolved
Hide resolved
services/web/server/src/simcore_service_webserver/resource_manager/garbage_collector.py
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great! Let's go wild!
🏗️ CI: mark
integration-test-director-v2-01
andintegration-test-director-v2-02
as Required;[int] director-v2
is no longer used🏗️ OPS: must be able to receive network traffic on
UUID.services.DEPLOYMENT_DNS
, a wildcard certificate for*.services.DEPLOYMENT_DNS
is requiredWhat do these changes do?
💣💥Development workflow change‼️
To properly display the content of a dynamic service, the frontend needs to access it via the following DNS
UUID.services.osparc.io
. As IPs do not support subdomains a DNS is always required during local development.NOTE: when starting the the services for development you will be informed with the correct address to open in your browser.
However pleas have a look below for a comparison before the only and new structure of the address:
http://127.0.0.1:9081
old versionhttp://127.0.0.1.nip.io:9081
new versionFor more information on nip.io have a look here.
👀 How the integration with the dynamic-sidecar works
Currently the system will support two types of dynamic services:
director-v0
which should no longer be created from this moment onwardsThe below labels are used to generate services ran via the dynamic-sidecar:
simcore.service.settings
shared with the legacy servicessimcore.service.paths-mapping
required if the service is started via dynamic-sidecar and is what actually gets checked; instructs the dynamic-sidecar where to mount special volumes like the outputs and inputs folderssimcore.service.compose-spec
if provided the dynamic-sidecar will use it instead of generating onesimcore.service.container-http-entrypoint
required whensimcore.service.compose-spec
is present, instructs Treafik to send network traffic to the appropriate container inside the provided docker-compose specPlatform services involved
webserver
receives requests regarding the dynamic service and forwards them to thedirector-v2
director-v2
usingsimcore.service.paths-mapping
label checks if target dynamic service in question is a legacy service, in which case the request is redirected todirector-v0
; otherwise the request is handled by thedirector-v2
director-v0
left virtually untouched, only extended with an endpoint to extract labels from docker images.dynamic-sidecar
is the interface between the oSPARC platform and the dynamic service🔍 A closer look at running via dynamic-sidecar
Dynamic services started via dynamic-sidecar are handled by
director-v2
, which dose the following when a service is started:traefik-proxy
(has access to the oSPARC platform)dynamic-sidecar
(has access to the oSPARC platform); all the resource reservations are summed up and assigned to this servicedynamic-sidecar
is started.dynamic-sidecar
is inrunning
state, it's assigned node id will be recovered and passed as a constraint to thetraefik-proxy
. Both services are guaranteed to be started on the same node. This is required to send traffic to containers started via thedocker-compose up
command by thedynamic-sidecar
. Also please note tha thetraefik-proxy
is running in docker mode and not swarm mode for this reason.monitor
module (part ofdirector-v2
). More about themonitor
:director-v2
stated at boot time and runs in the backgrounddirector-v2
and monitor themmonitor
will check all currently monitoreddynamic-sidecar
are healthy and runapply_monitoring
on each of them. If an error occurs the status of the service will be marked toFAILED
and the fronted will show inside the logs what is wrong with the service.CreateServices
is where:ServicesInspect
fetches the status for each container started by the dynamic-sidecar via API calls to thedynamic-sidecar
service; this information is used to compute the state of the service for the frontendRunDockerComposeUp
checks:dynamic-sidecar
is in arunning
statedynamic-sidecar
to invoke thedocker-compose up
commandwas_compose_spec_submitted
as True, and this step will be no longer executedmonitor
:dynamic-sidecar
is not in arunning
state, the state form the dynamic-sidecar service is mapped to the state that the frontend expectsdynamic-sidecar
is in arunning
state, the task status of all tasks created via thedocker-compose up
command are fetched and mapped to the state that the frontend expects; because multiple containers can be started, the statues are merged and the "lowest state" takes priority, further details can be found inparse_docker_status.py::extract_containers_minimim_statuses
. Example: if container-A is in "running" and container-B is in "pulling", the "pulling" state will be reported.🚧 How to transform a webapp into a dynamic service started via dynamic-sidecar
A service started via the dynamic-sidecar always requires a docker-compose spec. If one is not provided, it will be generated on the fly.
The below show the required
simcore.service
labels.With automatic docker-compose spec generation
Labels for dy-static-file-server-dynamic-sidecar
With provided docker-compose spec
Labels for dy-static-file-server-dynamic-sidecar-compose-spec
Related issues
How to test
Use version
1.0.5
ofdy-static-file-server
,dy-static-file-server-dynamic-sidecar
anddy-static-file-server-dynamic-sidecar-compose
to test if they run. Permissions must be manually granted.Note: it takes longer to start the
dynamic-sidecar
in development mode than in production, packages are installed, sources are mounted and permissions are changed.Checklist
make openapi-specs
,git commit ...
and thenmake version-*
)