Skip to content

Module Banner

terraform-aws-arc-sagemaker

Module: sourcefuse/arc-sagemaker/aws

Registry: https://registry.terraform.io/modules/sourcefuse/arc-sagemaker/aws

Category: AI / Machine Learning

Source: https://github.com/sourcefuse/terraform-aws-arc-sagemaker

Latest Release Last Updated Terraform GitHub Actions

Quality gate

Overview

Creates SageMaker domains, models, endpoint configurations, endpoints, notebooks, and training jobs with IAM roles and VPC configuration.

What It Does

  • SageMaker Domain for Studio users
  • Model creation with primary container configuration
  • Endpoint configuration with production variants
  • Real-time inference endpoints
  • Notebook instances
  • Training job definitions
  • IAM execution roles with S3 and ECR access
  • VPC configuration for private endpoints

For more information about this repository and its usage, please see Terraform AWS Sagemaker Module Usage Guide.

Quickstart

module "sagemaker_model" {
  source                 = "sourcefuse/arc-sagemaker/aws"
  version                = "0.0.1"

  name                   = "terraform-arc"
  create_endpoint_config = true
  create_model           = true


  primary_container = {
    image          = "683313688378.dkr.ecr.us-east-1.amazonaws.com/sagemaker-scikit-learn:1.0-1-cpu-py3"
    model_data_url = "s3://your-sagemaker-model-bucket-21-05-25/model/model.tar.gz"
    environment    = {}
  }

  production_variants = [
    {
      variant_name           = "AllTraffic"
      initial_instance_count = 1
      instance_type          = "ml.m5.large"
      initial_variant_weight = 1.0
    }
  ]
  tags = module.tags.tags
}

Required Inputs

Name Type Description
name string SageMaker resource name prefix
## Key Outputs
Name Description
endpoint_name SageMaker endpoint name
endpoint_arn SageMaker endpoint ARN
model_arn SageMaker model ARN
## Full Variable & Output Reference

The complete inputs/outputs reference is auto-generated below.

Requirements

Name Version
terraform >= 1.5.0
aws ~> 5.0

Providers

Name Version
aws 5.100.0

Modules

Name Source Version
arc_security_group sourcefuse/arc-security-group/aws 0.0.1

Resources

Name Type
aws_iam_role.execution_role resource
aws_iam_role.pipeline_role resource
aws_iam_role.sagemaker_execution_role resource
aws_iam_role_policy.execution_role_custom resource
aws_iam_role_policy.pipeline_role_custom resource
aws_iam_role_policy_attachment.attach_policy resource
aws_iam_role_policy_attachment.execution_role_all_policies resource
aws_iam_role_policy_attachment.pipeline_role_sagemaker_full_access resource
aws_sagemaker_domain.this resource
aws_sagemaker_endpoint.this resource
aws_sagemaker_endpoint_configuration.this resource
aws_sagemaker_model.this resource
aws_sagemaker_pipeline.this resource
aws_sagemaker_user_profile.this resource

Inputs

Name Description Type Default Required
additional_iam_policies List of additional IAM policy ARNs to attach to the execution role list(string) [] no
additional_security_group_ids List of additional security group IDs to attach to the domain list(string) [] no
app_network_access_type Specifies the VPC used for non-EFS traffic. Valid values are PublicInternetOnly and VpcOnly string "PublicInternetOnly" no
app_security_group_management The entity that creates and manages the required security groups for inter-app communication in VPCOnly mode. Valid values are Service and Customer string "Service" no
async_inference_config (Optional) Configuration for asynchronous inference.
object({
output_config = object({
s3_output_path = string
s3_failure_path = optional(string)
kms_key_id = optional(string)
notification_config = optional(object({
include_inference_response_in = optional(string)
error_topic = optional(string)
success_topic = optional(string)
}))
})
client_config = optional(object({
max_concurrent_invocations_per_instance = optional(number)
}))
})
null no
auth_mode The mode of authentication that members use to access the domain. Valid values are IAM and SSO string "IAM" no
container List of containers for inference pipeline (alternative to primary_container) list(any) null no
create_domain Whether to create the SageMaker domain bool false no
create_endpoint Whether to create the SageMaker endpoint bool false no
create_endpoint_config Whether to create the SageMaker endpoint configuration bool false no
create_execution_role Whether to create an execution role for SageMaker bool false no
create_model Whether to create the SageMaker model bool false no
create_pipeline Whether to create the SageMaker pipeline bool false no
create_pipeline_role Whether to create a separate role for pipelines bool false no
create_sagemaker_execution_role Whether to create an SageMaker execution role bool false no
create_security_groups Whether to create security groups for SageMaker Studio bool false no
create_user_profile Whether to create the SageMaker user profile bool false no
data_capture_config (Optional) Configuration for capturing input/output data.
object({
initial_sampling_percentage = number
destination_s3_uri = string
kms_key_id = optional(string)
enable_capture = optional(bool)
capture_options = list(object({
capture_mode = string
}))
capture_content_type_header = optional(object({
csv_content_types = optional(list(string))
json_content_types = optional(list(string))
}))
})
null no
default_space_settings The default space settings for the domain
object({
execution_role_arn = string
security_groups = optional(list(string))

jupyter_server_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string, "ml.t3.medium")
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))
}))

kernel_gateway_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string, "ml.t3.medium")
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))
}))

jupyter_lab_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string, "ml.t3.medium")
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))
}))

space_storage_settings = optional(object({
default_ebs_storage_settings = optional(object({
default_ebs_volume_size_in_gb = number
maximum_ebs_volume_size_in_gb = number
}))
}))

custom_file_system_config = optional(object({
efs_file_system_config = optional(object({
file_system_id = string
file_system_path = string
}))
}))

custom_posix_user_config = optional(object({
gid = optional(number)
uid = optional(number)
}))
})
null no
default_user_settings The default user settings for the domain
object({
execution_role_arn = string
auto_mount_home_efs = optional(string, "Disabled")
default_landing_uri = optional(string)
studio_web_portal = optional(string, "ENABLED")

jupyter_lab_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string, "ml.t3.medium")
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))

app_lifecycle_management = optional(object({
idle_settings = optional(object({
lifecycle_management = optional(string, "ENABLED")
idle_timeout_in_minutes = optional(number, 60)
max_idle_timeout_in_minutes = optional(number, 480)
min_idle_timeout_in_minutes = optional(number, 60)
}))
}))

custom_images = optional(list(object({
app_image_config_name = string
image_name = string
image_version_number = optional(number)
})))

code_repositories = optional(list(object({
repository_url = string
})))

lifecycle_config_arns = optional(list(string))
built_in_lifecycle_config_arn = optional(string)

emr_settings = optional(object({
assumable_role_arns = optional(list(string))
execution_role_arns = optional(list(string))
}))
}))

code_editor_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string, "ml.t3.medium")
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))

app_lifecycle_management = optional(object({
idle_settings = optional(object({
lifecycle_management = optional(string, "ENABLED")
idle_timeout_in_minutes = optional(number, 60)
max_idle_timeout_in_minutes = optional(number, 480)
min_idle_timeout_in_minutes = optional(number, 60)
}))
}))

custom_images = optional(list(object({
app_image_config_name = string
image_name = string
image_version_number = optional(number)
})))

lifecycle_config_arns = optional(list(string))
built_in_lifecycle_config_arn = optional(string)
}))

jupyter_server_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string, "ml.t3.medium")
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))

code_repositories = optional(list(object({
repository_url = string
})))

lifecycle_config_arns = optional(list(string))
}))

kernel_gateway_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string, "ml.t3.medium")
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))

custom_images = optional(list(object({
app_image_config_name = string
image_name = string
image_version_number = optional(number)
})))

lifecycle_config_arns = optional(list(string))
}))

canvas_app_settings = optional(object({
time_series_forecasting_settings = optional(object({
status = optional(string, "DISABLED")
amazon_forecast_role_arn = optional(string)
}))

model_register_settings = optional(object({
status = optional(string, "DISABLED")
cross_account_model_register_role_arn = optional(string)
}))

workspace_settings = optional(object({
s3_artifact_path = optional(string)
s3_kms_key_id = optional(string)
}))

direct_deploy_settings = optional(object({
status = optional(string, "DISABLED")
}))

kendra_settings = optional(object({
status = optional(string, "DISABLED")
}))

identity_provider_oauth_settings = optional(list(object({
data_source_name = optional(string)
secret_arn = optional(string)
status = optional(string, "DISABLED")
})))

emr_serverless_settings = optional(object({
execution_role_arn = optional(string)
status = optional(string, "DISABLED")
}))
}))

