TerraformでEC2のインスタンスプロファイルを生成する

TerraformでEC2のインスタンスプロファイルを生成する

解説

まずData Sourceを用いてIAMのロールを生成します。

data "aws_iam_policy_document" "ec2-role" {

  statement {
    effect = "Allow"

    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }
  }
}

上記を元に実際に生成されたロールは下記のようになります。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      }
    }
  ]
}

同じくData Sourceを用いてポリシーを作成します。

data "aws_iam_policy_document" "ec2-role_policy" {
  statement {
    effect = "Allow"
    actions = [
        "autoscaling:Describe*",
        "cloudwatch:*",
        "logs:*",
        "sns:*",
    ]

    resources = [
      "*",
    ]
  }
}

上記を元に実際に生成されたポリシーは下記のようになります。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Action": [
        "sns:*",
        "logs:*",
        "cloudwatch:*",
        "autoscaling:Describe*"
      ],
      "Resource": "*"
    }
  ]
}

次に、生成されたJSONデータをロール、ポリシーに割り当てます。

# Role
resource "aws_iam_role" "ec2-role" {
  name               = "${var.general_name}-ec2-role"
  assume_role_policy = "${data.aws_iam_policy_document.ec2-role.json}"
}
# Role END

# Role-Policy
resource "aws_iam_role_policy" "ec2-role_policy" {
  name   = "${var.general_name}-ec2-role-policy"
  role   = "${aws_iam_role.ec2-role.id}"
  policy = "${data.aws_iam_policy_document.ec2-role_policy.json}"
}
# Role-Policy END

下記のようにすることで、生成されたJOSNデータを割り当てることができます。

assume_role_policy = "${data.aws_iam_policy_document.ec2-role.json}"

policy = "${data.aws_iam_policy_document.ec2-role_policy.json}"

まとめるとこんな感じ

iam.tf
# IAM Role for EC2
data "aws_iam_policy_document" "ec2-role" {

  statement {
    effect = "Allow"

    actions = ["sts:AssumeRole"]

    principals {
      type        = "Service"
      identifiers = ["ec2.amazonaws.com"]
    }
  }
}
# IAM Role for EC2 END

# IAM Role Policy for EC2
data "aws_iam_policy_document" "ec2-role_policy" {
  statement {
    effect = "Allow"
    actions = [
        "autoscaling:Describe*",
        "cloudwatch:*",
        "logs:*",
        "sns:*",
    ]

    resources = [
      "*",
    ]
  }
}
# IAM Role Policy for EC2 END

# IAM Instance Profile
resource "aws_iam_instance_profile" "ec2-profile" {
  name  = "ec2-profile"
  roles = ["${aws_iam_role.ec2-role.name}"]
}
# IAM Instance Profile END

# Role
resource "aws_iam_role" "ec2-role" {
  name               = "${var.general_name}-ec2-role"
  assume_role_policy = "${data.aws_iam_policy_document.ec2-role.json}"
}
# Role END

# Role-Policy
resource "aws_iam_role_policy" "ec2-role_policy" {
  name   = "${var.general_name}-ec2-role-policy"
  role   = "${aws_iam_role.ec2-role.id}"
  policy = "${data.aws_iam_policy_document.ec2-role_policy.json}"
}
# Role-Policy END

続きを読む

AWS サービス別 APIプロトコル一覧

Pythonのbotocoreに入っているメタデータから持ってきた。

サービス名 API protocol
acm json
apigateway rest-json
application-autoscaling json
appstream json
athena json
autoscaling query
batch rest-json
budgets json
clouddirectory rest-json
cloudformation query
cloudfront rest-xml
cloudhsm json
cloudsearch query
cloudsearchdomain rest-json
cloudtrail json
cloudwatch query
codebuild json
codecommit json
codedeploy json
codepipeline json
codestar json
cognito-identity json
cognito-idp json
cognito-sync rest-json
config json
cur json
datapipeline json
dax json
devicefarm json
directconnect json
discovery json
dms json
ds json
dynamodb json
dynamodbstreams json
ec2 ec2
ecr json
ecs json
efs rest-json
elasticache query
elasticbeanstalk query
elastictranscoder rest-json
elb query
elbv2 query
emr json
es rest-json
events json
firehose json
gamelift json
glacier rest-json
greengrass rest-json
health json
iam query
importexport query
inspector json
iot rest-json
iot-data rest-json
kinesis json
kinesisanalytics json
kms json
lambda rest-json
lex-models rest-json
lex-runtime rest-json
lightsail json
logs json
machinelearning json
marketplace-entitlement json
marketplacecommerceanalytics json
meteringmarketplace json
mturk json
opsworks json
opsworkscm json
organizations json
pinpoint rest-json
polly rest-json
rds query
redshift query
rekognition json
resourcegroupstaggingapi json
route53 rest-xml
route53domains json
s3 rest-xml
sdb query
servicecatalog json
ses query
shield json
sms json
snowball json
sns query
sqs query
ssm json
stepfunctions json
storagegateway json
sts query
support json
swf json
waf json
waf-regional json
workdocs rest-json
workspaces json
xray rest-json

