さよならインターネット

EC2のStatus Checkの変異をSNSを通してPagerDutyからSlackへ通知させる

EC2がちょくちょくStatus ChecksがコケてTerminateされていたので
CloudWatchで見ているStatus Checkの値の変異を見て
SNSに通知をさせている。

SNS <-> PagerDuty <-> Slack

参考URL

一番良いのはEC2が立ち上がってきた時に自分自身に下記設定を導入し
自分が消える時に設定を削除するのが好ましいが、所々事情があり
下記のようなスクリプトを特定のEC2で回している。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#!/usr/bin/env ruby

region = 'REGION'

# インスタンスID一覧を取得する ( --max-items XXX # インスタンス数次第 )
instance_ids = `aws --region #{region} ec2 describe-instances \
                    --max-items XXX \
                    --filters Name=tag-key,Values=Name \
                    | jq -r '.Reservations[].Instances[].InstanceId'
                    `

# CloudWatchでStatusCheckFailed_Checkが設定されているインスタンスID一覧 ( --max-items XXX # インスタンス数次第 )
checked_instance_ids = `aws --region #{region} cloudwatch describe-alarms \
                            --max-items XXX \
                            | jq -r '.MetricAlarms[].AlarmName' \
                            | grep 'StatusCheckFailed_Check' \
                            | cut -f 1 -d ' '
                            `

# 改行で要素を分割
instance_ids = instance_ids.split("\n")
checked_instance_ids = checked_instance_ids.split("\n")

# インスタンス一覧にあってCloudWatch側にない監視追加対象のインスタンスID一覧を抽出
new_instance_ids = instance_ids - checked_instance_ids

# CloudWatch側にあってインスタンス一覧にない削除対象のインスタンスID一覧を抽出
deleted_instance_ids = checked_instance_ids - instance_ids

# 監視追加対象のインスタンスID一覧が空でなければCloudWatchに追加していく
unless new_instance_ids.empty?
  new_instance_ids.each do |instance_id|

    # StageというKeyのタグで本番かそれ以外を分けている
    stage = `aws --region #{region} ec2 describe-instances \
                 --instance-ids #{instance_id} \
                 --query 'Reservations[].Instances[].Tags[?Key==\`Stage\`].Value' \
                 --output text
                 `.chomp

    # 本番の場合は通知先が違うのでSNSの向き先を変える
    if stage == 'production'
      sns_topic = 'PRODUCTION_SNS_TOPIC'
    else
      sns_topic = 'OTHER_SNS_TOPIC'
    end

    # MAIN: ここで設定を追加する
    `aws --region #{region} cloudwatch put-metric-alarm \
         --alarm-name "#{instance_id} StatusCheckFailed_Check" \
         --metric-name StatusCheckFailed \
         --namespace AWS/EC2 \
         --statistic Maximum \
         --dimensions Name=InstanceId,Value=#{instance_id} \
         --period 60 \
         --unit Count \
         --evaluation-periods 1 \
         --threshold 0 \
         --comparison-operator GreaterThanThreshold \
         --ok-actions #{sns_topic} \
         --alarm-actions #{sns_topic} \
         --insufficient-data-actions #{sns_topic}
         `

    puts "#{instance_id} StatusCheckFailed_Check is created"
  end
end

# 削除対象のインスタンスID一覧が空でなければ設定を削除していく
unless deleted_instance_ids.empty?
  deleted_instance_ids.each do |instance_id|

    # MAIN: ここで設定を削除する
    `aws --region #{region} cloudwatch delete-alarms \
         --alarm-names "#{instance_id} StatusCheckFailed_Check"`

    puts "#{instance_id} StatusCheckFailed_Check is deleted"
  end
end

こんな感じでやってる。

特定のインスタンスIDのタグのValueを出力する

queryオプションとかよー使わんわということで個人的メモ

Nameタグを出力したければこう

1
2
3
4
$ aws ec2 describe-instances \
          --instance-ids i-XXXXXXXX \
          --query 'Reservations[].Instances[].Tags[?Key==`Name`].Value' \
          --output text

