пятница, 31 марта 2017 г.

AWS. Jenkins. ElasticBeansTalk. Docker. Green/Blue deployment

При создании варианта без простойного обновления приложений на базе BeansTalk можно применить Green/Blue схему. Что это такое можно читать на Amazon.
Конечно, как вариант, можно поставить плагин Deploy to EB, в нем крыжик Zero Time. Там будет магия по типу - создаем клон нашего окружения, деплоим в него новую версию, делаем SWAP URL, убиваем предыдущее окружение.
Если нужно использовать Docker, то этот плагин этого не умеет. Сделать можно скриптами.
Шаги сборки в Jenkins по типу Shell.
Шаг 1:
#!/bin/bash
cd ${WORKSPACE}
docker rmi -f $(docker images -a -q) 2>/dev/null
echo "Docker clean up completed."

Шаг 2
#!/bin/bash
set -e

# For AWS CLI propertly work
export LD_LIBRARY_PATH=""
REG_ADDRESS="XXXXXXXXXXX.YYY.ecr.us-east-1.amazonaws.com"
REPO="webapp"
IMAGE_VERSION=${GIT_COMMIT}
IMAGE_TAG=${IMAGE_VERSION}_b${BUILD_NUMBER}
EBFILENAME=${REPO}-${IMAGE_TAG}.zip
REGION="us-east-1"
APPBUCKET="jenkins-deploy"
BUCKETDIR="webapp-deploy"

echo "copy config file"
aws s3 cp s3://${APPBUCKET}/${BUCKETDIR}/Dockerfile ${WORKSPACE}
aws s3 cp s3://${APPBUCKET}/${BUCKETDIR}/Dockerrun.aws.json ${WORKSPACE}

cd ${WORKSPACE}
docker build -t ${REPO}:${IMAGE_VERSION} .

echo "Login to ECR Repository"
LOGIN_STRING=`aws ecr get-login --region us-east-1`
${LOGIN_STRING}

echo "Tag the build"
docker tag ${REPO}:${IMAGE_VERSION} ${REG_ADDRESS}/${REPO}:${IMAGE_TAG}
docker tag ${REPO}:${IMAGE_VERSION} ${REG_ADDRESS}/${REPO}:latest

echo "Push builds"
docker push ${REG_ADDRESS}/${REPO}:${IMAGE_TAG}
aws ecr batch-delete-image --repository-name "${REPO}" --image-ids imageTag="latest" --region ${REGION}
docker push ${REG_ADDRESS}/${REPO}:latest

echo "Prepare ElasticBeanstalk Template"
sed -i "s/${REPO}:latest/${REPO}:${IMAGE_TAG}/g" ./Dockerrun.aws.json
zip $EBFILENAME ./Dockerrun.aws.json ./Dockerfile

echo "Upload package to S3"
aws s3 cp ${WORKSPACE}/$EBFILENAME s3://${APPBUCKET}/${BUCKETDIR}/$EBFILENAME


Шаг 3
#!/bin/bash
set -e
export LD_LIBRARY_PATH=""

REPO="webapp"
IMAGE_VERSION=${GIT_COMMIT}
IMAGE_TAG=${IMAGE_VERSION}_b${BUILD_NUMBER}
EBFILENAME=${REPO}-${IMAGE_TAG}.zip
REGION="us-east-1"
APPBUCKET="jenkins-deploy"
BUCKETDIR="webapp-deploy"

APPVERSION="$BUILD_NUMBER"

EB_APP=WebApp-Application-XXXXXXX
EB_CNAME=WebApp-XXXXX.YYYYYY.us-east-1.elasticbeanstalk.com

echo "Start creating application version"
aws elasticbeanstalk create-application-version \
--application-name $EB_APP \
--version-label $APPVERSION  \
    --source-bundle S3Bucket=$APPBUCKET,S3Key=${BUCKETDIR}/$EBFILENAME \
    --region $REGION || ( echo "ERROR: application creation failed"; exit 1 )


echo "Wait until version is processed"
time_passed=0
while [ ! "$(aws --region $REGION elasticbeanstalk describe-application-versions --application-name ${EB_APP} --version-labels ${APP_VERSION} | grep UNPROCESSED)" ]; 
 do
echo -n "Application version still not ready. ";
if [ $time_passed -gt 300 ]; then
echo "Timeout reached, exiting..."
exit 1
else
echo "Waiting..."
sleep 15
((time_passed=time_passed+15))
fi
 done
echo "Application version update completed."

echo "Determine who is GREEN"
GREEN_ENV_ID=`aws --region ${REGION} elasticbeanstalk describe-environments \
--application-name ${EB_APP} --output text \
--query "Environments[?CNAME=='${EB_CNAME}'][EnvironmentId]"`

echo "GREEN ENV is "${GREEN_ENV_ID}

echo "Determine who is BLUE"
BLUE_ENV_ID=`aws --region ${REGION} elasticbeanstalk describe-environments \
--application-name ${EB_APP} --output text \
--query "Environments[?CNAME!='${EB_CNAME}'][EnvironmentId]"`

echo "BLUE ENV is "${BLUE_ENV_ID}

echo "Start updating a new BLUE environment"
aws elasticbeanstalk update-environment \
--environment-id $BLUE_ENV_ID \
    --version-label $APPVERSION \
    --region $REGION || ( echo "ERROR: environment update failed"; exit 1 )


echo "Wait until environment is ready"
time_passed=0
while [ "$(aws --region ${REGION} elasticbeanstalk describe-environments --environment-ids ${BLUE_ENV_ID} --output text --query 'Environments[0].Status')" != "Ready" ];
 do
echo -n "Application still not ready. ";
if [ $time_passed -gt 300 ]; then
echo "Timeout reached, exiting..."
>&2 echo "ERROR: Application update timed out"
exit 1
else
echo "Waiting..."
sleep 15
((time_passed=time_passed+15))
fi
 done
echo "Environment update completed."

echo "Check application version"
if [ "$(aws --region ${REGION} elasticbeanstalk describe-environments --environment-ids ${BLUE_ENV_ID} --output text --query 'Environments[0].VersionLabel')" -ne ${BUILD_NUMBER} ]; then
>&2 echo "ERROR: Application version update failed";
exit 1;
else
echo "Application version updated"
fi

echo "Check BLUE environment has Green health status"
[ `aws --region ${REGION} elasticbeanstalk describe-environments \
--environment-ids ${BLUE_ENV_ID} \
--output text --query 'Environments[0].Health'` = "Green" ] \
&& echo "App status is Green. Swapping CNAMEs..." \
|| ( echo "ERROR: App status is not Green"; exit 1)

echo "Starting SWAP URL"
aws elasticbeanstalk swap-environment-cnames \
--source-environment-id ${GREEN_ENV_ID} \
    --destination-environment-id ${BLUE_ENV_ID} \
    --region ${REGION}


echo "Clean Build Dir"
rm $EBFILENAME




Ну и здесь еще можно вызвать плагин AWS SNS notify

Комментариев нет: