ラベル Ansible の投稿を表示しています。 すべての投稿を表示
ラベル Ansible の投稿を表示しています。 すべての投稿を表示

12.16.2015

Manipulating Many Servers by Using parallel-ssh

parallel-ssh を使って複数サーバを同時に操作する

 

tl; dr

  • 2台〜100台程度のサーバに対して、同じオペレーションを同時に実行したい
  • parallel-ssh (pssh) の各種コマンドを使うと便利
  • ただし、リモートサーバで sudo が必要な場合は Ansible 等の他ツールが必要

 

parallel-ssh のセットアップ

 

インストール

parallel-ssh - PSSH: Parallel SSH Tools - Google Project Hosting
  • Mac
    $ brew install pssh
  • RHEL系
    # yum install pssh
ホストリストの準備
  • 任意のパスにテキストファイルを作成
    server-1
    server-2
    server-3 root
  • 1行ずつ、接続先サーバのホスト名またはIPアドレスを記述
  • ログインユーザの指定も可能

 

目的別コマンド実行例

 

SSH 認証のための設定

parallel-ssh を使うには、各サーバに SSH で接続できることが前提となる。
ssh-copy-id コマンドを利用して、~/.ssh/id_rsa の内容を登録する場合は以下。

$ for h in $(cat ~/hosts); do ssh-copy-id $h; done

 

pssh の使い方
  • 基本形
    $ pssh -h ~/hosts -i 'hostname'
    [1] 04:09:13 [SUCCESS] server-1
    server-1
    [2] 04:09:13 [SUCCESS] server-2
    server-2
  • ホスト名を直接指定
    $ pssh -H server-1 -H server-2 -i 'hostname'
    [1] 04:09:13 [SUCCESS] server-1
    server-1
    [2] 04:09:13 [SUCCESS] server-2
    server-2
  • タイムアウトを無制限に
    $ pssh -h ~/hosts -t 0 -i 'hostname'
    [1] 04:09:13 [SUCCESS] server-1
    server-1
    [2] 04:09:13 [SUCCESS] server-2
    server-2
  • アウトプットをすぐに表示
    $ pssh -h ~/hosts -P 'hostname'
    server-1: server-1
    [1] 04:13:28 [SUCCESS] server-1
    server-2: server-2
    [2] 04:13:28 [SUCCESS] server-2
    
  • リモートでバックグラウンド実行
    $ pssh -h ~/hosts -i 'nohup your_command > /path/to/output 2>&1 </dev/null &'
    [1] 04:13:28 [SUCCESS] server-1
    [2] 04:13:28 [SUCCESS] server-2
    
    バッファの影響で、標準出力の出力先ファイルがリアルタイムに更新されない場合がある。
    対応にはハックが必要: linux - redirect nohup stdout and flush - Stack Overflow

 

ファイル転送
  • ローカルからリモートに転送
    $ prsync -h ~/hosts -av /data/input/ /data/input/
    • パスの末尾にスラッシュを付けると、ディレクトリ間の同期となる。(rsync の仕様)
    • -z (圧縮オプション) は付けると CPU がボトルネックになって大幅に性能が劣化する場合がある。ナローバンドでなければ、付けないほうが良さそうだ。
  • リモートからローカルに転送
    $ pssh -h ~/hosts -p 4 -i 'rsync -e "ssh -o StrictHostKeyChecking=no" -av \
    /data/output/ server-1:/data/output/'
    • 全サーバから server-1 に集約する例
    • -p オプションを指定して、並列度を制限している。
      こうしないと、コネクションが多すぎて接続できない場合がある。
    • rsync -e "ssh -o ..." という書式で SSH オプションを指定。
      ここではホストキーのチェックを回避している。

 

リモートサーバで sudo が必要な場合
  • Ansible で代用
    $ ansible -i ~/hosts all --sudo -K \
    -a 'bash -c "cd /path/to/your/app && make install"'
    

 

References

6.28.2015

Ansible: Installing Graphite + Grafana 2

Ansible: Graphite + Grafana 2系をインストールする Playbook

 

以前作った Playbook が最新の Amazon Linux に対応できなくなっていたので更新。

主な対応内容

  • Amazon Linux のデフォルトの Python バージョンが、いつの間にか 2.7 に上がっていた。
    yum でインストールされる Python ライブラリは 2.6 向けにパッケージングされているので使えない。
  • インストールパスを標準準拠に。カスタマイズ箇所を最小限に留めるよう意識した。
  • MySQL の使用もやめた
  • Grafana 2系の導入
    • WebサービスやDBが内包されている。つまり Nginx, ElasticSearch も不要になった