特定のRoleのEIPが付与されているEC2がTerminateされた時に新しく起動したEC2に浮いたEIPを付与させるスクリプト

件の通り

今見直したら結構ひどい感じだったけど一旦公開しておく。
AWS SDK for Rubyを利用してもいいし、これぐらいならgoで書いても良いスね。

仕組み

  • Role - web, db, app, etc…
  • Stage - development, staging, production, etc…

EC2のインスタンスそれぞれにタグの設定を入れている。
それぞれのインスタンスはAutoScalingGroup管理下にあり、
上記タグもそれぞれのAutoScalingGroupにてインスタンス起動時に付与するようになっている。

起動時に浮いたEIPをアサインさせたい

Ref: Qiita:AmazonLinuxのcloud-initについての調査メモ

cloud-initのいい感じのオフィシャルドキュメントってどこにあるんだ…

  • /var/lib/cloud/scripts/per-boot/004_assign-elastic-ip.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#!/usr/bin/env ruby

#
# 基本的に 各Role に EIP を付与するインスタンスは 2台 毎
# 
#

INSTANCEID  = `curl -s http://169.254.169.254/latest/meta-data/instance-id/`

REGION      = 'ap-northeast-1'
ROLE        = `aws --region #{REGION} ec2 describe-instances \
                 --instance-ids #{INSTANCEID} \
                 --output text \
                 --query 'Reservations[].Instances[].Tags[?Key==\`Role\`].[Value]' \
                 `.chomp
STAGE       = `aws --region #{REGION} ec2 describe-instances \
                 --instance-ids #{INSTANCEID} \
                 --output text \
                 --query 'Reservations[].Instances[].Tags[?Key==\`Stage\`].[Value]' \
                 `.chomp

# foo, bar以外はEIPの付与はないので一旦この条件を設定する
exit 0 unless ROLE == 'foo' || ROLE == 'bar'

# 浮いたEIPを入れる変数
elasticip_allocation_ids = []

# ROLE と STAGE 毎に保持している EIP は違う
# TODO: hash or json
case ROLE
when 'foo'
  if STAGE == 'development'
    elasticip_allocation_ids = ['eipalloc-XXXXXXXX', 'eipalloc-XXXXXXXX']
  elsif STAGE == 'staging'
    elasticip_allocation_ids = ['eipalloc-XXXXXXXX', 'eipalloc-XXXXXXXX']
  else
    exit 0
  end
when 'bar'
  if STAGE == 'production'
    elasticip_allocation_ids = ['eipalloc-XXXXXXXX']
  elsif STAGE == 'staging'
    elasticip_allocation_ids = ['eipalloc-XXXXXXXX']
  else
    exit 0
  end
when 'baz'
  if STAGE == 'production'
    elasticip_allocation_ids = ['eipalloc-XXXXXXXX']
  elsif STAGE == 'staging'
    elasticip_allocation_ids = ['eipalloc-XXXXXXXX']
  else
    exit 0
  end
else
  exit 0
end

elasticip_allocation_ids.each do |eip_id|
  # 対象のEIPにEC2が紐付いているか確認(浮いたEIPを探す)
  assigned_instance_id = `aws --region #{REGION} ec2 describe-addresses \
                            --allocation-ids #{eip_id} \
                            | jq '.Addresses[].InstanceId' \
                            `.chomp

  # 浮いたEIPがあれば付与する処理へ移る
  next unless assigned_instance_id == 'null'

  # EIPを付与する
  `aws --region #{REGION} ec2 associate-address \
     --allocation-id #{eip_id} \
     --instance-id #{INSTANCEID}`
  puts "COMPLETE: associate-address --allocation-id #{eip_id} --instance-id #{INSTANCEID}"
  exit 0
end

puts "CANNOT ASSOCIATE EIP to `hostname`"
exit 1

という感じで/var/lib/cloud/scripts/per-boot/配下にスクリプトを置いている。

問題があったのでfluentdでsigdumpを使いstactraceしてmackerel-client-rubyにPRした話

みんなのネットワーク環境が安定しているのか..
我々の世界線にノイズが混在してしまっているのか…

