vague memory

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

collectd-cloudwatch を Amazon Linux 以外に導入してみる

導入対象EC2 が Amazon Linux の記事はよく見かけますが、他のディストリビューションでの情報があまりなかったため比較を行いました。



ディストリビューションと導入しやすさ

yum/apt での導入を前提としています。新しめのディストリビューションであれば特に苦労しません。

distribution Version python(Default) collectd 導入しやすさ
Amazon Linux 2017.09 2.7.12 5.7.1
CentOS 7.4.1708 2.7.5 5.7.1
CentOS 6.9 2.6.6 4.10.9 ×
Ubuntu 16.04.3 LTS 3.5.2 5.5.1
Ubuntu 14.04.5 LTS 2.7.6 5.4.0

Amazon Linux

提供元がAWSだけあって Amazon Linux は何も考えずに導入できます。

$ sudo yum install collectd collectd-python
$ curl -s -S -O "https://raw.githubusercontent.com/awslabs/collectd-cloudwatch/master/src/setup.py"
$ chmod u+x setup.py
$ sudo ./setup.py

CentOS

collectd は epel を利用しインストールします。

CentOS 7

README に記載がある collectd-python はパッケージが存在しなかったため未インストールです。

$ sudo yum install epel-release
$ sudo yum install collectd
$ curl -s -S -O "https://raw.githubusercontent.com/awslabs/collectd-cloudwatch/master/src/setup.py"
$ chmod u+x setup.py
$ sudo ./setup.py

CentOS 6

collectd 5.0.0 未満では collectd-cloudwatch は使用できません。

collectd は epel を利用してインストールしますが、4.10.9です。 また、 collectd-cloudwatch のインストールでエラーになります。

まず、python 2.6 では setup.py が動作しません。

$ python -V
Python 2.6.6
$ sudo ./setup.py
Traceback (most recent call last):
  File "./setup.py", line 28, in <module>
    from subprocess import check_output, CalledProcessError, Popen, PIPE
ImportError: cannot import name check_output

python 2.7 にしても setup.py は別のエラーとなります。

$ python -V
Python 2.7.14
$ sudo ./setup.py
Traceback (most recent call last):
  File "./setup.py", line 964, in <module>
    main()
  File "./setup.py", line 957, in main
    install_plugin()
  File "./setup.py", line 869, in install_plugin
    install_packages(SYSTEM_DEPENDENCIES)
  File "./setup.py", line 261, in install_packages
    command = DISTRIBUTION_TO_INSTALLER[detect_linux_distribution()] + " ".join(packages)
  File "./setup.py", line 270, in detect_linux_distribution
    return DISTRO_NAME_REGEX.search(search_string).group(1).strip()
AttributeError: 'NoneType' object has no attribute 'group'

ディストリビューションの判断を /etc/os-release で行っているので、無理矢理通してみるとようやく未サポートのメッセージ表示となりました。

$ sudo ./setup.py
Installing dependencies ... OK
Installing python dependencies ... OK
Downloading plugin ... OK
Extracting plugin ... OK
Moving to collectd plugins directory ... OK
The minimum supported version of collectd is 5.0.0, and your version is 4.10.9. You need to upgrade collectd before proceeding with the plugin installation.

Ubuntu

collectd の設定ファイル格納場所が Redhat系(Amazon Linux含む) とは異なります。

Ubuntu16

python 2.7 を使えるようにしておく必要があります。

$ python -V
Python 2.7.14
$ sudo apt-get install collectd
$ curl -s -S -O "https://raw.githubusercontent.com/awslabs/collectd-cloudwatch/master/src/setup.py"
$ chmod u+x setup.py
$ sudo ./setup.py

Ubuntu14

インストール自体は他と同様です。

$ sudo apt-get install collectd
$ curl -s -S -O "https://raw.githubusercontent.com/awslabs/collectd-cloudwatch/master/src/setup.py"
$ chmod u+x setup.py
$ sudo ./setup.py

ディストリビューションと異なり、collectd が5.4のため、インストール時にデフォルトで設定されているメトリクスが使用できません。
公式ブログにもありますが、disk 以外の cpu/memory/swap は、 5.5 からパーセンテージが利用できるようになっています。