セットアップ手順

README 参照。

色々ハマリどころも多かったが、いったん Playbook に反映。プロビジョニングしてすぐにグラフが作れるようになった。

 

s

S

 

ただし、Graphite はやはり依存関係が複雑で保守性が悪いので、今後は Grafana + InfluxDB の組み合わせを選択するのが主流になりそう。

 

References

11.06.2014

Cheat Sheets for My Sake

自分向け各種チートシートまとめ

 

自分が忘れがち or 使用頻度の高い事柄だけ書いておく。

11.05.2014

Ansible: Visualizing CloudWatch Metrics with Grafana

Ansible: Grafana で CloudWatch のメトリクスを可視化するための Playbook

 

tl;dr

Grafana に触れてみたいなら、まずは Grafana Play Home

 

目的
  • AWS CloudWatch の各種メトリクスを Grafana で見たい
  • Grafana の URL は SSL + ベーシック認証で保護したい
  • これらのセットアップ作業を Ansible で自動化したい

 

使ったもの
  • Amazon CloudWatch: AWS 標準の監視コンソール。メトリクスデータが蓄積している前提
  • Amazon EC2
    • Amazon Linux: インスタンスを1台立ち上げ、この中に全てをインストールする
  • Nginx: フロントエンドの Web サーバ。BASIC認証 + 自己署名証明書によるSSL通信を設定。
  • Grafana: メトリクスデータの可視化ツール
  • Graphite: メトリクスデータ管理システム
    • uWSGI: フロントエンド連携用に必要
    • MySQL: Graphite のデータストアとして使う
  • cloudwatch-dump: CloudWatch のメトリクスデータを取得し、Graphite に流し込むために使用
  • Ansible: セットアップ(プロビジョニング)の自動化

 

コード

こちらのリポジトリに Vagrant + Ansible コード一式と再現手順を書いた。

必要なソフトウェア/プラグインをインストール後、vagrant up を行えば以下のような Grafana の画面に触れられるようになる。

Grafana Grafana

Grafana のロゴが表示されないのは https 通信をしているためで、表示させるにはソースコードに手を入れる必要がありそう。

 

はじめに

システム監視の目的は大きく「異常検知」と「トレンド分析」の2つに分けられる。

また一般に、「トレンド分析」がその対象者に応じて、例えば「システム利用者向け分析」「システム管理者向け分析」「経営判断層層向け分析」の3つのように分類できると、スッキリとしたシステムになりやすい。

 

今回の構成ではメトリクスデータは一旦 CloudWatch に集約される想定である。

異常検知は CloudWatch が持ち合わせている Alarm 機能で対応する。
Simple Notification Service を使うことでメール送信だけではなく、携帯端末にpush通知を行ったり、特定のURLにhttpリクエストを投げたり、オートスケールを実現したりなど工夫次第でできることは多い。

次に、そのメトリクスデータを一式 Graphite に投入する。
これを Grafana のようなフロントエンドで可視化することにより、異なる対象者に向けたダッシュボードを簡単に作ることができる。
生成されたグラフを週次レポートのような形で定期的に発信するのもよい。

 

構成イメージ

解説

 

Vagrantfile
  • プラグイン dotenv を使うことでアカウント固有の定義を別ファイル(.env)に分離
  • (コスト節約のため)米国東部リージョンに t2.micro インスタンスを1個新規構築する
  • Ansible のロールの中で使う変数は、extra_vars として引き渡す
Role: aws-scripts-mon
  • これは本来監視される側のセットアップである
  • CloudWatch の標準機能だけは取得できない Linux 内部の情報(メモリ/スワップ/ディスクスペース使用状況)を CloudWatch に送信する
  • 今回は、ec2-user の ~/aws-scripts-mon ディレクトリ配下にモジュール一式を配置し、Cron で 5分おきにレポーティングが実行されるよう仕掛けた
  • CloudWatch API のアクセスには、EC2 構築時とは別の IAM ユーザ (cloudwatch) を準備した
Role: nginx
  • もちろん Grafana は Apache でも動作する(その方が簡単だ)が、今回は Web サーバとして Nginx を採用する
  • このロールの中で自己署名証明書を作成し、/etc/nginx/cert ディレクトリ配下に配置した
  • 実際のSSLサイトの設定は、Grafana のインストール後に実施する
