作った。
これは何か
RDS の設定値、max_connections は PostgreSQL、MySQL ともにある。接続数がこの数値を超えるとエラーとなるため、この数値を超えないように監視できることが望ましい。
しかしこの max_connections、RDS の parameter group の value の1つであり、cloudwatch metrc に存在しない。そのため Datadog Integration でも取ることができない。
というわけでそれを取って Prometheus 形式で Export することにした。
なお、現在の接続数 database_connections
は取れる。
これとの比で、例えば9割になったら Alert みたいなことができるようになって便利。
また、新規サービスリリース前に Production Readiness Checklist でも DB の接続数大丈夫?みたいな項目があるが、それを減らすことができる。
結果
こんな感じ。まぁ Maxcon を可視化しても全然面白くはない。そうそう変わるもんではないしね。Datadog 上に metric として値が欲しかっただけである。
アラート
ここで気づくが、aws.rds.database_connections はよしなにタグに値をつけてくれるが、この Exporter でもつけている、DB Instance Identifier と DB Instance Class の Key 名を合わせないと Alert が作れない。
雑に GitHub で調べると、付与されるタグはこのように決まっていることがわかる。
RDS auto_minor_version_upgrade、dbinstanceclass、dbclusteridentifier、dbinstanceidentifier、dbname、engine、engineversion、hostname、name、publicly_accessible、secondary_availability-zone
snake case かと思ったらそうでもなかったりしてポリシーがよくわからないが、とにかく同じ tag として扱いたければ dbinstanceclass
dbclusteridentifier
に変える必要があった。
タグさえ一致させればこんな風に欲しい値が手に入った。
こんな感じで monitor を作る。
いったん低めの8割で作った。
課題
Issue にあげているが、、、
Max Connection の値の確からしさ
一応 autora-postgresql の場合、デフォルトは以下のような計算式で max connections は決まる。
Aurora PostgreSQL: "LEAST({DBInstanceClassMemory/9531392},5000)"
ただ、この計算式がイマイチ実際の default と違うような予感がしているので、要検証だと思っている。
ちなみにこの default 値の場合の instance class に対する maxcon はこのように map を持っている。
auroraPostgresMaxcon := map[string]int{ "db.r4.large": 1600, // Memory 15.25 GB "db.r4.xlarge": 3200, // Memory 30.5 GB "db.r4.2xlarge": 5000, // Memory 61 GB "db.r4.4xlarge": 5000, // Memory 122 GB "db.r4.8xlarge": 5000, // Memory 244 GB "db.r4.16xlarge": 5000, // Memory 488 GB "db.r5.large": 1800, // Memory 16 GB "db.r5.xlarge": 3600, // Memory 32 GB "db.r5.2xlarge": 5000, // Memory 64 GB "db.r5.4xlarge": 5000, // Memory 128 GB "db.r5.8xlarge": 5000, // Memory 256 GB "db.r5.12xlarge": 5000, // Memory 384 GB "db.r5.16xlarge": 5000, // Memory 384 GB "db.r5.24xlarge": 5000, // Memory 768 GB "db.m4.large": 900, // Memory 8 GB "db.m4.xlarge": 1800, // Memory 16 GB "db.m4.2xlarge": 3600, // Memory 32 GB "db.m4.4xlarge": 5000, // Memory 64 GB "db.m4.10xlarge": 5000, // Memory 160 GB "db.m4.16xlarge": 5000, // Memory 256 GB "db.m5.large": 900, // Memory 8 GB "db.m5.xlarge": 1800, // Memory 16 GB "db.m5.2xlarge": 3600, // Memory 32 GB "db.m5.4xlarge": 5000, // Memory 64 GB "db.m5.8xlarge": 5000, // Memory 128 GB "db.m5.12xlarge": 5000, // Memory 192 GB "db.m5.16xlarge": 5000, // Memory 256 GB "db.m5.24xlarge": 5000, // Memory 384 GB "db.t2.micro": 125, // Memory 1 GB "db.t2.small": 250, // Memory 2 GB "db.t2.medium": 450, // Memory 4 GB "db.t2.large": 900, // Memory 8 GB "db.t2.xlarge": 1800, // Memory 16 GB "db.t2.2xlarge": 3600, // Memory 32 GB "db.t3.micro": 125, // Memory 1 GB "db.t3.small": 250, // Memory 2 GB "db.t3.medium": 450, // Memory 4 GB "db.t3.large": 900, // Memory 8 GB "db.t3.xlarge": 1800, // Memory 16 GB "db.t3.2xlarge": 3600, // Memory 32 GB }
これが多分ちょっとあやしいので確認したい。
RDS MySQL / Aurora MySQL サポート
現状していない。
やればできると思うが、こいつらの Default もまぁ結構キモい。特に Aurora MySQL。どうしてそうなったんだろう。
Aurora MySQL: "GREATEST({log(DBInstanceClassMemory/805306368)*45},{log(DBInstanceClassMemory/8187281408)*1000})" RDS MySQL: {DBInstanceClassMemory/12582880}
正規表現マッチやってやれないことはないけど、log とかなんとか言ってるしマジ。まぁ結局 default の場合結果の値は static に持つのだけれども。
驚いたこと
max_connections は cluster parameter group と db parameter group 両方で設定できる
max connections は実は cluster parameter group と db parameter group 両方で設定できるのだが
何この地獄の仕様。。。"クラスターパラメータグループと、DBパラメータグループで重複する項目は最後に更新した方が優先的に適用されます" / 1件のコメント https://t.co/R52IegRBWi “[AWS] RDSのパラメータグループ仕様変更がクリティカルな件 | 個人利用で始めるAWS学習記” https://t.co/oD5AXgkCE2
— Takeshi Kondo (@chaspy_) February 2, 2021
あとに設定したほうが有効になるということ。知らんわ。
今回作った Exporter は DB Instance の Parameter Group を describe しているので、cluster parameter group にだけ設定しているパターンだと正しい値が取れないです。
Default はインスタンスクラスによって決まるが、それを静的な値で上書きできる
なんか全部 max はこれで決まるかと思ったけど、fixed value を入れることもできる。
そうしている場合はそちらが値に入ってるので、素直にそれを使うようになっている。
感想
Database Instance を for でぶんまわしたあとインスタンスごとに db parameter group を describe するので、loop の頻度によっては結構すぐに rate limit に達してしまう。DB Instance、いま動かしている環境だと 90 なんだけど、1分おきでたかだか3周とかで rate limit に達してたので、270 / 3min でアウトは厳しすぎない?あと rate limit 各サービスによって違うので結局調べても正しい値にたどり着けなかった。
コード的には parameter group value が default だと LEAST({DBInstanceClassMemory/9531392},5000)
こういう式が、それ以外だと static に fixed value もとりうるというところがだいぶキモかった。計算式はわかったんだけど default は素直に計算された値を parameter group の value にいれといて、、、と思った。そうすれば今回書いたような map を持つ必要はなかった。
おわりに
これで aws.rds.database_connections の anormary のアラートで、接続数が少ない DB で false positive が起きてたのをアラート消せる。めでたしめでたし。
次回
AWS Config の結果を export するやつの予定。
なんかいろいろ考えてたけど忘れた。このへんか。
AWS Config の cli を見ている。https://t.co/1iTHvw2UCf get-compliance-details-by-config-rule 該当 Rule の結果、COMPLIANT かどうか、そして対象の Resource も得られるんだけど、Resource Type "AWS::IAM::User" と ResourceId に ID だけ得られて厳しい。この ID だけでは何か識別できない。
— Takeshi Kondo (@chaspy_) February 2, 2021
であれば Rule 一覧を取って結果 Compliant / Noncompliant の数だけを metric として出して詳細は見に行ってね、ぐらいが落とし所かなあ。
— Takeshi Kondo (@chaspy_) February 2, 2021
あーこれ使えば https://t.co/6ITgk1I6o6 rule とそれに対して COMPLIANT か、NON_COMPLIANT ならその数が得られるのでいったんこれ metric にするだけでもまぁ良さそう。
— Takeshi Kondo (@chaspy_) February 2, 2021
Go sdk はこれ https://t.co/TngJw9Y8XL
— Takeshi Kondo (@chaspy_) February 2, 2021