続きを読む

AutoScaling環境においてGitを使わないでEC2を冗長化する方法

制約

Git禁止(協力会社がFTPしか使えないため)

結論

  1. Master Serverを建てる
  2. Master Serverのファイルの更新をlsyncdで監視し、常にS3と同期する
  3. 任意のタイミングでSlave Server(ELB配下の全EC2インスタンス)をS3と同期する

イメージ図

だいたいこんな感じ

AutoScaling環境においてGitを使わないでEC2を冗長化する方法

Master Server編

1. S3バケットを作成する

公式サイトに詳しい方法が書いてあります。
S3 バケットを作成する方法 – Amazon Simple Storage Service

2. AWS CLIを設定する

公式サイトに詳しい方法が書いてあります。
AWS CLI の設定 – AWS Command Line Interface

3. lsyncdをインストールする

EPELリポジトリを利用してインストールします。

$ sudo yum install --enablerepo=epel lsyncd

4. lsyncdの設定を変更する

普通の書き方だとファイル名の末尾に/(スラッシュ)が混入してエラーが出たりうまくsyncしてくれなかったので、
下記のような感じでパースしてあげる必要があります。
komeda-shinjiさんの記事がとても参考になりました。ありがとうございます。

$ sudo vim /etc/lsyncd.conf
/etc/lsyncd.conf

source_dir = "/var/www/source"
s3bucket = "files.hoge.com"
prefix = "source"

snscmd = "echo !!! error "

settings {
    logfile    = "/var/log/lsyncd.log",
    statusFile = "/var/log/lsyncd.status",
    nodaemon = false,
    statusInterval = 1,
    delay = 5,
}

cp = function(event)
  local src_path = event.sourcePathname
  local dst_path = event.targetPathname

  if (string.sub(event.source, -1, -1) == "/") then
      src_path = string.sub(event.source, 1, -2) .. event.pathname
  end
  if (string.sub(event.target, -1, -1) == "/") then
      dst_path = string.sub(event.target, 1, -2) .. event.pathname
  end
  local s3cmd = "aws s3 cp '" .. src_path .. "' '" .. dst_path .. "'"
  local msg_body = "command failed: " .. s3cmd
  local msg = " --message '" ..  string.gsub(msg_body, "'", "\"") .. "'"


  local runcmd = "rc=0 && [ -f '" .. src_path .. "' ] && for try in 1 2 3; do " .. s3cmd .. "; rc=$?; [ $rc -eq 0 ] && break; done || " .. snscmd .. msg .. " || :"
  spawnShell(event, runcmd)
end

rm = function(event)
  local src_path = event.sourcePathname
  local dst_path = event.targetPathname

  if (string.sub(event.source, -1, -1) == "/") then
      src_path = string.sub(event.source, 1, -2) .. event.pathname
  end
  if (string.sub(event.target, -1, -1) == "/") then
      dst_path = string.sub(event.target, 1, -2) .. event.pathname
  end

  local s3cmd = "aws s3 rm '" .. dst_path .. "'"
  local msg_body = "command failed: " .. s3cmd
  local msg = " --message '" ..  string.gsub(msg_body, "'", "\"") .. "'"
  local runcmd = "rc=0 && [ ! -f '" .. src_path .. "' ] && for try in 1 2 3; do " .. s3cmd .. "; rc=$?; [ $rc -eq 0 ] && break; done || " .. snscmd .. msg .. " || :"
  spawnShell(event, runcmd)
end

mv = function(event)
  local src_path = event.o.targetPathname
  local dst_path = event.d.targetPathname

  if (string.sub(event.o.target, -1, -1) == "/") then
      src_path = string.sub(event.o.target, 1, -2) .. event.o.pathname
  end
  if (string.sub(event.d.target, -1, -1) == "/") then
      dst_path = string.sub(event.d.target, 1, -2) .. event.d.pathname
  end
  local s3cmd = "aws s3 mv '" .. src_path .. "' '" .. dst_path .. "'"
  local msg_body = "command failed: " .. s3cmd
  local msg = " --message '" ..  string.gsub(msg_body, "'", "\"") .. "'"

  local runcmd = "rc=0 && [ -f '" .. src_path .. "' ] && for try in 1 2 3; do " .. s3cmd .. "; rc=$?; [ $rc -eq 0 ] && break; done || " .. snscmd .. msg .." || :"
  spawnShell(event, runcmd)
end