tensor_board_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string, "ml.t3.medium")
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))
}))

r_session_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string, "ml.t3.medium")
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))

custom_images = optional(list(object({
app_image_config_name = string
image_name = string
image_version_number = optional(number)
})))
}))

r_studio_server_pro_app_settings = optional(object({
access_status = optional(string, "DISABLED")
user_group = optional(string, "R_STUDIO_USER")
}))

sharing_settings = optional(object({
notebook_output_option = optional(string, "Disabled")
s3_kms_key_id = optional(string)
s3_output_path = optional(string)
}))

space_storage_settings = optional(object({
default_ebs_storage_settings = optional(object({
default_ebs_volume_size_in_gb = number
maximum_ebs_volume_size_in_gb = number
}))
}))

custom_file_system_config = optional(object({
efs_file_system_config = optional(object({
file_system_id = string
file_system_path = string
}))
}))

custom_posix_user_config = optional(object({
gid = optional(number)
uid = optional(number)
}))

studio_web_portal_settings = optional(object({
hidden_app_types = optional(list(string))
hidden_instance_types = optional(list(string))
hidden_ml_tools = optional(list(string))
}))
})
null no
deployment_config Deployment configuration block
object({
blue_green_update_policy = optional(object({
traffic_routing_configuration = object({
type = string
wait_interval_in_seconds = number
canary_size = optional(object({
type = string
value = number
}))
linear_step_size = optional(object({
type = string
value = number
}))
})
maximum_execution_timeout_in_seconds = optional(number)
termination_wait_in_seconds = optional(number)
}))
auto_rollback_configuration = optional(object({
alarms = list(object({
alarm_name = string
}))
}))
rolling_update_policy = optional(object({
wait_interval_in_seconds = number
maximum_execution_timeout_in_seconds = optional(number)
maximum_batch_size = object({
type = string
value = number
})
rollback_maximum_batch_size = optional(object({
type = string
value = number
}))
}))
})
null no
domain_name The name of the SageMaker domain string "arc-sagemaker-domain" no
domain_settings The domain settings
object({
execution_role_identity_config = optional(string, "USER_PROFILE_NAME")
security_group_ids = optional(list(string))

docker_settings = optional(object({
enable_docker_access = optional(string, "ENABLED")
vpc_only_trusted_accounts = optional(list(string))
}))

r_studio_server_pro_domain_settings = optional(object({
domain_execution_role_arn = string
r_studio_connect_url = optional(string)
r_studio_package_manager_url = optional(string)

default_resource_spec = optional(object({
instance_type = optional(string, "ml.t3.medium")
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))
}))
})
null no
enable_network_isolation Isolate the model container from external network bool null no
execution_role_name Name of the execution role to create string "SageMakerStudioExecutionRole" no
execution_role_path Path for the execution role string "/" no
inference_execution_config Multi-container execution configuration
object({
mode = string
})
null no
kms_key_arn (Optional) ARN of the KMS key to encrypt storage volume data. string null no
kms_key_id The AWS KMS customer managed CMK used to encrypt the EFS volume attached to the domain string null no
name The name of the SageMaker model. string "terraform-sg" no
name_prefix (Optional) Prefix for the endpoint configuration name. Conflicts with name. string null no
pipeline_role_name Name of the pipeline role to create string "SageMakerPipelineExecutionRole" no
pipeline_role_path Path for the pipeline role string "/" no
pipelines List of SageMaker pipelines to create
list(object({
name = string
display_name = string
description = optional(string)
definition = optional(string)
role_arn = optional(string)
tags = optional(map(string))

pipeline_definition_s3_location = optional(object({
bucket = string
object_key = string
version_id = optional(string)
}))

parallelism_configuration = optional(object({
max_parallel_execution_steps = number
}))
}))
[] no
primary_container Primary container block
object({
image = string
mode = optional(string)
model_data_url = optional(string)
model_package_name = optional(string)
container_hostname = optional(string)
environment = optional(map(string))
image_config = optional(object({
repository_access_mode = string
repository_auth_config = optional(object({
repository_credentials_provider_arn = string
}))
}))
inference_specification_name = optional(string)
multi_model_config = optional(object({
model_cache_setting = string
}))
model_data_source = optional(object({
s3_data_source = object({
compression_type = string
s3_data_type = string
s3_uri = string
model_access_config = optional(object({
accept_eula = bool
}))
})
}))
})
{
"environment": {},
"image": "683313688378.dkr.ecr.us-east-1.amazonaws.com/sagemaker-scikit-learn:1.0-1-cpu-py3",
"model_data_url": "s3://your-sagemaker-model-bucket-21-05-25/model/model.tar.gz"
}
no
production_variants (Required) List of production variant configurations.
list(object({
variant_name = optional(string)
model_name = optional(string)
initial_instance_count = optional(number)
instance_type = optional(string)
accelerator_type = optional(string)
container_startup_health_check_timeout_in_seconds = optional(number)
core_dump_config = optional(object({
destination_s3_uri = string
kms_key_id = string
}))
enable_ssm_access = optional(bool)
inference_ami_version = optional(string)
initial_variant_weight = optional(number)
model_data_download_timeout_in_seconds = optional(number)
routing_config = optional(object({
routing_strategy = string
}))
serverless_config = optional(object({
max_concurrency = number
memory_size_in_mb = number
provisioned_concurrency = optional(number)
}))
managed_instance_scaling = optional(object({
status = optional(string)
min_instance_count = optional(number)
max_instance_count = optional(number)
}))
volume_size_in_gb = optional(number)
}))
[
{
"initial_instance_count": 1,
"initial_variant_weight": 1,
"instance_type": "ml.m5.large",
"variant_name": "AllTraffic"
}
]
no
retention_policy The retention policy for the domain
object({
home_efs_file_system = optional(string, "Retain")
})
null no
security_group_data (optional) Security Group data
object({
security_group_ids_to_attach = optional(list(string), [])
create = optional(bool, true)
description = optional(string, null)
ingress_rules = optional(list(object({
description = optional(string, null)
cidr_block = optional(string, null)
source_security_group_id = optional(string, null)
from_port = number
ip_protocol = string
to_port = string
self = optional(bool, false)
})), [])
egress_rules = optional(list(object({
description = optional(string, null)
cidr_block = optional(string, null)
destination_security_group_id = optional(string, null)
from_port = number
ip_protocol = string
to_port = string
prefix_list_id = optional(string, null)
})), [])
})
{
"create": false
}
no
security_group_name sagemaker security group name string "sagemaker-sg" no
shadow_production_variants (Optional) List of shadow production variant configurations.
list(object({
variant_name = optional(string)
model_name = string
initial_instance_count = optional(number)
instance_type = optional(string)
initial_variant_weight = optional(number)
}))
[] no
subnet_ids The VPC subnets that Studio uses for communication list(string) [] no
tag_propagation Indicates whether custom tag propagation is supported for the domain. Valid values are ENABLED and DISABLED string "DISABLED" no
tags Tags to assign to the SageMaker model map(string) {} no
user_profiles List of user profiles to create
list(object({
name = string
single_sign_on_user_identifier = optional(string)
single_sign_on_user_value = optional(string)
tags = optional(map(string))

user_settings = optional(object({
execution_role_arn = optional(string)
auto_mount_home_efs = optional(string)
default_landing_uri = optional(string)
studio_web_portal = optional(string)
security_groups = optional(list(string))

jupyter_lab_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string)
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))

app_lifecycle_management = optional(object({
idle_settings = optional(object({
lifecycle_management = optional(string)
idle_timeout_in_minutes = optional(number)
max_idle_timeout_in_minutes = optional(number)
min_idle_timeout_in_minutes = optional(number)
}))
}))

custom_images = optional(list(object({
app_image_config_name = string
image_name = string
image_version_number = optional(number)
})))

code_repositories = optional(list(object({
repository_url = string
})))

lifecycle_config_arns = optional(list(string))
built_in_lifecycle_config_arn = optional(string)

emr_settings = optional(object({
assumable_role_arns = optional(list(string))
execution_role_arns = optional(list(string))
}))
}))

code_editor_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string)
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))

