[AWS] CodeDeploy: Lambda ๋กค๋ง ๋ฐฐํฌ
๋๋ค๋ ์ฌ๋ฌ๋ชจ๋ก ์ ๋ง ํธ๋ฆฌํ ์๋น์ค ์ค ํ๋๋ค.
์ ๋ฐ์ ์ธ ๊ด๋ฆฌ๋น์ฉ์ด ๊ฑฐ์ ์๋ค๋ ๊ฒ๋ ๊ทธ๋ ์ง๋ง, ๋ฐฐํฌ๋ ์ ๋ง ํธํ๊ธด ํ๋ค.
๊ทธ๋ฅ ์๋์ฒ๋ผ ์์ค๋ง ์์ถํด์ ์ฌ๋ฆฌ๋ฉด ๋์ด๋ ๋ง์ด๋ค.
๊ฒ๋ค๊ฐ ์ด์ ๋ฐ๋ฅธ ์ ๋ฒ์ ์ ํ๋ ์๋นํ ๋น ๋ฅด๊ณ , ์์ค๊ฐ ๋ฐ๋๋ค๊ณ ์๋น์ค๊ฐ ์ค๊ฐ์ ๋๊ธฐ์ง๋ ์๋๋ค.
ํ์ง๋ง ์ด๋ ๊ฒ ๊ทธ๋ฅ ๋ฌด์์ ์ฌ๋ฆฌ๊ณ ๋ง๋ ๊ฒ์ ์ข.. ์์ฌ์ด ์ ์ด ์๋ค.
๋ง์ ํ๋๋ผ๋ ์๋ก ์ฌ๋ฆฌ๋ ์์ค์ ๋ฌธ์ ๊ฐ ์๋ค๋ฉด ์ด๋ป๊ฒ ํ๋? ๋ฐฐํฌ์์ ์ ๋์ํ๋์ง ํ๋ฒ๋ ์ต์ข
์ ๊ฒ์ ํด์ผ ํ์ง ์๋?
๊ทธ๋์ ํ์ํ ๊ฒ์ด [๋กค๋ง ๋ฐฐํฌ]๋ผ๋ ๊ฒ์ด๋ค.
๋กค๋ง ๋ฐฐํฌ๋ ์ ๋ฒ์ ์ ์ฌ๋ฆฌ๋๋ผ๋ ์ ๋ฒ์ ์ด ์ ๋์ํ ๋๊น์ง ๊ธฐ๋ค๋ฆฌ๊ณ , ์ ๋์ํ๋๊ฒ ํ์ธ๋๋ฉด ๋ฒ์ ์ ๊ต์ฒดํ๋, ๋์ํ์ง ์๋๋ค๋ฉด ๋ฐฐํฌ๋ฅผ ์ทจ์ํ๋ ๊ธฐ๋ฒ์ด๋ค.
Code Deploy๋ฅผ ํตํด ์ด๋ฅผ ์ ์ฉํด๋ณด๋๋ก ํ๊ฒ ๋ค.
๋๋ค ๋ฒ์ ์์ฑ
๋๋ค๋ ๋ณ๋ค๋ฅธ ์ค์ ์ ํ์ง ์๋๋ค๋ฉด LATEST ํ๋์ ๋ฒ์ ๋ง ์กด์ฌํ๋, ๋กค๋ง ๋ฐฐํฌ๋ฅผ ์ฒ๋ฆฌํ๋ ค๋ฉด ๋ฒ์ ์ ์ ๋๋ก ๋ช ์ํ ํ์๊ฐ ์๋ค.
๋ฒ์ ์ด ์๋ ์ํ๋ผ๋ฉด ๋ฒ์ ํญ์ ๋ค์ด๊ฐ์ ๋ฒ์ ์ 2๊ฐ ๋ง๋ค์ด์ฃผ์.

์ฐ๋ฆฌ๋ ์ฌ๊ธฐ์ ๋ฒ์ 1์ด ๊ธฐ์กด์ ์์ค. ๋ฒ์ 2๊ฐ ์๋ก ๋ฐฐํฌํ ๋ฒ์ ์ ์์ค๋ผ๊ณ ๊ฐ์ ํ๊ฒ ๋ค.
๋๋ค ๋ณ์นญ ์์ฑ
๋กค๋ง ๋ฐฐํฌ๋ฅผ ์ ๋๋ก ์ ์ฉํ๋ ค๋ฉด ๋๋ค์ ๋ณ์นญ์ ์ถ๊ฐํด์ผ ํ๋ค.
์๋ก์ด ๋ฒ์ ์ ๋๋ค๊ฐ ๊ณ์ ์ฌ๋ผ์ค๋๋ผ๋ ์ต์ข
์๋ํฌ์ธํธ๋ ํ๋์ฌ์ผ ํ์ง ์๊ฒ ๋๊ฐ? ๊ทธ๊ฑธ ์ก์์ฃผ๋ ๊ฒ์ด ๋ณ์นญ์ด๋ค.
์ ๊ธฐ ๋ณ์นญ ํญ์ ๋ณด๋ฉด ๋ณ์นญ ์์ฑ ๋ฒํผ์ด ์๋ค.