s3sync = {
    maxProcesses = 1,
    onCreate = cp,
    onModify = cp,
    onDelete = rm,
--  onMove = mv,
}

sync {
    s3sync,
    source = source_dir,
    target = "s3://" .. s3bucket .. "/" .. prefix,
}

5. lsyncdを起動する

$ sudo /etc/rc.d/init.d/lsyncd start
$ sudo chkconfig lsyncd on
$ /etc/rc.d/init.d/lsyncd status
lsyncd (pid  12345) is running...

6. Sourceを変更する

$ vim /var/www/source/hoge.txt
/var/www/source/hoge.txt
hogehoge

7. Sourceの変更がS3に反映しているか確認する

$ tailf /var/log/lsyncd.log

Slave Server編

1. AWS CLIを設定する

公式サイトに詳しい方法が書いてあります。
AWS CLI の設定 – AWS Command Line Interface

2. S3のSourceをローカルに同期するシェルスクリプトを作成する

$ vim /usr/local/bin/s3sync.sh
/usr/local/bin/s3sync.sh
#!/bin/sh
SOURCE_DIR="/var/www"
S3_BUCKET="files.hoge.com"
PREFIX="source"

TARGET_MASTER="s3://${S3_BUCKET}/${PREFIX}/"
TARGET_LOCAL="${SOURCE_DIR}/${PREFIX}/"

aws s3 sync ${TARGET_MASTER} ${TARGET_LOCAL} --delete

3. 同期スクリプトをEC2インスタンス起動時に実行するように設定する

$ vim /etc/rc.local
/etc/rc.local
s3sync.sh
exit 0

※ちなみに、rc.localに書かれたスクリプトはroot権限で実行されます。

4. 任意のタイミングで同期スクリプトを実行する

 cronするなり、execするなり

ボツ案

Master Server+rsyncパターン

s3Syncパターン

s3fsパターン

NFSパターン

AMIを最新にしてから起動するパターン

続きを読む

Auto ScalingのLifeCycleHookがマネジメントコンソールから作成できるようになりました

まいど、大阪の市田です。 Auto Scalingでは「LifeCycleHook」という機能を使って、インスタンスの起動/破棄時にユーザが処理をフックして独自のアクションを実行することが可能です。 この機能を使う時、こ […] 続きを読む

PackerでLaunch Configuration作るPlugin書いた

私はTerraformとPackerをよく使います。
しかしAutoScalingとLaunch Configurationの関係でいつも困ります。
卵が先か鶏が先かみたいな話で依存関係があります。
私はTerraformでLaunch Configurationを管理するのに疲れました。

そして別のアプローチ方法を取ることにしました。
それが今回作った、 packer-post-processor-amazon-launchconfiguration になります。
このプラグインはPackerのpost-processorの部分でLaunch Configurationを作成することができるプラグインです。
そしてオプションとしてAuto Scaling GroupのLaunch Configurationの値を更新することができます。
AMI作成 -> Launch Configuration作成 -> Auto Scaling Groupの更新が一つのJSONファイルで管理できます。
CIとも相性が良いように今後改善していきたいです。

https://github.com/a4t/packer-post-processor-amazon-launchconfiguration

Packerで管理することで変わること

TerraformとPackerを使った構成でよくある課題

  • Packerで作成したAMIをtfファイルに反映させる方法
  • UserData変わった際にLaunch Configurationが再作成されるが、Auto Scaling Groupとの依存関係

AMIは頻繁に更新した方がいいです。
OpenSSLの脆弱性とかあった際にはインスタンスの再起動がない場合、アップデートが反映されません。
気軽にLaunch Configurationは更新できるようにしておきたいです。
毎デプロイごとにAuto Scaling Groupを更新してもいいかもしれません。
Terraformで管理する場合はAMI作成 -> tfファイルにAMI反映という流れでしたが、その手間がなくなります。

使い方

こちらは基本的なAMI作成時のPackerのJSONです。

{
  "builders": [{
    "type": "amazon-ebs",
    "vpc_id": "vpc-xxxxxxxxxx",
    "subnet_id": "subnet-yyyyyyyyyy",
    "region": "ap-northeast-1",
    "source_ami": "ami-4af5022c",
    "instance_type": "t2.micro",
    "ssh_username": "ec2-user",
    "ami_name": "my-service-{{timestamp}}"
  }]
}

これに+αでこのような値を追加します。

