부록

이재홍 http://www.pyrasis.com 2014.03.24 ~ 2014.06.30

Auto Scaling 그룹의 EC2 인스턴스에 소스 배포하기

Auto Scaling으로 EC2 인스턴스가 많아지면 일일이 소스를 업데이트하기가 어려워집니다. 이번에는 Auto Scaling 그룹의 EC2 인스턴스에 소스를 배포하는 방법을 알아보겠습니다.

다음 예제 코드는 저의 GitHub 저장소에 있는 예제 코드를 받아서 사용합니다.

var AWS = require('aws-sdk')
  , fs = require('fs')
  , sshclient = require('sshclient')
  , async = require('async')

AWS.config.loadFromPath('./config.json');

var ec2 = new AWS.EC2({ region: 'ap-northeast-1' })
  , autoscaling = new AWS.AutoScaling({ region: 'ap-northeast-1' });

var privateKey = fs.readFileSync('../../awskeypair.pem');

function getInstanceIds(callback) {
  autoscaling.describeAutoScalingGroups({
    AutoScalingGroupNames: ['ExampleAutoScalingGroup'],
  }, function (err, data) {
    instanceIds = [];
    if (!err) {
      data.AutoScalingGroups[0].Instances.forEach(function (e) {
        instanceIds.push(e.InstanceId);
      });
    }
    callback(instanceIds);
  });
}

function getInstanceIpAddress(instanceId, callback) {
  ec2.describeInstances({
    InstanceIds: [ instanceId ]
  }, function (err, data) {
    if (err)
      console.log(err, err.stack);
    callback(data.Reservations[0].Instances[0].PublicIpAddress);
  });
}

function deploy(host) {
  sshclient.session({
    host: host,
    port: 22,
    username: 'ec2-user',
    privateKey: privateKey
  }, function (err, ses) {
    async.series([
      function (callback) {
        ses.exec('aws s3 sync --region=ap-northeast-1 s3://example.src/ExampleWebServer /home/ec2-user/ExampleWebServer', function (err, stream) {
          callback(err, stream);
        });
      }
    ], function (err, results) {
      console.log(results);
      ses.quit();
    });
  });
}

getInstanceIds(function (instanceIds) {
  instanceIds.forEach(function (e) {
    getInstanceIpAddress(e, function (ipAddress) {
      console.log(ipAddress);
      deploy(ipAddress);
    });
  });
});

다음과 같은 명령으로 스크립트를 실행하면 됩니다. Linux, Windows, Mac OS X에서 사용할 수 있습니다.

node deploy.js

이제 소스 내용을 살펴보겠습니다. SSH로 EC2 인스턴스에 접속할 수 있도록 pem 파일의 경로를 설정합니다. 이 파일은 키 쌍Key Pair을 생성할 때 다운로드 하였습니다.

var privateKey = fs.readFileSync('../../awskeypair.pem');

Auto Scaling 그룹에 속한 EC2 인스턴스의 ID를 얻어오는 함수입니다. AutoScalingGroupNames에 Auto Scaling 그룹의 이름을 설정합니다.

function getInstanceIds(callback) {
  autoscaling.describeAutoScalingGroups({
    AutoScalingGroupNames: ['ExampleAutoScalingGroup'],
  }, function (err, data) {
    instanceIds = [];
    if (!err) {
      data.AutoScalingGroups[0].Instances.forEach(function (e) {
        instanceIds.push(e.InstanceId);
      });
    }
    callback(instanceIds);
  });
}

SSH로 접속하려면 IP 주소가 필요합니다. EC2 인스턴스 ID로 IP 주소를 얻어오는 함수입니다.

function getInstanceIpAddress(instanceId, callback) {
  ec2.describeInstances({
    InstanceIds: [ instanceId ]
  }, function (err, data) {
    if (err)
      console.log(err, err.stack);
    callback(data.Reservations[0].Instances[0].PublicIpAddress);
  });
}

소스를 배포하는 함수입니다.

  • SSH로 EC2에 접속할 수 있도록 username을 설정합니다.
  • Amazon Linux: ec2-user
  • Ubuntu Linux: ubuntu
  • SSH로 EC2 인스턴스에 접속하여 aws s3 sync 명령을 실행합니다. S3 버킷에서 소스를 가져오는 방식입니다. S3 버킷 주소와 소스 경로는 자신의 상황에 맞게 설정합니다.
function deploy(host) {
  sshclient.session({
    host: host,
    port: 22,
    username: 'ec2-user',
    privateKey: privateKey
  }, function (err, ses) {
    async.series([
      function (callback) {
        ses.exec('aws s3 sync --region=ap-northeast-1 s3://example.src/ExampleWebServer /home/ec2-user/ExampleWebServer', function (err, stream) {
          callback(err, stream);
        });
      }
    ], function (err, results) {
      console.log(results);
      ses.quit();
    });
  });
}

S3 버킷에서 소스를 가져오지 않고 Git이나 Subversion을 사용하려면 아래와 같이 작성합니다. git pull과 svn update 명령을 사용하기 때문에 처음에 저장소를 클론/체크아웃 해놓아야 합니다.

Git

function deploy(host) {
  sshclient.session({
    host: host,
    port: 22,
    username: 'ec2-user',
    privateKey: privateKey
  }, function (err, ses) {
    async.series([
      function (callback) {
        ses.exec('cd /home/ec2-user/ExampleWebServer; git pull', function (err, stream) {
          callback(err, stream);
        });
      }
    ], function (err, results) {
      console.log(results);
      ses.quit();
    });
  });
}

Subversion

function deploy(host) {
  sshclient.session({
    host: host,
    port: 22,
    username: 'ec2-user',
    privateKey: privateKey
  }, function (err, ses) {
    async.series([
      function (callback) {
        ses.exec('cd /home/ec2-user/ExampleWebServer; svn update', function (err, stream) {
          callback(err, stream);
        });
      }
    ], function (err, results) {
      console.log(results);
      ses.quit();
    });
  });
}

저는 Node.js로 작성했지만 AWS API를 사용하여 Java, Python, Ruby 등 여러 가지 언어로 작성할 수 있습니다. 그리고 SSH로 접속하지 않고 Chef 또는 Docker로 구현해도 됩니다.


저작권 안내

이 웹사이트에 게시된 모든 글의 무단 복제 및 도용을 금지합니다.
  • 블로그, 게시판 등에 퍼가는 것을 금지합니다.
  • 비공개 포스트에 퍼가는 것을 금지합니다.
  • 글 내용, 그림을 발췌 및 요약하는 것을 금지합니다.
  • 링크 및 SNS 공유는 허용합니다.