Skip to content

Deployment Environment

Song Yoon edited this page Sep 1, 2021 · 13 revisions

EC2 Type

Type t2.micro
vCPU 1
Memory(GiB) 1

EC2 Instance (Amazon Linux AMI) Settings

Codedeploy Agent

기본 설치

Edit user data 에 삽입 인스턴스 생성 후 실행 시 작동되는 script.

#!/bin/bash
sudo yum -y update
sudo yum -y install ruby
sudo yum -y install wget
cd /home/ec2-user
wget https://aws-codedeploy-us-east-1.s3.amazonaws.com/latest/install
sudo chmod +x ./install
sudo ./install auto

Logo 확인

$ cd /opt/codedeploy-agent/deployment-root/deployxment-logs
$ cat codedeploy-agent-deployments.log


Blue/Green를 이용한 무중단 배포

  • ​Blue/Green를 통해 신규 어플리케이션은 기존에 있던 EC2 서버가 아닌 신규 서버에 배포된다.
  • 이 때, 신규 서버는 Codedeploy를 통해 프로비저닝이 되고 지정된 로드 밸런서에 등록이 되어 트래픽을 전달 받는다.
  • 신규 서버에서의 배포가 안정적으로 완료가 되면 기존 EC2 서버는 지정된 로드 밸런서에 받고있던 트래픽이 차단된 후 터미네이트 된다.
  • 지정된 로드 밸러서는 리스너 포트와 프로토콜을 Auto Scaling Group에서 지정된 target group으로 설정하여 트래픽을 라우팅한다.

프로비저닝: 액세스 및 인증 권한, 서버를 가동하기 위한 설치 작업 등 필요한 리소스를 기반으로 네트워크에 사용될 서버를 설정하는 단계

배포과정

SNS Lambda Setting

AWS Lambda란,

  • AWS에서 제공하는 서러비스 컴퓨팅 서비스
  • 별도의 서버 셋업없이 코드 실행 가능
  • Event Driven (또는 트리거) 형식으로 동작 (예. 오술에서는 Codedeploy와 SNS를 이용하여 람다가 실행된다.)

Runtime Version

  • Node.js 14.x

Lambda Code Source

view details
const services = process.env.SERVICES;  //Slack service
const channel = process.env.CHANNEL;  //Slack channel

const https = require('https');
const util = require('util');
const startTime = toYyyymmddhhmmss(new Date);



// 타임존 UTC -> KST
function toYyyymmddhhmmss(date) {

    if(!date){
        return '';
    }

    function utcToKst(utcDate) {
        return new Date(utcDate.getTime() + 32400000);
    }

    function pad2(n) { return n < 10 ? '0' + n : n }

    var kstDate = utcToKst(date);
    return kstDate.getFullYear().toString()
        + '-'+ pad2(kstDate.getMonth() + 1)
        + '-'+ pad2(kstDate.getDate())
        + ' '+ pad2(kstDate.getHours())
        + ':'+ pad2(kstDate.getMinutes())
        + ':'+ pad2(kstDate.getSeconds());
}

var formatFields = function(eventMessage) {
    var message = JSON.parse(eventMessage),
        fields  = [],
        deploymentOverview;
    
    // Make sure we have a valid response
    if (message) {
        fields = [
            {
                "title" : "Task",
                "value": "오늘의 술 AWS 현황",
                // "value" : message.eventTriggerName,
                "short" : true
            },
            {
                "title" : "Status",
                "value" : message.status ? message.status : "IN PROGRESS",
                "short" : true
            },
            {
                "title" : "Create Time",
                "value" : message.createTime ?  toYyyymmddhhmmss(new Date((message.createTime))) : "" ,
                // "value" : toYyyymmddhhmmss(new Date(message.createTime)),
                "short" : true
            },
            {
                "title" : "Complete Time",
                // "value" : toYyyymmddhhmmss(new Date((message.completeTime) ? message.completeTime : '')),
                "value" : message.completeTime ?  toYyyymmddhhmmss(new Date((message.completeTime))) : "" ,
                "short" : true
            },
            {
                "title" : "Error Code",
                "value" : message.errorInformation? JSON.parse(message.errorInformation).ErrorCode: '',
                "short" : true
            },
            {
                "title" : "Error Message",
                "value" : message.errorInformation? JSON.parse(message.errorInformation).ErrorMessage: '',
                "short" : true
            }
        ];

    }

    return fields;
};

exports.handler = function(event, context) {
    var postData = {
        "channel": channel,
        "username": "오늘의술 AWS BOT - " + startTime,
        "text": "*" + event.Records[0].Sns.Subject + "*",
        "icon_emoji": ":inbox_tray:"
    };

  
    var message = event.Records[0].Sns.Message;
    var severity = "good";
    var fields = formatFields(message);

    var dangerMessages = [
        " but with errors",
        " to RED",
        "During an aborted deployment",
        "FAILED",
        "Failed to deploy application",
        "Failed to deploy configuration",
        "has a dependent object",
        "is not authorized to perform",
        "Pending to Degraded",
        "Stack deletion failed",
        "Unsuccessful command execution",
        "You do not have permission",
        "Your quota allows for 0 more running instance"];

    var warningMessages = [
        " aborted operation.",
        " to YELLOW",
        "Adding instance ",
        "Degraded to Info",
        "Deleting SNS topic",
        "is currently running under desired capacity",
        "Ok to Info",
        "Ok to Warning",
        "Pending Initialization",
        "Removed instance ",
        "Rollback of environment"
    ];

    for(var dangerMessagesItem in dangerMessages) {
        if (message.indexOf(dangerMessages[dangerMessagesItem]) != -1) {
            severity = "danger";
            break;
        }
    }

    // Only check for warning messages if necessary
    if (severity === "good") {
        for(var warningMessagesItem in warningMessages) {
            if (message.indexOf(warningMessages[warningMessagesItem]) != -1) {
                severity = "warning";
                break;
            }
        }
    }

    postData.attachments = [
        {
            "color": severity,
            "fields": fields
        }
    ];

    var options = {
        method: 'POST',
        hostname: 'hooks.slack.com',
        port: 443,
        path: services  // Defined above
    };

    var req = https.request(options, function(res) {
        res.setEncoding('utf8');
        res.on('data', function (chunk) {
            context.done(null);
        });
    });

    req.on('error', function(e) {
        console.log('problem with request: ' + e.message);
    });

    req.write(util.format("%j", postData));
    req.end();
};

Mongo DB

기본설치

$sudo su
$ vi /etc/yum.repos.d/mongodb-org-4.0.repo

[mongodb-org-4.0]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/amazon/2013.03/mongodb-org/4.0/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-4.0.asc

$ yum install -y mongodb-org
$ service mongod start


관리자 권한 설정

$ use admin
$ db.createUser({user: "", pwd: "", roles:["root"]}); $ exit $ sudo service mongod start


보안 설정

$ vi /etc/mongod.conf

# network interfaces
net:
  port: 27017
  bindIp: 0.0.0.0
  .
  .
  .
security:
  authorization: enabled 

$ sudo service service mongod restart


EC2 Security Group 설정

IP version Type Port range
IPv6 Custom TCP 27017
IPv4 Custom TCP 27017