helen's blog

ずっとおもしろいことしてたいな。

なぜか公式ドキュメントのどのコマンドでもDatadog Agentが再起動できない

全部試してだめだったときにとても困っちゃったよね

# こういうとき
$ sudo service status datadog-agent
status: 認識されていないサービスです。

Datadog Agent の公式ドキュメント

docs.datadoghq.com

やってたこと

Amazon Linuxを使用しているので下記でインストールします

DD_API_KEY=<YOUR_API_KEY> bash -c "$(curl -L https://raw.githubusercontent.com/DataDog/datadog-agent/master/cmd/agent/install_script.sh)"

これはDatadogにログインして表示されるコマンドです
https://app.datadoghq.com/account/settings#agent/aws

これでインストールするとなぜか公式ドキュメントのどのコマンドでも再起動できない
どうしたものか・・と思ってルートディレクトリを見ると
ddagent-install.log というファイルが存在することに気づきました

そのファイルをぼんやり眺めると・・

Your Agent is running and functioning properly. It will continue to run in the
background and submit metrics to Datadog.

If you ever want to stop the Agent, run:

    sudo stop datadog-agent

And to run it again run:

    sudo start datadog-agent

見たことないコマンドだ・・・と思って実行すると停止と起動ができます

$ which datadog-agent
/usr/bin/datadog-agent

こういうことのようだ

ちなみに

$ ls /usr/bin/dd-agent
/usr/bin/dd-agent

こういうのもいたけど

$ dd-agent status
The deprecated binary 'dd-agent' is no longer provided. 
Please use the 'datadog-agent' binary instead.

でもこういうふうに怒られる

コマンドの順序を入れ替えて datadog-agent start とかするとコンソールを奪われる😇

よく見るとおもしろいね

Amazon Auroraでレプリケーションのために出力していたbinlogを止めるには

AuroraをオンプレミスのMySQLレプリケーションしていたけど
それが不要になってお片付けをしていたら
想定外のところで詰まってしまいサポートに問い合わせました

Auroraとのレプリケーション方法

binlogを出力する

公式に手順があります

docs.aws.amazon.com

クラスタのパラメータグループで binlog_format を ROW, STATEMENT, MIXEDのどれかにします
設定の反映にはAuroraクラスタの再起動が必要です

レプリケーションの撤去

binlogを停止する

先の手順にあるように、クラスタのパラメータグループで binlog_format を OFF にします
同様に反映にはAuroraクラスタの再起動が必要です

レプリケーション自体は STOP SLAVE; で止まるのですが、
binlogを出力しているとAuroraの性能に影響がでてしまうため
必要なくなったのであれば止めておくべきです

うまくいかなかった

わたしのところでは、今回、binlog_formatをMIXEDにしていました
クラスタのパラメータグループを編集し、
再起動など諸々を実施してもOFFになりませんでした

# なぜか STATEMENT になる
# もちろん再起動前はMIXEDでした
mysql> SHOW VARIABLES LIKE 'binlog_format';
+---------------+-----------+
| Variable_name | Value     |
+---------------+-----------+
| binlog_format | STATEMENT |
+---------------+-----------+
1 row in set (0.00 sec)

# 停止しているかのようなメッセージは出る
mysql> show binary logs;
ERROR 1381 (HY000): You are not using binary logging

サポートさんに問い合わせるまでに実施したこと

どれも状況は変わりませんでした

問い合わせた結果

  • binlog_format にOFFを設定すると log-bin は無効になる
  • ただし、 binlog_format の設定値によらず無効になっている
  • SHOW VARIABLES LIKE 'log_bin' が OFF になっていれば良い

とてもややこしいけれど、
binlog_formatを変更するとlog_binも変更され、
2つのパラメータで管理されているそうです

つまり

binlog_format は OFF になっていないけどbinlogは停止できていた!

mysql> SHOW VARIABLES LIKE 'log_bin'\G
*************************** 1. row ***************************
Variable_name: log_bin
        Value: OFF
