Admin

Artificial Intelligence

SageMaker MLOps: End-to-End Pipelines, Registry & A/B Deployment

Implement MLOps with SageMaker Pipelines, model registry & A/B endpoint deployment. Build scalable ML workflows on AWS for efficient model management.

By Sujay SinghPublished: August 1, 202611 min read11 views✓ Fact Checked
SageMaker MLOps: End-to-End Pipelines, Registry & A/B Deployment
SageMaker MLOps: End-to-End Pipelines, Registry & A/B Deployment

Building Robust MLOps Workflows: SageMaker Pipelines, Model Registry, and A/B Deployment

The promise of machine learning in transforming businesses is undeniable, yet translating experimental models into reliable, production-grade services remains a significant hurdle for many organizations. This is where MLOps – the amalgamation of Machine Learning, Development, and Operations – steps in. MLOps aims to automate, standardize, and govern the entire ML lifecycle, from data preparation and model training to deployment and monitoring. Amazon SageMaker offers a comprehensive suite of tools that are instrumental in achieving sophisticated MLOps, with SageMaker Pipelines, the Model Registry, and advanced A/B endpoint deployment capabilities being standout features.

As a senior technology writer for TechNews Venture, I've seen firsthand how these integrated services empower data science and engineering teams to accelerate their ML initiatives. In this article, we will delve deep into how to leverage SageMaker Pipelines for orchestrating end-to-end ML workflows, utilize the Model Registry for versioning and governance, and implement robust A/B testing for controlled model rollouts, ensuring your ML models deliver consistent value in production.

Overview of Key Components

  • SageMaker Pipelines: This is a purpose-built CI/CD service for machine learning. It allows you to create, manage, and execute automated ML workflows that include data processing, model training, model evaluation, and model registration. Pipelines ensure reproducibility, auditability, and automation of your ML lifecycle.

  • SageMaker Model Registry: A central repository for managing your ML models. It provides versioning, metadata tracking, and approval workflows, enabling better governance and traceability of models deployed to production. You can register model packages, track their lineage, and manage their status (e.g., Approved, Rejected, PendingManualApproval).

  • SageMaker A/B Endpoint Deployment: SageMaker Endpoints allow you to deploy models for real-time inference. For controlled rollouts and experimentation, SageMaker supports A/B testing by deploying multiple model versions (variants) behind a single endpoint, routing a configurable percentage of inference traffic to each variant. This enables testing new model versions with live traffic without impacting all users, facilitating safe deployments and performance comparisons.

Prerequisites