{
  "builders": [{
  .
  .
  .
  }],
  "post-processors":[{
    "type": "amazon-launchconfiguration",
    "config_name_prefix": "my-service-",
    "instance_type": "c4.large",
    "keep_releases": 3
  }]

こちらの設定を簡単に説明すると

  • type

    • plugin名
  • config_name_prefix
    • Launch ConfigurationのPrefix、Prefixの後ろに作成時日付が入る(例: my-service-20170911075353)
  • instance_type
    • 説明不要
  • keep_releases
    • Launch Configurationのrotateの設定、config_name_prefixの後ろを見て古い方から削除していく

Auto Scaling Groupの更新

Auto Scaling Groupの更新は追加でオプションをつけます。

  "post-processors":[{
    "type": "amazon-launchconfiguration",
    "config_name_prefix": "my-service-",
    "instance_type": "c4.large",
    "keep_releases": 3,
    "auto_scaling_group_names": [
      "my-autoscaling-1",
      "my-autoscaling-2"
    ]
  }]

Pluginの導入方法

ここから自分にあった環境を拾ってきてください
https://github.com/a4t/packer-post-processor-amazon-launchconfiguration/releases

そしてPATHの通ったところに packer-post-processor-amazon-launchconfiguration を配置してください
~/.packer.d/plugins が最善かと思います。

おまけ

AMIもRotateしてどんどん削除した方がいいと思うので、こちらも使うといいかもしれません。
http://tech.sideci.com/entry/2016/08/18/130609

packer-post-processor-amazon-launchconfiguration
https://github.com/a4t/packer-post-processor-amazon-launchconfiguration

続きを読む

EC2が止まったらS3に「死にました」と投稿する

概要

EC2インスタンスのシャットダウンをトリガーに、何か処理を実行する方法を記します。
今回はS3に辞世の句を投稿していますが、AutoScalingでterminateされるEC2のlocalのsyslogをS3に転送する等の処理にも応用できます。

やり方

S3編

S3にバケットを作成する

death_poem_1_1.png
  ※S3のバケット名はFQDNにしておくと色々捗る(余談) 

IAM編

S3にフルアクセスできるIAMを作成する

death_poem_2_1.png

death_poem_2_2.png

death_poem_2_3.png

death_poem_2_4.png

death_poem_2_5.png

 ※アクセスキーIDとシークレットアクセスキーは後で使うのでメモ帳にコピペしてください 

EC2編

1.AWS CLIをインストールする

 ※Amazon Linuxの場合は不要です  

//pipのインストール
# curl -O https://bootstrap.pypa.io/get-pip.py

//Python を使用してスクリプトを実行
# python get-pip.py --user

//PATH 変数に実行可能パスを追加
# export PATH=~/.local/bin:$PATH
# source ~/.bash_profile

//pipが正しくインストールされたことを確認
# pip --version

//pip を使用して AWS CLI をインストール
# pip install awscli --upgrade --user

//AWS CLI が正しくインストールされたことを確認
# aws --version

2.AWS CLIの初期設定をする

# aws configure

AWS Access Key ID [None]: [アクセスキーID]
AWS Secret Access Key [None]: [シークレットアクセスキー]
Default region name [None]: [空でok]
Default output format [None]:[空でok]

3.辞世の句スクリプトを作成する

# vim /etc/rc.d/init.d/DeathPoem.sh
/etc/rc.d/init.d/DeathPoem.sh

#!/bin/sh

InstanceId=`wget -q -O - http://169.254.169.254/latest/meta-data/instance-id`

declare logdir=/var/www/log
declare log=/death_poem.log
declare bucket=files.hoge.com
declare now=`date +'%Y-%m-%d'`
declare s3_target="s3://${bucket}/death_poem_${now}/"

mkdir $logdir >/dev/null 2>&1

printf 'I am '$InstanceId'¥n' >> $logdir$log
printf 'I was born 'date --date=@$(expr `date +%s` - `cut -d "." -f 1 /proc/uptime`) >> $logdir$log
printf 'I was just 'cat /proc/uptime | awk '{print $1 / 60 /60 /24 "days (" $1 "sec)"}' |  tr -d '¥n''  from birth ''¥n' >> $logdir$log
printf 'I will die 'date'¥n¥n' >> $logdir$log

aws s3 sync $logdir $s3_target

4.辞世の句スクリプトに実行権限を与える

# chmod 755 /etc/rc.d/init.d/DeathPoem.sh

5.rc.local(起動時実行)を編集する

# vim /etc/rc.d/rc.local
/etc/rc.d/rc.local

#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.

touch /var/lock/subsys/local

/sbin/ethtool -s eth0 wol g

touch /var/lock/subsys/DeathPoem
ln -s /etc/init.d/DeathPoem.sh /etc/rc0.d/K00DeathPoem
ln -s /etc/init.d/DeathPoem.sh /etc/rc6.d/K00DeathPoem

6.EC2インスタンスを再起動する

# reboot

7.ログを確認する

# tailf /var/www/log/death_poem.log
/var/www/log/death_poem.log

I am i-************
I was born Mon Sep 11 04:00:48 UTC 2017
I was just 0.00817488days (706.31sec)  from birth 
I will die Mon Sep 11 04:12:34 UTC 2017

8.S3のバケットを確認する

上記と同じ内容の辞世の句が投稿されているはず!

余談

昔は簡単だった(らしい)

EC2で起動時やterminate時にシェルを実行する | Developers.IO

mytest.sh
#!/bin/sh
# chkconfig: 2345 99 10
# description: test shell

case "$1" in
 start)
       echo "start!" > /path/your/start.txt
       ;;
 stop)
       echo "stop!" > /path/your/stop.txt
       ;;
  *) break ;;
