Skip to content

Latest commit

 

History

History
541 lines (406 loc) · 21.3 KB

3-deploy-aws-lambda.adoc

File metadata and controls

541 lines (406 loc) · 21.3 KB

3. Deploy to AWS Lambda with HTTP API

To deploy this application to AWS Lambda with HTTP API, add a new Quarkus extension(quarkus-amazon-lambda-http) using Quarkus CLI:

quarkus ext add quarkus-amazon-lambda-http

The output should be:

[SUCCESS] ✅  Extension io.quarkus:quarkus-amazon-lambda-http has been installed

You can also search what kinds of extensions are available to install on the working project:

quarkus ext --installable -s aws

The output looks like:

Listing extensions (default action, see --help).
Current Quarkus extensions installable:

✬ ArtifactId                                         Extension Name
✬ camel-quarkus-aws2-athena                          Camel AWS 2 Athena
✬ camel-quarkus-aws2-cw                              Camel AWS 2 CloudWatch
✬ camel-quarkus-aws2-ddb                             Camel AWS 2 DynamoDB
...
✬ quarkus-amazon-lambda                              AWS Lambda
✬ quarkus-amazon-lambda-http                         AWS Lambda HTTP
✬ quarkus-amazon-lambda-rest                         AWS Lambda Gateway REST API
✬ quarkus-amazon-lambda-xray                         AWS Lambda X-Ray
✬ quarkus-amazon-s3                                  Amazon S3
✬ quarkus-amazon-secretsmanager                      Amazon Secrets Manager
✬ quarkus-amazon-ses                                 Amazon SES
✬ quarkus-amazon-sns                                 Amazon SNS
✬ quarkus-amazon-sqs                                 Amazon SQS
✬ quarkus-amazon-ssm                                 Amazon SSM
✬ quarkus-funqy-amazon-lambda                        Funqy AWS Lambda Binding
  quarkus-hibernate-search-orm-elasticsearch-aws     Hibernate Search + Elasticsearch - AWS authentication and request signing

Before we deploy, let’s add a new method and class to expose a new function on AWS Lambda.

Create a new GreetingService.java file in src/main/java/org/acme/. Then copy the following code:

package org.acme;

import jakarta.enterprise.context.ApplicationScoped;

@ApplicationScoped
public class GreetingService {

    public String greeting(String name) {
        return "Enter Serverless Functions with Quarkus, " + name;
    }

}

Update GreetingResource.java file in src/main/java/org/acme/ to inject a CDI bean as well as modifying the return string in hello method:

package org.acme;

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;

@Path("/hello")
public class GreetingResource {

    @Inject
    GreetingService greetingService;

    @GET
    @Path("/greeting/{name}")
    public String greeting(String name) {
        return greetingService.greeting(name);
    }

    @GET
    public String hello() {
        return "Hello Serverless";
    }
}

Verify both a new endpoint(/hello/greeting/{name}) and an existing one(/hello) using HTTPie:

http :8080/hello

The output looks like:

HTTP/1.1 200 OK
Content-Length: 16
Content-Type: text/plain;charset=UTF-8

Hello Serverless

Access another REST API:

http :8080/hello/greeting/daniel

The output looks like:

HTTP/1.1 200 OK
Content-Length: 47
Content-Type: text/plain;charset=UTF-8

Enter Serverless Functions with Quarkus, daniel
Note

You don’t need to stop and re-run the serverless application because Quarkus will reload the changes automatically via the Live Coding feature.

In case you’re stuck when you invoke the REST APIs, make sure to close the Dev UI and restart the Quarkus dev mode.

To mirror the AWS Lambda environment as closely as possible in a dev environment, the Quarkus Amazon Lambda extension boots up a mock AWS Lambda event server in Quarkus Dev and Test mode. This mock event server simulates a true AWS Lambda environment.

While running in Quarkus Dev Mode, you can feed events to it by doing an HTTP POST to http://localhost:8080. The mock event server will receive the events and your lambda will be invoked. You can perform live coding on your lambda and changes will automatically be recompiled and available the next invocation you make.