์ด๋ฆ์ ์ ๋นํ ์ ์ง์ด์ค๋ค.
์ฌ๊ธฐ์๋ 1 ๋ฒ์ ์ ๋ณ์นญ์ผ๋ก ๋ง๋ค ๊ฒ์ด๋ค.

๊ทธ๋ฆฌ๊ณ ์ด ๋ณ์นญ์ ํตํด ์ต์ข
๋ฐฐํฌ๋ฅผ ํ๋ฉด ๋๋ ๊ฒ์ด๋ค.
API GateWay๋ก Api ์ด์ด์ฃผ๊ณ ์ฐ๋ฉด ๋๋๋ฐ, ์ฃผ์ํ ์ ์ ์ด๋ด๋ ๊ทธ๋ฅ ํจ์๋ช ์ ์ ๋๊ฒ ์๋๋ผ ๋ณ์นญ์ ARN์ ๋ฃ์ด์ค์ผ ํ๋ค๋ ๊ฒ์ด๋ค.
์ด๋ ๊ฒ ๋ง์ด๋ค.
Code Deploy ์ฑ ์์ฑ
Code Deploy์ ๋ค์ด๊ฐ์ ์ ํ๋ฆฌ์ผ์ด์ ์์ฑ์ ์ ํ, ํ๋ซํผ์ ๋๋ค๋ก ํ๊ณ ์์ฑํ๋ค.

๊ทธ๋ผ ์ด๋ ๊ฒ ๋ฐฐํฌ ๊ด๋ฆฌ ํ์ด์ง๊ฐ ์๊ฒจ๋ ๊ฒ์ด๋ค.
๊ทธ๋ผ ์ด์ ๋ฐฐํฌ ๊ทธ๋ฃน์ ์์ฑํด์
์ ๊ธฐ์ ์๋น์ค ์ญํ ์ ๋ง๋ค์ด์ arn์ ๋ฃ์ด์ฃผ๋ฉด ๋๋ค.
์๋น์ค ์ญํ ์์ฑ
๋ฐฐํฌ๊ทธ๋ฃน์ ์ฌ์ฉํ ์ญํ ์ ๋ค์๊ณผ ๊ฐ์ด ์์ฑํ ์ ์๋ค.
์ฌ์ฉ ์ฌ๋ก์์ ์ ๊ฑธ ๊ณจ๋ผ์

์ ์ฑ ์ ๋ค์๊ณผ ๊ฐ์ด 2๊ฐ ์ฐ๊ฒฐํด์ฃผ๊ณ

์ ๋ขฐ๊ด๊ณ์ codedeploy ๋๋ฉ์ธ์ ๋ฃ์ด์ฃผ๋ฉด ๋๋ค.

๊ทธ๋ผ ์ด๋ ๊ฒ ์์ฑ์ด ์ ๋ ๊ฒ์ด๋ค.

๋กค๋ฐฑ ์ค์
๋ง์ฝ ์๋ก๋ง๋ ๋๋ค ๋ฒ์ ์ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค๋ฉด ๋กค๋ฐฑ์ ์์ผ์ผ ํ์ง ์๊ฒ ๋๊ฐ.
๋ฐ์ ๊ณ ๊ธ์์ ๋กค๋ฐฑ ๋นํ์ฑํ๋ฅผ ํด์ ํ๊ณ ๋กค๋ฐฑ์ ์ค์ ํด์ฃผ์.

์ด๋ ๊ฒ ํด์ CodeDeploy ์ฑ์ ๋ง๋ค์ด์ฃผ๋ฉด ๋๋ค.
๋ฒํท ์์ฑ
์ด๊ฒ ๋ค๊ฐ ์๋๋ค.
๋ฐฐํฌํ ๋๋ง๋ค ๋ฒ์ ์ ์ด๋ป๊ฒ ์ฌ๋ฆด์ง ๊ทธ๋ฐ๊ฑธ ์ ์ํด์ผ ํ๋๋ฐ, ์ด๊ฑธ appspec ํ์ผ์ด๋ผ๊ณ ํ๋ค.
๊ทธ๊ฑธ ์ ์ฅํด๋์ S3 ๋ฒํท์ ๋ง๋ค์ด์ฃผ์.