esac

あのクラスメソッドさんが書いた記事なら間違いない!
…と思っていたのですが、上記の方法では”start”のイベントしか取得できませんでした。
コメントにあったprocessnameを追加しても結果は同様でした。
原因をご存じの方いたらぜひ教えて欲しいです :bow:

とても参考になった文献

CentOS6.0 Shutdown時にコマンド実行 : 事象の水平線 :

リスペクト

心臓が止まったらSNSに「死にました」と投稿する

続きを読む

AWS Solutions Architect Associate合格までの勉強法

タイトル通りです。同類の記事を受験前にかき集めて分析して、自分なりの計画を立てて約1ヶ月ほどで合格できました。他の方の記事がすごく助かったので、私もその後に続いてどんな風に勉強したかポストしたいと思います。

前提

DBAとして2年目のエンジニアです。普段はOracleとMySQLです。受験半年前におもしろそうなのであんど今後クラウドの1つは知らないとな〜、とか思って「Amazon Web Services実践入門 (WEB+DB PRESS plus)」を読んだりしていました。

また、手を動かすという意味で「Amazon Web Services 基礎からのネットワーク&サーバー構築」をざーっとやったことがありました。この本はインフラはじめてですみたいな方向けに書かれたAWSを実際に動かしながら勉強しようみたいな本で、AWS初めて触る人にはおすすめです。

勉強開始前にしたこと

計画の立て方としてはあくまで資格の合格に重きを置こうと思ってました。とは言え色々な人の記事を見ていくと、「あぁこれちゃんと動かしたりしないと合格できないやつや」と気付きました。

加えて資格対策として出版されてる本は以下に書いたのですが、これしかないので演習をどうしようか悩みました。いくら資料を大量に読んでも試験ポイントを掴まないと、最大の目的である合格できないのはつらいためです。探していたらudemyで良さげな試験対策問題集を販売している方がいて、かつudemyがセールやってて2000円ぐらいで購入できたのでそれをやりました。本番の問題がどんな感じか体験して、回答までどうやって考えるか練習になったので良かったです。(ただ的中率という意味では高くはないなと思いました。)
今見たらセール終わってて2万円(高い!)になっているのですが、udemyは頻繁にセールやっているイメージなので確認してみるといいかもしれません。

また、AWSのテスト要項とすでに合格した人の体験談を集めて、どのサービスにどれくらいの比重を置いて対策をするか気にしながら受験日まで学習を行いました。SAの範囲にどのAWSサービスが含まれるか未知数ですが、多くの問題はどのサービスから出るのかは決まってくるみたいなのでテストに出なさそうなサービスは割り切ってほんとに表面の概要レベルだけ頭に入れました。

使用したもの

<書籍>
合格対策 AWS認定ソリューションアーキテクト – アソシエイト
Amazon Web Services パターン別構築・運用ガイド 一番大切な知識と技術が身につく

<ネット資料>
BlackBelt
クラウドデザインパターン(Web版のみ)
http://aws.clouddesignpattern.org/index.php/%E3%83%A1%E3%82%A4%E3%83%B3%E3%83%9A%E3%83%BC%E3%82%B8

<演習>
udemy
https://www.udemy.com/aws-certified-solutions-architect-associate/

サービスの重点

以下個人的な感覚でのランク付けです。あくまでご参考に。
上述の資料で、こんな感じで勉強してからクラウドデザインパターンを読んで行きました。

<超最重要>
EC2,S3,IAM,VPC

<最重要>
ELB,AutoScaling,EBS,Glacier,CloudFront

<重要>
Elastic Beanstalk,Lambda,Storage Gateway,RDS,Route53,Direct Connect,CloudTrail,KMS,SNS

<最低限>
DynamoDB,ElastiCache,Redshift,CloudWatch,CloudFormation,Config,CloudHSM

テストを受けて

わりといい線であてて勉強できたのかなというのが実感値です。他の記事を見て助かったのが、Direct ConnectとStorage Gatewayです。オンプレとAWSで連携する方法としてなのか、私の時は何問か絡んで出題されました。上記にないサービスもしっかり何問か出てきましたが迷わず勘で答えて捨てました。
またエンジニアの世界、資格は実務的能力を示すものではないでしょう、というのは同意です。ので、資格合格したことでスタートするための知識という意味では身についたと思います。けどAWS自体はこれからしっかり身に付けていけるか頑張りたいです。

