2015年4月18日土曜日

IAMロールを使ってEC2からS3のバケット一覧を取得してみた時のメモ

このエントリーをはてなブックマークに追加 はてなブックマーク - IAMロールを使ってEC2からS3のバケット一覧を取得してみた時のメモ

IAMロールを使ってEC2からS3のバケット一覧を取得してみた時のメモ

参考

EC2からS3へアクセスするIAMロールを作る

  • Roles
  • Create New Role
  • ロール名を決める(S3_Accessなど)
  • AWS Services RoleではAmazon EC2を選択
  • Attach PolicyではAmazonS3FullAccessを選択(一覧を取るだけなのでReadOnlyのものでもOK)
  • Create Role

EC2の起動

起動する時のIAM Roreの項目で先ほどのロールを選択(S3_Accessなど)

確認

以降、対象のEC2にSSHログインしてからの操作。

Rubyでやってみる。まずはAWS-SDKをインストール

$gem install aws-sdk-core

コードを書いてみる

$vi get_buckets.rb

以下のようにする。

require "aws-sdk-core"

Aws.config[:region] = 'ap-northeast-1'
s3 = Aws::S3::Client.new

resp = s3.list_buckets
puts resp.buckets.map(&:name)

実行

$ruby get_buckets.rb

これで取得できちゃいます。credentialsの設定とかを特にしなくて良いので楽。ドキュメントを見るとローカルのcredential情報を探した後になければIAMRoleの情報を探して使うようです。便利。

This code initializes an AWS::S3 object without specifying any credentials, which initiates a search for credentials using the default credential provider chain. The default credential provider chain looks for credentials specified in the environment, and failing that, will look for credentials from EC2’s metadata service.

