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

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

尚、現時点で公式ドキュメントの記載は見つけられませんでしたので、仕様変更が入るかもしれません。 Knowledge Base に少しだけ記載があります。
インスタンスIDの取得
他のAPI同様に利用できるようなので curl コマンドでの取得を試します。 API Key、Application Key が必要になります。
EC2インスタンスの値としては以下のようになっていました。
aws_id で目的のインスタンス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 を有効化します。(初回のみ)

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

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 として作成します。

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

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

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バケットへの書込設定があります。

項目名の通り、収集実行結果の成否を書き込むだけで、インベントリデータが保存されるわけではありません。
- 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毎
$ 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/' ・・・
- 利用例

QuickSight でデータを使用
- 利用例

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

SSMエージェント導入等、少々手間は入りますがAWS内でソフトウェア管理が完結できるのは良いですね。
ansible pythonが無い場合の対処
Ubuntu 16.04.2 に対して ansible 実行しようとしたら python が見つからないよと怒られたのでメモ。
公式ドキュメントに記載があります。
- Managed Node Requirements
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
DynamoDB Auto Scaling 関連リソース
AWSマネジメントコンソールで新規テーブルを作成すると、デフォルトで Auto Scaling が有効な状態で作成されるようになっているそうです。(変わっていないAWSアカウントもありましたので、既存環境はIAM Role等々を用意しないと切り替わらないのかもしれません。)
- デフォルトで Auto Scaling 有効

- デフォルトで Auto Scaling 無効(既存)