続きを読む

AWS サービスがどこにあるのかまとめ

 AWS 上のセキュリティや NW 構成を考えるにあたって、どのサービスがどこにあるのか、AZ サービスなのか、リージョンサービスなのか を考える機会が多く、自分の頭の整理のため簡単にまとめます。

まとめた図

 サービスの「場所」を表現する為の図です、全エッセンスを入れるとゴチャゴチャするので、一部省略しています。
Image

説明

 代表的なもの以外(というか個人的に普段使わないもの)は入れてなかったりします。サービスと呼んでいいのかわからないものも混ぜ込みました。

  • AZ サービス

    • Subnet

      • サブネット単位で必要となる NAT Gateway / NACL も AZ サービス
    • EC2
      • AZ単位で設定する EBS / Placement Group も AZ サービス
    • RDS
    • ELB 1
    • ElasticCache
    • Redshift
    • ElasticChache
  • リージョンサービス
    • VPC

      • VPC毎に必要となる Security Group / VPC Endpoints / VPC Peering / EIP も リージョンサービス
    • Auto Scaling
    • S3 2
      • バックエンドで S3 を利用している EBS Snapshot / AMI も リージョンサービス
    • DynamoDB
    • SQS
    • CloudSearch
    • Lambda 3
    • API Gateway 3
    • Code 兄弟
  • グローバルサービス
    • IAM
    • Route53
    • CloudFront
    • WAF
    • Key Pair 4

 誤りあれば、ご指摘ください。


  1. リージョンサービスにも見えますが、実態は Multi-AZ で AutoScaling なインスタンスです、図示する場合は Subnet の間に書くのがよいです 

  2. S3 はサービスとしてはグローバルで、データはリージョンに配置されます  

  3. 指定した VPC / Subnet 内に起動することもできるが、Endpoint(ARN)はリージョン 

  4. EC2キーペアはリージョン毎、RSA キーペアはグローバル 

続きを読む

AWS CLI から ELB ~ Auto Scaling グループの作成・設定を行う

AWS CLI から ELB ~ Auto Scaling グループの作成を行ってみた時のメモ

ELB の作成

以下のコマンドを実行する
(aws cli の region が ap-northeast-1 に設定された状態で試しました)

ELBの作成

始めにELBの作成を行う
ヘルスチェックなどいくつかの設定は別のコマンドで設定しなければいけないよう

aws elb create-load-balancer \
        --load-balancer-name sample-elb \
        --listeners 'Protocol=HTTP,LoadBalancerPort=80,InstanceProtocol=HTTP,InstancePort=80' \
        --subnets 'subnet-123456' 'subnet-456789' \
        --security-groups 'sg-123456' \
        --scheme internal

今回は内部向けロードバランサー
http://docs.aws.amazon.com/ja_jp/elasticloadbalancing/latest/classic/elb-internal-load-balancers.html
を作成しようと思うので
--scheme internal
をつけているが、内部向けでなければこのオプションを外す

クロスゾーン負荷分散・接続のストリーミングの有効化

今回はクロスゾーン負荷分散と接続のストリーミングを有効化したいので以下のコマンドを追加で実行する

aws elb modify-load-balancer-attributes \
  --load-balancer-name sample-elb \
  --load-balancer-attributes '{
    "CrossZoneLoadBalancing":{
        "Enabled":true
    },
    "ConnectionDraining":{
        "Enabled":true,
        "Timeout":300
    }
  }'

ヘルスチェック設定を追加

更にヘルスチェックの設定を行うために以下のコマンドも実行する

aws elb configure-health-check \
  --load-balancer-name sample-elb \
  --health-check Target=HTTP:80/target/ping/path,Interval=30,UnhealthyThreshold=2,HealthyThreshold=2,Timeout=3

上記で設定は完了

値の確認