Before we embark on building our MLOps workflow, ensure you have the following:

  • An AWS Account: With necessary administrative access.

  • AWS CLI Configured: Ensure your AWS CLI is installed and configured with appropriate credentials. We will be using the us-east-1 region for our examples.

  • IAM Permissions: An IAM role with permissions to create and manage SageMaker resources (e.g., AmazonSageMakerFullAccess), S3 buckets, CloudWatch logs, and ECR (for custom containers, though we'll use built-in images here). For SageMaker execution, a dedicated IAM role for SageMaker is essential.

  • Python Environment: With the boto3 and sagemaker SDKs installed.

    
    pip install boto3 sagemaker --upgrade
            
  • SageMaker Studio (Optional but Recommended): Provides an integrated environment for ML development, including visual pipeline tracking.

Step-by-step Implementation

We will walk through creating a complete ML workflow, from data processing to A/B deployment, using a synthetic dataset for a binary classification task.

1. Initial Setup: S3 Bucket and IAM Role

First, let's set up an S3 bucket to store our data and model artifacts, and define an IAM role that SageMaker will use to execute our pipeline and access resources.


# Create S3 bucket
aws s3 mb s3://tech-news-venture-mlops-data-12345 --region us-east-1

# Create an IAM role for SageMaker
aws iam create-role --role-name SageMakerExecutionRoleTNVM --assume-role-policy-document '{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Service": "sagemaker.amazonaws.com"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}'

# Attach policies to the role
aws iam attach-role-policy --role-name SageMakerExecutionRoleTNVM --policy-arn arn:aws:iam::aws:policy/AmazonSageMakerFullAccess
aws iam attach-role-policy --role-name SageMakerExecutionRoleTNVM --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess
aws iam attach-role-policy --role-name SageMakerExecutionRoleTNVM --policy-arn arn:aws:iam::aws:policy/CloudWatchLogsFullAccess

# Get the ARN of the created role (you'll need this in your Python script)
aws iam get-role --role-name SageMakerExecutionRoleTNVM --query Role.Arn --output text
# Expected output: arn:aws:iam::123456789012:role/SageMakerExecutionRoleTNVM

Replace 123456789012 with your actual AWS account ID.

2. Data Preparation Script

We'll create a simple Python script to simulate data generation and preprocessing. This script will be executed as a SageMaker Processing job.

Save the following as preprocessing.py:


# preprocessing.py
import argparse
import os
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--input-data-dir", type=str, default="/opt/ml/processing/input")
    parser.add_argument("--output-data-dir", type=str, default="/opt/ml/processing/output")
    args = parser.parse_args()

    print("Generating synthetic data...")
    # Simulate generating some data
    data = {
        'feature_1': [i * 0.1 + (i % 5) for i in range(1000)],
        'feature_2': [i * 0.2 + (i % 3) for i in range(1000)],
        'feature_3': [i * 0.05 + (i % 7) for i in range(1000)],
        'target': [1 if i % 2 == 0 else 0 for i in range(1000)]
    }
    df = pd.DataFrame(data)

    # Simple preprocessing
    X = df[['feature_1', 'feature_2', 'feature_3']]
    y = df['target']

    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

    scaler = StandardScaler()
    X_train_scaled = scaler.fit_transform(X_train)
    X_test_scaled = scaler.transform(X_test)

    train_df = pd.DataFrame(X_train_scaled, columns=X.columns)
    train_df['target'] = y_train.reset_index(drop=True)
    
    test_df = pd.DataFrame(X_test_scaled, columns=X.columns)
    test_df['target'] = y_test.reset_index(drop=True)

    print("Saving processed data...")
    os.makedirs(os.path.join(args.output_data_dir, "train"), exist_ok=True)
    os.makedirs(os.path.join(args.output_data_dir, "test"), exist_ok=True)

    train_df.to_csv(os.path.join(args.output_data_dir, "train", "train.csv"), index=False)
    test_df.to_csv(os.path.join(args.output_data_dir, "test", "test.csv"), index=False)
    print("Data processing complete.")

3. Model Training Script

Next, we'll create a training script using scikit-learn. This script will be used by our SageMaker Training job.

Save the following as train.py:


# train.py
import argparse
import os
import pandas as pd
import joblib
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score, classification_report

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--train-data-dir", type=str, default=os.environ.get("SM_CHANNEL_TRAIN"))
    parser.add_argument("--model-dir", type=str, default=os.environ.get("SM_MODEL_DIR"))
    args = parser.parse_args()

    print(f"Loading training data from {args.train_data_dir}...")
    train_df = pd.read_csv(os.path.join(args.train_data_dir, "train.csv"))

    X_train = train_df.drop("target", axis=1)
    y_train = train_df["target"]

    print("Training Logistic Regression model...")
    model = LogisticRegression(random_state=42)
    model.fit(X_train, y_train)
    print("Model training complete.")

    print(f"Saving model to {args.model_dir}/model.joblib")
    joblib.dump(model, os.path.join(args.model_dir, "model.joblib"))
    print("Model saved.")

4. SageMaker Pipeline Definition

Now, let's define our MLOps pipeline using the SageMaker Python SDK. This script will orchestrate the data processing, training, and model registration steps.

Save the following as pipeline_definition.py:


# pipeline_definition.py
import sagemaker
import boto3
from sagemaker.workflow.pipeline import Pipeline
from sagemaker.workflow.steps import ProcessingStep, TrainingStep, CreateModelStep, CacheConfig
from sagemaker.workflow.step_collections import RegisterModel
from sagemaker.processing import ScriptProcessor
from sagemaker.sklearn.processing import SKLearnProcessor
from sagemaker.sklearn.estimator import SKLearn
from sagemaker.model import Model
from sagemaker.inputs import TrainingInput
from sagemaker.image_uris import retrieve
from sagemaker.workflow.parameters import (
    ParameterInteger,
    ParameterString,
    ParameterFloat,
)

# --- Configuration ---
region = "us-east-1"
bucket_name = "tech-news-venture-mlops-data-12345" # Replace with your S3 bucket name
sagemaker_session = sagemaker.Session(default_bucket=bucket_name, boto_session=boto3.Session(region_name=region))
# Replace with the ARN of the SageMakerExecutionRoleTNVM role you created
role = "arn:aws:iam::123456789012:role/SageMakerExecutionRoleTNVM" 

# Define pipeline parameters
processing_instance_type = ParameterString(name="ProcessingInstanceType", default_value="ml.m5.xlarge")
training_instance_type = ParameterString(name="TrainingInstanceType", default_value="ml.m5.xlarge")
model_approval_status = ParameterString(name="ModelApprovalStatus", default_value="PendingManualApproval")
model_package_group_name = ParameterString(name="ModelPackageGroupName", default_value="TechNewsVentureModelPackageGroup")

# Cache configuration for pipeline steps
cache_config = CacheConfig(enable_cache=True, expire_after="P30D") # Cache for 30 days

# --- Step 1: Data Processing ---
# Use an SKLearnProcessor for preprocessing script
sklearn_processor_image_uri = retrieve(framework="sklearn", region=region, version="1.2-1")
sklearn_processor = SKLearnProcessor(
    framework_version="1.2-1",
    role=role,
    instance_type=processing_instance_type,
    instance_count=1,
    sagemaker_session=sagemaker_session,
    base_job_name="tnv-data-preprocessing",
)

processing_step_args = sklearn_processor.run(
    outputs=[
        sagemaker.processing.ProcessingOutput(source="/opt/ml/processing/output/train", destination=f"s3://{bucket_name}/processed_data/train"),
        sagemaker.processing.ProcessingOutput(source="/opt/ml/processing/output/test", destination=f"s3://{bucket_name}/processed_data/test"),
    ],
    code="preprocessing.py",
)

processing_step = ProcessingStep(
    name="DataPreprocessing",
    step_args=processing_step_args,
    cache_config=cache_config
)

# --- Step 2: Model Training ---
# Use an SKLearn Estimator for the training script
sklearn_estimator_image_uri = retrieve(framework="sklearn", region=region, version="1.2-1")
sklearn_estimator = SKLearn(
    entry_point="train.py",
    role=role,
    instance_type=training_instance_type,
    instance_count=1,
    framework_version="1.2-1",
    sagemaker_session=sagemaker_session,
    output_path=f"s3://{bucket_name}/model_artifacts",
    base_job_name="tnv-model-training",
)

training_step_args = sklearn_estimator.fit(
    inputs={"train": TrainingInput(s3_data=processing_step.properties.ProcessingOutputConfig.Outputs["train"].S3Output.S3Uri)}
)

training_step = TrainingStep(
    name="ModelTraining",
    step_args=training_step_args,
    cache_config=cache_config
)

# --- Step 3: Model Registration ---
# Create a SageMaker Model object from the training job artifact
# This model will be used to create the ModelPackage
model_path = training_step.properties.ModelArtifacts.S3ModelArtifacts
model_image_uri = retrieve(framework="sklearn", region=region, version="1.2-1", py_version="py3", instance_type="ml.m5.xlarge") # Inference image

model = Model(
    image_uri=model_image_uri,
    model_data=model_path,
    sagemaker_session=sagemaker_session,
    role=role,
)

# Register the model to the Model Registry
register_model_step_args = model.register(
    content_types=["text/csv"],
    response_types=["application/json"],
    inference_instances=["ml.t2.medium", "ml.m5.large"],
    transform_instances=["ml.m5.xlarge"],
    model_package_group_name=model_package_group_name,
    model_approval_status=model_approval_status,
)

register_step = RegisterModel(
    name="RegisterModel",
    estimator=sklearn_estimator, # Use estimator to infer model data and image
    model_data=training_step.properties.ModelArtifacts.S3ModelArtifacts,
    content_types=["text/csv"],
    response_types=["application/json"],
    inference_instances=["ml.t2.medium", "ml.m5.large"],
    transform_instances=["ml.m5.xlarge"],
    model_package_group_name=model_package_group_name,
    model_approval_status=model_approval_status,
    depends_on=[training_step]
)


# --- Define the Pipeline ---
pipeline = Pipeline(
    name="TechNewsVentureMLOpsPipeline",
    parameters=[
        processing_instance_type,
        training_instance_type,
        model_approval_status,
        model_package_group_name,
    ],
    steps=[processing_step, training_step, register_step],
    sagemaker_session=sagemaker_session,
)

print(f"Pipeline definition: {pipeline.definition()}")

# Upload and create the pipeline
pipeline.upsert(role_arn=role)
print("Pipeline created/updated successfully!")

# Start a pipeline execution
execution = pipeline.start()
print(f"Pipeline execution started: {execution.arn}")

Run this script to define and start your pipeline:


python pipeline_definition.py

You can monitor the pipeline execution in SageMaker Studio or via the AWS CLI:


aws sagemaker list-pipeline-executions --pipeline-name TechNewsVentureMLOpsPipeline --region us-east-1

5. Model Registry Integration and Approval

Once the pipeline completes, a new model package version will be registered in the SageMaker Model Registry under the TechNewsVentureModelPackageGroup. By default, we set its status to PendingManualApproval. This allows for human review before deployment to production.

To approve a model package, you can use the AWS CLI or SageMaker Studio. First, find the latest model package ARN:


aws sagemaker list-model-packages \
    --model-package-group-name TechNewsVentureModelPackageGroup \
    --query "ModelPackageSummaryList[0].ModelPackageArn" \
    --region us-east-1 \
    --output text

Then, update its status:


MODEL_PACKAGE_ARN="arn:aws:sagemaker:us-east-1:123456789012:model-package/TechNewsVentureModelPackageGroup/1" # Replace with actual ARN
aws sagemaker update-model-package \
    --model-package-arn $MODEL_PACKAGE_ARN \
    --model-approval-status Approved \
    --region us-east-1

6. A/B Endpoint Deployment

Now, let's deploy our approved model (the "Challenger") to an existing endpoint that might be serving an older model (the "Champion"). We'll use traffic splitting to gradually shift inference traffic.

First, let's assume you have a "Champion" model already deployed. If not, we'll deploy one as our initial baseline.

Step 6.1: Deploy Initial Champion Model (if not already existing)

We'll manually create a model from the *first* approved package and deploy it as our Champion. This is typically done as part of a separate deployment pipeline or manually for the first model.


# deploy_ab_models.py (Part 1: Initial Champion Deployment)
import sagemaker
import boto3
from sagemaker.model import Model
from sagemaker.predictor import Predictor
from sagemaker.serializers import CSVSerializer
from sagemaker.deserializers import JSONDeserializer
from sagemaker.image_uris import retrieve
import time

region = "us-east-1"
sagemaker_session = sagemaker.Session(boto_session=boto3.Session(region_name=region))
role = "arn:aws:iam::123456789012:role/SageMakerExecutionRoleTNVM" # Replace with your SageMaker role ARN
model_package_group_name = "TechNewsVentureModelPackageGroup"
endpoint_name = "tnv-ab-test-endpoint"

# Get the latest APPROVED model package (Champion)
sm_client = boto3.client("sagemaker", region_name=region)
response = sm_client.list_model_packages(
    ModelPackageGroupName=model_package_group_name,
    ModelApprovalStatus="Approved",
    SortBy="CreationTime",
    SortOrder="Descending",
    MaxResults=1
)

if not response["ModelPackageSummaryList"]:
    print("No approved model packages found. Please ensure a model is approved in the registry.")
    exit()

champion_model_package_arn = response["ModelPackageSummaryList"][0]["ModelPackageArn"]
print(f"Champion Model Package ARN: {champion_model_package_arn}")

# Create SageMaker Model from the Model Package
champion_model_name = f"tnv-champion-model-{int(time.time())}"
print(f"Creating Champion SageMaker Model: {champion_model_name}")
champion_sagemaker_model = Model(
    image_uri=retrieve(framework="sklearn", region=region, version="1.2-1", py_version="py3", instance_type="ml.m5.xlarge"),
    model_data=None, # Model data is part of the Model Package
    sagemaker_session=sagemaker_session,
    role=role,
    name=champion_model_name,
    model_package_arn=champion_model_package_arn
)

# Create Endpoint Configuration for Champion
champion_variant_name = "ChampionModel"
endpoint_config_name = f"{endpoint_name}-config-{int(time.time())}"
print(f"Creating Endpoint Configuration: {endpoint_config_name} for Champion model...")
sm_client.create_endpoint_config(
    EndpointConfigName=endpoint_config_name,
    ProductionVariants=[
        {
            "VariantName": champion_variant_name,
            "ModelName": champion_sagemaker_model.name,
            "InitialInstanceCount": 1,
            "InstanceType": "ml.t2.medium",
            "InitialVariantWeight": 1.0
        }
    ]
)
print("Endpoint configuration created.")

# Create Endpoint with Champion model
print(f"Creating Endpoint: {endpoint_name}...")
sm_client.create_endpoint(
    EndpointName=endpoint_name,
    EndpointConfigName=endpoint_config_name
)

# Wait for endpoint to be IN_SERVICE
print("Waiting for endpoint to be IN_SERVICE...")
waiter = sm_client.get_waiter("endpoint_in_service")
waiter.wait(EndpointName=endpoint_name)
print(f"Endpoint {endpoint_name} is IN_SERVICE with Champion model.")

# Example inference
predictor = Predictor(endpoint_name, sagemaker_session, serializer=CSVSerializer(), deserializer=JSONDeserializer())
sample_data = [[0.5, 0.2, 0.8]] # Example features
print(f"Sample prediction for Champion model: {predictor.predict(sample_data)}")

Run the above script (or parts of it) to get your initial endpoint with the Champion model up. This establishes our baseline.


python deploy_ab_models.py

Step 6.2: Deploy Challenger Model for A/B Testing

Now, let's deploy a new model package (the Challenger, which would be a newer version from our pipeline) to the *same* endpoint, splitting traffic.

Modify the deploy_ab_models.py script or create a new one to perform the update:


# deploy_ab_models.py (Part 2: A/B Deployment Update)
import sagemaker
import boto3
from sagemaker.model import Model
from sagemaker.predictor import Predictor
from sagemaker.serializers import CSVSerializer
from sagemaker.deserializers import JSONDeserializer
from sagemaker.image_uris import retrieve
import time

region = "us-east-1"
sagemaker_session = sagemaker.Session(boto_session=boto3.Session(region_name=region))
role = "arn:aws:iam::123456789012:role/SageMakerExecutionRoleTNVM" # Replace with your SageMaker role ARN
model_package_group_name = "TechNewsVentureModelPackageGroup"
endpoint_name = "tnv-ab-test-endpoint"

sm_client = boto3.client("sagemaker", region_name=region)

# Get the LATEST approved model package (this will be our Challenger)
# This assumes your pipeline has run again and registered a new, approved version.
response = sm_client.list_model_packages(
    ModelPackageGroupName=model_package_group_name,
    ModelApprovalStatus="Approved",
    SortBy="CreationTime",
    SortOrder="Descending",
    MaxResults=1
)

if not response["ModelPackageSummaryList"]:
    print("No approved model packages found for Challenger. Ensure a new model is approved.")
    exit()

challenger_model_package_arn = response["ModelPackageSummaryList"][0]["ModelPackageArn"]
print(f"Challenger Model Package ARN: {challenger_model_package_arn}")

# Ensure the Challenger model package is different from the Champion if you ran the first part
# For demonstration, we assume a new version has been approved.
# In a real scenario, you'd compare ARNs or versions.

# Create SageMaker Model from the Challenger Model Package
challenger_model_name = f"tnv-challenger-model-{int(time.time())}"
print(f"Creating Challenger SageMaker Model: {challenger_model_name}")
challenger_sagemaker_model = Model(
    image_uri=retrieve(framework="sklearn", region=region, version="1.2-1", py_version="py3", instance_type="ml.m5.xlarge"),
    model_data=None,
    sagemaker_session=sagemaker_session,
    role=role,
    name=challenger_model_name,
    model_package_arn=challenger_model_package_arn
)
# Deploy the Challenger model to ensure it's created in SageMaker
# This step doesn't deploy to endpoint, just creates the SageMaker Model resource
challenger_sagemaker_model.deploy(initial_instance_count=0, instance_type="ml.t2.medium", endpoint_name="temp-dummy-endpoint-for-model-creation", wait=False)
sm_client.delete_endpoint(EndpointName="temp-dummy-endpoint-for-model-creation") # Clean up dummy endpoint
print(f"SageMaker Model resource '{challenger_sagemaker_model.name}' created.")


# Get current endpoint configuration to identify Champion variant
current_endpoint_desc = sm_client.describe_endpoint(EndpointName=endpoint_name)
current_endpoint_config_name = current_endpoint_desc["EndpointConfigName"]
current_endpoint_config_desc = sm_client.describe_endpoint_config(EndpointConfigName=
📧

Enjoyed this article?

Get articles like this delivered to your inbox daily. Join 10,000+ tech professionals.

Written By

Sujay Singh

Technology Expert / Cloud Architect at Virtual Venture covering AI, cloud computing, cybersecurity, and emerging tech trends.

Sources & References

• Official company announcements and press releases

• Industry reports from Gartner, IDC, and Statista

• Peer-reviewed research and technical documentation

• On-record statements from industry experts

Last verified: August 1, 2026

Fact-checked by TechNews Venture editorial team

Leave a Comment

Comments are moderated and will appear after review.