Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@ Check the [examples](examples/) directory for examples including:
- **Complete** - Full-featured ECR repository with all options
- **Protected** - Repository with deletion protection
- **With ECS Integration** - ECR configured for use with ECS
- **Multi-Region** - Repository configured for cross-region replication
- **Multi-Region** - Repository configured for cross-region replication (manual and automatic approaches)
- **Replication** - ECR repository with built-in cross-region replication support

### Simple example
This example creates an ECR registry using few parameters
Expand Down Expand Up @@ -109,6 +110,46 @@ The module outputs logging-related ARNs:
- `cloudwatch_log_group_arn` - The ARN of the CloudWatch Log Group
- `logging_role_arn` - The ARN of the IAM role used for logging

### Cross-Region Replication

The module now supports automatic cross-region replication for disaster recovery and multi-region deployments. When enabled, images are automatically replicated to specified regions whenever they are pushed to the primary repository.

```hcl
module "ecr" {
source = "lgallard/ecr/aws"

name = "my-application"

# Enable cross-region replication
enable_replication = true
replication_regions = ["us-west-2", "eu-west-1", "ap-southeast-1"]

tags = {
Environment = "production"
Application = "my-app"
}
}
```

**Key Benefits:**
- **Disaster Recovery** - Images remain available if a region becomes unavailable
- **Reduced Latency** - Pull images from the nearest region
- **High Availability** - Improved resilience for multi-region workloads
- **Automatic Sync** - No manual intervention required for replication

**Important Notes:**
- Replication is configured at the registry level (affects all repositories in the account)
- Use immutable tags (`image_tag_mutability = "IMMUTABLE"`) for consistency across regions
- Additional costs apply for cross-region data transfer and storage
- Replication is one-way from the source region to destination regions

The module provides replication-related outputs:
- `replication_status` - Overall replication configuration status
- `replication_regions` - List of destination regions
- `replication_configuration_arn` - ARN of the replication configuration

For more detailed examples, see the [replication example](examples/replication/) and [multi-region example](examples/multi-region/).

### Complete example
In this example the register is defined in detailed.

Expand Down
66 changes: 66 additions & 0 deletions docs/variable-examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -325,11 +325,77 @@ module "ecr" {
enable_logging = true
log_retention_days = 90

# Cross-region replication
enable_replication = true
replication_regions = ["us-west-2", "eu-west-1"]

# Tags
tags = {
Environment = "Production"
Department = "Engineering"
Project = "MyApp"
ManagedBy = "Terraform"
}
}
```

## Cross-Region Replication Settings

### `enable_replication` - Enable Cross-Region Replication

Enable automatic cross-region replication for disaster recovery and multi-region deployments.

```hcl
module "ecr" {
source = "lgallard/ecr/aws"
name = "production-app"

enable_replication = true # Enable automatic replication
}
```

### `replication_regions` - Target Regions for Replication

Specify the AWS regions where images should be automatically replicated.

```hcl
module "ecr" {
source = "lgallard/ecr/aws"
name = "production-app"

enable_replication = true
replication_regions = ["us-west-2", "eu-west-1", "ap-southeast-1"]
}
```

**Important Notes:**
- Replication is configured at the registry level (affects all repositories in the account)
- Use immutable tags for consistency across regions
- Additional costs apply for cross-region data transfer

### Complete Replication Example

```hcl
module "ecr_with_replication" {
source = "lgallard/ecr/aws"

name = "global-application"
image_tag_mutability = "IMMUTABLE" # Recommended for replication
scan_on_push = true

# Enable replication for disaster recovery
enable_replication = true
replication_regions = ["us-west-2", "eu-west-1", "ap-southeast-1"]

# Optional: Use KMS encryption for source repository
encryption_type = "KMS"

# Enable logging for monitoring
enable_logging = true

tags = {
Environment = "Production"
Application = "GlobalApp"
Purpose = "MultiRegion"
}
}
46 changes: 35 additions & 11 deletions examples/multi-region/README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,35 @@
# Multi-Region ECR Repository Example

This example demonstrates how to create an ECR repository that replicates images across multiple AWS regions for disaster recovery and global distribution use cases.
This example demonstrates two approaches for creating ECR repositories across multiple AWS regions for disaster recovery and global distribution use cases:

1. **Built-in Replication (Recommended)** - Uses the module's new replication features for automatic cross-region replication
2. **Manual Setup (Alternative)** - Manually creates repositories in each region with custom replication configuration

## Architecture

### Built-in Replication Approach (Recommended)
```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ β”‚ β”‚ Primary Region β”‚
β”‚ CI/CD System │────▢│ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ (Image Builds) β”‚ β”‚ β”‚ ECR Repositoryβ”‚ β”‚
β”‚ β”‚ β”‚ β”‚ + Replicationβ”‚ β”‚
β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β”‚ Automatic Replication
β”‚ (Managed by AWS)
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Secondary Region β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ ECR Repositoryβ”‚ β”‚
β”‚ β”‚ (Replica) β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

### Manual Setup Approach (Alternative)
```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ β”‚ β”‚ Primary Region β”‚
Expand All @@ -12,17 +38,15 @@ This example demonstrates how to create an ECR repository that replicates images
β”‚ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β”‚ Replication
β”‚ Manual Replication Config
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ β”‚
β–Ό β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Secondary Region A β”‚ β”‚ Secondary Region B β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ ECR Repositoryβ”‚ β”‚ β”‚ β”‚ ECR Repositoryβ”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Secondary Region β”‚
β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚
β”‚ β”‚ ECR Repositoryβ”‚ β”‚
β”‚ β”‚ (Manual) β”‚ β”‚
β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