Role: mysql
  • デフォルトの SQLite でも動作するが、運用を考えるなら MySQL 等のほうが堅い
  • Amazon Linux はデフォルトで利用可能な EPEL リポジトリに対して yum install するだけ  
Role: graphite
  • jsmartin/ansible-graphite を参考にした
  • python-carbon を yum でインストールしたのは、起動スクリプトの有り物を使いたかったので
  • 最初は graphite-web も yum で導入したのだが、/opt/graphite/bin 以下のモジュールがインストールされずエラーが出て面倒なことになったので、最終的にこちらは pip で入れることにした
  • そのため、carbon 関係はFHS準拠っぽいディレクトリ構成なのに graphite の場所は /opt/graphite 配下という状態になっている
  • コマンドによって処理の要否を判定する雛形はこちらにも書いた
  • Whisper のデフォルトのデータ間隔・保持期間を 5分・2年 に書き換えている。(storage-schemas.conf)
    こうすることで長期間の分析をしてもデータが重くならない。(逆に1分単位の分析はできなくなる)
  • 起動がうまくいかない場合は、大抵 /var/log/graphite-web.log を見れば原因がわかるはず 
Role: cloudwatch-dump
  • 自作のダンプツールを pip でインストール
  • ec2-user の ~/cloudwatch-dump ディレクトリ配下にシェルを置き、Cron で 1時間に1回(*:05)、graphite にデータを流し込む
  • 何かあった時でもデータを再投入できるよう、~/cloudwatch-dump/logs に直近のログを残している
    (ローテーションは logrotate を使ったほうが良かったかも)
  • シェルスクリプトの中で、メトリクスパス中に含まれるEC2インスタンスIDをニックネームへの変換している
Role: elasticsearch
  • RPM のダウンロード先を指定して、yum install するだけ
Role: grafana
  • Grafana 自体は独立したツールなので、インストールは素直に終わる
  • カスタマイズは config.js をテンプレートエンジンに乗せて行う。Grafana のバージョンによって微妙に項目が変わっているので注意
  • 最後に Nginx の SSL サイト設定と、BASIC認証用のファイルを作って完了
 
References

Related Posts

10.22.2014

Ansible: Playbook for AWS CloudWatch Monitoring Scripts

Ansible: CloudWatch 用 Linux 監視スクリプトをインストールする Playbook

 

前提

  • EC2 インスタンスの OS は Amazon Linux とする
  • 認証情報はファイルに保存する
    • インスタンス作成前であれば、IAM Role の設定により認証情報の保持が不要となる
    • CloudWatch API 専用の IAM ユーザの作成を推奨
  • 各種パラメータについては vars/main.yml を参照
  • 課金が発生する可能性があるので注意

 

コード

---
- name: install additional perl modules
  yum: name={{ item }} state=present
  with_items:
    - perl-Switch
    - perl-Sys-Syslog
    - perl-LWP-Protocol-https
  tags: aws-scripts-mon

- name: check if script is installed
  command: /usr/bin/test -e {{ path_to_script }}
  ignore_errors: True
  changed_when: False
  register: is_installed
  tags: aws-scripts-mon

- name: download scripts from AWS server
  get_url: url={{ download_url }} dest={{ path_to_download }}
  when: is_installed | failed
  tags: aws-scripts-mon

- name: unzip downloaded file
  unarchive: copy=no src={{ path_to_download }} dest={{ home_dir }}
  when: is_installed | failed
  tags: aws-scripts-mon

- name: create credential file
  template: src={{ item }}.j2 dest={{ script_dir }}/{{ item }} owner={{ user }} group={{ user }} mode="0600"
  with_items:
    - awscreds.conf
  tags: aws-scripts-mon

- name: set directory owner
  file: path={{ script_dir }} state=directory owner={{ user }} group={{ user }} recurse=yes
  tags: aws-scripts-mon

- name: remove downloaded file
  file: path={{ path_to_download }} state=absent
  tags: aws-scripts-mon

- name: set cron
  cron: user={{ user }}
        state=present
        name="CloudWatch monitoring script"
        minute="{{ cron.minute }}"
        hour="{{ cron.hour }}"
        job="{{ cron.job }}"
  tags: aws-scripts-mon
