AWS CodeDeploy
1 - Présentation
AWS CodeDeploy automatise les déploiements d'applications vers EC2, ECS, Lambda et les serveurs on-premises.
2 - Stratégies de déploiement
2.1 EC2/On-premises
| Stratégie | Description |
|---|---|
| AllAtOnce | Déploie sur toutes les instances simultanément |
| HalfAtATime | Déploie sur 50% des instances à la fois |
| OneAtATime | Déploie une instance à la fois |
| Custom | Pourcentage ou nombre personnalisé |
2.2 ECS
| Stratégie | Description |
|---|---|
| ECSAllAtOnce | Remplace tout le trafic immédiatement |
| ECSLinear10PercentEvery1Minutes | 10% du trafic toutes les minutes |
| ECSCanary10Percent5Minutes | 10% pendant 5 min, puis 100% |
2.3 Lambda
| Stratégie | Description |
|---|---|
| LambdaAllAtOnce | Tout le trafic immédiatement |
| LambdaLinear10PercentEvery1Minute | Linéaire 10%/min |
| LambdaCanary10Percent5Minutes | Canary 10% pendant 5 min |
3 - Configuration EC2
3.1 Installation de l'agent CodeDeploy
# Amazon Linux 2
sudo yum update -y
sudo yum install -y ruby wget
cd /home/ec2-user
wget https://aws-codedeploy-eu-west-1.s3.eu-west-1.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto
sudo service codedeploy-agent start
sudo service codedeploy-agent status
# Ubuntu
sudo apt update
sudo apt install -y ruby-full wget
cd /home/ubuntu
wget https://aws-codedeploy-eu-west-1.s3.eu-west-1.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto
sudo systemctl start codedeploy-agent
sudo systemctl enable codedeploy-agent
3.2 IAM Role pour EC2
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:Get*",
"s3:List*"
],
"Resource": [
"arn:aws:s3:::mon-bucket-deploy/*",
"arn:aws:s3:::aws-codedeploy-eu-west-1/*"
]
}
]
}
3.3 appspec.yml pour EC2
# appspec.yml
version: 0.0
os: linux
files:
- source: /
destination: /var/www/html
overwrite: yes
permissions:
- object: /var/www/html
pattern: "**"
owner: www-data
group: www-data
mode: 755
type:
- file
- directory
hooks:
BeforeInstall:
- location: scripts/before_install.sh
timeout: 300
runas: root
AfterInstall:
- location: scripts/after_install.sh
timeout: 300
runas: root
ApplicationStart:
- location: scripts/start_server.sh
timeout: 300
runas: root
ValidateService:
- location: scripts/validate_service.sh
timeout: 300
runas: root
3.4 Scripts de déploiement
# scripts/before_install.sh
#!/bin/bash
set -e
# Arrêter le service
systemctl stop nginx || true
# Nettoyer l'ancien déploiement
rm -rf /var/www/html/*
echo "BeforeInstall completed"
# scripts/after_install.sh
#!/bin/bash
set -e
# Installer les dépendances
cd /var/www/html
npm install --production
# Configurer les permissions
chown -R www-data:www-data /var/www/html
echo "AfterInstall completed"
# scripts/start_server.sh
#!/bin/bash
set -e
# Démarrer le service
systemctl start nginx
echo "ApplicationStart completed"
# scripts/validate_service.sh
#!/bin/bash
set -e
# Vérifier que le service répond
for i in {1..30}; do
if curl -s http://localhost/ > /dev/null; then
echo "Service is healthy"
exit 0
fi
sleep 2
done
echo "Service validation failed"
exit 1
4 - Configuration ECS
4.1 appspec.yml pour ECS
# appspec.yml
version: 0.0
Resources:
- TargetService:
Type: AWS::ECS::Service
Properties:
TaskDefinition: "arn:aws:ecs:eu-west-1:123456789:task-definition/mon-app:10"
LoadBalancerInfo:
ContainerName: "app"
ContainerPort: 8080
PlatformVersion: "LATEST"
NetworkConfiguration:
AwsvpcConfiguration:
Subnets:
- subnet-abc123
- subnet-def456
SecurityGroups:
- sg-12345678
AssignPublicIp: DISABLED
Hooks:
- BeforeInstall: "arn:aws:lambda:eu-west-1:123456789:function:BeforeInstallHook"
- AfterInstall: "arn:aws:lambda:eu-west-1:123456789:function:AfterInstallHook"
- AfterAllowTestTraffic: "arn:aws:lambda:eu-west-1:123456789:function:TestTrafficHook"
- BeforeAllowTraffic: "arn:aws:lambda:eu-west-1:123456789:function:BeforeTrafficHook"
- AfterAllowTraffic: "arn:aws:lambda:eu-west-1:123456789:function:AfterTrafficHook"
4.2 Blue/Green ECS avec ALB
# CloudFormation
ECSDeploymentGroup:
Type: AWS::CodeDeploy::DeploymentGroup
Properties:
ApplicationName: !Ref CodeDeployApplication
DeploymentGroupName: ecs-deployment-group
ServiceRoleArn: !GetAtt CodeDeployRole.Arn
DeploymentConfigName: CodeDeployDefault.ECSLinear10PercentEvery1Minutes
DeploymentStyle:
DeploymentOption: WITH_TRAFFIC_CONTROL
DeploymentType: BLUE_GREEN
BlueGreenDeploymentConfiguration:
DeploymentReadyOption:
ActionOnTimeout: CONTINUE_DEPLOYMENT
WaitTimeInMinutes: 0
TerminateBlueInstancesOnDeploymentSuccess:
Action: TERMINATE
TerminationWaitTimeInMinutes: 5
ECSServices:
- ClusterName: !Ref ECSCluster
ServiceName: !GetAtt ECSService.Name
LoadBalancerInfo:
TargetGroupPairInfoList:
- TargetGroups:
- Name: !GetAtt BlueTargetGroup.TargetGroupName
- Name: !GetAtt GreenTargetGroup.TargetGroupName
ProdTrafficRoute:
ListenerArns:
- !Ref ALBListener
TestTrafficRoute:
ListenerArns:
- !Ref TestListener
5 - Configuration Lambda
5.1 appspec.yml pour Lambda
# appspec.yml
version: 0.0
Resources:
- MyLambdaFunction:
Type: AWS::Lambda::Function
Properties:
Name: ma-fonction
Alias: live
CurrentVersion: 1
TargetVersion: 2
Hooks:
- BeforeAllowTraffic: arn:aws:lambda:eu-west-1:123456789:function:PreTrafficHook
- AfterAllowTraffic: arn:aws:lambda:eu-west-1:123456789:function:PostTrafficHook
5.2 Hook de validation
# pre_traffic_hook.py
import boto3
codedeploy = boto3.client('codedeploy')
lambda_client = boto3.client('lambda')
def handler(event, context):
deployment_id = event['DeploymentId']
lifecycle_event_hook_execution_id = event['LifecycleEventHookExecutionId']
try:
# Tester la nouvelle version
response = lambda_client.invoke(
FunctionName='ma-fonction',
Qualifier='2', # Nouvelle version
InvocationType='RequestResponse',
Payload='{"test": true}'
)
if response['StatusCode'] == 200:
status = 'Succeeded'
else:
status = 'Failed'
except Exception as e:
print(f"Error: {e}")
status = 'Failed'
# Reporter le résultat
codedeploy.put_lifecycle_event_hook_execution_status(
deploymentId=deployment_id,
lifecycleEventHookExecutionId=lifecycle_event_hook_execution_id,
status=status
)
return status
6 - Rollback automatique
6.1 Configuration
# CloudFormation
DeploymentGroup:
Type: AWS::CodeDeploy::DeploymentGroup
Properties:
AutoRollbackConfiguration:
Enabled: true
Events:
- DEPLOYMENT_FAILURE
- DEPLOYMENT_STOP_ON_ALARM
- DEPLOYMENT_STOP_ON_REQUEST
AlarmConfiguration:
Enabled: true
IgnorePollAlarmFailure: false
Alarms:
- Name: !Ref HighErrorRateAlarm
- Name: !Ref HighLatencyAlarm
6.2 CloudWatch Alarms
HighErrorRateAlarm:
Type: AWS::CloudWatch::Alarm
Properties:
AlarmName: HighErrorRate
MetricName: 5XXError
Namespace: AWS/ApplicationELB
Statistic: Sum
Period: 60
EvaluationPeriods: 2
Threshold: 10
ComparisonOperator: GreaterThanThreshold
Dimensions:
- Name: LoadBalancer
Value: !Ref ALB
7 - CLI et commandes
# Créer une application
aws deploy create-application \
--application-name mon-app \
--compute-platform Server
# Créer un deployment group
aws deploy create-deployment-group \
--application-name mon-app \
--deployment-group-name production \
--deployment-config-name CodeDeployDefault.OneAtATime \
--ec2-tag-filters Key=Environment,Value=Production,Type=KEY_AND_VALUE \
--service-role-arn arn:aws:iam::123456789:role/CodeDeployRole
# Déclencher un déploiement
aws deploy create-deployment \
--application-name mon-app \
--deployment-group-name production \
--s3-location bucket=mon-bucket,bundleType=zip,key=releases/v1.0.0.zip
# Suivre le déploiement
aws deploy get-deployment --deployment-id d-ABC123
# Stopper un déploiement
aws deploy stop-deployment --deployment-id d-ABC123
# Rollback
aws deploy create-deployment \
--application-name mon-app \
--deployment-group-name production \
--revision revisionType=S3,s3Location={bucket=mon-bucket,bundleType=zip,key=releases/v0.9.0.zip}
Résumé
Dans ce chapitre, nous avons appris :
- Les stratégies de déploiement (AllAtOnce, HalfAtATime, Blue/Green)
- La configuration pour EC2 avec appspec.yml et scripts
- Les déploiements ECS Blue/Green
- Les déploiements Lambda avec aliases
- Le rollback automatique avec CloudWatch Alarms
Prochaine étape
Dans le prochain chapitre, nous verrons AWS CodePipeline pour orchestrer le CI/CD complet.
→ Chapitre suivant : AWS CodePipeline