Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Development Instances Overview

Infrastructure Tooling for P2R Developers

The dev-instances project provides modern, single-user development instances with Golden AMI deployment, API-based management, and hybrid storage architecture. Each instance is dedicated to exactly one developer, with persistent EBS home volumes that survive AMI upgrades.

Purpose

Development Instances serves as P2R’s modernized development environment infrastructure, providing:

  1. Performance - EBS /home provides 10x faster I/O than the original EFS-based shared environment
  2. Persistence - Separate EBS home volumes enable AMI upgrades without data loss
  3. Usability - API and Slack integration for practical instance management (Phase 2+)
  4. Security - EC2 Instance Connect with AWS SSO, no SSH keys or open ports
  5. Maintainability - Golden AMI strategy for consistent, reproducible environments

Architecture

Core Components

                      ┌─────────────────────────────────────────────────────────┐
                      │              Golden AMI Build Pipeline                   │
                      │                                                          │
                      │   EC2 Image Builder → Golden AMI → SSM Parameter        │
                      │                                                          │
                      │   Monthly Schedule | Pre/Post-Upgrade Components        │
                      │   Ubuntu 24.04 LTS | Data Science Stack                 │
                      └─────────────────────────┬───────────────────────────────┘
                                                │
                                                │ AMI ID
                                                ▼
┌─────────────────────────────────────────────────────────────────────────────────┐
│                        Instance Deployment (CloudFormation)                      │
│                                                                                  │
│   Template URL: s3://p2r-dev-instances-templates/instance-deployment-template   │
│                                                                                  │
│   ┌──────────────────┐  ┌──────────────────┐  ┌──────────────────────────────┐  │
│   │  EC2 Instance    │  │  EBS Home Volume │  │  EFS Mounts (7 filesystems)  │  │
│   │  Single Owner    │  │  Persistent      │  │  Shared Data Access          │  │
│   └──────────────────┘  └──────────────────┘  └──────────────────────────────┘  │
└─────────────────────────────────────────────────────────────────────────────────┘

Technology Stack

ComponentTechnology
InfrastructureAWS CDK 2.233, TypeScript, CloudFormation
AMI PipelineEC2 Image Builder, Lambda, EventBridge
CI/CDAWS CodePipeline, CodeBuild, Bitbucket
Base OSUbuntu 24.04 LTS
Instance AuthEC2 Instance Connect, AWS SSO
StorageEBS (home), EFS (shared data)
ConfigurationSSM Parameter Store
TestingJest, ts-jest
RuntimeNode.js 20/22/24, npm 10/11

Repository Structure

dev-instances/
├── cdk/                           # CDK infrastructure code
│   ├── bin/
│   │   ├── dev-instances.ts       # Main CDK app (branch-aware deployment)
│   │   └── synthesize-instance-template.ts  # Template generator
│   ├── lib/
│   │   ├── config.ts              # DevInstancesConfig class + constants
│   │   ├── git-util.ts            # Git branch detection
│   │   ├── image-builder-stack.ts # Golden AMI pipeline infrastructure
│   │   ├── image-builder-pipeline-stack.ts  # CI/CD pipeline + S3 template bucket
│   │   ├── instance-deployment-stack.ts     # Instance deployment template
│   │   └── imagebuilder/
│   │       └── components/        # Image Builder components (TypeScript → YAML)
│   │           ├── build/         # Build phase components
│   │           │   ├── pre-upgrade/   # Before update-linux
│   │           │   └── post-upgrade/  # After update-linux
│   │           └── test/          # Test phase components
│   └── test/                      # Jest test files
├── docs/                          # Documentation
│   ├── ARCHITECTURE.md            # Complete system architecture
│   ├── INSTANCE_DEPLOYMENT_GUIDE.md   # User deployment guide
│   ├── TEMPLATE_MAINTENANCE.md    # DevOps maintenance guide
│   └── INTEGRATION_TESTING.md     # Testing procedures
├── lambda/                        # API Lambda functions (Phase 2)
├── cli/                           # Command-line interface (Phase 2)
├── slack-app/                     # Slack integration (Phase 3)
├── Makefile                       # Build automation
├── package.json                   # npm configuration
└── README.md                      # Project overview

