あきろぐ

いろいろめもするよ🐈🐈🐈

Ansibleでインベントリに書いたIPアドレスを変数として使いたい

概要

最近Ansibleを頻繁に使っていて、こういう使い方ないかなと思って調べたのでそのやり方を整理。
やりたいことは、「インベントリファイルにグループ別にIPアドレスを記載しているので、そのIPアドレスを変数として使いgroup_varsディレクトリ配下のグループ別変数ファイルにIPアドレスをべた書きしないようにする」です。

環境

  • CentOS7.6
  • Ansible2.8.5

解決方法

作成したインベントリファイルは、以下の通りです。

[compute]
192.168.13.xx
192.168.13.xx
192.168.13.xx
192.168.13.xx
192.168.13.xx

[zabbix]
192.168.13.xx
192.168.13.xx

computeグループに属するIPアドレス一覧を取得したい

以下のようにgroup_vars配下の変数ファイルを作成します。

compute_ip_list: "{{ groups['compute']|join('/n') }}"

上記のようにjoinを使って書いてTemplateファイルで使用すると、computeグループのIPアドレスが改行された状態でリモートホスト内で展開されます。

例えば、以下のようなtemplateファイル、playbookを作成します。

compute_ip.txt.j2
{{ compute_ip_list }}

playbook_copy_file.yml
---
- hosts: compute
  user: "{{ login_user }}"
  tasks:
     - name: copy ip list
       template:
          src: compute_ip.txt.j2
          dest: "{{ remote_dir }}/compute_ip.txt"

上記のように設定して、Ansibleを実行すると以下のようにリモートホスト内で展開されます。

compute_ip.txt
192.168.13.xx
192.168.13.xx
192.168.13.xx
192.168.13.xx
192.168.13.xx

こちらのサイトを参考にしました。
codeday.me

Zabbixグループの1番目に記載したIPアドレスを取得したい

グループに属するIPアドレスを全て取得する方法は分かったけど、グループに属する1つのIPアドレスを取得したいときはリストを使って変数ファイルに記載します。

# zabbixグループに属する1番目のIPアドレスを取得する
zabbix_ip_1: "{{ groups['zabbix'][0] }}"

このように書けば、グループに属する1つのIPアドレスを指定することができます。
しかし、リスト番号にマッチするものがないとplaybook実行時にエラーを吐くので注意してください。
こちらの解決策は、Ansibleユーザー会のSlackで教えていただきました!(ありがとうございます!)
ansible-users.connpass.com

一応、グループに1つのホストしか属していない場合でも以下の書き方は使うことができます。

compute_ip_list: "{{ groups['compute']|join('/n') }}"

まとめ

  • インベントリファイルのIPアドレスを使って変数を作成できる
  • 例えばjoinメソッドやリストを使うことができる
  • Ansibleおもしろい

おしまい!

Zabbixで1秒間隔の監視にしたらヒストリログの肥大化により1週間でディスクフルになった

概要

先日、Zabbixの監視間隔を1秒にしたらMySQLのバイナリファイルによってディスクフルになった話を書いた。
akng-engineer.hatenablog.com
しかし、バイナリファイルの肥大化より気にしなければならなかったのは、Zabbixで収集したデータのヒストリ保存期間だった。1秒間隔の監視だから、ヒストリの保存期間は7日程にして様子見ようと思ったが、予想上にデータが蓄積するのが早く1週間でディスクを逼迫してしまった。。。検証環境だとは言え、データベース設計の重要性を思い知ったので、今回実施した対処法を記録しておきたい。

環境

  • Zabbix3.0
  • MySQL5.6
  • 割り当てディスク: 128GB

チャットのアラート「ディスクの空き残り3%」

あれ、2日前にバイナリログの保持期間変更したのに....?(やばい)
急いでdfコマンドでディスクチェックしたが、やっぱり肥大化しているのはMySQL関連のディレクトリだった。しかし、今回はバイナリログそんなに出力されていないので、Zabbixデータベースのテーブルサイズを確認した。