それを調べるすべはないが、下記のような問題があった。

  • mackerelで突然グラフが表示されなくなる
  • そのグラフを表示しているのはfluent-plugin-mackerelを利用してfluentd経由で作成している
  • そのtd-agentは再起動しようとするとTimeout errorになる

ということで怪奇現象を解決する為にやったことをメモ

愚直にtd-agentの再起動を試みてみる

1
2
3
4
5
6
7
[watashi@example-host ~]$ 
[watashi@example-host ~]$ 
[watashi@example-host ~]$ sudo service td-agent restart
Restarting td-agent:

Timeout error occurred trying to stop td-agent...                                          [  OK  ]
[watashi@example-host ~]$ 

ダメや

fluentdのコミッターの@sonotsさんに

  • ログは出ない
  • デーモンは生きている

そんな現象に出会ったことない?と聞いたところ
fluentdにはsigdumpが入っているから
そこでstacktraceを追ってみれば、と意識の高いお返事を頂いたので実行してみる。

kill -CONT

ドキュメントに書いてあるようにCONTのシグナルを送る

1
2
3
4
5
6
7
8
9
10
[watashi@example-host ~]$ ps auxwwwf | grep td-agent
td-agent  7779  0.0  0.3 241756 26700 ?        Sl   May27   0:00 /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --log /var/log/td-agent/td-agent.log --use-v1-config --group td-agent --daemon /var/run/td-agent/td-agent.pid
td-agent  7915  0.3  3.7 838976 288956 ?       Sl   May27 225:44  \_ /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --log /var/log/td-agent/td-agent.log --use-v1-config --group td-agent --daemon /var/run/td-agent/td-agent.pid
[watashi@example-host ~]$ 
[watashi@example-host ~]$ sudo kill -CONT 7915
[watashi@example-host ~]$ 
[watashi@example-host ~]$ ps auxwwwf | grep td-agent
td-agent  7779  0.0  0.3 241756 26836 ?        Sl   May27   0:00 /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --log /var/log/td-agent/td-agent.log --use-v1-config --group td-agent --daemon /var/run/td-agent/td-agent.pid
td-agent  7915  0.3  3.7 838976 288956 ?       Sl   May27 225:44  \_ /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --log /var/log/td-agent/td-agent.log --use-v1-config --group td-agent --daemon /var/run/td-agent/td-agent.pid
[watashi@example-host ~]$

sigdumpができあがっている

1
2
3
4
[watashi@example-host ~]$ ls -la /tmp/
total 1048
-rw-rw-rw-  1 td-agent td-agent    5937 Jul  7 10:51 sigdump-7915.log
[watashi@example-host ~]$