バージョン 5.5 以降の collectd を使用している場合は、4 つのメトリックスがデフォルトで発行されるようなりました。

デフォルト設定での導入結果

f:id:htnosm:20171106033047p:plain

その他

CloudWatch の Endpoint(monitoring.{{region}}.amazonaws.com) へ送信しているため、Outbound制限を掛けている場合は 443 ポートの許可が必要です。

Backlog Git README.md で画像表示

Backlog の GitMarkdown 内の画像を表示したいという要件があったので調べました。
Backlog上(ブラウザ)で画像を表示 したい場合です。(Markdownエディタ等での表示は考慮していません)

現時点ではリポジトリ内ファイル参照はサポートしていないようです。 Wikiを使いましょういうことなのでしょうが、Gitでドキュメント管理する場合等に使えるかもしれない小ネタです。



GitHub での構文

Images
![GitHub Logo](/images/logo.png)
Format: ![Alt Text](url)

Backlog Git 上の .md での画像表示

Backlog上(ブラウザ)で画像ファイル自体が表示できるので、そのURLを指定すれば可能です。

# raw
![代替文字列](https://{{ Backlog Space }}.backlog.jp/git/{{ Backlog Project }}/{{ Git Repository }}/raw/{{ branch }}/{{ Path }}/{{ File }})

# preview
![代替文字列](https://preview-{{ Backlog Space }}.backlog.jp/git/{{ Backlog Project }}/{{ Git Repository }}.git/{{ branch }}/{{ Path }}/{{ File }})

尚、HTML直書きは未対応でした。

practice
├── TEST1.md
├── TEST2.md
└── img
    └── logo.png
  • Backlogスペース名: hoge
  • Backlogプロジェクト名: PCT
  • Gitリポジトリ名: practice
  • Gitブランチ: master
## Raw

- Markdown

![raw md](https://hoge.backlog.jp/git/PCT/practice/raw/master/img/logo.png)

- HTML

<img src="https://hoge.backlog.jp/git/PCT/practice/raw/master/img/logo.png" alt="raw html" title="raw html">

## Preview

- Markdown

![preview md](https://preview-hoge.backlog.jp/git/PCT/practice.git/master/img/logo.png)

- HTML

<img src="https://preview-hoge.backlog.jp/git/PCT/practice.git/master/img/logo.png" alt="preview html" title="preview html">

f:id:htnosm:20171005134852p:plain

リポジトリ内ファイル参照(未サポート)例

相対パスでの指定だと表示されません。

- Markdown

![md](img/logo.png)

- HTML

<img src="img/logo.png" alt="html" title="html">

f:id:htnosm:20171005134851p:plain


DatadogAgent を Windows10(日本語環境) へインストール

今更ながら、初めて Windows へ DatadogAgent をインストールしました。
Linux との違いを中心にメモ。

基本的には公式ドキュメント一読でほぼ事足ります。

目次

インストール

環境

Agent version
    5.17.2
Platform
    Windows-10-10.0.15063
Python version
    2.7.12, 64bit

以下デフォルトインストールです。

f:id:htnosm:20170923014827p:plain

起動/停止

Datadog Agent Manager

GUIで各種操作を行えるツールです。

  • Setting・・・Datadog.conf、各種インテグレーションファイルの編集
  • Log and Status・・・Agent Status、各種ログの参照
  • Actions・・・Agent起動・停止、サポートケース起票(Flare)

f:id:htnosm:20170923014828p:plain f:id:htnosm:20170923014829p:plain

各種インテグレーションファイルの編集は、[Save] しただけでは有効化されないため、[Enable] を押下して有効化する必要があります。

Service

Windowsサービスからも起動/停止が可能です。

f:id:htnosm:20170923014830p:plain

各種ディレクト

インストールディレクト

C:\PROGRAM FILES\DATADOG\DATADOG AGENT
├─agent
├─bin
├─dist
├─embedded
└─LICENSES

設定ファイル・ログ

Datadog Agent Manager を使用せずに直接参照・編集も可能です。
因みに、Datadog Agent Manager の [Enable/Disable] は conf.d 配下の 〜.yaml をリネームしています。

C:\PROGRAMDATA\DATADOG
│  datadog.conf    # Datadog Agent の設定ファイル
├─checks.d         # カスタムチェックファイル
├─conf.d           # Integrations の設定ファイル
└─logs             # 各種ログファイル
        collector.log
        dogstatsd.log
        forwarder.log
        service.log

Event Viewer Integration

WindowsイベントログをDatadogへ連携するインテグレーションが用意されています。

type でエラーレベルでの絞り込みができるようになっていますが、 マルチバイト(というかマルチロケーション)非対応で、 日本語環境では動作しません。 以下のように元のインテグレーションファイルを編集して、カスタムチェックを作成して回避しました。

  • win32_event_log_ja(差分)
--- win32_event_log.py
+++ win32_event_log_ja.py
@@ -1,3 +1,12 @@
+#!/usr/bin/python
+# -*- coding: cp932 -*-
+'''
+日本語環境用イベントログ監視
+'''
+import sys
+reload(sys)
+sys.setdefaultencoding('cp932')
+
 # (C) Datadog, Inc. 2010-2016
 # All rights reserved
 # Licensed under Simplified BSD License (see LICENSE)
@@ -87,6 +96,19 @@
         if ltypes:
             query['Type'] = []
             for ltype in ltypes:
+                if ltype == 'Critical':
+                    ltype = '重大'
+                elif ltype == 'Error':
+                    ltype = 'エラー'
+                elif ltype == 'Warning':
+                    ltype = '警告'
+                elif ltype == 'Information':
+                    ltype = '情報'
+                elif ltype == 'Audit Success':
+                    ltype = '成功の監査'
+                elif ltype == 'Audit Failure':
+                    ltype = '失敗の監査'
+
                 query['Type'].append(('=', ltype))
         if source_names:
             query['SourceName'] = []
@@ -223,9 +245,11 @@
     def _alert_type(self):
         event_type = self.event['Type']
         # Convert to a Datadog alert type
-        if event_type == 'Warning':
+        if event_type == '警告':
             return 'warning'
-        elif event_type == 'Error':
+        elif event_type == '重大':
+            return 'error'
+        elif event_type == 'エラー':
             return 'error'
         return 'info'

win32_event_log_ja.py を checks.d、win32_event_log_ja.yaml(中身はwin32_event_log.yamlと同じ) を conf.d に格納して使用します。

f:id:htnosm:20170923014831p:plain

WindowsでのカスタムCheckのテスト

日本語ドキュメントには shell.exe を使用するように記載がありますが、agent version 5.12 以上の場合の確認方法は下記になります。 (現時点で日本語ドキュメントには旧バージョンの確認方法しか記載がありません。)

<INSTALL_DIR>/embedded/python.exe <INSTALL_DIR>agent/agent.py check <CHECK_NAME>

今回インテグレーションは Event Viewer のみ導入しましたが、他にもロケール問題が出る物があるのかもしれません。 (イベントログのエラーレベル位、Windows側が英語で出力すれば良いのではと思いますが)
Datadog公式でマルチロケール対応が成されることを期待します。

Datadog EC2インスタンスIDの取得

Datadog Agent でのホスト名はルールに従って決定されます。

host名を固定化している場合、datadog.conf 内で明示的に hostname: を指定している場合等には、 指定値が優先されます。
監視対象 AWS EC2インスタンスの instance-id を取得したいと思ったのですが、上記設定が入っていたため tag では保持していませんでした。

ドキュメントの Host Aliases にある通り、 Host としては hostname: の設定値となり、 Alias として instance-id を持っている状態です。



Alias

Datadog Agent の info 情報で取得できる Hostnames を保持しているようです。
Infrastructure List 画面で確認できます。

  Hostnames
  =========

    ec2-hostname: ip-XXX-XX-XX-XXX.ap-northeast-1.compute.internal
    local-ipv4: XXX-XX-XX-XXX
    hostname: XX01
    socket-hostname: XX01
    local-hostname: ip-XXX-XX-XX-XXX.ap-northeast-1.compute.internal
    instance-id: i-XXXXX77e
    public-ipv4: XX.XX.XXX.XX
    socket-fqdn: localhost.localdomain

f:id:htnosm:20170919023321p:plain

JSON API permalink

Infrastructure 画面以外で Alias を取得する方法として JSON API permalink が用意されています。 画面下部からリンクURLを取得できます。
内容は Infrastructure 画面で参照できる値をJSON形式で取得できます。

f:id:htnosm:20170919023322p:plain

尚、現時点で公式ドキュメントの記載は見つけられませんでしたので、仕様変更が入るかもしれません。 Knowledge Base に少しだけ記載があります。

インスタンスIDの取得

他のAPI同様に利用できるようなので curl コマンドでの取得を試します。 API Key、Application Key が必要になります。

EC2インスタンスの値としては以下のようになっていました。 aws_id で目的のインスタンスIDを取得できます。

  • host_name : Datadog上のHostname
  • aws_name : AWS上のEC2タグ
  • aws_id : AWS EC2 Instance ID
$ apikey=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
$ appkey=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
$ hostname=XX01
$ curl -s -S "https://app.datadoghq.com/reports/v2/overview?api_key=${apikey}&application_key=${appkey}" \
  | jq '.rows[] | select(.host_name == "'${hostname}'") | { host_name:.host_name, aws_name:.aws_name, aws_id:.aws_id }'
{
  "host_name": "XX01",
  "aws_name": "XXXXXXXXX-XX01",
  "aws_id": "i-XXXXX77e"
}

因みに取得できる基本項目は以下です。オプション付与で他にも色々取得できるようです。 infrastructure で表示している項目は全て保持していると思われます。

{
  "rows": [
    {
      "display_name": "i-XXXXXXXXXXXXXXXXX",
      "name": "i-XXXXXXXXXXXXXXXXX",
      "tags_by_source": {
        "Amazon Web Services": [
          "availability-zone:ap-northeast-1a",
          "iam_profile:xxxxx",
          "image:ami-XXXXX2f5",
          "instance-type:t2.micro",
          "kernel:none",
          "name:XXXXX",
          "region:ap-northeast-1",
          "security-group:sg-XXXXXXXX"
        ]
      },
      "up": true,
      "aws_name": "XXXXX",
      "host_name": "i-XXXXXXXXXXXXXXXXX",
      "has_metrics": false,
      "aws_id": "i-XXXXXXXXXXXXXXXXX",
      "id": XXXXXXXXX,
      "last_seen": 1503457664
    },
・・・

Datadog Ansible Integration

Ansible の実行結果を Datadog へ連携できます。

Python 2.7 で試しました。 3系だと現状そのままだと Syntax Error となるので、 datadog_callback.py の一部書き換え(修正)が必要です。



Ansible Integration

Datadog 上で Ansible Integration を有効化します。(初回のみ)

f:id:htnosm:20170913013217p:plain

5分程で有効化が完了します。

f:id:htnosm:20170913013218p:plain

Setup

必要なライブラリ(datadogpy、pyyaml)をインストールしておきます。

$ pip list | grep -i -e "datadog" -e "pyyaml"
datadog (0.16.0)
PyYAML (3.12)

Ansible のコールバック機能を利用して連携します。 ansible-datadog-callback を適当なディレクトリに clone します。

datadog_callback.py があれば良いので、clone することは必須ではないです。

$ cd /tmp
$ git clone https://github.com/DataDog/ansible-datadog-callback.git 

Ansible へのコールバックプラグイン追加

既存の Playbook と同一階層に callback_plugins ディレクトリを作成し、 datadog_callback.py を格納します。

$ mkdir ansible/callback_plugins
$ cp /tmp/ansible-datadog-callback/datadog_callback.py ansible/callback_plugins

Datadog API キー用の yml を作成します。

$ echo "api_key: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" > ansible/callback_plugins/datadog_callback.yml

以下のような階層になりました。

ansible
├── main.yml
├── callback_plugins
│   ├── datadog_callback.py
│   └── datadog_callback.yml
├── group_vars
│   └── main.yml
├── hosts
├── roles
│   ├── hogehoge
・・・

Ansible Playbook 実行

通常通り実行します。

$ cd ansible
$ ansible-playbook -i hosts main.yml

結果

メトリクスとしては、 タスクの正常、失敗、スキップ、到達不能、変更無しの数と Playbook の実行時間が取得できます。

Events

ansible-playbook実行時、成功/失敗のイベントが生成されます。 failure, unreachable だと Error として作成します。

f:id:htnosm:20170913013219p:plain

Event Monitor で失敗時に通知させるには、 sources:ansible, status:error と Playbook名で絞り込みます。

f:id:htnosm:20170913013221p:plain

Integration Dashboards

Ansible のダッシュボード で見ると以下のような感じになります。

f:id:htnosm:20170913013220p:plain

AWS EC2 Systems Manager を S3 へ同期

System Manager のインベントリデータをS3バケットへ集約できるようになったとのことで試してみました。

公式ドキュメント上にも EC2 -> System Manager -> S3 -> Athena -> QuickSight 連携方法がありました。

手順はドキュメント通りで問題無いので引っ掛かったポイントだけメモします。



インベントリ収集

  • [EC2] → [Systems Manager Shared Resources] → [Managed Instances] → [Setup Inventory]

Write Execution History to S3

インベントリのセットアップ時に Write Execution History to S3 でS3バケットへの書込設定があります。

f:id:htnosm:20170817204119p:plain

項目名の通り、収集実行結果の成否を書き込むだけで、インベントリデータが保存されるわけではありません。

  • S3格納パス
{{ S3 Bucket Name }}/{{ S3 Key Prefix }}/{{ InstanceId }}/{{ AssociationId }}/{{ datetime(UTC) }}/awssoftwareInventory/collectSoftwareInventoryItems/{stdout|stderr}
  • 出力例
# 成功時
s3://xxx.bucket/xxx.keyprefix/i-0f7d0577f65XXXXX/8611acf6-f9a1-49b9-8907-XXXXXXXXXXXX/2017-mm-ddThh-mm-ss.077Z/awssoftwareInventory/collectSoftwareInventoryItems/stdout
# 失敗時
s3://xxx.bucket/xxx.keyprefix/i-0f7d0577f65XXXXX/8611acf6-f9a1-49b9-8907-XXXXXXXXXXXX/2017-mm-ddThh-mm-ss.077Z/awssoftwareInventory/collectSoftwareInventoryItems/stderr

インスタンスは一度に一つのインベントリのみ

インスタンスには、一度に 1 つのインベントリのみ関連付けることができます。インスタンスに 2 つ以上関連付けて設定した場合、その関連付けは実行されず、インベントリデータは収集されません。

重複設定を行った場合、stderr に以下のように出力されます。

aws:softwareInventory detected multiple inventory configurations associated to one instance. You can  associate multiple inventory configurations to an instance.
The association IDs are: e6df398e-a8fc-4b38-b349-XXXXXXXXXXXf and 8611acf6-f9a1-49b9-8907-XXXXXXXXXXX3.

リソースデータの同期

今回の本題です。特に引っ掛かる箇所は無いと思います。

  • [EC2] → [Systems Manager Shared Resources] → [Managed Instances] → [Resource Data Syncs] → [Create a Resource Data Sync]

同期とターゲット Amazon S3 バケットが異なるリージョンにある場合、データ転送料金がかかる場合があります。

特別理由が無いのであれば、S3バケットは同一リージョンに作成するのが良いと思います。

出力結果

  • S3格納パス
{{ Bucket Name }}/{{ Bucket Prefix }}/AWS:{{ Parameters }}/accountid={{ AWS AccountId }}/region={{ Region }}/resourcetype= ManagedInstanceInventory/{{ InstanceId }}.json
  • 出力例

    • バケット配下に Parameters 毎に出力
    • Athenaのパーティション向けにHiveフォーマットで階層が切られる
    • 出力形式はJSON
  • 出力例

# Parameters毎
$ aws s3 ls s3://{{ Bucket Name }}/{{ Bucket Prefix }}/
                           PRE AWS:AWSComponent/
                           PRE AWS:Application/
                           PRE AWS:InstanceDetailedInformation/
                           PRE AWS:InstanceInformation/
                           PRE AWS:Network/
# InstanceID.json
$ aws s3 ls s3://{{ Bucket Name }}/{{ Bucket Prefix }}/AWS:Application/accountid=XXXXXXXXXXXX/region=ap-northeast-1/resourcetype=ManagedInstanceInventory/
2017-mm-dd hh:mm:ss     123456 i-XXXXXXXXXXXXXXXXX.json

Athena でデータを使用

テーブル作成クエリもドキュメントに記載されていますので、順次実行していけば良いです。

バケット名とプレフィックスを書き換える必要がありますが、 ドキュメント内のクエリに不要な空白が入っていたり、置換前の名称が異なる部分があるので、少しだけ注意が必要です。

・・・
# 空白が入っている
) LOCATION 's3:// bucketname /bucketprefix/AWS:AWSComponent/'
・・・
# bucketname
) LOCATION 's3://bucketname/bucketprefix/AWS:WindowsUpdate/'
・・・
# bucket-name
) LOCATION 's3://bucket-name/bucketprefix/AWS:InstanceInformation/'
・・・
  • 利用例

f:id:htnosm:20170817204120p:plain

QuickSight でデータを使用

  • 利用例

f:id:htnosm:20170817204122p:plain

東京リージョン未対応

QuickSightは現時点では東京リージョンでは使用できません。 そのため、Athenaをデータソースとする場合はAthenaもQuickSightが対応しているリージョンを選択する必要があります。

f:id:htnosm:20170817204121p:plain


SSMエージェント導入等、少々手間は入りますがAWS内でソフトウェア管理が完結できるのは良いですね。

ansible pythonが無い場合の対処

Ubuntu 16.04.2 に対して ansible 実行しようとしたら python が見つからないよと怒られたのでメモ。

公式ドキュメントに記載があります。

python2 と python3 の共存問題のようです。



エラー内容と環境

  • エラー
fatal: [xxx.xxx.xxx.xxx]: FAILED! => {
    "changed": false,
    "failed": true,
    "module_stderr": "Shared connection to xxx.xxx.xxx.xxx closed.\r\n",
    "module_stdout": "/bin/sh: 1: /usr/bin/python: not found\r\n",
    "msg": "MODULE FAILURE",
    "rc": 0
}
  • 環境
$ cat /etc/os-release
NAME="Ubuntu"
VERSION="16.04.2 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.2 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
VERSION_CODENAME=xenial
UBUNTU_CODENAME=xenial
$ which python
$ which python3
/usr/bin/python3
$ ls -1 /usr/bin/python*
/usr/bin/python3
/usr/bin/python3.5
/usr/bin/python3.5m
/usr/bin/python3-jsondiff
/usr/bin/python3-jsonpatch
/usr/bin/python3-jsonpointer
/usr/bin/python3m

python2 で動かす

python2 をインストールします。 ansible で導入する場合は raw モジュールを使用します。

ansible コマンド例

ansible xxx.xxx.xxx.xxx --sudo -m raw -a "apt-get --yes install python python-simplejson" -i hosts
  • 導入後
$ which python
/usr/bin/python
$ python -V
Python 2.7.12

playbook 例

ansible-playbook で導入する場合は、 gather_facts: no の指定が必要です。

- hosts: xxxxxx
  become: yes
  gather_facts: no
  pre_tasks:
    - name: 'install python2'
      raw: apt-get --yes install python python-simplejson

python3 で動かす(Ansible 2.2以上)

※ 現時点ではプレビューとのことです。

インベントリで ansible_python_interpreter に python3 を指定します。

xxx.xxx.xxx.xxx ansible_python_interpreter=/usr/bin/python3

/usr/bin/python だけが無い場合

/usr/bin/python2 は有るが /usr/bin/python が無い場合などは、以下いずれかで対応できるかと思います。

Ansible 2.2以上

インベントリで ansible_python_interpreter に python2 を指定します。

xxx.xxx.xxx.xxx ansible_python_interpreter=/usr/bin/python2

Ansible 2.2未満

きちんと検証はしていませんが、シンボリックリンクで動作はするようです。

ln -s /usr/bin/python2 /usr/bin/python

参考URL