#ディスク使用率を確認
df -h
# Zabbixデータベースのテーブルサイズを確認(上位5つを表示)
use zabbix;
select table_name, engine, table_rows as tbl_rows, avg_row_length as rlen,  
floor((data_length+index_length)/1024/1024) as allMB,  
floor((data_length)/1024/1024) as dMB,  
floor((index_length)/1024/1024) as iMB   
from information_schema.tables  
where table_schema=database()  
order by (data_length+index_length) desc limit 5; 

Zabbixデータベースのテーブルを確認すると、historyテーブルのレコードが8億以上でサイズが60GB以上だった。ヒストリ関連のテーブルはほかにもhistory_uint, history_strがあるが、合計するとサイズは100GBを超えていた。なるほど.......(泣)

ZabbixのWebUI画面でディスク使用率の時系列グラフを見たが、1日に約15%の増加量だった。すさまじい。。。

対処策①:テーブル圧縮する

下記コマンドでヒストリ関連テーブルを圧縮しようかと思ったが、空き容量が3%のため巨大なテーブルを圧縮することはできなかったので断念。

#テーブルを圧縮する
alter table history row_format=compressed;

対処策②:ヒストリ関連のテーブルを作り直す

どうするかと思い色々調べていたところ、別テーブルを作って一部レコードを挿入するやり方が紹介されていたので試してみた。
phucnw.blogspot.com

#テーブルを複製して新しいテーブルを作る
create table history_new like history;
create table history_uint_new like history_uint;
create table history_str_new like history_str;

#元テーブルから一部レコードを新しいテーブルに流し込む
insert into history_new select * from history where clock > [unix_time];
insert into history_uint_new select * from history_uint where clock > [unix_time];
insert into history_str_new select * from history_str where clock > [unix_time];

#テーブル名を変更する
alter table history rename history_old;
alter table history_new rename history;
alter table history_uint rename history_uint_old;
alter table history_uint _new rename history_uint;
alter table history_str rename history_str_old;
alter table history_str_new rename history_str;

#一度Zabbixサーバーを立ち上げて問題ないか確認する
systemctl start zabbix-server

#旧テーブルを削除する
drop table history_old;
drop table history_uint_old;
drop table history_str_old;

#ディスク容量確認する
df -h

このやり方で、ディスク使用量が16%まで減少!!!なるほどー!
うまくいってよかった。めでたし。

【Zabbix】MySQLのバイナリファイルが肥大化してDBが立ち上がらなかった

概要

検証環境のZabbixサーバーがディスクフルでサービス停止していたため調べたところ、/data/mysql配下にmysql-bin-*ファイルが大量に作成されており、ディスク使用量が100%になっていた。なるほど。

原因

expire_logs_days設定していなかった?

いや、していた。"expire_logs_days=7"で設定しており、今までバイナリファイルによるディスクフルは発生していなかった。

じゃあ何が原因だったの?

最近、検証のためにZabbixエージェントの監視間隔を30秒⇒1秒にしていたため、バイナリファイルに書き込まれるイベント数が大幅に増加し、バイナリファイルの出力が増えたことが原因だと考えれる。4日間でディスクを50GB以上使っていたのでそれはディスク圧迫するよね。。。

そもそもmysql-binファイル何者?

公式ドキュメントを読んでみる。

バイナリログには、テーブル作成操作やテーブルデータへの変更などのデータベース変更を記述する「イベント」が格納されます。

なるほど。データのレプリケーションリカバリに使われるのがこのバイナリファイルらしい。現状、レプリケーションする予定もないし7日間もバイナリファイル保持しなくてもいいので、今回はこの期間を短くして対応したい。
dev.mysql.com

対処

そもそもMariaDBサービスが立ち上がらない

ディスクフルでサービス起動失敗するので、/data/mysql/mysql-bin*ファイルを空きディスクに移行させる。1つずつファイル移動させないとだめだったので、複数ファイル移動させてからサービス立ち上げる。

# 適当にディレクトリ作成して移動させる
mkdir /home/tmp/
mv /data/mysql/mysql-bin.xxxx /home/tmp
# ディスクに空きができたらサービス立ち上げる
systemctl restart mariadb

purgeコマンドでバイナリファイル削除する