Furthermore, if you’re still running (or re-run) the continuous testing, you can see the following TEST REPORT in the terminal because you only changed the business application code (e.g. hello()) without the test code.

ERROR [io.qua.test] (Test runner thread) ==================== TEST REPORT #1 ====================
ERROR [io.qua.test] (Test runner thread) Test GreetingResourceTest#testHelloEndpoint() failed
: java.lang.AssertionError: 1 expectation failed.
Response body doesn't match expectation.
Expected: is "Hello from RESTEasy Reactive"
  Actual: Hello Serverless

	at io.restassured.internal.ValidatableResponseImpl.body(ValidatableResponseImpl.groovy)
	at org.acme.GreetingResourceTest.testHelloEndpoint(GreetingResourceTest.java:18)

To fix the test error, update the test case along with the modified hello function. Open the GreetingResourceTest.java file in src/test/java/org/acme directory and replace testHelloEndpoint() method with the following code:

    @Test
    public void testHelloEndpoint() {
        given()
          .when().get("/hello")
          .then()
             .statusCode(200)
             .body(is("Hello Serverless"));
    }

Save the file then go back to the terminal where Quarkus Dev mode is running.

Then, you will see the test case passed as below:

All 1 test is passing (0 skipped), 1 test was run in 828ms. Tests completed at 10:59:56 due to changes to GreetingResourceTest.class.

Stop the Dev Mode using CTRL-C! Package the application using the following Quarkus CLI:

quarkus build --no-tests

or Use maven package command as below:

./mvnw clean package

The output will end with BUILD SUCCESS.

Inspect generated files in the target directory:

  • function.zip - lambda deployment file

  • bootstrap-example.sh - example bootstrap script for native deployments

  • sam.jvm.yaml - (optional) for use with sam cli and local testing

  • sam.native.yaml - (optional) for use with sam cli and native local testing

Note

If you have already tested the function using live coding with Quarkus Dev mode, you can skip the function simulation locally. Then jump into the deployment step.

To simulate the function locally using SAM CLI. The AWS SAM command line interface (CLI) requires you to set AWS credentials so that it can make calls to AWS services on your behalf. Find more information how to set up AWS credentials for SAM CLI here.

Note

You need to run a container runtime(e.g. Docker) to run the SAM emulator.

Open the sam.jvm.yaml file in the target directory. Then, update the Runtime to use Java 17. Currently, Quarkus doesn’t generate the Java17 runtime by default.

Runtime: java17

Save the file. Then, run the following SAM command:

sam local start-api -t target/sam.jvm.yaml

Output should look like:

Mounting EnterServerlessFunction at http://127.0.0.1:3000$default [X-AMAZON-APIGATEWAY-ANY-METHOD]
You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. If you used sam build before running local commands, you will need to re-run sam build for the changes to be picked up. You only need to restart SAM CLI if you update your AWS SAM template
YYYY-MM-SS HH:MM:SS WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:3000
YYYY-MM-SS HH:MM:SS Press CTRL+C to quit

Then, invoke the endpoint like in another terminal:

  • HTTPie:

http http://127.0.0.1:3000/hello/greeting/awslocal
  • Curl:

curl http://127.0.0.1:3000/hello

When you go back to the terminal where the sam local command is running, you will see that the Quarkus application gets started. It takes a few seconds to complete getting ready in Quarkus runtime.

Then, the output should look like:

HTTP/1.0 200 OK
Content-Type: text/plain;charset=UTF-8
Wed, 2 Non 2022 08:01:55 GMT
Server: Werkzeug/1.0.1 Python/3.8.13
content-length: 49

Enter Serverless Functions with Quarkus, awslocal

Stop the local testing by CTRL-C!

Note

You can also use the live coding feature for Lambda functions development locally. Find more information here

If you haven’t already configured AWS credential locally (e.g., ~/.aws/credentials) yet, run the following aws command line:

aws configure

Find more information about Configuration and credential file settings.

Deploy the function to AWS Lambda using SAM CLI:

sam deploy -t target/sam.jvm.yaml -g

Input the configuration for the SAM Deploy with your preferences (e.g., Stack Name: quarkus-function). For example,