๊ทธ๋ฆฌ๊ณ ๋ค์๊ณผ ๊ฐ์ ํ์์ผ๋ก ๋ฐฐํฌ ์ค์ ํ์ผ์ ์จ์ ๋ฃ์ด์ฃผ๋ฉด ๋๋ค.

version: 0.0
Resources:
- myLambdaFunction:
Type: AWS::Lambda::Function
Properties:
Name: "express_test"
Alias: "rolling"
CurrentVersion: "7"
TargetVersion: "8"
Hooks:
- BeforeAllowTraffic: "code-deploy-check"
์ฌ๊ธฐ์ Name์ ๋ง ๊ทธ๋๋ก ํจ์๋ช
, Alias๋ ์๊น ๋ง๋ ๋ณ์นญ.
Current๋ ํ์ฌ ๋ฐฐํฌ๋์ด์๋ ๋ฒ์ . TargetVersion์ ๋ฐฐํฌํ ๋ฒ์ ์ด๋ค.
๊ทธ๋ฆฌ๊ณ BeforeAllowTraffic๋ ํธ๋ํฝ์ ์ฎ๊ธฐ๊ธฐ ์ ์ ํธ๋ฆฌ๊ฑฐ๋ฅผ ๊ฑธ์ด์ฃผ๋ ๊ฒ์ด๋ค.
๊ฐ์ผ๋ก ๋ค์ด๊ฐ๋๊ฑด ํจ์๋ช
์ด๋ค.
์ ๊ธฐ์ ์์ค์ ์ ์์๋์ ๋ํ ๊ฒ์ฆ์ ํ๋ฉด ๋๋ค.
Health Check์ฉ ํ ํจ์
ํ ํจ์๋ ๋๋ต ๋ค์๊ณผ ๊ฐ์ ๊ตฌ์กฐ๋ก ์์ฑํ๋ฉด ๋๋ค.

