개인 용도로 AWS 프리티어 사용 중 실수로 요금을 내게 되는 경우들

  • EC2
    • EC2 인스턴스를 t1-micro 타입 이상의 사양으로 만들어서 사용하는 경우
    • EC2 인스턴스의 전체 사용시간이 750시간이 넘어 간 경우
      • ex) EC2 인스턴스 한개를 한달내내 켜놔서 750시간을 사용해 놓고, 그 인스턴스외에 다른 인스턴스를 추가로 더 사용해서 전체 사용시간이 750시간이 넘을때
  • EIP
    • EIP를 만들고 EC2에 붙여서 사용하지 않은 경우
    • EIP를 만들고 EC2에 붙였지만, 해당 EC2를 정지해 놓은 경우
  • EBS
    • EBS 사용량이 30GB를 넘어가는 경우
      • EC2인스턴스를 생성할때 AMI를 CentOS로 선택한 경우 EBS가 기본 8기가가 할당됩니다. 근대 생성할때 Delete on Termination을 체크하지 않고 생성하면, EC2인스턴스를 삭제할때 자동으로 EC2에 할당된 EBS가 삭제되지 않습니다. 그래서 여러번 인스턴스를 생성했다 삭제할 경우 EBS가 계속 쌓여서 30GB가 넘는 경우가 발생합니다.
      • 이걸 피하는 방법은 EC2인스턴스를 생성할때 Delete on Termination을 키고서 생성하시거나, EC2인스턴스를 삭제할때 EC2->ELSTIC BLOCK STORAGE->Volumes에서 EBS도 같이 삭제 하셔야 합니다.
      • 저 같은 경우엔 이번달에 chef 사용법을 익히느라 EC2인스턴스를 많이 생성하고 삭제 했더니 안지운 EBS가 40개가량 쌓여 있었고 EBS로만 40.57$라는 요금 폭탄을 맞았내요. ㅜㅜ

AWS S3 버킷에 추가되는 모든 파일을 누구나 다운받을 수 있게 정책 추가하기

S3 버킷에 파일이 추가될때, 기본적으로 파일을 다운로드 받을수 있는 권한은 계정소유자만 가지게 됩니다. 보안상 당연이 그렇게 처리되야 하는 부분이죠.

하지만 누구나 다운로드 받게 할 용도로 S3 버킷을 만든경우, 파일을 올릴때마다 일일이 누구나 다운로드 받게 퍼미션을 추가하는 일은 귀찮습니다. 특히나 단순 파일이 아니라 폴더형태로 복잡하게 많은 파일을 올리는 경우에는요.

그럴때 S3 버킷 정책에 누구나 다운로드 받을수 있는 정책을 추가하면 편리 합니다.

1. AWS Policy Generator 접속

