Category: 한국 기술 문서


Amazon GameLift를 시작하기 위한 기술 팁 모음

지난 2월 11일 클라우드 기반 게임 개발자에게 게임 개발을 위한 신규 Lumberyard, Amazon GameLift 및 Twitch 통합 서비스라는 반가운 소식이 있었습니다.

Amazon Lumberyard는 CryEngine에 기반한 게임 개발 엔진입니다. 소스 코드 형태로 제공되며 사용자가 직접적으로 빌드해서 원하는 게임을 만들 수 있습니다. 현재 CryEngine 3.8.1을 기본으로 AWS 서비스와 GameLift를 지원하도록 제공되고 있습니다. Lumberyard에 대한 튜토리얼 자료는 시작하기 기술 문서Amazon GameDev Tutorials를 참고하시면 됩니다.

이 글에서는 Amazon GameLift에 대한 소개와 첫 예제를 실행할 때, 발생하기 쉬운 문제들에 대한 해결 방법 등에 대해 소개하고자 합니다.

Amazon GameLift란 무엇인가?
Amazon GameLift는 세션 기반의 멀티 플레이어 게임 서비스를 위한 관리형 서비스입니다. 게임 서버를 배포, 운영, 확장하기 위해 기존 다른 AWS 서비스와 마찬가지로 관리형으로 제공되어 게임 서버를 쉽게 구현하고 관리할 수 있게 합니다.

Amazon GameLift 서비스는 클라우드에서 게임 서버를 운영할 때 생기는 어려운 점을 해소합니다. 게임 서버를 개발한 이후에 이것을 배포하고 확장성 있게 운영하는 것은 쉬운 일이 아닙니다. 일반적으로 게임 서비스를 만들면 최초로 게임이 오픈 되었을 때, 예측 할 수 없는 트래픽으로 서버가 다운되는 경우가 많습니다. 게임 서버의 다운은 매우 빠르게 알려지고, 게임 커뮤니티 내에서 좋지 않은 평판이 만들어져서 게임 서비스에 치명적이 될 소지가 많습니다. GameLift는 AWS의 클라우드 서비스를 통해 이러한 문제를 해결할 수 있습니다.

또한, 멀티 플레이어 게임에 대한 기본적인 서버 메커니즘을 제공합니다. 그간에 축적된 게임 서비스 기술 지식에 기반해서 AWS 내부 전문가들에 의해 설계 및 개발되었고, 게임 디버깅이나 플레이어들의 상태를 쉽게 파악하기 위해 다양한 게임 텔리메트리(telemetry)를 지원합니다.

뿐만 아니라, 세션형 멀티 플레이어 게임에도 적합합니다. 즉, 오랜 시간동안 세션이 유지되면서 상호 데이터가 동기화 되는 형태 보다는 일정 시간 안에 여러 사용자가 플레이하면서 상호 데이터 동기화를 할 필요가 있는 게임에 적합합니다.

Amazon GameLift에 대한 추천 게임 종류는 아래 표와 같습니다.

적합한 게임 형식 게임 예
FPS Call of Duty, Evolce
MOBA(Multiplayer Online Battle Arena)s Legue of Legends, Heroes of the Storm
Survival/Sandbox Minecraft, Ark
Racing Mario Kart, Kart Rider
Sports NBA2K, FIFA

MMO나 모바일 소셜 게임 및 전용 서버가 없는 P2P 게임 등은 적합하지 않으며, Amazon GameLift를 사용해서 개발하기 적합한 게임은 전용 서버(dedicate server) 형식 게임이라고 할 수 있습니다.

GameLift에 예제 서비스 올리기
향후에는 GameLift에 다양한 게임 엔진과도 연동한다는 계획이지만, 현재는 Lumberyard만 지원하고 있습니다. Lumberyard에는 여러 샘플 프로젝트가 포함되어 있는데 멀티플레이어 샘플 게임도 존재합니다.

예제 게임 튜토리얼을 따라 하면 손쉽게 샘플 게임을 빌드하고 GameLift로 서비스를 올려 볼 수 있습니다.

이 글에서는 튜토리얼 그 자체 보다는 샘플을 올리는 과정에서 나오는 버그라던가 실수를 방지하는 기술 팁을 살펴보도록 할 예정입니다. 먼저 기술 팁을 설명하기 앞서서 샘플 프로그램을 GameLift에 올리는 단계를 간단히 살펴보겠습니다.

  1. Lumberyard의 설치
    • Visual Studio 2013, update 4를 설치한다.
    • Lumberyard를 풀고, 3rd 파티 툴들을 모두 설치한다.
    • 예제 게임 튜토리얼대로 서버 예제를 선택한 이후에 프로젝트를 빌드한다.
    • 빌드 패키지를 구성한다 예) install.bat 등을 적절히 수정한다.
  2. 빌드된 패키지를 서버로 업로드
    • AWS CLI를 설치한다.
    • GameLift를 위한 Policy를 생성하고, AWS IAM 유저를 붙인다.
    • CLI 명령을 통해 GameLift에 빌드된 서버 패키지를 올린다.
  3. GameLift Fleet을 생성
    • Fleet이름, 서버 빌드, 인스턴스 타입을 선택한다.
    • EC2 포트 세팅을 한다.
    • 런치 패스와 런치 파라미터를 지정한다.
  4. 게임 클라이언트 생성
    • GameLiftClient.bat를 생성한다.
    • 게임 세션을 생성한다.
    • 플레이어가 게임 세션에 접근한다

흔히 발생하는 오류나 실수를 위한 기술 팁
위와 같이 GameLift에 샘플 게임을 올리는 과정에서 아래와 같은 문제가 발생할 수 있으며, 이를 위한 기술팁을 소개하고자 합니다.

Tip 1. Unicode 문제
앞서 설명한 단계 중 샘플 프로젝트를 컴파일 하는 와중에 에러가 발생하면서, 컴파일이 중단될 수 있습니다. 이것은 파일이 Unicode 파일 형식으로 저장이 되지 않아 주로 발생합니다.

에러 메시지를 보고 Visual Studio에서 해당 파일을 수정하면 됩니다. 아래는IntersectorSegment.cpp파일에 대한 수정 내역입니다.


[그림 1] 파일 인코딩 타입 변경

UTF-8 파일 타입으로 인한 오류는 게임 개발자에게 매우 익숙한 일이므로 쉽게 문제를 해결해서 다음 단계로 넘어 갈 수 있습니다.

Tip 2. Install.bat 등 배치 파일 오류
빌드 패키지를 구성할 때 흔한 오류는 배치 스크립트를 정확히 만들지 않는 것입니다. 예를 들어 Install.bat파일은 다음과 같이 설정해야 한다.

vcredist_x64.exe /q

만약 여기서 /q 옵션을 실수로 기술하지 않은 채 패키징을 하고, GameLift로 올렸다면 서버 그룹(Fleet)을 생성할 때 다음과 같은 에러 메시지가 발생합니다.

LEET STATUS changed sequentially like this: NEW  DOWNLOADING  ERROR.

배치 스크립트의 각종 오류로 인한 결과는 빌드를 GameLift로 올릴 때 발생하는 것이 아니라 서버 그룹(Fleet) 등을 생성할 때 나타날 수 있고, 또 에러 메시지가 직관적이지 않아 디버깅에 매우 어려움을 겪을 수 있습니다. 따라서, 꼭 배치 스크립트의 에러를 확인하시길 바랍니다.

Tip 3. EC2 포트설정
게임 서버 그룹(Fleet)을 생성할 때, EC2 port 에 대한 설정을 지정해야 합니다. 콘솔에서 작업할 때 포트 설정 저장이 되도록 하려면 아래 그림의 가장 오른 쪽의 작은 아이콘을 눌러서 저장을 해야 합니다.

흔히 그냥 값을 기록하면 자동으로 저장될 줄 알고 값만 넣은 다음 Initialize Fleet 버튼만 누를 수 있는데, 이렇게 되면 포트 설정이 되지 않아서 문제가 됩니다.


[그림 2] EC2 포트 설정

Fleet을 생성한 이후에는 각 설정 값을 확인 할 수 있습니다. 정확히 EC2 포트가 설정되었는지 그림 3에서 확인할 수 있습니다.


[그림 3] Fleet 의 설정 결과 확인

Tip 4. GameLiftClient.bat 수정하기
마지막으로 수정이 필요한 것은 게임 클라이언트 생성 시 GameLiftClient.bat를 생성한는 단계입니다. 튜토리얼 문서에는 아래와 같이 내용을 작성하면 된다고 했지만, 추가적으로 두 개의 정보가 더 필요합니다.

MultiplayerProjectLauncher.exe +sv_port 33435 +gamelift_endpoint gamelift.us-east-1.amazonaws.com +gamelift_aws_region us-east-1 +gamelift_fleet_id  +gamelift_aws_access_key  +gamelift_aws_secret_key  +map gameliftlobby

아래와 같이 엔드포인트와 리전 정보를 추가해 주어야 합니다.

MultiplayerProjectLauncher.exe +sv_port 33435 +gamelift_endpoint gamelift.us-east-1.amazonaws.com +gamelift_aws_region us-east-1 +gamelift_fleet_id  +gamelift_aws_access_key  +gamelift_aws_secret_key  +map gameliftlobby

배치 파일을 실행하면 아래와 같은 실행된 게임을 보실 수 있습니다.

이 글에서는 Amazon GameLift의 샘플 프로젝트를 세팅하면서 흔히 마주치게 되는 오류를 피하는 팁을 설명하였습니다. 다음에는 Amazon GameLift SDK를 이용해서 직접 클라이언트와 서버를 세팅하는 방법을 살펴보겠습니다.

본 글은 아마존웹서비스 코리아의 솔루션즈 아키텍트가 국내 고객을 위해 전해 드리는 AWS 활용 기술 팁을 보내드리는 코너로서, 이번 글은 박선용 솔루션즈 아키텍트께서 작성해주셨습니다.

AWS API 호출하기 (2) – Amazon S3 객체에 대한 미리 선언된(pre-signed) URL 생성하기

이번 블로그 포스팅은 지난 번에 올렸던 AWS API 호출하기(개론편)의 후속편입니다. 아마도 개론편 블로그를 끝까지 읽으시고도 애매모호 하셨을 것으로 생각됩니다. 실제로 HTTP/HTTPS API 호출 요청을 만들어 보면서 전체적인 흐름을 파악하고 이해를 돕도록 하겠습니다.  

‘어떤 예제가 간단하면서도 실제 업무에 도움이 될 수 있을까?’ 많이 고민하였는데요. 제목에서 추측하셨겠지만, Amazon S3 버킷에 있는 객체를 특정 시간 내에만 유효하게 공유할 수 있는 미리 선언된(pre-signed) URL을 만들어 보도록 하겠습니다. 물론 이곳을 참조해서, Java, .NET 그리고 Ruby용 SDK를 이용해 미리 선언된 URL을 쉽게 만들 수 있습니다. 또한 AWS Explorer나 기타 상용 도구에서도 이런 기능을 이용할 수 있습니다.

이번 블로그 포스팅에서는 bash 쉘 스크립트를 이용해서 이 기능을 지원하는 HTTP/HTTPS API 호출 요청을 직접 만들어 보도록 하겠습니다.

예제 쉘 스크립트는 미리 선언된 URL을 만드는데 서명 버전 4를 사용하였습니다. Amazon S3 경우 2014년 1월 30일 이후에 생성된 리전에서는 서명 버전 V2는 더 이상 지원하지 않습니다. 따라서 2016년 1월 7일 개설된 서울 리전도 서명 버전 V4 만 지원합니다.

1. 사전 준비 사항
스크립트를 작성하기 위해서는 openssl(1) 버전 1 또는 그 이상이 필요합니다. 서명키를 만들 때 키값이 문자열이 아닌 이진키값을 입력으로 받아야 하기 때문에 버전 1 이상이 필요합니다. 버전 확인은 아래와 같이 하시고, 예제와 같이 0.9.8zg 버전이면 이곳에서 소스 코드를 받아 설치하시면 됩니다. 설치 방법은 이 블로그 범위를 벗어나기 때문에 따로 설명드리지는 않겠습니다.

$ openssl version
OpenSSL 0.9.8zg 14 July 2015

그리고 사용자 신원 정보와 리전 정보를 얻기 위해서 환경 변수 AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY 및 AWS_DEFAULT_REGION 을 이용하였습니다. 설정 방법은 이곳이나 아래를 참조하시면 됩니다. AWS 계정에 대한 중요한 신원 정보를 스크립트 코드 내에 포함시키는 것은 위험합니다. 따라서 사용 환경에 설정하는 것을 권장합니다.

$ export AWS_ACCESS_KEY_ID=<YOUR_ACCESS_KEY_ID>
$ export AWS_SECRET_ACCESS_KEY=<YOUR_SECRET_ACCESS_KEY_ID>
$ export AWS_DEFAULT_REGION=<AWS_REGION>

로케일 언어 설정은 UTF-8인코딩으로 설정합니다. 이 로케일 설정이 여러분의 작업 환경과 다르다면 bash 쉘 스크립트 내에 포함시켜도 무방합니다.

$ export  export LC_ALL=ko_kr.UTF-8
$ export LANG=ko_kr.UTF-8

2. 스크립트 작성하기
위 선행 작업이 완료되었다면, 이제 스크립트를 작성할 준비가 되었습니다.  Amazon S3 API 호출 요청은 Amazon S3 API Reference를 기본적으로 참조하였으며, 미리 선언된 URL을 만들기 위한 전반적인 작업 순서는 아래와 같습니다:

  1. 표준 요청(Canonical Request) 형식으로 메시지 내용들을 정렬하기
  2. 서명하기 위한 문자열(String To Sign) 만들기
  3. AWS 서명 버전 4(Signature) 계산하기
  4. 생성한 서명 정보를 HTTP/HTTPS API 요청에 추가하기

위 서명 계산 절차를 구체적이고 이해하기 쉽게 도식화해 놓은 것이 아래 다이어그램이며, 이 순서를 따라서 스크립스틀 작성하였습니다. 그리고 각 항목에대한 구체적인 설명은 이곳을 참조하시면 많은 도움을 얻을 수 있습니다.

아래는 위 절차에 따라 생성된 미리 선언된 URL의 한 예입니다. 가독성을 높이기 위해 URL에 줄바꿈 문자를 추가했습니다. 실제로는 한 줄로 표현되어야 합니다.

https://examplebucket.s3.amazonaws.com /test.txt?
X-Amz-Algorithm=AWS4-HMAC-SHA256
&X-Amz-Credential=<YOUR_ACCESS_KEY_ID>/20160115/ap-northeast-2/s3/aws4_request&
&X-Amz-Date=20160115T000000Z
&X-Amz-Expires=86400
&X-Amz-SignedHeaders=host
&X-Amz-Signature=<SIGNATURE_VALUE>

