バージョン&記載ソースリポジトリ
version |
---|
ansible 1.9.0.1 |
ポイントとなるソースのみ載せています。全てのソースが見たい場合は、以下のリポジトリを参照してください。
Ansible で構築したサーバーのアプリの各バージョン
version |
---|
elasticsearch 1.6.0 |
td-agent 0.12.7 |
kibana 4.1.0 |
nginx 1.6.2 |
概要
ELB のアクセスログを Kibana で分析するサーバーをすぐに構築できるように Ansible playbook を作成しました。
前回の phpMyAdmin サーバー playbook の教訓を生かして、今回はロールを細かく定義しました。
ELBのアクセスログを S3 へ保存
- ELB のアクセスログを S3 へ保存する方法
ここを参考に ELB のアクセスログを S3 に保存するようにしました。
他にも参考はたくさんありました。
ElasticSearch のインストール
yum モジュールで rpm を直接インストールすることができました。
これで elasticsearch を簡単にインストールできます。
設定は、デフォルトのままを使っているので、templates, defines は特に定義していません。
ここら辺は、実際に使って問題が発生したら調整する予定です。
---
- name: Install elasticsearch
yum: name="https://download.elastic.co/elasticsearch/elasticsearch/elasticsearch-1.6.0.noarch.rpm" state="present"
notify: restart elasticsearch
- name: Set elasticsearch service to start on boot
service: name=elasticsearch enabled=true
Fluentd のインストール
Ansible Galaxy を見てると、install-redhat-td-agent2.sh の中でやってる処理を Ansible で記述する(Fluentd のインストールはリポジトリを追加して、yum でインストールする)のが正しいやり方みたいです。
ただ、、、今回は、install-redhat-td-agent2.sh を使う方法で書きました。
最近、この curl で shell をとってきて実行してインストールするタイプが増えてる気がするので、この手順を Ansible で書く方法を理解しておきたかったからです。
今の手順での欠点は、playbook を実行するたびに Ansible に「changed」判定されてしまうことです。
良い方法は、、、思いついてません。
ELB のアクセスログを収集するプラグインは2つありますが、
- https://github.com/shinsaka/fluent-plugin-elb-log
- https://github.com/winebarrel/fluent-plugin-elb-access-log
今回は、 fluent-plugin-elb-access-log を利用しました。
強い思いがあったわけではなく、まずは、こちらで試してみようっという感じです。
この辺も使っていくうちに変えると思います。
fluent-plugin-elb-access-log 0.2.4 と AWS SDK 2.1.1 (2015/06/21 時点最新)組み合わせだとエラーが発生していたので、 AWS SDK 2.0.48 を入れるようにしています。
証明書に関するエラーが発生したので、以下サイトを参考にして、証明書を置き換える処理を追加しました。
---
- name: Download fluentd
get_url: url="https://td-toolbelt.herokuapp.com/sh/install-redhat-td-agent2.sh" dest="/tmp/install-redhat-td-agent2.sh" mode=0755
- name: Install fluentd
shell: /tmp/install-redhat-td-agent2.sh
- name: Set fluentd service to start on boot
service: name=td-agent enabled=true
# 2015.06.27 fluent-plugin-elb-access-log が aws-sdk 2.1系に対応したので、aws-sdk 2.0系をインストールする処理は入りません!!
#- name: Install the aws-sdk (In version specified because there is a bug)
# gem: name={{ item }} version=2.0.48 executable="/opt/td-agent/embedded/bin/fluent-gem" user_install=false
# with_items:
# - aws-sdk
# - aws-sdk-core
# - aws-sdk-resources
- name: Install fluentd-plugins
gem: name={{ item }} state=latest executable="/opt/td-agent/embedded/bin/fluent-gem" user_install=false
with_items:
- fluent-plugin-elasticsearch
- fluent-plugin-elb-access-log
notify: restart fluentd
- name: Put td-agent.conf
template: src=td-agent.conf.j2 dest=/etc/td-agent/td-agent.conf backup=true mode=0644
notify: restart fluentd
- name: Check replaced the certificate
stat: path=/opt/td-agent/embedded/ssl/certs/cacert.pem.original
register: cert_pem_original
- name: Backup the certificate
command: cp /opt/td-agent/embedded/ssl/certs/cacert.pem /opt/td-agent/embedded/ssl/certs/cacert.pem.original
when: not cert_pem_original.stat.exists
- name: Replace the certificate
command: cp /etc/pki/tls/cert.pem /opt/td-agent/embedded/ssl/certs/cacert.pem
when: not cert_pem_original.stat.exists
fluent-plugin-elb-access-log の設定で、AWSに関連した情報が必要になります。
...
{% for source in fluentd_sources %}
<source>
type elb_access_log
aws_key_id {{ source.aws_key_id }}
aws_sec_key {{ source.aws_sec_key }}
account_id {{ source.account_id }}
region {{ source.region }}
s3_bucket {{ source.s3_bucket }}
s3_prefix {{ source.s3_prefix }}
tag elb.access_log
#tsfile_path /var/tmp/fluent-plugin-elb-access-log.ts
#histfile_path /var/tmp/fluent-plugin-elb-access-log.history
#interval 300
start_datetime {{ source.start_datetime }}
#buffer_sec 600
#history_length 100
#sampling_interval 1
debug true
</source>
{% endfor %}
<match elb.access_log>
type elasticsearch
type_name access_log
host localhost
port 9200
logstash_format true
include_tag_key true
tag_key @log_name
</match>
...
ぼくは アクセスキー/シークレットキーのために IAM でユーザーを作りました。
適用したポリシーは以下です。
Action は参照系の処理のみに絞るのが適切だと思いますが、どの Action のみにすればよいかがわからくて、 S3:* にしてしまいました。。。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt999999999999",
"Effect": "Allow",
"Action": [
"s3:*"
],
"Resource": [
"arn:aws:s3:::バケット名",
"arn:aws:s3:::バケット名/*"
]
}
]
}
Nginx のインストール
Kibana4 は単体でも動作しますが、HTTPS にして、Basic 認証をかけたかったので Nginx でリバースプロキシさせます。
そうすることで、AWS のセキュリティグループは、HTTP(80), HTTPS(443)の2つのみのポートを解放すれば良くなります。
Kibana4 のデフォルトポート 5601 を解放する必要はありません。
(ちなみに、、、Nginx を利用しなくても、ElasticSearch のデフォルトポート 9200 を解放する必要はありません。)
Nginx は yum でインストールできるので簡単です。
SSL を利用するための自己証明書(オレオレ証明書)も以下を参考に作っています。
---
- 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: Create self signed certificate
shell: |
mkdir -p /etc/nginx/certs &&
crt_file="/etc/nginx/certs/local-ssl.crt" &&
key_file="/etc/nginx/certs/local-ssl.key" &&
crt_and_key_file="/etc/nginx/certs/local-ssl.crt_and_key" &&
subject="/C=JP/ST=Osaka/L=Osaka City/CN=local-ssl" &&
openssl req -new -newkey rsa:2048 -sha1 -x509 -nodes \
-set_serial 1 \
-days 3650 \
-subj "$subject" \
-out "$crt_file" \
-keyout "$key_file" &&
cat "$crt_file" "$key_file" >> "$crt_and_key_file" &&
chmod 400 "$key_file" "$crt_and_key_file"
creates="/etc/nginx/certs/local-ssl.crt"
Kibana4 のインストール
Kibana4 が出ているので、3 ではなく 4 を使います。
Kibana のインストールは、tar.gz をダウンロードして解凍するタイプです。
command や shell モジュールを使いたくなってきましたが、ぐっとこらえて、
- ダウンロードは get_url モジュール
- 解凍は unarchive モジュール (copy=no でリモート内のファイルを解凍するように指定するのがポイント)
- シンボリックリックは file モジュール
の各モジュールを使うようにしました。急いでいるときには command, shell を使って良いと思うけど、時間があるときにはなるべく各モジュールを使ったほうが、ベキトウセイの考慮が楽になるので良いと思います。
init script については、以下サイトを参考にしました。
これで、service コマンドを使ってスタート/ストップ/リスタートが行えます。
どのサービスでも同じ手順で操作できることは重要だと思います。
Basic 認証をするための htpasswd 作成は、htpasswd モジュールを使っています。
ちょくちょく Basic 認証をかけたいことがあるので、htpasswd が簡単に作れることがわかったのはかなりの収穫です。
ec2-kibana のロールは、ec2-nginx に依存していますが、meta は書いていません。書いたほうがよいことはわかってますが、なくても動いているので、後回しにしています。
---
- name: Download kibana
get_url: url="https://download.elastic.co/kibana/kibana/kibana-4.1.0-linux-x64.tar.gz" dest="/tmp/kibana-4.1.0-linux-x64.tar.gz" mode=0644
- name: Unarchive kibana
unarchive: src=/tmp/kibana-4.1.0-linux-x64.tar.gz dest=/opt/ copy=no owner=root group=root
- name: Install kibana
file: src=/opt/kibana-4.1.0-linux-x64 dest=/opt/kibana state=link
- name: Put init script for kibana
template: src=kibana.j2 dest=/etc/init.d/kibana mode=0755
notify: restart kibana
- name: Set kibana service to start on boot
service: name=kibana enabled=true
- name: Install passlib for creating htpasswd
pip: name=passlib state=latest
when: kibana_basic_enabled
- name: Create htpasswd
htpasswd: path=/etc/nginx/conf.d/kibana.htpasswd name={{ kibana_basic_user_name }} password={{ kibana_basic_user_password }} create=yes state=present
when: kibana_basic_enabled
- name: Put nginx.kibana.conf
template: src=nginx.kibana.conf.j2 dest=/etc/nginx/conf.d/kibana.conf mode=0644
notify: restart nginx
Kibana 用の Nginx の設定です。
HTTP を HTTPS へリダイレクトして、Basic 認証を行えるようにしました。
これで最低限のセキュリティを保ちますが、できれば、さらにセキュリティグループで IP制限をかけたほうが良いと思います。
# {{ ansible_managed }}
# redirect https from http
server {
listen 80;
location ~ ^/kibana/.* {
return 301 https://$host$request_uri;
}
}
# proxy kibana
server {
listen 443;
access_log /var/log/nginx/kibana.access.log;
error_log /var/log/nginx/kibana.error.log;
ssl on;
ssl_certificate /etc/nginx/certs/local-ssl.crt;
ssl_certificate_key /etc/nginx/certs/local-ssl.key;
location ~ ^/kibana/.* {
proxy_pass http://localhost:5601;
rewrite ^/kibana/(.*) /$1 break;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
{% if kibana_basic_enabled %}
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/conf.d/kibana.htpasswd;
{% endif %}
}
}
各ロールの作成は以上です。
Playbook サンプルと実行
必要な role を読み込みます。
meta で依存関係を定義していないので、roles: の記述順を変えると動かないと思います。
- hosts: all
sudo: yes
vars:
fluentd_sources:
- aws_key_id: XXXXXXXXXXXX
aws_sec_key: XXXXXXXXXXXXXXXXXXXXXXXX
region: ap-northeast-1
account_id: 999999999999
s3_bucket: bucketname
s3_prefix: prefix
start_datetime: 2015/06/01 00:00
kibana_basic_enabled: true
kibana_basic_user_name: kibana
kibana_basic_user_password: kibanapassword
roles:
- ec2-elasticsearch
- ec2-fluentd
- ec2-nginx
- ec2-kibana
以下で inventory ファイルなしで実行できます。
ぼくは inventory ファイルなしで実行してばかりですが、本格的な運用をしてないからでしょうね。
$ ansible-playbook -i "xxx.xxx.xxx.xxx," --user=ec2-user --private-key=xxx.pem ec2-kibana.example.yml
playbook の適用が完了したら、以下の URL でアクセスできます。
https://xxx.xxx.xxx.xxx/kibana/
ここまでで環境はできますが、これからがログ解析の本番です。如何に Kibana4 を使いこなすか、です。
使いこなすことのほうが時間がかかりそうです。
感想
いろんなインストール方法を記述することになりました。あとはコンパイルが必要なタイプぐらいだと思います。
このことは、今後も Ansible を使うときに役に立ちそうです。
この Ansible の書き方だと今は動きますが、来年でも問題なく動くかはわかりません。
急ぎで構築したいときに動かないっといのは辛いです。
ServerSpec 等のテストに着手して、この点をどこまでカバーできるかを調べたいです。