S3のファイルの中身をSQLで検索できるAWS Athenaを(遅まきながら)触ってみた

AWS Athenaは表題の通り、S3にあるファイルをSQLで検索できるAWSのサービスで、
内部にはPrestoが使用されているそうです。

Athenaの利用

Athenaは東京リージョン(ap-northeeast-1)に対応していないので、東京リージョンからAthenaを選択すると、

1.png
[undefined]()

と出ますが、対応しているリージョンを選択すればいいので使用することに問題はありません。
Atenaを利用するリージョンと異なるリージョンにあるS3バケットも、検索の対象にすることができます。

注意:
AthenaのリージョンとS3のリージョンが異なる場合、リージョン間通信料金がかかります。

詳しくは、S3の料金についてを参照ください。

テーブルの作成

今回は、米国東部リージョンを利用しました。
Athenaが利用可能だと以下のような画面が表示されます。

2.png

Query実行欄があるので直接Queryを書いてテーブルを作ることもできますが、
Hiveの記法で書く必要があり、Hiveを知らないので、
CatalogManagerに従ってテーブルを作成します。

CatalogManagerを押下して遷移する以下の画面で、Add tableを押下します。

3.png

Name & Location

この画面では、作成するテーブルを配置するデータベースやテーブル名、
およびテーブルの元になるS3バケットのパスを指定します。

今回、テーブルを作成した時のバケット構成は以下の通りです。
(CloudWatch Logs + AWS Lambda で日付ごとインスタンス毎のログが.gzファイルに入っています。)

s3://xxxxxxxxxx-var-log-mssages/
 ┣━2016-12-29
 ┃ ┣━aws-logs-write-test
 ┃ ┗━5ce6a99c-bc8a-4af7-b818-061ed575183f
 ┃   ┣━i-03e629e997aa95f18
 ┃   ┃ ┗━000000.gz
 ┃   ┗━i-074549fdee10c46bc
 ┃     ┗━000000.gz
 ┗━2016-12-30
   ┣━aws-logs-write-test
   ┗━6c868fe1-d6ef-4d03-a6e0-4b2c89d1b44b
     ┣━i-03e629e997aa95f18
     ┃ ┗━000000.gz
     ┗━i-074549fdee10c46bc
       ┗━000000.gz

S3バケットで指定したパス以下にあるファイルがQuery対象のファイルになるので、
s3://xxxxxxxxxx-var-log-mssages/ 以下にあるファイルがQuery対象です。

4.png

Data Format

ここでは、テキストをテーブルの列として扱うために、
どのようなフォーマットで列を区切るか指定します。
CSVやTSV、正規表現等が使えます。

今回Athenaで検索対象とするテキストは以下のように記載されているため、

2016-12-30T13:46:43.279Z Dec 30 22:46:42 ip-172-16-2-115 dhclient[2069]: bound to 172.16.2.115 -- renewal in 1663 seconds.
2016-12-30T13:46:43.279Z Dec 30 22:46:42 ip-172-16-2-115 ec2net: [get_meta] Trying to get http://169.254.169.254/latest/meta-data/network/interfaces/macs/06:65:2d:4e:6d:cf/local-ipv4s
2016-12-30T13:46:43.280Z Dec 30 22:46:42 ip-172-16-2-115 ec2net: [rewrite_aliases] Rewriting aliases of eth0

先頭の時刻部分(CloudWatch Logsの時刻)とDec 30以降の部分(ログファイルの本体)との2列になるよう、
以下の正規表現で列の区切りを設定しました。

([0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{3}Z) (.*)

5.png

Columns

Data Formatで設定した列の区切りに対して、列名と型を設定します。

今回の列の区切りでは、1列目と2列目を文字列とするため、
以下のように設定しました。

6.png

Partitions

テーブルのパーティショニングを行うかどうかの設定ですが、
今回はお試しなのでパーティショニングは設定しません。
(Athenaはスキャン量に応じて課金されるので、
 実際に運用する場合はスキャン量を減らすためにパーティショニングをしたほうがよいそうです。)

7.png

テーブル作成

PartitionsCreate tableを押下すると、
Query画面に戻され、先ほどまで設定した内容に基づいてSQLを作成・発行します。

8.png

検索

テーブルができましたので、
log_bodyにerrorの文字列が存在するものを検索します。

SELECT * FROM messages_log where log_body like '%error%' order by log_time desc;

9.png

従来のSQLの書き方で、ログファイルにerrorの文字が存在するものを抜き出すことができました。

最後に

使った感想ですが、やはりログファイルをSQLで検索できるのは、
エラー頻度やエラー解析を行うには便利なように感じました。
ただ、クエリでスキャンしたデータ量に対して課金されるので、
エラー解析のためにガンガンSQLを実行するのは難しいかと思います。

続きを読む

シンプルなRails環境を最速プロビジョニング。各種ツールの利用比較 (Chef [Berkshelf], Ansible [Playbook], Docker [Docker Compose], 手動)

プロビジョニングのための構成管理フレームワークには様々なものがあり、例に挙げると以下のようなものがあります。

  • Chef
  • Ansible
  • Puppet
  • SaltStack
  • CFEngine
  • PowerShell DSC
  • Itamae
  • AWS CloudFormation
  • Terraform
  • Mobingi

ItamaeはCookpadの社員の方が開発した、機能がシンプルで学習コストが低く、Chefを簡略化したようなものです。AWS CloudFormationはAWS上のサーバなどの構成をJSONまたはYAMLで記述して管理するものです。TerraformVagrantPackerなどで有名なHashiCorp社により開発されたもので、AWSやGCP、Azureなどの様々なクラウドに対応した管理ツールとなっています。Mobingiは、従来のようなChefやAnsibleは開発者をターゲットとした扱いの難しいものとして、クラウドのデスクトップとしてGUIベースで管理できるというものです。

ここでは、Chef,Ansible,Dockerによる設定例を取り上げます。
ChefはBerkshelf、AnsibleはAnsible Playbook、DockerはDocker Composeを用いました。また、手動による設定のインストールの例も取り上げました。

例ではそれぞれ最後に、ChefはAWS OpsWorks、AnsibleはAmazon EC2、DockerはAmazon ECSを例に行っていますが、他の環境の場合は適宜置き換えて対応してください。

Chef [Berkshelf]

ローカルでテストせずにOpsWorksでデプロイする場合はVagrant周りの設定は不要で、サブタイトルに(※)のマークを入れた

  • Gemfileの作成
  • Berksfileの作成
  • Recipeの作成

の3つをやれば良い。

ディレクトリ構成

.
├── Berksfile
├── Gemfile
├── README.md
├── Vagrantfile
└── site-cookbooks
    ├── nginx
    │   ├── CHANGELOG.md
    │   ├── README.md
    │   ├── attributes
    │   │   └── default.rb
    │   ├── metadata.rb
    │   ├── recipes
    │   │   └── default.rb
    │   └── templates
    │       └── default
    │           └── nginx.conf.erb
    ├── nodejs
    │   ├── CHANGELOG.md
    │   ├── README.md
    │   ├── attributes
    │   │   └── default.rb
    │   ├── metadata.rb
    │   └── recipes
    │       └── default.rb
    └── ruby-env
        ├── CHANGELOG.md
        ├── README.md
        ├── attributes
        │   └── default.rb
        ├── metadata.rb
        ├── recipes
        │   └── default.rb
        └── templates
            └── default

VagrantでCentOS 6.7の環境設定

$ vagrant box add centos6-7 https://github.com/CommanderK5/packer-centos-template/releases/download/0.6.7/vagrant-centos-6.7.box
$ mkdir -p mkdir ./projects/chef_zero_test
$ cd projects/chef_zero_test
$ vagrant init centos6.7

Vagrantの設定ファイルを以下のように編集する。

$ vim Vagrantfile
Vagrant.configure("2") do |config|
  config.vm.box = "centos6.7"
  config.vm.box_url = "https://github.com/CommanderK5/packer-centos-template/releases/download/0.6.7/vagrant-centos-6.7.box"
  config.vm.network "private_network", ip: "192.168.33.10"
  config.vm.provider "virtualbox" do |vb|
    vb.customize ["modifyvm", :id, "--memory", "4096"]
  end
end

このままでVagrantを立ち上げると、SSH接続の設定で

default: Warning: Authentication failure. Retrying...

のようなエラーが繰り返し表示されて権限の問題でできないので、VagrantにSSHで入って

vagrant ssh

ホスト側で以下のコマンドを実行する。

cd /home
chmod 755 -R ./vagrant
exit

http://qiita.com/jshimazu/items/9db49ce64478e82d511e

Vagrantを立ち上げる。

vagrant up

Vagrantfileの設定

Vagrantfileをプロビジョニングの設定を以下のように追加する。

Vagrant.configure("2") do |config|
  config.vm.box = "centos6.7"
  config.vm.box_url = "https://github.com/CommanderK5/packer-centos-template/releases/download/0.6.7/vagrant-centos-6.7.box"
  config.vm.network "private_network", ip: "192.168.33.10"
  config.vm.provider "virtualbox" do |vb|
    vb.customize ["modifyvm", :id, "--memory", "4096"]
  end

  config.vm.provision :chef_solo do |chef|
    chef.cookbooks_path = ["./cookbooks", "./site-cookbooks"]
    chef.json = {
      nginx: {
        env: ["ruby"]
      }
    }
    chef.run_list = %w[
      recipe[yum-epel]
      recipe[nginx]
      recipe[ruby-env]
      recipe[nodejs]
    ]
  end
end

Gemfileの作成(※)

以下のようにGemfileを作成する。

$ vim Gemfile
source 'https://rubygems.org'

gem 'chef'
gem 'knife-solo'
gem 'berkshelf'
$ cd projects/chef_zero_test
$ rbenv exec bundle install

Berksfileの作成(※)

以下のようにBerksfileを作成する。

$ vim Berksfile
source "https://supermarket.chef.io"

cookbook "yum-epel"
cookbook "nginx", path: "./site-cookbooks/nginx"
cookbook "ruby-env", path: "./site-cookbooks/ruby-env"
cookbook "nodejs", path: "./site-cookbooks/nodejs"

※最初、site :opscodeの宣言方法はDeplicated

Recipeの作成(※)

nginxのレシピ

1.Cookbookの作成。

bundle exec knife cookbook create nginx -o ./site-cookbooks

2.Recipeファイルの作成。

vim site-cookbooks/nginx/recipes/default.rb
default.rb
include_recipe "yum-epel"

package "nginx" do
  action :install
end

service "nginx" do
  action [ :enable, :start ]
  supports :status => true, :restart => true, :reload => true
end

template 'nginx.conf' do
  path '/etc/nginx/nginx.conf'
  source "nginx.conf.erb"
  owner 'root'
  group 'root'
  mode '0644'
  notifies :reload, "service[nginx]"
end

3.attributeファイルの作成。

vim site-cookbooks/nginx/attributes/default.rb
default.rb
default['nginx']['env'] = []

4.nginx.confのテンプレートファイルの作成。

sudo cp /usr/local/etc/nginx/
nginx.conf ~/workspace/chef-tests/chef-test/projects/chef_zero_test/site-cookbooks/nginx/templates/default/nginx.conf.erb
vim site-cookbooks/nginx/template/default/nginx.conf.erb
nginx.conf.erb
user  nginx;
worker_processes  1;

error_log  /var/log/nginx/error.log warn;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;
    sendfile        on;
    keepalive_timeout  65;

    upstream app_server {
      server unix:/tmp/unicorn.sock;
    }

    server {
        listen       80 default_server;
        server_name  _;

        location / {
            rewrite ^/app_server/(.+) /$1 break;
            proxy_pass http://app_server/$1;
        }
    }
}

