vague memory

うろ覚えを無くしていこうともがき苦しむ人の備忘録

Mackerel事始め mkrで残アラートのクローズ

Mackerelを使用しているとアラート発生後に復旧せずに残り続けるアラートが出てきます。
AWS インテグレーションで CloudWatch 上に値が出力されない物(ELB の ERROR 等、CloudWatch上 0 ではなく、値が無い物)が良く残ります。
Web上から一つずつクリックしてCloseするのは数が多くなってくると厳しいので mkr を使用して一括Closeを行います。

今回の判定条件はアラート発生後 n秒経過した物を対象とします。
(Close実行部分はコメントアウトしています)

export MACKEREL_APIKEY='XXXXXXXXXX'
# 経過秒数を指定
_SEC=86400

# epoch秒生成
_EPOCH=$(expr $(date +'%s') - ${_SEC})
echo "Target: $(date --date "@${_EPOCH}" +'%Y-%m-%d %H:%M:%S')"
#BSD
#echo "Target: $(date -r "${_EPOCH}" +'%Y-%m-%d %H:%M:%S')"

# アラートをクローズ
for _ID in $(mkr alerts | jq -r '.[] | select(.openedAt < '${_EPOCH}').id')
do
  echo "${_ID}"
  # mkr alerts close ${_ID}
done
  • Closed by API f:id:htnosm:20160805023259p:plain

Mackerel事始め mkrでホストの退役

Mackerel で mkr と WebAPI を使用して poweroff にしたホストを退役します。
今回の判定条件は n日前のメトリクスが無いホストとします。(poweroff 直後のホストは非対象としています)

f:id:htnosm:20160429183205p:plain

ApiKey/URL/Metricsを設定

検索対象のメトリクスは loadavg5 等必ず存在する物を指定します。

export MACKEREL_APIKEY='XXXXXXXXXX'
_MACKEREL_URL="https://mackerel.io/api/v0"
_METRICS="loadavg5"
# 処理実行当日を含む日数
_KEEP_DAY=1

日数(epoch秒)生成

_KEEP_TO=$(date --date ''${_KEEP_DAY}' days ago' +'%Y-%m-%d 15:00:00')
_KEEP_TO=$(TZ=UTC date --date "${_KEEP_TO}" +'%s')
_KEEP_FROM=$(expr ${_KEEP_TO} - 86400)
_KEEP_TO=$(expr ${_KEEP_TO} - 1)
echo "From: $(date --date "@${_KEEP_FROM}" +'%Y-%m-%d %H:%M:%S')"
echo "  To: $(date --date "@${_KEEP_TO}" +'%Y-%m-%d %H:%M:%S')"

日数(epoch秒)生成 (BSD)

OSXの場合デフォルトのままだとこちらになります。(GNU date導入済みであれば上記)

_KEEP_TO=$(date -v-${_KEEP_DAY}d +'%Y-%m-%d 15:00:00')
_KEEP_TO=$(date -jf "%Y-%m-%d %H:%M:%S" "${_KEEP_TO}" +%s)
_KEEP_FROM=$(expr ${_KEEP_TO} - 86400)
_KEEP_TO=$(expr ${_KEEP_TO} - 1)
echo "From: $(date -r "${_KEEP_FROM}" +'%Y-%m-%d %H:%M:%S')"
echo "  To: $(date -r "${_KEEP_TO}" +'%Y-%m-%d %H:%M:%S')"

Metrics が存在しない host を退役

status が poweroff 且つ 実行日 - n日 のmetrics存在チェックをし、データが存在しないホストを退役します。
(実行すると有無を言わさず退役になるので、実行部分はコメントアウトしています)

for _ID in $(mkr hosts --status poweroff | jq -c -r '.[].id')
do
  _RES=$(curl -s -S -X GET -H "X-Api-Key: ${MACKEREL_APIKEY}" "${_MACKEREL_URL}/hosts/${_ID}/metrics?name=${_METRICS}&from=${_KEEP_FROM}&to=${_KEEP_TO}" | jq -r '.metrics | length')
  echo "HostId: ${_ID} / DataPoint: ${_RES}"
  #[ ${_RES} -eq 0 ] && mkr retire --force ${_ID}
done

cron等で定期的に実行すると退役漏れが無くせるかと思います。

Jenkins タイトル/ヘッダー文字の変更