MySQLのコマンドpurgeを使ってログファイルを消していく。rmコマンドでこのバイナリファイルを削除するとエラーになってしまうらしいので注意。。

# バイナリファイル削除
mysql -u root -p
purge master logs before 'YYYY-MM-DD hh:mm';
exit;
# ディスクの空き容量確認
df -h

この後退避させたバイナリファイルも削除を忘れずに。(これはrmコマンドで消した)

my.cnfを書き換える

バイナリファイルのサイズと出力頻度を見ると、1日に1.1GBのファイルが12回出力されていたのでディスクのサイズ的に2日以上保持しないように変更した。

# バイナリファイル保持期間変更
vi /etc/my.cnf
expire_logs_days=2
# mariaDB再起動
systemctl restart mariadb

正常にmariaDBが立ち上がれば問題なし。

追加設定

追記。
やっぱり不安だから1日の保持期間より短くしたいと思って、cronで定期的にqurgeしてくれるように設定を追加した。

vi purge_binary_log.spl
frush logs;
purge master logs before now() - interval 5 hour;
crontab -e 
0 * * * * mysql -u[username] -p[password] < purge_binary_log.sql

まとめ

Zabbixのデータ取得間隔変えるとバイナリファイルの出力も増えることが今回の学び。
おしまい。

prometheus+garfanaで遊んでみるよ

この前Prometheusを初めて使ってみたので、復習を兼ねてPrometheusで取得したメトリクスをGrafanaで可視化してみたいと思います。

Prometheus?

  • オープンソースの監視ツールです。
  • プル型なのでPrometehusサーバーが監視先サーバーに聞きまわり、監視メトリクスをかき集めているイメージです。
  • 可視化ツールのGrafanaと親和性が高いです。
  • Prometehusのデフォルトのダッシュボードがありますが、可視化には強くないので取得したメトリクスを分かりやすく可視化したい場合はGrafanaを使います。
  • セットアップが非常に簡単で、バイナリをインストールして起動させるだけで監視開始させることができます。

環境

  • CentOS7.6
  • Prometheus server v2.32
  • Prometheus node v0.16

Exporterのインストール

導入は本当に簡単です。さっと終わります。

#インストール先のディレクトリを作成する
$ mkdir /etc/prometheus
$ cd /etc/prometehus
#バイナリファイルをインストールする
$ wget https://github.com/prometheus/node_exporter/releases/download/v0.16.0/node_exporter-0.16.0.linux-amd64.tar.gz
#インストールしたバイナリを解凍する
tar xvzf node_exporter-0.16.0.linux-amd64.tar.gz
#ディレクトリ名を変更する
$ mv node_exporter-0.16.0.linux-amd64.tar.gz node_exporter
#exporterが動くかテストする
$ cd node_exporter
$ ./node_exporter

以下のようにデータ取得できていればOKです。

$ ./node_exporter
INFO[0000] Starting node_exporter (version=0.16.0, branch=HEAD, revision=d42bd70f4363dced6b77d8fc311ea57b63387e4f)  source="node_exporter.go:82"
INFO[0000] Build context (go=go1.9.6, user=root@a67a9bc13a69, date=20180515-15:52:42)  source="node_exporter.go:83"
INFO[0000] Enabled collectors:                           source="node_exporter.go:90"
INFO[0000]  - arp                                        source="node_exporter.go:97"
INFO[0000]  - bcache                                     source="node_exporter.go:97"
INFO[0000]  - bonding                                    source="node_exporter.go:97"
INFO[0000]  - conntrack                                  source="node_exporter.go:97"
INFO[0000]  - cpu                                        source="node_exporter.go:97"
INFO[0000]  - diskstats                                  source="node_exporter.go:97"
INFO[0000]  - edac                                       source="node_exporter.go:97"
INFO[0000]  - entropy                                    source="node_exporter.go:97"
INFO[0000]  - filefd                                     source="node_exporter.go:97"
INFO[0000]  - filesystem                                 source="node_exporter.g

動作確認できたら、exporterをサービス化します。

