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

Reply via email to