S3 Storage
Overview
S3 provides centralized storage for rootfs images and the Linux kernel, enabling:
- Fast deployment: New instances download pre-built images instead of building from scratch
- Consistency: All instances use identical rootfs images
- Version control: Store multiple versions of rootfs images
- Cost efficiency: Store once, download many times
Bucket Configuration
Default Settings
| Setting | Value |
|---|---|
| Bucket Name | llm-infra-operator-rootfs |
| Region | us-east-1 |
| Storage Class | Standard |
| Versioning | Disabled (enable for production) |
| Encryption | SSE-S3 (default) |
Creating the Bucket
The bucket was created with:
aws s3api create-bucket \
--bucket llm-infra-operator-rootfs \
--region us-east-1
For regions other than us-east-1, you need --create-bucket-configuration LocationConstraint=REGION
Bucket Contents
s3://llm-infra-operator-rootfs/
├── vmlinux # Linux kernel (20.4 MiB)
├── rootfs-base.ext4 # Base image (512 MiB)
├── rootfs-bash.ext4 # Bash minimal (512 MiB)
├── rootfs-python.ext4 # Python 3.10 (600 MiB)
├── rootfs-nodejs.ext4 # Node.js 20 (700 MiB)
├── rootfs-go.ext4 # Go 1.22.3 (700 MiB)
└── rootfs-rust.ext4 # Rust stable (2.0 GiB)
List Contents
task s3:list
Output:
=== S3 bucket contents (llm-infra-operator-rootfs) ===
2025-11-29 04:31:21 512.0 MiB rootfs-base.ext4
2025-11-29 04:31:23 2.0 GiB rootfs-bash.ext4
2025-11-29 04:31:30 700.0 MiB rootfs-go.ext4
2025-11-29 04:31:33 700.0 MiB rootfs-nodejs.ext4
2025-11-29 04:31:36 600.0 MiB rootfs-python.ext4
2025-11-29 04:31:42 2.0 GiB rootfs-rust.ext4
2025-11-29 04:31:49 20.4 MiB vmlinux
Total Objects: 7
Total Size: 6.5 GiB
Workflow Integration
Instance Launch Flow
When a new EC2 instance launches via task aws:launch, the user-data script automatically downloads from S3:
Rootfs Creation Flow
When creating new rootfs images with task aws:create-rootfs-*:
User-Data S3 Integration
The EC2 user-data script (aws/user-data.sh) handles S3 downloads:
S3_BUCKET="llm-infra-operator-rootfs"
S3_REGION="us-east-1"
echo "Downloading vmlinux kernel..."
if aws s3 cp s3://${S3_BUCKET}/vmlinux ${WORKDIR}/vmlinux --region ${S3_REGION}; then
echo "vmlinux downloaded successfully"
else
echo "WARNING: vmlinux not found in S3, downloading from Firecracker releases..."
curl -L -o vmlinux "https://s3.amazonaws.com/spec.ccfc.min/..."
fi
echo "Downloading rootfs images..."
aws s3 sync s3://${S3_BUCKET}/ ${WORKDIR}/images/ \
--exclude "*" --include "rootfs-*.ext4" \
--region ${S3_REGION}
if [ -f ${WORKDIR}/images/rootfs-python.ext4 ]; then
ln -sf ${WORKDIR}/images/rootfs-python.ext4 ${WORKDIR}/rootfs.ext4
echo "Default rootfs symlinked to rootfs-python.ext4"
fi
Key features:
- Downloads vmlinux with fallback to official Firecracker releases
- Uses
aws s3 syncfor efficient incremental downloads - Creates symlink to default rootfs
- Supports custom bucket and region configuration
Manual Operations
Upload All Images
task s3:upload 2>&1 | tee /tmp/log.txt
This uploads all rootfs-*.ext4 files and vmlinux from the EC2 instance to S3.
Download All Images
task s3:download 2>&1 | tee /tmp/log.txt
This downloads all images from S3 to the EC2 instance.
Upload Single Image
task s3:upload-single LANG=python
Direct AWS CLI Commands
aws s3 ls s3://llm-infra-operator-rootfs/ --human-readable
aws s3 cp /srv/firecracker/images/rootfs-python.ext4 s3://llm-infra-operator-rootfs/
aws s3 cp s3://llm-infra-operator-rootfs/rootfs-python.ext4 /srv/firecracker/images/
aws s3 sync /srv/firecracker/images/ s3://llm-infra-operator-rootfs/ --exclude "*" --include "rootfs-*.ext4"
IAM Permissions
Required Permissions
The EC2 instance role (or your AWS credentials) needs:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "S3RootfsAccess",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:PutObject",
"s3:ListBucket",
"s3:DeleteObject"
],
"Resource": [
"arn:aws:s3:::llm-infra-operator-rootfs",
"arn:aws:s3:::llm-infra-operator-rootfs/*"
]
}
]
}
Instance Profile (Production)
For production, attach an IAM role to the EC2 instance:
aws iam create-role \
--role-name FirecrackerEC2Role \
--assume-role-policy-document file://trust-policy.json
aws iam put-role-policy \
--role-name FirecrackerEC2Role \
--policy-name S3Access \
--policy-document file://s3-policy.json
aws iam create-instance-profile \
--instance-profile-name FirecrackerProfile
aws iam add-role-to-instance-profile \
--instance-profile-name FirecrackerProfile \
--role-name FirecrackerEC2Role
Cost Analysis
Storage Costs
| Image | Size | Monthly Cost |
|---|---|---|
| vmlinux | 20.4 MiB | $0.0005 |
| rootfs-base.ext4 | 512 MiB | $0.012 |
| rootfs-bash.ext4 | 512 MiB | $0.012 |
| rootfs-python.ext4 | 600 MiB | $0.014 |
| rootfs-nodejs.ext4 | 700 MiB | $0.016 |
| rootfs-go.ext4 | 700 MiB | $0.016 |
| rootfs-rust.ext4 | 2.0 GiB | $0.046 |
| Total | ~5.0 GiB | ~$0.12/month |
Transfer Costs
| Transfer Type | Cost |
|---|---|
| Upload (EC2 → S3, same region) | Free |
| Download (S3 → EC2, same region) | Free |
| Download (S3 → Internet) | $0.09/GB |
| Cross-region transfer | $0.02/GB |
Keep your S3 bucket and EC2 instances in the same region to avoid transfer costs.
Best Practices
Versioning
Enable versioning for production to maintain history:
aws s3api put-bucket-versioning \
--bucket llm-infra-operator-rootfs \
--versioning-configuration Status=Enabled
Lifecycle Rules
Set up lifecycle rules to manage old versions:
aws s3api put-bucket-lifecycle-configuration \
--bucket llm-infra-operator-rootfs \
--lifecycle-configuration file://lifecycle.json
Example lifecycle.json:
{
"Rules": [
{
"ID": "DeleteOldVersions",
"Status": "Enabled",
"Filter": {},
"NoncurrentVersionExpiration": {
"NoncurrentDays": 30
}
}
]
}
Cross-Region Replication
For multi-region deployments:
# Enable replication to eu-west-1
aws s3api put-bucket-replication \
--bucket llm-infra-operator-rootfs \
--replication-configuration file://replication.json
Troubleshooting
Access Denied
fatal error: An error occurred (AccessDenied) when calling the GetObject operation
Solutions:
- Check IAM permissions include
s3:GetObject - Verify bucket policy allows access
- Check if bucket is in correct region
Slow Downloads
If downloads are slow:
- Verify EC2 and S3 are in same region
- Use larger instance type for better network
- Consider S3 Transfer Acceleration
Missing Images
If images aren't found in S3:
aws s3 ls s3://llm-infra-operator-rootfs/
task s3:upload
Multi-Tenant Configuration
For multiple environments (dev, staging, prod):
aws s3 mb s3://llm-infra-operator-rootfs-dev
aws s3 mb s3://llm-infra-operator-rootfs-staging
aws s3 mb s3://llm-infra-operator-rootfs-prod
S3_BUCKET=llm-infra-operator-rootfs-dev task s3:list
Or use prefixes:
s3://llm-infra-operator-rootfs/
├── dev/
│ ├── rootfs-python.ext4
│ └── ...
├── staging/
│ └── ...
└── prod/
└── ...