From 2ac48b3b2d16f86d1ce1d05e060c8cfc4d4b5b6a Mon Sep 17 00:00:00 2001 From: Frank Afriat Date: Sun, 27 Dec 2020 17:52:00 +0200 Subject: [PATCH 1/4] Provide automatic configuration for native compilation using graalvm native-image --- .../META-INF/native-image/jni-config.json | 11 ++++++ .../META-INF/native-image/proxy-config.json | 2 + .../META-INF/native-image/reflect-config.json | 38 +++++++++++++++++++ .../native-image/resource-config.json | 8 ++++ 4 files changed, 59 insertions(+) create mode 100644 aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/jni-config.json create mode 100644 aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/proxy-config.json create mode 100644 aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/reflect-config.json create mode 100644 aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/resource-config.json diff --git a/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/jni-config.json b/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/jni-config.json new file mode 100644 index 00000000..e6c7da3c --- /dev/null +++ b/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/jni-config.json @@ -0,0 +1,11 @@ +[ +{ + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.LambdaRuntimeClientException", + "methods":[{"name":"","parameterTypes":["java.lang.String","int"] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name":"content"}], + "allPublicMethods":true +} +] diff --git a/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/proxy-config.json b/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/proxy-config.json new file mode 100644 index 00000000..0d4f101c --- /dev/null +++ b/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/proxy-config.json @@ -0,0 +1,2 @@ +[ +] diff --git a/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/reflect-config.json b/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/reflect-config.json new file mode 100644 index 00000000..c13cb49a --- /dev/null +++ b/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/reflect-config.json @@ -0,0 +1,38 @@ +[ +{ + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.deser.Deserializers[]" +}, +{ + "name":"com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.ext.Java7SupportImpl", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", + "fields":[{"name":"logger"}] +}, +{ + "name":"example.App", + "allPublicMethods":true +}, +{ + "name":"java.lang.Void", + "methods":[{"name":"","parameterTypes":[] }] +}, +{ + "name":"java.util.Collections$UnmodifiableMap", + "fields":[{"name":"m"}] +}, +{ + "name":"jdk.internal.module.IllegalAccessLogger", + "fields":[{"name":"logger"}] +}, +{ + "name":"sun.misc.Unsafe", + "fields":[{"name":"theUnsafe"}] +}, +{ + "name":"com.amazonaws.services.lambda.runtime.api.client.runtimeapi.InvocationRequest", + "fields":[{"name":"id"}, {"name":"invokedFunctionArn"}, {"name":"deadlineTimeInMs"}, {"name":"xrayTraceId"}, {"name":"clientContext"}, {"name":"cognitoIdentity"}, {"name":"content"}], + "allPublicMethods":true +} +] diff --git a/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/resource-config.json b/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/resource-config.json new file mode 100644 index 00000000..18f4ba9b --- /dev/null +++ b/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/resource-config.json @@ -0,0 +1,8 @@ +{ + "resources":{ + "includes":[ + {"pattern":"\\Qaws-lambda-runtime-interface-client.glibc.so\\E"}, + {"pattern":"\\Qaws-lambda-runtime-interface-client.musl.so\\E"} + ]}, + "bundles":[] +} From 29965bf73b2d5bf192b368a7ecc29988667460ba Mon Sep 17 00:00:00 2001 From: Frank Afriat Date: Tue, 29 Dec 2020 14:11:08 +0200 Subject: [PATCH 2/4] Use native-image.properties --- .../aws-lambda-java-runtime-interface-client}/jni-config.json | 0 .../native-image.properties | 4 ++++ .../reflect-config.json | 4 ---- .../resource-config.json | 0 .../main/resources/META-INF/native-image/proxy-config.json | 2 -- 5 files changed, 4 insertions(+), 6 deletions(-) rename aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/{ => com.amazonaws/aws-lambda-java-runtime-interface-client}/jni-config.json (100%) create mode 100644 aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties rename aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/{ => com.amazonaws/aws-lambda-java-runtime-interface-client}/reflect-config.json (94%) rename aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/{ => com.amazonaws/aws-lambda-java-runtime-interface-client}/resource-config.json (100%) delete mode 100644 aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/proxy-config.json diff --git a/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/jni-config.json b/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json similarity index 100% rename from aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/jni-config.json rename to aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/jni-config.json diff --git a/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties b/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties new file mode 100644 index 00000000..1ca4a3ca --- /dev/null +++ b/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/native-image.properties @@ -0,0 +1,4 @@ +Args = --initialize-at-build-time=jdk.xml.internal.SecuritySupport \ +-H:ReflectionConfigurationResources=${.}/reflect-config.json \ +-H:JNIConfigurationResources=${.}/jni-config.json \ +-H:ResourceConfigurationResources=${.}/resource-config.json diff --git a/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/reflect-config.json b/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json similarity index 94% rename from aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/reflect-config.json rename to aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json index c13cb49a..630a721e 100644 --- a/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/reflect-config.json +++ b/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/reflect-config.json @@ -10,10 +10,6 @@ "name":"com.amazonaws.services.lambda.runtime.LambdaRuntime", "fields":[{"name":"logger"}] }, -{ - "name":"example.App", - "allPublicMethods":true -}, { "name":"java.lang.Void", "methods":[{"name":"","parameterTypes":[] }] diff --git a/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/resource-config.json b/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json similarity index 100% rename from aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/resource-config.json rename to aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/com.amazonaws/aws-lambda-java-runtime-interface-client/resource-config.json diff --git a/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/proxy-config.json b/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/proxy-config.json deleted file mode 100644 index 0d4f101c..00000000 --- a/aws-lambda-java-runtime-interface-client/src/main/resources/META-INF/native-image/proxy-config.json +++ /dev/null @@ -1,2 +0,0 @@ -[ -] From 490913ea97f5f480fad0cb3f945dea1cb447f9ae Mon Sep 17 00:00:00 2001 From: Frank Afriat Date: Thu, 18 Feb 2021 01:09:43 +0200 Subject: [PATCH 3/4] Update RIC Readme for Native Compilation --- .../README.md | 222 +++++++++++++++++- 1 file changed, 219 insertions(+), 3 deletions(-) diff --git a/aws-lambda-java-runtime-interface-client/README.md b/aws-lambda-java-runtime-interface-client/README.md index 180d8eb9..bdadac69 100644 --- a/aws-lambda-java-runtime-interface-client/README.md +++ b/aws-lambda-java-runtime-interface-client/README.md @@ -2,12 +2,12 @@ We have open-sourced a set of software packages, Runtime Interface Clients (RIC), that implement the Lambda [Runtime API](https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.html), allowing you to seamlessly extend your preferred - base images to be Lambda compatible. + base images to be Lambda compatible or to implement your own custom Lambda runtime. The Lambda Runtime Interface Client is a lightweight interface that allows your runtime to receive requests from and send requests to the Lambda service. -You can include this package in your preferred base image to make that base image Lambda compatible. +## Usage 1: Deploy your Lambda as a Container Image without native compilation -## Usage +You can include this package in your preferred base image to make that base image Lambda compatible. ### Creating a Docker Image for Lambda with the Runtime Interface Client @@ -151,6 +151,222 @@ DOCKERHUB_PASSWORD= ``` Recommended way is to set the Docker Hub credentials in CodeBuild job by retrieving them from AWS Secrets Manager. +## Usage 2: Deploy your Lambda with Native Compilation + +You can include this package as a dependency to build your Custom Runtime or to run your Lambda as a Container without any Java Runtime. + +The idea here is to compile natively your java bytecode with [GraalVM](https://www.graalvm.org) [native-image](https://www.graalvm.org/reference-manual/native-image/) to a linux executable file. +In order to ease this native compilation of the Java Runtime Interface Client, the Java RIC jar artifact is now including special configuration files for GraalVM native-image. + +Note: In this example the docker image provided may be used +* For cross compiling only to linux x86-64 and extract the Custom Runtime zip to deploy +* For deploying your Lambda as a Container Image +* For local testing of your Container Image or your native executable. + +### Example: hello-lambda-native project + +Let's take the same Lambda as before: + +src/main/java/example/App.java +```java +package example; + +public class App { + public static String sayHello() { + return "Hello λ!"; + } +} +``` + +This is the needed configuration for native-image for finding the Lambda code: + +src/main/resources/META-INF/native-image/reflect-config.json +```json +[ +{ + "name":"example.App", + "allPublicMethods":true +} +] +``` + +When building a Custom Runtime you need a zip archive containing at root a file named bootstrap that will be the entry point for running your Lambda. In a Container, the same bootstrap file is used as ENTRYPOINT. And finally, it contains also the logic to identify the case of local testing: + +bootstrap +```bash +#!/bin/sh +if [ -z "${AWS_LAMBDA_RUNTIME_API}" ]; then + exec /usr/bin/aws-lambda-rie ./func $1 +else + set -euo pipefail + exec ./func $_HANDLER +fi +``` + +The Dockerfile is slightly more complex to support the three use cases described above: + +Dockerfile +```dockerfile +FROM amazonlinux:2 as base + +FROM base as build +ENV LANG=en_US.UTF-8 +RUN yum update -y && yum install -y gcc gcc-c++ zlib-devel zip tar gzip && yum clean all +RUN curl -4 -L https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-20.3.0/graalvm-ce-java11-linux-amd64-20.3.0.tar.gz -o /tmp/graalvm.tar.gz \ + && tar -zxf /tmp/graalvm.tar.gz -C /tmp \ + && mv /tmp/graalvm-ce-java11-20.3.0 /usr/lib/graalvm \ + && rm -rf /tmp/* +RUN /usr/lib/graalvm/bin/gu install native-image +ENV PATH=/usr/lib/graalvm/bin:${PATH} +ENV JAVA_HOME=/usr/lib/graalvm +RUN yum install -y maven + +# compile the function +WORKDIR /home/app +ADD . . +RUN mvn package + +COPY bootstrap /home/app/ +# (Optional) Add Lambda Runtime Interface Emulator and use a script in the ENTRYPOINT for simpler local runs +ADD https://github.com/aws/aws-lambda-runtime-interface-emulator/releases/latest/download/aws-lambda-rie /home/app/aws-lambda-rie +RUN native-image -jar target/hello-lambda-native-1.0-SNAPSHOT.jar -H:Name=func --no-fallback +RUN yum install -y zip && yum clean all +RUN chmod 755 aws-lambda-rie +RUN chmod 755 bootstrap +RUN chmod 755 func +RUN zip -j function.zip bootstrap func + +FROM base +WORKDIR /function +COPY --from=build /home/app/func /function/func +COPY --from=build /home/app/bootstrap /function/bootstrap +COPY --from=build /home/app/function.zip /function/function.zip +COPY --from=build /home/app/aws-lambda-rie /usr/bin/aws-lambda-rie +ENTRYPOINT [ "/function/bootstrap" ] +CMD [ "example.App::sayHello" ] +``` + +pom.xml +```xml + + 4.0.0 + example + hello-lambda-native + 1.0-SNAPSHOT + + + 11 + 11 + com.amazonaws.services.lambda.runtime.api.client.AWSLambda + + + + + com.amazonaws + aws-lambda-java-runtime-interface-client + 1.0.0 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.6.0 + + ${jdk.version} + ${release.version} + UTF-8 + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.1.2 + + + copy-dependencies + prepare-package + + copy-dependencies + + + + ${project.build.directory}/libs + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.2.0 + + + + true + libs/ + ${exec.mainClass} + + + + + + + + + + +``` + +### Custom Runtime + +just build the image with Docker: + +```bash +docker build -t hello-lambda-native:latest . +``` + +Then extract the Custom Runtime zip deployable bundle with this command: + +```bash +docker cp $(docker create hello-lambda-native:latest):/function/function.zip . +``` + +### Container with native compilation + +just build the image with Docker: + +```bash +docker build -t hello-lambda-native:latest . +``` + +This image can be deployed directly. + +### Local Testing + +just build the image with Docker: + +```bash +docker build -t hello-lambda-native:latest . +``` + +Then you can run the image locally: + +```bash +docker run -p 9000:8080 hello-lambda-native:latest +``` + +And test it from another Terminal/Console with: + +```bash +curl -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" -d '{}' +``` + ## Security If you discover a potential security issue in this project we ask that you notify AWS/Amazon Security via our [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/). Please do **not** create a public github issue. From 5d4aed3cc267304eb5378a2f8a9711b3da84ca2e Mon Sep 17 00:00:00 2001 From: Frank Afriat Date: Thu, 18 Feb 2021 01:11:06 +0200 Subject: [PATCH 4/4] Update README.md --- aws-lambda-java-runtime-interface-client/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aws-lambda-java-runtime-interface-client/README.md b/aws-lambda-java-runtime-interface-client/README.md index bdadac69..65255294 100644 --- a/aws-lambda-java-runtime-interface-client/README.md +++ b/aws-lambda-java-runtime-interface-client/README.md @@ -331,7 +331,7 @@ just build the image with Docker: docker build -t hello-lambda-native:latest . ``` -Then extract the Custom Runtime zip deployable bundle with this command: +Then extract the Custom Runtime deployable zip bundle with this command: ```bash docker cp $(docker create hello-lambda-native:latest):/function/function.zip .