1 row in set (0.00 sec)

サポートさんに確認してよかった〜

log_bin がOFFになっているのを見ても
binlog_format が OFF にならないんですけど!? って問い合わせしちゃいそう😅

おまけ

今回、レプリケーションのためのbinlog停止とともに、
Auroraインスタンスのスケールダウンとファミリー変更を行いました

事前に binlog_format を OFF にしておけば
改めて再起動は不要になる(スケールダウン作業中に適応される)のは学びでした

再起動の瞬断とはいえ、サービスのダウンする瞬間を減らせてよかった😊

Mackerelコンテナエージェントをちょっとだけ触りました

mackerel.io

待望の機能がリリースされてたのでちょっとだけ試します

用意したもの

  • Mackerel (しかもアンバサダーだよ!!!🌸😏🌸)
  • AWS Fargate 一式
    • なにかの検証で作って放置してたのを使いまわします
  • https://hub.docker.com/r/kennethreitz/httpbin/
    • お手軽に status 200 を用意するのによく使わせてもらっているやつ

手順

mackerel.io

サイドカーでコンテナエージェントを起動するだけなのでめっちゃ簡単
APIキーはパラメータストアとかで入れたほうが良さそう

起動する

AWS

f:id:heleeen:20190219005842p:plain

起動してるタスクが1つ

Mackerel

f:id:heleeen:20190219010227p:plain

タスクIDをホスト名としてタスク単位で登録される
設定項目にも見当たらないから手で入れるしかないのかな・・?

Fargate instance info

テーブルの一番右に気になるものがありました

Cluster	arn:aws:ecs:ap-northeast-1:ACCOUNT_ID:cluster/test
Task	32b720e1-b1f2-47e7-9b72-f8ae8ab30cee
Task Family	test
Task Version	6
Task ARN	arn:aws:ecs:ap-northeast-1:ACCOUNT_ID:task/32b720e1-b1f2-47e7-9b72-f8ae8ab30cee

Containers
Name: httpbin
Docker Name: ecs-test-6-httpbin-809d8593fab9ddd29101
Docker ID: 8aab519510a34f27de12b330861c615b60277b2ae26f0f73c7cd36da249acce7

Name: ~internal~ecs~pause # なんだこれ
Docker Name: ecs-test-6-internalecspause-d8c98efc81faf4d5a501
Docker ID: cfe07bc7071f847d01c7997016c6103af2e825303aeefb7cfac976faffbf3963

Name: mackerel-container-agent
Docker Name: ecs-test-6-mackerel-container-agent-bcdab3c995fffaecc401
Docker ID: 2246210032f1f619fb81d418df2bcd38c84d01134660a8200787213d4cf3f254

Known status	RUNNING
Desired status	RUNNING

httpbin が検証用につかっているstatus 200を返してくれるコンテナ、
mackerel-container-agent がコンテナエージェント、
~internal~ecs~pause は特に何か操作したものではありません

~internal~ecs~pause とは

aws.amazon.com

ネットワークスタックとアプリケーションコンテナのコマンドが競合しないように
まずECSエージェントがコンテナ開始前にpauseコンテナをタスクごとに作成する
次にCNIプラグインを実行してpauseコンテナの名前空間を用意し、
タスク定義内のコンテナを起動してpauseコンテナのネットワークスタックを共有する
タスク定義内のすべてのコンテナがENIによるIPアドレスを指定でき、
localhostで通信することができることを表す

なるほど?

グラフ

CPU

一番Poorなスペックでこれ
コンテナエージェントが全然CPU消費してない👀

f:id:heleeen:20190219025559p:plain

Memory

メモリも同様
だけどpauseコンテナが地味に存在感を出していて侮れないなぁ

f:id:heleeen:20190219025730p:plain

Mackerelコンテナエージェントの
設定ファイルがWeb経由やS3配置で取れるのがおもしろくて
apikeyがなければGitHubに設定ファイル入れてRawで取得して使えそう🤔

Mackerelアンバサダーになりました

わーい😁