그리고 URL에서 X-Amz-Credential 헤더의 값도 가독성을 위해서 “/”문자를 사용해서 표현하였습니다. 실제로는 %2F로 인코딩되어서 아래와 같이 사용되어야 합니다.

&X-Amz-Credential=<YOUR_ACCESS_KEY_ID>%2F20160115%2Fap-northeast-2%2Fs3%2Faws4_request

URL내에 인증 정보를 제공하기 위해, 다음과 같은 다양한 쿼리 매개변수들이 포함되어 있습니다.

매개변수 설명
X-Amz-Algorithm 서명 버전과 알고리즘을 식별하고, 서명을 계산하는데 사용. 서명 버전 4를 위해서 “AWS4-HMAC-SHA256” 로 설정
X-Amz-Credential 액세스 키 ID와 범위 정보(요청 날짜, 사용하는 리전, 서비스 명). 리전 명은 리전 및 엔드포인트에서 확인 가능
X-Amz-Date 날짜는 ISO 8601형식. 예: 20160115T000000Z
X-Amz-Expires 미리 선언된 URL이 유효한 시간 주기. 초단위. 정수 값. 최소 1에서 최대 604800 (7일) 예: 86400 (24시간)
X-Amz-SignedHeaders 서명을 계산하기 위해 사용되어지는 헤더 목록. HTTP host 헤더가 요구됨
X-Amz-Signature 요청을 인증하기 위한 서명

주의: X-Amz-Signature 헤더를 제외한 모든 쿼리 매개변수들은 표준 쿼리 문자열(Canonical Query String)에 포함시킵니다. 표준 헤더(Canonical Headers)는 HTTP host 헤더를 포함해야 합니다. 미리 사인된 URL을 만들 때 실제 페이로드에 대해 알 수 없기 때문에 표준 요청(Canonical Request)에 있는 페이로드 해시는 포함 안 시킵니다. 대신 “UNSIGNED-PAYLOAD” 문자열을 사용합니다.

이를 바탕으로 만든 완성된 스크립트는 아래와 같습니다. Bash 쉘 스크립트에 대한 블로그 포스팅이 아니기 때문에 bash 쉘 문구에 대해서는 따로 설명하지 않겠습니다.

#!/bin/bash
#
export PATH="/usr/local/ssl/bin:$PATH"
urlEncode() {
  LINE="$1"
  LENGTH="${#LINE}"
  I=0
  while [ $I -lt $LENGTH ]
    do
    C="${LINE:I:1}"
  case $C in
    [a-zA-Z0-9.~_-]) printf "$C" ;;
    *) printf '%%%02X' "'$C" ;;
  esac
    let I=I+1
  done
}

getHexaDecimalString() {
  read LINE
  LENGTH="${#LINE}"
  I=0
  while [ $I -lt $LENGTH ]
    do
    C="${LINE:I:1}"
   printf '%2x' "'$C"
   let I=I+1
  done
}

