본문 바로가기

Compute/EBS

AWS EBS Daily Snapshot

aws node sdk를 이용해서 EBS Daily Snapshot를 생성해본다. aws sdk 사용 방법은 이번 블로깅 범위가 아니니 생략한다. 사전에 sdk 사용 방법은 숙지해야 한다.

참고

 

Node.js의 JavaScript용 AWS SDK

Mac/Linux의 경우 ~/.aws/credentials에, Windows의 경우 C:\Users\USERNAME\.aws\credentials에 자격 증명 파일을 생성 [기본값] aws_access_key_id = your_access_key aws_secret_access_key = your_secret_key 자격 증명을 로드하는 다른 방법은 시작 안내서를 참조하십시오. 버킷 이름은 소문자, 숫자, 하이픈(-)을 포함할 수 있습니다. 각 레이블은

aws.amazon.com

 

NAT 혹은 Bastion Instance를 통해 API를 호출하여 매일 EBS Snapshot을 생성하고 주기적으로 삭제한다. 

 

 

먼저 API 호출하기 위한 Policy를 생성한다.

{
     "Version": "2012-10-17",
     "Statement": [
         {
             "Sid": "Stmt1456187863000",
             "Effect": "Allow",
             "Action": [
                 "ec2:CreateImage",
                 "ec2:CreateSnapshot",
                 "ec2:CreateTags",
                 "ec2:DeleteSnapshot",
                 "ec2:DescribeSnapshots",
                 "ec2:DescribeTags",
                 "ec2:DescribeVolumes"
             ],
             "Resource": [
                 "*"
             ]
         }
     ]
 }

 

이제 생성한 Policy를 NAT에 Load 해줘야 합니다. 방법은 크게 두 가지가 있다. IAM Roles를 이용하거나 Access&Secret Key를 사용한다.

 

자세한 내용은 참고

 

Configuring the SDK for JavaScript - AWS SDK for JavaScript

The AWS Documentation website is getting a new look! Try it now and let us know what you think. Switch to the new look >> You can return to the original look by selecting English in the language selector above. Configuring the SDK for JavaScript Before you

docs.aws.amazon.com

describeVolumes API를 통해 모든 Volume id를 가져온 후에 해당 id를 creatSnapshot을 통해 생성한다.

 

Snapshot Action은 토/일요일 제외한 매일 오전 4시 30분에 시작된다.

var AWS = require('aws-sdk');
var credentials = new AWS.SharedIniFileCredentials({profile: 'snapshot'});
AWS.config.credentials = credentials;
AWS.config.update({region:'ap-northeast-2'});
var dateFormat = require('dateformat');
var cronJob = require('cron').CronJob;
var ec2=new AWS.EC2();
 
var describeVolumes=function(ec2, callback){
    ec2.describeVolumes({}, function(err, data) { //Describe Volume
            if (err) console.log(err, err.stack); // an error occurred
            else{
                    callback(data);
                    return;
            }
    });
}
var createSnapshot=function(ec2, snapshotParams){
        ec2.createSnapshot(snapshotParams, function(err, data) { //Create Snapshot
                if (err) console.log(err, err.stack); // an error occurred
                else     console.log(data);           // successful response
        });
}
var createSnapshots=function(){
        console.log('Create Snapshots');
    describeVolumes(ec2, function(data){
            var volumes=data.Volumes;
            var volumesLength=volumes.length;
            var now=new Date();
            var date=dateFormat(now, "isoDateTime");
            for(var i=0; i<volumesLength; i++){
                    var volumeId = volumes[i]['VolumeId'];
                    var snapshotParams = {
                        VolumeId: volumeId,
                        Description: volumeId + "_" + date,
                        DryRun: false
                    };
                    createSnapshot(ec2, snapshotParams);
            }
    });
}
 
var deleteSnapshots=function(){
    console.log('delete Snapshots');
    describeSnapshots(ec2, function(data){
        var snapshots=data.Snapshots;
        var snapshotLength=snapshots.length;
        var now=new Date();
        var date=dateFormat(now, "yyyy-mm-dd");
        for(var i=0; i<snapshotLength; i++){
                var snapshotStart=snapshots[i]['StartTime'];
                var snapshotStart=dateFormat(snapshotStart, "yyyy-mm-dd");
                var diffDay=getDateDiff(date, snapshotStart);
            if(snapshots[i]['OwnerId']=='218116754327'){     //account ID
                    if(diffDay > 181){   // six months delete
                        var params={
                            SnapshotId: snapshots[i]['SnapshotId'],
                            DryRun: false
                         };
                        console.log(snapshots[i]);
                        deleteSnapshot(ec2,params);
                    }
            }
        }
    });
}
var deleteSnapshot=function(ec2, params){
    ec2.deleteSnapshot(params, function(err, data){
            if(err) console.log(err, err.stack);
    });
}
var describeSnapshots=function(ec2,callback){
    ec2.describeSnapshots({}, function(err, data){
          if (err) console.log(err, err.stack); // an error occurred
          else{
                   callback(data);
                   return;
        }
    });
}
var getDateDiff=function(date1,date2){
        var arrDate1 = date1.split("-");
        var getDate1 = new Date(parseInt(arrDate1[0]),parseInt(arrDate1[1])-1,parseInt(arrDate1[2]));
        var arrDate2 = date2.split("-");
        var getDate2 = new Date(parseInt(arrDate2[0]),parseInt(arrDate2[1])-1,parseInt(arrDate2[2]));
        var getDiffTime = getDate1.getTime() - getDate2.getTime();
        return Math.floor(getDiffTime / (1000 * 60 * 60 * 24));
}    
var job = new cronJob({
  cronTime: '00 30 04 * * 1-5',  
  onTick: function() {
    // Runs every weekday (Monday through Friday)
    // at 04:30:00 AM. It does not run on Saturday
    // or Sunday.
     createSnapshots();
     deleteSnapshots();
     console.log('cron job completed');
  },
  start: true,
  timeZone: 'Asia/Seoul'
});
job.start();

매일 모든 Volume들을 Snapshot, 6개월이 지난 Snapshot들은 삭제한다.

Snapshot이 시작되면 Disk IO 성능에 영향이 있으며, 약 1분 내외로 다시 성능은 증가한다. 따라서 상황에 따라 AZ나 서비스를 기준으로 Tag를 통해 인스턴스를 구분하여 Snapshot 작업을 하는 것을 권장한다.

더이상 Snapshot은 EBS에 성능 영향을 주지 않는다.

 

aws cli를 통해 간단한 스크립트 짜고 volume id 값 넣고 crontab 돌리면 된다.

 

CloudWatch Event와 Lambda를 통해서도 가능할 듯 합니다. 아직 서울 리전엔 서비스가 되지 않지만..

이제 서울 리전에서 Lambda가 지원하기 때문에 Lambda를 사용하자.

하...이제 CloudWatch Event에서 자동 스냅샷을 지원하니까 이번 글은 나가리 됐다. 점점 잡일은 할 일이 없어진당ㅎㅎ

 

 

 

 

 

 

 

 

 

 

 

'Compute > EBS' 카테고리의 다른 글

AWS EBS AMI 백업  (2) 2018.09.21
AWS EBS mount: unknown filesystem type ‘LVM2_member’ error  (0) 2016.01.28
AWS Elastic Block Store(EBS) 이해  (0) 2015.11.18