sigdumpの中身を見てみる

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
[watashi@example-host ~]$ sudo view /tmp/sigdump-7915.log
Sigdump at 2016-07-07 10:52:00 +0900 process 7915 (/usr/sbin/td-agent)
  Thread #<Thread:0x007fce4f19e658> status=run priority=0
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/sigdump-0.2.3/lib/sigdump.rb:39:in `backtrace'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/sigdump-0.2.3/lib/sigdump.rb:39:in `dump_backtrace'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/sigdump-0.2.3/lib/sigdump.rb:25:in `block in dump_all_thread_backtrace'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/sigdump-0.2.3/lib/sigdump.rb:24:in `each'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/sigdump-0.2.3/lib/sigdump.rb:24:in `dump_all_thread_backtrace'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/sigdump-0.2.3/lib/sigdump.rb:16:in `block in dump'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/sigdump-0.2.3/lib/sigdump.rb:119:in `open'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/sigdump-0.2.3/lib/sigdump.rb:119:in `_open_dump_path'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/sigdump-0.2.3/lib/sigdump.rb:14:in `dump'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/sigdump-0.2.3/lib/sigdump.rb:7:in `block in setup'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/agent.rb:102:in `call'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/agent.rb:102:in `join'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/agent.rb:102:in `block in shutdown'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/agent.rb:102:in `each'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/agent.rb:102:in `shutdown'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/root_agent.rb:131:in `block in shutdown'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/root_agent.rb:130:in `each'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/root_agent.rb:130:in `shutdown'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/engine.rb:229:in `shutdown'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/engine.rb:200:in `run'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/supervisor.rb:597:in `run_engine'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/supervisor.rb:148:in `block in start'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/supervisor.rb:352:in `call'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/supervisor.rb:352:in `main_process'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/supervisor.rb:325:in `block in supervise'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/supervisor.rb:324:in `fork'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/supervisor.rb:324:in `supervise'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/supervisor.rb:142:in `start'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/command/fluentd.rb:171:in `<top (required)>'
      /opt/td-agent/embedded/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:54:in `require'
      /opt/td-agent/embedded/lib/ruby/site_ruby/2.1.0/rubygems/core_ext/kernel_require.rb:54:in `require'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/bin/fluentd:6:in `<top (required)>'
      /opt/td-agent/embedded/bin/fluentd:23:in `load'
      /opt/td-agent/embedded/bin/fluentd:23:in `<top (required)>'
      /usr/sbin/td-agent:7:in `load'
      /usr/sbin/td-agent:7:in `<main>'
  Thread #<Thread:0x007fce4f1910c0> status=sleep priority=0
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/output.rb:165:in `sleep'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/output.rb:165:in `wait'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/output.rb:165:in `cond_wait'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/output.rb:149:in `run'
  Thread #<Thread:0x007fce4f192880> status=sleep priority=0
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/cool.io-1.4.2/lib/cool.io/loop.rb:88:in `run_once'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/cool.io-1.4.2/lib/cool.io/loop.rb:88:in `run'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/plugin/out_forward.rb:185:in `run'
  Thread #<Thread:0x007fce4f18eb40> status=sleep priority=0
      /opt/td-agent/embedded/lib/ruby/2.1.0/net/http.rb:923:in `connect'
      /opt/td-agent/embedded/lib/ruby/2.1.0/net/http.rb:923:in `block in connect'
      /opt/td-agent/embedded/lib/ruby/2.1.0/timeout.rb:75:in `timeout'
      /opt/td-agent/embedded/lib/ruby/2.1.0/net/http.rb:923:in `connect'
      /opt/td-agent/embedded/lib/ruby/2.1.0/net/http.rb:863:in `do_start'
      /opt/td-agent/embedded/lib/ruby/2.1.0/net/http.rb:852:in `start'
      /opt/td-agent/embedded/lib/ruby/2.1.0/net/http.rb:1375:in `request'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/adapter/net_http.rb:82:in `perform_request'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/adapter/net_http.rb:40:in `block in call'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/adapter/net_http.rb:87:in `with_net_http_connection'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/adapter/net_http.rb:32:in `call'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/rack_builder.rb:139:in `build_response'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/connection.rb:377:in `run_request'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/connection.rb:177:in `post'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/mackerel-client-0.1.0/lib/mackerel/client.rb:108:in `post_service_metrics'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluent-plugin-mackerel-0.1.3/lib/fluent/plugin/out_mackerel.rb:161:in `send'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluent-plugin-mackerel-0.1.3/lib/fluent/plugin/out_mackerel.rb:151:in `write'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/buffer.rb:345:in `write_chunk'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/buffer.rb:324:in `pop'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/output.rb:329:in `try_flush'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/output.rb:140:in `run'
  
  ...
  
    GC stat:
      count: 59808
      heap_used: 261
      heap_length: 261
      heap_increment: 0
      heap_live_slot: 105333
      heap_free_slot: 1061
      heap_final_slot: 0
      heap_swept_slot: 26253
      heap_eden_page_length: 261
      heap_tomb_page_length: 0
      total_allocated_object: 2536413815
      total_freed_object: 2536308482
      malloc_increase: 3756384
      malloc_limit: 16777216
      minor_gc_count: 58261
      major_gc_count: 1547
      remembered_shady_object: 2178
      remembered_shady_object_limit: 2276
      old_object: 62144
      old_object_limit: 112630
      oldmalloc_increase: 3800672
      oldmalloc_limit: 16777216
  Built-in objects:
   106,394: TOTAL
    47,172: T_STRING
    21,189: T_DATA
    16,574: T_ARRAY
     6,805: T_NODE
     3,221: T_OBJECT
     3,064: T_CLASS
     2,418: T_HASH
     1,910: T_FILE
     1,300: FREE
       736: T_ICLASS
       719: T_REGEXP
       701: T_STRUCT
       287: T_MATCH
       168: T_MODULE
        61: T_BIGNUM
        59: T_RATIONAL
         9: T_FLOAT
         1: T_COMPLEX
[watashi@example-host ~]$

よくわからんが読んで見る

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
  Thread #<Thread:0x007fce4f18f1a8> status=sleep priority=0
      /opt/td-agent/embedded/lib/ruby/2.1.0/net/http.rb:923:in `connect'
      /opt/td-agent/embedded/lib/ruby/2.1.0/net/http.rb:923:in `block in connect'
      /opt/td-agent/embedded/lib/ruby/2.1.0/timeout.rb:75:in `timeout'
      /opt/td-agent/embedded/lib/ruby/2.1.0/net/http.rb:923:in `connect'
      /opt/td-agent/embedded/lib/ruby/2.1.0/net/http.rb:863:in `do_start'
      /opt/td-agent/embedded/lib/ruby/2.1.0/net/http.rb:852:in `start'
      /opt/td-agent/embedded/lib/ruby/2.1.0/net/http.rb:1375:in `request'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/adapter/net_http.rb:82:in `perform_request'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/adapter/net_http.rb:40:in `block in call'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/adapter/net_http.rb:87:in `with_net_http_connection'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/adapter/net_http.rb:32:in `call'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/rack_builder.rb:139:in `build_response'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/connection.rb:377:in `run_request'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/faraday-0.9.2/lib/faraday/connection.rb:177:in `post'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/mackerel-client-0.1.0/lib/mackerel/client.rb:108:in `post_service_metrics'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluent-plugin-mackerel-0.1.3/lib/fluent/plugin/out_mackerel.rb:161:in `send'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluent-plugin-mackerel-0.1.3/lib/fluent/plugin/out_mackerel.rb:151:in `write'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/buffer.rb:345:in `write_chunk'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/buffer.rb:324:in `pop'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/output.rb:329:in `try_flush'
      /opt/td-agent/embedded/lib/ruby/gems/2.1.0/gems/fluentd-0.12.20/lib/fluent/output.rb:140:in `run'

fluent-plugin-mackerelfaradayという文字列が見える

mackerel-client-rubyにPRを送る

pull/24のやりとりがそれ

faradaytimeoutのオプションがなかったので足した。

後処理

  • 対象サーバでmackerel-client-rubyをバージョンアップ
1
2
3
4
5
6
7
8
9
10
11
12
13
14
[watashi@example-host ~]$
[watashi@example-host ~]$ sudo /opt/td-agent/embedded/bin/gem update mackerel-client
Updating installed gems
Updating mackerel-client
Fetching: mackerel-client-0.1.1.gem (100%)
Successfully installed mackerel-client-0.1.1
Parsing documentation for mackerel-client-0.1.1
Installing ri documentation for mackerel-client-0.1.1
Installing darkfish documentation for mackerel-client-0.1.1
Done installing documentation for mackerel-client after 0 seconds
Parsing documentation for mackerel-client-0.1.1
Done installing documentation for mackerel-client after 0 seconds
Gems updated: mackerel-client
[watashi@example-host ~]$
  • 対象のプロセスを始末してデーモンを起動
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[watashi@example-host ~]$ kill 7915
[watashi@example-host ~]$ ps auxwwwf | grep td-agent
td-agent  7779  0.0  0.3 241756 26836 ?        Sl   May27   0:00 /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --log /var/log/td-agent/td-agent.log --use-v1-config --group td-agent --daemon /var/run/td-agent/td-agent.pid
td-agent  7915  0.3  3.7 838976 288956 ?       Sl   May27 225:44  \_ /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --log /var/log/td-agent/td-agent.log --use-v1-config --group td-agent --daemon /var/run/td-agent/td-agent.pid
[watashi@example-host ~]$
[watashi@example-host ~]$ kill 7779
[watashi@example-host ~]$ ps auxwwwf | grep td-agent
td-agent  7779  0.0  0.3 241756 26836 ?        Sl   May27   0:00 /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --log /var/log/td-agent/td-agent.log --use-v1-config --group td-agent --daemon /var/run/td-agent/td-agent.pid
td-agent  7915  0.3  3.7 838976 288956 ?       Sl   May27 225:44  \_ /opt/td-agent/embedded/bin/ruby /usr/sbin/td-agent --log /var/log/td-agent/td-agent.log --use-v1-config --group td-agent --daemon /var/run/td-agent/td-agent.pid
[watashi@example-host ~]$
[watashi@example-host ~]$ kill -9 7915
[watashi@example-host ~]$ kill -9 7779
[watashi@example-host ~]$ ps auxwwwf | grep td-agent
[watashi@example-host ~]$
[watashi@example-host ~]$
[watashi@example-host ~]$ sudo  service td-agent start
Starting td-agent:                                         [  OK  ]
[watashi@example-host ~]$

ログやmackerelなどで問題なく出力がされているか確認する。

サービスを利用させてもらっている側もこのように地味なところで貢献できるので
何かあったら色々とやってみよう💪

Terraformを始める上でのresourceの命名規則について

Terraformとは

https://www.terraform.ioここ見てください。
INFRASTRUCTURE AS CODEと書いてあります。

何が便利か

たとえばAWSの新規VPCの作成など画面ポチポチで設定していくオペレーションをコードに落とせる。

それってAPI叩けば同じでは?
PaaSが色々対応している。MySQLにも対応しているの…

伝えたいこと

たとえばVPCを構築するとして

1
2
3
4
5
6
7
8
9
10
resource "aws_vpc" "${var.prefix}-${var.environment_name}-vpc" {
    cidr_block           = "${var.vpc.cidr_block}"
    enable_dns_hostnames = true
    enable_dns_support   = true
    instance_tenancy     = "default"

    tags {
        "Name" = "${var.environment_name}-vpc"
    }
}

などとresource名をユニークな感じでやろうとしたのだけれど

by designと言われていたので、なんだか使いづらいな〜と考えていた。が

そうなのだ。そもそもこの発想で良く、resourceはあくまでTerraform内での管理するためだけの命名であるので

  • vpc.tf
1
2
3
4
5
6
7
8
9
10
resource "aws_vpc" "main-vpc" {
    cidr_block           = "${var.vpc.cidr_block}"
    enable_dns_hostnames = true
    enable_dns_support   = true
    instance_tenancy     = "default"

    tags {
        "Name" = "${var.environment_name}-vpc"
    }
}

このようにName Tagsでユニークな情報を付与すれば良かった。
このことに気付かずresourceにひたすらvariableの値を入れようと頑張っていた。

結局、上記のようにresourceにユニークな情報を入れない仕組みで汎用性は担保できた。
これで似たような環境も

  • vpc.tf
1
2
3
4
5
6
7
8
9
10
# Create Subnet
# - ec2:CreateSubnet
resource "aws_subnet" "some-subnet-a" {
    vpc_id            = "${aws_vpc.main-vpc.id}"
    cidr_block        = "${var.vpc.public_subnet_a}"
    availability_zone = "${var.availability_zone.a}"
    tags {
        Name = "${var.environment_name}-some-subnet-a"
    }
}
  • variables.tf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
variable "region" {
    default = "ap-northeast-1"
}

variable "environment_name" {
    default = "development"
}

variable "availability_zone" {
    default = {
        a = "ap-northeast-1a"
        c = "ap-northeast-1c"
    }
}

variable "vpc" {
    default = {
        cidr_block    = "10.200.0.0/16"
        some_subnet_a = "10.200.210.0/24"
        some_subnet_c = "10.200.211.0/24"
    }
}

上記のようにvariables.tfなどと値を別のファイルに分けておくことで
汎用的なテンプレートが作成可能となる。しかし便利だな〜