また、メタデータ(curl http://169.254.169.254/latest/meta-data/iam/security-credentials/S3_Access)を直接取得すると分かるのですが、利用できるAccessKeyIdとSecretAccessKeyは一定周期でより変わるので、直接credentialファイルを置くよりもよりセキュアだと思います。

2015年4月16日木曜日

AWS-VPCピアリングを試してみた

このエントリーをはてなブックマークに追加 はてなブックマーク - AWS-VPCピアリングを試してみた

VPCピア接続を行い、異なるVPC間でのSSH接続を確認した時のメモ

参考

前提

  • 同一リージョン
  • アベイラビリティゾーンは違っても大丈夫
  • AWSアカウントが違っても大丈夫
  • IPアドレス帯域が重複することはNG。VPCに割り当たっているのが172.16.0.0/16と172.16.0.0/16だとNGダメ。同じように172.16.0.0/16と172.16.1.0/24でも重複する帯域があるのでNG

AWSでの設定

上記がとても詳しく書いてありました。下記メモ。

  • 異なるCIDRのVPCを作成。今回の場合、VPC-A(172.31.0.0/16)とVPC-B(10.0.0.0/16)のCIDRを持つVPCで検証。
  • VPCのPeering Connectionsを選択し、VPC-A側でVPC Peering Connectionを作成する。Local VPC to peerでは接続するVPC-Bを選択する。別のAWSアカウントを利用する場合、Account情報を入れる
  • 上記実施後、VPC-B側でPeeringの承認をする
  • VPC-A,Bそれぞれでルーティング設定を行う

テストしてみる

準備ができたのでEC2を起動して、異なるVPC間でSSH接続ができるか確認します。

  • VPC-A,VPC-BにそれぞれEC2を起動します。どちらのEC2でもAuto-assign PublicIPの設定を行います。また、SecurityGroupでは22ポートでanywhere(0.0.0.0)からの接続を許可するようにします。
  • 自分のPCからどちらにもSSH接続できることを確認します。
  • VPC-Bで新しくユーザーを作成します。EC2にSSH接続用のユーザーを作成するを実施。
  • VPC-Aにログイン。~/.ssh/id_rsaを上記でコピペしたid_rsaの内容に変更。その後、chmod 0600 ~/.ssh/id_rsaを行う。
  • ssh deploy@10.0.1.233としてSSHログインできるか確認。指定するVPC-Bに存在するEC2のプライベートIPの部分は読み替えてください。
  • VPC-B側のSecurityGroupでSSHのinboundを許可するIPをanywhere(0.0.0.0/0)からVPC-A側のプライベートIP(172.31.15.213/16)などに指定します。そうすることでVPC-B側へのSSHはVPC-Aのインスタンスを介してのみできるような設定とできます。

2015年4月11日土曜日

fluentd-v2+elasticsearch+kibana3をEC2上で実施する

このエントリーをはてなブックマークに追加 はてなブックマーク - fluentd-v2+elasticsearch+kibana3をEC2上で実施する

nginxのアクセスログをfluentdを使ってelasticsearchに登録し、その情報をkinaba3を使って見れるようにした時のメモ

環境

  • Amazon Linux AMI 2015.03 (HVM), SSD Volume Type
  • td-agent 0.12.7
  • elasticsearch 1.3(最終的に1.4にアップグレード)
  • kibana3

td-agent2のインストール

最新のFluentd(td-agent2)ではAmazonLinuxもサポートとなったようなのでスクリプトからインストールします

td-agent2をAmazon Linuxで実行する

curl -L http://toolbelt.treasuredata.com/sh/install-redhat-td-agent2.sh | sudo sh
$td-agent --version
td-agent 0.12.7
$sudo chkconfig td-agent on
$sudo chkconfig --list |grep td-agent

elastic-search1.3のインストール、起動

基本的には公式サイトに書いてあるように進めます。

elastic-search(YUM)

$sudo rpm --import https://packages.elasticsearch.org/GPG-KEY-elasticsearch
$sudo vi /etc/yum.repos.d/elasticsearch.repo

以下を記載します。

[elasticsearch-1.3]
name=Elasticsearch repository for 1.3.x packages
baseurl=http://packages.elasticsearch.org/elasticsearch/1.3/centos
gpgcheck=1
gpgkey=http://packages.elasticsearch.org/GPG-KEY-elasticsearch
enabled=1

インストールおよび自動起動登録、起動をします。

$sudo yum install elasticsearch
$sudo chkconfig --add elasticsearch
$sudo chkconfig --list |grep elasticsearch
$sudo service elasticsearch start

なお、起動時にメモリ量が確保出来なくてエラーになる場合があります。その場合には不要なプロセスをkillすればt2.microでも起動できました。もしくは/etc/elasticsearch/elasticsearch.ymlでメモリ量を記載することでも調整できるようです。

クラスタとノードの名前を確認

クラスタとノードの名前を確認します。 jqをインストールしていない人はyumでインストールしておくと便利だと思います。

# cluster
$curl -XGET http://localhost:9200/_cluster/health | jq .
{
  "cluster_name": "elasticsearch",
  "status": "green",
  "timed_out": false,
  "number_of_nodes": 1,
  "number_of_data_nodes": 1,
  "active_primary_shards": 0,
  "active_shards": 0,
  "relocating_shards": 0,
  "initializing_shards": 0,
  "unassigned_shards": 0
}

# node
$curl -XGET http://localhost:9200/ | jq .
{
  "status": 200,
  "name": "Sam Wilson",
  "version": {
    "number": "1.3.9",
    "build_hash": "0915c7306e6264ba21a6cb7609b93545ccc32ef1",
    "build_timestamp": "2015-02-19T12:34:48Z",
    "build_snapshot": false,
    "lucene_version": "4.9"
  },
  "tagline": "You Know, for Search"
}

デフォルトだとクラスタ名はelasticsearch、ノードは任意のマーベルコミックの人物になるようです。

クラスタの名前を変更する

クラスタ名とノード名を任意のものに変更します。本例ではクラスタ名をtest_cluster、ノード名をnode_1としました。

$sudo vi /etc/elasticsearch/elasticsearch.yml

cluster.name: test_cluster

node.name: "node_1"

設定後、サービスを再起動します。

$sudo service elasticsearch restart

変更を確認します。

# cluster
$curl -XGET http://localhost:9200/_cluster/health | jq .

# node
curl -XGET http://localhost:9200/ | jq .

どちらも変更されていることが確認できると思います。

nginxのインストール

$sudo yum install nginx
$sudo service nginx start
$sudo chkconfig nginx on
$chkconfig --list |grep nginx

fluentdのelastic-searchプラグインのインストール

fluentd経由でelastic-searchのプラグインをインストールします。事前に必要となるDevelopment toolscurl-develもインストールします。

$sudo yum groupinstall 'Development tools'
$sudo yum -y install curl-devel
$sudo /opt/td-agent/embedded/bin/fluent-gem install fluent-plugin-elasticsearch

nginxのアクセスログのフォーマットを確認する

nginxのログフォーマットを確認するためにFluentularというサイト上でFluentdのログフォーマットを確認できるサイトを使います。

上記サイトで実際に出力されるログとそのフォーマットが正しくできるまでを確認後、実際に設定ファイルに記載して内容を確認します。

まずは、標準出力に出すようにしています。

$sudo vi /etc/td-agent/td-agent.conf

以下のように記載します。

<source>
  type tail
  path /var/log/nginx/access.log
  format /^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)" "(?<forward>[^\"]*)")?$/
  time_format %d/%b/%Y:%H:%M:%S %z
  pos_file /var/log/td-agent/nginx-access.log.pos
  tag nginx.access
</source>

<match nginx.access.**>
  type stdout
</match>

実際に動作が可能なやってみます。 今回はログがわかり易いようにflunetdをトレースモードで起動します。

$sudo td-agent -vv &

その後、実際にnginxにアクセスしてみます。

$wget http://localhost
--2015-04-11 02:53:04--  http://localhost/
localhost (localhost) をDNSに問いあわせています... 127.0.0.1
localhost (localhost)|127.0.0.1|:80 に接続しています... 接続しました。
2015-04-11 02:53:04 +0000 nginx.access: {"remote":"127.0.0.1","host":"-","user":"-","method":"GET","path":"/","code":"200","size":"3770","referer":"-","agent":"Wget/1.16.1 (linux-gnu)","forward":"-"}
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 3770 (3.7K) [text/html]
`index.html' に保存中

index.html          100%[=====================>]   3.68K  --.-KB/s 時間 0s

2015-04-11 02:53:04 (555 MB/s) - `index.html' へ保存完了 [3770/3770]

設定がうまくいっていれば、上記のメッセージの中にnginx.accessなどのように正しくfluentdがログをパースできているか確認できます。

上記、問題なければ一度fluentdを止めます。

$ps aux|grep ruby|awk ‘{ print $2 }’|sudo xargs kill -KILL

td-agentの設定ファイルを変更します。 デバッグ用にcopyプラグインを使って、標準出力もしつつ、ElasticSearchへの登録を行う設定に変更します。

$vi td-agent.conf

以下のように変更します。

<source>
  type tail
  path /var/log/nginx/access.log
  format /^(?<remote>[^ ]*) (?<host>[^ ]*) (?<user>[^ ]*) \[(?<time>[^\]]*)\] "(?<method>\S+)(?: +(?<path>[^\"]*) +\S*)?" (?<code>[^ ]*) (?<size>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)" "(?<forward>[^\"]*)")?$/
  time_format %d/%b/%Y:%H:%M:%S %z
  pos_file /var/log/td-agent/nginx-access.log.pos
  tag nginx.access
</source>

<match nginx.access.**>
  type copy

  <store>
    type stdout
  </store>

  <store>
    type elasticsearch
    host localhost
    port 9200
    type_name nginx_log
    include_tag_key true
    logstash_format true
    tag_key tag
  </store>
</match>

再起動後、nginxにリクエストを投げてアクセスログを更新します。

$td-agent -vv &
$wget http://localhost

先程と同じように標準出力にログがパースできているか確認し、問題なければ少し待つと以下のような出力がされます。

2015-04-11 04:19:50 +0000 [info]: plugin/out_elasticsearch.rb:67:client: Connection opened to Elasticsearch cluster => {:host=>"localhost", :port=>9200, :scheme=>"http"}

上記出力後、問題なければlogstash–2015.04.11というような今日の日付のインデックスができていると思うので全ての内容を取得します。

#データ取得(全件)
curl -XGET http://localhost:9200/logstash-2015.04.11/_search -d '
{
  "query": {
    "match_all" : {}
  }
}
' | jq .
{
"took": 44,
"timed_out": false,
"_shards": {
  "total": 5,
  "successful": 5,
  "failed": 0
},
"hits": {
  "total": 1,
  "max_score": 1,
  "hits": [
    {
      "_index": "logstash-2015.04.11",
      "_type": "nginx_log",
      "_id": "8w0OI32bRRObQna13HGcJQ",
      "_score": 1,
      "_source": {
        "remote": "127.0.0.1",
        "host": "-",
        "user": "-",
        "method": "GET",
        "path": "/",
        "code": "200",
        "size": "3770",
        "referer": "-",
        "agent": "Wget/1.16.1 (linux-gnu)",
        "forward": "-",
        "tag": "nginx.access",
        "@timestamp": "2015-04-11T04:18:57+00:00"
      }
    }
  ]
}
}

例えばsizeパラメーターが3000より大きいものみ取得したい場合には以下のようなリクエストを送ります。

curl -XGET http://localhost:9200/logstash-2015.04.11/_search -d '
{
  "query": {
    "query_string" : {
    "query" : "size:>3000"
   }
 }
}
' | jq .

kibanaのインストール

現在はKibana4がリリースされていますが、導入してみたところ、elasticsearch1.4.4以上である必要があったので今回はKinaba3で実施することにしました。

Kibana3.1.2

$wget https://download.elastic.co/kibana/kibana/kibana-3.1.2.tar.gz
$tar -zxvf kibana-3.1.2.tar.gz
$mv kibana-3.1.2 kibana
$sudo mv kibana /usr/share/nginx/html

nginxを再起動します。

$service nginx restart

上記の場合http://yourhost/kibanaとするとkibanaのサイトにアクセスできるようになっているかと思います。

ただし、Connection failedと表示されてelasticsearchとの接続がうまくできていないようでした。

上記原因の一つとしてまず、SecurityGroupの設定で9200ポートを開いていないことが問題の一つだったので、開けるように設定します。

また、上記を対応してもまだ接続エラーとなってしまい、色々探したのですが、利用が全くわからなかったのでelasticsearchのバージョンを1.3から1.4にあげて、設定を変えてみたところうまくいきました。

ElasticSearch–1.4-YUM

$sudo vi /etc/yum.repos.d/elasticsearch.repo

以下に変更。

[elasticsearch-1.4]
name=Elasticsearch repository for 1.4.x packages
baseurl=http://packages.elasticsearch.org/elasticsearch/1.4/centos
gpgcheck=1
gpgkey=http://packages.elasticsearch.org/GPG-KEY-elasticsearch

アップデート。

$sudo yum update

また、elasticsearch1.4からセキュリティ向上が目的で設定が追加で必要になったようで、それを追加します。

Kibana3+Elasticsearch1.4.1でConnection Failedと怒られる

$sudo vi /etc/elasticsearch/elasticsearch.yml 

以下を末尾に追記。

http.cors.allow-origin: "/.*/"
http.cors.enabled: true

サービスを再起動。

$sudo service elasticsearch restart
$sudo service nginx

この状態でアクセスするとうまくできました。