Rubyのレシピ

1.Cookbookの作成。

$ bundle exec knife cookbook create ruby-env -o ./site-cookbooks

2.Recipeファイルの作成。

$ vim site-cookbooks/ruby-env/recipes/default.rb
%w{vim git openssl-devel sqlite-devel readline-devel}.each do |pkg|
    package pkg do
        action :install
    end
end

git "/home/#{node['ruby-env']['user']}/.rbenv" do
    repository node["ruby-env"]["rbenv_url"]
    action :sync
    user node['ruby-env']['user']
    group node['ruby-env']['group']
end

template ".bash_profile" do
    source ".bash_profile.erb"
    path "/home/#{node['ruby-env']['user']}/.bash_profile"
    mode 0644
    owner node['ruby-env']['user']
    group node['ruby-env']['group']
    not_if "grep rbenv ~/.bash_profile", :environment => { :'HOME' => "/home/#{node['ruby-env']['user']}"  }
end

directory "/home/#{node['ruby-env']['user']}/.rbenv/plugins" do
    owner node['ruby-env']['user']
    group node['ruby-env']['group']
    mode 0755
    action :create
end

git "/home/#{node['ruby-env']['user']}/.rbenv/plugins/ruby-build" do
    repository node["ruby-env"]["ruby-build_url"]
    action :sync
    user node['ruby-env']['user']
    group node['ruby-env']['group']
end

execute "rbenv install #{node['ruby-env']['version']}" do
    command "/home/#{node['ruby-env']['user']}/.rbenv/bin/rbenv install #{node['ruby-env']['version']}"
    user node['ruby-env']['user']
    group node['ruby-env']['group']
    environment 'HOME' => "/home/#{node['ruby-env']['user']}"
    not_if { File.exists?("/home/#{node['ruby-env']['user']}/.rbenv/versions/#{node['ruby-env']['version']}")}
end


execute "rbenv global #{node['ruby-env']['version']}" do
    command "/home/#{node['ruby-env']['user']}/.rbenv/bin/rbenv global #{node['ruby-env']['version']}"
    user node['ruby-env']['user']
    group node['ruby-env']['group']
    environment 'HOME' => "/home/#{node['ruby-env']['user']}"
    not_if { File.exists?("/home/#{node['ruby-env']['user']}/.rbenv/versions/#{node['ruby-env']['version']}")}
end


execute "rbenv shell #{node['ruby-env']['version']}" do
    command "/home/#{node['ruby-env']['user']}/.rbenv/bin/rbenv shell #{node['ruby-env']['version']}"
    user node['ruby-env']['user']
    group node['ruby-env']['group']
    environment 'HOME' => "/home/#{node['ruby-env']['user']}"
    not_if { File.exists?("/home/#{node['ruby-env']['user']}/.rbenv/versions/#{node['ruby-env']['version']}")}
end

3.attributeファイルの作成。

$ vim site-cookbooks/ruby-env/attributes/default.rb
default['ruby-env']['user'] = "vagrant"
default['ruby-env']['group'] = "vagrant"
default['ruby-env']['version'] = "2.3.1"
default['ruby-env']['rbenv_url'] = "https://github.com/sstephenson/rbenv"
default['ruby-env']['ruby-build_url'] = "https://github.com/sstephenson/ruby-build"

※EC2にデプロイする場合は以下のようにuserとgroupの内容をec2-userにする。

default['ruby-env']['user'] = "ec2-user"
default['ruby-env']['group'] = "ec2-user"
default['ruby-env']['version'] = "2.3.1"
default['ruby-env']['rbenv_url'] = "https://github.com/sstephenson/rbenv"
default['ruby-env']['ruby-build_url'] = "https://github.com/sstephenson/ruby-build"

4..bash_profileのテンプレートファイルの作成

$ vim site-cookbooks/ruby-env/template/default/.bash_profile.erb
bash_profile.erb
# .bash_profile

if [ -f ~/.bashrc] ; then
    . ~/.bashrc
fi

PATH=$PATH:$HOME/bin
export PATH="$HOME/.rbenv/bin:$PATH"
eval "$(rbenv init -)"

Node.jsのレシピ

1.Cookbookの作成。

$ bundle exec knife cookbook create nodejs -o ./site-cookbooks

2.Recipeファイルの作成。

$ vim site-cookbooks/nodejs/recipes/default.rb
bash "install nodejs" do
    user "root"
    cwd "/tmp"
    code <<-EOC
        curl --silent --location https://rpm.nodesource.com/setup_6.x | bash -
        yum -y install gcc-c++ make nodejs
     EOC
end

Berkshelfの実行 + Vagrantのプロビジョニング

Berkshelfを実行して、Vagrantでプロビジョニングを実行する。

$ bundle exec berks vendor ./cookbooks
$ vagrant reload
$ vagrant provision

bundle exec berks install --path ./cookbooksはdeprecated

Railsの動作確認

ホスト側でRailsをインストールする。

$ vagrant ssh
# rbenv shell 2.3.1
$ gem install rails -V
$ rails new sample --skip-bundle
$ cd sample/
$ mkdir -p shared/{pids,log}

Gemfileを開いてgem 'unicorn'の一行を追加する。

vim Gemfile
source 'https://rubygems.org'


gem 'rails', '~> 5.0.0', '>= 5.0.0.1'
gem 'sqlite3'
gem 'puma', '~> 3.0'
gem 'sass-rails', '~> 5.0'
gem 'uglifier', '>= 1.3.0'
gem 'coffee-rails', '~> 4.2'
gem 'jquery-rails'
gem 'turbolinks', '~> 5'
gem 'jbuilder', '~> 2.5'

gem 'unicorn'

group :development, :test do
  gem 'byebug', platform: :mri
end

group :development do
  gem 'web-console'
  gem 'listen', '~> 3.0.5'
  gem 'spring'
  gem 'spring-watcher-listen', '~> 2.0.0'
end

gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]

以下のコマンドで上記の内容をインストール。

bundle install

unicornの設定ファイルを以下のように編集する。

vim config/unicorn.rb
listen "/tmp/unicorn.sock"
worker_processes 2

pid "/home/vagrant/sample/shared/pids/unicorn.pid"
stderr_path "/home/vagrant/sample/shared/log/unicorn.log"
stdout_path "/home/vagrant/sample/shared/log/unicorn.log"
cd sample/ 
bundle exec unicorn -c config/unicorn.rb [-D]

UnicornではなくPumaで動かす場合は以下のコマンド

bundle exec rails s (-e production) -b '0.0.0.0'

 http://192.168.33.10:3000 にアクセスすると以下のような画面が現れる。

スクリーンショット 2016-11-17 0.59.18.png

Unicornのプロセスの終了(-Dでデーモンで立ち上げた場合)

kill -QUIT `cat /home/vagrant/test_unicorn/shared/pids/unicorn.pid`

OpsWorksでデプロイ

Berkshelfによるパッケージ化

以下のコマンドを実行して、S3にアップロードする。

$ bundle exec berks package cookbooks.tar.gz
$ aws s3 cp cookbooks.tar.gz s3://sample-bucket/

OpsWorks(OpsWorks Stacks)の操作

  1. マネジメントコンソールからOpsWorksを選択
  2. [Go to OpsWorks Stacks]を選択。

Stackの設定

  1. [Stacks]から[Add stack]を選択。
  2. [Chef 12 stack]タブを選択し、以下のように入力する。

Stack name: sample-stack
Region: Asia Pacific (Tokyo)
VPC: vpc-xxxxxxxx (default)
Default subnet: xxx.xxx.xxx.xxx/xx – ap-northeast-1a
Default operating system: Linux, Amazon Linux 2016.09
Default SSH key: Do not use a default SSH key
Chef version: 12
Use custom Chef cookbooks: Yes
Repository type: S3 Archive
Repository URL: http://.s3-website-ap-northeast-1.amazonaws.com/cookbooks.tar.gz
Access key ID: AKIAXXXXXXXXXXXXXXXXXXXX
Secret access key: xxxxxxxxxxxxxxxxxxxxxxxxx
Stack color: blue (default)

Advanced optionsは以下のような項目がある。
Default root device type: EBS backed
IAM role:
Default IAM instance profile:
API endpoint region: ap-northeast-1a (REGIONAL)
Hostname theme: Layer Dependent
OpsWorks Agent version: 4021(Dec 16th 2016)
Custom JSON: (空欄)
Use OpsWorks security groups: Yes

Layerの設定

  1. [Layers]の設定
  2. [Add layer]を選択し、以下のように入力する。
    Name: sample-layer
    Short name: sample

[Add layer]を選択。

  1. 作成したLayerを選択し、[Recipes]を選択。
  2. Setupに以下の5つを追加する。
  • nginx::default
  • nodejs::default
  • ruby-env::default
  • yum::default
  • yum-epel::default

[Save]を選択。

※これを忘れた場合、Chefによるプロビジョニングが行われずに、後述のインスタンスが起動してしまう。

Instanceの作成

1.[Instances]を選択。
2.[+ Instance]を選択し、以下のように入力する。

Hostname: sample
Size: t2.micro
Subnet: XXX.XXX.XXX.XXX/XX – ap-northeast-1a

[Add Instance]を選択。

3.作成したインスタンスのActionsから[start]を選択。以降プロビジョニングが始まる。もし、起動に失敗した場合は、Hostnameのホスト名を選択した時に遷移するページの最下部にあるLogsから確認出来るLogを確認する。

補足

Berkshelfの実行

bundle exec berks install --path ./cookbooks

これはdeprecatedなので以下を実行

bundle exec berks vendor --path ./cookbooks

注意点

ホスト側でgemコマンドが見つからない

rbenv shell 2.3.1

を実行することでgemを認識するようになる。
http://qiita.com/kasumani/items/042bf799d6794bd2e4f2

Ansible

導入

インストール

brew install ansible

試しにホストに疎通確認。

[sample]
<IP address> ansible_user=ec2-user ansible_ssh_private_key_file=~/.ssh/id_rsa
$ ansible -i hosts all -m ping
<IP address> | SUCCESS => {
    "changed": false, 
    "ping": "pong"
}

Ansible Playbookによるプロビジョニング

ディレクトリ構成

.
├── ansible.cfg
├── group_vars
│   └── sample
├── inventory
│   └── hosts
├── sample.yml
└── roles
    ├── nginx
    │   ├── defaults
    │   │   └── main.yml
    │   ├── handlers
    │   │   └── main.yml
    │   ├── tasks
    │   │   └── main.yml
    │   └── templates
    │       ├── 404.html.j2
    │       ├── 50x.html.j2
    │       ├── index.html.j2
    │       └── nginx.conf.j2
    ├── rails
    │   ├── defaults
    │   │   └── main.yml
    │   └── tasks
    │       └── main.yml
    ├── rbenv
    │   └── tasks
    │       └── main.yml
    └── yum
        └── tasks
            └── main.yml

ファイル内容

sample.yml
- hosts: sample
  become: yes 
  roles:
    - yum 
    - rbenv
    - rails
    - nginx
ansible.cfg
[defaults]
remote_user=ec2-user
private_key_file=~/.ssh/id_rsa
inventory=./inventory/hosts
executable = /bin/bash -l
  • inventory
[defualts]
<IP address>
  • group_vars
rbenv_user: ec2-user
rbenv_ruby_version: 2.3.1
  • roles

    • yum
yum
└── tasks
    └── main.yml
main.yml
---
- name: Install package for bundle install
  yum: name={{ item }} state=latest
  with_items:
    - sqlite-devel
    - gcc-c++
- name: Update all packages
  yum: name=* state=latest

 gcc-c++はtherubyracerのインストールに必要

  • rbenv
rbenv
└── tasks
    └── main.yml
---
- name: Install dependencies for rbenv
  yum: name={{ item }} state=latest
  with_items:
    - git

- name: Install rbenv
  become: yes
  become_user: "{{ rbenv_user }}"
  git: repo=https://github.com/sstephenson/rbenv.git dest=~/.rbenv

- name: Add ~.rbenv/bin to PATH
  become: yes
  become_user: "{{ rbenv_user }}"
  lineinfile: >
    dest="~/.bash_profile"
    line="export PATH=$HOME/.rbenv/bin:$PATH"
- name: Eval rbenv init in ~/.bash_profile
  become: yes
  become_user: "{{ rbenv_user }}"
  lineinfile: >
    dest="~/.bash_profile"
    line='eval "$(rbenv init -)"'