Golden AMI Pipeline

What Gets Built

The Golden AMI pipeline creates Ubuntu 24.04 LTS AMIs on a monthly schedule with:

System Users (6 accounts)

UsernameUIDGIDPurpose
datascience80038003Data science workloads
datatools80188018Data tools operations
orders80149006Order processing
convert80028002Data conversion
preselect80158015Preselection processing
households80058005Household operations

Development Tools

  • Git, Docker Engine, AWS CLI v2, Deno
  • Python 3.12.8 (Miniconda3), Poetry
  • Scala 2.12.20, Hadoop 3.4.0, Spark 3.5.2
  • EC2 Instance Connect package

System Configuration

  • Sophos gateway routing (Path2Response account)
  • EFS mounts for 7 filesystems
  • Passwordless sudo for sudo group
  • User package persistence system

Build Component Sequence

Pre-Upgrade Components (before update-linux):
  00-networking     → Sophos gateway configuration
  01-hosts-config   → /etc/hosts with P2R infrastructure
  02-system-config  → Sudoers, EFS mount points

System Update:
  update-linux      → AWS managed security updates

Post-Upgrade Components (after update-linux):
  00-system-users   → 6 system user accounts
  01-system-libs    → Build tools, network tools, DB clients
  02-dev-tools      → Git, Docker, AWS CLI, Deno
  03-additional-packages → Configurable APT packages
  04-snap-packages  → Configurable Snap packages
  05-ec2-instance-connect → SSH via AuthorizedKeysCommand
  06-user-package-persistence → APT hook + boot service
  07-data-science-stack → Python, Scala, Spark

Test Phase:
  01-gateway-test   → Internet connectivity validation
  02-service-validation → Docker daemon running
  04-dev-tools-integration → Tool functionality tests
  05-network-connectivity → DNS, HTTPS, AWS, EFS tests

Pipeline Triggers

TriggerCondition
ScheduledMonthly (1st at 2 AM UTC)
Base Image UpdateUbuntu 24.04 LTS security patches
ManualAWS CLI or Console

Instance Deployment

Single-User Model

Each development instance is dedicated to exactly ONE developer:

  • Instance owned by a single P2R developer
  • Operates with owner’s AWS permissions
  • Contains only owner’s home directory on EBS
  • Owner can SSH to system user accounts for shared workloads

Deployment Methods

Via AWS Console:

  1. Navigate to CloudFormation Console
  2. Create stack with S3 URL: https://p2r-dev-instances-templates.s3.amazonaws.com/instance-deployment-template.json
  3. Specify parameters (InstanceOwner required)
  4. Deploy

Via AWS CLI:

aws cloudformation create-stack \
  --stack-name dev-instance-whofmann-01 \
  --template-url https://p2r-dev-instances-templates.s3.amazonaws.com/instance-deployment-template.json \
  --parameters \
    ParameterKey=InstanceOwner,ParameterValue=whofmann \
    ParameterKey=InstanceType,ParameterValue=t3.xlarge \
  --capabilities CAPABILITY_IAM \
  --profile p2r_root

CloudFormation Parameters

ParameterRequiredDefaultDescription
InstanceOwnerYes-P2R username (e.g., “whofmann”)
HomeVolumeIdNo(new)Existing EBS volume to attach
InstanceTypeNot3.xlargeEC2 instance type
HomeVolumeSizeNo100 GBSize for new home volumes
RootVolumeSizeNo150 GBRoot volume size

P2R Users (10 developers)

chouk, dfuller, eyang, ioliynyk, jmalone, jsmith, mford, mpelikan, pmartin, whofmann


Hybrid Storage Architecture

Storage Layout

