From 78787b8e9949ee7ff882066129667873284fda77 Mon Sep 17 00:00:00 2001 From: Oliver Zollikofer Date: Wed, 19 Oct 2022 23:44:00 +0200 Subject: [PATCH 1/2] adding mlops terraform template folder --- mlops-template-terraform/LICENSE.txt | 16 + mlops-template-terraform/README.md | 62 + mlops-template-terraform/mlops_infra/Makefile | 17 + .../mlops_infra/README.md | 53 + .../diagrams/SageMaker_dev_env.png | Bin 0 -> 115097 bytes .../scripts/bootstrap/bootstrap_cfn.yaml | 13 + .../scripts/bootstrap/provider.template | 12 + .../scripts/terraform-account-setup.sh | 33 + .../mlops_infra/terraform/main.tf | 41 + .../mlops_infra/terraform/modules/iam/main.tf | 272 +++ .../terraform/modules/iam/outputs.tf | 3 + .../terraform/modules/iam/terraform.tf | 10 + .../terraform/modules/iam/variables.tf | 9 + .../mlops_infra/terraform/modules/kms/main.tf | 34 + .../terraform/modules/kms/outputs.tf | 11 + .../terraform/modules/kms/terraform.tf | 10 + .../terraform/modules/kms/variables.tf | 5 + .../terraform/modules/networking/main.tf | 306 ++++ .../terraform/modules/networking/outputs.tf | 11 + .../terraform/modules/networking/terraform.tf | 10 + .../terraform/modules/networking/variables.tf | 34 + .../modules/sagemaker_studio/main.tf | 55 + .../scripts/enable-projects.py | 28 + .../sagemaker_studio/scripts/requirements.txt | 1 + .../modules/sagemaker_studio/terraform.tf | 10 + .../modules/sagemaker_studio/variables.tf | 44 + .../mlops_infra/terraform/provider.tf | 12 + .../mlops_templates/Makefile | 17 + .../mlops_templates/README.md | 76 + .../mlops-terraform-template-overview.png | Bin 0 -> 195622 bytes .../diagrams/sm_project_template.png | Bin 0 -> 148115 bytes .../scripts/bootstrap/bootstrap_cfn.yaml | 13 + .../scripts/bootstrap/provider.template | 12 + .../scripts/terraform-account-setup.sh | 35 + .../mlops_templates/terraform/main.tf | 49 + .../sagemaker_project_template/main.tf | 131 ++ .../sagemaker_project_template/terraform.tf | 13 + .../sagemaker_project_template/variables.tf | 33 + .../mlops_templates/terraform/provider.tf | 14 + .../seed_code/.gitkeep | 0 .../seed_code/build_app/.gitignore | 141 ++ .../seed_code/build_app/Makefile | 12 + .../seed_code/build_app/README.md | 14 + .../seed_code/build_app/buildspec.yml | 17 + .../build_app/infra_scripts/bootstrap.sh | 117 ++ .../infra_scripts/bootstrap/provider.template | 12 + .../bootstrap/terraform.tfvars.template | 8 + .../build_app/ml_pipelines/README.md | 7 + .../build_app/ml_pipelines/__init__.py | 30 + .../build_app/ml_pipelines/__version__.py | 26 + .../build_app/ml_pipelines/_utils.py | 91 + .../ml_pipelines/get_pipeline_definition.py | 77 + .../build_app/ml_pipelines/run_pipeline.py | 110 ++ .../build_app/ml_pipelines/training/README.md | 7 + .../ml_pipelines/training/__init__.py | 30 + .../build_app/ml_pipelines/training/_utils.py | 86 + .../ml_pipelines/training/pipeline.py | 331 ++++ .../seed_code/build_app/notebooks/README.md | 4 + ...ocess-train-evaluate-batch-transform.ipynb | 1577 +++++++++++++++++ .../notebooks/sm_pipelines_runbook.ipynb | 538 ++++++ .../seed_code/build_app/requirements-dev.txt | 1 + .../seed_code/build_app/requirements.txt | 2 + .../seed_code/build_app/setup.cfg | 14 + .../seed_code/build_app/setup.py | 77 + .../build_app/source_scripts/Dockerfile | 40 + .../build_app/source_scripts/README.md | 0 .../evaluate/evaluate_xgboost/README.md | 0 .../evaluate/evaluate_xgboost/main.py | 72 + .../evaluate_xgboost/requirements.txt | 0 .../source_scripts/helpers/README.md | 0 .../source_scripts/helpers/logger.py | 16 + .../source_scripts/helpers/requirements.txt | 0 .../source_scripts/helpers/s3_helper.py | 16 + .../source_scripts/helpers/test/test_a.py | 16 + .../prepare_abalone_data/README.md | 0 .../prepare_abalone_data/main.py | 132 ++ .../prepare_abalone_data/requirements.txt | 0 .../source_scripts/training/xgboost/README.md | 0 .../training/xgboost/__main__.py | 16 + .../training/xgboost/requirements.txt | 0 .../training/xgboost/test/test_a.py | 16 + .../seed_code/build_app/terraform/.gitkeep | 0 .../seed_code/build_app/terraform/main.tf | 28 + .../terraform/modules/cicd/codebuild.tf | 118 ++ .../terraform/modules/cicd/codepipeline.tf | 133 ++ .../build_app/terraform/modules/cicd/main.tf | 28 + .../terraform/modules/cicd/outputs.tf | 3 + .../modules/cicd/sagemaker_pipeline.tf | 27 + .../terraform/modules/cicd/terraform.tf | 10 + .../terraform/modules/cicd/variables.tf | 65 + .../build_app/terraform/variables.tf | 42 + .../seed_code/deploy_app/.gitignore | 144 ++ .../deploy_app/.pre-commit-config.yaml | 52 + .../seed_code/deploy_app/Makefile | 19 + .../seed_code/deploy_app/README.md | 29 + .../seed_code/deploy_app/buildspec.yml | 23 + .../deploy_app/infra_scripts/bootstrap.sh | 131 ++ .../infra_scripts/bootstrap/provider.template | 12 + .../bootstrap/terraform.tfvars.template | 10 + .../infra_scripts/get_last_approved_model.py | 44 + .../seed_code/deploy_app/requirements-dev.txt | 1 + .../seed_code/deploy_app/requirements.txt | 1 + .../seed_code/deploy_app/terraform/.gitkeep | 0 .../seed_code/deploy_app/terraform/main.tf | 53 + .../terraform/modules/cicd/codebuild.tf | 150 ++ .../terraform/modules/cicd/codepipeline.tf | 139 ++ .../terraform/modules/cicd/event_bridge.tf | 55 + .../deploy_app/terraform/modules/cicd/main.tf | 26 + .../terraform/modules/cicd/outputs.tf | 4 + .../terraform/modules/cicd/terraform.tf | 10 + .../terraform/modules/cicd/variables.tf | 65 + .../modules/sm_endpoint_slim/README.md | 55 + .../modules/sm_endpoint_slim/main.tf | 52 + .../modules/sm_endpoint_slim/outputs.tf | 3 + .../modules/sm_endpoint_slim/terraform.tf | 9 + .../modules/sm_endpoint_slim/variables.tf | 47 + .../deploy_app/terraform/variables.tf | 71 + .../service_catalog_product_template.yaml.tpl | 63 + .../mlops_templates/terraform/variables.tf | 2 + 119 files changed, 6882 insertions(+) create mode 100644 mlops-template-terraform/LICENSE.txt create mode 100644 mlops-template-terraform/README.md create mode 100644 mlops-template-terraform/mlops_infra/Makefile create mode 100644 mlops-template-terraform/mlops_infra/README.md create mode 100644 mlops-template-terraform/mlops_infra/diagrams/SageMaker_dev_env.png create mode 100644 mlops-template-terraform/mlops_infra/scripts/bootstrap/bootstrap_cfn.yaml create mode 100644 mlops-template-terraform/mlops_infra/scripts/bootstrap/provider.template create mode 100755 mlops-template-terraform/mlops_infra/scripts/terraform-account-setup.sh create mode 100644 mlops-template-terraform/mlops_infra/terraform/main.tf create mode 100644 mlops-template-terraform/mlops_infra/terraform/modules/iam/main.tf create mode 100644 mlops-template-terraform/mlops_infra/terraform/modules/iam/outputs.tf create mode 100644 mlops-template-terraform/mlops_infra/terraform/modules/iam/terraform.tf create mode 100644 mlops-template-terraform/mlops_infra/terraform/modules/iam/variables.tf create mode 100644 mlops-template-terraform/mlops_infra/terraform/modules/kms/main.tf create mode 100644 mlops-template-terraform/mlops_infra/terraform/modules/kms/outputs.tf create mode 100644 mlops-template-terraform/mlops_infra/terraform/modules/kms/terraform.tf create mode 100644 mlops-template-terraform/mlops_infra/terraform/modules/kms/variables.tf create mode 100644 mlops-template-terraform/mlops_infra/terraform/modules/networking/main.tf create mode 100644 mlops-template-terraform/mlops_infra/terraform/modules/networking/outputs.tf create mode 100644 mlops-template-terraform/mlops_infra/terraform/modules/networking/terraform.tf create mode 100644 mlops-template-terraform/mlops_infra/terraform/modules/networking/variables.tf create mode 100644 mlops-template-terraform/mlops_infra/terraform/modules/sagemaker_studio/main.tf create mode 100644 mlops-template-terraform/mlops_infra/terraform/modules/sagemaker_studio/scripts/enable-projects.py create mode 100644 mlops-template-terraform/mlops_infra/terraform/modules/sagemaker_studio/scripts/requirements.txt create mode 100644 mlops-template-terraform/mlops_infra/terraform/modules/sagemaker_studio/terraform.tf create mode 100644 mlops-template-terraform/mlops_infra/terraform/modules/sagemaker_studio/variables.tf create mode 100644 mlops-template-terraform/mlops_infra/terraform/provider.tf create mode 100644 mlops-template-terraform/mlops_templates/Makefile create mode 100644 mlops-template-terraform/mlops_templates/README.md create mode 100644 mlops-template-terraform/mlops_templates/diagrams/mlops-terraform-template-overview.png create mode 100644 mlops-template-terraform/mlops_templates/diagrams/sm_project_template.png create mode 100644 mlops-template-terraform/mlops_templates/scripts/bootstrap/bootstrap_cfn.yaml create mode 100644 mlops-template-terraform/mlops_templates/scripts/bootstrap/provider.template create mode 100755 mlops-template-terraform/mlops_templates/scripts/terraform-account-setup.sh create mode 100644 mlops-template-terraform/mlops_templates/terraform/main.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/modules/sagemaker_project_template/main.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/modules/sagemaker_project_template/terraform.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/modules/sagemaker_project_template/variables.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/provider.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/.gitkeep create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/.gitignore create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/Makefile create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/README.md create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/buildspec.yml create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/infra_scripts/bootstrap.sh create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/infra_scripts/bootstrap/provider.template create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/infra_scripts/bootstrap/terraform.tfvars.template create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/README.md create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/__init__.py create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/__version__.py create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/_utils.py create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/get_pipeline_definition.py create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/run_pipeline.py create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/training/README.md create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/training/__init__.py create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/training/_utils.py create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/training/pipeline.py create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/notebooks/README.md create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/notebooks/sagemaker-pipelines-preprocess-train-evaluate-batch-transform.ipynb create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/notebooks/sm_pipelines_runbook.ipynb create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/requirements-dev.txt create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/requirements.txt create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/setup.cfg create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/setup.py create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/Dockerfile create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/README.md create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/evaluate/evaluate_xgboost/README.md create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/evaluate/evaluate_xgboost/main.py create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/evaluate/evaluate_xgboost/requirements.txt create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/helpers/README.md create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/helpers/logger.py create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/helpers/requirements.txt create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/helpers/s3_helper.py create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/helpers/test/test_a.py create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/preprocessing/prepare_abalone_data/README.md create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/preprocessing/prepare_abalone_data/main.py create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/preprocessing/prepare_abalone_data/requirements.txt create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/training/xgboost/README.md create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/training/xgboost/__main__.py create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/training/xgboost/requirements.txt create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/training/xgboost/test/test_a.py create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/terraform/.gitkeep create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/terraform/main.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/terraform/modules/cicd/codebuild.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/terraform/modules/cicd/codepipeline.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/terraform/modules/cicd/main.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/terraform/modules/cicd/outputs.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/terraform/modules/cicd/sagemaker_pipeline.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/terraform/modules/cicd/terraform.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/terraform/modules/cicd/variables.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/terraform/variables.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/.gitignore create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/.pre-commit-config.yaml create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/Makefile create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/README.md create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/buildspec.yml create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/infra_scripts/bootstrap.sh create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/infra_scripts/bootstrap/provider.template create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/infra_scripts/bootstrap/terraform.tfvars.template create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/infra_scripts/get_last_approved_model.py create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/requirements-dev.txt create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/requirements.txt create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/.gitkeep create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/main.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/cicd/codebuild.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/cicd/codepipeline.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/cicd/event_bridge.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/cicd/main.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/cicd/outputs.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/cicd/terraform.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/cicd/variables.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/sm_endpoint_slim/README.md create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/sm_endpoint_slim/main.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/sm_endpoint_slim/outputs.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/sm_endpoint_slim/terraform.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/sm_endpoint_slim/variables.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/variables.tf create mode 100644 mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/service_catalog_product_template.yaml.tpl create mode 100644 mlops-template-terraform/mlops_templates/terraform/variables.tf diff --git a/mlops-template-terraform/LICENSE.txt b/mlops-template-terraform/LICENSE.txt new file mode 100644 index 00000000..a44c3b63 --- /dev/null +++ b/mlops-template-terraform/LICENSE.txt @@ -0,0 +1,16 @@ +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. + +SPDX-License-Identifier: MIT-0 + +Permission is hereby granted, free of charge, to any person obtaining a copy of this +software and associated documentation files (the "Software"), to deal in the Software +without restriction, including without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/mlops-template-terraform/README.md b/mlops-template-terraform/README.md new file mode 100644 index 00000000..827b4133 --- /dev/null +++ b/mlops-template-terraform/README.md @@ -0,0 +1,62 @@ +## MLOps Terraform Template for SageMaker Projects + +An important aspect of Machine Learning (ML) projects is the transition from the manual experimentation with +Jupyter notebooks and similar to an architecture, where workflows for building, training, deploying and maintaining ML models +in production are automated and orchestrated. In order to achieve this, an operating model between different personas such as Data Scientists, +Data Engineers, ML Engineers, DevOps Engineers, IT and business stakeholders needs to be established. Further, the data and +model lifecycle and the underlying workflows need to be defined, as well as the responsibilities of the different personas +in these areas. This collection of practices is called Machine Learning Operations (MLOps). + +This repository contains a set baseline infrastructure for an MLOps environment on AWS for a single AWS account at this moment. +The infrastructure is defined with Terraform and is built around the Amazon SageMaker service. + +The 3 main components in the repository are: + +### Component 1: ./mlops_infra: + +This terraform project is used to bootstrap an account for ML and includes the following modules: +- modules/networking: Deploy vpc, subnet & vpc endpoints for SageMaker +- modules/code_commit: Deploy codecommit repository & associate it as SageMaker repository +- modules/kms: Deploy KMS key for encryption of SageMaker resources +- modules/iam: Deploy Sagemaker roles & policies +- modules/sagemaker_studio: Deploy SageMaker Studio with users and default Jupyterhub app, as well as enabling SageMaker projects + +### Component 2: ./mlops_templates: + +This terraform project is used to bootstrap service catalog with a portfolio and example terraform based SageMaker project. +It allows deploying many different organizational SageMaker project templates. + +- modules/sagemaker_project_template: Create Service Catalog Portolio & products + +### Component 3: ./mlops_templates/templates/mlops_terraform_template/seed_code + +These folders contain the "seed code", which is the code that will be initialized when a new SageMaker project is created in SageMaker Studio. +The seed code is associated with the corresponding template in the mlops_template code. The seed code should be 100% generic +and should provide the baseline for new ML projects to build on. + +- seed_code/build_app: Example terraform based model build application using SageMaker Pipelines, Codecommit & Codebuild +- seed_code/deploy_app: Example terraform based model deployment application that deploys trained models to SageMaker endpoints + +## Prerequisites + +- Terraform +- Git +- AWS CLI v2 + +## Architecture overview and workflows + +![Architecture Diagram](./mlops_templates/diagrams/mlops-terraform-template-overview.png) + + +## How to use + +### Step 1: Deploy mlops_infra into a fresh account + +Navigate to the 'mlops_infra' directory with `cd mlops_infra` and follow instructions: +[mlops_infra](mlops_infra/README.md) + + +### Step 2: Deploy mlops_template into the same account + +Navigate to the 'mlops_templates' directory with `cd mlops_templates` and follow instructions: +[mlops_templates](mlops_templates/README.md) diff --git a/mlops-template-terraform/mlops_infra/Makefile b/mlops-template-terraform/mlops_infra/Makefile new file mode 100644 index 00000000..e9940532 --- /dev/null +++ b/mlops-template-terraform/mlops_infra/Makefile @@ -0,0 +1,17 @@ +.DEFAULT_GOAL = help +.PHONY: help bootstrap init plan apply + +help: + @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' + +bootstrap: + @./scripts/terraform-account-setup.sh + +init: + @cd terraform && terraform init + +plan: + @cd terraform && terraform plan + +apply: + @cd terraform && terraform apply diff --git a/mlops-template-terraform/mlops_infra/README.md b/mlops-template-terraform/mlops_infra/README.md new file mode 100644 index 00000000..6f5600ac --- /dev/null +++ b/mlops-template-terraform/mlops_infra/README.md @@ -0,0 +1,53 @@ +# mlops_infra + +## Summary + +This repository is used to deploy the foundational infrastructure for MLOps on AWS using Terraform. It includes the modules to deploy: + +- `networking`: Sets up basic VPC and Subnets and required VPC Endpoints for running SageMaker Studio in private subnets +- `iam`: Sets up basic IAM roles and IAM policies +- `kms`: Creates KMS key and policies +- `sagemaker_studio`: Deploys and configures Amazon SageMaker Studio including automatically enabling Amazon SageMaker projects + +## Architecture overview + +![Architecture Diagram](./diagrams/SageMaker_dev_env.png) + +## Getting started + + +How to apply the resources: + +Expose aws credentials via environment variables(https://registry.terraform.io/providers/hashicorp/aws/latest/docs#environment-variables) + + +Create state bucket via CloudFormation & generate terraform/provider.tf, as well as initializing Terraform +```bat +make bootstrap +make init +``` + +Modify the locals in `terraform/main.tf`. In particular, change the `prefix` to a unique name for your project/use-case. This will allow deploying multiple versions of the infrastructure side by side for each prefix. + +## Deploying your infrastructure + +```bat +make plan +make apply +``` + +## Adding new users to Amazon SageMaker Studio Domain + +To add additional users to the Amazon SageMaker Studio domain + +1. Open `terraform/main.tf` +2. Modify the user list +3. `make plan && make apply` + +## How to destroy the resources: + +```bat +make destroy +``` + +> Note: For the SageMaker Studio related resources (e.g. User etc.) you need to currently do it manually, as the destroy command fails with the user still being in use. \ No newline at end of file diff --git a/mlops-template-terraform/mlops_infra/diagrams/SageMaker_dev_env.png b/mlops-template-terraform/mlops_infra/diagrams/SageMaker_dev_env.png new file mode 100644 index 0000000000000000000000000000000000000000..7f22a3653b77af0c9d2fac1a6f1ebfc45d93f441 GIT binary patch literal 115097 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 NR#3Z^d*$|n{{v5Lk6Qo$ literal 0 HcmV?d00001 diff --git a/mlops-template-terraform/mlops_infra/scripts/bootstrap/bootstrap_cfn.yaml b/mlops-template-terraform/mlops_infra/scripts/bootstrap/bootstrap_cfn.yaml new file mode 100644 index 00000000..3995a397 --- /dev/null +++ b/mlops-template-terraform/mlops_infra/scripts/bootstrap/bootstrap_cfn.yaml @@ -0,0 +1,13 @@ +Resources: + S3Bucket: + Type: 'AWS::S3::Bucket' + DeletionPolicy: Retain + Properties: + BucketName: !Sub 'mlops-${AWS::AccountId}-${AWS::Region}-tf-state' +Outputs: + BucketName: + Value: !Ref S3Bucket + Description: Name of the sample Amazon S3 bucket with CORS enabled. + BucketRegion: + Value: !Sub "${AWS::Region}" + Description: Region on state bucket diff --git a/mlops-template-terraform/mlops_infra/scripts/bootstrap/provider.template b/mlops-template-terraform/mlops_infra/scripts/bootstrap/provider.template new file mode 100644 index 00000000..687a0b11 --- /dev/null +++ b/mlops-template-terraform/mlops_infra/scripts/bootstrap/provider.template @@ -0,0 +1,12 @@ +provider "aws" { + region = "$BUCKET_REGION" +} + +terraform { + required_version = ">= 1.0.0" + backend "s3" { + bucket = "$BUCKET_NAME" + key = "mlops.tfstate" + region = "$BUCKET_REGION" + } +} diff --git a/mlops-template-terraform/mlops_infra/scripts/terraform-account-setup.sh b/mlops-template-terraform/mlops_infra/scripts/terraform-account-setup.sh new file mode 100755 index 00000000..efb6d29e --- /dev/null +++ b/mlops-template-terraform/mlops_infra/scripts/terraform-account-setup.sh @@ -0,0 +1,33 @@ +#!/bin/bash +STACK_NAME="mlops-tf-bootstrap" +AWS_ACCOUNT=$(aws sts get-caller-identity --query "Account" --output text) +AWS_REGION=${AWS_REGION:-$(aws configure get region)} + +bootstrap() { + echo "---------------------BOOTSTRAPPING---------------------" + aws cloudformation deploy --template ./scripts/bootstrap/bootstrap_cfn.yaml --stack-name $STACK_NAME --region $AWS_REGION + export BUCKET_NAME=$(aws cloudformation describe-stacks --stack-name $STACK_NAME --query "Stacks[0].Outputs[?OutputKey=='BucketName'].OutputValue" --output text) + export BUCKET_REGION=$(aws cloudformation describe-stacks --stack-name $STACK_NAME --query "Stacks[0].Outputs[?OutputKey=='BucketRegion'].OutputValue" --output text) + + # Update provider.tf to use bucket and region + envsubst < "./scripts/bootstrap/provider.template" > "./terraform/provider.tf" + + # Re-initialize terraform + terraform init -reconfigure || true + echo "State Bucket: $BUCKET_NAME" + echo "State Region: $BUCKET_REGION" + echo "-----------------------COMPLETE------------------------" + echo "Ensure to set your AWS_REGION environment variable to $AWS_REGION for Terrform to select the correct region" +} + +read -r -p "Bootstrap $AWS_ACCOUNT in $AWS_REGION?? [Y/n] " CONFIRMATION +case "$CONFIRMATION" in + [yY][eE][sS]|[yY]) + # Deploy bucket for state files + bootstrap + ;; + *) + echo "Skipping bootstrap" + ;; +esac + diff --git a/mlops-template-terraform/mlops_infra/terraform/main.tf b/mlops-template-terraform/mlops_infra/terraform/main.tf new file mode 100644 index 00000000..6adbe2bf --- /dev/null +++ b/mlops-template-terraform/mlops_infra/terraform/main.tf @@ -0,0 +1,41 @@ +locals { + prefix = "mlops" + user_profile_names = ["user1", "user2"] + domain_name = "${local.prefix}-studio-domain" + kms_key_alias = "${local.prefix}-kms-key" +} + +data "aws_caller_identity" "current" {} + +data "aws_region" "current" {} + +module "networking" { + source = ".//modules/networking" + prefix = local.prefix + vpc_cidr_block = "10.0.0.0/16" + private_subnet_cidr_block = "10.0.1.0/24" + public_subnet_cidr_block = "10.0.0.0/24" + availability_zone = "${data.aws_region.current.name}a" # Get rid of this +} + +module "kms" { + source = ".//modules/kms" + kms_key_alias = local.kms_key_alias +} + +module "iam" { + source = ".//modules/iam" + prefix = local.prefix + kms_key_arn = module.kms.kms_key_arn +} + +module "sm_studio" { + source = ".//modules/sagemaker_studio" + domain_name = local.domain_name + vpc_id = module.networking.vpc_id + subnet_ids = [module.networking.private_subnet_ids] + sm_execution_role_arn = module.iam.sm_execution_role_arn + kms_key_arn = module.kms.kms_key_arn + user_profile_names = local.user_profile_names +} + diff --git a/mlops-template-terraform/mlops_infra/terraform/modules/iam/main.tf b/mlops-template-terraform/mlops_infra/terraform/modules/iam/main.tf new file mode 100644 index 00000000..13dabcf2 --- /dev/null +++ b/mlops-template-terraform/mlops_infra/terraform/modules/iam/main.tf @@ -0,0 +1,272 @@ +locals { + prefix = var.prefix + sm_execution_role_name = "${local.prefix}-sagemaker-execution-role" + kms_key_arn = var.kms_key_arn +} + +data "aws_caller_identity" "current" {} + +data "aws_region" "current" {} +################################################################################################## +# Roles & Policies +################################################################################################## + +resource "aws_iam_role" "sagemaker_execution_role" { + name = local.sm_execution_role_name + + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Sid = "AllowRoleAssume" + Principal = { + Service = "sagemaker.amazonaws.com" + } + }, + ] + }) +} + +resource "aws_iam_role_policy_attachment" "aws_sagemaker_full_access" { + role = aws_iam_role.sagemaker_execution_role.name + policy_arn = "arn:aws:iam::aws:policy/AmazonSageMakerFullAccess" +} + +# How to restrict to necessary actions and services +# TODO: SCOPE DOWN! +resource "aws_iam_role_policy_attachment" "aws_sagemaker_cloudformation_poweruser" { + role = aws_iam_role.sagemaker_execution_role.name + policy_arn = "arn:aws:iam::aws:policy/AWSCloudFormationFullAccess" +} + + +resource "aws_iam_policy" "codecommit_policy" { + name = "${local.prefix}-codecommit-policy" + description = "${local.prefix} policy for SM Studio codecommit access" + + policy = < Control Panel -> Your User --> Launch App --> Studio +3. Wait for Amazon SageMaker Studio to launch +4. In the left bar -> SageMaker Resources -> In the drop down tab select Projects +5. Click "Create project" +6. Select the "Organization templates" tab +7. Select the "mlops_terraform_template & click on "Select project template" + - Note: Your template name might be different if you used a different prefix. +8. Enter a unique project name and the required fields +9. Click "Create" +10. Wait for the SageMaker Project instance to be created from the template +11. Open project by double clicking -> Repositories Tab +12. Click Clone Repository (for both) + +After a new project has been created. It needs to be bootstrapped: + +- Top Menu: Git -> Open a Terminal in SageMaker Studio and navigate to the modelbuild Git repository +- `$ make bootstrap` # tap enter for the defaults +- In case you get a permission denied error, consider using the command `chmod u+x ./infra_scripts/bootstrap.sh` +- Ensure entries are correct and complete after bootstrapping process. This will generate terraform/provider.tf & terraform/terraform.tfvars files and install Terraform +- `$ make init` +- `$ make plan` +- `$ make apply` # Deploys CICD pipeline for building models and running sagemaker pipelines on new commits +- `$ git add -A` +- `$ git commit -m "bootstrapped"` +- `$ git push` # Will trigger CodePipeline & deploy/train SageMaker pipeline +- Approve the resulting model in SageMaker Studio under Model Groups of the SageMaker Project + + +## 3. Create Inference Infrastructure based on your trained model +- Navigate to the modeldeploy repository in the terminal window of SageMaker Studio to deploy your infra related infrastructure: +- `$ make bootstrap` +- Ensure entries are correct and complete after bootstrapping process. This will generate terraform/provider.tf & terraform/terraform.tfvars files and install terraform +- `$ make init` +- `$ make plan` +- `$ make apply` \ No newline at end of file diff --git a/mlops-template-terraform/mlops_templates/diagrams/mlops-terraform-template-overview.png b/mlops-template-terraform/mlops_templates/diagrams/mlops-terraform-template-overview.png new file mode 100644 index 0000000000000000000000000000000000000000..e4af013c25407dfd1221cfd2d7b031d939e99f08 GIT binary patch literal 195622 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

    %c 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%0DZVk{iPFX{&9fWA+CF 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 F{{&gMWs3j+ literal 0 HcmV?d00001 diff --git a/mlops-template-terraform/mlops_templates/diagrams/sm_project_template.png b/mlops-template-terraform/mlops_templates/diagrams/sm_project_template.png new file mode 100644 index 0000000000000000000000000000000000000000..1fe710db65944eac7d9ca292da50d7e20315197a GIT binary patch literal 148115 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 literal 0 HcmV?d00001 diff --git a/mlops-template-terraform/mlops_templates/scripts/bootstrap/bootstrap_cfn.yaml b/mlops-template-terraform/mlops_templates/scripts/bootstrap/bootstrap_cfn.yaml new file mode 100644 index 00000000..3995a397 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/scripts/bootstrap/bootstrap_cfn.yaml @@ -0,0 +1,13 @@ +Resources: + S3Bucket: + Type: 'AWS::S3::Bucket' + DeletionPolicy: Retain + Properties: + BucketName: !Sub 'mlops-${AWS::AccountId}-${AWS::Region}-tf-state' +Outputs: + BucketName: + Value: !Ref S3Bucket + Description: Name of the sample Amazon S3 bucket with CORS enabled. + BucketRegion: + Value: !Sub "${AWS::Region}" + Description: Region on state bucket diff --git a/mlops-template-terraform/mlops_templates/scripts/bootstrap/provider.template b/mlops-template-terraform/mlops_templates/scripts/bootstrap/provider.template new file mode 100644 index 00000000..d44d64b2 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/scripts/bootstrap/provider.template @@ -0,0 +1,12 @@ +provider "aws" { + region = "$BUCKET_REGION" +} + +terraform { + required_version = ">= 1.0.0" + backend "s3" { + bucket = "$BUCKET_NAME" + key = "mlops-templates.tfstate" + region = "$BUCKET_REGION" + } +} diff --git a/mlops-template-terraform/mlops_templates/scripts/terraform-account-setup.sh b/mlops-template-terraform/mlops_templates/scripts/terraform-account-setup.sh new file mode 100755 index 00000000..f2ee6909 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/scripts/terraform-account-setup.sh @@ -0,0 +1,35 @@ +#!/bin/bash +STACK_NAME="mlops-tf-bootstrap" +AWS_ACCOUNT=$(aws sts get-caller-identity --query "Account" --output text) +AWS_REGION=${AWS_REGION:-$(aws configure get region)} + +# Deploy bucket for state files +bootstrap() { + echo "---------------------BOOTSTRAPPING---------------------" + aws cloudformation deploy --template ./scripts/bootstrap/bootstrap_cfn.yaml --stack-name $STACK_NAME + export BUCKET_NAME=$(aws cloudformation describe-stacks --stack-name $STACK_NAME --query "Stacks[0].Outputs[?OutputKey=='BucketName'].OutputValue" --output text) + export BUCKET_REGION=$(aws cloudformation describe-stacks --stack-name $STACK_NAME --query "Stacks[0].Outputs[?OutputKey=='BucketRegion'].OutputValue" --output text) + + # Update provider.tf to use bucket and region + envsubst < "./scripts/bootstrap/provider.template" > "./terraform/provider.tf" + + # Re-initialize terraform + terraform init -reconfigure || true + echo "State Bucket: $BUCKET_NAME" + echo "State Region: $BUCKET_REGION" + echo "-----------------------COMPLETE------------------------" + echo "Ensure to set your AWS_REGION environment variable to $AWS_REGION for Terrform to select the correct region" +} + + +read -r -p "Bootstrap $AWS_ACCOUNT in $AWS_REGION?? [Y/n] " CONFIRMATION +case "$CONFIRMATION" in + [yY][eE][sS]|[yY]) + # Deploy bucket for state files + bootstrap + ;; + *) + echo "Skipping bootstrap" + ;; +esac + \ No newline at end of file diff --git a/mlops-template-terraform/mlops_templates/terraform/main.tf b/mlops-template-terraform/mlops_templates/terraform/main.tf new file mode 100644 index 00000000..518502d2 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/main.tf @@ -0,0 +1,49 @@ +locals { + prefix = "mlops" + templates = { + mlops_terraform_template : { + name : "${local.prefix}_terraform_template" + owner : "central-IT" + template_key = "${local.prefix}/resouces/service_catalog/templates/terraform_template/service_catalog_product_template.yaml" + template_local_path = "./templates/mlops_terraform_template/service_catalog_product_template.yaml.tpl" + seed_code_map : { + "build" : { + local_path : "./templates/mlops_terraform_template/seed_code/build_app" + key : "${local.prefix}/resouces/service_catalog/seed_code/terraform_template/build.zip" + }, + "deploy" : { + local_path : "./templates/mlops_terraform_template/seed_code/deploy_app", + key : "${local.prefix}/resouces/service_catalog/seed_code/terraform_template/deploy.zip" + } + } + } + } +} + + +data "aws_caller_identity" "current" {} +data "aws_region" "current" {} + +module "sm_project_template" { + source = ".//modules/sagemaker_project_template" + template_name = local.templates.mlops_terraform_template.name + owner = local.templates.mlops_terraform_template.owner + sagemaker_execution_role_arn = "arn:aws:iam::${data.aws_caller_identity.current.account_id}:role/${local.prefix}-sagemaker-execution-role" + seed_code_map = local.templates.mlops_terraform_template.seed_code_map + template_local_path = local.templates.mlops_terraform_template.template_local_path + template_key = local.templates.mlops_terraform_template.template_key + + # These values will be injected into the template.yaml file. + # The $${} escape allows referencing CloudFormation Parameters + template_vars = { + prefix = local.prefix + artifact_bucket_name = "${local.prefix}-project-$${SageMakerProjectName}" + state_bucket_name = "${local.prefix}-project-$${SageMakerProjectName}-tf-state" + build_code_repo_name = "${local.prefix}-project-$${SageMakerProjectName}-modelbuild" + deploy_code_repo_name = "${local.prefix}-project-$${SageMakerProjectName}-modeldeploy" + seed_code_build_key = local.templates.mlops_terraform_template.seed_code_map["build"].key, + seed_code_deploy_key = local.templates.mlops_terraform_template.seed_code_map["deploy"].key, + default_branch = "main" + } +} + diff --git a/mlops-template-terraform/mlops_templates/terraform/modules/sagemaker_project_template/main.tf b/mlops-template-terraform/mlops_templates/terraform/modules/sagemaker_project_template/main.tf new file mode 100644 index 00000000..bc72c337 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/modules/sagemaker_project_template/main.tf @@ -0,0 +1,131 @@ +locals { + template_name = var.template_name + template_key = var.template_key + template_local_path = var.template_local_path + seed_code_map = var.seed_code_map + template_vars = var.template_vars + sm_execution_role_arn = var.sagemaker_execution_role_arn + owner = var.owner + sagemaker_execution_role_arn = var.sagemaker_execution_role_arn +} + +data "aws_caller_identity" "current" {} + +data "aws_region" "current" {} + +resource "aws_s3_bucket" "sc_bucket" { + bucket = "${replace(local.template_name, "_", "-")}-${data.aws_caller_identity.current.account_id}-${data.aws_region.current.name}-service-catalog" +} + +resource "aws_s3_bucket_acl" "private_acl" { + bucket = aws_s3_bucket.sc_bucket.id + acl = "private" +} + + +data "archive_file" "seed_source" { + for_each = local.seed_code_map + type = "zip" + source_dir = each.value.local_path + output_path = "${each.value.local_path}.zip" +} + +resource "aws_s3_bucket_object" "seed_code_archive" { + depends_on = [ + aws_s3_bucket.sc_bucket, + data.archive_file.seed_source + ] + for_each = local.seed_code_map + bucket = aws_s3_bucket.sc_bucket.id + key = each.value.key + source = "${each.value.local_path}.zip" + etag = filemd5("${each.value.local_path}.zip") +} +resource "local_file" "template_out" { + content = templatefile("${local.template_local_path}", merge({ seed_code_bucket = aws_s3_bucket.sc_bucket.id}, local.template_vars)) + filename = "${path.module}/.terraform.out/generated_template.yaml" +} + + +resource "aws_s3_bucket_object" "service_catalog_mlops_template" { + depends_on = [ + aws_s3_bucket.sc_bucket + ] + bucket = aws_s3_bucket.sc_bucket.id + key = local.template_key + content = templatefile("${local.template_local_path}", merge({ seed_code_bucket = aws_s3_bucket.sc_bucket.id}, local.template_vars)) +} + +resource "aws_servicecatalog_product" "mlops_product" { + depends_on = [ + aws_s3_bucket_object.service_catalog_mlops_template + ] + + name = local.template_name + owner = local.owner + type = "CLOUD_FORMATION_TEMPLATE" + + provisioning_artifact_parameters { + type = "CLOUD_FORMATION_TEMPLATE" + template_url = "https://${aws_s3_bucket.sc_bucket.id}.s3.amazonaws.com/${local.template_key}" + } + + tags = { + "sagemaker:studio-visibility" = "true" + } +} + + +resource "aws_iam_role" "service_launch_role" { + name = "service_launch_role" + path = "/service-role/" + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Action = "sts:AssumeRole" + Effect = "Allow" + Sid = "AllowRoleAssume" + Principal = { + Service = "servicecatalog.amazonaws.com" + } + }, + ] + }) +} + +resource "aws_iam_role_policy_attachment" "aws_sagemaker_full_access" { + role = aws_iam_role.service_launch_role.name + policy_arn = "arn:aws:iam::aws:policy/AmazonSageMakerAdmin-ServiceCatalogProductsServiceRolePolicy" +} + +resource "aws_servicecatalog_portfolio" "projects_templates" { + name = "${local.template_name}-portfolio" + description = "${local.template_name}: Terraform SageMaker Project Templates" + provider_name = local.owner + tags = { + "sagemaker:studio-visibility" = "true" + } +} + +resource "aws_servicecatalog_product_portfolio_association" "template_association" { + portfolio_id = aws_servicecatalog_portfolio.projects_templates.id + product_id = aws_servicecatalog_product.mlops_product.id +} + +resource "aws_servicecatalog_principal_portfolio_association" "sm_execution_role_principal_association" { + portfolio_id = aws_servicecatalog_portfolio.projects_templates.id + principal_arn = local.sagemaker_execution_role_arn +} + +# resource "aws_servicecatalog_constraint" "sm_execution_role_launch_constraint" { +# description = "${local.template_name} - constraint launch to Sagemaker execution role" +# portfolio_id = aws_servicecatalog_portfolio.projects_templates.id +# product_id = aws_servicecatalog_product.mlops_product.id +# type = "LAUNCH" + +# parameters = jsonencode({ +# "RoleArn" : local.sagemaker_execution_role_arn +# }) +# } + diff --git a/mlops-template-terraform/mlops_templates/terraform/modules/sagemaker_project_template/terraform.tf b/mlops-template-terraform/mlops_templates/terraform/modules/sagemaker_project_template/terraform.tf new file mode 100644 index 00000000..6e498ec5 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/modules/sagemaker_project_template/terraform.tf @@ -0,0 +1,13 @@ +terraform { + required_version = ">= 1.0 , <= 1.2.6" + + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 3.0" + } + local = { + version = "~> 2.1" + } + } +} diff --git a/mlops-template-terraform/mlops_templates/terraform/modules/sagemaker_project_template/variables.tf b/mlops-template-terraform/mlops_templates/terraform/modules/sagemaker_project_template/variables.tf new file mode 100644 index 00000000..93904031 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/modules/sagemaker_project_template/variables.tf @@ -0,0 +1,33 @@ +variable "template_name" { + type = string + description = "Name of template, used to lookup seed_code and CloudFormation templates for service catalog" +} + +variable "owner" { + type = string + description = "Owner of the service catalog product" +} + +variable "sagemaker_execution_role_arn" { + type = string + description = "Sagemaker Execution Role ARN" +} + +variable "template_key" { + type = string + description = "S3 Key for storing service catalog template" +} + +variable "template_local_path" { + type = string + description = "Path to local service catalog product template file" +} + +variable "seed_code_map" { + type = map(any) + description = "Map of seed code for template" +} +variable "template_vars" { + type = map(any) + description = "Values to substitute into service catalog product template" +} diff --git a/mlops-template-terraform/mlops_templates/terraform/provider.tf b/mlops-template-terraform/mlops_templates/terraform/provider.tf new file mode 100644 index 00000000..9c40338b --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/provider.tf @@ -0,0 +1,14 @@ +provider "aws" { + region = "" +} + +terraform { + required_version = ">= 1.0.0" + backend "s3" { + bucket = "" + key = "mlops-templates.tfstate" + region = "" + } +} + + diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/.gitkeep b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/.gitignore b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/.gitignore new file mode 100644 index 00000000..ed839918 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/.gitignore @@ -0,0 +1,141 @@ +*.tfstate +*.tfstate.* +*.tfvars.json +**/.terraform/* +override.tf +override.tf.json +*_override.tf +*_override.tf.json +.terraformrc +terraform.rc +.terraform.lock.hcl +.cache/ +*.zip +*.bundle.* +lib/ +node_modules/ +*.egg-info/ +.ipynb_checkpoints +*.tsbuildinfo + +# Created by https://www.gitignore.io/api/python +# Edit at https://www.gitignore.io/?templates=python + +### Python ### +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +pip-wheel-metadata/ +share/python-wheels/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ + +# Translations +*.mo +*.pot + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +target/ + +# pyenv +.python-version + +# celery beat schedule file +celerybeat-schedule + +# SageMath parsed files +*.sage.py + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# Mr Developer +.mr.developer.cfg +.project +.pydevproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# OS X stuff +*.DS_Store + +# End of https://www.gitignore.io/api/python + +_temp_extension +junit.xml +[uU]ntitled* +notebook/static/* +!notebook/static/favicons +notebook/labextension +notebook/schemas +docs/source/changelog.md +docs/source/contributing.md + +# playwright +ui-tests/test-results +ui-tests/playwright-report + +# VSCode +.vscode diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/Makefile b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/Makefile new file mode 100644 index 00000000..60b830f0 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/Makefile @@ -0,0 +1,12 @@ + +bootstrap: + @sh ./infra_scripts/bootstrap.sh + +init: + @cd terraform && terraform init + +plan: + @cd terraform && terraform plan + +apply: + @cd terraform && terraform apply \ No newline at end of file diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/README.md b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/README.md new file mode 100644 index 00000000..8e95b64b --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/README.md @@ -0,0 +1,14 @@ +# Terraform Build App + +After a new project has been created and bootstrapped, you can update your SageMaker Pipelines and scripts that are +running in the different steps. The main files and folders to consider are: +- `/ml_pipelines` for adapting any necessary changes to the SageMaker Pipeline definition such as data sources, instance types + and similiar +- `/source_scripts` for changing any of the source code for preprocessing, model evaluation or modelling logic. + +In order for your changes to become effective and retrain the ML model with the new source code, you will need to push the +code to the repository: +- `$ git add -A` +- `$ git commit -m "bootstrapped"` +- `$ git push` # Will trigger CodePipeline & deploy/train SageMaker pipeline +- Approve the resulting model in SageMaker Studio under Model Groups of the SageMaker Project \ No newline at end of file diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/buildspec.yml b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/buildspec.yml new file mode 100644 index 00000000..d6032bb4 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/buildspec.yml @@ -0,0 +1,17 @@ +version: 0.2 + +phases: + install: + runtime-versions: + python: 3.8 + commands: + - pip install --upgrade --force-reinstall . "awscli>1.20.30" + build: + commands: + - export PYTHONUNBUFFERED=TRUE + - | + run-pipeline --module-name ml_pipelines.training.pipeline \ + --role-arn $SAGEMAKER_PIPELINE_ROLE_ARN \ + --tags "[{\"Key\":\"sagemaker:project-name\", \"Value\":\"${SAGEMAKER_PROJECT_NAME}\"}, {\"Key\":\"sagemaker:project-id\", \"Value\":\"${SAGEMAKER_PROJECT_ID}\"}]" \ + --kwargs "{\"region\":\"${AWS_REGION}\",\"role\":\"${SAGEMAKER_PIPELINE_ROLE_ARN}\",\"default_bucket\":\"${ARTIFACT_BUCKET}\",\"pipeline_name\":\"${PIPELINE_NAME}\",\"model_package_group_name\":\"${MODEL_PACKAGE_GROUP_NAME}\",\"base_job_prefix\":\"${PIPELINE_NAME}\", \"bucket_kms_id\":\"${ARTIFACT_BUCKET_KMS_ID}\"}" + - echo "Create/Update of the SageMaker Pipeline and execution completed." \ No newline at end of file diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/infra_scripts/bootstrap.sh b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/infra_scripts/bootstrap.sh new file mode 100644 index 00000000..db0799a3 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/infra_scripts/bootstrap.sh @@ -0,0 +1,117 @@ +#!/bin/bash + +sudo yum install -y gettext wget unzip jq + +export TERRAFORM_VERSION="1.2.4" + +echo "Attempting to install terraform" && \ +wget -q https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip -P /tmp && \ +unzip -q /tmp/terraform_${TERRAFORM_VERSION}_linux_amd64.zip -d /tmp && \ +sudo mv /tmp/terraform /usr/local/bin/ && \ +rm -rf /tmp/terraform_${TERRAFORM_VERSION}_linux_amd64.zip && \ +echo "terraform is installed successfully" + + +# Read the SM_PROJECT_ID from the folder name +DEFAULT_SM_PROJECT_ID=$(cat .sagemaker-code-config | jq -r .sagemakerProjectId) +read -p "Sagemaker Project ID (default \"$DEFAULT_SM_PROJECT_ID\"): " sm_project_id_input +export SM_PROJECT_ID="${sm_project_id_input:-$DEFAULT_SM_PROJECT_ID}" + +if [[ -z $SM_PROJECT_ID ]]; then + echo "No Sagemaker Project ID provided" + exit 1 +fi + +# Read the SM_PROJECT_NAME from the folder name +DEFAULT_SM_PROJECT_NAME=$(cat .sagemaker-code-config | jq -r .sagemakerProjectName) +read -p "Sagemaker Project ID (default \"$DEFAULT_SM_PROJECT_NAME\"): " sm_project_id_input +export SM_PROJECT_NAME="${sm_project_id_input:-$DEFAULT_SM_PROJECT_NAME}" + +if [[ -z $SM_PROJECT_NAME ]]; then + echo "No Sagemaker Project Name provided" + exit 1 +fi + + +# Fetch Values from CloudFormation Stack Output +export STACK_NAME=$(aws cloudformation describe-stacks --query 'Stacks[?Tags[?Key == `sagemaker:project-id` && Value == `'$DEFAULT_SM_PROJECT_ID'`]].{StackName: StackName}' --output text) + +export PREFIX=$(aws cloudformation describe-stacks --query "Stacks[?StackName=='$STACK_NAME'][].Outputs[?OutputKey=='Prefix'].OutputValue" --output text) + +export STATE_BUCKET_NAME=$(aws cloudformation describe-stacks --query "Stacks[?StackName=='$STACK_NAME'][].Outputs[?OutputKey=='MlOpsProjectStateBucket'].OutputValue" --output text) + +export ARTIFACT_BUCKET_NAME=$(aws cloudformation describe-stacks --query "Stacks[?StackName=='$STACK_NAME'][].Outputs[?OutputKey=='MlOpsArtifactsBucket'].OutputValue" --output text) + +export BUCKET_REGION=$(aws cloudformation describe-stacks --query "Stacks[?StackName=='$STACK_NAME'][].Outputs[?OutputKey=='BucketRegion'].OutputValue" --output text) + +CF_DEFAULT_BRANCH=$(aws cloudformation describe-stacks --query "Stacks[?StackName=='$STACK_NAME'][].Outputs[?OutputKey=='DefaultBranch'].OutputValue" --output text) + +export DEFAULT_BRANCH=${CF_DEFAULT_BRANCH:-main} + +# Get the AWS Account ID. Should be set as environmet variable in SageMaker Studio +read -p "AWS_ACCOUNT_ID (default \"$AWS_ACCOUNT_ID\"): " input_account_id +export AWS_ACCOUNT_ID="${input_account_id:-$AWS_ACCOUNT_ID}" + +if [[ -z "$AWS_ACCOUNT_ID" ]]; then + echo "No AWS_ACCOUNT_ID provided" + exit 1 +fi + +# Get the AWS Region ID. Should be set as environmet variable in SageMaker Studio +read -p "AWS_REGION (default \"$AWS_REGION\"): " input_region +export AWS_REGION="${input_region:-$AWS_REGION}" + +if [[ -z "$AWS_REGION" ]]; then + echo "No AWS_REGION provided" + exit 1 +fi + +CODECOMMIT_ID=$(cat .sagemaker-code-config | jq -r .codeRepositoryName) +read -p "CODECOMMIT_ID (default \"$CODECOMMIT_ID\"): " input_codecommit_id +export CODECOMMIT_ID="${input_codecommit_id:-$CODECOMMIT_ID}" + +if [[ -z "$CODECOMMIT_ID" ]]; then + echo "No CODECOMMIT_ID provided" + exit 1 +fi + +read -p "DEFAULT_BRANCH (default \"$DEFAULT_BRANCH\"): " input_default_branch +export DEFAULT_BRANCH="${input_default_branch:-$DEFAULT_BRANCH}" + +if [[ -z "$DEFAULT_BRANCH" ]]; then + echo "No DEFAULT_BRANCH provided" + exit 1 +fi + + +echo "--------------Bootstrap Output-----------------" +echo "Prefix: $PREFIX" +echo "Sagmaker Project ID: $SM_PROJECT_ID" +echo "Sagmaker Name: $SM_PROJECT_NAME" +echo "AWS Account ID: $AWS_ACCOUNT_ID" +echo "AWS Region: $AWS_REGION" +echo "Artifact bucket name: $ARTIFACT_BUCKET_NAME" +echo "State bucket name: $STATE_BUCKET_NAME" +echo "CodeCommit ID: $CODECOMMIT_ID" +echo "Default Branch: $DEFAULT_BRANCH" +echo "-----------------------------------------------" + +# Update provider.tf to use bucket and region +envsubst < "./infra_scripts/bootstrap/provider.template" > "./terraform/provider.tf" + +# Update terraform.tfvars +envsubst < "./infra_scripts/bootstrap/terraform.tfvars.template" > "./terraform/terraform.tfvars" + +cd terraform + +terraform init + +cd .. + +echo "Commit & update tfvars, terraform provider and sagemaker-code-config" +git add .sagemaker-code-config +git add terraform/provider.tf +git add terraform/terraform.tfvars +git commit --author="SM Projects <>" -m "Bootstrapping complete" +git push +echo "Bootstrapping completed" \ No newline at end of file diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/infra_scripts/bootstrap/provider.template b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/infra_scripts/bootstrap/provider.template new file mode 100644 index 00000000..d90101c3 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/infra_scripts/bootstrap/provider.template @@ -0,0 +1,12 @@ +provider "aws" { + region = "$AWS_REGION" +} + +terraform { + required_version = ">= $TERRAFORM_VERSION" + backend "s3" { + bucket = "$STATE_BUCKET_NAME" + key = "projects/state/build/mlops-$SM_PROJECT_ID-build-state.tfstate" + region = "$AWS_REGION" + } +} diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/infra_scripts/bootstrap/terraform.tfvars.template b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/infra_scripts/bootstrap/terraform.tfvars.template new file mode 100644 index 00000000..d08f1e0a --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/infra_scripts/bootstrap/terraform.tfvars.template @@ -0,0 +1,8 @@ +aws_region = "$AWS_REGION" +aws_account_id = "$AWS_ACCOUNT_ID" +sm_project_id = "$SM_PROJECT_ID" +sm_project_name = "$SM_PROJECT_NAME" +codecommit_id = "$CODECOMMIT_ID" +prefix = "$PREFIX" +artifact_bucket_name = "$ARTIFACT_BUCKET_NAME" +default_branch = "$DEFAULT_BRANCH" \ No newline at end of file diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/README.md b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/README.md new file mode 100644 index 00000000..8e309f81 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/README.md @@ -0,0 +1,7 @@ +# SageMaker Pipelines + +This folder contains SageMaker Pipeline definitions and helper scripts to either simply "get" a SageMaker Pipeline definition (JSON dictionnary) with `get_pipeline_definition.py`, or "run" a SageMaker Pipeline from a SageMaker pipeline definition with `run_pipeline.py`. + +Those files are generic and can be reused to call any SageMaker Pipeline. + +Each SageMaker Pipeline definition should be be treated as a modul inside its own folder, for example here the "training" pipeline, contained inside `training/`. diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/__init__.py b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/__init__.py new file mode 100644 index 00000000..ff79f21c --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/__init__.py @@ -0,0 +1,30 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# SPDX-License-Identifier: MIT-0 +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this +# software and associated documentation files (the "Software"), to deal in the Software +# without restriction, including without limitation the rights to use, copy, modify, +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# © 2021 Amazon Web Services, Inc. or its affiliates. All Rights Reserved. This +# AWS Content is provided subject to the terms of the AWS Customer Agreement +# available at http://aws.amazon.com/agreement or other written agreement between +# Customer and either Amazon Web Services, Inc. or Amazon Web Services EMEA SARL +# or both. +# +# Any code, applications, scripts, templates, proofs of concept, documentation +# and other items provided by AWS under this SOW are "AWS Content," as defined +# in the Agreement, and are provided for illustration purposes only. All such +# AWS Content is provided solely at the option of AWS, and is subject to the +# terms of the Addendum and the Agreement. Customer is solely responsible for +# using, deploying, testing, and supporting any code and applications provided +# by AWS under this SOW. diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/__version__.py b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/__version__.py new file mode 100644 index 00000000..660d19ee --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/__version__.py @@ -0,0 +1,26 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# SPDX-License-Identifier: MIT-0 +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this +# software and associated documentation files (the "Software"), to deal in the Software +# without restriction, including without limitation the rights to use, copy, modify, +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +"""Metadata for the ml pipelines package.""" + +__title__ = "ml_pipelines" +__description__ = "ml pipelines - template package" +__version__ = "0.0.1" +__author__ = "" +__author_email__ = "" +__license__ = "Apache 2.0" +__url__ = "" diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/_utils.py b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/_utils.py new file mode 100644 index 00000000..581e1eb7 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/_utils.py @@ -0,0 +1,91 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# SPDX-License-Identifier: MIT-0 +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this +# software and associated documentation files (the "Software"), to deal in the Software +# without restriction, including without limitation the rights to use, copy, modify, +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# © 2021 Amazon Web Services, Inc. or its affiliates. All Rights Reserved. This +# AWS Content is provided subject to the terms of the AWS Customer Agreement +# available at http://aws.amazon.com/agreement or other written agreement between +# Customer and either Amazon Web Services, Inc. or Amazon Web Services EMEA SARL +# or both. +# +# Any code, applications, scripts, templates, proofs of concept, documentation +# and other items provided by AWS under this SOW are "AWS Content," as defined +# in the Agreement, and are provided for illustration purposes only. All such +# AWS Content is provided solely at the option of AWS, and is subject to the +# terms of the Addendum and the Agreement. Customer is solely responsible for +# using, deploying, testing, and supporting any code and applications provided +# by AWS under this SOW. + +# Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"). You +# may not use this file except in compliance with the License. A copy of +# the License is located at +# +# http://aws.amazon.com/apache2.0/ +# +# or in the "license" file accompanying this file. This file is +# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF +# ANY KIND, either express or implied. See the License for the specific +# language governing permissions and limitations under the License. +"""Provides utilities for SageMaker Pipeline CLI.""" +from __future__ import absolute_import + +import ast + + +def get_pipeline_driver(module_name, passed_args=None): + """Gets the driver for generating your pipeline definition. + + Pipeline modules must define a get_pipeline() module-level method. + + Args: + module_name: The module name of your pipeline. + passed_args: Optional passed arguments that your pipeline may be templated by. + + Returns: + The SageMaker Workflow pipeline. + """ + _imports = __import__(module_name, fromlist=["get_pipeline"]) + kwargs = convert_struct(passed_args) + return _imports.get_pipeline(**kwargs) + + +def convert_struct(str_struct=None): + """convert the string argument to it's proper type + + Args: + str_struct (str, optional): string to be evaluated. Defaults to None. + + Returns: + string struct as it's actuat evaluated type + """ + return ast.literal_eval(str_struct) if str_struct else {} + + +def get_pipeline_custom_tags(module_name, args, tags): + """Gets the custom tags for pipeline + + Returns: + Custom tags to be added to the pipeline + """ + try: + _imports = __import__(module_name, fromlist=["get_pipeline_custom_tags"]) + kwargs = convert_struct(args) + return _imports.get_pipeline_custom_tags(tags, kwargs["region"], kwargs["sagemaker_project_arn"]) + except Exception as e: + print(f"Error getting project tags: {e}") + return tags diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/get_pipeline_definition.py b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/get_pipeline_definition.py new file mode 100644 index 00000000..edfb6b40 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/get_pipeline_definition.py @@ -0,0 +1,77 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# SPDX-License-Identifier: MIT-0 +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this +# software and associated documentation files (the "Software"), to deal in the Software +# without restriction, including without limitation the rights to use, copy, modify, +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + +"""A CLI to get pipeline definitions from pipeline modules.""" +from __future__ import absolute_import + +import argparse +import sys + +from ml_pipelines._utils import get_pipeline_driver + + +def main(): # pragma: no cover + """The main harness that gets the pipeline definition JSON. + + Prints the json to stdout or saves to file. + """ + parser = argparse.ArgumentParser("Gets the pipeline definition for the pipeline script.") + + parser.add_argument( + "-n", + "--module-name", + dest="module_name", + type=str, + help="The module name of the pipeline to import.", + ) + parser.add_argument( + "-f", + "--file-name", + dest="file_name", + type=str, + default=None, + help="The file to output the pipeline definition json to.", + ) + parser.add_argument( + "-kwargs", + "--kwargs", + dest="kwargs", + default=None, + help="Dict string of keyword arguments for the pipeline generation (if supported)", + ) + args = parser.parse_args() + + if args.module_name is None: + parser.print_help() + sys.exit(2) + + try: + pipeline = get_pipeline_driver(args.module_name, args.kwargs) + content = pipeline.definition() + if args.file_name: + with open(args.file_name, "w") as f: + f.write(content) + else: + print(content) + except Exception as e: # pylint: disable=W0703 + print(f"Exception: {e}") + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/run_pipeline.py b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/run_pipeline.py new file mode 100644 index 00000000..7d07235d --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/run_pipeline.py @@ -0,0 +1,110 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# SPDX-License-Identifier: MIT-0 +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this +# software and associated documentation files (the "Software"), to deal in the Software +# without restriction, including without limitation the rights to use, copy, modify, +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +"""A CLI to create or update and run pipelines.""" +from __future__ import absolute_import + +import argparse +import json +import sys + +from ml_pipelines._utils import get_pipeline_driver, convert_struct, get_pipeline_custom_tags + + +def main(): # pragma: no cover + """The main harness that creates or updates and runs the pipeline. + + Creates or updates the pipeline and runs it. + """ + parser = argparse.ArgumentParser("Creates or updates and runs the pipeline for the pipeline script.") + + parser.add_argument( + "-n", + "--module-name", + dest="module_name", + type=str, + help="The module name of the pipeline to import.", + ) + parser.add_argument( + "-kwargs", + "--kwargs", + dest="kwargs", + default=None, + help="Dict string of keyword arguments for the pipeline generation (if supported)", + ) + parser.add_argument( + "-role-arn", + "--role-arn", + dest="role_arn", + type=str, + help="The role arn for the pipeline service execution role.", + ) + parser.add_argument( + "-description", + "--description", + dest="description", + type=str, + default=None, + help="The description of the pipeline.", + ) + parser.add_argument( + "-tags", + "--tags", + dest="tags", + default=None, + help="""List of dict strings of '[{"Key": "string", "Value": "string"}, ..]'""", + ) + args = parser.parse_args() + + if args.module_name is None or args.role_arn is None: + parser.print_help() + sys.exit(2) + tags = convert_struct(args.tags) + + try: + pipeline = get_pipeline_driver(args.module_name, args.kwargs) + print("###### Creating/updating a SageMaker Pipeline with the following definition:") + parsed = json.loads(pipeline.definition()) + print(json.dumps(parsed, indent=2, sort_keys=True)) + + all_tags = get_pipeline_custom_tags(args.module_name, args.kwargs, tags) + + upsert_response = pipeline.upsert(role_arn=args.role_arn, description=args.description, tags=all_tags) + + upsert_response = pipeline.upsert( + role_arn=args.role_arn, description=args.description + ) # , tags=tags) # Removing tag momentaneously + print("\n###### Created/Updated SageMaker Pipeline: Response received:") + print(upsert_response) + + execution = pipeline.start() + print(f"\n###### Execution started with PipelineExecutionArn: {execution.arn}") + + # TODO removiong wait time as training can take some time + #print("Waiting for the execution to finish...") + #execution.wait() + #print("\n#####Execution completed. Execution step details:") + print("Execution started. To view the pipeline execution go to SageMaker Studio -> Projects -> Your Project -> Pipelines") + + #print(execution.list_steps()) + except Exception as e: # pylint: disable=W0703 + print(f"Exception: {e}") + sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/training/README.md b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/training/README.md new file mode 100644 index 00000000..8a493ac6 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/training/README.md @@ -0,0 +1,7 @@ +# Training SageMaker Pipeline + +This SageMaker Pipeline definition creates a workflow that will: +- Prepare the Abalone dataset through a SageMaker Processing Job +- Train an XGBoost algorithm on the train set +- Evaluate the performance of the trained XGBoost algorithm on the validation set +- If the performance reaches a specified threshold, send the model for Manual Approval to SageMaker Model Registry. diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/training/__init__.py b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/training/__init__.py new file mode 100644 index 00000000..ff79f21c --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/training/__init__.py @@ -0,0 +1,30 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# SPDX-License-Identifier: MIT-0 +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this +# software and associated documentation files (the "Software"), to deal in the Software +# without restriction, including without limitation the rights to use, copy, modify, +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +# © 2021 Amazon Web Services, Inc. or its affiliates. All Rights Reserved. This +# AWS Content is provided subject to the terms of the AWS Customer Agreement +# available at http://aws.amazon.com/agreement or other written agreement between +# Customer and either Amazon Web Services, Inc. or Amazon Web Services EMEA SARL +# or both. +# +# Any code, applications, scripts, templates, proofs of concept, documentation +# and other items provided by AWS under this SOW are "AWS Content," as defined +# in the Agreement, and are provided for illustration purposes only. All such +# AWS Content is provided solely at the option of AWS, and is subject to the +# terms of the Addendum and the Agreement. Customer is solely responsible for +# using, deploying, testing, and supporting any code and applications provided +# by AWS under this SOW. diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/training/_utils.py b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/training/_utils.py new file mode 100644 index 00000000..78330433 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/training/_utils.py @@ -0,0 +1,86 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# SPDX-License-Identifier: MIT-0 +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this +# software and associated documentation files (the "Software"), to deal in the Software +# without restriction, including without limitation the rights to use, copy, modify, +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import logging + +from botocore.exceptions import ClientError + +logger = logging.getLogger(__name__) + + +def resolve_ecr_uri_from_image_versions(sagemaker_session, image_versions, image_name): + """Gets ECR URI from image versions + Args: + sagemaker_session: boto3 session for sagemaker client + image_versions: list of the image versions + image_name: Name of the image + + Returns: + ECR URI of the image version + """ + + # Fetch image details to get the Base Image URI + for image_version in image_versions: + if image_version["ImageVersionStatus"] == "CREATED": + image_arn = image_version["ImageVersionArn"] + version = image_version["Version"] + logger.info(f"Identified the latest image version: {image_arn}") + response = sagemaker_session.sagemaker_client.describe_image_version(ImageName=image_name, Version=version) + return response["ContainerImage"] + return None + + +def resolve_ecr_uri(sagemaker_session, image_arn): + """Gets the ECR URI from the image name + + Args: + sagemaker_session: boto3 session for sagemaker client + image_name: name of the image + + Returns: + ECR URI of the latest image version + """ + + # Fetching image name from image_arn (^arn:aws(-[\w]+)*:sagemaker:.+:[0-9]{12}:image/[a-z0-9]([-.]?[a-z0-9])*$) + image_name = image_arn.partition("image/")[2] + try: + # Fetch the image versions + next_token = "" + while True: + response = sagemaker_session.sagemaker_client.list_image_versions( + ImageName=image_name, MaxResults=100, SortBy="VERSION", SortOrder="DESCENDING", NextToken=next_token + ) + + ecr_uri = resolve_ecr_uri_from_image_versions(sagemaker_session, response["ImageVersions"], image_name) + + if ecr_uri is not None: + return ecr_uri + + if "NextToken" in response: + next_token = response["NextToken"] + else: + break + + # Return error if no versions of the image found + error_message = f"No image version found for image name: {image_name}" + logger.error(error_message) + raise Exception(error_message) + + except (ClientError, sagemaker_session.sagemaker_client.exceptions.ResourceNotFound) as e: + error_message = e.response["Error"]["Message"] + logger.error(error_message) + raise Exception(error_message) diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/training/pipeline.py b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/training/pipeline.py new file mode 100644 index 00000000..de25b8ba --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/ml_pipelines/training/pipeline.py @@ -0,0 +1,331 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# SPDX-License-Identifier: MIT-0 +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this +# software and associated documentation files (the "Software"), to deal in the Software +# without restriction, including without limitation the rights to use, copy, modify, +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +"""Example workflow pipeline script for abalone pipeline. + + . -RegisterModel + . + Process-> Train -> Evaluate -> Condition . + . + . -(stop) + +Implements a get_pipeline(**kwargs) method. +""" +import os + +import boto3 +import logging +import sagemaker +import sagemaker.session + +from sagemaker.estimator import Estimator +from sagemaker.inputs import TrainingInput +from sagemaker.model_metrics import ( + MetricsSource, + ModelMetrics, +) +from sagemaker.processing import ( + ProcessingInput, + ProcessingOutput, + ScriptProcessor, +) +from sagemaker.sklearn.processing import SKLearnProcessor +from sagemaker.workflow.conditions import ConditionLessThanOrEqualTo +from sagemaker.workflow.condition_step import ( + ConditionStep, +) +from sagemaker.workflow.functions import ( + JsonGet, +) +from sagemaker.workflow.parameters import ( + ParameterInteger, + ParameterString, +) +from sagemaker.workflow.pipeline import Pipeline +from sagemaker.workflow.properties import PropertyFile +from sagemaker.workflow.steps import ( + ProcessingStep, + TrainingStep, +) +from sagemaker.workflow.step_collections import RegisterModel + +from botocore.exceptions import ClientError +from sagemaker.network import NetworkConfig + + +# BASE_DIR = os.path.dirname(os.path.realpath(__file__)) + +logger = logging.getLogger(__name__) + + +def get_session(region, default_bucket): + """Gets the sagemaker session based on the region. + + Args: + region: the aws region to start the session + default_bucket: the bucket to use for storing the artifacts + + Returns: + `sagemaker.session.Session instance + """ + + boto_session = boto3.Session(region_name=region) + + sagemaker_client = boto_session.client("sagemaker") + runtime_client = boto_session.client("sagemaker-runtime") + session = sagemaker.session.Session( + boto_session=boto_session, + sagemaker_client=sagemaker_client, + sagemaker_runtime_client=runtime_client, + default_bucket=default_bucket, + ) + + return session + + +def get_pipeline( + region, + role=None, + default_bucket=None, + bucket_kms_id=None, + model_package_group_name="AbalonePackageGroup", + pipeline_name="AbalonePipeline", + base_job_prefix="Abalone", + project_id="SageMakerProjectId", +): + """Gets a SageMaker ML Pipeline instance working with on abalone data. + + Args: + region: AWS region to create and run the pipeline. + role: IAM role to create and run steps and pipeline. + default_bucket: the bucket to use for storing the artifacts + + Returns: + an instance of a pipeline + """ + + sagemaker_session = get_session(region, default_bucket) + if role is None: + role = sagemaker.session.get_execution_role(sagemaker_session) + + # parameters for pipeline execution + processing_instance_count = ParameterInteger(name="ProcessingInstanceCount", default_value=1) + processing_instance_type = ParameterString(name="ProcessingInstanceType", default_value="ml.m4.xlarge") + training_instance_type = ParameterString(name="TrainingInstanceType", default_value="ml.m4.xlarge") + inference_instance_type = ParameterString(name="InferenceInstanceType", default_value="ml.m4.xlarge") + model_approval_status = ParameterString(name="ModelApprovalStatus", default_value="PendingManualApproval") + input_data = ParameterString( + name="InputDataUrl", + default_value=f"s3://sagemaker-servicecatalog-seedcode-{region}/dataset/abalone-dataset.csv", + ) + processing_image_name = "sagemaker-{0}-processingimagebuild".format(project_id) + training_image_name = "sagemaker-{0}-trainingimagebuild".format(project_id) + inference_image_name = "sagemaker-{0}-inferenceimagebuild".format(project_id) + + # network_config = NetworkConfig( + # enable_network_isolation=True, + # security_group_ids=security_group_ids, + # subnets=subnets, + # encrypt_inter_container_traffic=True, + # ) + + # processing step for feature engineering + try: + processing_image_uri = sagemaker_session.sagemaker_client.describe_image_version( + ImageName=processing_image_name + )["ContainerImage"] + except (sagemaker_session.sagemaker_client.exceptions.ResourceNotFound): + processing_image_uri = sagemaker.image_uris.retrieve( + framework="xgboost", + region=region, + version="1.0-1", + py_version="py3", + instance_type="ml.m4.xlarge", + ) + script_processor = ScriptProcessor( + image_uri=processing_image_uri, + instance_type=processing_instance_type, + instance_count=processing_instance_count, + base_job_name=f"{base_job_prefix}/sklearn-abalone-preprocess", + command=["python3"], + sagemaker_session=sagemaker_session, + role=role, + output_kms_key=bucket_kms_id, + ) + step_process = ProcessingStep( + name="PreprocessAbaloneData", + processor=script_processor, + outputs=[ + ProcessingOutput(output_name="train", source="/opt/ml/processing/train"), + ProcessingOutput(output_name="validation", source="/opt/ml/processing/validation"), + ProcessingOutput(output_name="test", source="/opt/ml/processing/test"), + ], + code="source_scripts/preprocessing/prepare_abalone_data/main.py", # we must figure out this path to get it from step_source directory + job_arguments=["--input-data", input_data], + ) + + # training step for generating model artifacts + model_path = f"s3://{default_bucket}/{base_job_prefix}/AbaloneTrain" + + try: + training_image_uri = sagemaker_session.sagemaker_client.describe_image_version(ImageName=training_image_name)[ + "ContainerImage" + ] + except (sagemaker_session.sagemaker_client.exceptions.ResourceNotFound): + training_image_uri = sagemaker.image_uris.retrieve( + framework="xgboost", + region=region, + version="1.0-1", + py_version="py3", + instance_type="ml.m4.xlarge", + ) + + xgb_train = Estimator( + image_uri=training_image_uri, + instance_type=training_instance_type, + instance_count=1, + output_path=model_path, + base_job_name=f"{base_job_prefix}/abalone-train", + sagemaker_session=sagemaker_session, + role=role, + output_kms_key=bucket_kms_id, + ) + xgb_train.set_hyperparameters( + objective="reg:linear", + num_round=50, + max_depth=5, + eta=0.2, + gamma=4, + min_child_weight=6, + subsample=0.7, + silent=0, + ) + step_train = TrainingStep( + name="TrainAbaloneModel", + estimator=xgb_train, + inputs={ + "train": TrainingInput( + s3_data=step_process.properties.ProcessingOutputConfig.Outputs["train"].S3Output.S3Uri, + content_type="text/csv", + ), + "validation": TrainingInput( + s3_data=step_process.properties.ProcessingOutputConfig.Outputs["validation"].S3Output.S3Uri, + content_type="text/csv", + ), + }, + ) + + # processing step for evaluation + script_eval = ScriptProcessor( + image_uri=training_image_uri, + command=["python3"], + instance_type=processing_instance_type, + instance_count=1, + base_job_name=f"{base_job_prefix}/script-abalone-eval", + sagemaker_session=sagemaker_session, + role=role, + output_kms_key=bucket_kms_id, + ) + evaluation_report = PropertyFile( + name="AbaloneEvaluationReport", + output_name="evaluation", + path="evaluation.json", + ) + step_eval = ProcessingStep( + name="EvaluateAbaloneModel", + processor=script_eval, + inputs=[ + ProcessingInput( + source=step_train.properties.ModelArtifacts.S3ModelArtifacts, + destination="/opt/ml/processing/model", + ), + ProcessingInput( + source=step_process.properties.ProcessingOutputConfig.Outputs["test"].S3Output.S3Uri, + destination="/opt/ml/processing/test", + ), + ], + outputs=[ + ProcessingOutput(output_name="evaluation", source="/opt/ml/processing/evaluation"), + ], + code="source_scripts/evaluate/evaluate_xgboost/main.py", + property_files=[evaluation_report], + ) + + # register model step that will be conditionally executed + model_metrics = ModelMetrics( + model_statistics=MetricsSource( + s3_uri="{}/evaluation.json".format( + step_eval.arguments["ProcessingOutputConfig"]["Outputs"][0]["S3Output"]["S3Uri"] + ), + content_type="application/json", + ) + ) + + try: + inference_image_uri = sagemaker_session.sagemaker_client.describe_image_version(ImageName=inference_image_name)[ + "ContainerImage" + ] + except (sagemaker_session.sagemaker_client.exceptions.ResourceNotFound): + inference_image_uri = sagemaker.image_uris.retrieve( + framework="xgboost", + region=region, + version="1.0-1", + py_version="py3", + instance_type="ml.m4.xlarge", + ) + step_register = RegisterModel( + name="RegisterAbaloneModel", + estimator=xgb_train, + image_uri=inference_image_uri, + model_data=step_train.properties.ModelArtifacts.S3ModelArtifacts, + content_types=["text/csv"], + response_types=["text/csv"], + inference_instances=["ml.m4.xlarge", "ml.m4.xlarge"], + transform_instances=["ml.m4.xlarge"], + model_package_group_name=model_package_group_name, + approval_status=model_approval_status, + model_metrics=model_metrics, + ) + + # condition step for evaluating model quality and branching execution + cond_lte = ConditionLessThanOrEqualTo( + left=JsonGet( + step_name=step_eval.name, property_file=evaluation_report, json_path="regression_metrics.mse.value" + ), + right=6.0, + ) + step_cond = ConditionStep( + name="CheckMSEAbaloneEvaluation", + conditions=[cond_lte], + if_steps=[step_register], + else_steps=[], + ) + + # pipeline instance + pipeline = Pipeline( + name=pipeline_name, + parameters=[ + processing_instance_type, + processing_instance_count, + training_instance_type, + model_approval_status, + input_data, + ], + steps=[step_process, step_train, step_eval, step_cond], + sagemaker_session=sagemaker_session, + ) + return pipeline diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/notebooks/README.md b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/notebooks/README.md new file mode 100644 index 00000000..c0749333 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/notebooks/README.md @@ -0,0 +1,4 @@ +# Jupyter Notebooks + +This folder is intended to store your experiment notebooks. +Typically the first step would be to store your Data Science notebooks, and start defining example SageMaker pipelines in here. Once satisfied with the first iteration of a SageMaker pipeline, the code should move as python scripts inside the respective `ml_pipelines/` and `source_scripts/` folders. diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/notebooks/sagemaker-pipelines-preprocess-train-evaluate-batch-transform.ipynb b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/notebooks/sagemaker-pipelines-preprocess-train-evaluate-batch-transform.ipynb new file mode 100644 index 00000000..58db3199 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/notebooks/sagemaker-pipelines-preprocess-train-evaluate-batch-transform.ipynb @@ -0,0 +1,1577 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "# Orchestrate Jobs to Train and Evaluate Models with Amazon SageMaker Pipelines\n", + "\n", + "Amazon SageMaker Pipelines offers machine learning (ML) application developers and operations engineers the ability to orchestrate SageMaker jobs and author reproducible ML pipelines. It also enables them to deploy custom-built models for inference in real-time with low latency, run offline inferences with Batch Transform, and track lineage of artifacts. They can institute sound operational practices in deploying and monitoring production workflows, deploying model artifacts, and tracking artifact lineage through a simple interface, adhering to safety and best practice paradigms for ML application development.\n", + "\n", + "The SageMaker Pipelines service supports a SageMaker Pipeline domain specific language (DSL), which is a declarative JSON specification. This DSL defines a directed acyclic graph (DAG) of pipeline parameters and SageMaker job steps. The SageMaker Python Software Developer Kit (SDK) streamlines the generation of the pipeline DSL using constructs that engineers and scientists are already familiar with.\n", + "\n", + "## Runtime\n", + "\n", + "This notebook takes approximately an hour to run.\n", + "\n", + "## Contents\n", + "\n", + "1. [SageMaker Pipelines](#SageMaker-Pipelines)\n", + "1. [Notebook Overview](#Notebook-Overview)\n", + "1. [A SageMaker Pipeline](#A-SageMaker-Pipeline)\n", + "1. [Dataset](#Dataset)\n", + "1. [Define Parameters to Parametrize Pipeline Execution](#Define-Parameters-to-Parametrize-Pipeline-Execution)\n", + "1. [Define a Processing Step for Feature Engineering](#Define-a-Processing-Step-for-Feature-Engineering)\n", + "1. [Define a Training Step to Train a Model](#Define-a-Training-Step-to-Train-a-Model)\n", + "1. [Define a Model Evaluation Step to Evaluate the Trained Model](#Define-a-Model-Evaluation-Step-to-Evaluate-the-Trained-Model)\n", + "1. [Define a Create Model Step to Create a Model](#Define-a-Create-Model-Step-to-Create-a-Model)\n", + "1. [Define a Transform Step to Perform Batch Transformation](#Define-a-Transform-Step-to-Perform-Batch-Transformation)\n", + "1. [Define a Register Model Step to Create a Model Package](#Define-a-Register-Model-Step-to-Create-a-Model-Package)\n", + "1. [Define a Fail Step to Terminate the Pipeline Execution and Mark it as Failed](#Define-a-Fail-Step-to-Terminate-the-Pipeline-Execution-and-Mark-it-as-Failed)\n", + "1. [Define a Condition Step to Check Accuracy and Conditionally Create a Model and Run a Batch Transformation and Register a Model in the Model Registry, Or Terminate the Execution in Failed State](#Define-a-Condition-Step-to-Check-Accuracy-and-Conditionally-Create-a-Model-and-Run-a-Batch-Transformation-and-Register-a-Model-in-the-Model-Registry,-Or-Terminate-the-Execution-in-Failed-State)\n", + "1. [Define a Pipeline of Parameters, Steps, and Conditions](#Define-a-Pipeline-of-Parameters,-Steps,-and-Conditions)\n", + "1. [Submit the pipeline to SageMaker and start execution](#Submit-the-pipeline-to-SageMaker-and-start-execution)\n", + "1. [Pipeline Operations: Examining and Waiting for Pipeline Execution](#Pipeline-Operations:-Examining-and-Waiting-for-Pipeline-Execution)\n", + " 1. [Examining the Evaluation](#Examining-the-Evaluation)\n", + " 1. [Lineage](#Lineage)\n", + " 1. [Parametrized Executions](#Parametrized-Executions)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "## SageMaker Pipelines\n", + "\n", + "SageMaker Pipelines supports the following activities, which are demonstrated in this notebook:\n", + "\n", + "* Pipelines - A DAG of steps and conditions to orchestrate SageMaker jobs and resource creation.\n", + "* Processing job steps - A simplified, managed experience on SageMaker to run data processing workloads, such as feature engineering, data validation, model evaluation, and model interpretation.\n", + "* Training job steps - An iterative process that teaches a model to make predictions by presenting examples from a training dataset.\n", + "* Conditional execution steps - A step that provides conditional execution of branches in a pipeline.\n", + "* Register model steps - A step that creates a model package resource in the Model Registry that can be used to create deployable models in Amazon SageMaker.\n", + "* Create model steps - A step that creates a model for use in transform steps or later publication as an endpoint.\n", + "* Transform job steps - A batch transform to preprocess datasets to remove noise or bias that interferes with training or inference from a dataset, get inferences from large datasets, and run inference when a persistent endpoint is not needed.\n", + "* Fail steps - A step that stops a pipeline execution and marks the pipeline execution as failed.\n", + "* Parametrized Pipeline executions - Enables variation in pipeline executions according to specified parameters." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "## Notebook Overview\n", + "\n", + "This notebook shows how to:\n", + "\n", + "* Define a set of Pipeline parameters that can be used to parametrize a SageMaker Pipeline.\n", + "* Define a Processing step that performs cleaning, feature engineering, and splitting the input data into train and test data sets.\n", + "* Define a Training step that trains a model on the preprocessed train data set.\n", + "* Define a Processing step that evaluates the trained model's performance on the test dataset.\n", + "* Define a Create Model step that creates a model from the model artifacts used in training.\n", + "* Define a Transform step that performs batch transformation based on the model that was created.\n", + "* Define a Register Model step that creates a model package from the estimator and model artifacts used to train the model.\n", + "* Define a Conditional step that measures a condition based on output from prior steps and conditionally executes other steps.\n", + "* Define a Fail step with a customized error message indicating the cause of the execution failure.\n", + "* Define and create a Pipeline definition in a DAG, with the defined parameters and steps.\n", + "* Start a Pipeline execution and wait for execution to complete.\n", + "* Download the model evaluation report from the S3 bucket for examination.\n", + "* Start a second Pipeline execution." + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "## A SageMaker Pipeline\n", + "\n", + "The pipeline that you create follows a typical machine learning (ML) application pattern of preprocessing, training, evaluation, model creation, batch transformation, and model registration:\n", + "\n", + "![A typical ML Application pipeline](img/pipeline-full.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "## Dataset\n", + "\n", + "The dataset you use is the [UCI Machine Learning Abalone Dataset](https://archive.ics.uci.edu/ml/datasets/abalone) [1]. The aim for this task is to determine the age of an abalone snail from its physical measurements. At the core, this is a regression problem.\n", + "\n", + "The dataset contains several features: length (the longest shell measurement), diameter (the diameter perpendicular to length), height (the height with meat in the shell), whole_weight (the weight of whole abalone), shucked_weight (the weight of meat), viscera_weight (the gut weight after bleeding), shell_weight (the weight after being dried), sex ('M', 'F', 'I' where 'I' is Infant), and rings (integer).\n", + "\n", + "The number of rings turns out to be a good approximation for age (age is rings + 1.5). However, to obtain this number requires cutting the shell through the cone, staining the section, and counting the number of rings through a microscope, which is a time-consuming task. However, the other physical measurements are easier to determine. You use the dataset to build a predictive model of the variable rings through these other physical measurements.\n", + "\n", + "Before you upload the data to an S3 bucket, install the SageMaker Python SDK and gather some constants you can use later in this notebook.\n", + "\n", + "> [1] Dua, D. and Graff, C. (2019). [UCI Machine Learning Repository](http://archive.ics.uci.edu/ml). Irvine, CA: University of California, School of Information and Computer Science." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "import sys\n", + "\n", + "!{sys.executable} -m pip install \"sagemaker>=2.99.0\"\n", + "\n", + "import boto3\n", + "import sagemaker\n", + "from sagemaker.workflow.pipeline_context import PipelineSession\n", + "\n", + "sagemaker_session = sagemaker.session.Session()\n", + "region = sagemaker_session.boto_region_name\n", + "role = sagemaker.get_execution_role()\n", + "pipeline_session = PipelineSession()\n", + "default_bucket = sagemaker_session.default_bucket()\n", + "model_package_group_name = f\"AbaloneModelPackageGroupName\"" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "Now, upload the data into the default bucket. You can select our own data set for the `input_data_uri` as is appropriate." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "!mkdir -p data" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "local_path = \"data/abalone-dataset.csv\"\n", + "\n", + "s3 = boto3.resource(\"s3\")\n", + "s3.Bucket(f\"sagemaker-sample-files\").download_file(\n", + " \"datasets/tabular/uci_abalone/abalone.csv\", local_path\n", + ")\n", + "\n", + "base_uri = f\"s3://{default_bucket}/abalone\"\n", + "input_data_uri = sagemaker.s3.S3Uploader.upload(\n", + " local_path=local_path,\n", + " desired_s3_uri=base_uri,\n", + ")\n", + "print(input_data_uri)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "Download a second dataset for batch transformation after model creation. You can select our own dataset for the `batch_data_uri` as is appropriate." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "local_path = \"data/abalone-dataset-batch\"\n", + "\n", + "s3 = boto3.resource(\"s3\")\n", + "s3.Bucket(f\"sagemaker-servicecatalog-seedcode-{region}\").download_file(\n", + " \"dataset/abalone-dataset-batch\", local_path\n", + ")\n", + "\n", + "base_uri = f\"s3://{default_bucket}/abalone\"\n", + "batch_data_uri = sagemaker.s3.S3Uploader.upload(\n", + " local_path=local_path,\n", + " desired_s3_uri=base_uri,\n", + ")\n", + "print(batch_data_uri)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "## Define Parameters to Parametrize Pipeline Execution\n", + "\n", + "Define Pipeline parameters that you can use to parametrize the pipeline. Parameters enable custom pipeline executions and schedules without having to modify the Pipeline definition.\n", + "\n", + "The supported parameter types include:\n", + "\n", + "* `ParameterString` - represents a `str` Python type\n", + "* `ParameterInteger` - represents an `int` Python type\n", + "* `ParameterFloat` - represents a `float` Python type\n", + "\n", + "These parameters support providing a default value, which can be overridden on pipeline execution. The default value specified should be an instance of the type of the parameter.\n", + "\n", + "The parameters defined in this workflow include:\n", + "\n", + "* `processing_instance_count` - The instance count of the processing job.\n", + "* `instance_type` - The `ml.*` instance type of the training job.\n", + "* `model_approval_status` - The approval status to register with the trained model for CI/CD purposes (\"PendingManualApproval\" is the default).\n", + "* `input_data` - The S3 bucket URI location of the input data.\n", + "* `batch_data` - The S3 bucket URI location of the batch data.\n", + "* `mse_threshold` - The Mean Squared Error (MSE) threshold used to verify the accuracy of a model." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "from sagemaker.workflow.parameters import (\n", + " ParameterInteger,\n", + " ParameterString,\n", + " ParameterFloat,\n", + ")\n", + "\n", + "processing_instance_count = ParameterInteger(name=\"ProcessingInstanceCount\", default_value=1)\n", + "instance_type = ParameterString(name=\"TrainingInstanceType\", default_value=\"ml.m4.xlarge\")\n", + "model_approval_status = ParameterString(\n", + " name=\"ModelApprovalStatus\", default_value=\"PendingManualApproval\"\n", + ")\n", + "input_data = ParameterString(\n", + " name=\"InputData\",\n", + " default_value=input_data_uri,\n", + ")\n", + "batch_data = ParameterString(\n", + " name=\"BatchData\",\n", + " default_value=batch_data_uri,\n", + ")\n", + "mse_threshold = ParameterFloat(name=\"MseThreshold\", default_value=6.0)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "![Define Parameters](img/pipeline-1.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "## Define a Processing Step for Feature Engineering\n", + "\n", + "First, develop a preprocessing script that is specified in the Processing step.\n", + "\n", + "This notebook cell writes a file `preprocessing_abalone.py`, which contains the preprocessing script. You can update the script, and rerun this cell to overwrite. The preprocessing script uses `scikit-learn` to do the following:\n", + "\n", + "* Fill in missing sex category data and encode it so that it is suitable for training.\n", + "* Scale and normalize all numerical fields, aside from sex and rings numerical data.\n", + "* Split the data into training, validation, and test datasets.\n", + "\n", + "The Processing step executes the script on the input data. The Training step uses the preprocessed training features and labels to train a model. The Evaluation step uses the trained model and preprocessed test features and labels to evaluate the model." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "!mkdir -p code" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "%%writefile code/preprocessing.py\n", + "import argparse\n", + "import os\n", + "import requests\n", + "import tempfile\n", + "\n", + "import numpy as np\n", + "import pandas as pd\n", + "\n", + "from sklearn.compose import ColumnTransformer\n", + "from sklearn.impute import SimpleImputer\n", + "from sklearn.pipeline import Pipeline\n", + "from sklearn.preprocessing import StandardScaler, OneHotEncoder\n", + "\n", + "\n", + "# Since we get a headerless CSV file, we specify the column names here.\n", + "feature_columns_names = [\n", + " \"sex\",\n", + " \"length\",\n", + " \"diameter\",\n", + " \"height\",\n", + " \"whole_weight\",\n", + " \"shucked_weight\",\n", + " \"viscera_weight\",\n", + " \"shell_weight\",\n", + "]\n", + "label_column = \"rings\"\n", + "\n", + "feature_columns_dtype = {\n", + " \"sex\": str,\n", + " \"length\": np.float64,\n", + " \"diameter\": np.float64,\n", + " \"height\": np.float64,\n", + " \"whole_weight\": np.float64,\n", + " \"shucked_weight\": np.float64,\n", + " \"viscera_weight\": np.float64,\n", + " \"shell_weight\": np.float64,\n", + "}\n", + "label_column_dtype = {\"rings\": np.float64}\n", + "\n", + "\n", + "def merge_two_dicts(x, y):\n", + " z = x.copy()\n", + " z.update(y)\n", + " return z\n", + "\n", + "\n", + "if __name__ == \"__main__\":\n", + " base_dir = \"/opt/ml/processing\"\n", + "\n", + " df = pd.read_csv(\n", + " f\"{base_dir}/input/abalone-dataset.csv\",\n", + " header=None,\n", + " names=feature_columns_names + [label_column],\n", + " dtype=merge_two_dicts(feature_columns_dtype, label_column_dtype),\n", + " )\n", + " numeric_features = list(feature_columns_names)\n", + " numeric_features.remove(\"sex\")\n", + " numeric_transformer = Pipeline(\n", + " steps=[(\"imputer\", SimpleImputer(strategy=\"median\")), (\"scaler\", StandardScaler())]\n", + " )\n", + "\n", + " categorical_features = [\"sex\"]\n", + " categorical_transformer = Pipeline(\n", + " steps=[\n", + " (\"imputer\", SimpleImputer(strategy=\"constant\", fill_value=\"missing\")),\n", + " (\"onehot\", OneHotEncoder(handle_unknown=\"ignore\")),\n", + " ]\n", + " )\n", + "\n", + " preprocess = ColumnTransformer(\n", + " transformers=[\n", + " (\"num\", numeric_transformer, numeric_features),\n", + " (\"cat\", categorical_transformer, categorical_features),\n", + " ]\n", + " )\n", + "\n", + " y = df.pop(\"rings\")\n", + " X_pre = preprocess.fit_transform(df)\n", + " y_pre = y.to_numpy().reshape(len(y), 1)\n", + "\n", + " X = np.concatenate((y_pre, X_pre), axis=1)\n", + "\n", + " np.random.shuffle(X)\n", + " train, validation, test = np.split(X, [int(0.7 * len(X)), int(0.85 * len(X))])\n", + "\n", + " pd.DataFrame(train).to_csv(f\"{base_dir}/train/train.csv\", header=False, index=False)\n", + " pd.DataFrame(validation).to_csv(\n", + " f\"{base_dir}/validation/validation.csv\", header=False, index=False\n", + " )\n", + " pd.DataFrame(test).to_csv(f\"{base_dir}/test/test.csv\", header=False, index=False)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "Next, create an instance of a `SKLearnProcessor` processor and use that in our `ProcessingStep`.\n", + "\n", + "You also specify the `framework_version` to use throughout this notebook.\n", + "\n", + "Note the `processing_instance_count` parameter used by the processor instance." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "from sagemaker.sklearn.processing import SKLearnProcessor\n", + "\n", + "\n", + "framework_version = \"0.23-1\"\n", + "\n", + "sklearn_processor = SKLearnProcessor(\n", + " framework_version=framework_version,\n", + " instance_type=\"ml.m4.xlarge\",\n", + " instance_count=processing_instance_count,\n", + " base_job_name=\"sklearn-abalone-process\",\n", + " role=role,\n", + " sagemaker_session=pipeline_session,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "Finally, we take the output of the processor's `run` method and pass that as arguments to the `ProcessingStep`. By passing the `pipeline_session` to the `sagemaker_session`, calling `.run()` does not launch the processing job, it returns the arguments needed to run the job as a step in the pipeline.\n", + "\n", + "Note the `\"train_data\"` and `\"test_data\"` named channels specified in the output configuration for the processing job. Step `Properties` can be used in subsequent steps and resolve to their runtime values at execution. Specifically, this usage is called out when you define the training step." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "from sagemaker.processing import ProcessingInput, ProcessingOutput\n", + "from sagemaker.workflow.steps import ProcessingStep\n", + "\n", + "processor_args = sklearn_processor.run(\n", + " inputs=[\n", + " ProcessingInput(source=input_data, destination=\"/opt/ml/processing/input\"),\n", + " ],\n", + " outputs=[\n", + " ProcessingOutput(output_name=\"train\", source=\"/opt/ml/processing/train\"),\n", + " ProcessingOutput(output_name=\"validation\", source=\"/opt/ml/processing/validation\"),\n", + " ProcessingOutput(output_name=\"test\", source=\"/opt/ml/processing/test\"),\n", + " ],\n", + " code=\"code/preprocessing.py\",\n", + ")\n", + "\n", + "step_process = ProcessingStep(name=\"AbaloneProcess\", step_args=processor_args)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "![Define a Processing Step for Feature Engineering](img/pipeline-2.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "## Define a Training Step to Train a Model\n", + "\n", + "In this section, use Amazon SageMaker's [XGBoost Algorithm](https://docs.aws.amazon.com/sagemaker/latest/dg/xgboost.html) to train on this dataset. Configure an Estimator for the XGBoost algorithm and the input dataset. A typical training script loads data from the input channels, configures training with hyperparameters, trains a model, and saves a model to `model_dir` so that it can be hosted later.\n", + "\n", + "The model path where the models from training are saved is also specified.\n", + "\n", + "Note the `instance_type` parameter may be used in multiple places in the pipeline. In this case, the `instance_type` is passed into the estimator." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "from sagemaker.estimator import Estimator\n", + "from sagemaker.inputs import TrainingInput\n", + "\n", + "model_path = f\"s3://{default_bucket}/AbaloneTrain\"\n", + "image_uri = sagemaker.image_uris.retrieve(\n", + " framework=\"xgboost\",\n", + " region=region,\n", + " version=\"1.0-1\",\n", + " py_version=\"py3\",\n", + " instance_type=\"ml.m4.xlarge\",\n", + ")\n", + "xgb_train = Estimator(\n", + " image_uri=image_uri,\n", + " instance_type=instance_type,\n", + " instance_count=1,\n", + " output_path=model_path,\n", + " role=role,\n", + " sagemaker_session=pipeline_session,\n", + ")\n", + "xgb_train.set_hyperparameters(\n", + " objective=\"reg:linear\",\n", + " num_round=50,\n", + " max_depth=5,\n", + " eta=0.2,\n", + " gamma=4,\n", + " min_child_weight=6,\n", + " subsample=0.7,\n", + ")\n", + "\n", + "train_args = xgb_train.fit(\n", + " inputs={\n", + " \"train\": TrainingInput(\n", + " s3_data=step_process.properties.ProcessingOutputConfig.Outputs[\"train\"].S3Output.S3Uri,\n", + " content_type=\"text/csv\",\n", + " ),\n", + " \"validation\": TrainingInput(\n", + " s3_data=step_process.properties.ProcessingOutputConfig.Outputs[\n", + " \"validation\"\n", + " ].S3Output.S3Uri,\n", + " content_type=\"text/csv\",\n", + " ),\n", + " }\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "Finally, we use the output of the estimator's `.fit()` method as arguments to the `TrainingStep`. By passing the `pipeline_session` to the `sagemaker_session`, calling `.fit()` does not launch the training job, it returns the arguments needed to run the job as a step in the pipeline.\n", + "\n", + "Pass in the `S3Uri` of the `\"train_data\"` output channel to the `.fit()` method. Also, use the other `\"test_data\"` output channel for model evaluation in the pipeline. The `properties` attribute of a Pipeline step matches the object model of the corresponding response of a describe call. These properties can be referenced as placeholder values and are resolved at runtime. For example, the `ProcessingStep` `properties` attribute matches the object model of the [DescribeProcessingJob](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_DescribeProcessingJob.html) response object." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "from sagemaker.inputs import TrainingInput\n", + "from sagemaker.workflow.steps import TrainingStep\n", + "\n", + "\n", + "step_train = TrainingStep(\n", + " name=\"AbaloneTrain\",\n", + " step_args=train_args,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "![Define a Training Step to Train a Model](img/pipeline-3.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "## Define a Model Evaluation Step to Evaluate the Trained Model\n", + "\n", + "First, develop an evaluation script that is specified in a Processing step that performs the model evaluation.\n", + "\n", + "After pipeline execution, you can examine the resulting `evaluation.json` for analysis.\n", + "\n", + "The evaluation script uses `xgboost` to do the following:\n", + "\n", + "* Load the model.\n", + "* Read the test data.\n", + "* Issue predictions against the test data.\n", + "* Build a classification report, including accuracy and ROC curve.\n", + "* Save the evaluation report to the evaluation directory." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "%%writefile code/evaluation.py\n", + "import json\n", + "import pathlib\n", + "import pickle\n", + "import tarfile\n", + "\n", + "import joblib\n", + "import numpy as np\n", + "import pandas as pd\n", + "import xgboost\n", + "\n", + "from sklearn.metrics import mean_squared_error\n", + "\n", + "\n", + "if __name__ == \"__main__\":\n", + " model_path = f\"/opt/ml/processing/model/model.tar.gz\"\n", + " with tarfile.open(model_path) as tar:\n", + " tar.extractall(path=\".\")\n", + "\n", + " model = pickle.load(open(\"xgboost-model\", \"rb\"))\n", + "\n", + " test_path = \"/opt/ml/processing/test/test.csv\"\n", + " df = pd.read_csv(test_path, header=None)\n", + "\n", + " y_test = df.iloc[:, 0].to_numpy()\n", + " df.drop(df.columns[0], axis=1, inplace=True)\n", + "\n", + " X_test = xgboost.DMatrix(df.values)\n", + "\n", + " predictions = model.predict(X_test)\n", + "\n", + " mse = mean_squared_error(y_test, predictions)\n", + " std = np.std(y_test - predictions)\n", + " report_dict = {\n", + " \"regression_metrics\": {\n", + " \"mse\": {\"value\": mse, \"standard_deviation\": std},\n", + " },\n", + " }\n", + "\n", + " output_dir = \"/opt/ml/processing/evaluation\"\n", + " pathlib.Path(output_dir).mkdir(parents=True, exist_ok=True)\n", + "\n", + " evaluation_path = f\"{output_dir}/evaluation.json\"\n", + " with open(evaluation_path, \"w\") as f:\n", + " f.write(json.dumps(report_dict))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "Next, create an instance of a `ScriptProcessor` processor and use it in the `ProcessingStep`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "from sagemaker.processing import ScriptProcessor\n", + "\n", + "\n", + "script_eval = ScriptProcessor(\n", + " image_uri=image_uri,\n", + " command=[\"python3\"],\n", + " instance_type=\"ml.m4.xlarge\",\n", + " instance_count=1,\n", + " base_job_name=\"script-abalone-eval\",\n", + " role=role,\n", + " sagemaker_session=pipeline_session,\n", + ")\n", + "\n", + "eval_args = script_eval.run(\n", + " inputs=[\n", + " ProcessingInput(\n", + " source=step_train.properties.ModelArtifacts.S3ModelArtifacts,\n", + " destination=\"/opt/ml/processing/model\",\n", + " ),\n", + " ProcessingInput(\n", + " source=step_process.properties.ProcessingOutputConfig.Outputs[\"test\"].S3Output.S3Uri,\n", + " destination=\"/opt/ml/processing/test\",\n", + " ),\n", + " ],\n", + " outputs=[\n", + " ProcessingOutput(output_name=\"evaluation\", source=\"/opt/ml/processing/evaluation\"),\n", + " ],\n", + " code=\"code/evaluation.py\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "Use the processor's arguments returned by `.run()` to construct a `ProcessingStep`, along with the input and output channels and the code that will be executed when the pipeline invokes pipeline execution.\n", + "\n", + "Specifically, the `S3ModelArtifacts` from the `step_train` `properties` and the `S3Uri` of the `\"test_data\"` output channel of the `step_process` `properties` are passed as inputs. The `TrainingStep` and `ProcessingStep` `properties` attribute matches the object model of the [DescribeTrainingJob](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_DescribeTrainingJob.html) and [DescribeProcessingJob](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_DescribeProcessingJob.html) response objects, respectively." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "from sagemaker.workflow.properties import PropertyFile\n", + "\n", + "\n", + "evaluation_report = PropertyFile(\n", + " name=\"EvaluationReport\", output_name=\"evaluation\", path=\"evaluation.json\"\n", + ")\n", + "step_eval = ProcessingStep(\n", + " name=\"AbaloneEval\",\n", + " step_args=eval_args,\n", + " property_files=[evaluation_report],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "![Define a Model Evaluation Step to Evaluate the Trained Model](img/pipeline-4.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "## Define a Create Model Step to Create a Model\n", + "\n", + "In order to perform batch transformation using the example model, create a SageMaker model.\n", + "\n", + "Specifically, pass in the `S3ModelArtifacts` from the `TrainingStep`, `step_train` properties. The `TrainingStep` `properties` attribute matches the object model of the [DescribeTrainingJob](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_DescribeTrainingJob.html) response object." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "from sagemaker.model import Model\n", + "\n", + "model = Model(\n", + " image_uri=image_uri,\n", + " model_data=step_train.properties.ModelArtifacts.S3ModelArtifacts,\n", + " sagemaker_session=pipeline_session,\n", + " role=role,\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "Define the `ModelStep` by providing the return values from `model.create()` as the step arguments." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "from sagemaker.inputs import CreateModelInput\n", + "from sagemaker.workflow.model_step import ModelStep\n", + "\n", + "step_create_model = ModelStep(\n", + " name=\"AbaloneCreateModel\",\n", + " step_args=model.create(instance_type=\"ml.m4.xlarge\", accelerator_type=\"ml.eia1.medium\"),\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "## Define a Transform Step to Perform Batch Transformation\n", + "\n", + "Now that a model instance is defined, create a `Transformer` instance with the appropriate model type, compute instance type, and desired output S3 URI.\n", + "\n", + "Specifically, pass in the `ModelName` from the `CreateModelStep`, `step_create_model` properties. The `CreateModelStep` `properties` attribute matches the object model of the [DescribeModel](https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_DescribeModel.html) response object." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "from sagemaker.transformer import Transformer\n", + "\n", + "\n", + "transformer = Transformer(\n", + " model_name=step_create_model.properties.ModelName,\n", + " instance_type=\"ml.m4.xlarge\",\n", + " instance_count=1,\n", + " output_path=f\"s3://{default_bucket}/AbaloneTransform\",\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "Pass in the transformer instance and the `TransformInput` with the `batch_data` pipeline parameter defined earlier." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "from sagemaker.inputs import TransformInput\n", + "from sagemaker.workflow.steps import TransformStep\n", + "\n", + "\n", + "step_transform = TransformStep(\n", + " name=\"AbaloneTransform\", transformer=transformer, inputs=TransformInput(data=batch_data)\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "## Define a Register Model Step to Create a Model Package\n", + "\n", + "A model package is an abstraction of reusable model artifacts that packages all ingredients required for inference. Primarily, it consists of an inference specification that defines the inference image to use along with an optional model weights location.\n", + "\n", + "A model package group is a collection of model packages. A model package group can be created for a specific ML business problem, and new versions of the model packages can be added to it. Typically, customers are expected to create a ModelPackageGroup for a SageMaker pipeline so that model package versions can be added to the group for every SageMaker Pipeline run.\n", + "\n", + "To register a model in the Model Registry, we take the model created in the previous steps\n", + "```\n", + "model = Model(\n", + " image_uri=image_uri,\n", + " model_data=step_train.properties.ModelArtifacts.S3ModelArtifacts,\n", + " sagemaker_session=pipeline_session,\n", + " role=role,\n", + ")\n", + "```\n", + "and call the `.register()` function on it while passing all the parameters needed for registering the model.\n", + "\n", + "We take the outputs of the `.register()` call and pass that to the `ModelStep` as step arguments." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "from sagemaker.model_metrics import MetricsSource, ModelMetrics\n", + "\n", + "model_metrics = ModelMetrics(\n", + " model_statistics=MetricsSource(\n", + " s3_uri=\"{}/evaluation.json\".format(\n", + " step_eval.arguments[\"ProcessingOutputConfig\"][\"Outputs\"][0][\"S3Output\"][\"S3Uri\"]\n", + " ),\n", + " content_type=\"application/json\",\n", + " )\n", + ")\n", + "\n", + "register_args = model.register(\n", + " content_types=[\"text/csv\"],\n", + " response_types=[\"text/csv\"],\n", + " inference_instances=[\"ml.m4.xlarge\"],\n", + " transform_instances=[\"ml.m4.xlarge\"],\n", + " model_package_group_name=model_package_group_name,\n", + " approval_status=model_approval_status,\n", + " model_metrics=model_metrics,\n", + ")\n", + "step_register = ModelStep(name=\"AbaloneRegisterModel\", step_args=register_args)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "![Define a Create Model Step and Batch Transform to Process Data in Batch at Scale](img/pipeline-5.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "## Define a Fail Step to Terminate the Pipeline Execution and Mark it as Failed\n", + "\n", + "This section walks you through the following steps:\n", + "\n", + "* Define a `FailStep` with customized error message, which indicates the cause of the execution failure.\n", + "* Enter the `FailStep` error message with a `Join` function, which appends a static text string with the dynamic `mse_threshold` parameter to build a more informative error message." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "from sagemaker.workflow.fail_step import FailStep\n", + "from sagemaker.workflow.functions import Join\n", + "\n", + "step_fail = FailStep(\n", + " name=\"AbaloneMSEFail\",\n", + " error_message=Join(on=\" \", values=[\"Execution failed due to MSE >\", mse_threshold]),\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "![Define a Fail Step to Terminate the Execution in Failed State](img/pipeline-8.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "## Define a Condition Step to Check Accuracy and Conditionally Create a Model and Run a Batch Transformation and Register a Model in the Model Registry, Or Terminate the Execution in Failed State\n", + "\n", + "In this step, the model is registered only if the accuracy of the model, as determined by the evaluation step `step_eval`, exceeded a specified value. Otherwise, the pipeline execution fails and terminates. A `ConditionStep` enables pipelines to support conditional execution in the pipeline DAG based on the conditions of the step properties.\n", + "\n", + "In the following section, you:\n", + "\n", + "* Define a `ConditionLessThanOrEqualTo` on the accuracy value found in the output of the evaluation step, `step_eval`.\n", + "* Use the condition in the list of conditions in a `ConditionStep`.\n", + "* Pass the `CreateModelStep` and `TransformStep` steps, and the `RegisterModel` step collection into the `if_steps` of the `ConditionStep`, which are only executed if the condition evaluates to `True`.\n", + "* Pass the `FailStep` step into the `else_steps`of the `ConditionStep`, which is only executed if the condition evaluates to `False`." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "from sagemaker.workflow.conditions import ConditionLessThanOrEqualTo\n", + "from sagemaker.workflow.condition_step import ConditionStep\n", + "from sagemaker.workflow.functions import JsonGet\n", + "\n", + "\n", + "cond_lte = ConditionLessThanOrEqualTo(\n", + " left=JsonGet(\n", + " step_name=step_eval.name,\n", + " property_file=evaluation_report,\n", + " json_path=\"regression_metrics.mse.value\",\n", + " ),\n", + " right=mse_threshold,\n", + ")\n", + "\n", + "step_cond = ConditionStep(\n", + " name=\"AbaloneMSECond\",\n", + " conditions=[cond_lte],\n", + " if_steps=[step_register, step_create_model, step_transform],\n", + " else_steps=[step_fail],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "![Define a Condition Step to Check Accuracy and Conditionally Execute Steps](img/pipeline-6.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "## Define a Pipeline of Parameters, Steps, and Conditions\n", + "\n", + "In this section, combine the steps into a Pipeline so it can be executed.\n", + "\n", + "A pipeline requires a `name`, `parameters`, and `steps`. Names must be unique within an `(account, region)` pair.\n", + "\n", + "Note:\n", + "\n", + "* All the parameters used in the definitions must be present.\n", + "* Steps passed into the pipeline do not have to be listed in the order of execution. The SageMaker Pipeline service resolves the data dependency DAG as steps for the execution to complete.\n", + "* Steps must be unique to across the pipeline step list and all condition step if/else lists." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "from sagemaker.workflow.pipeline import Pipeline\n", + "\n", + "\n", + "pipeline_name = f\"AbalonePipeline\"\n", + "pipeline = Pipeline(\n", + " name=pipeline_name,\n", + " parameters=[\n", + " processing_instance_count,\n", + " instance_type,\n", + " model_approval_status,\n", + " input_data,\n", + " batch_data,\n", + " mse_threshold,\n", + " ],\n", + " steps=[step_process, step_train, step_eval, step_cond],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "![Define a Pipeline of Parameters, Steps, and Conditions](img/pipeline-7.png)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "### (Optional) Examining the pipeline definition\n", + "\n", + "The JSON of the pipeline definition can be examined to confirm the pipeline is well-defined and the parameters and step properties resolve correctly." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "import json\n", + "\n", + "\n", + "definition = json.loads(pipeline.definition())\n", + "definition" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "## Submit the pipeline to SageMaker and start execution\n", + "\n", + "Submit the pipeline definition to the Pipeline service. The Pipeline service uses the role that is passed in to create all the jobs defined in the steps." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "pipeline.upsert(role_arn=role)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "Start the pipeline and accept all the default parameters." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "execution = pipeline.start()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "## Pipeline Operations: Examining and Waiting for Pipeline Execution\n", + "\n", + "Describe the pipeline execution." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "execution.describe()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "Wait for the execution to complete." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "execution.wait()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "List the steps in the execution. These are the steps in the pipeline that have been resolved by the step executor service." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "execution.list_steps()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "### Examining the Evaluation\n", + "\n", + "Examine the resulting model evaluation after the pipeline completes. Download the resulting `evaluation.json` file from S3 and print the report." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "from pprint import pprint\n", + "\n", + "\n", + "evaluation_json = sagemaker.s3.S3Downloader.read_file(\n", + " \"{}/evaluation.json\".format(\n", + " step_eval.arguments[\"ProcessingOutputConfig\"][\"Outputs\"][0][\"S3Output\"][\"S3Uri\"]\n", + " )\n", + ")\n", + "pprint(json.loads(evaluation_json))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "### Lineage\n", + "\n", + "Review the lineage of the artifacts generated by the pipeline." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "import time\n", + "from sagemaker.lineage.visualizer import LineageTableVisualizer\n", + "\n", + "\n", + "viz = LineageTableVisualizer(sagemaker.session.Session())\n", + "for execution_step in reversed(execution.list_steps()):\n", + " print(execution_step)\n", + " display(viz.show(pipeline_execution_step=execution_step))\n", + " time.sleep(5)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "### Parametrized Executions\n", + "\n", + "You can run additional executions of the pipeline and specify different pipeline parameters. The `parameters` argument is a dictionary containing parameter names, and where the values are used to override the defaults values.\n", + "\n", + "Based on the performance of the model, you might want to kick off another pipeline execution on a compute-optimized instance type and set the model approval status to \"Approved\" automatically. This means that the model package version generated by the `RegisterModel` step is automatically ready for deployment through CI/CD pipelines, such as with SageMaker Projects." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "execution = pipeline.start(\n", + " parameters=dict(\n", + " ModelApprovalStatus=\"Approved\",\n", + " )\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "execution.wait()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "execution.list_steps()" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "Apart from that, you might also want to adjust the MSE threshold to a smaller value and raise the bar for the accuracy of the registered model. In this case you can override the MSE threshold like the following:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "execution = pipeline.start(parameters=dict(MseThreshold=3.0))" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "If the MSE threshold is not satisfied, the pipeline execution enters the `FailStep` and is marked as failed." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "try:\n", + " execution.wait()\n", + "except Exception as error:\n", + " print(error)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "execution.list_steps()" + ] + } + ], + "metadata": { + "instance_type": "ml.t3.medium", + "kernelspec": { + "display_name": "Python 3 (Data Science)", + "language": "python", + "name": "python3__SAGEMAKER_INTERNAL__arn:aws:sagemaker:eu-west-1:470317259841:image/datascience-1.0" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.10" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/notebooks/sm_pipelines_runbook.ipynb b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/notebooks/sm_pipelines_runbook.ipynb new file mode 100644 index 00000000..7196902d --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/notebooks/sm_pipelines_runbook.ipynb @@ -0,0 +1,538 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "import os\n", + "\n", + "import boto3\n", + "import logging\n", + "import sagemaker\n", + "import sagemaker.session\n", + "\n", + "from sagemaker.estimator import Estimator\n", + "from sagemaker.inputs import TrainingInput\n", + "from sagemaker.model_metrics import (\n", + " MetricsSource,\n", + " ModelMetrics,\n", + ")\n", + "from sagemaker.processing import (\n", + " ProcessingInput,\n", + " ProcessingOutput,\n", + " ScriptProcessor,\n", + ")\n", + "from sagemaker.sklearn.processing import SKLearnProcessor\n", + "from sagemaker.workflow.conditions import ConditionLessThanOrEqualTo\n", + "from sagemaker.workflow.condition_step import (\n", + " ConditionStep,\n", + ")\n", + "from sagemaker.workflow.functions import (\n", + " JsonGet,\n", + ")\n", + "from sagemaker.workflow.parameters import (\n", + " ParameterInteger,\n", + " ParameterString,\n", + ")\n", + "from sagemaker.workflow.pipeline import Pipeline\n", + "from sagemaker.workflow.properties import PropertyFile\n", + "from sagemaker.workflow.steps import (\n", + " ProcessingStep,\n", + " TrainingStep,\n", + ")\n", + "from sagemaker.workflow.step_collections import RegisterModel\n", + "\n", + "from botocore.exceptions import ClientError" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "logger = logging.getLogger(__name__)\n", + "\n", + "\"\"\"Environment Variables\"\"\"\n", + "proj_dir = \"TO_BE_DEFINED\"\n", + "region= \"TO_BE_DEFINED\"\n", + "model_artefact_bucket= \"TO_BE_DEFINED\"\n", + "role = \"TO_BE_DEFINED\"\n", + "project_name= \"TO_BE_DEFINED\"\n", + "stage= \"test\"\n", + "model_package_group_name=\"AbalonePackageGroup\",\n", + "pipeline_name=\"AbalonePipeline\",\n", + "base_job_prefix=\"Abalone\",\n", + "project_id=\"SageMakerProjectId\",\n", + "processing_image_uri=None\n", + "training_image_uri=None\n", + "inference_image_uri=None" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "def get_session(region, default_bucket):\n", + " \"\"\"Gets the sagemaker session based on the region.\n", + "\n", + " Args:\n", + " region: the aws region to start the session\n", + " default_bucket: the bucket to use for storing the artifacts\n", + "\n", + " Returns:\n", + " `sagemaker.session.Session instance\n", + " \"\"\"\n", + "\n", + " boto_session = boto3.Session(region_name=region)\n", + "\n", + " sagemaker_client = boto_session.client(\"sagemaker\")\n", + " runtime_client = boto_session.client(\"sagemaker-runtime\")\n", + " return sagemaker.session.Session(\n", + " boto_session=boto_session,\n", + " sagemaker_client=sagemaker_client,\n", + " sagemaker_runtime_client=runtime_client,\n", + " default_bucket=default_bucket,\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "sagemaker_session = get_session(region, model_artefact_bucket)" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "## Feature Engineering\n", + "This section describes the different steps involved in feature engineering which includes loading and transforming different data sources to build the features needed for the ML Use Case" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "processing_instance_count = ParameterInteger(name=\"ProcessingInstanceCount\", default_value=1)\n", + "processing_instance_type = ParameterString(name=\"ProcessingInstanceType\", default_value=\"ml.m5.xlarge\")\n", + "training_instance_type = ParameterString(name=\"TrainingInstanceType\", default_value=\"ml.m5.xlarge\")\n", + "inference_instance_type = ParameterString(name=\"InferenceInstanceType\", default_value=\"ml.m5.xlarge\")\n", + "model_approval_status = ParameterString(name=\"ModelApprovalStatus\", default_value=\"PendingManualApproval\")\n", + "input_data = ParameterString(\n", + " name=\"InputDataUrl\",\n", + " default_value=f\"s3://sagemaker-servicecatalog-seedcode-{region}/dataset/abalone-dataset.csv\",\n", + ")\n", + "processing_image_name = \"sagemaker-{0}-processingimagebuild\".format(project_id)\n", + "training_image_name = \"sagemaker-{0}-trainingimagebuild\".format(project_id)\n", + "inference_image_name = \"sagemaker-{0}-inferenceimagebuild\".format(project_id)\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "# processing step for feature engineering\n", + "try:\n", + " processing_image_uri = sagemaker_session.sagemaker_client.describe_image_version(\n", + " ImageName=processing_image_name\n", + " )[\"ContainerImage\"]\n", + "\n", + "except (sagemaker_session.sagemaker_client.exceptions.ResourceNotFound):\n", + " processing_image_uri = sagemaker.image_uris.retrieve(\n", + " framework=\"xgboost\",\n", + " region=region,\n", + " version=\"1.0-1\",\n", + " py_version=\"py3\",\n", + " instance_type=processing_instance_type,\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "# Define Script Processor\n", + "script_processor = ScriptProcessor(\n", + " image_uri=processing_image_uri,\n", + " instance_type=processing_instance_type,\n", + " instance_count=processing_instance_count,\n", + " base_job_name=f\"{base_job_prefix}/sklearn-abalone-preprocess\",\n", + " command=[\"python3\"],\n", + " sagemaker_session=sagemaker_session,\n", + " role=role,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "# Define ProcessingStep\n", + "step_process = ProcessingStep(\n", + " name=\"PreprocessAbaloneData\",\n", + " processor=script_processor,\n", + " outputs=[\n", + " ProcessingOutput(output_name=\"train\", source=\"/opt/ml/processing/train\"),\n", + " ProcessingOutput(output_name=\"validation\", source=\"/opt/ml/processing/validation\"),\n", + " ProcessingOutput(output_name=\"test\", source=\"/opt/ml/processing/test\"),\n", + " ],\n", + " code=\"source_scripts/preprocessing/prepare_abalone_data/main.py\", # we must figure out this path to get it from step_source directory\n", + " job_arguments=[\"--input-data\", input_data],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "# Training an XGBoost model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "# training step for generating model artifacts\n", + "model_path = f\"s3://{sagemaker_session.default_bucket()}/{base_job_prefix}/AbaloneTrain\"\n", + "\n", + "try:\n", + " training_image_uri = sagemaker_session.sagemaker_client.describe_image_version(ImageName=training_image_name)[\n", + " \"ContainerImage\"\n", + " ]\n", + "except (sagemaker_session.sagemaker_client.exceptions.ResourceNotFound):\n", + " training_image_uri = sagemaker.image_uris.retrieve(\n", + " framework=\"xgboost\",\n", + " region=region,\n", + " version=\"1.0-1\",\n", + " py_version=\"py3\",\n", + " instance_type=training_instance_type,\n", + " )\n", + "\n", + "xgb_train = Estimator(\n", + " image_uri=training_image_uri,\n", + " instance_type=training_instance_type,\n", + " instance_count=1,\n", + " output_path=model_path,\n", + " base_job_name=f\"{base_job_prefix}/abalone-train\",\n", + " sagemaker_session=sagemaker_session,\n", + " role=role,\n", + ")\n", + "xgb_train.set_hyperparameters(\n", + " objective=\"reg:linear\",\n", + " num_round=50,\n", + " max_depth=5,\n", + " eta=0.2,\n", + " gamma=4,\n", + " min_child_weight=6,\n", + " subsample=0.7,\n", + " silent=0,\n", + ")\n", + "step_train = TrainingStep(\n", + " name=\"TrainAbaloneModel\",\n", + " estimator=xgb_train,\n", + " inputs={\n", + " \"train\": TrainingInput(\n", + " s3_data=step_process.properties.ProcessingOutputConfig.Outputs[\"train\"].S3Output.S3Uri,\n", + " content_type=\"text/csv\",\n", + " ),\n", + " \"validation\": TrainingInput(\n", + " s3_data=step_process.properties.ProcessingOutputConfig.Outputs[\"validation\"].S3Output.S3Uri,\n", + " content_type=\"text/csv\",\n", + " ),\n", + " },\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "# Evaluate the Model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "# processing step for evaluation\n", + "script_eval = ScriptProcessor(\n", + " image_uri=training_image_uri,\n", + " command=[\"python3\"],\n", + " instance_type=processing_instance_type,\n", + " instance_count=1,\n", + " base_job_name=f\"{base_job_prefix}/script-abalone-eval\",\n", + " sagemaker_session=sagemaker_session,\n", + " role=role,\n", + ")\n", + "evaluation_report = PropertyFile(\n", + " name=\"AbaloneEvaluationReport\",\n", + " output_name=\"evaluation\",\n", + " path=\"evaluation.json\",\n", + ")\n", + "step_eval = ProcessingStep(\n", + " name=\"EvaluateAbaloneModel\",\n", + " processor=script_eval,\n", + " inputs=[\n", + " ProcessingInput(\n", + " source=step_train.properties.ModelArtifacts.S3ModelArtifacts,\n", + " destination=\"/opt/ml/processing/model\",\n", + " ),\n", + " ProcessingInput(\n", + " source=step_process.properties.ProcessingOutputConfig.Outputs[\"test\"].S3Output.S3Uri,\n", + " destination=\"/opt/ml/processing/test\",\n", + " ),\n", + " ],\n", + " outputs=[\n", + " ProcessingOutput(output_name=\"evaluation\", source=\"/opt/ml/processing/evaluation\"),\n", + " ],\n", + " code=\"source_scripts/evaluate/evaluate_xgboost/main.py\",\n", + " property_files=[evaluation_report],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "# Conditional step to push model to SageMaker Model Registry" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "# register model step that will be conditionally executed\n", + "model_metrics = ModelMetrics(\n", + " model_statistics=MetricsSource(\n", + " s3_uri=\"{}/evaluation.json\".format(\n", + " step_eval.arguments[\"ProcessingOutputConfig\"][\"Outputs\"][0][\"S3Output\"][\"S3Uri\"]\n", + " ),\n", + " content_type=\"application/json\",\n", + " )\n", + ")\n", + "\n", + "try:\n", + " inference_image_uri = sagemaker_session.sagemaker_client.describe_image_version(ImageName=inference_image_name)[\n", + " \"ContainerImage\"\n", + " ]\n", + "except (sagemaker_session.sagemaker_client.exceptions.ResourceNotFound):\n", + " inference_image_uri = sagemaker.image_uris.retrieve(\n", + " framework=\"xgboost\",\n", + " region=region,\n", + " version=\"1.0-1\",\n", + " py_version=\"py3\",\n", + " instance_type=inference_instance_type,\n", + " )\n", + "step_register = RegisterModel(\n", + " name=\"RegisterAbaloneModel\",\n", + " estimator=xgb_train,\n", + " image_uri=inference_image_uri,\n", + " model_data=step_train.properties.ModelArtifacts.S3ModelArtifacts,\n", + " content_types=[\"text/csv\"],\n", + " response_types=[\"text/csv\"],\n", + " inference_instances=[\"ml.t2.medium\", \"ml.m5.large\"],\n", + " transform_instances=[\"ml.m5.large\"],\n", + " model_package_group_name=model_package_group_name,\n", + " approval_status=model_approval_status,\n", + " model_metrics=model_metrics,\n", + ")\n", + "\n", + "# condition step for evaluating model quality and branching execution\n", + "cond_lte = ConditionLessThanOrEqualTo(\n", + " left=JsonGet(\n", + " step_name=step_eval.name, property_file=evaluation_report, json_path=\"regression_metrics.mse.value\"\n", + " ),\n", + " right=6.0,\n", + ")\n", + "step_cond = ConditionStep(\n", + " name=\"CheckMSEAbaloneEvaluation\",\n", + " conditions=[cond_lte],\n", + " if_steps=[step_register],\n", + " else_steps=[],\n", + ")" + ] + }, + { + "cell_type": "markdown", + "metadata": { + "pycharm": { + "name": "#%% md\n" + } + }, + "source": [ + "# Create and run the Pipeline" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "# pipeline instance\n", + "pipeline = Pipeline(\n", + " name=pipeline_name,\n", + " parameters=[\n", + " processing_instance_type,\n", + " processing_instance_count,\n", + " training_instance_type,\n", + " model_approval_status,\n", + " input_data,\n", + " ],\n", + " steps=[step_process, step_train, step_eval, step_cond],\n", + " sagemaker_session=sagemaker_session,\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "import json\n", + "\n", + "\n", + "definition = json.loads(pipeline.definition())\n", + "definition" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "pipeline.upsert(role_arn=role, description=f'{stage} pipelines for {project_name}')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "pycharm": { + "name": "#%%\n" + } + }, + "outputs": [], + "source": [ + "pipeline.start()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "conda_python3", + "language": "python", + "name": "conda_python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.13" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} \ No newline at end of file diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/requirements-dev.txt b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/requirements-dev.txt new file mode 100644 index 00000000..92709451 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/requirements-dev.txt @@ -0,0 +1 @@ +pytest==6.2.5 diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/requirements.txt b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/requirements.txt new file mode 100644 index 00000000..db9da2db --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/requirements.txt @@ -0,0 +1,2 @@ +sagemaker +boto3 diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/setup.cfg b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/setup.cfg new file mode 100644 index 00000000..6f878705 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/setup.cfg @@ -0,0 +1,14 @@ +[tool:pytest] +addopts = + -vv +testpaths = tests + +[aliases] +test=pytest + +[metadata] +description-file = README.md +license_file = LICENSE + +[wheel] +universal = 1 diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/setup.py b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/setup.py new file mode 100644 index 00000000..b10bb142 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/setup.py @@ -0,0 +1,77 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# SPDX-License-Identifier: MIT-0 +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this +# software and associated documentation files (the "Software"), to deal in the Software +# without restriction, including without limitation the rights to use, copy, modify, +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +import os +import setuptools + + +about = {} +here = os.path.abspath(os.path.dirname(__file__)) +with open(os.path.join(here, "ml_pipelines", "__version__.py")) as f: + exec(f.read(), about) + + +with open("README.md", "r") as f: + readme = f.read() + + +required_packages = ["sagemaker"] +extras = { + "test": [ + "black", + "coverage", + "flake8", + "mock", + "pydocstyle", + "pytest", + "pytest-cov", + "sagemaker", + "tox", + ] +} +setuptools.setup( + name=about["__title__"], + description=about["__description__"], + version=about["__version__"], + author=about["__author__"], + author_email=["__author_email__"], + long_description=readme, + long_description_content_type="text/markdown", + url=about["__url__"], + license=about["__license__"], + packages=setuptools.find_packages(), + include_package_data=True, + python_requires=">=3.6", + install_requires=required_packages, + extras_require=extras, + entry_points={ + "console_scripts": [ + "get-pipeline-definition=pipelines.get_pipeline_definition:main", + "run-pipeline=ml_pipelines.run_pipeline:main", + ] + }, + classifiers=[ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "Natural Language :: English", + "Programming Language :: Python", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + ], +) diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/Dockerfile b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/Dockerfile new file mode 100644 index 00000000..7057bb4f --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/Dockerfile @@ -0,0 +1,40 @@ +FROM public.ecr.aws/docker/library/python:3.7-buster as base + +RUN apt-get -y update && apt-get install -y \ + nginx \ + ca-certificates \ + policycoreutils \ + && rm -rf /var/lib/apt/lists/* + +ENV PATH="/usr/sbin/:${PATH}" + +COPY helpers/requirements.txt /requirements.txt + +RUN pip install --upgrade pip && pip install --no-cache -r /requirements.txt && \ + rm /requirements.txt +# Set up the program in the image +COPY helpers /opt/program + + +### start of TRAINING container +FROM base as xgboost +COPY training/xgboost/requirements.txt /requirements.txt +RUN pip install --no-cache -r /requirements.txt && \ + rm /requirements.txt + +# sm vars +ENV SAGEMAKER_MODEL_SERVER_TIMEOUT="300" +ENV MODEL_SERVER_TIMEOUT="300" +ENV PYTHONUNBUFFERED=TRUE +ENV PYTHONDONTWRITEBYTECODE=TRUE +ENV PATH="/opt/program:${PATH}" + +# env vars + +# Set up the program in the image +COPY training/xgboost /opt/program + +# set permissions of entrypoint +RUN chmod +x /opt/program/__main__.py + +WORKDIR /opt/program diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/README.md b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/README.md new file mode 100644 index 00000000..e69de29b diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/evaluate/evaluate_xgboost/README.md b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/evaluate/evaluate_xgboost/README.md new file mode 100644 index 00000000..e69de29b diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/evaluate/evaluate_xgboost/main.py b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/evaluate/evaluate_xgboost/main.py new file mode 100644 index 00000000..7027811e --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/evaluate/evaluate_xgboost/main.py @@ -0,0 +1,72 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# SPDX-License-Identifier: MIT-0 +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this +# software and associated documentation files (the "Software"), to deal in the Software +# without restriction, including without limitation the rights to use, copy, modify, +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +"""Evaluation script for measuring mean squared error.""" +import json +import logging +import pathlib +import pickle +import tarfile + +import numpy as np +import pandas as pd +import xgboost + +from sklearn.metrics import mean_squared_error + +logger = logging.getLogger() +logger.setLevel(logging.INFO) +logger.addHandler(logging.StreamHandler()) + + +if __name__ == "__main__": + logger.debug("Starting evaluation.") + model_path = "/opt/ml/processing/model/model.tar.gz" + with tarfile.open(model_path) as tar: + tar.extractall(path=".") + + logger.debug("Loading xgboost model.") + model = pickle.load(open("xgboost-model", "rb")) + + logger.debug("Reading test data.") + test_path = "/opt/ml/processing/test/test.csv" + df = pd.read_csv(test_path, header=None) + + logger.debug("Reading test data.") + y_test = df.iloc[:, 0].to_numpy() + df.drop(df.columns[0], axis=1, inplace=True) + X_test = xgboost.DMatrix(df.values) + + logger.info("Performing predictions against test data.") + predictions = model.predict(X_test) + + logger.debug("Calculating mean squared error.") + mse = mean_squared_error(y_test, predictions) + std = np.std(y_test - predictions) + report_dict = { + "regression_metrics": { + "mse": {"value": mse, "standard_deviation": std}, + }, + } + + output_dir = "/opt/ml/processing/evaluation" + pathlib.Path(output_dir).mkdir(parents=True, exist_ok=True) + + logger.info("Writing out evaluation report with mse: %f", mse) + evaluation_path = f"{output_dir}/evaluation.json" + with open(evaluation_path, "w") as f: + f.write(json.dumps(report_dict)) diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/evaluate/evaluate_xgboost/requirements.txt b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/evaluate/evaluate_xgboost/requirements.txt new file mode 100644 index 00000000..e69de29b diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/helpers/README.md b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/helpers/README.md new file mode 100644 index 00000000..e69de29b diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/helpers/logger.py b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/helpers/logger.py new file mode 100644 index 00000000..bc27f7d9 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/helpers/logger.py @@ -0,0 +1,16 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# SPDX-License-Identifier: MIT-0 +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this +# software and associated documentation files (the "Software"), to deal in the Software +# without restriction, including without limitation the rights to use, copy, modify, +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/helpers/requirements.txt b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/helpers/requirements.txt new file mode 100644 index 00000000..e69de29b diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/helpers/s3_helper.py b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/helpers/s3_helper.py new file mode 100644 index 00000000..bc27f7d9 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/helpers/s3_helper.py @@ -0,0 +1,16 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# SPDX-License-Identifier: MIT-0 +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this +# software and associated documentation files (the "Software"), to deal in the Software +# without restriction, including without limitation the rights to use, copy, modify, +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/helpers/test/test_a.py b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/helpers/test/test_a.py new file mode 100644 index 00000000..bc27f7d9 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/helpers/test/test_a.py @@ -0,0 +1,16 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# SPDX-License-Identifier: MIT-0 +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this +# software and associated documentation files (the "Software"), to deal in the Software +# without restriction, including without limitation the rights to use, copy, modify, +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/preprocessing/prepare_abalone_data/README.md b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/preprocessing/prepare_abalone_data/README.md new file mode 100644 index 00000000..e69de29b diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/preprocessing/prepare_abalone_data/main.py b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/preprocessing/prepare_abalone_data/main.py new file mode 100644 index 00000000..063a1d81 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/preprocessing/prepare_abalone_data/main.py @@ -0,0 +1,132 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# SPDX-License-Identifier: MIT-0 +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this +# software and associated documentation files (the "Software"), to deal in the Software +# without restriction, including without limitation the rights to use, copy, modify, +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +"""Feature engineers the abalone dataset.""" +import argparse +import logging +import os +import pathlib +import requests +import tempfile + +import boto3 +import numpy as np +import pandas as pd + +from sklearn.compose import ColumnTransformer +from sklearn.impute import SimpleImputer +from sklearn.pipeline import Pipeline +from sklearn.preprocessing import StandardScaler, OneHotEncoder + +logger = logging.getLogger() +logger.setLevel(logging.INFO) +logger.addHandler(logging.StreamHandler()) + + +# Since we get a headerless CSV file we specify the column names here. +feature_columns_names = [ + "sex", + "length", + "diameter", + "height", + "whole_weight", + "shucked_weight", + "viscera_weight", + "shell_weight", +] +label_column = "rings" + +feature_columns_dtype = { + "sex": str, + "length": np.float64, + "diameter": np.float64, + "height": np.float64, + "whole_weight": np.float64, + "shucked_weight": np.float64, + "viscera_weight": np.float64, + "shell_weight": np.float64, +} +label_column_dtype = {"rings": np.float64} + + +def merge_two_dicts(x, y): + """Merges two dicts, returning a new copy.""" + z = x.copy() + z.update(y) + return z + + +if __name__ == "__main__": + logger.debug("Starting preprocessing.") + parser = argparse.ArgumentParser() + parser.add_argument("--input-data", type=str, required=True) + args = parser.parse_args() + + base_dir = "/opt/ml/processing" + pathlib.Path(f"{base_dir}/data").mkdir(parents=True, exist_ok=True) + input_data = args.input_data + bucket = input_data.split("/")[2] + key = "/".join(input_data.split("/")[3:]) + + logger.info("Downloading data from bucket: %s, key: %s", bucket, key) + fn = f"{base_dir}/data/abalone-dataset.csv" + s3 = boto3.resource("s3") + s3.Bucket(bucket).download_file(key, fn) + + logger.debug("Reading downloaded data.") + df = pd.read_csv( + fn, + header=None, + names=feature_columns_names + [label_column], + dtype=merge_two_dicts(feature_columns_dtype, label_column_dtype), + ) + os.unlink(fn) + + logger.debug("Defining transformers.") + numeric_features = list(feature_columns_names) + numeric_features.remove("sex") + numeric_transformer = Pipeline(steps=[("imputer", SimpleImputer(strategy="median")), ("scaler", StandardScaler())]) + + categorical_features = ["sex"] + categorical_transformer = Pipeline( + steps=[ + ("imputer", SimpleImputer(strategy="constant", fill_value="missing")), + ("onehot", OneHotEncoder(handle_unknown="ignore")), + ] + ) + + preprocess = ColumnTransformer( + transformers=[ + ("num", numeric_transformer, numeric_features), + ("cat", categorical_transformer, categorical_features), + ] + ) + + logger.info("Applying transforms.") + y = df.pop("rings") + X_pre = preprocess.fit_transform(df) + y_pre = y.to_numpy().reshape(len(y), 1) + + X = np.concatenate((y_pre, X_pre), axis=1) + + logger.info("Splitting %d rows of data into train, validation, test datasets.", len(X)) + np.random.shuffle(X) + train, validation, test = np.split(X, [int(0.7 * len(X)), int(0.85 * len(X))]) + + logger.info("Writing out datasets to %s.", base_dir) + pd.DataFrame(train).to_csv(f"{base_dir}/train/train.csv", header=False, index=False) + pd.DataFrame(validation).to_csv(f"{base_dir}/validation/validation.csv", header=False, index=False) + pd.DataFrame(test).to_csv(f"{base_dir}/test/test.csv", header=False, index=False) diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/preprocessing/prepare_abalone_data/requirements.txt b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/preprocessing/prepare_abalone_data/requirements.txt new file mode 100644 index 00000000..e69de29b diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/training/xgboost/README.md b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/training/xgboost/README.md new file mode 100644 index 00000000..e69de29b diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/training/xgboost/__main__.py b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/training/xgboost/__main__.py new file mode 100644 index 00000000..bc27f7d9 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/training/xgboost/__main__.py @@ -0,0 +1,16 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# SPDX-License-Identifier: MIT-0 +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this +# software and associated documentation files (the "Software"), to deal in the Software +# without restriction, including without limitation the rights to use, copy, modify, +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/training/xgboost/requirements.txt b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/training/xgboost/requirements.txt new file mode 100644 index 00000000..e69de29b diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/training/xgboost/test/test_a.py b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/training/xgboost/test/test_a.py new file mode 100644 index 00000000..bc27f7d9 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/source_scripts/training/xgboost/test/test_a.py @@ -0,0 +1,16 @@ +# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +# +# SPDX-License-Identifier: MIT-0 +# +# Permission is hereby granted, free of charge, to any person obtaining a copy of this +# software and associated documentation files (the "Software"), to deal in the Software +# without restriction, including without limitation the rights to use, copy, modify, +# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/terraform/.gitkeep b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/terraform/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/terraform/main.tf b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/terraform/main.tf new file mode 100644 index 00000000..fee92b0d --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/terraform/main.tf @@ -0,0 +1,28 @@ +locals { + prefix = var.prefix + sm_project_id = var.sm_project_id + sm_project_name = var.sm_project_name + aws_account_id = var.aws_account_id + aws_region = var.aws_region + target_branch = var.default_branch + codecommit_id = var.codecommit_id + artifact_bucket_name = var.artifact_bucket_name + sm_pipeline_name = "modelbuild-pipeline" + model_package_group_name = "models" + pipeline_name = "modelbuild-pipeline" +} + +module "cicd_build_pipeline" { + source = ".//modules/cicd" + + prefix = local.prefix + sm_project_id = local.sm_project_id + sm_project_name = local.sm_project_name + sm_pipeline_name = local.sm_pipeline_name + model_package_group_name = local.model_package_group_name + codecommit_id = local.codecommit_id + target_branch = local.target_branch + artifact_bucket_name = local.artifact_bucket_name + pipeline_name = local.pipeline_name +} + diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/terraform/modules/cicd/codebuild.tf b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/terraform/modules/cicd/codebuild.tf new file mode 100644 index 00000000..942c5b58 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/build_app/terraform/modules/cicd/codebuild.tf @@ -0,0 +1,118 @@ +data "aws_iam_policy_document" "codebuild_assume_policy" { + statement { + effect = "Allow" + actions = ["sts:AssumeRole"] + + principals { + type = "Service" + identifiers = ["codebuild.amazonaws.com"] + } + } +} + +resource "aws_iam_role" "codebuild_role" { + name = "${local.prefix}-${local.sm_project_id}-codebuild-modelbuild" + assume_role_policy = data.aws_iam_policy_document.codebuild_assume_policy.json +} + +# TODO: SCOPE THIS DOWN!!!!!!!!!!!!!!!!!!!!! +resource "aws_iam_role_policy_attachment" "power_user" { + role = aws_iam_role.codebuild_role.id + policy_arn = "arn:aws:iam::aws:policy/PowerUserAccess" +} + +resource "aws_iam_policy" "pass_role_to_sm_pipelines" { + description = "pass_role_to_sm_pipelines for SM Pipelines for ${local.sm_project_id}" + + policy = < Open Git Repository In Terminal +- Run the following commands + +```bash +make bootstrap +# tap enter for the defaults +make plan +make apply +``` + +Your CICD pipeline should now be deployed. Push bootstrapping changes to the repo + +``` +git add -A +git commit -m "bootstrapping" +git push +``` + +Open CodePipeline and see the pipeline execute. + +## Automated Endpoint Deployment + +Whenever a new model has been trained and approved by the modelbuild project, the CICD pipeline for this project will +trigger and attempt to deploy a SageMaker Endpoint. \ No newline at end of file diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/buildspec.yml b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/buildspec.yml new file mode 100644 index 00000000..8cc367e2 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/buildspec.yml @@ -0,0 +1,23 @@ +version: 0.2 +env: + variables: + TERRAFORM_VERSION: 1.2.4 + +phases: + install: + runtime-versions: + python: 3.8 + commands: + - pip install --upgrade --force-reinstall "awscli>1.20.30" + - pip install -r requirements.txt + - export PYTHONUNBUFFERED=TRUE + - echo "Installing Terraform" + - curl -o /tmp/terraform_${TERRAFORM_VERSION}_linux_amd64.zip https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip + - unzip -o /tmp/terraform_${TERRAFORM_VERSION}_linux_amd64.zip -d /tmp && mv /tmp/terraform /usr/bin + - chmod +x /usr/bin/terraform + - terraform --version + + build: + commands: + - echo "Looking up last approved model and deploying infra" + - make auto-apply \ No newline at end of file diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/infra_scripts/bootstrap.sh b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/infra_scripts/bootstrap.sh new file mode 100644 index 00000000..a7dd0d8a --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/infra_scripts/bootstrap.sh @@ -0,0 +1,131 @@ +#!/bin/bash + +sudo yum install -y gettext wget unzip jq + +export TERRAFORM_VERSION="1.2.4" + +echo "Attempting to install terraform" && \ +wget -q https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip -P /tmp && \ +unzip -q /tmp/terraform_${TERRAFORM_VERSION}_linux_amd64.zip -d /tmp && \ +sudo mv /tmp/terraform /usr/local/bin/ && \ +rm -rf /tmp/terraform_${TERRAFORM_VERSION}_linux_amd64.zip && \ +echo "terraform is installed successfully" + +FOLDER_NAME=$(basename "$PWD") + +# Read the SM_PROJECT_ID from the folder name +DEFAULT_SM_PROJECT_ID=$(cat .sagemaker-code-config | jq -r .sagemakerProjectId) +read -p "Sagemaker Project ID (default \"$DEFAULT_SM_PROJECT_ID\"): " sm_project_id_input +export SM_PROJECT_ID="${sm_project_id_input:-$DEFAULT_SM_PROJECT_ID}" + +if [[ -z $SM_PROJECT_ID ]]; then + echo "No Sagemaker Project ID provided" + exit 1 +fi + +# Read the SM_PROJECT_NAME from the folder name +DEFAULT_SM_PROJECT_NAME=$(cat .sagemaker-code-config | jq -r .sagemakerProjectName) +read -p "Sagemaker Project ID (default \"$DEFAULT_SM_PROJECT_NAME\"): " sm_project_id_input +export SM_PROJECT_NAME="${sm_project_id_input:-$DEFAULT_SM_PROJECT_NAME}" + +if [[ -z $SM_PROJECT_NAME ]]; then + echo "No Sagemaker Project Name provided" + exit 1 +fi + + +# Fetch Values from CloudFormation Stack Output +export STACK_NAME=$(aws cloudformation describe-stacks --query 'Stacks[?Tags[?Key == `sagemaker:project-id` && Value == `'$DEFAULT_SM_PROJECT_ID'`]].{StackName: StackName}' --output text) + +export PREFIX=$(aws cloudformation describe-stacks --query "Stacks[?StackName=='$STACK_NAME'][].Outputs[?OutputKey=='Prefix'].OutputValue" --output text) + +export STATE_BUCKET_NAME=$(aws cloudformation describe-stacks --query "Stacks[?StackName=='$STACK_NAME'][].Outputs[?OutputKey=='MlOpsProjectStateBucket'].OutputValue" --output text) + +export ARTIFACT_BUCKET_NAME=$(aws cloudformation describe-stacks --query "Stacks[?StackName=='$STACK_NAME'][].Outputs[?OutputKey=='MlOpsArtifactsBucket'].OutputValue" --output text) + +export BUCKET_REGION=$(aws cloudformation describe-stacks --query "Stacks[?StackName=='$STACK_NAME'][].Outputs[?OutputKey=='BucketRegion'].OutputValue" --output text) + +CF_DEFAULT_BRANCH=$(aws cloudformation describe-stacks --query "Stacks[?StackName=='$STACK_NAME'][].Outputs[?OutputKey=='DefaultBranch'].OutputValue" --output text) + +export DEFAULT_BRANCH=${CF_DEFAULT_BRANCH:-main} + + +# Get the AWS Account ID. Should be set as environmet variable in SageMaker Studio +read -p "AWS_ACCOUNT_ID (default \"$AWS_ACCOUNT_ID\"): " input_account_id +export AWS_ACCOUNT_ID="${input_account_id:-$AWS_ACCOUNT_ID}" + +if [[ -z "$AWS_ACCOUNT_ID" ]]; then + echo "No AWS_ACCOUNT_ID provided" + exit 1 +fi + +# Get the AWS Region ID. Should be set as environmet variable in SageMaker Studio +read -p "AWS_REGION (default \"$AWS_REGION\"): " input_region +export AWS_REGION="${input_region:-$AWS_REGION}" + +if [[ -z "$AWS_REGION" ]]; then + echo "No AWS_REGION provided" + exit 1 +fi + +CODECOMMIT_ID=$(cat .sagemaker-code-config | jq -r .codeRepositoryName) +read -p "CODECOMMIT_ID (default \"$CODECOMMIT_ID\"): " input_codecommit_id +export CODECOMMIT_ID="${input_codecommit_id:-$CODECOMMIT_ID}" + +if [[ -z "$CODECOMMIT_ID" ]]; then + echo "No CODECOMMIT_ID provided" + exit 1 +fi + +read -p "DEFAULT_BRANCH (default \"$DEFAULT_BRANCH\"): " input_default_branch +export DEFAULT_BRANCH="${input_default_branch:-$DEFAULT_BRANCH}" + +if [[ -z "$DEFAULT_BRANCH" ]]; then + echo "No DEFAULT_BRANCH provided" + exit 1 +fi + + +export SM_EXECUTION_ROLE_ARN="arn:aws:iam::$AWS_ACCOUNT_ID:role/$PREFIX-sagemaker-execution-role" +export MODEL_PACKAGE_GROUP_NAME="$PREFIX-$SM_PROJECT_NAME-models" + +echo "--------------Bootstrap Output-----------------" +echo "Prefix: $PREFIX" +echo "Sagmaker Project ID: $SM_PROJECT_ID" +echo "Sagmaker Name: $SM_PROJECT_NAME" +echo "AWS Account ID: $AWS_ACCOUNT_ID" +echo "AWS Region: $AWS_REGION" +echo "Artifact bucket name: $ARTIFACT_BUCKET_NAME" +echo "State bucket name: $STATE_BUCKET_NAME" +echo "CodeCommit ID: $CODECOMMIT_ID" +echo "Default Branch: $DEFAULT_BRANCH" +echo "SageMaker Execution Role: $SM_EXECUTION_ROLE_ARN" +echo "Model Package Group Name: $MODEL_PACKAGE_GROUP_NAME" +echo "-----------------------------------------------" + +# Update provider.tf to use bucket and region +envsubst < "./infra_scripts/bootstrap/provider.template" > "./terraform/provider.tf" + +# Update terraform.tfvars +envsubst < "./infra_scripts/bootstrap/terraform.tfvars.template" > "./terraform/terraform.tfvars" + +# Update .project.env +SM_CODE_CONFIG=$(cat .sagemaker-code-config) +UPDATED_SM_CODE_CONFIG=$(echo $SM_CODE_CONFIG | jq ".prefix |= \"${PREFIX}\"" | jq ".model_package_group_name |= \"$MODEL_PACKAGE_GROUP_NAME\"" ) + +echo ${UPDATED_SM_CODE_CONFIG} | jq '.' > .sagemaker-code-config + +cd terraform + +terraform init + +cd .. + +echo "Commit & update tfvars, terraform provider and sagemaker-code-config" +git add .sagemaker-code-config +git add terraform/provider.tf +git add terraform/terraform.tfvars +git commit --author="SM Projects <>" -m "Bootstrapping complete" +git push +echo "Bootstrapping completed" + diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/infra_scripts/bootstrap/provider.template b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/infra_scripts/bootstrap/provider.template new file mode 100644 index 00000000..abfbbe43 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/infra_scripts/bootstrap/provider.template @@ -0,0 +1,12 @@ +provider "aws" { + region = "$AWS_REGION" +} + +terraform { + required_version = ">= $TERRAFORM_VERSION" + backend "s3" { + bucket = "$STATE_BUCKET_NAME" + key = "projects/state/deploy/mlops-$SM_PROJECT_ID-deploy-state.tfstate" + region = "$AWS_REGION" + } +} diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/infra_scripts/bootstrap/terraform.tfvars.template b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/infra_scripts/bootstrap/terraform.tfvars.template new file mode 100644 index 00000000..e3926291 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/infra_scripts/bootstrap/terraform.tfvars.template @@ -0,0 +1,10 @@ +aws_region = "$AWS_REGION" +aws_account_id = "$AWS_ACCOUNT_ID" +sm_project_id = "$SM_PROJECT_ID" +sm_project_name = "$SM_PROJECT_NAME" +codecommit_id = "$CODECOMMIT_ID" +prefix = "$PREFIX" +artifact_bucket_name = "$ARTIFACT_BUCKET_NAME" +default_branch = "$DEFAULT_BRANCH" +sm_execution_role_arn = "$SM_EXECUTION_ROLE_ARN" +model_package_group_name = "$MODEL_PACKAGE_GROUP_NAME" \ No newline at end of file diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/infra_scripts/get_last_approved_model.py b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/infra_scripts/get_last_approved_model.py new file mode 100644 index 00000000..adb39c6d --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/infra_scripts/get_last_approved_model.py @@ -0,0 +1,44 @@ +import os +import boto3 +import json +import botocore + +region = boto3.Session().region_name +sm_client = boto3.client('sagemaker', region_name=region) + +sagemaker_code_config = open('.sagemaker-code-config') +config = json.load(sagemaker_code_config) +model_package_group_name = config["model_package_group_name"] + +mpg = sm_client.list_model_packages(ModelPackageGroupName=model_package_group_name) + +mpsl = mpg["ModelPackageSummaryList"] +last_approved_model = None +for model_package in mpsl: + approval_status = model_package["ModelApprovalStatus"] + model_arn = model_package["ModelPackageArn"] + # print(f'version:{model_package["ModelPackageVersion"]}\tapproval:{approval_status}\tarn:{model_arn}') + if last_approved_model is None and approval_status == "Approved": + last_approved_model = model_arn + +try: + model_response = sm_client.describe_model_package( + ModelPackageName=last_approved_model + ) + inference_image = model_response['InferenceSpecification']['Containers'][0]['Image'] + model_data_url = model_response['InferenceSpecification']['Containers'][0]['ModelDataUrl'] + +except botocore.exceptions.ParamValidationError as e: + if 'Invalid type for parameter ModelPackageName, value: None' in str(e): + inference_image = 'None' + model_data_url = 'None' + else: + raise e + +tf_vars_data = f'''inference_image = "{inference_image}" +model_data_url = "{model_data_url}"''' + +with open('terraform/model.auto.tfvars', 'w') as f: + f.write(tf_vars_data) + +print(f"Last Approved Model: {last_approved_model}") \ No newline at end of file diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/requirements-dev.txt b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/requirements-dev.txt new file mode 100644 index 00000000..92709451 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/requirements-dev.txt @@ -0,0 +1 @@ +pytest==6.2.5 diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/requirements.txt b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/requirements.txt new file mode 100644 index 00000000..30ddf823 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/requirements.txt @@ -0,0 +1 @@ +boto3 diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/.gitkeep b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/main.tf b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/main.tf new file mode 100644 index 00000000..d9f7ea99 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/main.tf @@ -0,0 +1,53 @@ +locals { + prefix = var.prefix + sm_project_id = var.sm_project_id + sm_project_name = var.sm_project_name + aws_account_id = var.aws_account_id + aws_region = var.aws_region + target_branch = var.default_branch + artifact_bucket_name = var.artifact_bucket_name + codecommit_id = var.codecommit_id + initial_instance_count = 1 + initial_sampling_percentage = 30 + initial_variant_weight = 1 + instance_type = "ml.t2.medium" + model_name = "${local.sm_project_name}-model" + sagemaker_endpoint_configuration_name = "${local.prefix}-${local.sm_project_name}-config" + sagemaker_endpoint_name = "${local.prefix}-${local.sm_project_name}-endpoint" + variant_name = "v1" + sagemaker_execution_role = var.sm_execution_role_arn + inference_image = var.inference_image + model_data_url = var.model_data_url + pipeline_name = "modeldeploy-pipeline" + model_package_group_name = var.model_package_group_name +} + + +module "cicd_build_pipeline" { + source = ".//modules/cicd" + + prefix = local.prefix + sm_project_id = local.sm_project_id + sm_project_name = local.sm_project_name + model_package_group_name = local.model_package_group_name + codecommit_id = local.codecommit_id + target_branch = local.target_branch + artifact_bucket_name = local.artifact_bucket_name + pipeline_name = local.pipeline_name + sagemaker_execution_role = local.sagemaker_execution_role +} + +module "sm_endpoint_slim" { + source = ".//modules/sm_endpoint_slim" + + count = "${local.inference_image == "None" ? 0 : 1}" + prefix = local.prefix + instance_type = local.instance_type + initial_instance_count = local.initial_instance_count + model_name = local.model_name + sagemaker_execution_role = local.sagemaker_execution_role + sagemaker_endpoint_name = local.sagemaker_endpoint_name + variant_name = local.variant_name + inference_image = local.inference_image + model_data_url = local.model_data_url +} \ No newline at end of file diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/cicd/codebuild.tf b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/cicd/codebuild.tf new file mode 100644 index 00000000..90640134 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/cicd/codebuild.tf @@ -0,0 +1,150 @@ +data "aws_iam_policy_document" "codebuild_assume_policy" { + statement { + effect = "Allow" + actions = ["sts:AssumeRole"] + + principals { + type = "Service" + identifiers = ["codebuild.amazonaws.com"] + } + } +} + +resource "aws_iam_role" "codebuild_role" { + name = "${local.prefix}-${local.sm_project_name}-codebuild-modeldeploy-role" + assume_role_policy = data.aws_iam_policy_document.codebuild_assume_policy.json +} + +# TODO: SCOPE THIS DOWN!!!!!!!!!!!!!!!!!!!!! +resource "aws_iam_role_policy_attachment" "power_user" { + role = aws_iam_role.codebuild_role.id + policy_arn = "arn:aws:iam::aws:policy/PowerUserAccess" +} + +resource "aws_iam_policy" "manage_roles" { + description = "pass_role_to_sm_pipelines for SM Pipelines for ${local.sm_project_name}" + + policy = < +## Requirements + +| Name | Version | +|------|---------| +| [terraform](#requirement\_terraform) | >= 1.0 , < 1.1 | +| [aws](#requirement\_aws) | ~> 3.0 | + +## Providers + +| Name | Version | +|------|---------| +| [aws](#provider\_aws) | ~> 3.0 | + +## Modules + +| Name | Source | Version | +|------|--------|---------| +| [module\_tags](#module\_module\_tags) | ../tags_module | n/a | + +## Resources + +| Name | Type | +|------|------| +| [aws_sagemaker_endpoint.inference_endpoint](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sagemaker_endpoint) | resource | +| [aws_sagemaker_endpoint_configuration.inference_endpoint_configuration](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/sagemaker_endpoint_configuration) | resource | +| [aws_caller_identity.current](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/caller_identity) | data source | + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|------|---------|:--------:| +| [bucket\_name](#input\_bucket\_name) | The name of the S3 bucket. | `string` | n/a | yes | +| [capture\_modes](#input\_capture\_modes) | Data Capture Mode. Acceptable Values Input and Output. | `list(string)` |

    [
    "Input",
    "Output"
    ]
    | no | +| [csv\_content\_types](#input\_csv\_content\_types) | The CSV content type headers to capture. | `list(string)` |
    [
    "text/csv"
    ]
    | no | +| [enable\_data\_capture\_config](#input\_enable\_data\_capture\_config) | Enable Data Capture Config. | `bool` | `false` | no | +| [initial\_instance\_count](#input\_initial\_instance\_count) | Instance Count. | `number` | `1` | no | +| [initial\_sampling\_percentage](#input\_initial\_sampling\_percentage) | Sampling Percentage.Acceptable Value Range Between 0 and 100. | `number` | `30` | no | +| [initial\_variant\_weight](#input\_initial\_variant\_weight) | Initial Variant Weight. Acceptable Value Range Between 0 and 1. | `number` | `1` | no | +| [instance\_type](#input\_instance\_type) | Instance Type. | `string` | `"ml.t2.medium"` | no | +| [kms\_key\_arn](#input\_kms\_key\_arn) | KMS key ARN. | `string` | n/a | yes | +| [model\_name](#input\_model\_name) | Approved Model Name. | `string` | n/a | yes | +| [sagemaker\_endpoint\_configuration\_name](#input\_sagemaker\_endpoint\_configuration\_name) | The name of the inference endpoint configuration. | `string` | n/a | yes | +| [sagemaker\_endpoint\_name](#input\_sagemaker\_endpoint\_name) | The name of the inference endpoint. | `string` | n/a | yes | +| [tags](#input\_tags) | Tags to be attached to the module tags of the resources. | `map(string)` | `{}` | no | +| [variant\_name](#input\_variant\_name) | The name of the variant. | `string` | `"variant-1"` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| [inference\_endpoint](#output\_inference\_endpoint) | n/a | + diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/sm_endpoint_slim/main.tf b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/sm_endpoint_slim/main.tf new file mode 100644 index 00000000..ee01ddda --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/sm_endpoint_slim/main.tf @@ -0,0 +1,52 @@ +data "aws_caller_identity" "current" {} + +locals { + prefix = var.prefix + model_name = var.model_name + initial_instance_count = var.initial_instance_count + instance_type = var.instance_type + sagemaker_endpoint_name = var.sagemaker_endpoint_name + variant_name = var.variant_name + sagemaker_execution_role = var.sagemaker_execution_role + inference_image = var.inference_image + model_data_url = var.model_data_url +} + + +resource "random_id" "force_endpoint_update" { + keepers = { + # Generate a new id each time we switch model data url + model_data_url = local.model_data_url + } + byte_length = 8 +} + +resource "aws_sagemaker_model" "model" { + name = "${local.prefix}-${local.model_name}-${random_id.force_endpoint_update.dec}" + execution_role_arn = local.sagemaker_execution_role + + container { + image = local.inference_image + model_data_url = local.model_data_url + } +} + +resource "aws_sagemaker_endpoint_configuration" "inference_endpoint_configuration" { + name = "${local.sagemaker_endpoint_name}-${random_id.force_endpoint_update.dec}" + + production_variants { + variant_name = local.variant_name + model_name = aws_sagemaker_model.model.name + initial_instance_count = local.initial_instance_count + instance_type = local.instance_type + } + + lifecycle { + create_before_destroy = true + } +} + +resource "aws_sagemaker_endpoint" "inference_endpoint" { + endpoint_config_name = aws_sagemaker_endpoint_configuration.inference_endpoint_configuration.name + name = local.sagemaker_endpoint_name +} \ No newline at end of file diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/sm_endpoint_slim/outputs.tf b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/sm_endpoint_slim/outputs.tf new file mode 100644 index 00000000..8677673c --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/sm_endpoint_slim/outputs.tf @@ -0,0 +1,3 @@ +output "inference_endpoint" { + value = aws_sagemaker_endpoint.inference_endpoint +} diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/sm_endpoint_slim/terraform.tf b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/sm_endpoint_slim/terraform.tf new file mode 100644 index 00000000..03d0656a --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/sm_endpoint_slim/terraform.tf @@ -0,0 +1,9 @@ +terraform { + required_providers { + aws = { + source = "hashicorp/aws" + version = "~> 3.0" + } + } + required_version = ">= 1.0 , <= 1.2.4" +} diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/sm_endpoint_slim/variables.tf b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/sm_endpoint_slim/variables.tf new file mode 100644 index 00000000..49097ad3 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/modules/sm_endpoint_slim/variables.tf @@ -0,0 +1,47 @@ +variable "prefix" { + type = string + description = "Namespace prefix from the template." +} + +variable "initial_instance_count" { + default = 1 + description = "Instance Count." + type = number +} + +variable "instance_type" { + default = "ml.t2.medium" + description = "Instance Type." + type = string +} + +variable "model_name" { + description = "Model Name." + type = string +} + +variable "sagemaker_endpoint_name" { + description = "The name of the sagemaker endpoint." + type = string +} + +variable "variant_name" { + default = "variant-1" + description = "The name of the variant." + type = string +} + +variable "sagemaker_execution_role" { + description = "The name of the SM execution role for the model" + type = string +} + +variable "inference_image" { + type = string + description = "SageMaker inference image" +} + +variable "model_data_url" { + type = string + description = "SageMaker model data url" +} diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/variables.tf b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/variables.tf new file mode 100644 index 00000000..16225a3c --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/seed_code/deploy_app/terraform/variables.tf @@ -0,0 +1,71 @@ +variable "sm_project_id" { + type = string + description = "Sagemaker Project ID" +} + +variable "sm_project_name" { + type = string + description = "Sagemaker Project Name" +} + +variable "aws_account_id" { + type = string + description = "AWS Account ID" +} + +variable "aws_region" { + type = string + description = "AWS Region" +} + +variable "codecommit_id" { + type = string + description = "CodeCommit ID." +} + +variable "prefix" { + type = string + description = "Namespace prefix from the template." +} + +variable "artifact_bucket_name" { + type = string + description = "Project artifact bucket name." +} + +variable "default_branch" { + type = string + description = "Default CodeCommit branch." +} + +variable "model_name" { + type = string + description = "SageMaker model name" + default = "" +} + +variable "sm_execution_role_arn" { + type = string + description = "SageMaker Execution role arn" +} + +variable "inference_image" { + type = string + default = "" + description = "Model inference image" +} + +variable "model_data_url" { + type = string + description = "SageMaker model data url" + default = "" +} + +variable "model_package_group_name" { + type = string + description = "Name of project's model package group" +} + + + + diff --git a/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/service_catalog_product_template.yaml.tpl b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/service_catalog_product_template.yaml.tpl new file mode 100644 index 00000000..e35cb2d8 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/templates/mlops_terraform_template/service_catalog_product_template.yaml.tpl @@ -0,0 +1,63 @@ +Description: |- + Sagemaker Projects - MLOps Template using Terraform +Parameters: + SageMakerProjectName: + Type: String + AllowedPattern: ^[a-zA-Z](-*[a-zA-Z0-9])* + Description: Name of the project + MaxLength: 32 + MinLength: 1 + SageMakerProjectId: + Type: String + Description: Service generated Id of the project. +Resources: + MlOpsArtifactsBucket: + Type: AWS::S3::Bucket + Properties: + BucketName: + Fn::Sub: "${artifact_bucket_name}" + DeletionPolicy: Retain + MlOpsProjectStateBucket: + Type: AWS::S3::Bucket + Properties: + BucketName: + Fn::Sub: "${state_bucket_name}" + DeletionPolicy: Retain + ModelBuildCodeCommitRepository: + Type: AWS::CodeCommit::Repository + Properties: + RepositoryName: + Fn::Sub: "${build_code_repo_name}" + Code: + BranchName: ${default_branch} + S3: + Bucket: ${seed_code_bucket} + Key: ${seed_code_build_key} + RepositoryDescription: Model Build Code + ModelDeployCodeCommitRepository: + Type: AWS::CodeCommit::Repository + Properties: + RepositoryName: + Fn::Sub: "${deploy_code_repo_name}" + Code: + BranchName: ${default_branch} + S3: + Bucket: ${seed_code_bucket} + Key: ${seed_code_deploy_key} + RepositoryDescription: Model Deploy Code +Outputs: + Prefix: + Value: "${prefix}" + Description: Prefix value for infrastructure created by this template + DefaultBranch: + Value: "${default_branch}" + Description: Default branch CodeCommit + MlOpsProjectStateBucket: + Value: !Ref MlOpsProjectStateBucket + Description: Name of State Bucket for Project + MlOpsArtifactsBucket: + Value: !Ref MlOpsArtifactsBucket + Description: Name of Artifacts Bucket for Project + BucketRegion: + Value: !Sub "$${AWS::Region}" + Description: Region on State Bucket for Project diff --git a/mlops-template-terraform/mlops_templates/terraform/variables.tf b/mlops-template-terraform/mlops_templates/terraform/variables.tf new file mode 100644 index 00000000..139597f9 --- /dev/null +++ b/mlops-template-terraform/mlops_templates/terraform/variables.tf @@ -0,0 +1,2 @@ + + From caeae9cb42636f30d506f059eab84104dc972a05 Mon Sep 17 00:00:00 2001 From: Oliver Zollikofer Date: Thu, 20 Oct 2022 00:03:44 +0200 Subject: [PATCH 2/2] comment cleaning --- .../mlops_infra/terraform/modules/iam/main.tf | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/mlops-template-terraform/mlops_infra/terraform/modules/iam/main.tf b/mlops-template-terraform/mlops_infra/terraform/modules/iam/main.tf index 13dabcf2..c0f0353d 100644 --- a/mlops-template-terraform/mlops_infra/terraform/modules/iam/main.tf +++ b/mlops-template-terraform/mlops_infra/terraform/modules/iam/main.tf @@ -1,3 +1,5 @@ +# TODO: Consider scoping down IAM roles depending on your needs + locals { prefix = var.prefix sm_execution_role_name = "${local.prefix}-sagemaker-execution-role" @@ -34,8 +36,6 @@ resource "aws_iam_role_policy_attachment" "aws_sagemaker_full_access" { policy_arn = "arn:aws:iam::aws:policy/AmazonSageMakerFullAccess" } -# How to restrict to necessary actions and services -# TODO: SCOPE DOWN! resource "aws_iam_role_policy_attachment" "aws_sagemaker_cloudformation_poweruser" { role = aws_iam_role.sagemaker_execution_role.name policy_arn = "arn:aws:iam::aws:policy/AWSCloudFormationFullAccess" @@ -120,10 +120,6 @@ resource "aws_iam_role_policy_attachment" "attach_codepipeline_policy" { } - - -# Only to bucket attached to the project -# TODO: SCOPE DOWN! resource "aws_iam_role_policy_attachment" "aws_sagemaker_s3_full_access" { role = aws_iam_role.sagemaker_execution_role.name policy_arn = "arn:aws:iam::aws:policy/AmazonS3FullAccess" @@ -155,7 +151,6 @@ resource "aws_iam_role_policy_attachment" "attach_eventbridge_policy" { policy_arn = aws_iam_policy.eventbridge_policy.arn } -# Below should be fine as only access to the created KMS key resource "aws_iam_policy" "kms_policy" { name = "${local.prefix}-kms-policy" description = "kms_policy for SM Studio"

    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