正しく作成・設定されたか確認する
(値は適当な値に書き換えてます)

 aws elb describe-load-balancers --load-balancer-name sample-elb
{
    "LoadBalancerDescriptions": [
        {
            "Subnets": [
                "subnet-123456",
                "subnet-456789"
            ],
            "CanonicalHostedZoneNameID": "CanonicalHostedZoneNameID",
            "VPCId": "vpc-123456",
            "ListenerDescriptions": [
                {
                    "Listener": {
                        "InstancePort": 80,
                        "LoadBalancerPort": 80,
                        "Protocol": "HTTP",
                        "InstanceProtocol": "HTTP"
                    },
                    "PolicyNames": []
                }
            ],
            "HealthCheck": {
                "HealthyThreshold": 2,
                "Interval": 30,
                "Target": "HTTP:80/target/ping/path",
                "Timeout": 3,
                "UnhealthyThreshold": 2
            },
            "BackendServerDescriptions": [],
            "Instances": [],
            "DNSName": "internal-sample-elb-123456.ap-northeast-1.elb.amazonaws.com",
            "SecurityGroups": [
                "sg-123456"
            ],
            "Policies": {
                "LBCookieStickinessPolicies": [],
                "AppCookieStickinessPolicies": [],
                "OtherPolicies": []
            },
            "LoadBalancerName": "sample-elb",
            "CreatedTime": "2017-08-27T04:54:54.290Z",
            "AvailabilityZones": [
                "ap-northeast-1b",
                "ap-northeast-1c"
            ],
            "Scheme": "internal",
            "SourceSecurityGroup": {
                "OwnerAlias": "123456",
                "GroupName": "default"
            }
        }
    ]
}

起動設定 ~ Auto Scaling グループを作成

起動設定を作成

以下のコマンドで起動設定を作成

試した時の状況としてオプションとして行ってることとして

  • 詳細モニタリングをOFFにしてる
  • インスタンスプロファイルを設定してる
  • ブロックデバイスを手動で設定してる

あたりが入ってる

aws autoscaling create-launch-configuration \
  --launch-configuration-name launch-configuration-for-sample-elb \
  --image-id ami-123456 \
  --instance-type m4.large \
  --security-groups sg-123456 \
  --instance-monitoring Enabled=false \
  --iam-instance-profile sample-instance-profile \
  --key-name keyname \
  --block-device-mappings '[
    {
        "DeviceName": "/dev/sdx",
        "Ebs": {
          "VolumeSize": 100,
          "VolumeType": "gp2",
          "DeleteOnTermination": true
        }
      },
      {
        "DeviceName": "/dev/xvda",
        "Ebs": {
          "VolumeSize": 8,
          "VolumeType": "gp2",
          "DeleteOnTermination": true
        }
      }
    ]'

Auto Scaling グループを作成

上記で作成した ELB と 起動設定を利用して Auto Scaling グループを作成

注意点として一旦台数固定の Scaling Policy は無しで作成してる

aws autoscaling create-auto-scaling-group \
    --auto-scaling-group-name auto-scaling-group-for-sample-elb \
    --launch-configuration-name launch-configuration-for-sample-elb \
    --min-size 2 \
    --max-size 2 \
    --desired-capacity 2 \
    --load-balancer-names sample-elb \
    --health-check-type EC2 \
    --health-check-grace-period 300 \
    --availability-zones ap-northeast-1b ap-northeast-1c \
    --vpc-zone-identifier subnet-123456,subnet-456789 \
    --tags '[
      {
        "PropagateAtLaunch": true,
        "Key": "Name",
        "Value": "sample-elb-instance"
      }
    ]'

Auto Scaling グループの通知設定を作成

先程作成した Auto Scaling グループに通知設定を追加

aws autoscaling put-notification-configuration \
  --auto-scaling-group-name auto-scaling-group-for-sample-elb \
  --topic-arn arn:aws:sns:ap-northeast-1:XXXXXX:XXXXXX \
  --notification-type autoscaling:EC2_INSTANCE_LAUNCH autoscaling:EC2_INSTANCE_LAUNCH_ERROR autoscaling:EC2_INSTANCE_TERMINATE autoscaling:EC2_INSTANCE_TERMINATE_ERROR

値の確認

正しく作成・設定されたか確認する
(値は適当な値に書き換えてます)

$ aws autoscaling describe-launch-configurations --launch-configuration-names launch-configuration-for-sample-elb
{
    "LaunchConfigurations": [
        {
            "UserData": "",
            "IamInstanceProfile": "intent-recommend-search",
            "EbsOptimized": false,
            "LaunchConfigurationARN": "arn:aws:autoscaling:ap-northeast-1:XXXXXX:launchConfiguration:XXXXXX:launchConfigurationName/launch-configuration-for-sample-elb",
            "InstanceMonitoring": {
                "Enabled": false
            },
            "ClassicLinkVPCSecurityGroups": [],
            "CreatedTime": "2017-08-27T06:31:16.558Z",
            "BlockDeviceMappings": [
                {
                    "DeviceName": "/dev/xvda",
                    "Ebs": {
                        "DeleteOnTermination": true,
                        "VolumeSize": 8,
                        "VolumeType": "gp2"
                    }
                },
                {
                    "DeviceName": "/dev/sdx",
                    "Ebs": {
                        "DeleteOnTermination": true,
                        "VolumeSize": 100,
                        "VolumeType": "gp2"
                    }
                }
            ],
            "KeyName": "keyname",
            "SecurityGroups": [
                "sg-123456"
            ],
            "LaunchConfigurationName": "launch-configuration-for-sample-elb",
            "KernelId": "",
            "RamdiskId": "",
            "ImageId": "ami-123456",
            "InstanceType": "m4.large"
        }
    ]
}