/                        # Root EBS volume (OS, applications)
├── home/                # Dedicated EBS volume (persistent user data)
│   ├── datascience/     # System user (from AMI)
│   ├── datatools/       # System user (from AMI)
│   ├── orders/          # System user (from AMI)
│   ├── convert/         # System user (from AMI)
│   ├── preselect/       # System user (from AMI)
│   ├── households/      # System user (from AMI)
│   └── <owner>/         # P2R user (instance owner only)
│       ├── .dev-instance/    # Package persistence (bind-mounted)
│       ├── .linuxbrew/       # Homebrew installation
│       ├── .local/           # pip --user packages
│       └── code/             # User projects
├── var/
│   └── dev-instance/    # Bind mount from ~/.dev-instance
├── mnt/
│   ├── data/            # Symlink to owner's preferred EFS
│   ├── shared-home/     # EFS shared collaboration space
│   ├── etl.production/  # EFS (read-only)
│   ├── etl.development/ # EFS (read-write)
│   ├── orders.production/   # EFS (read-only)
│   ├── orders.rc/           # EFS (read-only)
│   ├── orders.staging/      # EFS (read-write)
│   └── orders.development/  # EFS (read-write)

EFS Filesystems (7 total)

Mount PointAccessDescription
/mnt/shared-homeRead-WriteShared user collaboration space
/mnt/etl.productionRead-OnlyETL production data
/mnt/etl.developmentRead-WriteETL development data
/mnt/orders.productionRead-OnlyOrders production data
/mnt/orders.rcRead-OnlyOrders RC data
/mnt/orders.stagingRead-WriteOrders staging data
/mnt/orders.developmentRead-WriteOrders development data

Performance Rationale

Why EBS for /home?

  • Original implementation used EFS for /home
  • EFS was too slow for development work (IDE indexing, compilation, etc.)
  • EBS provides 10x faster I/O performance
  • Separate EBS volume persists across AMI upgrades

User Package Persistence

Problem

Users need to install additional software that persists across AMI upgrades.

Solution

Automatic package tracking and reinstallation system:

User installs package → APT hook tracks → ~/.dev-instance/apt-packages.txt
                                                    ↓
AMI upgrade → Boot service reads list → Reinstalls packages

Three Installation Options

MethodCommandPersistenceBest For
APTsudo apt-get installAuto-reinstall via boot serviceSystem libraries, services
Homebrewbrew installDirect on EBSDev tools, modern versions
Language Managerspip install --userDirect on EBSLanguage ecosystems

Branch-Based Deployment

Main Branch (Automated Pipeline)

git checkout main
AWS_PROFILE=p2r_root npx cdk deploy
# Creates: DevInstancesImageBuilderPipeline
# Pipeline deploys:
#   - DevInstancesImageBuilderPipeline-ImageBuilderStack
#   - Uploads instance-deployment-template.json to S3

Features:

  • Self-mutating CodePipeline monitors Bitbucket main branch
  • Automatic builds on git push
  • Slack notifications for pipeline events
  • Writes SSM parameters for service discovery

Feature Branch (Manual Deployment)

git checkout feature/my-feature
AWS_PROFILE=p2r_root npx cdk deploy
# Creates: DevInstancesImageBuilder-feature-my-feature

Features:

  • Direct deployment (no pipeline)
  • Isolated testing environment
  • Branch-specific SSM namespace
  • Does not affect main deployment

Resource Isolation

ResourceMain BranchFeature Branch
S3 Bucketp2r-devinst-imgbldr-main-root-us-east-1p2r-devinst-imgbldr-{branch}-root-us-east-1
SSM Namespace/config/dev-instances//config/dev-instances-{branch}/
Stack NameDevInstancesImageBuilderPipelineDevInstancesImageBuilder-{branch}

Configuration Management

DevInstancesConfig Class

The project uses a class-based configuration approach that encapsulates branch context:

const config = new DevInstancesConfig(isMainBranch, branchName);

// SSM parameter paths - clean API
config.output.goldenAmiLatestId(region)      // Latest AMI ID
config.output.imageBuilderPipelineArn(region) // Pipeline ARN
config.input.vpcId(region)                    // VPC from Terraform

Key Configuration Constants

ConstantLocationPurpose
RECIPE_VERSIONconfig.tsManual versioning for Image Builder recipes
SYSTEM_USERSconfig.ts6 system user accounts
EFS_CONFIGconfig.ts7 EFS filesystems with mount options
IMAGE_BUILDER_DEFAULTSconfig.tsBuild instance type, schedule, retention

SSM Parameter Structure

Infrastructure Configuration (Input)

