|
1 |
| -# Blank function (Java) |
| 1 | +# AWS Lambda on Java with CRaC |
2 | 2 |
|
3 |
| - |
| 3 | +This is an example of a Java AWS Lambda that uses Project CRaC to reduce the cost and time of the first function invocation. |
4 | 4 |
|
5 |
| -The project source includes function code and supporting resources: |
| 5 | +Based on https://github.com/awsdocs/aws-lambda-developer-guide/tree/main/sample-apps/blank-java. |
6 | 6 |
|
7 |
| -- `src/main` - A Java function. |
8 |
| -- `src/test` - A unit test and helper classes. |
9 |
| -- `template.yml` - An AWS CloudFormation template that creates an application. |
10 |
| -- `build.gradle` - A Gradle build file. |
11 |
| -- `pom.xml` - A Maven build file. |
12 |
| -- `1-create-bucket.sh`, `2-build-layer.sh`, etc. - Shell scripts that use the AWS CLI to deploy and manage the application. |
| 7 | +In this example the function will be packed as the [container image](https://docs.aws.amazon.com/lambda/latest/dg/gettingstarted-images.html#gettingstarted-images-package) together with JDK CRaC runtime and the CRaC image. |
13 | 8 |
|
14 |
| -Use the following instructions to deploy the sample application. |
| 9 | +The CRaC image with the snapshot of JVM and application states will be preparied with the help of [AWS Runtime Interface Emulator](https://github.com/aws/aws-lambda-runtime-interface-emulator). |
15 | 10 |
|
16 |
| -# Requirements |
17 |
| -- [Java 8 runtime environment (SE JRE)](https://www.oracle.com/java/technologies/javase-downloads.html) |
18 |
| -- [Gradle 5](https://gradle.org/releases/) or [Maven 3](https://maven.apache.org/docs/history.html) |
19 |
| -- The Bash shell. For Linux and macOS, this is included by default. In Windows 10, you can install the [Windows Subsystem for Linux](https://docs.microsoft.com/en-us/windows/wsl/install-win10) to get a Windows-integrated version of Ubuntu and Bash. |
20 |
| -- [The AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-install.html) v1.17 or newer. |
| 11 | +The deployment scheme will be: |
| 12 | +* Create the container image with the function |
| 13 | +* Create the CRaC image: |
| 14 | + * Run the function in the local environment |
| 15 | + * Optionally, warm-up the function |
| 16 | + * Trigger checkpoint to dump the image |
| 17 | +* Create the container image with the function and the image |
| 18 | +* Deploy the container to AWS |
21 | 19 |
|
22 |
| -If you use the AWS CLI v2, add the following to your [configuration file](https://docs.aws.amazon.com/cli/latest/userguide/cli-configure-files.html) (`~/.aws/config`): |
| 20 | + |
| 21 | + |
| 22 | +* [Instruction](#instruction) |
| 23 | + * [Build](#build) |
| 24 | + * [Checkpoint](#checkpoint) |
| 25 | + * [Deploy](#deploy) |
| 26 | + * [Test locally](#test-locally) |
| 27 | + * [Deploy to AWS](#deploy-to-aws) |
| 28 | +* [Techical details](#techical-details) |
| 29 | + |
| 30 | +## Instruction |
| 31 | + |
| 32 | +The repo contain a helper script to perform routine operations. |
| 33 | +Its intended to be "executable documetnation", so the reader is invited to look to the script |
| 34 | + |
| 35 | +The step zero fetches necessary dependencies: |
23 | 36 |
|
24 | 37 | ```
|
25 |
| -cli_binary_format=raw-in-base64-out |
| 38 | +./crac-steps.sh s00_init |
26 | 39 | ```
|
27 | 40 |
|
28 |
| -This setting enables the AWS CLI v2 to load JSON events from a file, matching the v1 behavior. |
| 41 | +### Build |
29 | 42 |
|
30 |
| -# Setup |
31 |
| -Download or clone this repository. |
| 43 | +The function needs to use a fork of [AWS Lambda Java Libraries](https://github.com/CRaC/aws-lambda-java-libs), `pom.xml` was changed to: |
32 | 44 |
|
33 |
| - $ git clone https://github.com/awsdocs/aws-lambda-developer-guide.git |
34 |
| - $ cd aws-lambda-developer-guide/sample-apps/blank-java |
| 45 | +``` |
| 46 | + <dependency> |
| 47 | + <groupId>io.github.crac.com.amazonaws</groupId> |
| 48 | + <artifactId>aws-lambda-java-runtime-interface-client</artifactId> |
| 49 | + <version>1.0.0</version> |
| 50 | + </dependency> |
| 51 | +``` |
35 | 52 |
|
36 |
| -To create a new bucket for deployment artifacts, run `1-create-bucket.sh`. |
| 53 | +Build the app and create the container image for checkpoint (`crac-lambda-checkpoint`): |
| 54 | +``` |
| 55 | +./crac-steps.sh s01_build |
| 56 | +``` |
37 | 57 |
|
38 |
| - blank-java$ ./1-create-bucket.sh |
39 |
| - make_bucket: lambda-artifacts-a5e491dbb5b22e0d |
| 58 | +### Checkpoint |
| 59 | + |
| 60 | +Run the container for checkpoint on the local machine: |
| 61 | + |
| 62 | +``` |
| 63 | +./crac-steps.sh s02_start_checkpoint |
| 64 | +``` |
| 65 | + |
| 66 | +At this point you may provide a workload to warm-up your function, served on port `8080`. |
| 67 | + |
| 68 | +Then trigger checkpoint from another terminal: |
| 69 | +``` |
| 70 | +./crac-steps.sh s03_checkpoint |
| 71 | +``` |
40 | 72 |
|
41 |
| -To build a Lambda layer that contains the function's runtime dependencies, run `2-build-layer.sh`. Packaging dependencies in a layer reduces the size of the deployment package that you upload when you modify your code. |
| 73 | +The former function process should exit, leaving the CRaC image in the `cr` directory. |
42 | 74 |
|
43 |
| - blank-java$ ./2-build-layer.sh |
| 75 | +Create the final container image with the CRaC image (`crac-lambda-restore`): |
44 | 76 |
|
45 |
| -# Deploy |
| 77 | +``` |
| 78 | +./crac-steps.sh s04_prepare_restore |
| 79 | +``` |
46 | 80 |
|
47 |
| -To deploy the application, run `3-deploy.sh`. |
| 81 | +### Deploy |
48 | 82 |
|
49 |
| - blank-java$ ./3-deploy.sh |
50 |
| - BUILD SUCCESSFUL in 1s |
51 |
| - Successfully packaged artifacts and wrote output template to file out.yml. |
52 |
| - Waiting for changeset to be created.. |
53 |
| - Successfully created/updated stack - blank-java |
| 83 | +Now you can deploy `crac-lambda-restore` as the container function to the AWS. |
54 | 84 |
|
55 |
| -This script uses AWS CloudFormation to deploy the Lambda functions and an IAM role. If the AWS CloudFormation stack that contains the resources already exists, the script updates it with any changes to the template or function code. |
| 85 | +You may also check the function locally with RIE. |
56 | 86 |
|
57 |
| -You can also build the application with Maven. To use maven, add `mvn` to the command. |
| 87 | +#### Test locally |
58 | 88 |
|
59 |
| - java-basic$ ./3-deploy.sh mvn |
60 |
| - [INFO] Scanning for projects... |
61 |
| - [INFO] -----------------------< com.example:blank-java >----------------------- |
62 |
| - [INFO] Building blank-java-function 1.0-SNAPSHOT |
63 |
| - [INFO] --------------------------------[ jar ]--------------------------------- |
64 |
| - ... |
| 89 | +You can also test the container locally: |
65 | 90 |
|
66 |
| -# Test |
67 |
| -To invoke the function, run `4-invoke.sh`. |
| 91 | +``` |
| 92 | +./crac-steps.sh s05_local_restore |
| 93 | +``` |
68 | 94 |
|
69 |
| - blank-java$ ./4-invoke.sh |
70 |
| - { |
71 |
| - "StatusCode": 200, |
72 |
| - "ExecutedVersion": "$LATEST" |
73 |
| - } |
| 95 | +From another terminal: |
| 96 | +``` |
| 97 | +./crac-steps.sh "post hi" |
| 98 | +``` |
74 | 99 |
|
75 |
| -Let the script invoke the function a few times and then press `CRTL+C` to exit. |
| 100 | +To test cold start, drop file system caches by: |
| 101 | +``` |
| 102 | +./crac-steps.sh make_cold_local |
| 103 | +``` |
76 | 104 |
|
77 |
| -The application uses AWS X-Ray to trace requests. Open the [X-Ray console](https://console.aws.amazon.com/xray/home#/service-map) to view the service map. |
| 105 | +#### Deploy to AWS |
78 | 106 |
|
79 |
| - |
| 107 | +The helper script can deploy the container, assuming there is a function named `crac-test` configured to use image `crac-test`. |
80 | 108 |
|
81 |
| -Choose a node in the main function graph. Then choose **View traces** to see a list of traces. Choose any trace to view a timeline that breaks down the work done by the function. |
| 109 | +Initialize the evironment: |
| 110 | +``` |
| 111 | +eval $(./crac-steps.sh s06_init_aws) |
| 112 | +``` |
82 | 113 |
|
83 |
| - |
| 114 | +Push the container and update the function: |
| 115 | +``` |
| 116 | +./crac-steps.sh s07_deploy_aws |
| 117 | +``` |
84 | 118 |
|
85 |
| -Finally, view the application in the Lambda console. |
| 119 | +To test cold start, reconfigure the function by: |
| 120 | +``` |
| 121 | +./crac-steps.sh make_cold_aws |
| 122 | +``` |
86 | 123 |
|
87 |
| -*To view the application* |
88 |
| -1. Open the [applications page](https://console.aws.amazon.com/lambda/home#/applications) in the Lambda console. |
89 |
| -2. Choose **blank-java**. |
| 124 | +## Techical details |
90 | 125 |
|
91 |
| -  |
| 126 | +AWS environment restricts features and capabilities for functions in containers: |
| 127 | +* the file system is read-only, except `/tmp` |
| 128 | +* setting PID/TIDs for being restored process, `ptrace`, and some other syscalls that are usually required by CRIU are not allowed |
| 129 | +* storage performance is not great |
92 | 130 |
|
93 |
| -# Cleanup |
94 |
| -To delete the application, run `5-cleanup.sh`. |
| 131 | +To overcome storage limits we unpack libjvm.so to /tmp at the start of the container. |
| 132 | +Same is done for CRaC image after it's added to the container image. |
95 | 133 |
|
96 |
| - blank$ ./5-cleanup.sh |
| 134 | +CRaC's build of CRIU attempts to set the PID/TIDs on restore first, in case this functionality is presented. |
| 135 | +When this fails in AWS, it attempts to align the next PID by creating empty do-nothing processes/threads. |
| 136 | +As in the vanilla CRIU, there is strict requirement for PID/TIDs to be available. |
| 137 | +To ensure Java PID/TIDs won't intersect with another processes on restore, checkpoint script ensures Java PID/TIDs are created with a reasonable offset, see [the script](./checkpoint.cmd.sh#L8). |
0 commit comments