#サービスファイルの作成
$ vi /etc/systemd/system/node_exporter.service
[Unit]
Description=Node Exporter
Documentation=https://github.com/prometheus/node_exporter

[Service]
Type=simple
ExecStart=/etc/prometheus/node_exporter/node_exporter
Restart=always

[Install]
WantedBy=multi-user.target

サービスを有効にするためにデーモンをリロードし、サービスを起動する

$systemctl daemon-reload
$systemctl enable node_exporter
$systemctl start node_exporter
$systemctl status node_exporter
● prometheus_node.service - Node Exporter
   Loaded: loaded (/etc/systemd/system/prometheus_node.service; enabled; vendor preset: disabled)
   Active: active (running) since Sun 2019-07-07 06:43:19 UTC; 34min ago
     Docs: https://github.com/prometheus/node_exporter
 Main PID: 8700 (node_exporter)
   CGroup: /system.slice/prometheus_node.service
           mq8700 /etc/prometheus/node_exporter/node_exporter

Jul 07 06:43:19 localhost.localdomain node_exporter[8700]: time="2019-07-07T0...
Jul 07 06:43:19 localhost.localdomain node_exporter[8700]: time="2019-07-07T0...
Jul 07 06:43:19 localhost.localdomain node_exporter[8700]: time="2019-07-07T0...

ステータスがアクティブになっていればOKです。

Prometheus_serverのインストール

続いて、Prometheus_serverの準備をしていきます。

#prometheus serverのインストール
$ wget https://github.com/prometheus/prometheus/releases/download/v2.3.2/prometheus-2.3.2.linux-amd64.tar.gz
#バイナリファイルを解凍する
$ tar xvzf prometheus-2.3.2.linux-amd64.tar.gz
#ディレクトリ名を変更する
$ mv prometheus-2.3.2.linux-amd64 prometheus_server
$ cd prometheus_server
#設定ファイルの修正
$ vi prometheus.yml
# my global config
global:
  scrape_interval:     15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
  evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.
  # scrape_timeout is set to the global default (10s).

# Alertmanager configuration
alerting:
  alertmanagers:
  - static_configs:
    - targets:
      # - alertmanager:9093

# Load rules once and periodically evaluate them according to the global 'evaluation_interval'.
rule_files:
  # - "first_rules.yml"
  # - "second_rules.yml"

# A scrape configuration containing exactly one endpoint to scrape:
# Here it's Prometheus itself.
scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: 'node_exporter' #変更箇所

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
    - targets: ['localhost:9100']  #変更箇所

今回は同じホストでexporterを起動させているので、ターゲット先は"localhost:9100"となります。exporterによって指定するポートが違うので注意が必要です。

prometheusを起動させ、正常に監視開始するか確認します。"Server is ready to receive web requests."とうメッセージが表示されていればOKです。

$ ./prometheus
level=info ts=2019-07-07T08:12:19.556134535Z caller=main.go:222 msg="Starting Prometheus" version="(version=2.3.2, branch=HEAD, revision=71af5e29e815795e9dd14742ee7725682fa14b7b)"
level=info ts=2019-07-07T08:12:19.556251007Z caller=main.go:223 build_context="(go=go1.10.3, user=root@5258e0bd9cc1, date=20180712-14:02:52)"
level=info ts=2019-07-07T08:12:19.556276083Z caller=main.go:224 host_details="(Linux 3.10.0-957.10.1.el7.x86_64 #1 SMP Mon Mar 18 15:06:45 UTC 2019 x86_64 localhost.localdomain (none))"
level=info ts=2019-07-07T08:12:19.556296925Z caller=main.go:225 fd_limits="(soft=1024, hard=4096)"
level=info ts=2019-07-07T08:12:19.556926921Z caller=main.go:533 msg="Starting TSDB ..."
level=info ts=2019-07-07T08:12:19.559585106Z caller=web.go:415 component=web msg="Start listening for connections" address=0.0.0.0:9090
level=info ts=2019-07-07T08:12:19.570862184Z caller=main.go:543 msg="TSDB started"
level=info ts=2019-07-07T08:12:19.570898772Z caller=main.go:603 msg="Loading configuration file" filename=prometheus.yml
level=info ts=2019-07-07T08:12:19.573468239Z caller=main.go:629 msg="Completed loading of configuration file" filename=prometheus.yml
level=info ts=2019-07-07T08:12:19.573559206Z caller=main.go:502 msg="Server is ready to receive web requests."