## Use Cases
Expand Down
56 changes: 49 additions & 7 deletions examples/multi-region/main.tf
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
################################################################################
# Multi-Region ECR Repository Example
################################################################################
# This example demonstrates two approaches for multi-region ECR setups:
# 1. Built-in replication using the module's replication features
# 2. Manual multi-region setup with separate repositories

# Primary region provider
provider "aws" {
Expand All @@ -14,14 +17,43 @@ provider "aws" {
alias = "secondary"
}

# Approach 1: Using Built-in Replication (Recommended)
# This approach uses the module's built-in replication feature
module "ecr_with_replication" {
source = "../.."
providers = {
aws = aws.primary
}

name = "${var.repository_name}-replicated"
scan_on_push = true
image_tag_mutability = "IMMUTABLE"

# Enable automatic replication to secondary region
enable_replication = var.enable_replication
replication_regions = var.enable_replication ? [var.secondary_region] : []

# Optional: Enable logging for monitoring
enable_logging = var.enable_logging

tags = {
Environment = var.environment
Approach = "built-in-replication"
ManagedBy = "Terraform"
}
}

# Approach 2: Manual Multi-Region Setup (Alternative)
# This approach manually creates repositories in each region
# Create ECR repository in primary region
module "ecr_primary" {
count = var.use_manual_setup ? 1 : 0
source = "../.."
providers = {
aws = aws.primary
}

name = var.repository_name
name = "${var.repository_name}-manual"
scan_on_push = true
image_tag_mutability = "IMMUTABLE" # Use immutable tags for consistency across regions

Expand Down Expand Up @@ -66,17 +98,19 @@ module "ecr_primary" {
Environment = var.environment
Region = var.primary_region
Replication = "source"
Approach = "manual-setup"
}
}

# Create ECR repository in secondary region
# Create ECR repository in secondary region (manual approach)
module "ecr_secondary" {
count = var.use_manual_setup ? 1 : 0
source = "../.."
providers = {
aws = aws.secondary
}

name = var.repository_name
name = "${var.repository_name}-manual"
scan_on_push = true
image_tag_mutability = "IMMUTABLE" # Match primary region configuration

Expand Down Expand Up @@ -121,21 +155,29 @@ module "ecr_secondary" {
Environment = var.environment
Region = var.secondary_region
Replication = "replica"
Approach = "manual-setup"
}
}

# Create ECR Replication Configuration
resource "aws_ecr_replication_configuration" "replication" {
# Manual replication configuration (only for manual approach)
resource "aws_ecr_replication_configuration" "manual_replication" {
count = var.use_manual_setup ? 1 : 0
provider = aws.primary

replication_configuration {
rules {
destinations {
rule {
destination {
region = var.secondary_region
registry_id = data.aws_caller_identity.current.account_id
}
}
}

# Ensure replication is configured after repositories are created
depends_on = [
module.ecr_primary,
module.ecr_secondary
]
}

# Get current account ID
Expand Down
52 changes: 52 additions & 0 deletions examples/multi-region/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Built-in Replication Outputs (recommended approach)
output "replicated_repository_url" {
description = "URL of the ECR repository with built-in replication"
value = module.ecr_with_replication.repository_url
}

output "replicated_repository_arn" {
description = "ARN of the ECR repository with built-in replication"
value = module.ecr_with_replication.repository_arn
}

output "replication_status" {
description = "Replication configuration status"
value = module.ecr_with_replication.replication_status
}

output "replication_regions" {
description = "Regions where images are replicated"
value = module.ecr_with_replication.replication_regions
}

# Manual Setup Outputs (alternative approach)
output "primary_repository_url" {
description = "URL of the primary ECR repository (manual setup)"
value = var.use_manual_setup ? module.ecr_primary[0].repository_url : null
}

output "primary_repository_arn" {
description = "ARN of the primary ECR repository (manual setup)"
value = var.use_manual_setup ? module.ecr_primary[0].repository_arn : null
}

output "secondary_repository_url" {
description = "URL of the secondary ECR repository (manual setup)"
value = var.use_manual_setup ? module.ecr_secondary[0].repository_url : null
}

output "secondary_repository_arn" {
description = "ARN of the secondary ECR repository (manual setup)"
value = var.use_manual_setup ? module.ecr_secondary[0].repository_arn : null
}

# Comparison Output
output "approach_summary" {
description = "Summary of the multi-region approach being used"
value = {
built_in_replication = var.enable_replication
manual_setup = var.use_manual_setup
primary_region = var.primary_region
secondary_region = var.secondary_region
}
}
18 changes: 18 additions & 0 deletions examples/multi-region/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,22 @@ variable "environment" {
description = "Environment name"
type = string
default = "prod"
}

variable "enable_replication" {
description = "Whether to use built-in ECR replication (recommended)"
type = bool
default = true
}

variable "use_manual_setup" {
description = "Whether to demonstrate manual multi-region setup (alternative approach)"
type = bool
default = false
}

variable "enable_logging" {
description = "Whether to enable CloudWatch logging"
type = bool
default = false
}
Loading