Configuring SAM deploy
======================

	Looking for config file [samconfig.toml] :  Not found

	Setting default arguments for 'sam deploy'
	=========================================
	Stack Name [sam-app]: quarkus-function
	AWS Region [us-east-1]:
	#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
	Confirm changes before deploy [y/N]: y
	#SAM needs permission to be able to create roles to connect to the resources in your template
	Allow SAM CLI IAM role creation [Y/n]: y
	#Preserves the state of previously provisioned resources when an operation fails
	Disable rollback [y/N]: n
	EnterServerlessFunction may not have authorization defined, Is this okay? [y/N]: y
	Save arguments to configuration file [Y/n]: y
	SAM configuration file [samconfig.toml]:
	SAM configuration environment [default]:
...
Note

If you have a S3 Bucket does not exist error, you probably have old CloudFormation Stack that looks up to the aws-sam-cli-managed-default-samclisourcebucket service. In that case, Go to CloundFormation Service in the AWS portal. Then, delete aws-sam-cli-managed-default stack.

Then, you might need to confirm your configurations as below:

CloudFormation stack changeset
-------------------------------------------------------------------------------------------------------------------------------------
Operation                         LogicalResourceId                 ResourceType                      Replacement
-------------------------------------------------------------------------------------------------------------------------------------
+ Add                             EnterServerlessFunctionsHttpApi   AWS::Lambda::Permission           N/A
                                  EventPermission
+ Add                             EnterServerlessFunctionsRole      AWS::IAM::Role                    N/A
+ Add                             EnterServerlessFunctions          AWS::Lambda::Function             N/A
+ Add                             ServerlessHttpApiApiGatewayDefa   AWS::ApiGatewayV2::Stage          N/A
                                  ultStage
+ Add                             ServerlessHttpApi                 AWS::ApiGatewayV2::Api            N/A
-------------------------------------------------------------------------------------------------------------------------------------

Changeset created successfully. arn:aws:cloudformation:us-east-1:716861016243:changeSet/samcli-deploy1633488868/1e632117-3395-4b76-8037-bc6529ace78d


Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]:

Press y then you will receive the outputs by CloudFormation in a few minutes. It should look like:

CloudFormation events from changeset
-------------------------------------------------------------------------------------------------------------------------------------
ResourceStatus                    ResourceType                      LogicalResourceId                 ResourceStatusReason
-------------------------------------------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS                AWS::IAM::Role                    EnterServerlessFunctionsRole      Resource creation Initiated
CREATE_IN_PROGRESS                AWS::IAM::Role                    EnterServerlessFunctionsRole      -
CREATE_COMPLETE                   AWS::IAM::Role                    EnterServerlessFunctionsRole      -
CREATE_IN_PROGRESS                AWS::Lambda::Function             EnterServerlessFunctions          -
CREATE_IN_PROGRESS                AWS::Lambda::Function             EnterServerlessFunctions          Resource creation Initiated
CREATE_COMPLETE                   AWS::Lambda::Function             EnterServerlessFunctions          -
CREATE_IN_PROGRESS                AWS::ApiGatewayV2::Api            ServerlessHttpApi                 -
CREATE_COMPLETE                   AWS::ApiGatewayV2::Api            ServerlessHttpApi                 -
CREATE_IN_PROGRESS                AWS::ApiGatewayV2::Api            ServerlessHttpApi                 Resource creation Initiated
CREATE_IN_PROGRESS                AWS::Lambda::Permission           EnterServerlessFunctionsHttpApi   Resource creation Initiated
                                                                    EventPermission
CREATE_IN_PROGRESS                AWS::Lambda::Permission           EnterServerlessFunctionsHttpApi   -
                                                                    EventPermission
CREATE_IN_PROGRESS                AWS::ApiGatewayV2::Stage          ServerlessHttpApiApiGatewayDefa   -
                                                                    ultStage
CREATE_COMPLETE                   AWS::ApiGatewayV2::Stage          ServerlessHttpApiApiGatewayDefa   -
                                                                    ultStage
CREATE_IN_PROGRESS                AWS::ApiGatewayV2::Stage          ServerlessHttpApiApiGatewayDefa   Resource creation Initiated
                                                                    ultStage