- name: Install dependencies for ruby-build (see. https://github.com/sstephenson/ruby-build/wiki)
  yum: name={{ item }} state=latest
  with_items:
    - gcc
    - openssl-devel
    - libyaml-devel
    - libffi-devel
    - readline-devel
    - zlib-devel
    - gdbm-devel
    - ncurses-devel

- name: Install ruby-build as rbenv plugin
  become: yes
  become_user: "{{ rbenv_user }}"
  git: repo=https://github.com/sstephenson/ruby-build.git dest=~/.rbenv/plugins/ruby-build

- name: Check if version is installed ruby
  become_method: yes
  become_user: "{{ rbenv_user }}"
  shell: "rbenv versions | grep {{ rbenv_ruby_version }}"
  register: rbenv_check_install
  changed_when: False
  ignore_errors: yes

- name: Install ruby
  become_method: yes
  become_user: "{{ rbenv_user }}"
  shell: "rbenv install {{ rbenv_ruby_version }}"
  when: rbenv_check_install|failed

- name: Check if version is the default ruby version
  become_method: yes
  become_user: "{{ rbenv_user }}"
  shell: "rbenv version | grep {{ rbenv_ruby_version }}"
  register: rbenv_check_default
  changed_when: False
  ignore_errors: yes

- name: Set default ruby version
  become_method: yes
  become_user: "{{ rbenv_user }}"
  shell: "rbenv global {{ rbenv_ruby_version }}"
  when: rbenv_check_default|failed

※注意点で、rbenvのコマンドのパスを通すところで、.bash_profileに設定を追記しているが、sourceコマンドでは反映されない。なので、パスを適用させるために、シェルはログインシェルとして実行することで解決できる。具体的には、ansible.cfg中でexecutable = /bin/bash -lを宣言すると良い。

  • rails
rails
├── defaults
│   └── main.yml
└── tasks
    └── main.yml
  • defaults
main.yml
---
railsenv_deploy_dir: "/var/www/sample"
railsenv_deploy_user: ec2-user
railsenv_deploy_group: ec2-user
  • tasks
main.yml
---
- name: Install mysql-devel
  yum: name={{ item }} state=latest
  with_items:
    - mysql-devel
    - gcc-c++

- name: Install dependencies for nokogiri
  yum: name={{ item }} state=latest
  with_items:
    - patch

- name: Install bundler
  become_user: "{{ rbenv_user }}"
  gem: name={{ item }} user_install=False
  with_items:
    - bundler

- name: Create deploy directory
  file: path={{ railsenv_deploy_dir }} state=directory owner={{ railsenv_deploy_user }} group={{ railsenv_deploy_group }} mode=0755
  • nginx
nginx
├── defaults
│   └── main.yml
├── handlers
│   └── main.yml
├── tasks
│   └── main.yml
└── templates
    ├── index.html.j2
    └── nginx.conf.j2
  • tasks
main.yml
---
- name: Install nginx
  yum: name=nginx state=latest

- name: Set nginx service to start on boot
  service: name=nginx enabled=true

- name: Put nginx.conf
  template: src=nginx.conf.j2 dest=/etc/nginx/nginx.conf backup=true mode=0644
  notify: restart nginx

- name: Put share index.html
  template: src=index.html.j2 dest=/usr/share/nginx/html/index.html mode=644
  • handlers
main.yml
---
- name: restart nginx
  service: name=nginx state=restarted
  • defualts
main.yml
---
nginx_woker_processes: "auto"
nginx_server_tokens: "off"
nginx_includes: []
  • templates
index.html.j2
<html>
    <body>
        <h1>Hello, world!</h1>
    </body>
</html>
nginx.conf.j2
user  nginx;
worker_processes  {{ nginx_woker_processes }};

error_log  /var/log/nginx/error.log;

pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    error_log  /var/www/sample/log/nginx.error.log; 
    access_log /var/www/sample/log/nginx.access.log; 

    server_tokens {{ nginx_server_tokens }};

    sendfile        on;

    keepalive_timeout  65;

    include /etc/nginx/conf.d/*.conf;
{% for include in nginx_includes %}
    include {{ include }};
{% endfor %}

    index   index.html index.htm;

    client_max_body_size 2G;
    upstream app_server {
        server unix:/var/www/sample/tmp/sockets/.unicorn.sock fail_timeout=0;
    }

   server {
        listen 80;
        server_name <IP address>;

        keepalive_timeout 5;
        root /var/www/sample/public;
        try_files $uri/index.html $uri.html $uri @app;
        location @app {
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_redirect off;
            proxy_pass http://app_server;
        }
    }
}

実行

ansible-playbook sample.yml

ansible.cfg中でremote_user, private_key_file, inventoryの設定を追加しない場合は以下のようにコマンドを打つ必要がある。

ansible-playbook -i "<IP address>," --user=ec2-user --private-key=~/.ssh/id_rsa sample.yml

注意点

  • rbenvの設定ファイルを.bash_profileの内容がsourceでは反映されないのでshellモジュールを使う時は必ずログインシェルとして実行する
[defaults]
executable = /bin/bash -l
- name: Sample shell execution
  become_method: yes
  become_user: ec2-user
  shell: "~~~"

http://www.bunkei-programmer.net/entry/2015/05/16/162020

  • therubyracerの依存パッケージでgcc-c++をyumで入れる。

Docker [Docker Compose]

FROM ruby:2.3.1

ENV APP_ROOT /app

RUN apt-get update -qq && 
    apt-get install -y build-essential 
                       libmysqld-dev 
                       libmysqlclient-dev 
                       mysql-client 
                       --no-install-recommends && 
    rm -Rf /var/lib/opt/lists/*

RUN mkdir $APP_ROOT
WORKDIR $APP_ROOT

ADD . /app
RUN bundle install
docker-compose.yml
version: '2' 
services:
  app:
    build: .
    command: bundle exec rails s -b '0.0.0.0'
    volumes:
      - .:/app
    ports:
      - "3000:3000"
    links:
      - db
  db: 
    image: mysql:5.6.30
    ports:
      - "3306:3306"
    environment:
      MYSQL_ROOT_PASSWORD: root

ただし、Gemfile中でtherubyracerを使用しない場合は、Dockerfile中でapt-get installnodejsもインストールする。

ビルド & 実行

以下のコマンドはターミナルのウィンドウを新たに開くたびに実行する。

docker-machine start default
eval $(docker-machine env defualt)

ビルド

docker-compose build

実行

docker-compose up

IPアドレスを以下のコマンドで調べる。

docker-machine ip

192.168.99.100:3000のようにブラウザにアクセスする。

ECSでデプロイ

ECSでデプロイする場合は別投稿の下記のURLを参考にして下さい。
http://qiita.com/hayashier/items/b34f82c42053f85e5b09

マニュアルで環境構築

Railsの環境準備

sudo yum install -y git make gcc-c++ patch openssl-devel libyaml-devel libffi-devel libicu-devel libxml2 libxslt libxml2-devel libxslt-devel zlib-devel readline-devel mysql mysql-server mysql-devel ImageMagick ImageMagick-devel epel-release
sudo yum install -y nodejs npm --enablerepo=epel
git clone https://github.com/sstephenson/rbenv.git ~/.rbenv 
echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile 
echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
source .bash_profile
git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
rbenv install 2.3.1
rbenv global 2.3.1
ruby -v

Webサーバのインストール

sudo yum install gem
gem install bundle
bundle -v
rake secret
sudo yum install nginx
sudo service nginx start

以下、Capistrano等のデプロイツールを用いてデプロイする場合は必ずしも必要ではありません。

gitの準備

vim ~/.netrc
cd ~/.ssh
ssh-keygen -t rsa -C "<メールアドレス>"
ssh-add ~/.ssh/id_rsa
cat id_rsa_admin.pub 
ssh -T git@github.com

GitHubに公開鍵の登録をする。

  • .netrc
machine github.com
login <GitHubユーザ名>
password xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Webサーバの環境・設定

cd /var/www/
sudo git clone https://github.com/<GitHubユーザ名>/<レポジトリ名>.git
sudo chown -R ec2-user:ec2-user <レポジトリ名>/
cd <レポジトリ名>/
bundle install --path ./vendor/bundle/ 
sudo vim /etc/nginx/conf.d/admin.conf 
sudo service nginx restart
bundle exec rake secret
cat config/secrets.yml 
vim .env
source .env
echo $SECRET_KEY_BASE
sudo service nginx restart
rails s -e production
  • .env
export DATABASE_PASSWORD_PRODUCT=xxxxxxxxxxxxxxx

config/database.yml中のデータベースへのパスワードを以下のように環境変数として定義しておき、.env中でインポートする。

<%= ENV[‘DATABASE_PASSWORD_PRODUCT’] %>

  • sample.conf
error_log  /var/www/sample/log/nginx.error.log; 
access_log /var/www/sample/log/nginx.access.log;

client_max_body_size 2G;
upstream app_server {
  server unix:/var/www/sample/tmp/sockets/.unicorn.sock fail_timeout=0; 
}
server {
  listen 80;
  server_name <IPアドレス>;
  # nginx so increasing this is generally safe...
  keepalive_timeout 5;
  # path for static files
  root /var/www/sample/public; 
  # page cache loading
  try_files $uri/index.html $uri.html $uri @app;
  location @app {
    # HTTP headers
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://app_server;
  }     
  # Rails error pages
  error_page 500 502 503 504 /500.html;
  location = /500.html {
    root /var/www/sample/public; 
  }
}

参考

Chef

Ansible

Docker

https://docs.docker.com/compose/rails/

続きを読む

ローカル環境でAmazon Linuxをテストする

はじめに

可搬性(ポータビリティ)に立ちふさがる密林、Amazon Linux。担当プロジェクトでもご多分に漏れず、Amazon LinuxをOSとしたシステムを組んでいます。
chefを用いて構成管理(商用環境は、OpsWorks)、Test Kitchen + ServerspecでインフラテストしているがOSはCentOS6.7(packerで生成したVagrant box)…OSが違うのに、何が構成管理か、何が可搬性か。

AWS公式のDockerイメージもリリースされたことですし、Dockerを武器にローコストで可搬性を手に入れることが出来ると思い立ったが吉日。
1営業日くらいで可搬性のあるインフラテスト環境を手に入れることが出来ました :dragon_face:

変更のサマリ

OpsWorks用cookbook ローカル環境用cookbook Test KitchenでプロビジョニングするホストのOS Test Kitchenのドライバ 初回のテスト完了までの所要時間
ビフォー example example_local CentOS6.7 Vagrant 20分程度
アフター example Amazon Linux Docker 5分程度

主たる変更は、kitchen-dockerを導入し、Test KitchenのドライバとしてDockerを採用したことです。
変更により、以下のメリットを享受出来るようになりました。

  • cookbookの統一
  • プロビジョニング対象ホストのOSをOpsWorksと合わせることが出来る
  • 初回テスト時の所要時間の短縮

以下で、詳細を記載していきます。

ビフォー

before.png

  1. exampleアプリケーションを稼働させるためのcookbook(example)を開発する

    • OpsWorksを利用しているので、リポジトリ直下にcookbookを配置する必要がある
  2. example cookbookをTest Kitchenで稼働させるために、example_localを開発する
    • example::defaultをincludeし、attributeを上書きするcookbook
  3. Serverspecでテストコードを開発する
    • Test Kitchenにも対応するので、example_localに配置
  4. Test Kitchenでexample cookbookの動作確認とテストを実施
    • プロビジョニング:bundle exec kitchen converge default-example
    • テスト:bundle exec kitchen verify default-example
  5. テストが通ったら、packerに対応させる
    • packer/example.jsonを開発し、cookbookと一緒にAtlasにアップロード
    • AtlasのpackerでVagrant boxを生成する(リモートビルド)
  6. 開発担当者がAtlasからVagrant boxをダウンロードし、exampleアプリケーションを開発

…だるい

設計し、実装を終えた当初は、堅牢で素晴らしいワークフローだと思ったものです。
このケースの課題は

  • cookbook開発のオーバーヘッドが無視できない

    • cookbookの見通しが悪い。_localって何??
    • Atlasは、日本の日勤帯の時間は、ネットワーク帯域を絞っているのでboxのダウンロードが激重
  • attributeでパッケージ名を上書きしている

    • OSが異なることが諸悪の根源
  • 学習コストが結構かかる

    • chefとServerspecは必要経費だとしても、Test Kitchen、Vagrant、Packer、Atlas….

ゴールデンイメージなVagrant boxを中心に添えたワークフローは、堅牢ですがミドルウェアのアップデートのスピードには着いていくことが難しいというのが個人的な印象です。

アフター

after.png

  1. exampleアプリケーションを稼働させるためのcookbook(example)を開発する

    • OpsWorksを利用しているので、リポジトリ直下にcookbookを配置する必要がある
  2. Serverspecでテストコードを開発する
    • Test Kitchenにも対応するので、example_localに配置
  3. Test Kitchenでexample cookbookの動作確認とテストを実施
    • Test Kitchenのドライバとして、Dockerを指定
    • kitchen-dockerでAmazon LinuxのイメージをPULLし、example cookbookをプロビジョニング
    • プロビジョニング:bundle exec kitchen converge default-example
    • テスト:bundle exec kitchen verify default-example
  4. テストが通ったら、リモートリポジトリにPUSH
  5. OpsWorksのスタックをsetupし、AWS上のインフラをプロビジョニング

cookbook開発だけでなく、アプリケーションのローカル開発環境の見直しも併せて行った(Dockerの導入)ので、かなりシンプルはワークフローとなりました。
メリットをまとめると

  • 同一のOSに対してプロビジョニングし、テスト出来る

    • AWS公式Dockerイメージに対してプロビジョニングした結果をテスト出来る
  • コードベースがシンプルになる

    • example_local cookbookを破棄することが出来る
  • cookbook開発に注力出来る

    • 以前に比べて、学習費用対効果が良い
    • 必要経費(chef、Serverspec)のみで開発出来る

Tips

導入に際してのポイントをコードを交えて説明してみます。

kitchen-dockerの導入

gemのインストール

kitchen-dockerというgemが必要になりますので、Gemfileに追記しましょう。
Kitchen-vagrantは不要となりますので、削除しました。

source "https://rubygems.org"

gem "chef"
gem "berkshelf"
gem "test-kitchen"
gem "kitchen-docker"

Gemfileの編集が終わったらbundlerでインストールします。

bundle install --path ./vendor/bundle

.kitchen.ymlの編集

kitchen-dockerのREADMEを参考に、Test Kitchenの設定ファイルを編集していきます。

provisioner:
  name: chef_solo
  environments_path: ../environments
  solo_rb:
    environment: local

Test KitchenのドライバとしてDockerを指定します。sudoするとdockerコマンドへのパスが見つからない場合が多いかと思うので、use_sudo: falseと指定しておきます。
OpsWorks環境とは異なるattributeがあれば、environmentsとしてJSON形式のファイルにまとめておくことをおすすめします。

platforms:
  - name: amazonlinux-201609
    driver_config:
      platform: rhel
      image: amazonlinux:2016.09

name要素でプロビジョニング対象のホストの名前を指定します。
Amazon Linuxは、Test Kitchenの分類ではRHEL系のディストリビューションとなるので、platform: rhelと指定します。
image要素で、Dockerレジストリから取得したいイメージを指定します。OpsWorks環境のOSバージョンと合わせるため、image: amazonlinux:2016.09と指定します。

suites:
  - name: default
    run_list:
      - recipe[example::amazonlinux-local]
      - recipe[example::default]
    attributes:

テストしたいrecipeをリストします。
amazonlinux-localというレシピについては、後述します。

上記をまとめると、以下の様な.Kitchen.ymlとなります。

---
driver:
  name: docker
  use_sudo: false

provisioner:
  name: chef_solo
  environments_path: ../environments
  solo_rb:
    environment: local

platforms:
  - name: amazonlinux-201609
    driver_config:
      platform: rhel
      image: amazonlinux:2016.09

suites:
  - name: default
    run_list:
      - recipe[example::amazonlinux-local]
      - recipe[example::default]
    attributes:

amazonlinuxの導入

amazonlinuxは、AWS公式のDockerイメージですが、AWS環境と全く同一のものではありません。あくまでも、可搬性の観点で現状取りうる手段の中で最もAWS環境で稼働するAmazon Linuxに近い仮想環境です。
そのため、AWS環境との差異(OSの初期設定含む)については、自分たちで対応する必要があります。
私達のチームでは、差異を埋めるrecipeを開発して対応しました。

# sysconfigファイル
default[:sysconfigs] = ['i18n', 'network']

システム設定ファイル(/etc/sysconfig)の差異をattributeにまとめ、templateとして配置しておきます。

$ tree /path/to/example/example/templates/default/
/path/to/example/example/templates/default/
├── i18n.erb
├── config.erb
└── network.erb
# ローカル開発環境(Amazon LinuxのDockerイメージ)でのレシピ開発のための各種ファイルの配置
node[:sysconfigs].each do |sysconfig|
  template "/etc/sysconfig/#{sysconfig}" do
    owner "root"
    group "root"
    mode 0644
    not_if { File.exist?("/etc/sysconfig/#{sysconfig}") }
  end
end

配置したtemplateを上記の様なrecipeでプロビジョニングしていきます。

# SELinuxは明示的にDisable
include_recipe 'selinux'
template "/etc/selinux/config" do
  owner "root"
  group "root"
  mode 0644
  not_if { File.exist?("/etc/selinux/config") }
end

これは、テストのためのプロビジョニングです。
ServerspecでSELinuxの設定をテストしているのですが、/etc/selinux/configファイルが必須の内容となっておりましたので、ローカル環境でのrecipe開発のためだけにプロビジョニングしています。

# peclを利用するのでコンパイラをインストール
package "gcc"

gccがインストールされておりませんので、テスト対象のrecipeをプロビジョニングする前にインストールしておきます。

上記をまとめると、以下の様なrecipe(amazonlinux-local.rb)となります。
このrecipeをテスト対象のrecipe(example::default)の前にプロビジョニングします(前述の.kitchen.yml参照)。

# Cookbook Name:: example
# Recipe:: amazonlinux-local

# ローカル開発環境(Amazon LinuxのDockerイメージ)でのレシピ開発のための各種ファイルの配置
node[:sysconfigs].each do |sysconfig|
  template "/etc/sysconfig/#{sysconfig}" do
    owner "root"
    group "root"
    mode 0644
    not_if { File.exist?("/etc/sysconfig/#{sysconfig}") }
  end
end

# SELinuxは明示的にDisable
include_recipe 'selinux'
template "/etc/selinux/config" do
  owner "root"
  group "root"
  mode 0644
  not_if { File.exist?("/etc/selinux/config") }
end

# peclを利用するのでコンパイラをインストール
package "gcc"

Test Kitchen

kitchen-dockerの導入を紹介してきましたが、Test Kitchenのコマンド集をまとめておきます。

# cookbookのディレクトリに移動
$ cd /path/to/example/example

# インスタンスの確認
$ bundle exec kitchen list
Instance                    Driver  Provisioner  Verifier  Transport  Last Action  Last Error
default-amazonlinux-201609  Docker  ChefSolo     Busser    Ssh        Verified     <None>

# インスタンスを作成
$ bundle exec kitchen create default-amazonlinux-201609

# インスタンスのセットアップ
$ bundle exec kitchen converge default-amazonlinux-201609

# インスタンスへログイン(tty)
$ bundle exec kitchen login default-amazonlinux-201609
Last login: Thu Jan  5 20:23:42 2017 from 172.17.0.1
[kitchen@685fdd7c1349 ~]$
[kitchen@685fdd7c1349 ~]$ pwd
/home/kitchen

# テスト(serverspec)の実行
$ bundle exec kitchen verify default-amazonlinux-201609

# インスタンスの破棄
% bundle exec kitchen destroy default-amazonlinux-201609

おわりに

OpsWorksを導入して以来、Amazon Linuxをどうテストするかという課題を抱えていましたが、AWS公式のDockerイメージが提供されたことにより、ローコストで可搬性のあるテストを実施出来るようになりました。
今後の課題は、プロビジョニングをCIすることを目標に必要なライブラリの導入や開発、変更を加えて行きたいと思います。
増え続けるcookbookや優秀なchefの育成に困っている開発チームの課題解決の一助となれば幸いです。

参考

続きを読む

Amazon EC2 VPCのIPv6対応 インスタンスへのIPv6アドレス付与は m-flagつきRA + stateful DHCPv6

サマリ

Amazon VPC内のEC2インスタンスへのIPv6アドレス付与は RA with m-flag + stateful DHCPv6 で行われている。

ubuntu 16.04 のインスタンスを立てて、DHCPv6の設定をする

Developers.IO: Amazon EC2とVPCがIPv6に対応しました #reinvent
http://dev.classmethod.jp/cloud/aws/vpc-ipv6/

上記の記事の通りに、オハイオリージョンのVPCにIPv6の設定をして、ubuntu 16.04 LTSのEC2インスタンスを作ってみたが初期設定では、eth0にIPv6アドレスがつかない。

eth0 I/Fに prefix information option を含むRAが降ってくるが、m-flagがついるので、stateful DHCPv6クライアントを起動(IA_NAをリクエスト)してIPv6アドレスを取得する。

手動で起動するなら

# sudo dhclient -6 eth0

OS起動時の設定にするなら下記の設定を入れておく

# echo "iface eth0 inet6 dhcp" > /etc/network/interfaces.d/60-default-with-ipv6.cfg

Amazon Linux, Windows インスタンスの初期設定

Amazon提供のドキュメントには下記の記述があり、標準でDHCPv6クライアントを起動する設定が入っている。Windowsについては、m-flagつきRAを受け取った時、stateful DHCPv6クライアントを起動するのはOSデフォルトの挙動である。

Amazon Linux 2016.09.0 以降、または Windows Server 2008 R2 以降のバージョンを使用してインスタンスを起動した場合、インスタンスは IPv6 に設定され、追加の手順は必要ありません。

Amazon提供のドキュメント

日本語版も不自然な翻訳は見当たらず質が高いですが、英語版のほうが改定が進んでいて若干の違いがあります(2017.1.12現在)

[1] 日本語版 IPv6 への移行 http://docs.aws.amazon.com/ja_jp/AmazonVPC/latest/UserGuide/vpc-migrate-ipv6.html
[2] 英語版 Migrating to IPv6 http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/vpc-migrate-ipv6.html

続きを読む

AWS EC2にMongoDBインストールとレプリケーション設定

MongoDBインストールとレプリケーション設定について、簡易的な抜粋メモとして書いています。
詳細に関しては、記事の最後の参考サイトを確認するようにしてください。

◆ 今日やること

  • MongoDBをEC2にインストール
  • レプリケーションの設定と確認
    • 今回せっていするレプリケーションの形式は、以下の図の通り、「Primary with Secondary Members」です。

mongorepl.png
引用元:Replication — MongoDB Manual 3.4

◆ バージョン

  • MongoDB 3.2
  • Linux 4.4.30-32.54.amzn1.x86_64 #1 SMP Thu Nov 10 15:52:05 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

◆ 実装編

> EC2へのインストール

sudo yum update -y
sudo vim /etc/yum.repos.d/mongodb-org-3.2.repo

[mongodb-org-3.2]
name=MongoDB Repository
baseurl=https://repo.mongodb.org/yum/amazon/2013.03/mongodb-org/3.2/x86_64/
gpgcheck=1
enabled=1
gpgkey=https://www.mongodb.org/static/pgp/server-3.2.asc
sudo yum install -y mongodb-org
sudo service mongod start

sudo chkconfig mongod on

> 設定周り

  • WoredTigerストレージエンジンの主な設定

    • cacheSizeGB: システムメモリの6、7割
    • blockCompressor:デフォルトはsnappy(中間です)
/etc/mongod.conf
# Where and how to store data.
storage:
  dbPath: /data
  journal:
    enabled: true
  wiredTiger:
    engineConfig:
       cacheSizeGB: 1
       journalCompressor: snappy
    collectionConfig:
       blockCompressor: snappy

> EBSボリュームをAttach

  • EBSボリュームにmongoのデータを溜めるようにする。

Amazon EBS ボリュームを使用できるようにする – Amazon Elastic Compute Cloudに従って、EBSボリュームをアタッチする

  • パーミッションを変更するのを忘れないように。
sudo chown -R mongod:mongod /data
  • /etc/mongod.conf
/etc/mongod.conf
# Where and how to store data.
storage:
  dbPath: /data

> レプリケーションの設定

MongoDBではマスターのことをプライマリ,スレーブのことをセカンダリと呼びます。
MongoDBのレプリケーションの最小構成は,3つのノードが必要です。

  • ネットワークインターフェイスの設定で、レプリケーションを組むサーバのIPを記述しておくこと

レプリケーション設定前には、お互いに通信できることを確認しないといけません
Troubleshoot Replica Sets — MongoDB Manual 3.4

mongodb が listen するIPアドレスはデフォルトでは 127.0.0.1 に設定されており、ローカルからのみアクセスを許可するようになっています
mongod.conf の bind_ip に設定されたIPアドレスで listen するのでこれを変更することで外部からの接続を許可します
ここに 0.0.0.0 を設定すると全てのIPアドレスからの接続を許可します

/etc/mongod.conf
# network interfaces
net:
  port: 27017
  bindIp: [127.0.0.1,10.1.52.111,10.1.51.227,10.1.51.68]


  • レプリケーション名を決める
  • Oplogのサイジングと設定サイズを決める
/etc/mongod.conf
replication:
   oplogSizeMB: 500
   replSetName: testRepl

第4回 MongoDBのレプリケーションを構築してみよう:MongoDBでゆるふわDB体験|gihyo.jp … 技術評論社

OplogはCapped Collectionなので,作成時以外にサイズ変更することができません。 デフォルトのOplogのサイズは「1GBまたは,ディスクの空き領域の5%」
Staleを避けるために,Oplogのサイジングは非常に重要となります。
Oplogのサイズは,mongodの初回起動時にoplogSizeオプションで変更可能です。
Oplogの適切なサイズを見積もる方法のひとつに,本番を想定した書き込みテストを実施し,作成されたOplogのサイズを取得する方法があります。
1時間程度,本番想定と同程度の書き込みテストを行った後,以下のコマンドでレプリケーションの最新情報を取得します。

> db.getReplicationInfo()

1時間で作成されたOplogのサイズがわかれば,Oplogのサイジングの目安となります。
少なくとも8時間のセカンダリのダウンタイムに耐えられるようにしておくことが推奨されています。

  • レプリケーションの設定

どれかのサーバに入って、以下のコマンドを実行

config = {
  _id : "testRepl",
  members : [
    { _id : 0, host : "10.1.51.227:27017" },
    { _id : 1, host : "10.1.51.68:27017" },
    { _id : 2, host : "10.1.52.111:27017"} ] }

rs.initiate(config)
  • スレーブの読み取り専用動作設定

そのままだと、スレーブが読み取り専用としてアクセスできないので以下の設定を行っておく。

スレーブノードで、以下のコマンドを実行

 db.getMongo().setSlaveOk()
  • レプリケーションステータスの確認
testRepl:PRIMARY> rs.status();
{
    "set" : "connobaRepl",
    "date" : ISODate("2017-01-12T07:03:05.556Z"),
    "myState" : 1,
    "term" : NumberLong(6),
    "heartbeatIntervalMillis" : NumberLong(2000),
    "members" : [
        {
            "_id" : 0,
            "name" : "10.1.51.227:27017",
            "health" : 1,
            "state" : 1,
            "stateStr" : "PRIMARY",
            "uptime" : 100310,
            "optime" : {
                "ts" : Timestamp(1484182286, 1),
                "t" : NumberLong(6)
            },
            "optimeDate" : ISODate("2017-01-12T00:51:26Z"),
            "electionTime" : Timestamp(1484104344, 1),
            "electionDate" : ISODate("2017-01-11T03:12:24Z"),
            "configVersion" : 3,
            "self" : true
        },
        {
            "_id" : 1,
            "name" : "10.1.51.68:27017",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 100245,
            "optime" : {
                "ts" : Timestamp(1484182286, 1),
                "t" : NumberLong(6)
            },
            "optimeDate" : ISODate("2017-01-12T00:51:26Z"),
            "lastHeartbeat" : ISODate("2017-01-12T07:03:04.017Z"),
            "lastHeartbeatRecv" : ISODate("2017-01-12T07:03:04.020Z"),
            "pingMs" : NumberLong(0),
            "syncingTo" : "10.1.51.227:27017",
            "configVersion" : 3
        },
        {
            "_id" : 2,
            "name" : "10.1.52.47:27017",
            "health" : 1,
            "state" : 2,
            "stateStr" : "SECONDARY",
            "uptime" : 99751,
            "optime" : {
                "ts" : Timestamp(1484182286, 1),
                "t" : NumberLong(6)
            },
            "optimeDate" : ISODate("2017-01-12T00:51:26Z"),
            "lastHeartbeat" : ISODate("2017-01-12T07:03:05.025Z"),
            "lastHeartbeatRecv" : ISODate("2017-01-12T07:03:05.022Z"),
            "pingMs" : NumberLong(2),
            "syncingTo" : "10.1.51.227:27017",
            "configVersion" : 3
        }
    ],
    "ok" : 1
}

> mongoログインの時の警告メッセージを消す方法

[ec2-user@ip-10-1-52-47 ~]$ mongo
MongoDB shell version: 3.2.11
connecting to: test
Server has startup warnings:
2017-01-11T03:10:18.308+0000 I CONTROL  [initandlisten]
2017-01-11T03:10:18.308+0000 I CONTROL  [initandlisten] ** WARNING: /sys/kernel/mm/transparent_hugepage/defrag is 'always'.
2017-01-11T03:10:18.308+0000 I CONTROL  [initandlisten] **        We suggest setting it to 'never'
2017-01-11T03:10:18.308+0000 I CONTROL  [initandlisten]
testRepl:SECONDARY>

◆ 参考サイト

続きを読む

【メモ】 AWSにkopsを使ってkubernetesのクラスタを構築する

kopsでクラスターをインストールしてみたのでメモしておく

眠い。

元ネタ

http://kubernetes.io/docs/getting-started-guides/kops/

普通に上の記事を見ながらやった方が良い

kubectlのインストール

# 最新が1.5.1だったので1.5.1をインストール
# Linux
wget https://storage.googleapis.com/kubernetes-release/release/v1.5.1/bin/linux/amd64/kubectl
chmod +x kubectl
mv kubectl /usr/local/bin/kubectl

# Macで作業する場合は以下らしい(やってない)
wget https://storage.googleapis.com/kubernetes-release/release/v1.5.1/bin/darwin/amd64/kubectl
chmod +x kubectl
mv kubectl /usr/local/bin/kubectl

kopsのインストール

# Linuxから作業した場合
wget https://github.com/kubernetes/kops/releases/download/v1.4.1/kops-linux-amd64
chmod +x kops-linux-amd64
mv kops-linux-amd64 /usr/local/bin/kops

# Macで作業する場合は以下らしい(やってない)
wget https://github.com/kubernetes/kops/releases/download/v1.4.1/kops-darwin-amd64
chmod +x kops-darwin-amd64
mv kops-darwin-amd64 /usr/local/bin/kops

AWS Cliをインストール/設定しておく

cliで使うユーザの権限でS3とかIAMの作成権限とか必要っぽいのでIAMロールに追加しておく

今回つけておいたポリシー (不要なのもあるかも)

  • AmazonEC2FullAccess
  • AmazonSQSFullAccess (どっかでSQS権限が必要とか見た記憶があるんだけど幻だったかもしれない)
  • IAMFullAccess
  • AmazonS3FullAccess
  • AmazonRoute53FullAccess
curl "https://bootstrap.pypa.io/get-pip.py" -o "get-pip.py"
sudo python get-pip.py
sudo pip install awscli
aws configure

Route53にkubernetesクラスター用のゾーンを作成

# aws cliが使えるなら以下の感じで作る
aws route53 create-hosted-zone --name dev.example.com --caller-reference 1

S3にクラスターの設定ファイルを置くバケットを作る

# aws cliが使えるなら以下の感じで作る
aws s3 mb s3://clusters.dev.example.com

# 以下の設定をbash_profileあたりに書いて置く
# export KOPS_STATE_STORE=s3://clusters.dev.example.com
vi ~/.bash_profile
source ~/.bash_profile

クラスターの作成

この時点では設定ファイルが出来上がるだけでEC2インスタンスとかは立ち上がらないです

# VPCを指定しないと自動でVPCが作られてそこにインスタンスが配置される
kops create cluster --zones=ap-northeast-1a apnortheast1.dev.example.com
# 既存のVPCを指定する場合はvpcオプションとnetwork-cidrオプションを指定すればOK
# https://github.com/kubernetes/kops/blob/master/docs/run_in_existing_vpc.md
kops create cluster --zones=ap-northeast-1a apnortheast1.dev.example.com --vpc=vpc-xxxxxxx --network-cidr=172.31.0.0/16

クラスターの定義を修正

デフォルトで立ち上げるとそこそこ良いインスタンス作られるので貧乏仕様に変更

# クラスターの設定
# デフォルトのままで問題ないかと。名前が気に入らなかったり、kubernetesのバージョンとか変えたかったら編集
kops edit cluster apnortheast1.dev.example.com

# master用インスタンスの設定
# なんか自動でmaster-zone名で名前ついてる
# machineTypeを好きなインスタンスタイプに変える
# おそらくmaxSize/minSizeでmasterのインスタンス数を制御できる
# イメージはAMI IDを指定しても大丈夫。デフォルトだとDebian(jessie)だったけど、ami-eec1c380とか指定すればCentOS7で作成される
# https://github.com/kubernetes/kops/blob/master/docs/images.md
kops edit ig --name=apnortheast1.dev.example.com master-ap-northeast-1a

# node用インスタンスの設定
# マスター用と同じノリ
kops edit ig --name=apnortheast1.dev.example.com nodes

クラスター情報の更新

# 設定ファイルだけ反映
kops update cluster apnortheast1.dev.example.com

# 問題なければ --yesをつけて実行するとインスタンスとか作られる
# ちなみにVPCは自動的に"apnortheast1.dev.example.com"で作成されている
# networkCIDRが一致してるVPCがあったらそこに作ってくれるのかな?
# -> 20170111追記 create時に指定すればVPCを指定できた。createのとこにコマンド追記。後からは変えられないっぽい
kops update cluster apnortheast1.dev.example.com --yes

API用のDNSレコードができてないバグ

https://github.com/kubernetes/kops/issues/859

v1.5で修正されるかな

sshログインしてみる

コンソールで確認するとパブリックIPが付与されているので~/.ssh/id_rsaを使ってssh接続できる

# デフォルトで~/.ssh/id_rsa.pubを使って鍵交換してくれるっぽい
# なので-iで指定しなくても一緒
ssh -i ~/.ssh/id_rsa $publicIP
# kubectlのバージョン確認
kubectl version
# ノードの確認
kubectl get nodes
NAME                                               STATUS    AGE
ip-172-20-46-247.ap-northeast-1.compute.internal   Ready     1h
ip-172-20-51-144.ap-northeast-1.compute.internal   Ready     1h
ip-172-20-61-100.ap-northeast-1.compute.internal   Ready     1h

続きを読む

CentOS-7の再起動時、Amazon SSM エージェントが立ち上がらなかった時の対応

Amazon SSM エージェントがOS再起動時こける

AWSのEC2インスタンスでCentOS7を作成し、Amazon SSMエージェントを使うためインストールしたが、OSを再起動したらAmazon SSMエージェントがこけていたので、その対応した時の備忘録。

今回の環境

  • Amazon EC2 (Instance Type: t2.micro)
  • CentOS-7 (AMI ID ami-eec1c380)

再起動したときのエラー

/var/log/message
Jan  6 19:09:23 hogehoge2 systemd: Started amazon-ssm-agent.
Jan  6 19:09:23 hogehoge2 systemd: Starting amazon-ssm-agent...
Jan  6 19:09:23 hogehoge2 amazon-ssm-agent: 2017/01/06 19:09:23 Failed to load instance info from vault. RegistrationKey does not exist.
Jan  6 19:09:23 hogehoge2 amazon-ssm-agent: Error occured fetching the seelog config file path:  open /etc/amazon/ssm/seelog.xml: no such file or directory
Jan  6 19:09:23 hogehoge2 amazon-ssm-agent: 2017-01-06 19:09:23 INFO Starting Agent: amazon-ssm-agent - v2.0.562.0
Jan  6 19:09:23 hogehoge2 amazon-ssm-agent: 2017-01-06 19:09:23 INFO OS: linux, Arch: amd64
Jan  6 19:09:25 hogehoge2 amazon-ssm-agent: 2017-01-06 19:09:25 ERROR error fetching the region, Failed to fetch region. Data from vault is empty. Get http://169.254.169.254/latest/dynamic/instance-identity/document: dial tcp 169.254.169.254:80: connect: network is unreachable
Jan  6 19:09:25 hogehoge2 amazon-ssm-agent: 2017-01-06 19:09:25 ERROR error occured when starting core manager: Failed to fetch region. Data from vault is empty. Get http://169.254.169.254/latest/dynamic/instance-identity/document: dial tcp 169.254.169.254:80: connect: network is unreachable
Jan  6 19:09:25 hogehoge2 amazon-ssm-agent: 2017-01-06 19:09:25 ERROR error occured when starting amazon-ssm-agent: Failed to fetch region. Data from vault is empty. Get http://169.254.169.254/latest/dynamic/instance-identity/document: dial tcp 169.254.169.254:80: connect: network is unreachable

エラーが表示されているところで Get http://169.254.169.254/latest/dynamic/instance-identity/document: dial tcp 169.254.169.254:80: connect: network is unreachable とあり、ネットワークがまだ立ち上がろうとしている前にAmazon SSM エージェントが立ち上がろうとし、コケているのではと推測しました。

psコマンドで確認するも、Amazon SSM エージェントのプロセスは無かったです。

対応

社内で「systemdの順序を定義してやれば、解消する気がしますね。」という話とともに、Systemd メモ書き – Qiita の記事をもらいましたのでやってみました。

やってみた

/etc/systemd/system/amazon-ssm-agent.service
[Unit]
Description=amazon-ssm-agent
After=network.target ←追記部分
  〜〜snip〜〜

結果、うまく動いた感じっぽ・・・

上記にある /etc/systemd/system/amazon-ssm-agent.service のファイルに、 After=network.target を追記してOSを再起動した。
そのときのログ

/var/log/message
Jan 10 12:38:25 hogehoge2 systemd: Started amazon-ssm-agent.
Jan 10 12:38:25 hogehoge2 systemd: Starting amazon-ssm-agent...
Jan 10 12:38:25 hogehoge2 amazon-ssm-agent: 2017/01/10 12:38:25 Failed to load instance info from vault. RegistrationKey does not exist.
Jan 10 12:38:25 hogehoge2 amazon-ssm-agent: Error occured fetching the seelog config file path:  open /etc/amazon/ssm/seelog.xml: no such file or directory
Jan 10 12:38:25 hogehoge2 amazon-ssm-agent: 2017-01-10 12:38:25 INFO Starting Agent: amazon-ssm-agent - v2.0.562.0
Jan 10 12:38:25 hogehoge2 amazon-ssm-agent: 2017-01-10 12:38:25 INFO OS: linux, Arch: amd64
Jan 10 12:38:25 hogehoge2 amazon-ssm-agent: 2017-01-10 12:38:25 INFO Initializing bookkeeping folders
Jan 10 12:38:25 hogehoge2 amazon-ssm-agent: datastore file /var/lib/amazon/ssm/i-XXXXXXXXXXXXXXXXX/longrunningplugins/datastore/store doesn't exist - no long running plugins to execute
Jan 10 12:38:25 hogehoge2 amazon-ssm-agent: 2017-01-10 12:38:25 INFO Initializing bookkeeping folders for long running plugins
Jan 10 12:38:25 hogehoge2 amazon-ssm-agent: 2017-01-10 12:38:25 INFO Initializing healthcheck folders for long running plugins
Jan 10 12:38:25 hogehoge2 amazon-ssm-agent: 2017-01-10 12:38:25 INFO Initializing locations for inventory plugin
Jan 10 12:38:25 hogehoge2 amazon-ssm-agent: 2017-01-10 12:38:25 INFO Initializing default location for custom inventory
Jan 10 12:38:25 hogehoge2 amazon-ssm-agent: 2017-01-10 12:38:25 INFO [instanceID=i-XXXXXXXXXXXXXXXXX] Create new startup processor

うまく動いたようです〜!
以下の様にプロセスも確認できました。

$ ps -ax | grep ssm
  756 ?        Ssl    0:00 /usr/bin/amazon-ssm-agent

最後に・・・

Amazon Linux (AMI ID ami-9f0c67f8)で同じ事になっているか同じように確認したのですが、こちらは /etc/systemd/system/amazon-ssm-agent.service を設定する事なく、デフォルトのままでOSを再起動をしてもSSMエージェントが立ち上がらないということは無いようでした。

理由はわかりませんが、こんな事もあったと言うことで、備忘録として記録しておきます。

続きを読む

StackStormでNew Relicと連携してみました

image

はじめに

前回はAWSにStackStormをインストールしたので、今回はアプリケーション監視ツールであるNew Relicと連携できるようにしたいと思います。
StackStormには、Packと呼ばれるソフトウェアコンポーネントの追加機能があり、New RelicのPackも用意されています。今回はPackのインストールから使い方まで紹介したいと思います。

New Relicに関しては、下記記事を参考にしてください。
New RelicのAPMとINFRASTRUCTUREを使って監視してみました(前半)
New RelicのAPMとINFRASTRUCTUREを使って監視してみました(後半)

StackStomの設定

New Relic Packのインストール

下記st2コマンドでNewRelicのPackをインストールします。statusがsucceededになっていたら成功です。

$ st2 run packs.install packs=newrelic
......................
id: 586df3da897d4405b3b07f36
action.ref: packs.install
parameters:
  packs:
  - newrelic
status: succeeded
start_timestamp: 2017-01-05T07:20:58.022719Z
end_timestamp: 2017-01-05T07:23:13.100056Z
+--------------------------+-------------------------+--------------------------+-------------------------+------------------------------+
| id                       | status                  | task                     | action                  | start_timestamp              |
+--------------------------+-------------------------+--------------------------+-------------------------+------------------------------+
| 586df3da897d440342b8b6ba | succeeded (7s elapsed)  | download                 | packs.download          | Thu, 05 Jan 2017 07:20:58    |
|                          |                         |                          |                         | UTC                          |
| 586df3e2897d440342b8b6bd | succeeded (3s elapsed)  | virtualenv_prerun        | packs.virtualenv_prerun | Thu, 05 Jan 2017 07:21:06    |
|                          |                         |                          |                         | UTC                          |
| 586df3e5897d440342b8b6c0 | succeeded (56s elapsed) | setup_virtualenv         | packs.setup_virtualenv  | Thu, 05 Jan 2017 07:21:09    |
|                          |                         |                          |                         | UTC                          |
| 586df41e897d440342b8b6c4 | succeeded (63s elapsed) | reload                   | packs.load              | Thu, 05 Jan 2017 07:22:06    |
|                          |                         |                          |                         | UTC                          |
| 586df45e897d440342b8b6c8 | succeeded (2s elapsed)  | restart-sensor-container | packs.restart_component | Thu, 05 Jan 2017 07:23:10    |
|                          |                         |                          |                         | UTC                          |
+--------------------------+-------------------------+--------------------------+-------------------------+------------------------------+

New Relic Packの確認

1) センサー確認

$ st2 sensor list
+---------------------------------+----------+---------------------------------+---------+
| ref                             | pack     | description                     | enabled |
+---------------------------------+----------+---------------------------------+---------+
| newrelic.NewRelicHookSensor     | newrelic | Sensor which watches for alerts | True    |
|                                 |          | from NewRelic API.              |         |
| newrelic.LegacyNewRelicHookSens | newrelic | Sensor which watches for alerts | False   |
| or                              |          | from the NewRelic legacy API.   |         |
+---------------------------------+----------+---------------------------------+---------+

2)トリガー確認

$ st2 trigger list
+--------------------------------------+----------+-------------------------------------------+
| ref                                  | pack     | description                               |
+--------------------------------------+----------+-------------------------------------------+
| newrelic.WebAppAlertTrigger          | newrelic |                                           |
| newrelic.WebAppNormalTrigger         | newrelic |                                           |
| newrelic.ServerAlertTrigger          | newrelic |                                           |
| newrelic.ServerNormalTrigger         | newrelic |                                           |
+--------------------------------------+----------+-------------------------------------------+

3)アクション確認

$ st2 action list | grep new
+---------------------------------+----------+-------------------------------------------+
| ref                             | pack     | description                               |
+---------------------------------+----------+-------------------------------------------+
| newrelic.get_alerts             | newrelic | Get alerts for app.                       |
| newrelic.get_metric_data        | newrelic | Get metric data for metric.               |

New Relic Packの設定

1) 設定ファイルコピー
New RelicのPackは、下記フォルダーに保存されるので、

/opt/stackstorm/packs/newrelic/

サンプルファイルから設定ファイルを作成します

cd /opt/stackstorm/configs
cp /opt/stackstorm/packs/newrelic/newrelic.yaml.example ./newrelic.yaml

2) 設定ファイルの編集
デフォルトだとBase URLが、http://x.x.x.x:10001/st2/nrhook/になります

$vim ./newrelic.yaml
---
api_url: "https://api.newrelic.com/v2/"
api_key: "<New RelicのAPIキーを入力します>"
sensor_config:
    host: "0.0.0.0"
    port: 10001
    url: "/st2/nrhook/"
    normal_report_delay: 300

3) st2 再起動
設定を有効にするためにStackStormを再起動します

$ st2ctl reload

4) TCPポート起動確認
New RelicのSenserが起動すると、TCPの10001番でListenします

$ netstat -ln | grep 10001
tcp        0      0 0.0.0.0:10001           0.0.0.0:*               LISTEN

ルール作成

New Relicから送信されたアラート内容を、ファイル(st2.newrelic.out)に出力するルールを作成

1) APMアラート用ルール作成

$ cd /opt/stackstorm/packs/newrelic/rules/
$ vim webapp_notify.yaml
---
name: "webapp.notify"
pack: "newrelic"
description: "WebAppAlertTrigger Sample rule for newrelic."
enabled: true

trigger:
    type: "newrelic.WebAppAlertTrigger"

criteria: {}

action:
    ref: "core.local"
    parameters:
        cmd: "echo {{ trigger.alert }} >> ~/st2.newrelic.out"

2) Serversアラート用ルール作成

$ vim server_notify.yaml
---
name: "server.notify"
pack: "newrelic"
description: "ServerAlertTrigger Sample rule for newrelic."
enabled: true

trigger:
    type: "newrelic.ServerAlertTrigger"

criteria: {}

action:
    ref: "core.local"
    parameters:
        cmd: "echo {{ trigger.alert }} >> ~/st2.newrelic.out"

3)st2ルール作成

st2 rule create /opt/stackstorm/packs/newrelic/rules/webapp_notify.yaml
st2 rule create /opt/stackstorm/packs/newrelic/rules/server_notify.yaml

4)st2ルール確認

$ st2 rule list
+------------------------+----------+-----------------------------------------+---------+
| ref                    | pack     | description                             | enabled |
+------------------------+----------+-----------------------------------------+---------+
| newrelic.server.notify | newrelic | ServerAlertTrigger Sample rule for      | True    |
|                        |          | newrelic.                               |         |
| newrelic.webapp.notify | newrelic | WebAppAlertTrigger Sample rule for      | True    |
|                        |          | newrelic.                               |         |
+------------------------+----------+-----------------------------------------+---------+

動作確認

StackStomから自分宛(127.0.0.1)にテスト用のアラートを送信して確認します。

1) APMアラート確認用

curl -X POST 
    -H 'Content-Type:application/json; charset=UTF-8' 
    -d '{ 
    "current_state":"open",
    "details":"Apdex < .50 for at least 10 min",
    "severity":"CRITICAL",
    "event_type":"INCIDENT",
    "targets":[{
        "product": "APM", 
        "name": "TEST APM",
        "labels": {}, 
        "type": "Application", 
        "id": "123456789"
        }]
    }' 
http://127.0.0.1:10001/st2/nrhook/

2) Serversアラート確認用

curl -X POST 
    -H 'Content-Type:application/json; charset=UTF-8' 
    -d '{ 
    "current_state":"open",
    "details":"System load > 0.1 for at least 5 minutes",
    "severity":"CRITICAL",
    "event_type":"INCIDENT",
    "targets":[{
        "product": "SERVERS", 
        "name": "TEST Servers",
        "labels": {}, 
        "type": "Server", 
        "id": "123456789"
        }]
    }' 
http://127.0.0.1:10001/st2/nrhook/

3) アラート内容の確認

$ tail /home/stanley/st2.newrelic.out
{uevent_type: uINCIDENT, udetails: uApdex < .50 for at least 10 min, ucurrent_state: uopen, utargets: [{uproduct: uAPM, ulabels: {}, utype: uApplication, uname: uTEST APM, uid: u123456789}], useverity: uCRITICAL}
{uevent_type: uINCIDENT, udetails: uSystem load > 0.1 for at least 5 minutes, ucurrent_state: uopen, utargets: [{uproduct: uSERVERS, ulabels: {}, utype: uServer, uname: uTEST Servers, uid: u123456789}], useverity: uCRITICAL}

AWSの設定

1)セキュリテイ―グループの追加
外部(New Relic)からTCP:10001の接続ができるようセキュリテイ―グループを変更
New Relic DocumentのWebhook alerts項目にアラートの送信元IPが記載されているので、必要であれば送信元を制限します。

Webhook alerts
New Relic-generated webhooks for alert policies will be sent from an IP address in the 50.31.164.0/24 or 162.247.240.0/22 network block.

New Relic Alertsの設定

1)AlertsのNotification Channelの追加
image

2)Channelの設定
StackStomの待ち受けポート(10001/tcp)に対してWebhookの設定をします。
image

3)Alert Policyの作成

image

4)Alerts Conditionの作成
アラート条件を設定します
image

5)Channelの選択
先ほど作成したStackStomのWebhookのChannelを選択し追加します。
image

これでNew RelicからのAlertsをトリガーにStackStormで連携する事ができました。

続きを読む