'use strict';
const aws = require('aws-sdk');
const codedeploy = new aws.CodeDeploy({apiVersion: '2014-10-06'});
exports.handler = async (event, context, callback) => {
//Read the DeploymentId from the event payload.
var deploymentId = event.DeploymentId;
//Read the LifecycleEventHookExecutionId from the event payload
var lifecycleEventHookExecutionId = event.LifecycleEventHookExecutionId;
/*
... ์ฌ๊ธฐ์ ๊ฒ์ฆ.
*/
// Prepare the validation test results with the deploymentId and
// the lifecycleEventHookExecutionId for CodeDeploy.
var params = {
deploymentId: deploymentId,
lifecycleEventHookExecutionId: lifecycleEventHookExecutionId,
status: 'Succeeded' // status can be 'Succeeded' or 'Failed'
};
//const bar = await codedeploy.getDe
// Pass CodeDeploy the prepared validation test results.
codedeploy.putLifecycleEventHookExecutionStatus(params, function(err, data) {
if (err) {
// ๊ฒ์ฆ ์คํจ
callback('Validation test failed');
} else {
// ๊ฒ์ฆ ์ฑ๊ณต
callback(null, 'Validation test succeeded');
}
});
};
์ด๊ฑด ๊ณต์๋ฌธ์์์ ์ ๊ณตํ๋ ํ ํ๋ฆฟ์ด๊ณ , ๋๋ ๋ค์๊ณผ ๊ฐ์ด ์ฌ์ฉํ๋ค.
๋๋ค์ target version์ ํธ์ถํด์ ์ค๋ฅ๊ฐ ๋๋ฉด putLifecycleEventHookExecutionStatus๋ก ์คํจํ๋ค๊ณ ์ด๋ฒคํธ๋ฅผ ๋ ๋ ค์ฃผ๊ณ , ๋ฌธ์ ์์ผ๋ฉด putLifecycleEventHookExecutionStatus์ ์ฑ๊ณต์๋ฆผ์ ๋ณด๋ด๋ ๊ฒ์ด๋ค.
'use strict';
const aws = require('aws-sdk');
const codedeploy = new aws.CodeDeploy({apiVersion: '2014-10-06'});
const lambda = new aws.Lambda();
exports.handler = async (event, context, callback) => {
// ์ด ๊ฐ์ BeforeAllowTraffic๋ก ๊ฑธ๋ฉด ์๋์ผ๋ก ๋ค์ด์ด
const deploymentId = event.DeploymentId;
const lifecycleEventHookExecutionId = event.LifecycleEventHookExecutionId;
// ์ฒดํฌ์ฉ ํธ์ถ
const response = await lambda
.invoke({
FunctionName: 'express_test:9', //๋ฒ์ ์ ๋ฐฐํฌ์ค์ธ target ๋ฒ์ ์ด ๋ค์ด๊ฐ๊ฒ ํด์ฃผ๋ฉด ๋จ.
Payload: JSON.stringify({}),
})
.promise()
console.log('response: ', response)
if(response.FunctionError !=='Unhandled') {
console.log('์ฑ๊ณต')
await codedeploy.putLifecycleEventHookExecutionStatus({
deploymentId: deploymentId,
lifecycleEventHookExecutionId: lifecycleEventHookExecutionId,
status: 'Succeeded'
}).promise();
callback(null, 'Validation test succeeded');
}
else {
console.log('์คํจ')
await codedeploy.putLifecycleEventHookExecutionStatus({
deploymentId: deploymentId,
lifecycleEventHookExecutionId: lifecycleEventHookExecutionId,
status: 'Failed'
}).promise();
callback('Validation test failed');
}
};
๋๋ค ์ญํ ์ CodeDeploy์ LambdaInvoke ๊ถํ์ ๊ฑธ์ด์ฃผ๊ณ , ๋ฉ๋ชจ๋ฆฌ์ ์คํ์๊ฐ ์ ํ์ ์ข ๋๋ ค์ค์ผ ํ๋ค.
์ฌ๊ธฐ์ ๋๋ ๋จ์ํ๊ฒ ๋ฉ์ธ์์ ์ค๋ฅ๊ฐ ๋จ๋์ง ์๋์ง๋ง ๊ฒ์ฌํ์ง๋ง, ์ํฉ์ ๋ฐ๋ผ์ ๋ ๋ง์ ๊ฒ์ฆ์ ํด์ผํ ์๋ ์์ ๊ฒ ๊ฐ๋ค.
๋ฐฐํฌ ์์ฑ
์ด์ ๋ฐฐํฌ ์ค์ ์ ๋ง๋ค์ด๋ณด์.
์ด๋ฆ์ ์ง๊ณ , ์์์ ๋ง๋ ๋ฐฐํฌ์ฉ ์ค์ ํ์ผ์ ์ฐ๊ฒฐํด์ฃผ๋ฉด ๋๋ค.
s3๋ก ๋ฐ์์๋ ๋๊ณ , ํธ์ง๊ธฐ๋ก ๊ทธ๋ฅ ํ
์คํธ๋ฅผ ๋ฐ์ ์๋ ์๋ค.
๊ทธ๋ฆฌ๊ณ ๋ฐฐํฌ ๊ตฌ์ฑ๊ณผ ๋กค๋ฐฑ ๊ตฌ์ฑ์ ์ค์ ํด์ค๋ค.
์ด์์ด๋ฉด ๋กค๋ฐฑ์ ๋๊ฒ ํด๋๋๊ฒ ์ข๊ฒ ๊ณ ...
๋ฐฐํฌ ๊ตฌ์ฑ์ ํ์์ ๋ฐ๋ผ ๋ค์ ๋ฆฌ์คํธ ์ค์ ๊ณ ๋ฅด๋ฉด ๋๋ค.
๋๋ ๊ฐ์ธ์ ์ผ๋ก ์นด๋๋ฆฌ๊ฐ ์ข์ ๊ฒ ๊ฐ๋ค.
๊ทธ๋์ ์ด๋ ๊ฒ ๋ค ํต๊ณผํ๋ฉด ์ ๋ฐฐํฌ๊ฐ ๋ ๊ฒ์ด๋ค.

์ ์๋ ์ ๋๋ฉด ์ฑ๊ณต์ด๋ค.


๋ง์ฝ์ ๋ค์๊ณผ ๊ฐ์ด ์์ค์ ์ค๋ฅ๊ฐ ์๋ ์ฑ๋ก ๋ฐฐํฌ๋ฅผ ์๋ํ๋ค๋ฉด

ํ ํจ์์์ failed๋ฅผ ๋ ๋ฆฌ๋ฏ๋ก ๋ฐฐํฌ๊ฐ ์ทจ์๋๊ณ ๋กค๋ฐฑ์ด ์ํ๋ ๊ฒ์ด๋ค.

๊ทธ๋ ๋ค.
์ฐธ์กฐ
https://docs.aws.amazon.com/ko_kr/lambda/latest/dg/lambda-rolling-deployments.html
https://docs.aws.amazon.com/codedeploy/latest/userguide/tutorial-lambda-sam.html
https://docs.aws.amazon.com/codedeploy/latest/userguide/getting-started-create-service-role.html
https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/reference-appspec-file-example.html
https://ystatit.medium.com/aws-codedeploy-basic-walk-through-lambda-cf3be01d3e06
https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/reference-appspec-file-structure-hooks.html#appspec-hooks-lambda