以下、既存テーブルへ適用しようとした際に調査した内容です。
DynamoDB Auto Scaling 設定値
設定できる最小/最大値は以下の通りです。
- Provisioned capacity
- Auto Scaling を有効化した場合は設定不可
- Auto Scaling
- Target utilization (%)
- 20 〜 80
- Minimum provisioned capacity
- 1 〜 5
- Maximum provisioned capacity
- 5 〜 10000
- IAM Role
- AWSマネジメントコンソール上でのデフォルトは DynamoDBAutoscaleRole
- Target utilization (%)
DynamoDB Auto Scaling 有効化で作成されるリソース
IAM Role
規定では DynamoDBAutoscaleRole です。 後述のポリシー(DynamoDBAutoscalePolicy)、Trust Relationshipが付与されます。
DynamoDBAutoscalePolicy
"Document": {
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"dynamodb:DescribeTable",
"dynamodb:UpdateTable",
"cloudwatch:PutMetricAlarm",
"cloudwatch:DescribeAlarms",
"cloudwatch:GetMetricStatistics",
"cloudwatch:SetAlarmState",
"cloudwatch:DeleteAlarms"
],
"Resource": "*",
"Effect": "Allow"
}
]
}
Trust Relationship
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "",
"Effect": "Allow",
"Principal": {
"Service": "application-autoscaling.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Application Auto Scaling
スケーリングは DynamoDB での管理ではなく、 Application Auto Scaling での管理となります。
ScalableTarget
テーブル単位で ReadCapacityUnits と WriteCapacityUnits がそれぞれ作成されます。
"ScalableTargets": [
{
"ScalableDimension": "dynamodb:table:ReadCapacityUnits",
"ResourceId": "table/dummy-table",
"RoleARN": "arn:aws:iam::999999999999:role/service-role/DynamoDBAutoscaleRole",
"CreationTime": 9999999999.99,
"MinCapacity": 1,
"ServiceNamespace": "dynamodb",
"MaxCapacity": 5
},
{
"ScalableDimension": "dynamodb:table:WriteCapacityUnits",
"ResourceId": "table/dummy-table",
"RoleARN": "arn:aws:iam::999999999999:role/service-role/DynamoDBAutoscaleRole",
"CreationTime": 9999999999.99,
"MinCapacity": 1,
"ServiceNamespace": "dynamodb",
"MaxCapacity": 5
}
]
ScalingPolicy
テーブル単位で ReadCapacityUnits と WriteCapacityUnits がそれぞれ作成されます。
加えて、スケーリング判断用の CloudWatch Alarm が4つ付随します。
"ScalingPolicies": [
{
"PolicyName": "DynamoDBReadCapacityUtilization:table/dummy-table",
"ScalableDimension": "dynamodb:table:ReadCapacityUnits",
"ResourceId": "table/dummy-table",
"CreationTime": 9999999999.999,
"PolicyARN": "arn:aws:autoscaling:ap-northeast-1:999999999999:scalingPolicy:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:resource/dynamodb/table/dummy-table:policyName/DynamoDBReadCapacityUtilization:table/dummy-table",
"PolicyType": "TargetTrackingScaling",
"TargetTrackingScalingPolicyConfiguration": {
"TargetValue": 70.0,
"PredefinedMetricSpecification": {
"PredefinedMetricType": "DynamoDBReadCapacityUtilization"
}
},
"Alarms": [
{
"AlarmName": "TargetTracking-table/dummy-table-AlarmHigh-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"AlarmARN": "arn:aws:cloudwatch:ap-northeast-1:999999999999:alarm:TargetTracking-table/dummy-table-AlarmHigh-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
},
{
"AlarmName": "TargetTracking-table/dummy-table-AlarmLow-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"AlarmARN": "arn:aws:cloudwatch:ap-northeast-1:999999999999:alarm:TargetTracking-table/dummy-table-AlarmLow-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
},
{
"AlarmName": "TargetTracking-table/dummy-table-ProvisionedCapacityHigh-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"AlarmARN": "arn:aws:cloudwatch:ap-northeast-1:999999999999:alarm:TargetTracking-table/dummy-table-ProvisionedCapacityHigh-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
},
{
"AlarmName": "TargetTracking-table/dummy-table-ProvisionedCapacityLow-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"AlarmARN": "arn:aws:cloudwatch:ap-northeast-1:999999999999:alarm:TargetTracking-table/dummy-table-ProvisionedCapacityLow-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
}
],
"ServiceNamespace": "dynamodb"
},
・・・略
]
CloudWatch Alarm
AlarmHigh のみ 5分間、その他は 15分間での設定になっています。 Description に DO NOT EDIT OR DELETE と有り、閾値時間変更は推奨されないようです。
- AlarmLow
- AlarmHigh
- ProvisionedCapacityLow
- ProvisionedCapacityHigh
AWS CLI チュートリアル
CLI を使用したチュートリアルが公開されていますので、一通り実行してみるとイメージを掴みやすいかと思います。
Using the AWS CLI to Manage DynamoDB Auto Scaling - Amazon DynamoDB
チュートリアル実施時の注意点としては下記のような感じでしょうか。
DynamoDB Auto Scaling 設定は、aws dynamodb ではなく、aws application-autoscaling です。
マネジメントコンソールから作成すると、ScaleOutCooldown/ScaleInCooldown はデフォルト0で作成されます。 マネジメントコンソール上からの変更方法は現時点では提供されていないようです。
Mackerel 自動復旧させないアラートは手動復旧しないとその後のアラートが通知されないことがあるので気を付ける
経緯
Mackerel のチェック監視に prevent_alert_auto_close オプションが追加されました。
自動復旧しないアラート ということで、ログ監視に利用できるかと考えたのですが、思っていた内容とは少し異なる動きでした。
やりたかったこと
- check-log でのアラート発生時の後に通知される 復旧通知(OK)を無くしたい

ログの監視なのでアラート通知されればよく、復旧通知は不要と思っています。
実際
test_1.log を prevent_alert_auto_close = true として、2つのログファイルに同一タイミングで同一メッセージを出力して確認します。
[plugin.checks.test_1_log]
command = '''
check-log \
--file /var/log/test_1.log \
--pattern 'ERROR' \
--warning-over 0 \
--critical-over 0 \
--return
'''
prevent_alert_auto_close = true
[plugin.checks.test_2_log]
command = '''
check-log \
--file /var/log/test_2.log \
--pattern 'ERROR' \
--warning-over 0 \
--critical-over 0 \
--return
'''
アラート1回目
test_1 は復旧通知が無いため、要望を満たせたように見えます。
- test_1 (Auto Close 無し)

- test_2 (Auto Close)

- 通知結果

アラート2回目
test_1 はアラートが発生しません。
- 通知結果

アラート3回目
test_1 を手動で復旧してから、再度ログ出力を行います。

- 通知結果

結論
アラートの復旧を行った状態でないと、次回以降のチェック時にアラート状態であっても通知は行われません。
チェック監視のアラート通知
アラートが発生した場合と、アラート発生後にアラートの状態が変更した場合にアラートの通知が行われます。「アラートの状態が変更した場合」には以下の2つの場合があります。ステータスが変更になった場合
ex. CRITICAL -> WARNING, WARNING -> CRITICAL, CRITICAL -> OK
ステータスがOKになった場合も含みます
チェックプラグインが送信してくるメッセージの内容が変わった場合
ということで、 prevent_alert_auto_close オプション はログ監視(特にエラー時にのみ出力されるログ)には向かないようです。
復旧通知の無効化や、某abbixの 障害イベントを継続して生成 のような機能の実装を待ちます。
Datadog 通知先振分あれやこれや
Datadog Monitor 通知先の振り分け設定パターンです。

前提
通知先のインテグレーション設定を済ませておきます。 今回は Slack インテグレーションで試してます。

ちなみに今回は通知先しか設定していませんが、同様に通知する本文も振り分け先により変更できます。
基本形
Monitor設定画面の Notify your team から定義済みの通知設定を選択することで、本文(Say what’s happening) に自動的に入力されます。 複数設定も可能です。

メールアドレス通知については定義済み通知先の他に、直接指定も可能です。
(例えばuser@example.comなら@user@example.comと記述)。
アラートレベルで振分
テンプレート変数を利用し、Alert/Warning/Recoveryなどで通知先を振り分けます。
本文に以下のように記載することで、正しい値であればNotify your teamが自動入力されます。

- Monitoringレファレンス
- “通知内で使うことのできるテンプレート変数” 辺り
- 設定できる値は http://docs.datadoghq.com/monitoring/#message-template-variables に表有り
タグの値で振分
テンプレート変数の亜種です。 match変数を利用し、指定したタグの値により通知先を振り分けます。

{{#is_match “タグ変数” “文字列”}}
ここに、一致した場合に表示する本文を記述します。
{{/is_match}}
ドキュメントに記載が無いですが、 exact_match 変数が存在します。 使い方は match と同じです。
{{#is_exact_match “タグ変数” “文字列”}}
ここに、一致した場合に表示する本文を記述します。
{{/is_exact_match}}
match と exact_match の違いは、 match = 中間一致、exact_match = 完全一致 のようです。
タグで指定
ドキュメントに記載はありません。明確に駄目とも記載は無いので今の所は利用可能なようです。
通知先を設定する @〜 部分にタグを埋め込みます。
Monitor画面上は通知先が決定されていないため、Notify your teamには値が入りません。
また、同一タグ名で複数値がある場合はカンマ区切りで設定され、両方へ通知が成されるようです。

例として、 対象に slack_channel_name というタグを付与しています。
slack_channel_name:alert_yabai i-04bxxxxxxxxx51fc0 slack_channel_name:alert_sodemonai i-093xxxxxxxxx1b20d
- alert_sodemonai

- alert_yabai
