3.3 In-Place, Rolling & Immutable Deployments on EC2
Key Takeaways
- In-place deployments update code directly on existing EC2 instances with minimal resource cost, whereas rolling updates maintain capacity across batches, and immutable deployments replace instances entirely to prevent configuration drift.
- The AWS CodeDeploy agent relies on outbound polling over HTTPS port 443, eliminating the need for open inbound firewall ports, and executes lifecycle hooks sequentially according to the appspec.yml specification.
- In-place CodeDeploy deployments execute an exact sequence of lifecycle hooks: ApplicationStop, DownloadBundle, BeforeInstall, Install, AfterInstall, ApplicationStart, and ValidateService.
- Deployment configurations (such as CodeDeployDefault.OneAtATime, HalfAtATime, or custom minimumHealthyHosts) govern fleet availability thresholds and trigger automatic rollbacks on CloudWatch alarms or failed hooks.
- AWS Elastic Beanstalk provides five distinct deployment policies (All at once, Rolling, Rolling with additional batch, Immutable, and Traffic splitting), each presenting specific trade-offs regarding deployment duration, cost, and availability.
EC2 Deployment Paradigms
When deploying application code to Amazon EC2 fleets, DevOps engineers must select an appropriate deployment pattern based on availability requirements, rollback speed, cost tolerances, and sensitivity to configuration drift.
1. In-Place Deployment (Mutable)
In an In-Place Deployment, the deployment agent stops the application on existing running instances, installs the new revision bundle, updates configuration files, and restarts the service.
- Advantages: Fastest deployment cycle; zero additional infrastructure cost; preserves instance metadata, Elastic IP attachments, and local caches.
- Disadvantages: Fleet capacity is reduced while instances undergo updates (unless overprovisioned); instances can suffer from configuration drift over time; rollbacks require redeploying the previous revision bundle, which takes just as long as the original deployment.
2. Rolling Deployment
A Rolling Deployment updates an Auto Scaling group or fleet in discrete, sequential batches (e.g., 20% or 1 instance at a time). As each batch successfully completes health checks, the orchestrator moves to the next batch.
- Advantages: Avoids complete service downtime; limits blast radius of defects to the active batch size.
- Disadvantages: Deployment duration scales linearly with fleet size; fleet capacity temporarily drops during the update unless an additional batch is launched ahead of time; transient mixed-version states exist where both version A and version B handle live user traffic simultaneously.
3. Immutable Deployment
An Immutable Deployment never modifies running instances. Instead, an entirely new set of EC2 instances is launched (either via an updated AMI or clean user-data bootstrapping). The new instances are placed behind the load balancer, validated with health checks, and old instances are terminated once the new fleet is healthy.
- Advantages: Absolute immunity against configuration drift; pristine runtime state; near-instant rollback (simply terminate the newly launched instances while leaving the old fleet untouched).
- Disadvantages: Requires temporary duplicate infrastructure capacity (doubling compute costs during rollout); longer launch times due to instance provisioning.
AWS CodeDeploy Architecture & Agent Operations
AWS CodeDeploy automates application deployments across Amazon EC2 instances, on-premises servers, Amazon ECS, and AWS Lambda.
The CodeDeploy Agent
The CodeDeploy Agent is an open-source software package (built in Ruby) that runs on each target EC2 instance:
- Network Communication: The agent uses an outbound-only polling model over HTTPS (port 443) to communicate with the CodeDeploy control plane. It does not require any inbound ports to be open in security groups or network ACLs.
- IAM Instance Profile: The EC2 instance profile must grant permissions to interact with CodeDeploy and retrieve deployment artifacts from Amazon S3 (
s3:GetObject) or GitHub. - Auto Scaling Group Integration: When integrated with an Auto Scaling group, CodeDeploy automatically suspends specific ASG scaling processes (
ReplaceUnhealthy,AZRebalance,AlarmNotification,ScheduledActions) during deployment execution to prevent race conditions.
The appspec.yml Anatomy & Lifecycle Event Hooks
The appspec.yml file is placed in the root directory of the application revision bundle. For EC2/On-Premises deployments, it defines files to copy, permissions to set, and custom scripts to execute during specific Lifecycle Event Hooks.
Exact Lifecycle Hook Execution Sequence (In-Place)
During an in-place deployment to an EC2 instance, CodeDeploy executes hooks in an exact, deterministic order:
+-------------------------------------------------------------+
| CodeDeploy EC2 In-Place Lifecycle Hook Sequence |
| |
| 1. ApplicationStop <-- Gracefully stop existing app |
| 2. DownloadBundle <-- Reserved (Agent downloads zip) |
| 3. BeforeInstall <-- Pre-install tasks, decrypting |
| 4. Install <-- Reserved (Agent extracts files)|
| 5. AfterInstall <-- Post-install config & symlinks |
| 6. ApplicationStart <-- Start daemon / application |
| 7. ValidateService <-- Health checks & endpoint probe |
+-------------------------------------------------------------+
- ApplicationStop: Executes scripts to gracefully drain connections and stop the running application version. On an instance's very first deployment, this hook is skipped.
- DownloadBundle (Agent Reserved): The CodeDeploy agent downloads the revision bundle from the S3 bucket to a temporary directory on the host. Custom scripts cannot be mapped here.
- BeforeInstall: Custom pre-installation scripts execute (e.g., pre-allocating directories, backing up databases, decrypting secrets from AWS Secrets Manager).
- Install (Agent Reserved): The agent copies files from the extracted bundle to the target file system locations specified in the
filessection. - AfterInstall: Custom scripts execute to configure file permissions, establish symlinks, compile assets, or install dependencies.
- ApplicationStart: Starts the application services or background daemons.
- ValidateService: The most critical verification hook. Executes scripts (such as curl health probes against
http://localhost:8080/health) to confirm the service is healthy and ready to accept traffic. If this script exits with a non-zero exit code or times out, the deployment fails.
Production appspec.yml Snippet
version: 0.0
os: linux
files:
- source: /build/target/app.jar
destination: /opt/production/app/
- source: /config/application.yml
destination: /etc/app/
hooks:
ApplicationStop:
- location: scripts/stop_service.sh
timeout: 120
runas: root
BeforeInstall:
- location: scripts/backup_and_clean.sh
timeout: 60
runas: root
AfterInstall:
- location: scripts/configure_environment.sh
timeout: 180
runas: appuser
ApplicationStart:
- location: scripts/start_service.sh
timeout: 60
runas: appuser
ValidateService:
- location: scripts/validate_health.sh
timeout: 90
runas: appuser
Deployment Configurations & Minimum Healthy Hosts
CodeDeploy uses Deployment Configurations to govern the speed of rollout and enforce fleet health guardrails.
Predefined Deployment Configurations
CodeDeployDefault.AllAtOnce: Deploys to all instances simultaneously. Fastest rollout; maximum capacity degradation during deployment.CodeDeployDefault.HalfAtATime: Deploys to a maximum of 50% of instances at a time. Retains at least half capacity.CodeDeployDefault.OneAtATime: Deploys to one instance at a time. Lowest risk; slowest execution.
Custom Deployment Configurations: Minimum Healthy Hosts
You can create custom configurations using minimumHealthyHosts defined as either FLEET_PERCENT or HOST_COUNT:
- FLEET_PERCENT: Specifies that at least X percent of instances in the deployment group must remain in a healthy, running state throughout the deployment. For example, in a 10-instance fleet with
minimumHealthyHosts: 80%, CodeDeploy deploys to at most 2 instances (20%) concurrently. - HOST_COUNT: Specifies the exact absolute number of healthy instances required. In a 5-instance fleet with
minimumHealthyHosts: 4, CodeDeploy deploys to exactly 1 instance at a time.
AWS Elastic Beanstalk Deployment Policies
AWS Elastic Beanstalk abstracts EC2 deployment orchestration through five distinct deployment policies:
+---------------------------------------------------------------------------------------------------------+
| Elastic Beanstalk Deployment Policies |
| |
| Policy | Downtime | Capacity Impact | Cost Overhead | Rollback Speed | Drift Protection|
| -----------------------+----------+-----------------+---------------+----------------+-----------------|
| All at Once | Yes | 100% loss | None (0%) | Slow | Poor |
| Rolling | No | Reduced by batch| None (0%) | Slow | Poor |
| Rolling + Addl Batch | No | None (100% kept)| 1 Batch temp | Slow | Moderate |
| Immutable | No | None (100% kept)| 100% temp | Instant | Absolute |
| Traffic Splitting | No | None (100% kept)| 100% temp | Instant | Absolute |
+---------------------------------------------------------------------------------------------------------+
- All at once: Deploys the new version to all instances simultaneously. Causes complete environment downtime. Suitable only for non-critical development environments.
- Rolling: Deploys in batches. While a batch is updating, total fleet capacity drops by the batch size. Zero additional infrastructure cost, but capacity is compromised during deployment.
- Rolling with additional batch: Launches an extra batch of new EC2 instances first to maintain 100% operational capacity throughout the deployment. Once the extra batch is healthy, it updates existing instances in batches, terminating the extra instances at the end.
- Immutable: Creates an entirely new, temporary Auto Scaling group within the same environment. Launches a single instance to verify health; once validated, it launches the remaining capacity in the temporary ASG, shifts all traffic, merges instances into the main ASG, and terminates old instances.
- Traffic splitting: Launches an immutable temporary ASG and splits a configurable percentage of live production traffic (e.g., 10% for 15 minutes) via Application Load Balancer routing rules. If CloudWatch health alarms breach, traffic immediately reverts to the old fleet.
Automated Rollbacks & Hook Failure Handling
CodeDeploy incorporates automated rollback safety triggers configured in the Deployment Group settings:
- Rollback on Deployment Failure: Automatically triggers a rollback if any instance fails a lifecycle hook (such as
ValidateService) or exceeds timeout limits. - Rollback on CloudWatch Alarms: Monitors CloudWatch alarms (e.g., ALB HTTP 5xx error rate or high latency). If an alarm transitions to
ALARMstate while a deployment is in progress, CodeDeploy halts progression and immediately redeploys the last known good revision. - The ApplicationStop Caveat: If an application is corrupted or misconfigured, the
ApplicationStopscript on the instance may fail during a new deployment. By default, a failed hook halts deployment. However, you can pass the--ignore-application-stop-failuresflag via the CLI or enable it in deployment settings to bypassApplicationStopfailures and proceed with deployment.
A production application running on Amazon EC2 instances managed by AWS CodeDeploy fails during a deployment. Inspection of the deployment logs shows that the revision bundle was successfully extracted to /var/www/html, but the deployment failed before the load balancer resumed sending traffic to the instance. The team needs to insert an automated synthetic smoke test script that verifies local HTTP endpoint availability before the instance is registered back into the target group. Which lifecycle hook in the appspec.yml must execute this verification script?
An enterprise e-commerce platform hosted on AWS Elastic Beanstalk must deploy a critical application update. The architecture requires that 100% of existing operational capacity must remain available to customer traffic throughout the rollout to avoid latency spikes, while avoiding long-term infrastructure cost increases. The deployment must automatically roll back with zero customer impact if any health check fails. Which Elastic Beanstalk deployment policy best satisfies these requirements?
A DevOps engineer is provisioning fifty new Amazon EC2 instances across private subnets for an in-place deployment managed by AWS CodeDeploy. After triggering the deployment, the CodeDeploy console reports that the deployment timed out with status 'Created' or 'Pending', and no lifecycle event hooks executed on the instances. What are the two most likely infrastructure misconfigurations causing this issue?