getSignatureKey() {
  SECRET_KEY=$1
  DATESTAMP=$2
  REGIONNAME=$3
  SERVICENAME=$4
  STRING_TO_SIGN=$5

  HEX_KEY=$(echo -n "AWS4${SECRET_KEY}" | getHexaDecimalString)
  HEX_KEY=$(echo -n "${DATESTAMP}" | openssl dgst -sha256 -mac HMAC -macopt hexkey:${HEX_KEY})
  HEX_KEY=$(echo -n "${REGIONNAME}" | openssl dgst -sha256 -mac HMAC -macopt hexkey:${HEX_KEY#* })
  HEX_KEY=$(echo -n "${SERVICENAME}" | openssl dgst -sha256 -mac HMAC -macopt hexkey:${HEX_KEY#* })
  SIGNING_KEY=$(echo -n "aws4_request" | openssl dgst -sha256 -mac HMAC -macopt hexkey:${HEX_KEY#* })

  SIGNATURE=$(echo -en "${STRING_TO_SIGN}" | openssl dgst -binary -hex -sha256 -mac HMAC -macopt hexkey:${SIGNING_KEY#* })
  echo "${SIGNATURE#* }"
} 

getHexaHash() {
  PAYLOAD="$@"
  HASH=$(echo -n "${PAYLOAD}" | openssl dgst -sha256)
  echo  "${HASH#* }"
}

### Main ###
if [ -z $AWS_DEFAULT_REGION ] || [ -z $AWS_SECRET_ACCESS_KEY ] || [ -z $AWS_ACCESS_KEY_ID ]
then
  echo "Please set $AWS_DEFAULT_REGION, $AWS_SECRET_ACCESS_KEY, and $AWS_ACCESS_KEY_ID environment variables"
exit 1
fi
SK="$AWS_SECRET_ACCESS_KEY"
AK="$AWS_ACCESS_KEY_ID"
REGION="$AWS_DEFAULT_REGION"

[ $# -ne 6 ] && exit 2
 
while getopts ":b:k:e:" OPT; do
  case $OPT in
        b)
         BUCKET=$OPTARG
         ;;
        k)
         S3KEY=$OPTARG
         ;;
        e)
         EXPIRES=$OPTARG
         ;;
       *)
   echo "Invalid option: -$OPTARG" >&2
   exit 3
   ;;
   esac
done

SERVICENAME="s3"
HOST="${BUCKET}.${SERVICENAME}.amazonaws.com"
ENDPOINT="http://${BUCKET}.${SERVICENAME}.amazonaws.com"

# step 1. Create a Canonical request
AMZ_DATE=$(date -u +%Y%m%dT%H%M%SZ)
DATESTAMP=$(date -u +%Y%m%d)
AMZ_EXPIRES=$((${EXPIRES}*60))   # minute -> second

HTTPMETHOD="GET"
CANONICAL_URI="/${S3KEY}"
#
CANONICAL_HEADERS="host:${HOST}\n"
SIGNED_HEADERS="host"
PAYLOAD_HASH="UNSIGNED-PAYLOAD"
#
ALGORITHM="AWS4-HMAC-SHA256"
CREDENTIAL_SCOPE="${DATESTAMP}/${REGION}/${SERVICENAME}/aws4_request"
#
CANONICAL_QUERYSTRING="X-Amz-Algorithm=${ALGORITHM}"
CANONICAL_QUERYSTRING="${CANONICAL_QUERYSTRING}&X-Amz-Credential=$(urlEncode "${AK}/${CREDENTIAL_SCOPE}")"
CANONICAL_QUERYSTRING="${CANONICAL_QUERYSTRING}&X-Amz-Date=${AMZ_DATE}"
CANONICAL_QUERYSTRING="${CANONICAL_QUERYSTRING}&X-Amz-Expires=${AMZ_EXPIRES}"
CANONICAL_QUERYSTRING="${CANONICAL_QUERYSTRING}&X-Amz-SignedHeaders=${SIGNED_HEADERS}"
CANONICAL_REQUEST="${HTTPMETHOD}\n${CANONICAL_URI}\n${CANONICAL_QUERYSTRING}\n${CANONICAL_HEADERS}\n${SIGNED_HEADERS}\n${PAYLOAD_HASH}"

# step 2. String To Sign
STRING_TO_SIGN="${ALGORITHM}\n${AMZ_DATE}\n${CREDENTIAL_SCOPE}\n$(getHexaHash "$(echo -e "${CANONICAL_REQUEST}")")"

# step 3. Signature
SIGNATURE="$(getSignatureKey $SK $DATESTAMP $REGION $SERVICENAME $STRING_TO_SIGN)"

# step 4.  Create a request URL
CANONICAL_QUERYSTRING="${CANONICAL_QUERYSTRING}&X-Amz-Signature=${SIGNATURE}"

echo "request_url = ${ENDPOINT}/${S3KEY}?${CANONICAL_QUERYSTRING}"

스크립트의 간결성을 유지하기 위해서 대부분의 에러 처리 루틴을 배제하였습니다. 따라서 범용적으로 사용하기 위해서는 적절한 에러 처리 루틴들이 추가되어야 하고 충분한 테스트를 거친 후 사용하시길 권장합니다.

아래는 이 스크립트를 이용해서 한 시간동안만 버킷 examplebucket에 포함된 오브젝트test.txt를 다른 사람에게 공유하기 위해 미리 사인된 URL을 만든 예입니다.

$ ./apis3.sh -b examplebucket -k test.txt -e 60
request_url = http://examplebucket.s3.amazonaws.com/test.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=<YOUR_ACCESS_KEY_ID>%2F20160115%2Fap-northeast-2%2Fs3%2Faws4_request&X-Amz-Date=20160115T130732Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=d0578b9fe721c9964765f2ab6bf6f8a1fc7c4966956785688b881783b661bdfd

이 URL은 생성된 시간부터 60분간 유효하며, 공유하고 싶은 임의의 사람에게 전달하면 됩니다. 그리고 공유된 링크를 클릭하거나 curl(1) 명령어로 실행하게 되면,  해당 API 호출 요청이Amazon S3 엔드포인트로 전달되고 적절히 처리됩니다.

아래는 curl(1) 를 이용해서 오브젝트를 성공적으로 다운로드한 예입니다.

$ curl -o "test.txt" "http://examplebucket.s3.amazonaws.com/test.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=<YOUR_ACCESS_KEY_ID>%2F20160115%2Fap-northeast-2%2Fs3%2Faws4_request&X-Amz-Date=20160115T130732Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=d0578b9fe721c9964765f2ab6bf6f8a1fc7c4966956785688b881783b661bdfd"
% Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
Dload  Upload   Total   Spent    Left  Speed
100  3619  100  3619    0     0   6305      0 --:--:-- --:--:-- --:--:--  6304

그리고 아래는 시간이 초과되어 다운로드가 실패한 예입니다.

$ curl -o "test.txt" "http://examplebucket.s3.amazonaws.com/test.txt?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=<YOUR_ACCESS_KEY_ID>%2F20160115%2Fap-northeast-2%2Fs3%2Faws4_request&X-Amz-Date=20160115T130732Z&X-Amz-Expires=3600&X-Amz-SignedHeaders=host&X-Amz-Signature=d0578b9fe721c9964765f2ab6bf6f8a1fc7c4966956785688b881783b661bdfd"
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Request has expired</Message><X-Amz-Expires>60</X-Amz-Expires><Expires>2016-01-15T140732:52Z</Expires><ServerTime>2016-01-18T20:13:55Z</ServerTime><RequestId>F865CB514FF4C92A</RequestId><HostId>f6Bv6Jtht91bSqt8OPsxirsrHZkWs7Qcc4kNYjZ2tJbPUmt8BW9Wv1hAUY2YFDKqSpEvFr8PLbI=</HostId></Error>

지금까지 총 2회의 포스팅을 통해서 AWS API 호출 요청을 어떻게 만들 수 있는지 살펴보았습니다. 특히 실전편에서 제공된 예는 많은 사용자들이 문의하신 내용이기도 합니다. 이번 글을 통해서 앞으로AWS API 호출을 활용하실 수 있고,  S3 오브젝트를 안전하게 공유하는데 조금이라도 도움이 되었으면 합니다.
본 글은 아마존웹서비스 코리아의 솔루션즈 아키텍트가 국내 고객을 위해 전해 드리는 AWS 활용 기술 팁을 보내드리는 코너로서, 이번 글은 박철수 솔루션즈 아키텍트께서 작성해주셨습니다.

AWS API 호출하기 (1) – 개론편

애플리케이션을 구동하기 위한 환경을 얻기까지 전통적인 데이터센터 환경에서 관리자는 거의 모든 작업을 수동으로 수행합니다. 관리자와 운영자는 서버, 스토리지 및 네트워크와 같은 인프라를 구성하고 운영체제와 필요한 프레임워크를 설치하여 애플리케이션을 구동할 수 있는 환경까지 제공하는데 상당한 시간을 소비합니다.

따라서 그 만큼 비즈니스의 시장 진입 시간은 길어질 수 밖에 없습니다. 하지만 클라우드 환경의 경우에는 네트워크가 가능한 곳이라면 장소나 시간에 구애 받지 않고 언제 어디서나 API 호출을 통해 수분내에 원하는 자원을 쉽게 얻을 수 있습니다.

AWS 클라우드에서 인프라 뿐만 아니라 보안, 데이터베이스, 분석, 배포 및 모니터링  등의 모든 IT 자원은 API 호출을 통해서 이용됩니다. API는 이렇게 모든 IT 자원을 코드로 제어할 수 있도록 만들었습니다. API를 호출한다는 것은 개발자에게는 그리 어렵고 생소한 일은 아니지만, 운영자나 관라자 그리고 일반 사용자 측면에서는 낯선 일입니다.

그래서, AWS는 사용자들의 편의를 위해 직접 API 호출을 하지 않고도 보다 쉽고 편하게 자원을 프로비저닝하거나 변경 및 관리할 수 있는 여러가지 도구들도 개발해서 함께 지원합니다. 서비스마다 잘 설계된 웹 기반의 관리 콘솔이나 명령줄 인터페이스가 대표적인 예이고, 심지어 개발자에게도 다양한 프로그래밍 언어를 위한 SDK까지 제공합니다. 이 모든 것은 내부적으로 기본 원재료에 해당하는 API를 호출하도록 설계되어 있습니다.

이처럼 직관적이고 편리한 많은 도구들이 제공되지만, 경우에 따라 AWS 클라우드에 HTTP/HTTPS 기반의 API호출 요청을 직접 보내야 하는 때도 있습니다.  아래와 같은 경우가 대표적인 예라고 생각됩니다:

  1. C와 같이 SDK를 제공하지 않는 프로그래밍 언어를 사용해야 하는 경우
  2. 신규로 제공되는 서비스와 기능들에 대해 SDK 지원이 아직 안 되는 경우
  3. AWS 자원에 보내진 요청이나 응답에 대해서, 보다 세부적이고 완벽하게 제어하고 싶은 경우

AWS클라우드로 API를 요청할 때, 모든 HTTP/HTTPS 요청은 메시지에 대한 무결성과 인증을 보장해야 합니다. 그래서 미리 서명 처리가 되어야 하고, 이런 서명처리는 아래와 같은 방법을 통해서 요청 메시지의 안정성을 보장합니다:

  1. 요청자 신원 확인: 요청자는 유효한 ‘액세스 키 ID’와 ‘비밀 액세스 키’를 가지고 있어야 합니다. (또는 AssumeRole이나 GetFederationToken과 같은 STS API 호출을 통해서 얻은 임시 보안 자격을 가지고도 요청할 수 있습니다.)
  2. 전송 중 데이터 보호: 전송 중 요청이 조작되는 것을 방지하기 위해서, 요청 구성 요소들 중 몇 가지는 요청에 대해 해시를 계산하는데 사용됩니다. 그리고 그 해시값은 요청의 일부로 포함됩니다. AWS가 해당 요청을 수신하면, 동일한 정보에 기초하여 해시를 계산하고 요청에 포함된 해시 값과 일치하는지 비교합니다. 만일 해시값이 일치하지 않으며, AWS는 해당 요청을 거절합니다.
  3. 잠재적인 재생 공격(replay attack) 방어: 모든 요청은 타임 스탬프를 기준으로 5분간만 유효하다고 인정되며, 그 기간이 지난 요청은 전부 거절됩니다.

이에 대한 전체적인 서명 과정을 요약하자면 아래 그림과 같습니다.

보안을 더 강화하기 위해서 HTTPS를 사용하여 요청을 전송할 수 있습니다. SSL은 암호화 전송을 하기 때문에, 요청과 응답 전송을 암호화해서 추가적으로 더 보호합니다. 하지만 AWS의 서비스들마다 지원하는 프로토콜이 다를 수 있습니다.  어떤 서비스는HTTP 또는 HTTPS만 지원하는 서비스가 있을 수 있고, 또 두 가지 프로토콜 모두를 지원하는 서비스도 있습니다. 지원하는 서비스와 프로토콜에 대한 자세한 사항은 여기를 클릭해보시면 확인 가능합니다.

AWS는 현재 서명 버전 (signature version) 2와 서명 버전 4 두 가지를 지원합니다. 대부분의 서비스는 버전2보다 버전 4를 더 지원합니다. 만일 서비스가 두 가지 서명 버전을 모두 지원한다면, 최신의 버전 4를 사용하는 것을 권장합니다. 서명 버전 2에 대한 사항은 이곳을 참조하시고, 서명 버전4에서 변경된 사항을 확인하시려면 여기를 확인해 보세요. 이 후 설명되는 모든 사항들은 서명 버전 4에 대한 내용입니다.

각 요청에 서명을 추가하는 방법은 아래 두 가지 방법 중 하나를 선택할 수 있습니다:

  1. HTTP 인증 헤더: HTTP 인증 헤더를 사용하여 서명을 추가합니다.
  2. 쿼리 문자열 매개변수: 서명을 쿼리 문자열 값으로 추가합니다. 요청 서명이 그 URL의 일부이기 때문에 이런 종류의 URL을 미리 서명된(pre-signed) URL이라고 지칭합니다.

아래는 예는 브라우저에서 서명정보 없이 AWS로 요청을 보낼 경우 어떻게 보이는지 보여주고 있습니다.

GET https://iam.amazonaws.com/?Action=ListUsers&Version=2010-05-08 HTTP/1.1
Content-Type: application/x-www-form-urlencoded; charset=utf-8
Host: iam.amazonaws.com
X-Amz-Date: 20150830T123600Z

이러한 요청은 HTTP 인증 헤더로 전송되었을 때와 쿼리 문자열 매개변수로 전송되어졌을 때 아래와 같이 달라질 수 있습니다.

HTTP 인증 헤더
사용자는 Authorization 헤더를 통해서 인증 정보를 추가할 수 있습니다. 비록 헤더 이름이 Authorization로 되어 있지만, 서명 정보를 담고 있는 헤더 값들은 실제로 해당 요청이 누구에서 왔는지 인증을 확립하기 위해서 사용됩니다.

Authorization 헤더는 아래 정보를 포함하고 있습니다:

  • 서명하기 위해 사용된 알고리즘 (예: AWS4-HMAC-SHA256)
  • 자격 범위 (예: 액세스 키 등)
  • 서명 헤더 목록
  • 계산된 서명

계산된 서명은 암호화되어 생성된 문자열입니다. 이 서명은 요청 정보에 기반하여 생성되며, AWS 비밀 액세스 키를 사용해서 서명을 생성합니다. 그리고 이 값은 요청을 수신한 AWS에서 사용자 신원을 확인하는데 이용됩니다.

아래 예는 앞에서 보셨던 요청에 서명 정보를 생성하고, 이를 Authorization 헤더에 추가할 경우 보여지는 내용입니다.

GET https://iam.amazonaws.com/?Action=ListUsers&Version=2010-05-08 HTTP/1.1
Authorization: AWS4-HMAC-SHA256 Credential=AKIDEXAMPLE/20150830/us-east-1/iam/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=5d672d79c15b13162d9279b0855cfba6789a8edb4c82c400e06b5924a6f2b5d7
content-type: application/x-www-form-urlencoded; charset=utf-8
host: iam.amazonaws.com
x-amz-date: 20150830T123600Z

쿼리 문자열 매개변수
요청 헤더에 인증정보를 추가하는 대신, 쿼리 문자열을 포함 할 수 있습니다. 쿼리 문자열은 서비스 이름과 액션, 날짜, 그리고 인증 정보를 위한 매개변수들 등 요청의 일부인 모든 것을 포함합니다.

아래 예는 쿼리 문자열에 액션과 인증 정보를 포함시켜서, GET 요청을 어떻게 구성하였는지 보여주고 있습니다

GET https://iam.amazonaws.com?Action=ListUsers&Version=2010-05-08&X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIDEXAMPLE%2F20150830%2Fus-east-1%2Fiam%2Faws4_request&X-Amz-Date=20150830T123600Z&X-Amz-Expires=60&X-Amz-SignedHeaders=content-type%3Bhost&X-Amz-Signature=37ac2f4fde00b0ac9bd9eadeb459b1bbee224158d66e7ae5fcadb70b2d181d02 HTTP/1.1
content-type: application/x-www-form-urlencoded; charset=utf-8
host: iam.amazonaws.com

많은 AWS 서비스들이 지원하는 쿼리API는 HTTP GET이나 POST를 사용해서 요청을 만들 수 있도록 해줍니다.  GET 요청은 쿼리 문자열을 매개변수로 전달하기 때문에, URL의 최대 길이 제한에 적용될 수 있습니다. 만일 IAM 정책을 업로드하거나 DynamoDB 요청을 위해 JSON 형태의 매개변수를 사용하는 것처럼 요청이 큰 페이로드(Payload)를 포함하고 있다면, 일반적으로 POST 요청을 사용하는 것을 권장합니다.

아래 절차는 HTTP/HTTPS 기반의 서명된 AWS API 요청을 어떻게 만드는지 간략하게 요약한 내용입니다:

  1. 표준 요청(Canonical Request)형식으로 내용들을 정렬하기 – 호스트, 액션, 헤더 등의 요청 내용을 정렬하여 표준 형식으로 만듭니다. 이 표준 요청은 아래 서명하기 위한 문자열을 만들기 위해 사용됩니다. 구체적은 정보는 이곳에서 확인하실 수 있습니다.
  2. 서명하기 위한 문자열(StringToSign) 만들기 – 알고리즘, 요청 날짜, 자격 범위 및 앞서 생성한 표준 요청의 해시 정보를 가지고 서명하기 위한 문자열을 만듭니다. 구체적인 내용은 이곳에서 확인하실 수 있습니다.
  3. AWS 서명 버전 4(Signature) 계산하기 – AWS 비밀 액세스 키뿐만 아니라 요청 날짜, 리전, 그리고 서비스이름을 가지고 연속적인 해시 키잉 동작을 행함으로써 서명 키를 유도합니다. 그리고 이 서명 키와 서명하기 위한 문자열을 이용해서 서명을 만듭니다. 구체적인 정보는 이곳에서 확인하실 수 있습니다.
  4. 생성한 서명 정보를 HTTP/HTTPS API 요청에 추가하기 – 서명을 계산한 후, 그것을 헤더나 요청 쿼리 문자열에 추가합니다. 구체적인 정보는 이곳에서 확인하실 수 있습니다.

이렇게 생성된 URL을 해당 AWS 서비스의 엔드포인트에 보내는 것이 API 호출입니다. 리전별 각 서비스의 엔드포인트는 이곳에서 확인 가능합니다.

이번 블로그에서는 AWS API 호출 요청에 대한 기본 정보와 어떻게 만드는지 전반적인 골격을 확인하였습니다. 다음 회에서는 이를 바탕으로 실제 HTTP/HTTPS API 호출 요청을 직접 생성해 보겠습니다.

AWS API 호출 하기 (2) – Amazon S3 객체에 대한 미리 선언된(pre-signed) URL 생성하기

본 글은 아마존웹서비스 코리아의 솔루션즈 아키텍트가 국내 고객을 위해 전해 드리는 AWS 활용 기술 팁을 보내드리는 코너로서, 이번 글은 박철수 솔루션즈 아키텍트께서 작성해주셨습니다.

Amazon CloudWatch 맞춤형 지표 생성하기

Amazon CloudWatch는 AWS 클라우드 리소스와 AWS에서 실행되는 어플리케이션을 위한 모니터링 서비스입니다. 게임 개발자나 시스템 운영자가 서비스를 관리하기 위해서는 필수적으로 CloudWatch를 사용해서 여러 서비스나 어플리케이션의 지표(metric)를 확인해야 합니다.

CloudWatch는 사용자의 편의를 위해서 전체 AWS 서비스에 대해 총 300개가 넘는 기본(Built-in) 지표를 제공합니다. 예를 들어, EC2나 RDS의 CPU 사용률이나 네트워크 트리팩 인/아웃,  ELB의 지연시간(Latency) 등이 대표적인 기본 지표입니다.

일반적인 시스템 모니터링은 기본 지표로 충분합니다만 메모리나 각 마운트된 디스크에 대한 사용률을 확인하려고 할 때는 맞춤형 지표(Custom Metric)를 생성해야 합니다.

맞춤형 지표 만들기
맞춤형 지표란 모니터링하고자 하는 통계치를 여러분이 선정해서 CloudWatch로 보내 관리하는 지표를 말합니다. 맞춤형 지표를 CloudWatch로 보내는 것은 매우 간단합니다. CLI를 사용해서 여러분이 정의한 통계치를 보낼 수 있습니다.

$ aws cloudwatch put-metric-data --metric-name PageViewCount --namespace "MyService" --value 2 --timestamp 2016-01-15T12:00:00.000Z

put-metric-data 명령을 사용해서 원하는 값을 원하는 지표 이름으로 지정해서 보낼 수 있습니다. 위 명령은 “MyService”라는 새로운 서비스명(네임스페이스)으로 지표 이름은 “PageViewCount”로 2의 값을 보내는 명령입니다.

물론 이렇게 명령을 수행하기 위해서는 EC2인스턴스에 CloudWatch에 대한 접근 권한이 있는 역할(Role)이 할당되었거나 aws configure 명령을 사용해서 접근키(access key)와 비밀키(secret key)를 설정해 주어야 합니다.

맞춤형 지표를 퍼블리싱하는 것은 다음 문서에 매우 상세히 설명되어 있습니다.
http://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/DeveloperGuide/publishingMetrics.html

맞춤형 메트릭을 등록하면 CloudWatch 콘솔의 좌측 메뉴 화면 하단에 드롭다운 박스가 생성되면서 본인이 등록한 서비스 명을 확인해 볼 수 있습니다.

Amazon CloudWatch의 차원(dimensions)
CloudWatch에는 차원(dimensions)이라는 개념이 있으며, 이는 데이터를 구분하기 위한 기준을 말합니다. 예를 들어, 아래와 같이 데이터를 보냈다고 가정합시다.

$ aws cloudwatch put-metric-data --metric-name "FileSystem Utilization" --namespace "OurService" --value 16 --unit Percent --dimensions FileSystem="dev/xvda1" --timestamp 2016-01-12T12:00:00.000Z

이렇게 보낸 경우에는 CloudWatch 콘솔에서는 아래와 같은 FileSystem에 대한 차원 정보가 화면이 나오게 됩니다.

만약 여기에 차원을 다음과 같이 해서 추가해 봅니다.

--dimensions FileSystem="dev/xvda1",HostId="ami-249b554a",MountPath="/"

이제 기존 차원에 더해 새로운 차원이 등록 됩니다. 맞춤형 지표에 대해 데이터를 보는 새로운 뷰가 추가된 것을 확인할 수 있습니다.

메모리와 디스크에 대한 지표 등록

이제 리눅스 계열의 OS를 대상으로 메모리와 디스크에 대한 지표를 새로 작성해 보도록 하겠습니다. AWS 문서 중에 이를 수행하기 위한 Perl 스크립트 사용법이 소개되어 있는데 다음 링크에서 볼 수 있습니다.

http://docs.aws.amazon.com/ko_kr/AmazonCloudWatch/latest/DeveloperGuide/mon-scripts.html

위의 Perl 스트립트를 이용해서 메모리와 디스크에 대한 맞춤 지표를 등록할 수 있습니다. 그런데 이 스크립트는 오직 예제로 기술 지원은 제공하지 않습니다. 많은 시스템에서 대부분 제대로 동작하지만,  혹시라도 동작을 하지 않는다면 Perl 스트립트를 수정하면서 적용하는 것은 쉬운 일이 아닙니다.

이를 해결할 간단한 방법 중의 하나가 쉘 스크립트를 이용해서 커스텀 지표를 등록하는 방법입니다. 이 글을 위한 블로그를 위한 커스텀 지표 등록 쉘 스크립트는 아래에서 다운로드 받으실 수 있습니다.

http://awsblogskr.s3-ap-northeast-2.amazonaws.com/articles/2016-01-cloudwatch-seonyong/custom_metric2.sh

이제 이 스크립트에 대해 처음 부터 살펴보겠습니다. 먼저 타임스탬프 값을 얻어오기 위해서 다음과 같은 쉘 스크립트 함수를 정의합니다.

get_time_stamp() {
	time_stamp=$(date -u +%Y-%m-%dT%R:%S.000Z)
	echo "$time_stamp"
}

타입스탬프는 UTF를 기준으로 하기 때문에 –u 옵션을 사용해서 생성합니다. 이 타임스탬프 값은 커스텀 지표를 보낼 때의 타임스탬프 값으로 사용합니다.

다음은 인스턴스의 아이디를 가져오는 함수이다.

get_instance_id() {
	instance_id=$(curl http://169.254.169.254/latest/meta-data/ami-id)
	echo $instance_id
}

여기서 특이한 점은 curl 명령을 사용해서 아이디를 얻어옵니다. 169.254.169.254 주소는 Amazon EC2 인스턴스 내에서 해당 인스턴스의 메타 정보를 가져오는 주소값입니다.

메타정보나 유저정보를 가져올 수 있는 내용에 대해서는 다음 문서에 잘 설명되어 있다.
http://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/ec2-instance-metadata.html#instancedata-data-retrieval

리눅스 계열의 서버에서 메모리 정보를 가져오는 방법은 여러가지가 있습니다. top, free, vmstat 등 다양하지만 여기서는 /proc/meminfo 파일 정보를 읽어와서 awk로 가공하는 방법을 사용합니다.

free_mem_ratio=$(awk '/MemTotal:/{total=$2} \
       /MemFree:/{free=$2} \
       END{ \
        print (free*100/total); \
       }' /proc/meminfo 

위 코드는 파일을 읽어와서 MemTotal, MemFree정보를 이용해서 자유 메모리의 비율을 계산하는 부분입니다.

디스크의 경우에는 df –h 명령을 이용합니다. 명령의 출력은 시스템 마다 다양한데, 보려고 하는 값들을 탭으로 구분된 문자열로 생성합니다.

declare -a fs_list=$(df -h | awk '$1 ~ /^ *\/dev\//{print $1, "\t", $2, "\t", $3, "\t", $4, "\t", $5, "\t", $6}')

기준은 /dev/로 시작하는 문자열만을 뽑아서, 원하는 지표를 탭 공백이 있는 하나의 문자열로 만듭니다. 물론 /dev/로 시작하는 볼륨이 여럿 있을 수 있으므로 fs_list는 배열로 정의합니다.

이후에 한 문자열에서 원하는 탭 구분 정보를 루프를 돌면서 추출합니다.  이때 G, %같은 문자는 sed를 이용해서 제거합니다.

fs=$(echo $f_info       | sed 's/[G%]//g' | awk '{ print $1}' )

이렇게 만들어진 정보(여기서는 파일시스템, 전체 크기, 사용 중 크기, 사용 가능 크기,  마운트 포인트)를 변수에 담아 CLI를 통해 CloudWatch로 전달합니다.

$ aws cloudwatch put-metric-data --metric-name "Filesystem Utilization" --namespace "OurService" --value $fs_util  --unit Percent --dimensions FileSystem=$fs,HostId=$instance_id,MountPath=$fs_mount --timestamp $time_stamp

시스템에 따라 변경 필요가 있는 부분은 아래 두 부분입니다.

declare -a fs_list=$(df -h | awk '$1 ~ /^ *\/dev\//{print $1, "\t", $2, "\t", $3, "\t", $4, "\t", $5, "\t", $6}')
sed 's/[G%]//g'

출력되는 정보의 위치나 제거해야 할 문자 등이 시스템마다 조금씩 다를 수 있는데, 이는 약간의 주의만 기울이면 쉽게 바꿀 수 있습니다.

이제 쉘 스크립트를 crontab에 등록하면 쉽게 자동화 할 수 있습니다. 다음은 본 예제를 crontab으로 설정 한 것이다. 1분에 한번씩 커스텀 지표를 등록합니다.

$ crontab –e
*/1 * * * * /etc/cronjob/custom_metric2.sh

마지막으로 맞춤형 지표를 등록하는 CLI 명령이나, EC2에 대한 조작을 하는 CLI는 모두 계정별로 일정 정도 성능 제한이 설정되어 있습니다. 따라서 특정 시점에 한꺼번에 요청을 하면 명령이 수행이 안될 가능성이 있습니다. 각 요청은 가능한 동시가 아니라 분산되어 수행되도록 하는 것이 바람직합니다.

이와 관련한 참고 문서는 다음과 같습니다.

http://docs.aws.amazon.com/ko_kr/AWSEC2/latest/APIReference/query-api-troubleshooting.html#api-request-rate

맞춤형 지표는 서비스 모니터링을 강화시키는 효율적인 도구입니다. 가능한 CLI와 연계해서 메트릭을 자동화하는 것이 바람직합니다.

본 글은 아마존웹서비스 코리아의 솔루션즈 아키텍트가 국내 고객을 위해 전해 드리는 AWS 활용 기술 팁을 보내드리는 코너로서, 이번 글은 박선용 솔루션즈 아키텍트께서 작성해주셨습니다.

AWS Lambda와 Slack을 이용한 DevOps Chatroom 구현하기

Slack이 제공하는 협업을 위한 채팅을 통해 DevOps팀에서 실제 운영이나 서로 의견이나 정보를 다양한 플랫폼에서 동시에 주고 받을 수 있습니다. 예를 들어, 스마트폰 앱을 이용하거나 맥에서는 클라이언트 도구도 제공하고 있습니다. 메시지를 다양한 형태로 전달할 수 있는 Amazon SNS(Simple Notification Service)를 통해 이벤트를 발생시키고, AWS Lambda 는 SNS를 통해 전달된 메시지를 이벤트 트리거(Event trigger)를 통해 원하는 코드를 직접 수행 할 수 있습니다.

Slack은 API를 통해 메시지를 보낼 수 있는 방법을 제공하고 있습니다. AWS Lambda에서 알림을 받아 Slack 대화 채널로 메시지를 전달할 수 있습니다. 이에 관한 간략한 소개는 ChatOps를 위한 AWS Lambda를 통한 Slack 통합 샘플 코드에서 제공하고 있습니다. 이번 글에서는 좀 더 상세하게 해당 기능을 소개하여 쉽게 구성할 수 있도록 도움을 드리고자합니다.

1. AWS Elastic Beanstalk로 웹 서비스 구성하기
AWS Elastic Beanstalk을 사용하면 아주 쉽게 웹 서비스를 바로 만들 수 있습니다. 또한, ELB(Elastic Load Balancing)과 RDS(Relational Database Service)를 같이 생성해 주며, Auto Scaling Group도 자동으로 생성하여 트래픽을 분산하고 스케일링을 자동화 할 수 있습니다. Auto Scaling을 위한 Policy 역시 생성되며, 확장을 위한 조건 및 정책 변경이 가능합니다.

Beanstalk은 로컬에서 개발한 코드를 AWS 환경에 바로 배포가 가능합니다. 로컬에서 Git을 이용하여 개발 후 EB CLI(Elastic Beanstalk CLI)를 통해 쉽게 업로드하여 배포할 수 있습니다. 로컬 환경에 EB CLI를 설치하고 웹서비스는 Github awslabs에 있는 Node.js로 만들어진 예제를 사용하겠습니다.

원하는 폴더를 생성 후 Github에서 예제를 다운로드합니다.

$ git clone https://github.com/awslabs/eb-node-express-sample.git
Cloning into 'eb-node-express-sample'...
remote: Counting objects: 56, done.
remote: Total 56 (delta 0), reused 0 (delta 0), pack-reused 56
Unpacking objects: 100% (56/56), done.
Checking connectivity... done.

Git사용을 위한 초기화를 진행합니다.

$ git init .
Reinitialized existing Git repository in /Users/ilho/Github/ebsample1/ebsample2/eb-node-express-sample/.git/

EB CLI를 설정하면 $ eb라는 명령을 통해 Elastic Beanstalk을 로컬 환경에서 구성하여 사용할 수 있습니다. 처음에 개발하는 폴더를 Root로 지정하고 Beanstalk 환경에 대한 설정을 진행합니다. eb init이란 명령으로 수행합니다. Beanstalk을 어느 Region에 생성할지부터 서비스 이름 등 기본적인 설정을 진행합니다. 현재 AWS Lambda가 도쿄 리전에서 지원하고 있기 이를 활용하기 위해 Elastic Beanstalk을 도쿄 리전에서 시작해 보겠습니다.

AWS Elastic Beanstalk은 Node.js외에도 Java, .NET, PHP, Python, Ruby, Go, Docker를 모두 지원합니다.

a0999b0edcf5:eb-node-express-sample ilho$ eb init
Select a default region
1) us-east-1 : US East (N. Virginia)
2) us-west-1 : US West (N. California)
3) us-west-2 : US West (Oregon)
4) eu-west-1 : EU (Ireland)
5) eu-central-1 : EU (Frankfurt)
6) ap-southeast-1 : Asia Pacific (Singapore)
7) ap-southeast-2 : Asia Pacific (Sydney)
8) ap-northeast-1 : Asia Pacific (Tokyo)
9) ap-northeast-2 : Asia Pacific (Seoul)
10) sa-east-1 : South America (Sao Paulo)
11) cn-north-1 : China (Beijing)
(default is 3): 8