app_lifecycle_management = optional(object({
idle_settings = optional(object({
lifecycle_management = optional(string)
idle_timeout_in_minutes = optional(number)
max_idle_timeout_in_minutes = optional(number)
min_idle_timeout_in_minutes = optional(number)
}))
}))

custom_images = optional(list(object({
app_image_config_name = string
image_name = string
image_version_number = optional(number)
})))

lifecycle_config_arns = optional(list(string))
built_in_lifecycle_config_arn = optional(string)
}))

jupyter_server_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string)
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))

code_repositories = optional(list(object({
repository_url = string
})))

lifecycle_config_arns = optional(list(string))
}))

kernel_gateway_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string)
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))

custom_images = optional(list(object({
app_image_config_name = string
image_name = string
image_version_number = optional(number)
})))

lifecycle_config_arns = optional(list(string))
}))

canvas_app_settings = optional(object({
time_series_forecasting_settings = optional(object({
status = optional(string)
amazon_forecast_role_arn = optional(string)
}))

model_register_settings = optional(object({
status = optional(string)
cross_account_model_register_role_arn = optional(string)
}))

workspace_settings = optional(object({
s3_artifact_path = optional(string)
s3_kms_key_id = optional(string)
}))

direct_deploy_settings = optional(object({
status = optional(string)
}))

kendra_settings = optional(object({
status = optional(string)
}))

identity_provider_oauth_settings = optional(list(object({
data_source_name = optional(string)
secret_arn = optional(string)
status = optional(string)
})))

emr_serverless_settings = optional(object({
execution_role_arn = optional(string)
status = optional(string)
}))
}))