AWSAccessKeyId={{ access_key }}
AWSSecretKey={{ secret_key }}
---
user: ec2-user
version: 1.1.0
filename: CloudWatchMonitoringScripts-v{{ version }}.zip
download_url: http://ec2-downloads.s3.amazonaws.com/cloudwatch-samples/{{ filename }}

path_to_download: "/tmp/{{ filename }}"

home_dir: "/home/{{ user }}"
script_dir: "{{ home_dir }}/aws-scripts-mon"
path_to_script: "{{ script_dir }}/mon-put-instance-data.pl"

access_key: "{{ aws_cloudwatch_agent_access_key_id }}"
secret_key: "{{ aws_cloudwatch_agent_secret_access_key }}"

cron:
  hour: "*"
  minute: "*/5"
  job: "{{ path_to_script }} --mem-util --mem-used --mem-avail --swap-util --swap-used --disk-path=/ --disk-space-util --disk-space-used --disk-space-avail --aws-credential-file={{ script_dir }}/awscreds.conf --from-cron"

credential 情報 (aws_cloudwatch_agent_xxx) は、extra-vars などで渡す想定。

 

 

References

7.18.2014

How to Monitor Amazon EC2 Instances with NewRelic (Provisioned by Vagrant + Ansible)

New Relic で EC2 インスタンスを監視する方法

 

目的

Amazon EC2 の新規インスタンスを立ち上げ、New Relic でリソース監視をする。
これを vagrant up コマンド一発で実現したい。

プロビジョニングには Ansible を使う。

 

事前準備

 

1. New Relic アカウントの準備

 

2. AWS Management Console の作業
  • AWS アカウントの作成 (手順割愛)
  • ユーザ・グループ作成
    • Services -> Deployment & Management -> IAM
    • IAM -> Groups: vagrant グループ (Power User Access) を追加
    • IAM -> Users: vagrant ユーザを追加し、vagrant グループに所属。APIキーを確認
  • セキュリティグループ作成
    • Services -> Compute & Networking -> EC2 -> NETWORK & SECURITY -> Security Groups
    • vagrant グループを追加し、Inbound 許可, {SSH, HTTP, HTTPS}, Anywhere を設定
  • SSH鍵の作成
    • Services -> Compute & Networking -> EC2 -> NETWORK & SECURITY -> Key Pairs
    • キーペア vagrant を作成し、vagrant.pem を適当な場所に保存 (例: ~/.ssh/aws-vagrant.pem)

 

3. プロビジョニング実行環境の整備
  • Vagrant のインストール
  • Vagrant プラグインのインストール
    $ vagrant plugin install vagrant-aws
    $ vagrant plugin install dotenv
     
  • Ansible のインストール

 

プロビジョニング用ファイルの作成

 

Vagrantfile

 

.env ファイル

Vagrantfile と同じディレクトリに「.env」というファイルを作成する。

以下のように認証情報を適宜設定すること。

# default provider
VAGRANT_DEFAULT_PROVIDER="aws"

# credentials
AWS_SSH_USERNAME="ec2-user"
AWS_SSH_KEY="path/to/your/vagrant.pem"
AWS_ACCESS_KEY_ID="your access key id"
AWS_SECRET_ACCESS_KEY="your secret"
AWS_KEYPAIR_NAME="vagrant"
AWS_SECURITY_GROUP="vagrant"

# new relic
NEWRELIC_LICENSE_KEY="your license key"

 

Ansible 関連ファイル

 

プロビジョニングの実行

$ vagrant up
Bringing machine 'aws-newrelic-test' up with 'aws' provider...
[aws-newrelic-test] Warning! The AWS provider doesn't support any of the Vagrant
high-level network configurations (`config.vm.network`). They
will be silently ignored.
[aws-newrelic-test] Launching an instance with the following settings...
[aws-newrelic-test]  -- Type: t2.micro
[aws-newrelic-test]  -- AMI: ami-29dc9228
[aws-newrelic-test]  -- Region: ap-northeast-1
[aws-newrelic-test]  -- Availability Zone: ap-northeast-1a
[aws-newrelic-test]  -- Keypair: vagrant
[aws-newrelic-test]  -- Security Groups: ["vagrant"]
[aws-newrelic-test]  -- Block Device Mapping: []
[aws-newrelic-test]  -- Terminate On Shutdown: false
[aws-newrelic-test]  -- Monitoring: false
[aws-newrelic-test]  -- EBS optimized: false
[aws-newrelic-test]  -- Assigning a public IP address in a VPC: false
[aws-newrelic-test] Waiting for instance to become "ready"...
[aws-newrelic-test] Waiting for SSH to become available...
[aws-newrelic-test] Machine is booted and ready for use!
[aws-newrelic-test] Running provisioner: ansible...