Jenkinsを使っていて、複数環境を使い分ける必要が出てきた場合に、 見た目が全部一緒で判り難いので環境別に表示を変えたいと思いました。

f:id:htnosm:20160710205120p:plain

Jenkinsの標準機能では存在せず、Simple Theme Plugin を使用するのが定石のようなので、こちらを使用します。

変更点

ヘッダーの色と Jenkins の文字部分を変更します。ついでにジェンキンスおじさまにはご退場いただきます。

f:id:htnosm:20160710205121p:plain

おじさまとJenkinsロゴはトップページへのリンクが付与されていますが、無くなっても支障が無いので文字列に置き換えます。

環境

Jenkins Ver: 2.7.1

css と js の格納

${JENKINS_HOME}/userContentcss と js を格納します。

  • theme.css
    • backgroud に任意の色を設定
    • theme.js で使用する header-text のstyleを指定
#header{
    background: #99999;
    position: relative;
}
.header-text{
    font-size: 26px;
    line-height: 1.4em;
    color: white;
}
  • theme.js
    • titleStr に任意の文字列を設定
var titleStr = "XXXXX"

// Title Replace
window.addEventListener("load", function() {
  var title = document.querySelector('title')
  title.innerHTML = title.innerHTML.replace(/\[Jenkins\]/, titleStr)
}, false);

// HeaderLogo Replace
document.addEventListener("DOMContentLoaded", function(){
  var img = document.getElementsBySelector('[id="jenkins-home-link"]')[0];
  var alink = img.parentNode;
  alink.removeChild(img);
  alink.appendChild(document.createTextNode(titleStr));
  alink.setAttribute("class", "header-text");
}, false);

変更結果

Jenkinsの設定で URL of theme CSS/JS に格納した theme.css/theme.js を指定すると反映されます。
上からデフォルト、緑、青、赤と3パターンの変更例です。

f:id:htnosm:20160710205122p:plain f:id:htnosm:20160710205123p:plain f:id:htnosm:20160710205124p:plain f:id:htnosm:20160710205125p:plain

mackerel-plugin-apache2 BASIC認証

ApacheBASIC認証が掛かっている場合の取得方法です。
ユーザ・パスワードを設定するオプションは無いですが、URLに直接入れ込む形で設定できます。

apache2.conf

[plugin.metrics.apache2]
command = "/usr/local/bin/mackerel-plugin-apache2 -o <USER>:<PASSWORD>@<HOSTNAME>"
type = "metric"

# ロングオプションの場合
command = '''
  /usr/local/bin/mackerel-plugin-apache2 \
     --http_host <USER>:<PASSWORD>@<HOSTNAME>
'''
type = "metric"

access_log 例

# 未設定
localhost - - [24/May/2016:05:59:00 +0900] "GET /server-status?auto HTTP/1.1" 401 401 "-" "Go-http-client/1.1" 505 761
# ユーザ・パスワード設定
localhost - authuser [24/May/2016:05:59:15 +0900] "GET /server-status?auto HTTP/1.1" 200 1181 "-" "Go-http-client/1.1" 1056 893

Mackerel事始め mkr(3)

Mackerel で mkr を使用した CLI 操作の続きです。

f:id:htnosm:20160523041549p:plain

create

ホストを作成します。 オプション指定無しだと working で作成されます。

$ mkr create TEST
   created XXXXXXXXtLu

f:id:htnosm:20160523041550p:plain

  • ステータスをメンテナンスとし、ロールを指定した場合
$ mkr create -st maintenance -R testservice:testrole TEST
   created XXXXXXXXPcN
   updated XXXXXXXXPcN maintenance

f:id:htnosm:20160523041551p:plain

update

ホスト情報を更新します。

$ mkr update --displayName 表示名更新 XXXXXXXXtLu
   updated XXXXXXXXtLu

f:id:htnosm:20160523041552p:plain

  • ステータスをスタンバイ、ロールを更新した場合

ロールは追加されるようです。

$ mkr update --st standby --roleFullname testservice:web -n test2 XXXXXXXXPcN
   updated XXXXXXXXPcN

f:id:htnosm:20160523041553p:plain

fetch

メトリックの最新値を取得します。 name で指定する値は上記ヘルプページに記載があります。

  • loadavg5
$ mkr fetch -n loadavg5 `mkr hosts -n TEST | jq -r '.[].id'`
{
    "XXXXXXXkAJd": {
        "loadavg5": {
            "time": 1463941200,
            "value": 0.45499999999999996
        }
    }
}
  • cpu.system.percentage