/config/p2r-tf-infra-network/{region}/Vpc4General/id
/config/p2r-tf-infra-network/{region}/Vpc4General/private-subnet-ids
/config/p2r-tf-infra-network/{region}/Vpc4General/public-subnet-ids

User Configuration (50 parameters)

/config/dev-instances/global/users/{username}/uid
/config/dev-instances/global/users/{username}/shell
/config/dev-instances/global/users/{username}/groups
/config/dev-instances/global/users/{username}/data-mount-preference
/config/dev-instances/global/users/{username}/ssh-public-keys

Image Builder Outputs

/config/dev-instances/{region}/golden-ami/latest-id
/config/dev-instances/{region}/image-builder/pipeline-arn
/config/dev-instances/{region}/image-builder/recipe-arn
/config/dev-instances/{region}/image-builder/artifact-bucket-name

Instance Metadata (per instance)

/config/dev-instances/{region}/instances/by-id/{instance-id}/owner
/config/dev-instances/{region}/instances/by-id/{instance-id}/home-volume-id
/config/dev-instances/{region}/instances/by-id/{instance-id}/created-at
/config/dev-instances/{region}/instances/by-owner/{owner}/{instance-id}

Development Workflow

Build and Deploy

# Install dependencies
npm install

# Build TypeScript
npm run build

# Run tests
npm test

# Deploy (branch-aware)
AWS_PROFILE=p2r_root npx cdk deploy

# Generate instance template locally (for testing)
npm run template:generate

Trigger Manual AMI Build

# Get pipeline ARN
PIPELINE_ARN=$(aws ssm get-parameter \
  --name /config/dev-instances/us-east-1/image-builder/pipeline-arn \
  --query 'Parameter.Value' --output text --profile p2r_root)

# Start build
aws imagebuilder start-image-pipeline-execution \
  --image-pipeline-arn $PIPELINE_ARN \
  --profile p2r_root

Build time: 20-30 minutes.

View Build Logs

# CloudWatch Logs
aws logs tail /aws/imagebuilder/DevInstancesImageBuilder-pipeline \
  --profile p2r_root --follow

# S3 Logs
aws s3 ls s3://p2r-devinst-imgbldr-main-root-us-east-1/image-builder-logs/ \
  --profile p2r_root --recursive

Implementation Status

Phase 1: Golden AMI Pipeline - COMPLETE

TicketDescriptionStatus
PATH-25858EC2 Image Builder in CDKComplete
PATH-25859Core Software SetupComplete
PATH-25860Data Science StackComplete
PATH-25861Instance Deployment TemplatesComplete

Phase 2: Instance Management - PLANNED

TicketDescriptionStatus
PATH-27115Core Management APIPlanned
PATH-27116API Control OperationsPlanned
PATH-27119CLI FrontendPlanned
PATH-25864Documentation & MigrationPlanned

Phase 3: Advanced Features - PLANNED

TicketDescriptionStatus
PATH-27117Slack IntegrationPlanned
PATH-27118AMI Upgrade FunctionalityPlanned

Success Metrics

MetricTarget
Performance10x I/O improvement over EFS-only
Deployment Speed< 5 minutes from API call to running
User Adoption80% using API/Slack within 1 month
Support Reduction50% fewer access-related tickets
Availability99.5% uptime during business hours

Cost Estimates

Running Instance (t3.xlarge)

ResourceMonthly Cost
Instance (730 hours)~$121
Root volume (150 GB)~$15
Home volume (100 GB)~$10
Total~$146/month

Stopped Instance

ResourceMonthly Cost
Root volume (150 GB)~$15
Home volume (100 GB)~$10
Total~$25/month


Important Notes

  • Single-user model - Each instance is dedicated to exactly one developer
  • AMI upgrades preserve data - Home EBS volume persists across upgrades
  • Target account - Path2Response root account (448838825215) only
  • VPC peering - Required for EFS access to production/RC environments
  • Recipe versioning - Manual increment required when components change
  • Component lifecycle - Components are development artifacts, not production resources

Source: dev-instances repository (README.md, docs/ARCHITECTURE.md, cdk/lib/) Documentation created: 2026-01-24