CREATE_COMPLETE                   AWS::Lambda::Permission           EnterServerlessFunctionsHttpApi   -
                                                                    EventPermission
CREATE_COMPLETE                   AWS::CloudFormation::Stack        quarkus-function                  -
-------------------------------------------------------------------------------------------------------------------------------------

CloudFormation outputs from deployed stack
----------------------------------------------------------------------------------------------------------------------------------------
Outputs
----------------------------------------------------------------------------------------------------------------------------------------
Key                 EnterServerlessFunctionsApi
Description         URL for application
Value               https://wcji0ss0ge.execute-api.us-east-1.amazonaws.com/
----------------------------------------------------------------------------------------------------------------------------------------

Successfully created/updated stack - quarkus-function in us-east-1
Note

During the sam deploy, CloudFormation template will be created automatically (This is not stored in target directory though). Then you can monitor the function in AWS console.

Verify the Function in AWS Console

Go to AWS Console then navigate the following resources if they are automatically created along with the Quarkus function.

AWS API Gateway

A new API gateway(e.g., quarkus-function) will show up when you specified it during the SAM deployment:

aws-gateapi

AWS Identity and Access Management (IAM)

A new role for the Quarkus function will show up:

aws-iam

AWS Lambda

A new Quarkus function will show up:

aws-function

When you click on the function name, you can see the details such as package sizes as well as testing the function:

aws-function-detail

Access the function via HTTP gateway API URL. For example:

http https://wcji0ss0ge.execute-api.us-east-1.amazonaws.com/hello/greeting/awsprod

The output should look like:

HTTP/1.1 200 OK
Apigw-Requestid: EUxSijdzoAMEJ4w=
Connection: keep-alive
Content-Length: 48
Content-Type: text/plain;charset=UTF-8
Date: Wed, 03 May 2023 02:37:20 GMT

Enter Serverless Functions with Quarkus, awsprod

Deploy a native executable to AWS Lambda. Package the application once again using the following command:

Note

When you build a native executable on macOS or Windows, you need to add the following configuration in src/main/resources/application.properties for building a Linux format image using Docker runtime

quarkus.native.container-runtime=docker
quarkus build --native --no-tests

Or you can run the following maven command:

 ./mvnw clean package -DskipTests -Pnative

Once the build is complete, run the SAM CLI to deploy it using the following command. It takes a few minutes to complete the build:

sam deploy -t target/sam.native.yaml -g

Key a different stack name (quarkus-native-function) in the prompt:

	Looking for config file [samconfig.toml] :  Not found

	Setting default arguments for 'sam deploy'
	=========================================
	Stack Name [quarkus-function]: quarkus-native-function
	AWS Region [us-east-1]:
	#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
	Confirm changes before deploy [Y/n]: y
	#SAM needs permission to be able to create roles to connect to the resources in your template
	Allow SAM CLI IAM role creation [Y/n]: y
	#Preserves the state of previously provisioned resources when an operation fails
	Disable rollback [y/N]: n
	EnterServerlessFunctionNative may not have authorization defined, Is this okay? [y/N]: y
	Save arguments to configuration file [Y/n]: y
	SAM configuration file [samconfig.toml]:
	SAM configuration environment [default]:
...

Once you deploy it successfully, go back to the AWS console. You have new resources now.

AWS HTTP Gateway API

aws-gateapi2

AWS Lambda

aws-function2

Great job! You can access the new Quarkus native function via the new HTTP Gateway API. For example,

http https://whgv0dgboe.execute-api.us-east-1.amazonaws.com/hello/greeting/awsnativeprod

The output should look like:

HTTP/1.1 200 OK
Apigw-Requestid: T4gs9iu3oAMEMWw
Connection: keep-alive
Content-Length: 54
Content-Type: text/plain;charset=UTF-8
Date: Wed, 2 Nov 2022 20:18:14 GMT

Enter Serverless Functions with Quarkus, awsnativeprod

You can showcase the performance stats to compare JVM vs. Native function in CloudWatch metrics:

aws-metrics