$ mkr fetch -n cpu.system.percentage `mkr hosts -n TEST | jq -r '.[].id'`
{
    "XXXXXXXkAJd": {
        "cpu.system.percentage": {
            "time": 1463941200,
            "value": 0.6792990723058558
        }
    }
}

複数ホスト

hostId をスペース区切りで指定することで複数ホストのメトリック値の収集が可能です。

% mkr fetch -n loadavg5 `mkr hosts -n TEST2 | jq -r '.[].id'` `mkr hosts -n TEST | jq -r '.[].id'`
{
    "XXXXXXXkcAq": {
        "loadavg5": {
            "time": 1463941500,
            "value": 0.21799999999999997
        }
    },
    "XXXXXXXkAJd": {
        "loadavg5": {
            "time": 1463941500,
            "value": 0.144
        }
    }
}

throw

mackerel-agentが存在しない環境からでもメトリックデータの送信が行えます。

書式

以下の様な書式で値を登録します。 数値以外の値は投稿できません。

cat <<EOF | mkr throw --host <hostId>
<name>  <value> <time>
<name>  <value> <time>
EOF
...

cat <<EOF | mkr throw --service My-Service
<name>  <value> <time>
<name>  <value> <time>
EOF
...

ホスト(カスタムメトリック)

$ cat <<EOF | mkr throw --host XXXXXXXXtLu
lv15 `uptime | awk '{print $10}'` `date +'%s'`
uptime `uptime | awk '{print $1}'` `date +'%s'`
str "aaa" `date +'%s'`
EOF
   warning Failed to parse values: strconv.ParseFloat: parsing "3:48": invalid syntax
   warning Failed to parse values: strconv.ParseFloat: parsing "\"aaa\"": invalid syntax
    thrown XXXXXXXXtLu 'lv15    1.810000    1463942894'

f:id:htnosm:20160523041554p:plain

サービスメトリック

$ cat <<EOF | mkr throw --service test
ResponseTime `curl -L -S -s 'https://example.com/' -o /dev/null -w "%{time_total}" | sed -e 's/%//'` `date +'%s'`
EOF
    thrown test 'ResponseTime   0.714000    1463943757'

f:id:htnosm:20160523041555p:plain

存在しないサービス名指定ではエラーとなります。

% cat <<EOF | mkr throw --service TEST-SERVICE
pipe heredoc> ResponseTime `curl -L -S -s 'https://example.com/' -o /dev/null -w "%{time_total}" | sed -e 's/%//'` `date +'%s'`
pipe heredoc> EOF
     error API result failed: 404 Not Found

mkr コマンドを一通り試しましたが、一括で操作が行える点が便利だと感じました。 特にAPI + α の仕様となっている monitors と、 一括退役が行える retire は利用頻度が高いのではと思います。

Mackerel事始め mkr(2)

Mackerel で mkr を使用した CLI 操作の続きです。 ホスト一覧取得と退役操作を行います。

f:id:htnosm:20160523024748p:plain

hosts

ホスト一覧を取得します。ホストを対象とする操作を行う際のidを抽出する為に使用します。

オプション

オプション ロングオプション 説明
-n --name ホスト名で検索。 完全一致。
-s --service サービス名で検索
-r --role ロール名で検索。複数指定可。 サービス未指定だと無視。
-st --status ステータスで検索。複数指定可。デフォルト working もしくは standby
-f --format 出力フォーマット指定
-v --verbose 詳細表示

-f | --format

READMEを参照すると以下の様な指定方法のようです。mkrはjqと組み合わせて使う事が多いので、固有の指定方法ではなく、jq側でフォーマット調整をすることになりそうです。

mkr hosts -f '{{range .}}{{if (len .Interfaces)}}{{(index .Interfaces 0).IPAddress}}{{end}}{{"\t"}}{{.Name}}{{"\n"}}{{end}}'

id 抽出

READMEを真似て id を抜き出してみると以下のようになります。

$ mkr hosts -f '{{range .}}{{.ID}}{{"\n"}}{{end}}'
XXXXXXXXes1
XXXXXXXXWNU
XXXXXXXXAJd
・・・略・・・
素直に jq 使用

私はjqの方が慣れているのでこちらを使用すると思います。

mkr hosts | jq -r '.[].id'

-v | --verbose

