chetanmeh opened a new pull request #4556: Execute OpenWhisk action via Ignite and Firecracker VM URL: https://github.com/apache/incubator-openwhisk/pull/4556 This is a proof of concept to execute OpenWhisk actions via [Weave Ignite][1] which uses [Firecracker MicroVMs][2] Recently [Weave works announced Ignite][3] project which supports running compatible docker images as [Firecracker MicroVMs][4]. Such an execution can provide better security compared to simple container based execution. ## Objective Some of the key aspects here are 1. Rebuild OpenWhisk runtime as Ignote compatible docker image 2. Execute action via vm build from those images ## Usage ### 1. Install Ignite Follow the [Ignite installation steps][6] and ensure that required [dependencies][7] are met. OpenWhisk would check for `ignite` cli at `/usr/local/bin/ignite` ### 2. Build a Ignite compatible docker image for nodejs. Currently a docker file is provided for nodejs 12 [here][5] ```bash $ cd tools/ignite/nodejs $ docker build -t whisk/ignite-nodejs-v12:latest . ``` ### 3. Build the standalone OpenWhisk ```bash $ ./gradlew :core:standalone:build ``` ### 4. Start the server Start the server passing a custom runtime manifest which refers to new nodejs docker image build in previous steps ``` $ sudo java -Dwhisk.spi.ContainerFactoryProvider=org.apache.openwhisk.core.containerpool.ignite.IgniteContainerFactoryProvider \ -jar bin/openwhisk-standalone.jar \ -m tools/ignite/ignite-runtimes.json ``` Note that this is run with `sudo` as `ignite` needs root access to run. Once started it would launch 2 pre warm containers (vms!) In startup logs you can see the vm being created ``` [2019-07-12T18:12:07.811Z] [INFO] [#tid_sid_unknown] [IgniteClient] Detected ignite client version Ignite version: version.Info{Major:"0", Minor:"4", GitVersion:"v0.4.0", GitCommit:"e0e7e8c50cd3c6532486625393dff4d415081829", GitTreeState:"clean", BuildDate:"2019-07-10T12:30:11Z", GoVersion:"go1.12.1", Compiler:"gc", Platform:"linux/amd64"} Firecracker version: v0.17.0 [2019-07-12T18:12:08.080Z] [INFO] [#tid_sid_invokerWarmup] [IgniteClient] running /usr/local/bin/ignite -q image import whisk/ignite-nodejs-v12:latest (timeout: 10 minutes) [marker:invoker_ignite.image_start:1384] [2019-07-12T18:12:08.101Z] [INFO] [#tid_sid_invokerWarmup] [IgniteClient] running /usr/local/bin/ignite -q run whisk/ignite-nodejs-v12:latest --cpus 1 --memory 256m --size 1GB --name wsk0_1_prewarm_nodejs12 (timeout: 5 minutes) [marker:invoker_ignite.run_start:1406] ``` Checking running vms ``` # ignite vm ps VM ID IMAGE KERNEL CREATED SIZE CPUS MEMORY STATE IPS PORTS NAME 296c4f2fd75bf834 whisk/ignite-nodejs-v12:latest weaveworks/ignite-kernel:4.19.47 17s ago 1024.0 MB 1 256.0 MB Running 172.17.0.10 wsk0_1_prewarm_nodejs12 e9c77eb3f95e7d7c whisk/ignite-nodejs-v12:latest weaveworks/ignite-kernel:4.19.47 17s ago 1024.0 MB 1 256.0 MB Running 172.17.0.11 wsk0_2_prewarm_nodejs12 ``` There would also be 2 "proxy" docker container for these 2 vm ``` # docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES f94d7c15ed90 weaveworks/ignite:v0.4.0 "/usr/local/bin/igni…" 28 seconds ago Up 24 seconds ignite-e9c77eb3f95e7d7c be939a1e2d5a weaveworks/ignite:v0.4.0 "/usr/local/bin/igni…" 29 seconds ago Up 25 seconds ``` Now you can invoke js action ```json { "namespace": "guest", "name": "hello", "version": "0.0.1", "subject": "guest", "activationId": "1b86c507e4df4b6286c507e4df3b62ea", "start": 1562937307810, "end": 1562937323341, "duration": 15531, "statusCode": 0, "response": { "status": "success", "statusCode": 0, "success": true, "result": { "LANG": "en_US.UTF-8", "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin", "__OW_ACTION_NAME": "/guest/hello", "__OW_ACTIVATION_ID": "1b86c507e4df4b6286c507e4df3b62ea", "__OW_DEADLINE": "1562937383336", "__OW_NAMESPACE": "guest", "payload": "hello, world" } }, "logs": [], "annotations": [ { "key": "path", "value": "guest/hello" }, { "key": "waitTime", "value": 100 }, { "key": "kind", "value": "nodejs:12" }, { "key": "timeout", "value": false }, { "key": "limits", "value": { "concurrency": 1, "logs": 10, "memory": 256, "timeout": 60000 } }, { "key": "initTime", "value": 15526 } ], "publish": false } ``` ## Design This PR adds a new `IgniteContainerFactory` which internally launches the vm and route calls to it. See [Getting started with Ignite][8] to get a quick overview of how ignite works Upon first launch it would 1. Import the image via `ignite image import whisk/ignite-nodejs-v12:latest`. This would implicitly pull the image if not present 2. Create and run the vm `ignite run whisk/ignite-nodejs-v12:latest --cpus 1 --memory 256m --size 1GB --name wsk0_1_prewarm_nodejs12` 3. Connect to the 8080 port of launched vm for actual execution `IgniteContainer` would also figure out the matching docker container running for given vm and use that to make calls as being done with standard Docker implementation. ### Docker Image For any docker image to be usable with `ignite` it must have init system present. For this it provides some [base images][10]. This PR uses there centos image to build a custom nodejs action runtime image ``` FROM openwhisk/action-nodejs-v12:1.14.0-incubating AS ownode FROM weaveworks/ignite-centos RUN curl -sL https://rpm.nodesource.com/setup_10.x | bash - RUN sudo yum -y install nodejs COPY --from=ownode /nodejsAction /nodejsAction COPY --from=ownode /node_modules /node_modules COPY ./action.service /etc/systemd/system/ RUN chmod 664 /etc/systemd/system/action.service \ && systemctl enable action.service ``` ### Service Startup Despite `ignite` use of OCI Image the end result is a vm being launched. So for our action runtime to be launches this docker image also adds a [systemd][10] service ``` [Unit] Description=OpenWhisk Nodejs action server Wants=network-online.target After=network-online.target [Service] WorkingDirectory=/nodejsAction ExecStart=/usr/bin/node --expose-gc app.js [Install] WantedBy=multi-user.target ``` So upon startup of vm the node server would be launched and it would bind to 8080 port. ### Logging Currently `logs` support does not work. For that we need to figure out how to route nodejs logs to vm logs. These logs are then routed to docker logging sub system so we can then fetch it via standard docker log access. ### Things to note Currently the cold start takes long time as for some reason even if vm launches quickly the nodejs server does not respond for some time post start. This aspect would need to be investigated [1]: https://github.com/weaveworks/ignite [2]: https://firecracker-microvm.github.io/ [3]: https://www.weave.works/blog/fire-up-your-vms-with-weave-ignite [4]: https://aws.amazon.com/about-aws/whats-new/2018/11/firecracker-lightweight-virtualization-for-serverless-computing/ [5]: https://github.com/chetanmeh/incubator-openwhisk/tree/ignite/tools/ignite/nodejs [6]: https://github.com/weaveworks/ignite/blob/master/docs/installation.md [7]: https://github.com/weaveworks/ignite/blob/master/docs/dependencies.md [8]: https://github.com/weaveworks/ignite/blob/master/docs/usage.md [9]: https://github.com/weaveworks/ignite#base-images [10]: https://www.freedesktop.org/software/systemd/man/systemd.service.html
---------------------------------------------------------------- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. For queries about this service, please contact Infrastructure at: [email protected] With regards, Apache Git Services