Select an application to use
1) MyNewTest
2) ebsample1
3) [ Create new Application ]
(default is 3): 3

Enter Application Name
(default is "eb-node-express-sample"): ebsample2
Application ebsample2 has been created.
 
It appears you are using Node.js. Is this correct?
(y/n): y
Do you want to set up SSH for your instances?
(y/n): y
 
Select a keypair.
1) example_key1
2) example_key2
3) example_key3
4) example_key4
5) [ Create new KeyPair ]
(default is 5): 4

Beanstalk Application을 AWS 콘솔을 통해서도 만들 수 있지만, EB 명령을 이용하여 로컬에서 바로 생성을 시킬 수 있습니다. Eb create 명령을 사용하여 Beanstalk 환경을 구성합니다. 아래처럼 필요한 환경을 구성하면서 만들어지는 내용을 확인할 수 있습니다. 명령을 실행하여 AWS 콘솔에서 환경이 구성되는 것을 확인할 수도 있습니다. 환경이 구성 중에는 회색으로 표기되며 모두 정상적으로 만들어지면 녹색으로 변경되어 상태를 구분할 수도 있습니다.

$ eb create web2-env
WARNING: You have uncommitted changes.
Creating application version archive "app-5529-160121_085131".
Uploading ebsample2/app-5529-160121_085131.zip to S3. This may take a while.
Upload Complete.
Environment details for: web2-env
Application name: ebsample2
Region: ap-northeast-1
Deployed Version: app-5529-160121_085131
Environment ID: e-immiw7zwnk
Platform: 64bit Amazon Linux 2015.09 v2.0.6 running Node.js
Tier: WebServer-Standard
CNAME: UNKNOWN
Updated: 2016-01-20 23:51:35.207000+00:00
Printing Status:
INFO: createEnvironment is starting.
INFO: Using elasticbeanstalk-ap-northeast-1-1234567890 as Amazon S3 storage bucket for environment data.
INFO: Created load balancer named: awseb-e-i-AWSEBLoa-5F13U6NNRGJT
INFO: Environment health has transitioned to Pending. There are no instances.
INFO: Created security group named: awseb-e-immiw7zwnk-stack-AWSEBSecurityGroup-59FO03AWS48X
INFO: Created Auto Scaling launch configuration named: awseb-e-immiw7zwnk-stack-AWSEBAutoScalingLaunchConfiguration-42NJ3UCM61ZD
INFO: Added instance [i-00952c8f] to your environment.
INFO: Created Auto Scaling group named: awseb-e-immiw7zwnk-stack-AWSEBAutoScalingGroup-1QP37B57TQ43O
INFO: Waiting for EC2 instances to launch. This may take a few minutes.
INFO: Created Auto Scaling group policy named: arn:aws:autoscaling:ap-northeast-1:1234567890:scalingPolicy:6b7c0afe-3c1e-436d-a2e0-fcbc96d9c3c2:autoScalingGroupName/awseb-e-immiw7zwnk-stack-AWSEBAutoScalingGroup-1QP37B57TQ43O:policyName/awseb-e-immiw7zwnk-stack-AWSEBAutoScalingScaleUpPolicy-6FX2ZY0A9VIG
INFO: Created Auto Scaling group policy named: arn:aws:autoscaling:ap-northeast-1:1234567890:scalingPolicy:e8e7a4c3-af2f-4557-98e2-2dc472470f2e:autoScalingGroupName/awseb-e-immiw7zwnk-stack-AWSEBAutoScalingGroup-1QP37B57TQ43O:policyName/awseb-e-immiw7zwnk-stack-AWSEBAutoScalingScaleDownPolicy-1RY0SZO4CF9VP
INFO: Created CloudWatch alarm named: awseb-e-immiw7zwnk-stack-AWSEBCloudwatchAlarmHigh-10PTC4TZJA6XR
INFO: Created CloudWatch alarm named: awseb-e-immiw7zwnk-stack-AWSEBCloudwatchAlarmLow-1485FJORPZ9R3
INFO: Environment health has transitioned from Pending to Ok.
INFO: Successfully launched environment: web2-env

eb 명령어를 이용하면 바로 브라우져를 통해 Beanstalk으로 구성된 웹페이지를 열어볼 수 있습니다.

$ eb open

2. CloudWatch Alarm에 Notification 추가하기
Elastic Beanstalk은 Auto Scaling Group, CloudWatch Alarm, ScalingPolicy, SNS를 모두 구성해 줍니다. 자동으로 만들어진 SNS Topic을 이용하여 Lambda 함수와 연계되도록 구성을 할 수도 있고, 별도의 SNS Topic을 구성하여 Lambda 함수와 연계할 수도 있습니다.

CloudWatch 메뉴로 이동하여 자동으로 생성된 CloudWatch Alarm을 찾아 알람이 발생하면 SNS로 Notification을 전달 할 수 있도록 추가합니다.

기본으로 CPUUtilization을 모니터링하여 알람이 발생하도록 구성되어 있습니다. 스케일인-아웃(Scaling-in/out)을 위한 두 개의 알람이 생성되어 있으며, 해당 알람을 선택하여 Modify를 선택하고 Notification을 아래와 같이 추가합니다.

3. AWS Lambda에 Slack메시지 전송 함수 생성하기
Lambda에서는 Slack을 위한 함수가 예제로 추가되어 있습니다. 아래와 같이 slack으로 검색하면 Node.js와 Python 을 지원하는 Slack-echo-command, cloudwatch-alarm-to-slack 함수가 있습니다. 여기서는 Node.js를 사용하도록 하겠습니다.

cloudwatch-alarm-to-slack을 선택 후 Event Source로 앞에서 확인한 SNS Topic을 선택합니다. 해당 SNS Topic에 메시지가 전달되면 Lambda 함수가 자동으로 실행됩니다. 다음으로 제공하는 코드의 내용을 원하는 Slack 채팅 그룹, 채널에 메시지를 전달하기 위한 내용이 Comment에 설명되어 있습니다. 우선 Slack Incoming WebHooks 을 사용하여 메시지를 전달할 수 있도록 정보를 확인합니다.

  1. https://<your-team-domain>.slack.com/services/new로 이동합니다.
  2. “Incoming WebHooks”을 검색하여 채팅 그룹와 채널을 선택하고, 추가합니다.
  3. “Webhook URL” 을 확인하고 노트합니다.

Webhook URL이 노출되지 않도록 AWS KMS(Key Management Service)를 이용하여 Webhook URL을 암호화합니다. 별도의 암호화 관리를 하지 않고 쉽게 사용할 수 있는 서비스입니다. AWS CLI를 통해 직접 콘솔을 통하지 않고도 키 생성이 가능합니다.

1) AWS CLI로 KMS에 Key를 생성합니다. 이 예제에서는 Tokyo Region의 KMS에 키를 생성합니다.