オプション無し

$ mkr hosts -n ip-172-31-3-172
[
    {
        "id": "XXXXXXXX37m",
        "name": "ip-172-31-3-172",
        "status": "working",
        "roleFullnames": [
            "test:testrole"
        ],
        "isRetired": false,
        "createdAt": "Mar 23, 2016 at 4:39pm (JST)",
        "ipAddresses": {
            "eth0": "172.31.3.172"
        }
    }
]

オプション有り

オプション無しの出力と出力形式が変わり、CPUやメモリ情報が追加されます。
createAt はUNIXTIMEになるのでスクリプト等で使用する場合はこちらの方が扱い易いと思います。

  • 長いので所々省略
$ mkr hosts -n ip-172-31-3-172 -v
[
    {
        "id": "XXXXXXXX37m",
        "name": "ip-172-31-3-172",
        "type": "unknown",
        "status": "working",
        "roles": {
            "test": [
                "testrole"
            ]
        },
        "createdAt": 1458718748,
        "meta": {
            "agent-revision": "7d278aa",
            "agent-version": "0.30.0",
            "block_device": {
                "loop0": {
                    "removable": "0",
                    "size": "0"
                },
・・・略・・・
                "ram0": {
                    "removable": "0",
                    "size": "131072"
                },
・・・略・・・
                "xvda": {
                    "removable": "0",
                    "size": "16777216"
                }
            },
            "cpu": [
                {
                    "cache_size": "25600 KB",
                    "core_id": "0",
                    "cores": "1",
                    "family": "6",
                    "mhz": "2500.066",
                    "model": "62",
                    "model_name": "Intel(R) Xeon(R) CPU E5-2670 v2 @ 2.50GHz",
                    "physical_id": "0",
                    "stepping": "4",
                    "vendor_id": "GenuineIntel"
                }
            ],
            "filesystem": {
                "/dev/xvda1": {
                    "kb_available": 5.8507e+06,
                    "kb_size": 8.115168e+06,
                    "kb_used": 1.829192e+06,
                    "mount": "/",
                    "percent_used": "24%"
                },
・・・略・・・
            },
            "kernel": {
                "machine": "x86_64",
                "name": "Linux",
                "os": "GNU/Linux",
                "release": "3.13.0-48-generic",
                "version": "#80-Ubuntu SMP Thu Mar 12 11:16:15 UTC 2015"
            },
            "memory": {
                "active": "474800kB",
                "anon_pages": "55116kB",
                "bounce": "0kB",
                "buffers": "136852kB",
                "cached": "482840kB",

・・・略・・・
                "writeback": "0kB"
            }
        },
        "interfaces": [
            {
                "name": "eth0",
                "ipAddress": "172.31.3.172",
                "macAddress": "00:00:00:00:00:7d"
            }
        ]
    }
]

retire

ホストの退役を行います。 オプションは --force のみで、違いは y/n プロンプトの有無です。

USAGE:
    mkr retire hostIds...

オプション有無

オプション未指定では y/n を聞いてきます。

# forceオプション無
$ mkr retire XXXXXXXXCVE
Retire following hosts.
  XXXXXXXXCVE
Are you sure? (y/n) [y]: y
   retired XXXXXXXXCVE
# forceオプション有
$ mkr retire --force XXXXXXXXHwG
   retired XXXXXXXXHwG

キャンセル (n押下)

明示的に "n" を指定しないと、 "y" を指定した際と同じ動作です。

# n 押下でキャンセル
$ mkr retire XXXXXXXX1N5
Retire following hosts.
  XXXXXXXX1N5
Are you sure? (y/n) [y]: n
           retirement is canceled.
# n 以外押下だと y 押下と同様に削除
$ mkr retire XXXXXXXX1N5
Retire following hosts.
  XXXXXXXX1N5
Are you sure? (y/n) [y]:
   retired XXXXXXXX1N5

複数指定

スペース区切りで複数指定が可能です。

% mkr retire XXXXXXXXUmG XXXXXXXXrdm
Retire following hosts.
  XXXXXXXXUmG
  XXXXXXXXrdm
Are you sure? (y/n) [y]:
   retired XXXXXXXXUmG
   retired XXXXXXXXrdm

PowerOffを全てretire

hosts コマンドから id を抽出して削除する例です。

mkr retire --force $(mkr hosts --status poweroff | jq -r '.[].id' | tr '\n' ' ')