PLAY [all] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [aws-newrelic-test]

TASK: [newrelic | check if repository is installed] ***************************

*snip*

PLAY RECAP ********************************************************************
aws-newrelic-test          : ok=9    changed=6    unreachable=0    failed=0

AWSインスタンス作成、起動、Ansible によるプロビジョニングが一気通貫で実行される。

暫くすると、New Relic の画面で EC2 サーバの情報が見られるようになった。
AWS課金には注意。

 

 

References

4.30.2014

Ansible Playbook for MySQL Replication

Ansible: MySQL レプリケーションを実現するためのプレイブック 

 

目的

OSインストール済みの CentOS 6.5 サーバ 2台に対してそれぞれに MySQL をインストールし、
master - slave 構成のレプリケーション環境を構築したい。

普通にやっても面白くないので、Python製のオーケストレーションツール(構成管理ツール) Ansible を使って
インフラの状態をコードとして管理する。

とはいえ実際にやったことと言えば、こちらの素晴らしい playbook のミックスイン写経にすぎない。 

 

コード

説明するよりコードを見たほうが早いと思う。こちらにアップしている。

ファイル、ディレクトリ構成はこのような感じ。

.
├── README.md                    簡単な説明
├── Vagrantfile                  CentOS 6.5 x2台をVirtualBoxで
├── host_vars
│   ├── mysql-master             レプリケーションに関わるホスト単位の定義
│   └── mysql-slave
├── hosts                        インベントリ用
├── roles
│   └── mysql
│       ├── handlers
│       │   └── main.yml         conf書き換え時にサービス再起動
│       ├── tasks
│       │   └── main.yml         メインディッシュ
│       ├── templates
│       │   ├── .my.cnf.j2       rootユーザ用の認証情報を書いておく
│       │   └── my.cnf.j2        設定ファイルのテンプレート
│       └── vars
│           └── main.yml         バージョン設定やユーザのアカウントなど
└── site.yml

 

ポイント

 

Vagrantfile

opscode の CentOS 6.5 イメージをダウンロードして使用。
SELinux が有効だったので、libselinux-python を事前にインストールする必要があった。
IPアドレスは適当に振った。

 

site.yml

とりあえず vagrant ユーザで、sudo してタスクを実行する設定。

 

roles/mysql/tasks/main.yml

一連の処理を 5個のフェーズに分けている。

  • 1. Install packages
    • jaist.ac.jp から新しめのパッケージを一式ダウンロード
    • ローカルファイルを yum モジュールでインストールする際、
      /usr/local/src/{{ item }} のような指定ができなかったので、やむを得ずパスを echo するだけのタスクを一個作っている (need improvement)
    • MySQL関連の操作をするため、MySQL-python のインストールが必要
    • 今回、スローログを /var/log/mysql-slow.log として書くため、パーミッションの関係で事前にファイルを touch している
  • 2. Change credentials for root
    • /root/.mysql_secret ファイルが存在する場合にはパスワードが初期設定のままと判断し、roles/mysql/vars/main.yml の方で指定した root パスワードに設定し直す
    • 新しいパスワードは、/root/.my.cnf に記録しておく
  • 3. Setup users
    • ゲストアクセスを停止し、アプリユーザ、レプリケーション用ユーザを作成
  • 4. Create database
    • test データベースを削除し、vars で指定したDB (今回は awesome) を作成
  • 5. Replication settings
    • mysql_replication モジュールを活用
    • ハマったのが、changemaster する時に以下のようなエラーが出て、コマンドが success にならないこと。

      _mysql_exceptions.Warning: Sending passwords in plain text without SSL/TLS is extremely insecure. 

      MySQL 5.6 の仕様変更の影響で、start slave の時にパスワードを指定するのが新しいお作法のようだが、どうにもうまくいかず。
      結局、不本意ながら (ignore_errors: True) を設定した。(need improvement)

 

roles/mysql/templates/my.cnf.j2

jinja2 のテンプレートファイル。if や for を活用している。
slave 側には read_only の設定を入れた。

 

遊び方

Vagrantfile を作ったので手元でも試せる。README 参照。