$ aws kms create-key --region ap-northeast-1
{
"KeyMetadata": {
"KeyId": " xxxxxx-xxxx-xxx-xxxx-xxxxxxxx ",
"Description": "",
"Enabled": true,
"KeyUsage": "ENCRYPT_DECRYPT",
"KeyState": "Enabled",
"CreationDate": 1453342025.031,
"Arn": "arn:aws:kms:ap-northeast-1:1234567890:key/xxxxxx-xxxx-xxx-xxxx-xxxxxxxx",
"AWSAccountId": "123456789"
}
}

2) Key 사용이 쉽도록 Alias를 생성합니다. 이 예제에서는 SlackKey라는 이름으로 타겟 키를 지정하여 Alias를 생성합니다.

$ aws kms create-alias --alias-name "alias/SlackKey" --target-key-id " xxxxxx-xxxx-xxx-xxxx-xxxxxxxx " --region ap-northeast-1

3) WebHook URL을 생성한 키와 AWS CLI를 이용하여 암호화합니다. URL은 프로토콜 부분은 제외하고 입력합니다.

$ aws kms encrypt --key-id alias/SlackKey --plaintext "hooks.slack.com/services/abcdefghijklmnopqrstuvwxyz" --region ap-northeast-1
{
"KeyId": "arn:aws:kms:ap-northeast-1:1234567890:key/ xxxxxx-xxxx-xxx-xxxx-xxxxxxxx ",
"CiphertextBlob": "AbcdfghijksN8ta1n/abdefjiowl/x5RwtKZGSctHgnMVKeNo2xZjoAAACnMIGkBgkqhkiG9abcdefghijklmnb3DQEHATAeBglghkgBZQMEAS4wEQQMPWtiU2OmhyBJ9/swAgEQgGCZJ7fabcdefghijklmnUt6ltc1avMiWQawdgW9tj8Xv3drF7savCoL0oVDzRYRabcdefghijklmncIjX4LdXbAIg6nNWcF2JEa4v9Ze9WWNA9yrzJmmNs="
}

4) 암호화되어 생성된 WebHook URL을 Lambda코드의 kmsEncryptHookUrl 변수에 입력합니다. 입력할 Slack 채널명도 slackChannel 변수에 입력합니다.

var AWS = require('aws-sdk');
var url = require('url');
var https = require('https');
var hookUrl, kmsEncyptedHookUrl, slackChannel;

kmsEncyptedHookUrl = 'AbcdfghijksN8ta1n/abdefjiowl/x5RwtKZGSctHgnMVKeNo2xZjoAAACnMIGkBgkqhkiG9abcdefghijklmnb3DQEHATAeBglghkgBZQMEAS4wEQQMPWtiU2OmhyBJ9/swAgEQgGCZJ7fabcdefghijklmnUt6ltc1avMiWQawdgW9tj8Xv3drF7savCoL0oVDzRYRabcdefghijklmncIjX4LdXbAIg6nNWcF2JEa4v9Ze9WWNA9yrzJmmNs="';  // Enter the base-64 encoded, encrypted key (CiphertextBlob)
slackChannel = '#general';  // Enter the Slack channel to send a message to

5) Lambda 함수가 KMS를 사용하여 URL Decryption을 해야하므로 함수가 KMS를 사용할 수 있는 권한이 필요합니다. Lambda 함수가 사용할 Role에 KMS의 Decrypt API 접근 허용을 추가합니다. 아래 예제는 lambda_basic_execution role의 Policy에 추가한 화면입니다.

6) Lambda 함수에 lambda_basic_execution role을 지정하고 함수를 생성합니다.

7) Lambda Event Source의 처음 설정은 Disabled 이므로 Enabled로 변경합니다.

4. Slack 대화방에서 메시지 확인하기
Beanstalk에서 만든 사이트는 현재 트래픽이 없으므로, CPUUtilization이 낮아 Low CPU Alarm이 생성되어 메시지가 전달되게 됩니다. 아래와 같이 Slack 대화방에 해당 Alarm이 전달된 것을 확인할 수 있습니다.

Beanstalk을 활용하여 아주 간단히 웹서비스를 만들고 CloudWatch 알람 이벤트를 소스로 Lambda 함수를 활용하여 Slack 서비스에 메시지를 자동으로 포스팅하는 서비스를 상세히 구현해 보았습니다. Ops 혹은 DevOps팀에서 AWS의 여러 상태 정보나 메시지를 받아서 활용할 수 있습니다. Slack에서는 메시지의 포맷을 변경하거나 할 수 있는 여러가지 예제를 제공하고 있어 보아 다양한 메시지 구현이 가능합니다.

본 글은 아마존웹서비스 코리아의 솔루션즈 아키텍트가 국내 고객을 위해 전해 드리는 AWS 활용 기술 팁을 보내드리는 코너로서, 이번 글은 김일호 솔루션즈 아키텍트께서 작성해주셨습니다.

2015년 AWS 한국 콘텐츠 결산!

지난 한해 즐겁고 유익하게 보내셨나요? 아마존웹서비스 역시 한국 블로그를 개설하고, 다양한 소셜 채널로 고객 및 개발자 여러분들과 소통할 수 있었습니다. 한 해를 마무리하면서 많은 분들이 사랑해 주신 콘텐츠를 공유해 드릴까 합니다.

먼저 2015년 한해 동안 AWS Korea 슬라이드 쉐어 계정에 올라온 100여개의 슬라이드 중 가장 많은 분들이 본 “Top 10 AWS 발표 자료”를 공유합니다!

  1. AWS와 함께 확장성 높은 천만 사용자 웹 서비스 만들기
  2. 알파 유저를 위한 AWS 스터디 시리즈
  3. 넥슨 – AWS에서 실시간 멀티플레이 게임 구현하기
  4. 모바일 및 IoT 환경을 위한 AWS 클라우드 플랫폼의 진화
  5. 메가존 – 국내 사례로 본 클라우드 운영 최적화
  6. 메가마트 – 국내 엔터프라이즈 클라우드 도입 구축사례 및 고려사항
  7. 국민내비 김기사, AWS 하이브리드 환경 구축사례
  8. AWS에 대해 궁금했던 10가지 질문들
  9. IGAWorks – 혼자서 2주일만에 AWS로 서비스 론칭하기
  10. 스마트스터디 – CloudFront와 S3를 이용한 컨텐츠 배포 전략

2015년 정리 2탄! 올 한해 AWS 한국 블로그에서 가장 많은 분들이 읽어 주신 “Top 10 AWS 뉴스”를 공유합니다!

  1. AWS가 한국에 리전을 설립합니다!
  2. AWS Device Farm – 실제 기기로 모바일 앱 테스트하기
  3. AWS 한국 블로그를 시작합니다.
  4. EC2 업데이트- T2.Nano 인스턴스 타입 출시
  5. AWS Unity SDK 로 간단한 게임 구현하기
  6. Amazon Aurora 정식 출시
  7. Amazon EMR, Apache Spark 지원 시작
  8. AWS IoT – 사물 인터넷을 위한 클라우드 서비스
  9. 한국 AWS 클라우드 에반젤리스트 활동
  10. AWS SDK for Go 1.0 정식 출시

■ 주요 정보 모음

■ 유튜브 동영상 채널

내년에도 한국 블로그는 더 유익하고 알찬 정보로 찾아뵙겠습니다. 한해 잘 마무리하시고, 내년에도 AWS 클라우드와 성공하는 비지니스가 되기를 기원합니다.

새해 복 많이 받으세요.

AWS CLI를 사용한 리전간 DB 파라미터 그룹 복사하기

Amazon Relational Database Service (RDS) 는 클라우드에서 관계형 데이터베이스를 손쉽게 설정, 운영 및 확장할 수 있는 관리형 서비스입니다. RDS를 사용하면 데이터베이스 패치 작업, 백업, 특정 시점으로의 복원 등의 복잡한 관리 절차를 자동화 할 수 있습니다.

AWS에서 글로벌 서비스를 진행할 때, 하나의 리전(Region)에서 운영 중인 서비스를  전 세계로 확장하기 위해 데이터베이스를 다른 리전으로 복사해야 하는 경우가 있습니다. 이때 스냅샷(Snapshot)을 생성하여 대상 리전에 복사 후 해당 스냅샷으로부터 새로운 데이터베이스 인스턴스를 만들면 글로벌 서비스가 가능합니다.

RDS의 Snapshot을 다른 리전으로 옮긴 후, 복원하여 사용하시기 위해서는 몇 가지 사전 작업이 필요합니다.

  • 보안 그룹 (Security Groups)생성
  • DB 옵션 그룹 생성
  • DB 서브넷 그룹 생성
  • DB 파라미터 그룹 생성

위의 정보들은 특정 리전에만 국한된 것이기에, 복사하려는 대상 리전에 미리 생성하여 준비 시켜두어야 합니다.

특히, 이중에 기존에 운영 중인 서비스와 동일한 환경과 성능을 보장하기 위해서는 파라미터 그룹을 일치화 시켜야 합니다. 대상이 MySQL의 경우에는 콘솔에서 설정할 수 있는 파라미터들이 300여개에 달하기에 이를 하나하나 비교해가며 수동으로 작업하는 것은 쉽지 않습니다.

(이 글이 작성되는 시점에는 아직 리전간 파라미터 그룹 복사 기능이 지원되지 않으므로) AWS Command-Line Interface(CLI)를 활용하여 다른 리전에서 복사한 스냅샷으로부터 데이터베이스를 생성 후 기존에 사용 중이던 파라미터 그룹과 일치화 시키는 방법에 대해서 알아보고자 합니다.

참고로 한번의 명령으로 최대 20개의 파라미터 값만 변경 가능합니다. 따라서, 설명의 편의를 위해 20개 이하의 파라미터 값 변경을 기준으로 진행하도록 하겠습니다. 20개 이상의 파라미터 값 변경은 반복 실행하는 스크립트 작성을 통해 가능합니다.

1. 환경 설정
우리는 AWS CLI를 활용한 DB 파라미터 그룹 복사 방법을 확인 하기 위해 동경(ap-northeast-1) 리전의 RDS에서 파라미터 그룹을 ‘src-pg’ 라는 이름으로 생성한 뒤 다음과 같이 파라미터를 수정하도록 하겠습니다.

Parameter src-pg default.mysql5.6
innodb_flush_log_at_trx_commit 0 <engine-default>
slow_query_log 1 <engine-default>
innodb_support_xa 0 <engine-default>
long_query_time 60 <engine-default>
character_set_server utf8 <engine-default>

2. 복사 대상 DB 파라미터 그룹 정보 확인
우리의 아이디어는 describe-db-parameters를 통해 파라미터 그룹의 정보를 출력 후, 대상 리전의 RDS에서 생성한 파라미터 그룹에 앞서 출력한 원본 파라미터 그룹의 정보를 modify-db-parameter-group를 통하여 업데이트 하는 것입니다.

수정된 파라미터 중 하나를 선택하여 어떠한 포맷과 형태로 정보들이 출력 되는지 확인 해 봅니다.

$ aws rds describe-db-parameters --db-parameter-group-name src-pg --query "Parameters [? ParameterName == 'long_query_time']"

결과는 JSON 포맷으로 다음과 같이 나옵니다.

[
    {
        "Description": "Defines what MySQL considers long queries",
        "DataType": "float",
        "IsModifiable": true,
        "AllowedValues": "0-31536000",
        "Source": "user",
        "ParameterValue": "60",
        "ParameterName": "long_query_time",
        "ApplyType": "dynamic"
    }
]

파라미터 정보들을 업데이트 하기 위해서는 modify-db-parameter-group명령을 사용합니다. 이 때 --generate-cli-skeleton 옵션을 주게 되면 업데이트를 위해 입력하여야 하는 데이터의 구조를 확인할 수 있습니다.

$ aws rds modify-db-parameter-group --generate-cli-skeleton

결과는 아래와 같이 파라미터를 업데이트 하기 위한 기본 구조가 출력 됩니다.

{
    "DBParameterGroupName": "",
    "Parameters": [
        {
            "ParameterName": "",
            "ParameterValue": "",
            "Description": "",
            "Source": "",
            "ApplyType": "",
            "DataType": "",
            "AllowedValues": "",
            "IsModifiable": true,
            "MinimumEngineVersion": "",
            "ApplyMethod": ""
        }
    ]
}

앞서 describe-db-parameters를 통하여 출력된 정보들과 비교해보면 거의 동일하며, MinimumEngineVersion과 ApplyMethod 가 추가되어 있는것을 확인할 수 있습니다. ApplyMethod 는 꼭 필요한 정보이며 MinimumEngineVersion 은 선택사항 입니다.

이를 통해 기존 출력된 정보에 ApplyMethod 만 추가하여 업데이트 한다면 원하는 파라미터 그룹을 다른 리전에서도 그대로 사용할 수 있다는 것을 알 수 있습니다.

ApplyMethod는 immediate와 pending-reboot 값 중 하나를 가질 수 있습니다. immediate는 변경 사항을 RDS 인스턴스에 즉시 적용하는 것을 의미하며, pending-reboot 은 인스턴스가 재시작 될 때 적용되는 것을 의미 합니다. 각 정보는 파라미터 종류와 운영 환경에 맞게 결정되어야 하겠지만, 이 글에서는 immediate로 지정하여 진행하도록 하겠습니다.

3. 복사하려는 파라미터 그룹 정보 출력
대상 파라미터 그룹에 업데이트 하기 위한, 복사하려는 파라미터 그룹 정보를 파일에 출력해 보겠습니다. 다만, 불필요하게 모든 파라미터 정보를 출력하지 않고, 수정된 파라미터만 출력하기 위해 --source 옵션을 사용하도록 하겠습니다.

$ aws rds describe-db-parameters --db-parameter-group-name src-pg --source user > src-pg.json

아래와 같은 결과가 src-pg.json 파일에 출력됩니다.