ホストの退役はWeb画面上からだと1ホストずつしか行えないため、一括退役をさせる場合に非常に便利です。

おそらく次回に続きます

Mackerel事始め mkr (1)

Mackerel の CLI 操作を試します。

f:id:htnosm:20160523005746p:plain

WebAPIが用意されていますが、APIを簡略化したコマンド mkr があるのでそちらを利用してみます。

機能

利用頻度の高い操作が揃っているようです。mkrに無い機能の CLI 利用は直接APIを使用することになります。

Command 機能 用途
monitors 監視 監視ルールの取得・更新・差分表示
alerts アラート 一覧取得・クローズ
hosts ホスト 一覧取得
status ホスト 詳細情報取得
create ホスト 新規作成
update ホスト 情報更新
retire ホスト ホストを退役
fetch メトリック 最新値の取得
throw メトリック 値の投稿

APIKEY

APIKEYの設定が必要になるので予め取得・設定をしておきます。 設定をしていない場合以下の様なエラーが出力されます。

$ mkr hosts
     error
    MACKEREL_APIKEY environment variable is not set. (Try "export MACKEREL_APIKEY='<Your apikey>'")

monitors

公式ヘルプにも固有ページがあります。 jsonダウンロード → 編集 → jsonアップロードで設定変更が簡単に行なえます。
サブコマンドも pull、diff、push のみとシンプルです。

設定数が多くなってきた場合、jsonファイルは可読性に難有りになるかもしれません。(split的な物が欲しくなりそうです)

ちなみにヘルプ表示の際に GLOBAL OPTION は使えないようです。

# 不可
#mkr monitors {-h|--help}
# ヘルプ表示
mkr monitors {h|help}

pull

  • Mackerel から monitor 設定をダウンロード

直下に monitors.json が生成されます。

$ mkr monitors pull
$ ls -l
total 8
-rw-r--r--  1 testuser  testgroup  1394  5 10 13:27 monitors.json
$ cat monitors.json
{
    "monitors": [
        {
            "id": "XXXXXXXXkdu",
            "type": "connectivity"
        },
        {
            "id": "XXXXXXXXQTj",
            "name": "loadavg5",
            "type": "host",
            "metric": "loadavg5",
            "operator": ">",
            "warning": 5,
            "critical": 10,
            "duration": 10
        },
        {
            "id": "XXXXXXXXZfY",
            "name": "CPU %",
            "type": "host",
・・・略

diff

  • Mackerel と monitors.json の差分表示
# Mackerel との差分が無い場合
$ mkr monitors diff
Summary: 0 modify, 0 append, 0 remove

# monitors.json を編集
$ vi monitors.json
# Mackerel との差分が有る場合
$ mkr monitors diff
Summary: 1 modify, 0 append, 0 remove

  {
    "name": "Filesystem %",
    "type": "host",
    "metric": "disk%",
    "operator": ">",
-   "warning": 50.000000,
+   "warning": 60.000000,
    "critical": 80.000000,
    "duration": 1,
  },

push

  • Mackerel への反映
$ mkr monitors push
      info Update a rule.
 {
   "id": "XXXXXXXXopA",
   "name": "Filesystem %",
   "type": "host",
   "metric": "disk%",
   "operator": ">",
   "warning": 60,
   "critical": 80,
   "duration": 1
 },
$ mkr monitors diff
Summary: 0 modify, 0 append, 0 remove

Web画面で確認

  • 反映前

f:id:htnosm:20160523005747p:plain

  • 反映(push)後

f:id:htnosm:20160523005748p:plain

Web画面でも変更が確認できました。

alerts

アラート操作としては一覧表示とクローズのみです。 ちなみにこちらもヘルプ表示の際に GLOBAL OPTION は使えないようです。

list

  • アラート一覧出力

アラートが存在しない場合は当然ですが何も返って来ません。

$ mkr alerts list
$

アラートが存在する場合は以下のようになります。レベルに色が付いていて良い感じです。

  • アラートが存在

f:id:htnosm:20160523005749p:plain

  • コマンド出力結果

f:id:htnosm:20160523005750p:plain

close

  • アラートのクローズ(アラートID指定)

list で取得した Id を指定してクローズします。

  • コマンド出力結果

f:id:htnosm:20160523005751p:plain

  • アラートがクローズされる

f:id:htnosm:20160523005752p:plain


きっと次回に続きます