koudenpaのブログ

趣味のブログです。株式会社はてなでWebアプリケーションエンジニアをやっています。職業柄IT関連の記事が多いと思います。

Mackerelでクラウドインテグレーションしているリソースが消えた時にそのホストのステータスを変える

この記事は Mackerel Advent Calendar 2019 - Qiita の16日目くらいの記事です。昨日は id:tomato3713 さんの mackerel-agent に PullRequest を出した話 - tomato3713’s blog でした。

数ヶ月前、このようなことを行なっていました。

koudenpa.hatenablog.com

ここではそれを育てた結果を記事にできればいいな、と考えていたのですが、

f:id:koudenpa:20191215221323p:plain
『まるで成長していない!!』

悲しいことです。とはいえ、このライブラリ以前に半端ながらどうしていたのかのネタがあるので、今回はそちらを共有しようと思います。

どう言う状況なのか

Mackerelのクラウドインテグレーション(僕の造語)では、一度クラウドリソースがホストとして登録されると、リソースを削除などしてもホストは退役されません。

AWSインテグレーション - Mackerel ヘルプ

AWS 側でインスタンスの削除などを行っただけでは、Mackerel 側のホストは削除(退役)されません。AWSインテグレーションにより連携したホストを Mackerel の監視対象から外すには、別途退役の作業を実施する必要があります。

ちなみに、存在しないリソース分のコストはかからないため放置でもよいです。

どうしたいのか

当時、サービスの開発中だったこともあり頻繁にリソースの作成・削除を行なっていました。消したリソースが Working のまま並んでいると(ホストメトリクスを見たいときなどに)邪魔だったので、ステータスを変えるなり退役させるなりしたいなぁ、と思いました。

どうしていたか

以下のようなことができればよかったわけです。

  1. Mackerelでクラウドインテグレーションしているホストを一覧する
  2. そのうち実際には削除されているリソースのホストを抽出する
  3. 抽出されたホストに何かする

当時はGitHub Actionsがお試し期間中だったんで、なんとなくそれを使って動かしました。定期的に自作したシェルスクリプトを実行する指定です。

name: Update AWS Integration Host status

on: 
   schedule:
     - cron: '05 11 * * *'

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v1
    - run: |
          cd .github/workflows/update-aws-host-status
          ./update-aws-host-status.sh
      env:
        MACKEREL_APIKEY: ${{ secrets.MACKEREL_APIKEY }}
        AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
        AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
        AWS_DEFAULT_REGION: ap-northeast-1

リソースの状態チェックはAWS CLImkr、そしてjqを使っていました。

#!/bin/bash

docker pull mesosphere/aws-cli
docker pull mackerel/mkr

aws() {
    docker run --rm -t $(tty &>/dev/null && echo "-i") \
        -e "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}" \
        -e "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}" \
        -e "AWS_DEFAULT_REGION=${AWS_DEFAULT_REGION}" \
        -v "$(pwd):/project" mesosphere/aws-cli $@
}

mkr() {
    docker run --rm -e "MACKEREL_APIKEY=${MACKEREL_APIKEY}" mackerel/mkr $@
}

hosts=`mkr hosts -v | jq '. | map(select(.type == "cloud" and .isRetired == false))'`
echo $hosts | jq .

hosts_length=`echo ${hosts} | jq length`

for i in `seq 0 $(expr ${hosts_length} - 1)`
do
    host=`echo ${hosts} | jq .[${i}]`
    hostId=`echo ${host} | jq -r .id`
    echo "hostId: ${hostId}"
    hostId=`echo ${hosts} | jq -r .[${i}].id`
    name=`echo ${hosts} | jq -r .[${i}].name`
    customIdentifier=`echo ${hosts} | jq -r .[${i}].customIdentifier`
    provider=`echo ${hosts} | jq -r .[${i}].meta.cloud.provider`

    echo "${host_id} ${provider} ${name} ${customIdentifier}"

    queryOutput=""
    notFoundError="Undefined"
    case "${provider}" in
        "alb" )
            # An error occurred (LoadBalancerNotFound) when calling the DescribeLoadBalancers operation: One or more load balancers not found
            key=`echo ${host} | jq -r .meta.cloud.metadata.\"load-balancer-arn\"`
            queryOutput=`aws elbv2 describe-load-balancers --load-balancer-arns ${key}`
            notFoundError="LoadBalancerNotFound"
            ;;
# ここに消したいリソースのチェックを並べる。。。
    esac
    echo "queryOutput: ${queryOutput}"

    if [ "`echo ${queryOutput} | grep ${notFoundError}`" ]; then
        # 対応リソースなしはパワーオフする
        mkr update --status poweroff ${hostId}
    fi
done

いい感じのスクリーンショットがなかったけれど、こんな感じで消したリソースをPoweroffすることでメトリクスがちょっと見やすくなりました。

展望はあるか

型がある世界で生きていきたい&AWS以外のリソースにも対応したいと思って記事冒頭に書いたライブラリを作り始めたのですけれど、進んでいないこのざまです。いろんな種類に対応するのは大変ですね。ポチッと設定するだけでいい感じのメトリクスが取れる便利さを改めて知る形となってしまいました。

(気分が向いて時間があれば育てたいライブラリではあります)

明日は id:side_tana さんが何か書くようです。