f:id:heleeen:20190213002523p:plain

この見栄えのためにOrganizationのアイコンを設定しました😅

Mackerelアンバサダーとは

mackerel.io

要するに

  • 個人では試しづらかったMackerelの有償機能も無料で使わせていただける🎉
  • ノベルティがもらえる🙌
  • ブログなどでアウトプットしてMackerelにより貢献できる💪
  • ※ アンバサダーになったことの公開はOKだそうです

Win-Winですね😊

わたしのMackerel Organization

いつの日かハムスターと温度と湿度を見守ってくれていたラズパイは
今は別の用途で使われていますが、Mackerelエージェントは動かしています

Mackerelアンバサダーになった今日、突然アラートがあがりました

f:id:heleeen:20190213011426p:plain

以前からいつの間にかsshできなくなっていることがあったので
今度は何が起こったんだ..と思いながら再起動しちゃいました
繋げれるやつ持ってないんです😢

github.com

これと同じ現象だったので同じ対応を入れて数日様子を見ることにしました

Mackerelエージェントをアップデートする

最初にMackerelエージェントを入れてからそのままであり
いい機会なのでエージェントをアップデートします

現状

$ /usr/local/bin/mackerel-agent version
mackerel-agent version 0.47.3 (rev 4334e86) [linux arm go1.9.2]

Raspberry Pi なので Releases · mackerelio/mackerel-agent · GitHub から
mackerel-agent_linux_arm.tar.gz をwgetして再配置して再起動

f:id:heleeen:20190213023105p:plain

バイナリなので簡単ですね

0.47.3 から 0.59.0 へ

アップデートを放置していた間にいろいろ変わりました

Memory使用率の算出方法が変わる

mackerel.io

f:id:heleeen:20190213024404p:plain

グラフはこんな感じになりました

インストールに際して

貧弱なディスクしかないので一応気にしてる

圧縮ファイル

1.3Mほど大きくなっています

2.4M Nov 28  2017 0_47_mackerel-agent_linux_arm.tar.gz
3.7M Jan 10 07:00 0_59_mackerel-agent_linux_arm.tar.gz

エージェント

エージェント自体のファイルサイズ0.5M増、
あといろんなファイルが増えていました

# 0.59.0
total 6.8M
19K Jan 10 06:52 CHANGELOG.md
10K Jan 10 06:52 LICENSE
13K Jan 10 06:52 LICENSE.rtf
2.2K Jan 10 06:52 README.md
6.8M Jan 10 06:57 mackerel-agent
3.6K Jan 10 06:55 mackerel-agent.conf

# 0.47.3
total 6.3M
2.2K Nov 28  2017 README.md
6.2M Nov 28  2017 mackerel-agent
3.6K Nov 28  2017 mackerel-agent.conf

ラズパイの掃除しないとDiskが危ういなぁ...