$ aws autoscaling describe-auto-scaling-groups --auto-scaling-group-name auto-scaling-group-for-sample-elb
{
    "AutoScalingGroups": [
        {
            "AutoScalingGroupARN": "arn:aws:autoscaling:ap-northeast-1:XXXXXXX:autoScalingGroup:XXXXXX:autoScalingGroupName/auto-scaling-group-for-sample-elb",
            "TargetGroupARNs": [],
            "SuspendedProcesses": [],
            "DesiredCapacity": 2,
            "Tags": [
                {
                    "ResourceType": "auto-scaling-group",
                    "ResourceId": "auto-scaling-group-for-sample-elb",
                    "PropagateAtLaunch": true,
                    "Value": "sample-elb-instance",
                    "Key": "Name"
                }
            ],
            "EnabledMetrics": [],
            "LoadBalancerNames": [
                "intent-recommend-search-ja-JP"
            ],
            "AutoScalingGroupName": "auto-scaling-group-for-sample-elb",
            "DefaultCooldown": 300,
            "MinSize": 2,
            "Instances": [
                ...
            ],
            "MaxSize": 2,
            "VPCZoneIdentifier": "subnet-123456,subnet-456789",
            "HealthCheckGracePeriod": 300,
            "TerminationPolicies": [
                "Default"
            ],
            "LaunchConfigurationName": "launch-configuration-for-sample-elb",
            "CreatedTime": "2017-08-27T06:31:16.558Z",
            "AvailabilityZones": [
                "ap-northeast-1b",
                "ap-northeast-1c"
            ],
            "HealthCheckType": "EC2",
            "NewInstancesProtectedFromScaleIn": false
        }
    ]
}


$ autoscaling describe-notification-configurations --auto-scaling-group-name auto-scaling-group-for-sample-elb
{
    "NotificationConfigurations": [
        {
            "AutoScalingGroupName": "auto-scaling-group-for-sample-elb",
            "NotificationType": "autoscaling:EC2_INSTANCE_LAUNCH",
            "TopicARN": "arn:aws:sns:ap-northeast-1:XXXXXX:XXXXXX"
        },
        {
            "AutoScalingGroupName": "auto-scaling-group-for-sample-elb",
            "NotificationType": "autoscaling:EC2_INSTANCE_LAUNCH_ERROR",
            "TopicARN": "arn:aws:sns:ap-northeast-1:XXXXXX:XXXXXX"
        },
        {
            "AutoScalingGroupName": "auto-scaling-group-for-sample-elb",
            "NotificationType": "autoscaling:EC2_INSTANCE_TERMINATE",
            "TopicARN": "arn:aws:sns:ap-northeast-1:XXXXXX:XXXXXX"
        },
        {
            "AutoScalingGroupName": "auto-scaling-group-for-sample-elb",
            "NotificationType": "autoscaling:EC2_INSTANCE_TERMINATE_ERROR",
            "TopicARN": "arn:aws:sns:ap-northeast-1:XXXXXX:XXXXXX"
        }
    ]
}

参考:

続きを読む

AWSのAutoScalingでインスタンスを起動する際にコマンドを実行したい

タイトルの通り、AWSのAutoScalingでスケールアウトさせる際に、起動するインスタンス上でコマンドを実行したい場合についてです。
インスタンスを起動する際に、ソースコードを最新にしたいとか、webサーバーのプロセスを立ち上げたいと言う時ありますよね。
以下の前提のもと、ここでは最もシンプルであろうという方法を記載していきます。

前提

  • 既に利用可能なAMIを作成済み
  • AutoScalingグループも作成済み
  • ブラウザ上のマネジメントコンソールから設定

では、AWSのEC2サービスの中の起動設定の作成を行います。
1.AMIの選択、2.インスタンスタイプの選択を済ませ、3.詳細設定まで進みます。

スクリーンショット 2017-08-16 0.28.36.png

ここのユーザーデータの項目にインスタンス起動時に渡してあげたいコマンドを記載すればOKです。
気を付けなければいけない点は

  • 渡されたコマンドはrootユーザーとして実行される
  • インタラクティブな操作をコマンドの実行途中ではさむようなものは実行できない

です。
このユーザーデータのテキストボックス内に下記のような感じで記述してしまえば完了です。

#!/bin/bash
cd /path/to/myproject
sudo -u ec2-user /usr/bin/git pull origin master
sudo -u ec2-user /usr/local/bin/gunicorn myproject.wsgi -D

ユーザーデータは様々な形式で渡せるようです
https://cloudinit.readthedocs.io/en/latest/topics/format.html

続きを読む