2. 정책 설정

  • Select Type of Policy : S3 Bucket Policy
  • Effect : Allow
  • Principal : *
  • Actions : GetObject
  • Amazon Resource Name (ARN) : arn:aws:s3:::누구나다운받게할버킷이름/*

3. 정책 생성

  • Add Statement 클릭
  • Generate Policy 클릭
  • 생성된 정책 확인 : 대략 아래와 같은 형태의 JSON이 나오면 됩니다(Id와 Sid는 다를겁니다).
    {
     "Id": "Policy1386756553403",
     "Statement": [
     {
     "Sid": "Stmt1386756999855",
     "Action": [
     "s3:GetObject"
     ],
     "Effect": "Allow",
     "Resource": "arn:aws:s3:::누구나다운받게할버킷이름/*",
     "Principal": {
     "AWS": [
     "*"
     ]
     }
     }
     ]
    }
    

4. 정책 적용

  • S3 -> 누구나다운받게할버킷선택 -> Permission -> Edit bucket policy -> json형태의 정책 붙여놓기 -> save 클릭

EC2에 생성된 chef-node를 role단위로 업데이트하는 방법

chef-repo 폴더안에 updatenode.sh라는 아래와 같은 스크립트를 만듭니다.

knife node list | while read line; do
 role=`knife node show $line -a roles | awk 'FNR==2' | sed "s/ roles: //g"`
 fqdn=`knife node show $line -a fqdn | awk 'FNR==2' | sed "s/ fqdn: //g"`
 if [ "$role" == $1 ]; then
 ssh root@$fqdn -i yours.pem chef-client
 fi
done

위 스크립트의 yours.pem은 EC2에 ssh로 접속하기위해 사용하는 pem 파일을 사용하시면 됩니다.

사용법은 updatenode.sh [role이름]으로 하시면 됩니다.
ex) $ updatenode.sh was

AWS CloudWatch에서 CentOS의 메모리와 디스크 사용량을 모니터링 하는 방법

아쉽게도 CloudWatch가 기본으로 제공하는 EC2 metrics에는 메모리와 디스크 사용량이 포함되어 있지 않습니다. 하지만 아래 링크를 보고 따라하면 custom metrics 형태로 모니터링 할 수 있습니다.

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

문제는 CentOS에서는 위 링크대로 잘 되지 않습니다. Prerequisites 부분부터 막히게 됩니다. 그 부분만 넘어가면 나머지는 문제없이 잘 되구요.

삽질하다가 쉽게 Prerequisites관련 부분을 해결할수 있는 방법을 찾게되서 공유합니다.

$ yum -y install wget make gcc perl-ExtUtils-CBuilder cpan
$ wget http://xrl.us/cpanm -P /usr/bin
$ chmod +x /usr/bin/cpanm
$ cpanm -f Bundle::LWP5_837

Prerequisites 관련되서 설정하는 부분을 위 방법으로 대체하시고 Getting Started부터 진행 하시면 됩니다.

AWS EC2 user-data를 이용해서 chef node를 설정 및 생성하는 AMI 만들기

1. 깨끗한 CentOS AMI로 EC2 인스턴스 생성

2. chef-client 및 유틸리티 프로그램 설치

# install chef-client
curl -L https://www.opscode.com/chef/install.sh | bash
# install wget
yum -y install wget
# install jsonparser
wget http://stedolan.github.io/jq/download/linux64/jq -P /usr/bin
chmod +x /usr/bin/jq
# make chef directory
mkdir /etc/chef

3. validation.pem 복사

chef-server의 /root/chef-repo/.chef/chef-validator.pem을
chef-client의 /etc/chef/validation.pem으로 복사

4. startup.sh 생성 및 부팅할때 실행되도록 /etc/rc.local에 startup.sh 등록

startup.sh는 Using Chef to bootstrap AutoScaled EC2 instance 에 있는 스크립트를 이용해서 만들었습니다.

#!/bin/bash

# The script is set to run at multiple RC runlevels so make sure it can only be ran once
if [ -f /etc/chef/chef-bootstrap.done ]
then
 exit
fi
touch /etc/chef/chef-bootstrap.done

# define a function for later use
function getmeta() {
 wget -qO- http://169.254.169.254/latest$1
}

# get EC2 meta-data
env=`(getmeta /user-data) | jq '.chef' | jq '.env'`
jsonattribute=`(getmeta /user-data) | jq '.chef' | jq '.jsonattribute'`
runlist=`(getmeta /user-data) | jq '.chef' | jq '.jsonattribute' | jq '.run_list'`
hostname="$(getmeta /meta-data/local-hostname)"

# write first-boot.json to be used by the chef-client command.
# this sets the ROLE of the node.
echo -e $jsonattribute >> /etc/chef/first-boot.json

# write client.rb
# this sets the ENVIRONMENT of the node, along with some basics.
echo -e "log_level :info" >> /etc/chef/client.rb
echo -e "log_location STDOUT" >> /etc/chef/client.rb
echo -e "chef_server_url 'https://ip-172-31-23-206.ap-northeast-1.compute.internal'" >> /etc/chef/client.rb
echo -e "validation_client_name 'chef-validator'" >> /etc/chef/client.rb
echo -e "environment $env" >> /etc/chef/client.rb

# append the node FQDN to knife.fb
echo -e "node_name '$hostname'" >> /etc/chef/knife.rb

# run chef-client to register the node and to bootstrap the instance
chef-client -d -j /etc/chef/first-boot.json

5. 해당 EC2 인스턴스를 AMI로 저장.

6. AMI로 EC2 인스턴스를 만들때 user-data에 JSON형식으로 node 설정 정보를 포함시킨다.

아래와 같은 user-data를 입력하여 생성된 node에는 6379 port를 사용하는 redis master와 6380 port를 사용하는 redis slave가 설치되어 실행되게 됩니다. 단 이링크를 수행하셔서 redisio cookbook이 설치되어 있고, role에 redis가 추가 되어있는 경우에만 가능합니다.

run_list 및 env를 상황에 맞게 변경하시고, 필요한 attributes를 추가해서 사용하시면 됩니다.

{ "chef": {
 "env" : "dev",
 "jsonattribute" : {
 "run_list": ["role[primarydb]"],
 "redisio" : {
 "servers" : [
 {"port" : "6379"},
 {"port" : "6380", "slaveof" : { "address" : "127.0.0.1", "port" : "6379" }}
 ]
 }
 }
 }
}

MongoDB의 질의 결과를 file에 저장하기

1. 질의 스크립트를 생성해주세요.
query.js

var dbname = 'log';
var db = db.getSiblingDB(dbname);
var cursor = db.ItemLogData.find();

while(cursor.hasNext()) {
 printjson(cursor.next());
}

query.js의 내용중에 dbname과 collection, 질의 내용을 본인에 맞게 수정해주세요.

2 mongo 명령어를 사용해서 질의 스크립트를 실행해주시면 됩니다.
$mongo –quiet query.js > result.txt

Chef 서버가 설치된 머신의 IP가 변경 되었을때 같이 변경해주어야 하는것

AWS에서 학습용으로 CentOS에 Chef서버를 설치한 후, 유지비가 아쉬어서 인스턴스를 꺼두었다가 다시 공부하기 위해 켰습니다. Chef서버가 설치된 인스턴스의 IP는 기존과 달라졌고, 기존에 잘 작동하던 Chef의 knife명령어가 작동을 하지 않게 되었습니다.

[root@ip-172-31-21-96 chef-repo]# knife client list
ERROR: Server returned error for https://54.238.235.209/clients, retrying 1/5 in 3s
ERROR: Server returned error for https://54.238.235.209/clients, retrying 2/5 in 7s
ERROR: Server returned error for https://54.238.235.209/clients, retrying 3/5 in 11s
ERROR: Server returned error for https://54.238.235.209/clients, retrying 4/5 in 19s
ERROR: Server returned error for https://54.238.235.209/clients, retrying 5/5 in 63s
ERROR: bad gateway
Response: <html>
<head><title>502 Bad Gateway</title></head>
<body bgcolor="white">
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx/1.2.3</center>
</body>
</html>

몇시간의 삽질끝에 위 에러는 knife.rb를 수정하면서 해결했습니다.

  • $vi /root/chef-repo/.chef/knife.rb
  • chef_server_url  항목을 변경된 IP로 수정

그 후 테스트로 knife ec2 server create를 해보니 cookbook syncing 하는 단계에서 문제가 있내요.

ec2-54-238-153-102.ap-northeast-1.compute.amazonaws.com Synchronizing Cookbooks:
ec2-54-238-153-102.ap-northeast-1.compute.amazonaws.com
ec2-54-238-153-102.ap-northeast-1.compute.amazonaws.com ================================================================================
ec2-54-238-153-102.ap-northeast-1.compute.amazonaws.com Error Syncing Cookbooks:
ec2-54-238-153-102.ap-northeast-1.compute.amazonaws.com ================================================================================
ec2-54-238-153-102.ap-northeast-1.compute.amazonaws.com
ec2-54-238-153-102.ap-northeast-1.compute.amazonaws.com
ec2-54-238-153-102.ap-northeast-1.compute.amazonaws.com Networking Error:
ec2-54-238-153-102.ap-northeast-1.compute.amazonaws.com -----------------
ec2-54-238-153-102.ap-northeast-1.compute.amazonaws.com Error connecting to https://ip-172-31-19-139.ap-northeast-1.compute.internal/bookshelf/organization-00000000000000000000000000000000/checksum-cab742118ad189a0ce294a7237aacd66?AWSAccessKeyId=5e7260ff7bfe2c7401f4695883b2d47382cc2268&Expires=1384651008&Signature=xfBGBilY9jsKRXCkXbB1/tUT6qM%3D - Connection timed out - connect(2)
ec2-54-238-153-102.ap-northeast-1.compute.amazonaws.com
ec2-54-238-153-102.ap-northeast-1.compute.amazonaws.com Your chef_server_url may be misconfigured, or the network could be down.

결국 또 몇시간의 삽질끝에 chef-pedant와 erchef의 설정을 수정해서 해결했습니다.

  • $vi /var/opt/chef-server/chef-pedant/etc/pedant_config.rb
  • chef_server 항목을 변경된 IP로 수정
  • $vi /var/opt/chef-server/erchef/etc/app.config
  • {s3_url, 항목을 변경된 IP로 수정
  • $chef-server-ctl restart

결론은 Chef서버 IP가 바뀌면 이것저것 귀찮게 수정해줘야 하는게 있으니 되도록 Chef서버 IP는 바꾸지 맙시다. ㅜㅜ

————————————————내용추가————————————————

결론을 위와 같이 내리려다가 연습용 인스턴스를 계속 켜두기에는 돈이 아까워서, 서버가 실행될때 현재IP로 위 내용을 수정하는 스크립트를 만들었습니다.

startup.sh

#!/bin/sh

knife_replacefrom="chef_server_url.*"
knife_replaceto="chef_server_url ""\'https:\/\/"`hostname -f`":443\'"
sed -i "s/$knife_replacefrom/$knife_replaceto/g" /root/chef-repo/.chef/knife.rb

pedant_replacefrom="chef_server.*"
pedant_replaceto="chef_server ""\"https:\/\/"`hostname -f`"\""
sed -i "s/$pedant_replacefrom/$pedant_replaceto/g" /var/opt/chef-server/chef-pedant/etc/pedant_config.rb

erchef_replacefrom="{s3_url,.*"
erchef_replaceto="{s3_url, ""\"https:\/\/"`hostname -f`"\"},"
sed -i "s/$erchef_replacefrom/$erchef_replaceto/g" /var/opt/chef-server/erchef/etc/app.config

/opt/chef-server/bin/chef-server-ctl restart

startup.sh를 실행하도록 /etc/rc.local을 수정해주세요.

ps : AWS에서 Chef 서버는 최소 m1.small이상에서 돌려 주세요. t1.micro는 사양 문제로 알수없는 오류가 많이 납니다.

실수로 AWS AMI를 날려 먹을뻔한 이야기;

여러 Region을 사용하기 위해서 작업을 하고 있는 중입니다.
Region마다 서로 다른 Key Pairs를 사용하기 귀찮아서 단일 Key Pairs를 사용할수 없나 검색 해보니, 기존에 AWS에서 생성한 Key Pairs는 사용할수 없고 직접 키를 하나 생성해서 여러 Region의 Key Pairs에 등록하라는 내용이 나오더군요.

아무 생각없이 기존 Key Pairs는 삭제하고, 직접 키를 생성해서 Key Pairs에 등록했습니다. 그리고 기존 AMI로 EC2를 만들어서 새로 생성한 키로 접속을 시도해 보니 왠걸 유효하지 않은 키라고 로그인이 되지를 않더군요.

키를 잘못 만들었나 싶어서 다시 계속 생성해서 시도해 봐도 안됐습니다. 혹시나 싶어서 기존 생성된 AMI말고 Market에 있는 CentOS AMI로 시도해보니 잘되내요.

알고보니 기존 AMI를 이용해서 새로운 Key Pairs로 EC2를 생성해도, AMI에 포함된 authorized_keys를 새로운 Key Pairs의 public key로 갱신을 안해주더군요.

어떻게든 authorized_keys에만 접근해서 수정하면 되는 문제라고 생각되서, 기존 AMI에서 Volume만 띠어내서 Market의 CentOS AMI로 만든 EC2에 붙이려고 했습니다.

하지만 “‘vol-xxxxxxxx’ with Marketplace codes may not be attached as a secondary device.”라는 에러가 뜨면서 절대 붙지를 않더군요. 검색 해보니 Market 보안 문제 이슈로 제공을 안하고 있고, AWS Marketplace team은 이를 지원하기 위해서 열심이 노력중이라는군요.

그걸 보고 잠시 멘붕이 왔습니다. 하하;

멘탈을 잠시 회복하고 생각을 해보니, private key를 구글드라이브에도 보관하고 있었으니 휴지통에 남아있을 거라는 생각이 들었습니다. 뒤져보니 다행이 private key가 휴지통에 곱게 모셔저 있더군요!

휴지통에서 건진 private key로 public key를 만들어서 Key Pairs를 등록하니 다행이 기존 AMI에서 만든 EC2에 접속이 가능 해졌습니다.

그때 뭔가 문득 떠올라서 다른 Region에도 똑같은 방식으로 Key Pairs를 등록했더니 다른 Region에서도 잘 사용 되내요.

그냥 자기가 기존에 만들어서 사용하던 Key Pairs의 private key로 public key 만들어서 다른 Region에 등록하면 되는거 였던 겁니다.

이렇게 쉬운걸 지금까지 삽질하고 있었다니… ㅜㅜ

삽질한걸 적다보니 스크롤이 많이 길어 졌내요. 짧게요약하면 아래와 같습니다.

1. 기존 AMI에 새로운 Key Pairs를 사용해서 EC2를 만들어도, AMI가 포함하고 있는 authorized_key는 갱신되지 않는다.
2. 새로운 Region에 기존 사용하던 Key Pairs를 사용하고 싶으면, 기존 Key Pairs의 private key로 publick key만 만들어서 새로운 Region의 Key Pairs에 등록하면 된다.

3. AMI로 생성한 EC2의 Volume은 다른 EC2에 붙일수 없다(이걸 허용하면 AWS Marketplace vendor software의 보안에 문제가 생길수 있어서 현재 막혀있다).

AWS의 여러 Region에서 단일 KeyPairs를 사용하기

  1. 기존에 Key Pairs를 생성할때 다운받은 privatekey(확장자가 pem)를 준비한다.
  2. PuTTY Key Generator 실행
    1. Conversions -> Import Key에서 준비한 privatekey를 불러온다.
    2. Save public key를 눌러서 publickey를 저장한다.
  3. AWS Console 접속 및 다른 Region으로 이동
    1. EC2 -> Key Pairs -> Import Key에서 준비한 publiickey를 불러온다.
  4. 끝~