アンバサダープログラム使い倒すぞ٩(๑`^´๑)۶

AWSのAuto ScalingでTarget Tracking Scaling PolicyのALBRequestCountPerTargetを本番試用した

自分が初めて使った Amazon EC2 Auto Scaling についてのログと感想を残します

Auto Scaling

Auto ScalingはEC2やRDSなどのサービスに対し、正常なインスタンス数を保ったり
スケジュール・負荷に合わせてスケーリングしてくれるAWSの便利サービスです
もちろん手動でのインスタンス増減も対応していて、
ヘルスチェック、Warming time、Instance Drawningを利用して安全に増減させてくれます

Amazon EC2 Auto Scaling の動的スケーリングとして現在3つのスケーリングポリシーがあります

Target tracking scaling: 
  特定のメトリクスのターゲット値に基づいて、グループの現在の容量を増減させます。
  これはサーモスタットで家の温度を管理する方法と似ています(温度を選択すれば、後はサーモスタットがすべてを実行する)。
Step scaling:
  アラーム超過のサイズに応じて変動する一連のスケーリング調整値(ステップ調整値)に基づいて、
  グループの現在の容量を増減させます。
Simple scaling: 
  1つのスケーリング調整値に基づいて、グループの現在の容量を増減させます。 
https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/as-scale-based-on-demand.html

そして続けてこんな記載があります

If you are scaling based on a utilization metric 
that increases or decreases proportionally to the number of instances in an Auto Scaling group,
we recommend that you use target tracking scaling policies. 
Otherwise, we recommend that you use step scaling policies.

インスタンスの使用率に基づく場合はTarget Tracking Policy、
そうでなければStep Scaling Policyがおすすめだそうです

今回はインスタンスのキャパシティがわかっていたため Target Tracking Policyを選択してみたくなりました

Simple Scale, Step Scale

Target Tracking Policyは2017/7/12にリリースされました
Introducing Target Tracking Scaling Policies for Auto Scaling

それまでに追加されていたポリシーはSimple Scale Policyとして扱われます

スケーリングアクティビティまたはヘルスチェック交換の最中でも、
アラームを継続的に評価し、グループをロックしない

という点から、Simple Scale PolicyよりStep Scaling, Target Tracking Scalingが推奨されています

Step Scaling, Target Tracking Scalingは

Auto Scaling グループ内のインスタンス数に比例して増減するメトリクスに基づいてスケールする場合は、
代わりにターゲット追跡スケーリングポリシーを使用することをお勧めします

という基準があります
ちなみにAWSコンソールからEC2 Auto Scale Policyを追加するとデフォルトはTarget Tracking Policyになっています
日本語では"ターゲット追跡スケーリングポリシー"などと表記されます

docs.aws.amazon.com

Target Tracking Scale

Target Tracking Scaleの特徴は下記です

ターゲットの追跡スケーリングポリシーは、メトリクスをターゲット値近くに維持することに加えて、
負荷パターンの変動によるメトリクスの変動に合わせて調整し、
Auto Scaling グループの容量の急速な変動を最小化します。
https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/as-scaling-target-tracking.html

このドキュメントでの "事前定義されたメトリクス" は現在4つあります

ASGAverageCPUUtilization: 
  average CPU utilization of the Auto Scaling group
ASGAverageNetworkIn: 
  average number of bytes received on all network interfaces by the Auto Scaling group
ASGAverageNetworkOut: 
  average number of bytes sent out on all network interfaces by the Auto Scaling group
ALBRequestCountPerTarget: 
  number of requests completed per target in an Application Load Balancer target group
https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/APIReference/API_PredefinedMetricSpecification.html

事前定義されたメトリクスを使用する場合、CloudWatchAlarmの作成も自動で行われます
Alarmを定義しなくて済むのはすごく便利でした

今回はRequest数に基づいてスケールさせたかったので(本当は私のTryしてみたい思いが99.8%です)ALBRequestCountPerTargetを選択したのですが自分の理想通りになかなかいきませんでした

Terraformする

Target Tracking PolicyをTerraformするとこうなります
なお、今回のTarget Value閾値)は4200と仮定します

resource "aws_autoscaling_policy" "scale_out_policy" {
  name                      = "scale-out-policy"
  autoscaling_group_name    = "<Auto Scaling Group Name>"
  policy_type               = "TargetTrackingScaling"
  estimated_instance_warmup = "180"

  target_tracking_configuration {
    predefined_metric_specification {
      predefined_metric_type = "ALBRequestCountPerTarget"
      resource_label = "<ALB ARN Suffix>/<TargetGroup ARN Suffix>"
    }
    target_value = 4200 # ↓で使う仮のTargetValue
    disable_scale_in = true # チキンなのでScale inはDisable
  }
}

Simple Policy, Step Policyでは閾値を超えたときにインスタンスのを追加するなどの指定がありますが、
Target Tracking Policyでは閾値を超えたときの挙動をALBとターゲットグループ以外指定しません
Target Tracking Policyの場合、閾値を上回らないようにAuto Scaleしてくれるので指定する必要がありません

ALBRequestCountPerTarget

ポリシーを作成すると、CloudWatchAlarmが作成されます
ALBRequestCountPerTarget(Scaling Policy作成画面ではApplication Load Balancer Request Count Per Targetと表記されます)を選択したときに作成されるAlarmの一部をピックアップします

Title Description Value
State Details アラームの状態(OK, ALARM or INSUFFICIENT_DATA)とその理由 OK. 理由: 3データポイントがthresholdを超えていませんでした
Threshold ALARMになる条件 RequestCountPerTargetが3分間の3データポイントでthresholdを超えたとき
Statistic メトリクスの統計方法 Sum
Period データポイントの粒度 1 minute

Thresholdは

RequestCountPerTarget > 4200 for 3 datapoints within 3 minutes

などが表示されていて、
詳細モニタリングが有効になっていて1分に1回メトリクスが投稿されているとすると、
3分間に3つのデータポイントがあり、TargetValue(4200)を超えると閾値をオーバーしたとみなします

RequestCountPerTargetはCloudWatch MetricsのApplicationELB > TargetGroup内にあり、

RequestCountPerTarget
Statistics: The only valid statistic is Sum. Note that this represents the average not the sum.
https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-cloudwatch-metrics.html

StatisticのSumはSumという名の平均値になります

Alarm状態を眺める

ALARM状態になったときのState Reasonの例は下記です

Threshold Crossed: 3 datapoints [5200, 5300, 4250] were greater than the threshold (4200.0).

この[5200, 5300, 4250]はRequestCountPerTargetの値で、
ApplicationELBのRequestCountをTargetGroup内で稼働しているインスタンス数で割った数におよそ一致するはずです
[5200, 5300, 4250]のように3datapointsがthe threshold(4200)を超えるとALARMとなります

Target Valueを考える

(1秒間に捌けるリクエスト数) * 60(秒) * 係数(という気持ち)

チューニングすれば1秒間に捌けるリクエスト数が増えるし、
係数はモニタリングしながら調整かなぁとやりながら思いました
同様に総リクエスト数を考慮してAuto ScaleのMax, Minを指定します

仮に秒間100Requestsをギリギリ捌けるインスタンスをTargetとした場合、
100 * 60(1minute) = 6000のRequestCountPerTargetはギリギリ捌けることになり、
インスタンスが2台ある場合、1分間に12000リクエストをさばくことができると想定されます
そこでScale PolicyのTarget Valueを4200くらい(6000さばけるけど余裕見て0.7掛け)にしておくと、
1分間に8400Request(4200*2)を超えた状態が3分続くとスケールアウトされる計算になります

この計算が全然わからなくて苦労しました
クッ...Sumに惑わされた...

おまけ

実際にインスタンスを増減させる際にはこんな挙動も起こります

ターゲット値と実際のメトリクスデータポイント間にギャップが発生する場合があります。
これは、追加または削除するインスタンス数を決定するときに、
その数を切り上げまたは切り捨てて常に控えめに動作するためです。
これにより、不十分な数のインスタンスを追加したり、インスタンスを過剰に削除したりすることがなくなります。
https://docs.aws.amazon.com/ja_jp/autoscaling/ec2/userguide/as-scaling-target-tracking.html

結局、リクエストが瞬間的に増加するが継続時間は2,3分程度で、
スケールアウトする頃にはリクエストが落ち着いているというよくある状態になってしまいました

感想

構築時は1秒間に捌けるリクエスト数がわかっていてCPU使用率が高騰していてもさばけるときに
ALBRequestCountPerTargetを使うといいのかなぁと考えていたのですが
リクエストがバーストしてもインスタンスの各使用率が高騰せず済んでしまうほどチューニングが優秀過ぎて
余裕でアクセスをさばくインスタンス郡が増設されるだけになってしまいました😂
一度バーストするとしばらく継続される状況でAuto Scale Inもさせるなら良さそうでした

瞬間にバーストしてすぐ落ち着くサービスは難しいなぁ🤔
台数用意して耐えきるほうが現実的なのかなぁ🤔