{
    "Parameters": [
        {
            "Description": "The server's default character set.",
            "DataType": "string",
            "IsModifiable": true,
            "AllowedValues": "big5,dec8,cp850,hp8,koi8r,latin1,latin2,swe7,ascii,ujis,sjis,hebrew,tis620,euckr,koi8u,gb2312,greek,cp1250,gbk,latin5,armscii8,utf8,ucs2,cp866,keybcs2,macce,macroman,cp852,latin7,utf8mb4,cp1251,utf16,cp1256,cp1257,utf32,binary,geostd8,cp932,eucjpms",
            "Source": "user",
            "ParameterValue": "utf8",
            "ParameterName": "character_set_server",
            "ApplyType": "dynamic"
        },
...

4. 파라미터 정보 추가하기
앞서 살펴본바와 같이 ApplyMethod는 필수이기 때문에 각 파라미터 정보에 추가하도록 하겠습니다. 먼저 파이썬(Python)을 활용한 방법입니다.

$ cat src-pg.json | python -c 'import sys,json; data=json.loads(sys.stdin.read()); map(lambda x: x.update({"ApplyMethod":"immediate"}), data["Parameters"]); print json.dumps(data)' | python -m json.tool > dest-pg.json

두번째는 jq를 사용(설치 필요) 하는 방법입니다.

$ cat src-pg.json | jq '.Parameters[] |= . + {"ApplyMethod": "immediate"}' > dest-pg.json

이제 dest-pg.json 파일을 출력해보면 다음과 같이 ApplyMethod 가 추가된 것을 확인할 수 있습니다.

{
    "Parameters": [
        {
            "AllowedValues": "big5,dec8,cp850,hp8,koi8r,latin1,latin2,swe7,ascii,ujis,sjis,hebrew,tis620,euckr,koi8u,gb2312,greek,cp1250,gbk,latin5,armscii8,utf8,ucs2,cp866,keybcs2,macce,macroman,cp852,latin7,utf8mb4,cp1251,utf16,cp1256,cp1257,utf32,binary,geostd8,cp932,eucjpms",
            "ApplyMethod": "immediate",
            "ApplyType": "dynamic",
            "DataType": "string",
            "Description": "The server's default character set.",
            "IsModifiable": true,
            "ParameterName": "character_set_server",
            "ParameterValue": "utf8",
            "Source": "user"
        },
....

5. 대상 리전에 파라미터 그룹 생성 및 업데이트
이제 복사할 대상 리전에 dest-pg 라는 이름의 기본 값을 가진 파라미터 그룹을 생성하겠습니다.

$ aws rds create-db-parameter-group --db-parameter-group-family MySQL5.6 --db-parameter-group-name dest-pg --description "This is a destination parameter group" --region us-east-1

결과는 다음과 같이 파라미터 그룹명을 포함한 정보가 출력 됩니다.

{
    "DBParameterGroup": {
        "DBParameterGroupName": "dest-pg",
        "DBParameterGroupFamily": "mysql5.6",
        "Description": "This is a destination parameter group"
    }
}

여기서는 명시적으로 –-region 이라는 옵션을 통하여 파라미터 그룹이 생성될 리전(us-east-1, Virginia)을 지정하였습니다.

앞서 만든 대상 리전의 파라미터 그룹에 원본 파라미터 그룹 정보를 업데이트를 합니다. --cli-input-json 옵션을 사용하여 앞서 원본 파라미터 그룹 정보에ApplyMethod 를 추가한 json 파일을 지정합니다.

$ aws rds modify-db-parameter-group --region us-east-1 --db-parameter-group-name dest-pg --cli-input-json file://dest-pg.json

정상적으로 완료되면 파라미터 그룹명이 출력 됩니다.

{
    "DBParameterGroupName": "dest-pg"
}

원본 파라미터 그룹과 대상 파라미터 그룹이 동일한지 diff를 사용하여 확인할 수 있습니다.

$ diff -s <(aws rds describe-db-parameters --db-parameter-group-name src-pg --source user) <(aws rds describe-db-parameters --region us-east-1 --db-parameter-group-name dest-pg --source user)

동일하다면, 다음과 같은 결과가 출력되며 완료된 것을 확인할 수 있습니다.

$ Files /dev/fd/?? and /dev/fd/??? are identical

지금까지 AWS CLI를 사용하여 리전간 RDS 파라미터 그룹을 복사하는 방법에 대해서 알아 보았습니다. 이외에도 다양한 방법으로 가능하겠지만, 앞서 살펴본 바와 같이 CLI를 활용한다면 몇 가지 명령어를 사용해 어렵지 않게 수행 할 수 있을 뿐만 아니라 자동화 할 수 있음을 확인 할 수 있습니다.

AWS CLI는 지속적으로 업데이트 되고 있으며, 새롭게 추가되는 새로운 명령어들과 기능들을 업무에 적용함으로써 작업 능률 향상을 꾀할 수 있을 것입니다. 이러한 점이 AWS의 매력 중 하나가 아닐까 생각합니다.

본 글은 아마존웹서비스 코리아의 솔루션즈 아키텍트가 국내 고객을 위해 전해 드리는 AWS 활용 기술 팁을 보내드리는 코너로서, 이번 글은 김필중 솔루션즈 아키텍트께서 작성해주셨습니다.

DevOps를 위한 AWS CLI 활용팁

AWS 클라우드를 사용하는 개발자 및 운영자라면 웹 기반 관리 콘솔 사용에 익숙하실 것입니다. 하지만, 좀 더 다양한 기능을 수행하거나 반복 작업 그리고 프로그래밍 언어를 통한 체계적인 관리가 필요하다면 AWS 명령줄 인터페이스(Command-line Interface, CLI)를 사용하는 것이 필요합니다.

AWS CLI 를 이용하면 다양한 AWS 서비스를 스크립트로 작성을 해서 여러 작업을 한번에 동작 시킬 수 있으며, 각종 관리 자동화를 수행하는데 유리합니다. AWS의 모든 서비스 기능은 API를 호출함으로서 가능하며, CLI 역시 간단한 명령줄을 통해 이러한 광범위한 API 기능을 수행할 수 있습니다. 이번 글에서는 여러분이 알아두시면 좋은 편리한 몇 가지 CLI 팁을 설명 드리겠습니다.

AWS CLI를 설치하고 나서 처음 해야 할 일은 Access Key 및 Secret Access Key 그리고 기본 리전 및 출력 결과를 설정하는 것입니다. (이 때, 접근 키들은 Root 권한의 키가 아니라, IAM(Identity & Access Management)을 통해 개별 서비스 권한 사용자를 생성하고 만든 키를 사용하는 것이 안전합니다. 더 자세한 사항은 IAM 사용자 가이드를 참고하세요.)

$ aws configure
AWS Access Key ID [****************YOJQ]: 
AWS Secret Access Key [****************5Mhd]:   
Default region name [ap-northeast-1]:
Default output format [json]:

Tip 1. AWS CLI 지원 도구를 활용하라.
AWS CLI의 대부분의 명령어는 $ aws help를 실행해보시면 알아보실 수 있습니다. 하지만, 매번 명령어를 기억하기는 쉽지 않습니다. 손쉽게 각 CLI 명령어를 자동 완성을 통해 실행하고자 한다면 aws shell를 설치해서 사용하시는 것을 권장합니다.

본 기능은 Donne Martin이 만든 SAWS라는 CLI 지원용 오픈소스 도구를 AWS CLI팀과 함께 통합한 것으로 다양한 상위 커맨드와 하위 커맨드를 자동 완성을 지원 합니다.

손쉽게 명령어를 입력 중에도 인라인 명령어 도움말을 바로 보실 수도 있습니다.

명령어 입력 중 AWS 리소스 자원, 예를 들어 Amazon EC2 instance IDs, Amazon SQS queue URL, Amazon SNS 토픽명) 등을 자동 완성 할 수도 있습니다.

그밖에 명령어 실행 기록 및 내보내기, 각종 기능의 도구바 지원 명령어 추천 기능 지원 등 다양한 기능도 제공합니다. 더 자세한 것은 aws-shell 기본 사용법Super-Charge Your AWS Command-Line Experience with aws-shell 블로그 글을 참고하시기 바랍니다.

Tip 2. aws configure 서브 명령어를 사용하라.
AWS CLI 설정을 위한 여러 서브 명령어가 존재합니다. 다음은 설정과 관련된 서브 명령어 입니다.

    $ aws configure
    list – 설정 관련 소스들을 보여준다.
    get – 하나의 설정 변수 값을 가져온다.
    set – 하나의 설정 변수 값을 저장한다.

예를 들어, 리전을 설정하는 것은 다음과 같이 하면 됩니다.

$ aws configure set profile.prod.region us-west-2

좀 더 자세히 살펴봐야 하는 것은, 설정 파일은 두개의 파일로 구성됩니다.

위치 기능
~/.aws/credentials 모든 AWS SDK에서 지원. 오직 인증 정보만 담고 있다.
~/.aws/config CLI에서만 사용되는 정보. 인증 정보를 담을 수도 있다.

설정 파일이 나뉜 것은 위와 같이 각기 수행하는 기능의 목적이 다르기 때문입니다. 구체적으로 명령 예를 들면 다음과 같습니다.

Access Key 아이디 설정

$ aws configure set profile.prod.aws_access_key_id foo
~/.aws/credentials ~/.aws/config
[prod]
aws_access_key_id = foo
 

Secret Access Key 아이디 설정

$ aws configure set profile.prod.aws_secret_access_key bar
~/.aws/credentials ~/.aws/config
[prod]
aws_access_key_id = foo
aws_secret_access_key = bar
 

리전 및 아웃풋 형식 설정

$ aws configure set profile.prod.region ap-northeast-1
$ aws configure set profile.prod.output text
~/.aws/credentials ~/.aws/config
[prod]
aws_access_key_id = foo
aws_secret_access_key = bar
[profile prod]
region = ap-northeast-1
output = text

이런 설정 정보를 알고 싶으면 list 서브 명령어를 사용해서 정보를 가져오면 됩니다.

$ aws configure list
      Name                    Value             Type    Location
      ----                    -----             ----    --------
   profile                             None    None
access_key     ****************YOJQ shared-credentials-file    
secret_key     ****************5Mhd shared-credentials-file    
    region           ap-northeast-1      config-file    

Tip 3. waiter를 적극 활용하라.
AWS CLI를 활용하면 쉘스크립트를 통해 프로그래밍 방식으로 여러 명령어를 하나로 처리할 수 있습니다. 예를 들어, EC2와 관련된 작업을 하는 경우, 대상이 되는 EC2가 동작하게 되고 나서 다른 동작을 처리해야 하는 경우가 생깁니다. 아래 그림은 일반적인 EC2 라이프 사이클입니다.

인스턴스가 새롭게 생성될 때 까지 기다렸다가 그 다음 동작을 해야 한다면, AWS CLI를 이용하여 아래와 같은 스크립트를 작성할 수 있을 것입니다. (예시 코드이며, 리눅스 쉘 스크립트를 기본으로 했습니다. 윈도우 사용자라면 파워셀 등을 이용하셔서 작성하시면 됩니다)

#!/bin/bash
instance_id=$(aws ec2 run-instances --image-id ami-12345 \
        --query Instances[].InstanceId \
        --output text)
instance_state=$(aws ec2 describe-instances --instance-ids $instance_id \
        --query 'Reservations[].Instances[].State.Name')
while [ "$instance_state" != "running" ]
do
    sleep 1
    instance_state=$(aws ec2 describe-instances --instance-ids $instance_id \
        --query 'Reservations[].Instances[].State.Name')
done

위의 코드는 단순 합니다. 이미지 아이디를 통해서 인스턴스 아이디와 인스턴스 상태 정보를 가져옵니다. 그리고 인스턴스 상태가 아직 “running”이 아니면, 무한 반복을 하면서 1초마다 확인해서 반복 루프를 도는 것입니다.

그런데, 이렇게 작성을 하게 되면 타임아웃 설정이 없어서, 대상 인스턴스가 뜨지 않은 경우 무한 반복을 하게 되고, 실패처리 로직이 없다는 문제가 발생합니다. 또한, 매우 코드가 길어지게 되는 단점이 있습니다. 이러한 문제를 해결하기 위해 존재하는 것이 “waiter”입니다. 이것을 활용한 명령어는 다음과 같이 됩니다.

...
instance_id=$(aws ec2 run-instances --image-id ami-12345 \
        --query Instances[].InstanceId \
        --output text)
instance_state=$(aws ec2 wait instance-running --instance-ids $instance_id \
...

EC2에 대해 wait 서브 명령어 다음에 나오는 것은 “대기 이름(waiter name)”입니다. 여기서는 instance-running이 됩니다. 위 명령으로 해당 인스턴스가 “러닝”상태가 될 때 까지 기다립니다.

사용 가능한 “대기 이름”은 help 명령어를 통해서 확인 할 수 있습니다. 또한, 이러한 wait 명령어는 EC2만이 아니라, 다른 서비스에도 적용할 수 있으며, 아래 코드는 Amazon DynamoDB 사례입니다.

$ aws dynamodb wait table-exists
$ aws dynamodb wait table-not-exists

AWS CLI는 AWS 서비스를 손쉽게 조작하는데 있어서 매우 중요한 도구입니다. 명령어 기반의 인터페이스로서 콘솔에서 하기 어려운 조작을 쉽고 편리하게 처리할 수 있습니다. AWS CLI를 사용해서 보다 강력한 AWS 서비스를 사용할 수 있으며, 다양한 활용 팁을 AWS CLI 영문 블로그 혹은 아래 한국팀에서 만든 AWS CLI 활용 사례 예제 코드도 한번 익혀보시기 바랍니다.

본 글은 아마존웹서비스 코리아의 솔루션즈 아키텍트가 국내 고객을 위해 전해 드리는 AWS 활용 기술 팁을 보내드리는 코너로서, 이번 글은 박선용 솔루션즈 아키텍트께서 작성해주셨습니다.

2015년 11월 AWS 최신 보안 뉴스

새로운 SOC 심사 결과 발표- 신규 3개 서비스 포함

새로운 SOC(Service Organization Controls) 심사 결과를 발표하게 되어 무척 기쁩니다.

AWS SOC 프로그램은 매년 반기 별로 광범위한 감사 결과를 발표합니다. SOC 리포트(전신 SAS 70)은 2009년부터 계속되고 있으며, 해를 거듭할 수록 많은 통제 요소와 보다 많은 서비스들이 포함되고 있습니다. 제3 의 평가 기관인 Ernst & Young으로부터, AWS가 American Institute of Certified Public Accountants (AICPA)의 Security Trust Principles을 잘 준수 하고 있다는 점을 평가 받고 있습니다. AWS SOC 프로그램은 정보 보안, 기밀성, 개인정보 보호에 대한 투명한 정보를 고객들에게 계속적으로 제공할 예정입니다.

그리고 이번 결과에는 다음 3가지 AWS 서비스들이 SOC 결과 리포트에 추가되었습니다.:

    • AWS Key Management Service (KMS)
    • Amazon Simple Email Service (SES)
    • Amazon WorkSpaces

결과적으로 SOC리포트에 포함된 서비스의 갯수는 26개로 증가 하였고, 또한 34개의 엣지 로케이션도 포함되었습니다.

최신 AWS SOC 1 와 SOC 2 Security & Availability 리포트는 2015년 4월 1일부터 9월 30일까지의 기간 동안하게 되며, 앞으로도 6개월의 주기로 재 심사 받을 예정입니다. 최신 SOC 1 혹은 SOC 2 리포트를 신청하려면, AWS Sales and Business Development를 연락하시기 바랍니다. 더불어, 여러분의 규제 요건에 따라 SOC 3 리포트를 AWS Compliance 웹 사이트를 통해 다운 받거나 직접 보기 하실 수 있습니다.

리포트에 관해 좀 더 질문이 있으시면 관련 FAQ사이트 를 방문해 보세요.

공개된 모든 인증 내역을 보시려면, AWS Published Certifications 참조 하시고, 최신 AWS Compliance news가 여기(AWS Compliance – Latest News)에서 보실 수 있습니다.

– Chad Woolf, Director of AWS Risk and Compliance

IAM 사용자를 위한 SMS MFA 기능 프리뷰

AWS는 새롭게 복합 인증을 지원하는 Short Message Service (SMS) 에 대한 미리보기를 발표했으며 이것은 여러분들이 보안 모범사례를 쉽게 구축하는데 도움을 줄 것입니다. 지금까지 여러분들은 하드웨어나 가상 MFA토큰방식의 서비스를 IAM 사용자에 적용하였을 것입니다. 이번 발표된 기능은 MFA 방식으로 IAM 사용자를 인증할때, 모바일 기기상에서 텍스트 메세지 기반으로 할 수 있도록 해줍니다. AWS 관리 콘솔에 로그인 할때 IAM 사용자는 모바일 기기를 통해 텍스트로 된 보안 코드를 받게 되고, 브라우져 상에 전달된 코드를 입력함으로써 본인임을 인증 받게 됩니다.

SMS MFA 는 모든 모바일 기기에서 사용하기 쉬운 텍스트 기반의 OTP기능을 제공합니다. 또한 모바일 앱을 다운로드 받을 필요가 없고 특별한 하드웨어를 필요로 하지도 않습니다. 모바일 기기 간에는 번호가 이동될 수 있기 때문에 여러분들은 모바일 기기를 교체, 업그레이드, 분실했을 경우에도, 편하게 이동하여 AWS에 대한 접근 통로를 유지할 수 있습니다. 이 기능을 이용하는데 별도의 요금은 없지만 SMS 이용 요금이 발생할 것이며 이 부분은 통신사에 따라 달라집니다.

이 기능을 이용하기 위해 여러분들은 ‘AWS account에서 미리보기 신청하기’ 과정을 해야 합니다. 미리 보기를 수락하고 1, 2일 이내에 여러분의 AWS Account에 SMS MFA기능을 활성화 할 것이라는 내용의 이메일을 받게 됩니다. 이 기능에 대한 좀 더 자세한 정보는 SMS 텍스트 메세지 MFA 이용하기에 있습니다.

새로 나온 SMS MFA에 대한 여러분들의 생각을 알고 싶습니다. 사용후 피드백을 주시거나 IAM forum 을 방문하시어 코멘트를 남겨 주시기 바랍니다.

– Vikram

IAM 콘솔 검색 기능 소개

지금까지 AWS IAM콘솔 상의 피드백 링크를 통해 여러분들의 의견을 받아 왔습니다. 지금까지 피드백 중, 빈번하게 들어오는 요청은 바로 특정 Access Key ID를 가진 IAM사용자를 찾을 수 있는 가 하는 문제였습니다. 이와 같은 기능을 구현하면서, 동시에 AWS고객들이 IAM 콘솔상에서 쉽게 뭔가를 찾을 수 있어야 한다고 생각했으며, 이에 대한 답변이 바로 IAM콘솔 검색 기능입니다.

이번 포스팅에서, IAM콘솔 검색기능을 통해, 이름, 계정정보 제공자, 타스크, 엑세스 키 등의 기준을 가지고 IAM엔티티들(사용자, 그룹, 롤 등)을 찾는 과정을 진행하게 됩니다. 상세 내용 →

AWS KMS 서비스와 EncryptionContext를 통해 암호화된 데이터를 보호하는 방법

중요한 기밀 데이터를 위한 AWS KMS의 가장 중요하고 핵심적인 개념은 EncryptionContext입니다. EncryptionContext를 제대로 잘 활용하게 되면 어플리케이션 보안을 향상시키는데 엄청난 도움이 됩니다. 이번 포스팅에서는 EncryptionContext 이 얼마나 중요한지 살펴보고, 암호화된 데이터의 무결성을 보호하기 위한 간단한 예제가 제공됩니다.

EncryptionContext는 KMS 가 암복호화 작업을 수행하는 데 제공되는 키-값 맵핑(둘다 문자열) 입니다. 암호화와 복호화 간의 맵핑은 반드시 상호 매치되어야 하며 그렇지 않다면 복호화 요청은 실패하게 됩니다.

EncryptionContext 아래의 3가지 이점을 제공합니다.:

  • 부가적인 인증 데이터
  • 감사 로그
  • 인가 컨텍스트

상세내용 →

IAM 정책 시뮬레이터를 통해 리소스수준의 권한 테스트 하기

여러분들은 AWS IAM의 policy simulator 를 통해 리소스 레벨의 퍼미션에 대한 테스트 및 검증하고 파악하는 것을 훨씬 더 쉽게 할 수 있게 됩니다. 이것은 리소스의 목록을 보여주고 AWS액션이 요구하는 필수 파라메터들을 자동으로 제공합니다. 이 기능을 통해 보다 정확한 조건으로 시뮬레이션하고 새로 작성한 정책이 예상대로 동작하는지 검증할 수 있게 됩니다. 현재까진 이 기능이 아마존 EC2, IAM, CloudFormation에서만 지원된 다는 것을 주목하시기 바랍니다. 계속적으로 다른 서비스 들에 대해서도 확대해 나갈 예정입니다.

IAM 정책 시뮬레이터는 두가지 UI개선 사항이 있습니다. 첫 번째는 Simulation Settings가 새롭게 Global Settings으로 변경되었습니다. Global Settings 섹션에는aws:SourceIP정책 변수와 같은 시뮬레이션 상의 모든 액션에 적용될 정보들을 입력하게 됩니다. 두번째는 Results 테이블이 Action Settings and Results 테이블에 들어왔습니다. 이 테이블에서 여러분들은 모든 필요한 리소스와 각 액션에 대한 조건 값들을 입력하게 됩니다. 이를 통해 AWS API 요청을 만들 때 같은 조건으로 시뮬레이션하게 해줍니다. 상세 내용 →

Amazon WorkDocs 보안 설정하기

Amazon WorkDocs (이전 Amazon Zocalo) 는 관리형으로 제공되는 안전한 기업 저장소이자 공유 기능을 제공하는 서비스입니다. 여러분들은 파일에 대해 코멘트를 남기고, 다른 사용자의 피드백을 요청하는 과정에서 이메일 첨부로 많은 파일들을 첨부하던 방식을 탈피할 수 있습니다. Workdocs는 암호화, 세부 공유, 접근 제어 등 다양한 보안 기능을 제공합니다. 게다가 Workdocs는 현재 ISO/IEC 27018:2014 를 준수하고 있으며 이것은 여러분들의 컨텐츠에 대한 개인 정보 보호 관련 수준에 대한 내용입니다.

본 포스팅에서는 이와 같은 WorkDocs 보안 기능들에 대해 다루게 되면 이를 통해 여러분의 WorkDocs 싸이트의 보안 수준을 어떨게 향상 시킬 수 있는지를 소개드립니다. 상세 내용 →

AWS 는 ISO 27018 개인 정보 인증 취득

본 포스팅에서는 AWS 가 성공적으로 새로운 인증 ISO/IEC 27018:2014 을 성공적으로 취득했음을 안내합니다. 이 인증은 클라우드 상에서의 개인정보(PII) 보호와 관련된 프랙티스들을 다루며, AWS가 클라우드 상에서 고객의 개인정보를 안전하게 취급할 책임을 잘 견지하고 있음을 나타냅니다. 이 개인정보 보호 관련 인증은 ISO 27001 인증 프로그램의 일부입니다

ISO 27018 은 클라우드 상의 개인정보 보호와 관련하여 첫번째로 나온 국제 규범입니다. ISO 27018 인증 취득은 AWS가 고객의 컨텐츠에 대한 개인 정보 보호와 관련된 통제 장치를 가지고 있다는 점을 입증합니다. 상세 설명 →

AWS KMS 암호화 키의 삭제 지원

AWS 는 새롭게 KMS에서 관리되는 암호화 키의 삭제 기능을 제공합니다. 암호화 키 관련된 전체 라이프 사이클을 완성할 수 있게 되었으며, 본 포스팅에서는 새로운 기능의 소개와 함께 키를 삭제하기 전에 어떤 일을 해야 하는지, 그런 후 어떤 절차로 삭제하는 지를 보여줍니다.

암호화 키를 삭제한다는 것이 잠재적으로 위험한 행동이라는 것을 꼭 인지하기 바랍니다. 키가 없을 때 데이터 복구가 불가능 한 점 때문에, 예정된 삭제 요청 뒤에도, 즉각 삭제를 하는 것이 아니고 복호화 요구가 발생할 가능성이 있는 일정 기간의 대기 시간을 둘 수 있습니다. 7일에서 30일 간에 대기 시간을 설정할 수 있으며, 그 기간 동안 삭제 요청을 취소하고 다시 키를 복원할 수 있습니다. 상세 내용 →

AWS 와 EU 세이프 하버

최근, 유럽 연합의 대법원은 지난 15년간 유지되어온 US-EU 세이프 하버 프레임 웍과 관련, EU권역에서 미국으로 개인정보를 이전하는 것이 더이상 유효하지 않다는 판결을 내렸습니다.

고객 개인 정보의 보안을 각별히 다루고 있는 AWS에서는 이에 대한 면밀한 검토 끝에, AWS 의 고객 혹은 파트너들이 AWS상에서 자신들의 고객 개인정보를 다룰 때 EU 권역에서 미국으로 정보를 이관하는데 문제가 없으며 어떠한 부가적인 절차도 필요 없음을 확인 드리게 되었습니다. 이것은 AWS 가 EU 데이터 보안 당국(Article 29 Working Party로 알려진)과 맺었던 AWS 데이터 처리 절차 부가조항과 모델 조항에 의거하며, 미국을 포함하여 EU 바깥으로 개인정보 이관이 가능하게 됩니다. 또한 AWS 고객은 EU Data Protection Directive (Directive 95/46/EC) 조항을 완벽히 준수하는 상태로서, AWS상에서 운영 중인 글로벌 업무를 지속할 수 있습니다. 그리고 AWS의 데이터 처리 부가 조항은 고객이 EU에서 설립되었든 글로벌 회사든 간에, 개인정보를 취급하는 모든 AWS 고객에게 적용됩니다. 보다 자세한 내용은 이곳을 방문해 보세요 AWS EU Data Protection FAQ.

EU 권역 밖으로 개인정보를 이전할 필요가 없는 고객들을 위해, 지속적으로 다음과 같은 통제 및 보안 기능을 제공할 것입니다.:

  • 고객들은 그들의 고객 정보에 대한 소유권을 그대로 유지하게 되며, 어떤 AWS 서비스를 통해 처리, 저장, 호스팅 되는지 선택할 수 있습니다.
  • 고객들은 특별한 지역적인 요건에 맞추어 그들의 고객 정보가 어디에 저장되는지 선택할 수 있습니다.
  • 고객은 그들의 고객 정보에 대한 전송 중 또는 저장 시 보안 상태에 대해 본인들의 암호화 키를 가지고 수행할 수 있도록 선택할 수 있습니다.

부가적인 정보는 여기를 방문해 보세요 AWS Privacy and Data Security FAQ.

AWS에 있어서, 고객으로부터의 신뢰는 저희의 최우선 과제이며, 고객이 계속해서 AWS의 보안, 컴플라이언스와 관련하여 이점을 누릴 수 있도록 노력해 나가고 있습니다.

– Steve

re:Invent 2015 신규 보안 서비스—Amazon Inspector, AWS WAF, and AWS Config Rules

이번 re:Invent에서, AWS 는 여러분의 보안 수준을 향상하고 AWS상에서 운영 중인 어플리케이션을 보호하기 위한 2개의 새로운 보안 서비스와 한 개의 신규 기능을 소개했습니다.

Amazon Inspector는 자동화된 보안 진단 서비스로서 AWS상에서 운영 중인 어플리케이션에 대한 보안 혹은 컴플라이언스 관점의 이슈들을 적발해 줍니다. Amazon Inspector 는 자동으로 어플리케이션의 취약점이나, 모범 사례를 기준으로 위반 사례들이 있는지 점검하게 되며, 점검 이후, 경감 조치를 위한 자세한 절차를 담고 있는 리포트를 생성해 줍니다.

빠르게 시작할 수 있도록, Amazon Inspector는 PCI DSS와 취약점 정의서 등 수 백 가지 규칙들을 담고 있는 지식 기반을 포함하고 있습니다. 예를 들자면, 리모트 루트 로그인이나, 취약한 소프트웨어 버전들 같은 것들이 포함됩니다. 이와 같은 규칙들은 정기적으로 AWS 보안 연구원들에 의해 업데이트 됩니다. 상세 설명 →

11월의 AWS 보안 뉴스는 AWS코리아의 보안 분야 솔루션 아키텍트로 일하시고 있는 임기성님께서 작성해 주셨습니다.

 

AWS Unity SDK 로 간단한 게임 구현하기

AWS는 다양한 프로그래밍 언어를 위한 소프트웨어 개발 도구(SDK)를 제공하고 있습니다. Python, Java, PHP 등은 물론이고, 최근에는 C/C++를 지원하는 SDK도 발표를 하였습니다. 또한, 모바일 앱을 개발을 지원하는 AWS Mobile SDK가 있습니다. AWS Mobile SDK는 iOS, Android, Fire OS 그리고 오늘 설명 드릴 Unity를 지원합니다.

Unity는 잘 알려진 게임 개발 통합 플랫폼입니다. 주로 3D게임을 편리하게 개발하기 위한 기능과 툴을 제공하고 있으며, Unity를 통해 개발된 많은 게임이 존재합니다. Unity는 게임 디자인부터 사운드와 물리 엔진 등의 여러가지 기능과 네트워크 기능도 제공하고 있습니다. AWS Mobile SDK는 기본적으로 Mobile apps에서 AWS 를 쉽게 접근할 수 있도록 함수를 제공하는 것이 기본적인 목적입니다.

따라서, AWS Mobile SDK for Unity는 Unity를 통해서 모바일 게임 등을 개발할 때 직접 Unity 코드에서 SDK를 이용하여 AWS 에서 제공하는 서비스들을 편리하게 사용할 수 있습니다.

아래 내용은 SurvivalShooter라는 공개 데모 게임에 AWS Unity SDK를 설치하고 개발하여 실제 게임에서 AWS Cognito를 통해 인증 및 데이타 싱크, S3에서 설정 파일 다운로드, Facebook과 인증 연동, 게임 정보와 로그를 DynamoDB에 기록, Mobile analytics로 게임 로그 전송을 구현한 예제입니다. 전체 코드를 참조하여 주시고, 설명은 각각의 주요 내용에 대한 핵심 부분을 간략히 설명하겠습니다.

☞샘플 코드: https://s3-ap-northeast-1.amazonaws.com/www.cloudinternal.com/SurvivalShooterAWS.zip

참고: 본 가이드는 AWS Mobile SDK for Unity Preview 버전을 기반으로 작성되어 최신 정식 SDK 버전과 약간의 차이가 있을 수 있습니다.

1. AWS Mobile SDK for Unity 소개

AWS Unity SDK는 현재(21-Oct-2015) 아래 AWS 서비스를 지원하고 있습니다. 아래 AWS 서비스를 사용하기 위한 .NET Classes를 제공하고 있어, Unity로 게임을 개발하면서 아래 서비스를 사용하기 위해 클래스를 호출하여 개발을 하게 됩니다. 최근에는 AWS Lambda를 추가로 지원하면서 Unity로 개발된 게임에서 Lambda 함수를 호출하여 (별도 백엔드 서버를 통한 처리가 아니라) 이벤트 기반 개발 로직 처리 및 구현이 가능합니다. SDK 내용을 보면 아래의 각 서비스의 플러그인 패키지로 구성되어 있습니다.

2. Unity 및 AWS Unity SDK 설치

AWS Unity SDK는 Unity version 4.x 와 5.x 의 버전과의 호환성을 가지고 있으며, 4.0~4.2버젼의 경우는 설치 시에 몇 가지 작업이 필요합니다. AWS Unity SDK의 소개와 설치에 대한 부분은 아래 링크에서 상세히 가이드하고 있습니다. 아래 링크를 참조하시어 개발 환경 구성을 구성하십시오. 순서를 요약하면 아래와 같습니다.

  1. Unity 다운로드 및 설치
  2. AWS Unity SDK 다운로드 설치
  3. AWS Unity SDK 설정 (생략을 하고 코드에서 직접 지정을 할 수도 있습니다.)
  4. Amazon Cognito를 통해 AWS Credentials 획득
  5. 주요 개발 문서:

3. Amazon Cognito 인증하기

AWS Unity SDK에서 AWS 리소스에 접근하기 위해서는 인증이 필요하게 됩니다. 인증을 위한 정보가 바로 AWS Credential입니다. 보통 access key, secret key로 구성하나, 모바일 게임을 개발하면서 지정된 키를 직접 코드에 넣는 것은 좋은 방법이 아닙니다. 모바일 인증을 손쉽게 하기 위한 빌딩 블럭인 Amazon Cognito를 통해 쉽게 구성할 수 있습니다.

Amazon Cognito는 Identity pool을 구성하고 해당 풀에 사용자 정보를 저장할 수 있습니다. 그리고 해당 Identity pool에 IAM 역할(role)을 정의하여 게임 사용자가 어떤 AWS 서비스를 이용할 수 있는지 정할 수 있습니다. 예를 들어 IAM role에서 DynamoDB에 PutItem API를 허락하도록 추가한다면 사용자는 AWS Cognito를 통해 전달 받은 임시 토큰을 통해 DynamoDB에 직접 데이터를 입력할 수 있습니다.

그 과정을 살펴 보도록 하겠습니다. 먼저 아래 아래 코드와 같이 AWSManager.cs 파일에 Credential provider를 생성합니다.


public string IDENTITY_POOL_ID = "";
public string ANALYTICS_APP_ID = "";
public RegionEndpoint ENDPOINT = RegionEndpoint.USEast1;

private CognitoAWSCredentials credentials;
private CognitoSyncManager syncManager;

// Create a Credentials provider that uses Cognito Identity
credentials = new CognitoAWSCredentials(IDENTITY_POOL_ID, ENDPOINT);

IDENTITY_POOL_ID를 입력 받아 코드에서 해당 Identity pool ID를 읽어 인증을 진행하게 됩니다. Unity개발 도구의 Inspector에서 생성한 ID를 입력하도록 합니다. AWS 콘솔에서는 아래와 같이 Amazon Cognito 메뉴로 이동하여, Identity pool을 생성하여 인증 사용자와 비인증 사용자가 이용할 IAM 역할(Role)을 선택합니다. 위에서 설명 드린 것처럼 IAM Role에 AWS 서비스에 접근할 수 있는 권한이 주어져야 개발된 게임에서 해당 서비스에 접근을 할 수 있습니다.

4. Amazon Cognito 데이터 싱크

Amazon Cognito는 사용자 별로 데이터를 각각 저장하고 동기화하는 기능을 제공합니다. 멀티 플랫폼에서 사용자와 애플리케이션 정보를 유지하여 지속적으로 서비스에 활용하도록 하는 기능입니다. 데모 게임에서는 플레이어의 위치를 Cognito Dataset에 저장하고 다음 플레이에 해당 위치에서 시작하도록 예를 구성하였습니다.

AWSManager 클래스에서 CognitoSynchManager를 생성



// Cognito Sync Manager
syncManager = new DefaultCognitoSyncManager(
credentials, new AmazonCognitoSyncConfig { RegionEndpoint = ENDPOINT });
//UserDataManager에서 플레이어 위치 정보를 저장하고 읽어 올 수 있도록 구현합니다.
public Dataset GetUserProfileDataset() {
	return userProfileDataset;
}

public void SetPlayerPosition(Vector3 pos) {
	userProfileDataset.Put("position", NDCUtil.stringFromVector3(pos));
}

public Vector3 GetUserPosition() {
	Vector3 pos = NDCUtil.vector3FromString(userProfileDataset.Get("position"));
	if (pos == null) {
		pos = new Vector3(0, 0, 0);
		userProfileDataset.Put("position", NDCUtil.stringFromVector3(pos));
	}
return pos;
}

public void SyncUserProfile() {
	userProfileDataset.Synchronize();
}

Amazon S3 파일 가져오기

Amazon S3 스토리지 서비스를 게임 자원의 DLC(Downloadable Content)에 활용하면 편리하게 파일 형태의 데이터를 저장하고 읽어 올 수 있습니다. 정적 콘텐츠(Static Contents)는 물론 게임 내에서 활용할 설정이나 환경 설정(Configuration) 정보를 저장하여 게임 시작 시 다운로드하여 게임에 쉽게 활용할 수 있습니다.

이 예제 게임에서는 S3 URL을 입력하여 간단한 JSON 형태의 입력 파일을 게임 시작 시 다운로드 합니다. DLCManager 클래스에서 다운로드 코드를 구현합니다. S3를 보다 잘 사용하기 위해서는 AmazonS3Client를 이용하면 편리합니다.


public string DLC_URL = "";
public void CheckDLC() {
	WWW www = new WWW(DLC_URL);
	print (GameManager.Instance);
	StartCoroutine(WaitForDLCRequest(www));
}

IEnumerator WaitForDLCRequest(WWW www) {
	yield return www;

	// check for errors
	if (www.error == null) {
		GameManager.Instance.UpdateStatusMessage("DLC updating...");
		Debug.Log("WWW Ok!: " + www.text);
		ParseAndUpdateDLC(www.text);
		GameManager.Instance.UpdateStatusMessage("Facebook initializing...");
	//  FB.Init(FacebookInitCallback);

		GameManager.Instance.OnDLCUpdateEnded();
	} else {
		Debug.Log("WWW Error: "+ www.error);
		GameManager.Instance.UpdateStatusMessage("Failed to update content: " + www.error, false);
		}
}

AmazonS3Client를 활용할 경우 아래의 예제 코드를 간단히 변경하여 적용이 가능합니다.


private void GetObject()	{
	ResultText.text = string.Format("fetching {0} from bucket {1}",
	SampleFileName, S3BucketName);
	Client.GetObjectAsync(S3BucketName, SampleFileName, (responseObj) =< {
		string data = null;
		var response = responseObj.Response;
	        if (response.ResponseStream != null) {
		      using (StreamReader reader = new StreamReader(response.ResponseStream)) {
		      data = reader.ReadToEnd();
		     }
	        ResultText.text += "\n";
	        ResultText.text += data;
	       }
        });
}

5. Facebook과 인증 연동하기

Amazon Cognito Identity 는 Facebook, Google, Amazon, Twitter/Digits 및 OpenID를 이용한 연동 인증을 지원합니다. 이 게임 예제에서는 Facebook을 인증 제공자로 선택하여 인증할 수 있도록 구현하였습니다.

앞에 설명한 것처럼 Cognito는 비인증 사용자(Unauthenticated user)와 인증 사용자(Authenticated user)를 구분하여 지원할 수 있습니다. Facebook developers 페이지에서 앱을 등록하여 ID를 발급받아 Amazon Cognito Identity pool에 등록하는 과정이 필요합니다.

아래와 같이 Facebook developer 페이지에서 앱을 등록하여 ID를 발급받습니다.

Amazon Congito 에서 생성한 Identity pool의 설정에 아래와 같이 ID를 등록합니다.

보다 상세한 내용은 아래 링크를 참조해 주십시오.

http://docs.aws.amazon.com/cognito/devguide/identity/external-providers/facebook/

Unity에 Facebook 연동으로 위해 Facebook SDK를 설치합니다. 아래 링크에서 다운로드가 가능합니다.

https://developers.facebook.com/docs/android

Facebook 연동 인증은 FacebookManager.cs로 구현되어 있습니다. GUI로 화면에서 로긴 정보를 입력할 수 있도록 구현되어 있습니다.

위에서 Find Access Token을 누르면 Facebook 페이지에서 사용자 토큰(User token)을 발급받아 입력할 수 있습니다. 키를 입력하고 Login을 누르면 Facebook 과 연동하여 Authenticated user로 인증을 진행 할 수 있습니다.

6. Amazon Mobile Analytics 사용하기

Amazon Mobile Analytics 서비스는 모바일 게임 또는 서비스에서 나오는 사용자 및 매출 통계, 캠페인을 통한 결과 등 비지니스를 위한 다양한 정보를 그래프와 함께 제공해 주는 기능입니다. 또한 맞춤형 이벤트(Custom Events)를 만들어주면 원하는 통계를 받아 볼 수 있습니다. 게임이라면 게임 내에 일어나는 다양한 이벤트를 Amazon Mobile Analytics로 간단히 추가해서 반영할 수 있습니다.

이 게임 예제에서는 게임 중에 Enemy와 Damage에 대한 정보와, 세션 시간에 대한 정보를 예제로 Amazon Mobile Analytics Custom events로 보내는 내용이 구현되어 있습니다. 참조하여 다양한 정보를 간단한 코드 추가로 분석해 볼 수 있는 기능입니다.

Amazon Mobile Analytics를 이용하기 위해서는 App을 등록하는 과정이 필요합니다 등록하여 ID를 발급 받아 해당 아디이로 생성한 App에 데이터를 넣을 수 있게 됩니다. 아래 그림은 콘솔에서 Mobile analytics app을 생성한 내용입니다.

위에 App ID를 Unity inspector에서 Cognito ID처럼 동일하게 값을 입력하여 코드에서 읽어 사용하게 됩니다.

AWSManage 클래스에 구현되어 있는 코드는 아래와 같습니다. AnalyticsManager를 생성하고 원하는 통계치 메트릭을 추가합니다.


// Amazon Mobile Analytics Manager
analyticsManager = AmazonMobileAnalyticsManager.GetOrCreateInstance(
	credentials, ENDPOINT, ANALYTICS_APP_ID);
//-------
public void RecordEnemyHit(string weapon, int damage, string enemyName, int score) {
	AmazonMobileAnalyticsEvent customEvent = new AmazonMobileAnalyticsEvent("ShooterEnemyHit");
	customEvent.AddAttribute("Enemy", enemyName);
	customEvent.AddMetric("Damage", damage);
	analyticsManager.RecordEvent(customEvent);
}

public void RecordSessionTime(int time) {
	AmazonMobileAnalyticsEvent customEvent = new AmazonMobileAnalyticsEvent("SessionTime");
	customEvent.AddMetric("SessionTime", time);
	analyticsManager.RecordEvent(customEvent);
}

DynamoDB에 데이터 적재하기

AWS Unity SDK는 직접 DynamoDB에 데이터를 넣고 쓸 수 있도록 지원하고 있습니다. 중간에 다른 Back-end server를 구현하지 않고, 직접 NoSQL 데이터베이스인 DynamoDB를 읽고 쓸 수 있는 방법은 비용을 줄이고 빠르게 개발할 수 있는 장점이 있습니다. 이 게임 예제에서는 UserInfo와 ShotInfo라는 두 개의 테이블을 만들어 사용자 정보와 사용자가 게임을 하면서 발생하는 적과 데미지 무기 종류에 대한 정보를 지속적으로 DynamoDB에 넣을 수 있도록 구현하였습니다.

아래는 코드 예제로 Cognito 인증 정보를 통해 DynamoDB client객체를 생성하고 데이터를 넣는 예제입니다.


// Dynamo DB Client
dynamoClient = new AmazonDynamoDBClient(new CognitoAWSCredentials(IDENTITY_POOL_ID, ENDPOINT), ENDPOINT);
dynamoContext = new DynamoDBContext(dynamoClient);
// -----

public void PutUserShotInfo(string weapon, int damage, string enemyName, int score) {
	string userId = GameManager.Instance.userDataManager.userId;
	UserShotInfo userShotInfo = new UserShotInfo{
	Id = userId,
	Timestamp = NDCUtil.CurrentTimestamp(),
	Weapon = weapon,
	Damage = damage,
	Score = score
};
dynamoContext.SaveAsync<UserShotInfo>(userShotInfo,
(AmazonDynamoResult<VoidResponse> r) =< {
		if (r.Exception != null) {
		Debug.LogError("Save error");
		Debug.LogException(r.Exception);
		return;
		}
	}, null);
}

AWS Mobile SDK를 통해 서버를 통하지 않고 직접 AWS의 다양한 서비스를 활용하는 방법은 최근 이야기되는 Serverless architecture를 이용하여 낮은 비용과 빠른 개발 시간을 통해 다양한 게임을 개발할 수 있는 새로운 방법을 제공하여 줍니다.

더불어 Unity라는 게임 개발 플랫폼에서 게임 개발과 동시에 AWS의 서비스를 직접 활용할 수 있도록 하는 AWS Mobile SDK for Unity는 예제와 같이 단순한 코드로 콘텐츠, NoSQL DB, 분석 등의 다양한 기능을 직접 구현할 수 있도록 게임 개발자 분들에게 편리한 기능을 제공합니다. Unity로 게임을 개발하면서 Back-end service를 AWS로 구성하여 다양한 게임을 개발하는데 도움이 되었으면 합니다.

본 글은 아마존웹서비스 코리아의 솔루션즈 아키텍트가 국내 고객을 위해 전해 드리는 AWS 활용 기술 팁을 보내드리는 코너로서, 이번 글은 김일호 솔루션즈 아키텍트께서 작성해주셨습니다.