tensor_board_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string)
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))
}))

r_session_app_settings = optional(object({
default_resource_spec = optional(object({
instance_type = optional(string)
lifecycle_config_arn = optional(string)
sagemaker_image_arn = optional(string)
sagemaker_image_version_arn = optional(string)
sagemaker_image_version_alias = optional(string)
}))

custom_images = optional(list(object({
app_image_config_name = string
image_name = string
image_version_number = optional(number)
})))
}))

r_studio_server_pro_app_settings = optional(object({
access_status = optional(string)
user_group = optional(string)
}))

sharing_settings = optional(object({
notebook_output_option = optional(string)
s3_kms_key_id = optional(string)
s3_output_path = optional(string)
}))

space_storage_settings = optional(object({
default_ebs_storage_settings = optional(object({
default_ebs_volume_size_in_gb = number
maximum_ebs_volume_size_in_gb = number
}))
}))

custom_file_system_config = optional(object({
efs_file_system_config = optional(object({
file_system_id = string
file_system_path = string
}))
}))

custom_posix_user_config = optional(object({
gid = optional(number)
uid = optional(number)
}))

studio_web_portal_settings = optional(object({
hidden_app_types = optional(list(string))
hidden_instance_types = optional(list(string))
hidden_ml_tools = optional(list(string))
}))
}))
}))
[] no
vpc_config VPC configuration for the model
object({
security_group_ids = list(string)
subnets = list(string)
})
null no
vpc_id The ID of the VPC that Studio uses for communication string null no

Outputs

Name Description
domain_arn ARN of the SageMaker domain
domain_id ID of the SageMaker domain
domain_url URL to access the SageMaker Studio
endpoint_arn ARN of the SageMaker endpoint
endpoint_config_arn ARN of the SageMaker endpoint configuration
endpoint_config_name Name of the SageMaker endpoint configuration
endpoint_name Name of the SageMaker endpoint
model_arn ARN of the SageMaker model
model_name Name of the SageMaker model
pipeline_arns List of SageMaker pipeline ARNs
pipeline_names List of SageMaker pipeline names
user_profile_names List of SageMaker user profile names
user_profiles Map of SageMaker user profiles with their ARNs

Versioning

This project uses a .version file at the root of the repo which the pipeline reads from and does a git tag.

When you intend to commit to main, you will need to increment this version. Once the project is merged, the pipeline will kick off and tag the latest git commit.

Development

Prerequisites

Configurations

  • Configure pre-commit hooks
    pre-commit install
    

Versioning

while Contributing or doing git commit please specify the breaking change in your commit message whether its major,minor or patch

For Example

git commit -m "your commit message #major"
By specifying this , it will bump the version and if you don't specify this in your commit message then by default it will consider patch and will bump that accordingly

Tests

  • Tests are available in test directory
  • Configure the dependencies
    1
    2
    3
    cd test/
    go mod init github.com/sourcefuse/terraform-aws-refarch-<module_name>
    go get github.com/gruntwork-io/terratest/modules/terraform
    
  • Now execute the test
    go test -timeout  30m
    

Contributing

See CONTRIBUTING.md for commit conventions and development setup.

Authors

This project is authored by: - SourceFuse ARC Team