起動確認ができたら、サービス化ファイルを作成します。

$ vi /etc/systemd/system/prometheus_server.serivice
[Unit]
Description=Prometheus
Documentation=https://prometheus.io/docs/introduction/overview/
After=network-online.target
After=network-online.target

[Service]
Type=simple
ExecStart=/etc/prometheus/prometheus_server/prometheus \
  --config.file=/etc/prometheus/prometheus_server/prometheus.yml \

[Install]
WantedBy=multi-user.target

#デーモンをリロードする
$systemctl daemon-reload
#サービスを有効にする
$systemctl enable prometheus_server
#サービスを起動する
$systemctl start prometheus_server
$systemctl status prometheus_server
● prometheus_server.service - Prometheus
   Loaded: loaded (/etc/systemd/system/prometheus_server.service; enabled; vendor preset: disabled)
   Active: active (running) since Sun 2019-07-07 08:24:42 UTC; 6s ago
     Docs: https://prometheus.io/docs/introduction/overview/
 Main PID: 16275 (prometheus)
   CGroup: /system.slice/prometheus_server.service
           mq16275 /etc/prometheus/prometheus_server/prometheus --config.file...

Jul 07 08:24:42 localhost.localdomain prometheus[16275]: level=info ts=2019-0...
Jul 07 08:24:42 localhost.localdomain prometheus[16275]: level=info ts=2019-0...
Jul 07 08:24:42 localhost.localdomain prometheus[16275]: level=info ts=2019-0...
Jul 07 08:24:42 localhost.localdomain prometheus[16275]: level=info ts=2019-0...
Jul 07 08:24:42 localhost.localdomain prometheus[16275]: level=info ts=2019-0...
Jul 07 08:24:42 localhost.localdomain prometheus[16275]: level=info ts=2019-0...
Jul 07 08:24:42 localhost.localdomain prometheus[16275]: level=info ts=2019-0...
Jul 07 08:24:42 localhost.localdomain prometheus[16275]: level=info ts=2019-0...
Jul 07 08:24:42 localhost.localdomain prometheus[16275]: level=info ts=2019-0...
Jul 07 08:24:42 localhost.localdomain prometheus[16275]: level=info ts=2019-0...

サービスがアクティブであることを確認できたらOKです。

prometheusのGUI画面を確認する

"http://[prometheus_server_IPaddress]:9100/graph"にアクセスすると、下記のような画面が表示されます。[Execuse]ボタン横のドロップダウンからグラフ化したいメトリクスを選択し、[Execuse]ボタンをクリックするとメトリクスの時系列グラフが表示されます。今回は、nodeのディスクIOの現在値を表示してみました。
f:id:akngo22:20190708214912j:plain

Grafanaにデータソース登録する

prometheusのGUI画面にてメトリクスを取得できていることを確認できたら、Grafanaにデータソース登録していきます。
Grafanaにログイン後、prometheusをデータソースに登録していきます。URLは9090ポートを指定し「Save&Test」をクリックし問題なければ登録完了となります。
f:id:akngo22:20190708215708j:plain

既存のテンプレートを使ってダッシュボートをインポートする

Grafanaは個人でダッシュボード開発している方がいるので、公式ドキュメント見るとテンプレートが豊富にあります。せっかくなので使えるものは使っていきます。今回は以下のPrometheusサーバーの状態を示すダッシュボートを使用しました。
grafana.com

上記のURLにアクセスしてダッシュボードIDをコピーした後、GrafanaGUI画面の右上「▼」から「Import Dashboard」をクリックしダッシュボードIDを入力します。
f:id:akngo22:20190814174228j:plain
後はちょこちょこっと微調整すれば簡単にダッシュボード作成できました!わーい!
f:id:akngo22:20190814174448j:plain

今回はこんな感じで。
おしまい