├── 03-lambda-template ├── xgboost_inference_function │ ├── __init__.py │ ├── requirements.txt │ └── app.py └── template.yaml ├── 02-train-code ├── requirements.txt └── bc_xgboost_train.py ├── images ├── sam-deploy-guided-input.png ├── cloudformation-create-stack-output.png └── cloudformation-describe-stack-output.png ├── CODE_OF_CONDUCT.md ├── LICENSE ├── 04-lambda-test-events └── test-event-1.json ├── .gitignore ├── CONTRIBUTING.md ├── README.md └── 01-setup ├── create-efs-ec2-cfn.yml └── create-efs-ec2-mounted-cfn.yml /03-lambda-template/xgboost_inference_function/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /03-lambda-template/xgboost_inference_function/requirements.txt: -------------------------------------------------------------------------------- 1 | requests -------------------------------------------------------------------------------- /02-train-code/requirements.txt: -------------------------------------------------------------------------------- 1 | xgboost==1.1.1 2 | pandas 3 | sklearn 4 | joblib 5 | -------------------------------------------------------------------------------- /images/sam-deploy-guided-input.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-lambda-serverless-inference/HEAD/images/sam-deploy-guided-input.png -------------------------------------------------------------------------------- /images/cloudformation-create-stack-output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-lambda-serverless-inference/HEAD/images/cloudformation-create-stack-output.png -------------------------------------------------------------------------------- /images/cloudformation-describe-stack-output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aws-samples/aws-lambda-serverless-inference/HEAD/images/cloudformation-describe-stack-output.png -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | ## Code of Conduct 2 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 3 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 4 | opensource-codeofconduct@amazon.com with any additional questions or comments. 5 | -------------------------------------------------------------------------------- /03-lambda-template/xgboost_inference_function/app.py: -------------------------------------------------------------------------------- 1 | import os 2 | import json 3 | import joblib 4 | import xgboost as xgb 5 | import pandas as pd 6 | 7 | model_file_name = os.environ['MODEL_FILE_NAME'] 8 | loaded_model = joblib.load(model_file_name) 9 | 10 | def lambda_handler(event, context): 11 | print("Received event: " + json.dumps(event, indent=2)) 12 | 13 | payload_df = pd.json_normalize([event]) 14 | result = loaded_model.predict(payload_df) 15 | 16 | print("Returning: {}".format(result[0])) 17 | return(json.dumps({"result": result[0]})) 18 | 19 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 7 | the Software, and to permit persons to whom the Software is furnished to do so. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 10 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 11 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 12 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 13 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 14 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 15 | 16 | -------------------------------------------------------------------------------- /04-lambda-test-events/test-event-1.json: -------------------------------------------------------------------------------- 1 | { 2 | "radius_mean": 13.49, 3 | "texture_mean": 22.3, 4 | "perimeter_mean": 86.91, 5 | "area_mean": 561, 6 | "smoothness_mean": 0.08752, 7 | "compactness_mean": 0.07697999999999999, 8 | "concavity_mean": 0.047510000000000004, 9 | "concave points_mean": 0.033839999999999995, 10 | "symmetry_mean": 0.1809, 11 | "fractal_dimension_mean": 0.057179999999999995, 12 | "radius_se": 0.2338, 13 | "texture_se": 1.3530000000000002, 14 | "perimeter_se": 1.735, 15 | "area_se": 20.2, 16 | "smoothness_se": 0.004455, 17 | "compactness_se": 0.013819999999999999, 18 | "concavity_se": 0.02095, 19 | "concave points_se": 0.01184, 20 | "symmetry_se": 0.01641, 21 | "fractal_dimension_se": 0.001956, 22 | "radius_worst": 15.15, 23 | "texture_worst": 31.82, 24 | "perimeter_worst": 99, 25 | "area_worst": 698.8, 26 | "smoothness_worst": 0.1162, 27 | "compactness_worst": 0.1711, 28 | "concavity_worst": 0.2282, 29 | "concave points_worst": 0.1282, 30 | "symmetry_worst": 0.2871, 31 | "fractal_dimension_worst": 0.06917000000000001 32 | } 33 | -------------------------------------------------------------------------------- /02-train-code/bc_xgboost_train.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import pandas as pd 3 | import joblib 4 | 5 | from sklearn.model_selection import train_test_split 6 | import xgboost as xgb 7 | from sklearn.metrics import accuracy_score 8 | 9 | data = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/wdbc.data', header = None) 10 | 11 | # specify columns extracted from wbdc.names 12 | data.columns = ["id","diagnosis","radius_mean","texture_mean","perimeter_mean","area_mean","smoothness_mean", 13 | "compactness_mean","concavity_mean","concave points_mean","symmetry_mean","fractal_dimension_mean", 14 | "radius_se","texture_se","perimeter_se","area_se","smoothness_se","compactness_se","concavity_se", 15 | "concave points_se","symmetry_se","fractal_dimension_se","radius_worst","texture_worst", 16 | "perimeter_worst","area_worst","smoothness_worst","compactness_worst","concavity_worst", 17 | "concave points_worst","symmetry_worst","fractal_dimension_worst"] 18 | 19 | # save the data 20 | data.to_csv("data.csv", sep=',', index=False) 21 | 22 | # print the shape of the data file 23 | print(data.shape) 24 | 25 | y = data["diagnosis"] 26 | X = data.drop(["id", "diagnosis"], axis=1) 27 | X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.20, random_state=42) 28 | 29 | model = xgb.XGBClassifier().fit(X_train, y_train) 30 | 31 | # make prediction 32 | y_pred = model.predict(X_test) 33 | accuracy = accuracy_score(y_test, y_pred) 34 | print("Accuracy: %.2f%%" % (accuracy * 100.0)) 35 | 36 | # save the trained model file 37 | model_file_name = "bc-xgboost-model" 38 | joblib.dump(model, model_file_name) 39 | print("Model file {} saved successfully".format(model_file_name)) 40 | 41 | -------------------------------------------------------------------------------- /03-lambda-template/template.yaml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Transform: AWS::Serverless-2016-10-31 3 | Description: > 4 | serverless-bc-inference 5 | 6 | SAM Template for serverless-bc-inference Lambda function for XGBoost serveless inference 7 | 8 | 9 | Parameters: 10 | SecurityGroupIds: 11 | Type: CommaDelimitedList 12 | Default: sg-0954e57a2a15bee3a 13 | SubnetIDs: 14 | Type: CommaDelimitedList 15 | Description: The list of SubnetIDs in your Virtual Private Cloud (VPC) 16 | Default: subnet-05f266e00a019717f,subnet-032244c407a1536e4,subnet-03c60e04e8dc41d5a 17 | EFSpath: 18 | Type: String 19 | Default: /mnt/inference 20 | AccessPointARN: 21 | Type: String 22 | Description: Access point ARN 23 | Default: arn:aws:elasticfilesystem:us-east-1::access-point/fsap-0f3485a8f4b32a316 24 | 25 | Resources: 26 | XGBoostInferenceFunction: 27 | Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction 28 | Properties: 29 | CodeUri: xgboost_inference_function/ 30 | Handler: app.lambda_handler 31 | Runtime: python3.7 32 | Timeout: 60 33 | MemorySize: 256 34 | VpcConfig: 35 | SecurityGroupIds: !Ref SecurityGroupIds 36 | SubnetIds: !Ref SubnetIDs 37 | FileSystemConfigs: 38 | - Arn: !Ref AccessPointARN 39 | LocalMountPath: !Ref EFSpath 40 | Policies: 41 | - Statement: 42 | - Sid: AWSLambdaVPCAccessExecutionRole 43 | Effect: Allow 44 | Action: 45 | - logs:CreateLogGroup 46 | - logs:CreateLogStream 47 | - logs:PutLogEvents 48 | - ec2:CreateNetworkInterface 49 | - ec2:DescribeNetworkInterfaces 50 | - ec2:DeleteNetworkInterface 51 | Resource: "*" 52 | - Sid: AmazonElasticFileSystemClientFullAccess 53 | Effect: Allow 54 | Action: 55 | - elasticfilesystem:ClientMount 56 | - elasticfilesystem:ClientRootAccess 57 | - elasticfilesystem:ClientWrite 58 | - elasticfilesystem:DescribeMountTargets 59 | Resource: "*" 60 | Environment: 61 | Variables: 62 | PYTHONPATH: /mnt/inference/lib 63 | MODEL_FILE_NAME: /mnt/inference/model/bc-xgboost-model 64 | 65 | Outputs: 66 | XGBoostInferenceFunction: 67 | Description: "XGBoost Inference Lambda Function ARN" 68 | Value: !GetAtt XGBoostInferenceFunction.Arn 69 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | *$py.class 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | .eggs/ 19 | lib/ 20 | lib64/ 21 | parts/ 22 | sdist/ 23 | var/ 24 | wheels/ 25 | share/python-wheels/ 26 | *.egg-info/ 27 | .installed.cfg 28 | *.egg 29 | MANIFEST 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 34 | *.manifest 35 | *.spec 36 | 37 | # Installer logs 38 | pip-log.txt 39 | pip-delete-this-directory.txt 40 | 41 | # Unit test / coverage reports 42 | htmlcov/ 43 | .tox/ 44 | .nox/ 45 | .coverage 46 | .coverage.* 47 | .cache 48 | nosetests.xml 49 | coverage.xml 50 | *.cover 51 | *.py,cover 52 | .hypothesis/ 53 | .pytest_cache/ 54 | cover/ 55 | 56 | # Translations 57 | *.mo 58 | *.pot 59 | 60 | # Django stuff: 61 | *.log 62 | local_settings.py 63 | db.sqlite3 64 | db.sqlite3-journal 65 | 66 | # Flask stuff: 67 | instance/ 68 | .webassets-cache 69 | 70 | # Scrapy stuff: 71 | .scrapy 72 | 73 | # Sphinx documentation 74 | docs/_build/ 75 | 76 | # PyBuilder 77 | .pybuilder/ 78 | target/ 79 | 80 | # Jupyter Notebook 81 | .ipynb_checkpoints 82 | 83 | # IPython 84 | profile_default/ 85 | ipython_config.py 86 | 87 | # pyenv 88 | # For a library or package, you might want to ignore these files since the code is 89 | # intended to run in multiple environments; otherwise, check them in: 90 | # .python-version 91 | 92 | # pipenv 93 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 94 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 95 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 96 | # install all needed dependencies. 97 | #Pipfile.lock 98 | 99 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 100 | __pypackages__/ 101 | 102 | # Celery stuff 103 | celerybeat-schedule 104 | celerybeat.pid 105 | 106 | # SageMath parsed files 107 | *.sage.py 108 | 109 | # Environments 110 | .env 111 | .venv 112 | env/ 113 | venv/ 114 | ENV/ 115 | env.bak/ 116 | venv.bak/ 117 | 118 | # Spyder project settings 119 | .spyderproject 120 | .spyproject 121 | 122 | # Rope project settings 123 | .ropeproject 124 | 125 | # mkdocs documentation 126 | /site 127 | 128 | # mypy 129 | .mypy_cache/ 130 | .dmypy.json 131 | dmypy.json 132 | 133 | # Pyre type checker 134 | .pyre/ 135 | 136 | # pytype static type analyzer 137 | .pytype/ 138 | 139 | # Cython debug symbols 140 | cython_debug/ 141 | 142 | 03-lambda-template/.DS_Store 143 | *.iml 144 | *.xml 145 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing Guidelines 2 | 3 | Thank you for your interest in contributing to our project. Whether it's a bug report, new feature, correction, or additional 4 | documentation, we greatly value feedback and contributions from our community. 5 | 6 | Please read through this document before submitting any issues or pull requests to ensure we have all the necessary 7 | information to effectively respond to your bug report or contribution. 8 | 9 | 10 | ## Reporting Bugs/Feature Requests 11 | 12 | We welcome you to use the GitHub issue tracker to report bugs or suggest features. 13 | 14 | When filing an issue, please check existing open, or recently closed, issues to make sure somebody else hasn't already 15 | reported the issue. Please try to include as much information as you can. Details like these are incredibly useful: 16 | 17 | * A reproducible test case or series of steps 18 | * The version of our code being used 19 | * Any modifications you've made relevant to the bug 20 | * Anything unusual about your environment or deployment 21 | 22 | 23 | ## Contributing via Pull Requests 24 | Contributions via pull requests are much appreciated. Before sending us a pull request, please ensure that: 25 | 26 | 1. You are working against the latest source on the *master* branch. 27 | 2. You check existing open, and recently merged, pull requests to make sure someone else hasn't addressed the problem already. 28 | 3. You open an issue to discuss any significant work - we would hate for your time to be wasted. 29 | 30 | To send us a pull request, please: 31 | 32 | 1. Fork the repository. 33 | 2. Modify the source; please focus on the specific change you are contributing. If you also reformat all the code, it will be hard for us to focus on your change. 34 | 3. Ensure local tests pass. 35 | 4. Commit to your fork using clear commit messages. 36 | 5. Send us a pull request, answering any default questions in the pull request interface. 37 | 6. Pay attention to any automated CI failures reported in the pull request, and stay involved in the conversation. 38 | 39 | GitHub provides additional document on [forking a repository](https://help.github.com/articles/fork-a-repo/) and 40 | [creating a pull request](https://help.github.com/articles/creating-a-pull-request/). 41 | 42 | 43 | ## Finding contributions to work on 44 | Looking at the existing issues is a great way to find something to contribute on. As our projects, by default, use the default GitHub issue labels (enhancement/bug/duplicate/help wanted/invalid/question/wontfix), looking at any 'help wanted' issues is a great place to start. 45 | 46 | 47 | ## Code of Conduct 48 | This project has adopted the [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). 49 | For more information see the [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 50 | opensource-codeofconduct@amazon.com with any additional questions or comments. 51 | 52 | 53 | ## Security issue notifications 54 | 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. 55 | 56 | 57 | ## Licensing 58 | 59 | See the [LICENSE](LICENSE) file for our project's licensing. We will ask you to confirm the licensing of your contribution. 60 | 61 | We may ask you to sign a [Contributor License Agreement (CLA)](http://en.wikipedia.org/wiki/Contributor_License_Agreement) for larger changes. 62 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pay as you go machine learning inference with AWS Lambda 2 | 3 | This repo contains AWS CloudFormation and SAM templates that deploy serverless applications. The applications illustrate how to perform inference with breast cancer XGBoost ML model, and Python packages mounted from EFS. 4 | 5 | For full details on how this works: 6 | - Read the Compute Blog post at: https://aws.amazon.com/blogs/compute/pay-as-you-go-machine-learning-inference-with-aws-lambda/ 7 | 8 | Important: this application uses various AWS services and there are costs associated with these services after the Free Tier usage - please see the [AWS Pricing page](https://aws.amazon.com/pricing/) for details. You are responsible for any AWS costs incurred. No warranty is implied in these examples. 9 | 10 | ```bash 11 | . 12 | ├── README.MD <-- This instructions file 13 | ├── 01-setup <-- Creates VPC, subnets and EFS file system 14 | │ └── create-efs-ec2-cfn.yml <-- CloudFormation template to creates VPC, subnets, EFS file system and EC2 15 | ├── 02-train-code <-- Python code used to train breast cancel XGBoost Model 16 | │ └── requirements.txt <-- Python packages needed for the training and inference 17 | │ └── bc_xgboost_train.py <-- Python file used to train breast cancel XGBoost Model 18 | ├── 03-lambda-template <-- XGBoost inference function example to use VPC and EFS 19 | │ └── xgboost_inference_function <-- Python dependencies and scripts 20 | │ └── template.yaml <-- SAM template 21 | ├── 04-lambda-test-events <-- Lambda test events 22 | │ └── test-event-1.json <-- One sample Lambda test events for Breast Cancer prediction 23 | ``` 24 | 25 | 26 | ## Requirements 27 | 28 | * AWS CLI already configured with Administrator permission 29 | * [Python 3.7.9 installed](https://www.python.org/downloads/release/python-379/) 30 | 31 | ## Installation Instructions 32 | 33 | 1. [Create an AWS account](https://portal.aws.amazon.com/gp/aws/developer/registration/index.html) if you do not already have one and login. 34 | 35 | 1. Clone the repo onto your local development machine using `git clone`. 36 | 37 | ## Setup 38 | **Note that the CloudFormation stack will create all the resources in us-east-1 (N. Virginia)**. 39 | 40 | To create a VPC, subnets, EFS file system, and EC2 launched in the VPC, use the `create-efs-ec2-cfn.yml` in the `01-setup` directory. 41 | 42 | Replace `ParameterValue` with a Key pair name in your AWS account, in order to enable SSH access to the EC2 created. 43 | 44 | To deploy this template, run in a terminal: 45 | 46 | ``` 47 | aws cloudformation create-stack --region us-east-1 \ 48 | --stack-name create-efs-ec2-cfn \ 49 | --template-body file://./create-efs-ec2-cfn.yml\ 50 | --parameters ParameterKey=KeyName,ParameterValue=my_default_ec2 51 | ``` 52 | Note that the `template-body` parameter must include the `file://` prefix when run locally. 53 | 54 | Expected output: 55 | ![cloudformation create-stack output](./images/cloudformation-create-stack-output.png) 56 | 57 | 58 | 59 | You can find VPC settings, list of subnet IDs, and list of access point ARNs created previously by the CloudFormation Stack, in the setup phase, by executing the following CLI command: 60 | ``` 61 | aws cloudformation describe-stacks --region us-east-1\ 62 | --stack-name create-efs-ec2-cfn --query "Stacks[0].Outputs" 63 | ``` 64 | Expected output: 65 | ![cloudformation describe-stack output](./images/cloudformation-describe-stack-output.png) 66 | 67 | ## Deploying the Lambda function 68 | 69 | 1. From the command line, change directory into the `03-lambda-template` directory, then run: 70 | ``` 71 | sam build 72 | sam deploy --guided 73 | ``` 74 | Follow the prompts in the deploy process to set the stack name, AWS Region, security group ID, subnets IDs (comma separated), and Access Point ARN. 75 | 76 | ![sam deploy guided input](./images/sam-deploy-guided-input.png) 77 | 78 | ## How it works 79 | 80 | * The deployed Lambda functions are configured with your VPC and subnet settings. 81 | * The Lambda functions mount the EFS file system you specify. 82 | * Upon invocation, the Lambda function will load the Python Packages and XGBoost model from EFS to run the code that performs the inference. 83 | 84 | ## Testing 85 | 86 | Now you can test your Lambda with the example test event `test-event-1.json` in the `04-lambda-test-events` directory. 87 | 88 | ## Questions? 89 | 90 | Please contact [@e_sela](https://twitter.com/e_sela) or raise an issue on this repo. 91 | 92 | ============================================== 93 | 94 | Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 95 | 96 | SPDX-License-Identifier: MIT-0 -------------------------------------------------------------------------------- /01-setup/create-efs-ec2-cfn.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Description: Create VPC, Subnets, EFS with Access points and EC2. 3 | 4 | Parameters: 5 | KeyName: 6 | Description: Name of an existing EC2 KeyPair to enable SSH access into the EC2 with mounted Access Point 7 | Type: AWS::EC2::KeyPair::KeyName 8 | ConstraintDescription: Must be the name of an existing EC2 KeyPair 9 | 10 | Resources: 11 | MountTargetVPC: 12 | Type: AWS::EC2::VPC 13 | Properties: 14 | EnableDnsSupport: 'true' 15 | EnableDnsHostnames: 'true' 16 | CidrBlock: 10.0.0.0/16 17 | Tags: 18 | - Key: Application 19 | Value: 20 | Ref: AWS::StackId 21 | 22 | InternetGateway: 23 | Type: AWS::EC2::InternetGateway 24 | Properties: 25 | Tags: 26 | - Key: Application 27 | Value: 28 | Ref: AWS::StackName 29 | - Key: Network 30 | Value: Public 31 | 32 | InternetGatewayAttachment: 33 | Type: AWS::EC2::VPCGatewayAttachment 34 | Properties: 35 | VpcId: 36 | Ref: MountTargetVPC 37 | InternetGatewayId: 38 | Ref: InternetGateway 39 | 40 | MountTargetSubnetOne: 41 | Type: AWS::EC2::Subnet 42 | Properties: 43 | CidrBlock: 10.0.1.0/24 44 | VpcId: !Ref MountTargetVPC 45 | AvailabilityZone: "us-east-1a" 46 | MapPublicIpOnLaunch: true 47 | 48 | MountTargetSubnetTwo: 49 | Type: AWS::EC2::Subnet 50 | Properties: 51 | CidrBlock: 10.0.2.0/24 52 | VpcId: !Ref MountTargetVPC 53 | AvailabilityZone: "us-east-1b" 54 | MapPublicIpOnLaunch: true 55 | 56 | MountTargetSubnetThree: 57 | Type: AWS::EC2::Subnet 58 | Properties: 59 | CidrBlock: 10.0.3.0/24 60 | VpcId: !Ref MountTargetVPC 61 | AvailabilityZone: "us-east-1c" 62 | MapPublicIpOnLaunch: true 63 | 64 | PublicRouteTable: 65 | Type: AWS::EC2::RouteTable 66 | Properties: 67 | VpcId: 68 | Ref: MountTargetVPC 69 | 70 | DefaultPublicRoute: 71 | Type: AWS::EC2::Route 72 | DependsOn: InternetGatewayAttachment 73 | Properties: 74 | RouteTableId: !Ref PublicRouteTable 75 | DestinationCidrBlock: 0.0.0.0/0 76 | GatewayId: !Ref InternetGateway 77 | 78 | PublicSubnet1RouteTableAssociation: 79 | Type: AWS::EC2::SubnetRouteTableAssociation 80 | Properties: 81 | RouteTableId: !Ref PublicRouteTable 82 | SubnetId: !Ref MountTargetSubnetOne 83 | 84 | PublicSubnet2RouteTableAssociation: 85 | Type: AWS::EC2::SubnetRouteTableAssociation 86 | Properties: 87 | RouteTableId: !Ref PublicRouteTable 88 | SubnetId: !Ref MountTargetSubnetTwo 89 | 90 | PublicSubnet3RouteTableAssociation: 91 | Type: AWS::EC2::SubnetRouteTableAssociation 92 | Properties: 93 | RouteTableId: !Ref PublicRouteTable 94 | SubnetId: !Ref MountTargetSubnetThree 95 | 96 | 97 | InstanceSecurityGroup: 98 | Type: AWS::EC2::SecurityGroup 99 | Properties: 100 | VpcId: 101 | Ref: MountTargetVPC 102 | GroupName: EfsMountedEC2SG 103 | GroupDescription: Enable SSH access via port 22 104 | SecurityGroupIngress: 105 | - IpProtocol: tcp 106 | FromPort: '22' 107 | ToPort: '22' 108 | CidrIp: 0.0.0.0/0 109 | 110 | MountTargetSecurityGroup: 111 | Type: AWS::EC2::SecurityGroup 112 | Properties: 113 | VpcId: 114 | Ref: MountTargetVPC 115 | GroupDescription: Security group for mount target 116 | SecurityGroupIngress: 117 | - IpProtocol: tcp 118 | FromPort: '2049' 119 | ToPort: '2049' 120 | CidrIp: 0.0.0.0/0 121 | 122 | FileSystemResource: 123 | Type: 'AWS::EFS::FileSystem' 124 | Properties: 125 | PerformanceMode: generalPurpose 126 | Encrypted: true 127 | FileSystemTags: 128 | - Key: Name 129 | Value: MLInferenceFileSystem 130 | 131 | MountTargetResource1: 132 | Type: AWS::EFS::MountTarget 133 | Properties: 134 | FileSystemId: !Ref FileSystemResource 135 | SubnetId: !Ref MountTargetSubnetOne 136 | SecurityGroups: 137 | - !Ref MountTargetSecurityGroup 138 | 139 | MountTargetResource2: 140 | Type: AWS::EFS::MountTarget 141 | Properties: 142 | FileSystemId: !Ref FileSystemResource 143 | SubnetId: !Ref MountTargetSubnetTwo 144 | SecurityGroups: 145 | - !Ref MountTargetSecurityGroup 146 | 147 | MountTargetResource3: 148 | Type: AWS::EFS::MountTarget 149 | Properties: 150 | FileSystemId: !Ref FileSystemResource 151 | SubnetId: !Ref MountTargetSubnetThree 152 | SecurityGroups: 153 | - !Ref MountTargetSecurityGroup 154 | 155 | AccessPointResource: 156 | Type: 'AWS::EFS::AccessPoint' 157 | Properties: 158 | AccessPointTags: 159 | - Key: Name 160 | Value: MLInferenceAccessPoint 161 | FileSystemId: !Ref FileSystemResource 162 | PosixUser: 163 | Uid: "1001" 164 | Gid: "1001" 165 | RootDirectory: 166 | CreationInfo: 167 | OwnerGid: "1001" 168 | OwnerUid: "1001" 169 | Permissions: "755" 170 | Path: "/ml" 171 | 172 | 173 | EfsMountEC2Instance: 174 | Type: AWS::EC2::Instance 175 | Properties: 176 | InstanceType: c5.large 177 | ImageId: ami-0c94855ba95c71c99 178 | KeyName: !Ref "KeyName" 179 | SecurityGroupIds: 180 | - !Ref InstanceSecurityGroup 181 | SubnetId: !Ref MountTargetSubnetOne 182 | Tags: 183 | - Key: Name 184 | Value: xgboost-for-serverless-inference-cfn-ec2 185 | DependsOn: 186 | - FileSystemResource 187 | - AccessPointResource 188 | - MountTargetResource1 189 | 190 | Outputs: 191 | FileSystemID: 192 | Description: File system ID 193 | Value: !Ref FileSystemResource 194 | Export: 195 | Name: !Sub "${AWS::StackName}-FileSystemID" 196 | AccessPointID: 197 | Description: Access Point ID 198 | Value: !Ref AccessPointResource 199 | Export: 200 | Name: !Sub "${AWS::StackName}-AccessPointID" 201 | DefaultSecurityGroup: 202 | Description: Default Security Group 203 | Value: !GetAtt MountTargetVPC.DefaultSecurityGroup 204 | Export: 205 | Name: !Sub "${AWS::StackName}-DefaultSecurityGroup" 206 | MountTargetSubnetOne: 207 | Description: Subnet 1 in the VPC 208 | Value: !Ref MountTargetSubnetOne 209 | Export: 210 | Name: !Sub "${AWS::StackName}-MountTargetSubnetOne" 211 | MountTargetSubnetTwo: 212 | Description: Subnet 2 in the VPC 213 | Value: !Ref MountTargetSubnetTwo 214 | Export: 215 | Name: !Sub "${AWS::StackName}-MountTargetSubnetTwo" 216 | MountTargetSubnetThree: 217 | Description: Subnet 3 in the VPC 218 | Value: !Ref MountTargetSubnetThree 219 | Export: 220 | Name: !Sub "${AWS::StackName}-MountTargetSubnetThree" 221 | MountTargetVPC: 222 | Description: The Mount Target VPC Id 223 | Value: !Ref MountTargetVPC 224 | Export: 225 | Name: !Sub "${AWS::StackName}-MountTargetVPC" 226 | -------------------------------------------------------------------------------- /01-setup/create-efs-ec2-mounted-cfn.yml: -------------------------------------------------------------------------------- 1 | AWSTemplateFormatVersion: '2010-09-09' 2 | Description: Create VPC, Subnets, EFS with Access points and EC2 with the EFS mounted. 3 | 4 | Parameters: 5 | KeyName: 6 | Description: Name of an existing EC2 KeyPair to enable SSH access into the EC2 with mounted Access Point 7 | Type: AWS::EC2::KeyPair::KeyName 8 | ConstraintDescription: Must be the name of an existing EC2 KeyPair 9 | 10 | Resources: 11 | MountTargetVPC: 12 | Type: AWS::EC2::VPC 13 | Properties: 14 | EnableDnsSupport: 'true' 15 | EnableDnsHostnames: 'true' 16 | CidrBlock: 10.0.0.0/16 17 | Tags: 18 | - Key: Application 19 | Value: 20 | Ref: AWS::StackId 21 | 22 | InternetGateway: 23 | Type: AWS::EC2::InternetGateway 24 | Properties: 25 | Tags: 26 | - Key: Application 27 | Value: 28 | Ref: AWS::StackName 29 | - Key: Network 30 | Value: Public 31 | 32 | InternetGatewayAttachment: 33 | Type: AWS::EC2::VPCGatewayAttachment 34 | Properties: 35 | VpcId: 36 | Ref: MountTargetVPC 37 | InternetGatewayId: 38 | Ref: InternetGateway 39 | 40 | MountTargetSubnetOne: 41 | Type: AWS::EC2::Subnet 42 | Properties: 43 | CidrBlock: 10.0.1.0/24 44 | VpcId: !Ref MountTargetVPC 45 | AvailabilityZone: "us-east-1a" 46 | MapPublicIpOnLaunch: true 47 | 48 | MountTargetSubnetTwo: 49 | Type: AWS::EC2::Subnet 50 | Properties: 51 | CidrBlock: 10.0.2.0/24 52 | VpcId: !Ref MountTargetVPC 53 | AvailabilityZone: "us-east-1b" 54 | MapPublicIpOnLaunch: true 55 | 56 | MountTargetSubnetThree: 57 | Type: AWS::EC2::Subnet 58 | Properties: 59 | CidrBlock: 10.0.3.0/24 60 | VpcId: !Ref MountTargetVPC 61 | AvailabilityZone: "us-east-1c" 62 | MapPublicIpOnLaunch: true 63 | 64 | PublicRouteTable: 65 | Type: AWS::EC2::RouteTable 66 | Properties: 67 | VpcId: 68 | Ref: MountTargetVPC 69 | 70 | DefaultPublicRoute: 71 | Type: AWS::EC2::Route 72 | DependsOn: InternetGatewayAttachment 73 | Properties: 74 | RouteTableId: !Ref PublicRouteTable 75 | DestinationCidrBlock: 0.0.0.0/0 76 | GatewayId: !Ref InternetGateway 77 | 78 | PublicSubnet1RouteTableAssociation: 79 | Type: AWS::EC2::SubnetRouteTableAssociation 80 | Properties: 81 | RouteTableId: !Ref PublicRouteTable 82 | SubnetId: !Ref MountTargetSubnetOne 83 | 84 | PublicSubnet2RouteTableAssociation: 85 | Type: AWS::EC2::SubnetRouteTableAssociation 86 | Properties: 87 | RouteTableId: !Ref PublicRouteTable 88 | SubnetId: !Ref MountTargetSubnetTwo 89 | 90 | PublicSubnet3RouteTableAssociation: 91 | Type: AWS::EC2::SubnetRouteTableAssociation 92 | Properties: 93 | RouteTableId: !Ref PublicRouteTable 94 | SubnetId: !Ref MountTargetSubnetThree 95 | 96 | 97 | InstanceSecurityGroup: 98 | Type: AWS::EC2::SecurityGroup 99 | Properties: 100 | VpcId: 101 | Ref: MountTargetVPC 102 | GroupName: EfsMountedEC2SG 103 | GroupDescription: Enable SSH access via port 22 104 | SecurityGroupIngress: 105 | - IpProtocol: tcp 106 | FromPort: '22' 107 | ToPort: '22' 108 | CidrIp: 0.0.0.0/0 109 | 110 | MountTargetSecurityGroup: 111 | Type: AWS::EC2::SecurityGroup 112 | Properties: 113 | VpcId: 114 | Ref: MountTargetVPC 115 | GroupDescription: Security group for mount target 116 | SecurityGroupIngress: 117 | - IpProtocol: tcp 118 | FromPort: '2049' 119 | ToPort: '2049' 120 | CidrIp: 0.0.0.0/0 121 | 122 | FileSystemResource: 123 | Type: 'AWS::EFS::FileSystem' 124 | Properties: 125 | PerformanceMode: generalPurpose 126 | Encrypted: true 127 | FileSystemTags: 128 | - Key: Name 129 | Value: MLInferenceFileSystem 130 | 131 | MountTargetResource1: 132 | Type: AWS::EFS::MountTarget 133 | Properties: 134 | FileSystemId: !Ref FileSystemResource 135 | SubnetId: !Ref MountTargetSubnetOne 136 | SecurityGroups: 137 | - !Ref MountTargetSecurityGroup 138 | 139 | MountTargetResource2: 140 | Type: AWS::EFS::MountTarget 141 | Properties: 142 | FileSystemId: !Ref FileSystemResource 143 | SubnetId: !Ref MountTargetSubnetTwo 144 | SecurityGroups: 145 | - !Ref MountTargetSecurityGroup 146 | 147 | MountTargetResource3: 148 | Type: AWS::EFS::MountTarget 149 | Properties: 150 | FileSystemId: !Ref FileSystemResource 151 | SubnetId: !Ref MountTargetSubnetThree 152 | SecurityGroups: 153 | - !Ref MountTargetSecurityGroup 154 | 155 | AccessPointResource: 156 | Type: 'AWS::EFS::AccessPoint' 157 | Properties: 158 | AccessPointTags: 159 | - Key: Name 160 | Value: MLInferenceAccessPoint 161 | FileSystemId: !Ref FileSystemResource 162 | PosixUser: 163 | Uid: "1001" 164 | Gid: "1001" 165 | RootDirectory: 166 | CreationInfo: 167 | OwnerGid: "1001" 168 | OwnerUid: "1001" 169 | Permissions: "755" 170 | Path: "/ml" 171 | 172 | 173 | EfsMountEC2Instance: 174 | Type: AWS::EC2::Instance 175 | Properties: 176 | InstanceType: c5.large 177 | ImageId: ami-0c94855ba95c71c99 178 | KeyName: !Ref "KeyName" 179 | SecurityGroupIds: 180 | - !Ref InstanceSecurityGroup 181 | SubnetId: !Ref MountTargetSubnetOne 182 | UserData: 183 | Fn::Base64: !Sub | 184 | #!/bin/bash 185 | set -x 186 | exec > >(tee /var/log/user-data.log|logger -t user-data ) 2>&1 187 | # Installing the amazon-efs-utils Package on Amazon Linux 188 | sudo yum -y install amazon-efs-utils 189 | # A directory for our Python packages and model 190 | mkdir -p /home/ec2-user/efs 191 | # Wait for EFS File System to be ready and DNS to propagate 192 | date 193 | echo Waiting for EFS File System to be ready and DNS to propagate 194 | until nslookup ${FileSystemResource}.efs.us-east-1.amazonaws.com; do 195 | sleep 5 196 | done 197 | date 198 | # Mount the EFS file system using Access Point 199 | sudo mount -t efs -o tls,accesspoint=${AccessPointResource} ${FileSystemResource}:/ /home/ec2-user/efs 200 | # Install Python and pip 201 | sudo yum -y install python37 202 | curl -O https://bootstrap.pypa.io/get-pip.py 203 | python3 get-pip.py --user 204 | # Install the required Python packages to be able to train a model and make inference 205 | pip3 install joblib -t /home/ec2-user/efs/lib/ 206 | pip3 install pandas -t /home/ec2-user/efs/lib/ 207 | pip3 install sklearn -t /home/ec2-user/efs/lib/ 208 | pip3 install xgboost==1.1.1 -t /home/ec2-user/efs/lib/ 209 | sudo chown -R ec2-user:ec2-user /home/ec2-user/efs/ 210 | Tags: 211 | - Key: Name 212 | Value: xgboost-for-serverless-inference-cfn-ec2 213 | DependsOn: 214 | - FileSystemResource 215 | - AccessPointResource 216 | - MountTargetResource1 217 | 218 | Outputs: 219 | FileSystemID: 220 | Description: File system ID 221 | Value: !Ref FileSystemResource 222 | Export: 223 | Name: !Sub "${AWS::StackName}-FileSystemID" 224 | AccessPointID: 225 | Description: Access Point ID 226 | Value: !Ref AccessPointResource 227 | Export: 228 | Name: !Sub "${AWS::StackName}-AccessPointID" 229 | DefaultSecurityGroup: 230 | Description: Default Security Group 231 | Value: !GetAtt MountTargetVPC.DefaultSecurityGroup 232 | Export: 233 | Name: !Sub "${AWS::StackName}-DefaultSecurityGroup" 234 | MountTargetSubnetOne: 235 | Description: Subnet 1 in the VPC 236 | Value: !Ref MountTargetSubnetOne 237 | Export: 238 | Name: !Sub "${AWS::StackName}-MountTargetSubnetOne" 239 | MountTargetSubnetTwo: 240 | Description: Subnet 2 in the VPC 241 | Value: !Ref MountTargetSubnetTwo 242 | Export: 243 | Name: !Sub "${AWS::StackName}-MountTargetSubnetTwo" 244 | MountTargetSubnetThree: 245 | Description: Subnet 3 in the VPC 246 | Value: !Ref MountTargetSubnetThree 247 | Export: 248 | Name: !Sub "${AWS::StackName}-MountTargetSubnetThree" 249 | MountTargetVPC: 250 | Description: The Mount Target VPC Id 251 | Value: !Ref MountTargetVPC 252 | Export: 253 | Name: !Sub "${AWS::StackName}-MountTargetVPC" 254 | --------------------------------------------------------------------------------