作った。
github.com
これは何か
RDS の設定値、max_connections は PostgreSQL、MySQL ともにある。接続数がこの数値を超えるとエラーとなるため、この数値を超えないように監視できることが望ましい。
しかしこの max_connections、RDS の parameter group の value の1つであり、cloudwatch metrc に存在しない。そのため Datadog Integration でも取ることができない。
というわけでそれを取って Prometheus 形式で Export することにした。
なお、現在の接続数 database_connections
は取れる。
docs.datadoghq.com
これとの比で、例えば9割になったら Alert みたいなことができるようになって便利。
また、新規サービスリリース前に Production Readiness Checklist でも DB の接続数大丈夫?みたいな項目があるが、それを減らすことができる。
結果
こんな感じ。まぁ Maxcon を可視化しても全然面白くはない。そうそう変わるもんではないしね。Datadog 上に metric として値が欲しかっただけである。
アラート
ここで気づくが、aws.rds.database_connections はよしなにタグに値をつけてくれるが、この Exporter でもつけている、DB Instance Identifier と DB Instance Class の Key 名を合わせないと Alert が作れない。
雑に GitHub で調べると、付与されるタグはこのように決まっていることがわかる。
github.com
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 を持っている。
github.com
auroraPostgresMaxcon := map[string]int{
"db.r4.large": 1600,
"db.r4.xlarge": 3200,
"db.r4.2xlarge": 5000,
"db.r4.4xlarge": 5000,
"db.r4.8xlarge": 5000,
"db.r4.16xlarge": 5000,
"db.r5.large": 1800,
"db.r5.xlarge": 3600,
"db.r5.2xlarge": 5000,
"db.r5.4xlarge": 5000,
"db.r5.8xlarge": 5000,
"db.r5.12xlarge": 5000,
"db.r5.16xlarge": 5000,
"db.r5.24xlarge": 5000,
"db.m4.large": 900,
"db.m4.xlarge": 1800,
"db.m4.2xlarge": 3600,
"db.m4.4xlarge": 5000,
"db.m4.10xlarge": 5000,
"db.m4.16xlarge": 5000,
"db.m5.large": 900,
"db.m5.xlarge": 1800,
"db.m5.2xlarge": 3600,
"db.m5.4xlarge": 5000,
"db.m5.8xlarge": 5000,
"db.m5.12xlarge": 5000,
"db.m5.16xlarge": 5000,
"db.m5.24xlarge": 5000,
"db.t2.micro": 125,
"db.t2.small": 250,
"db.t2.medium": 450,
"db.t2.large": 900,
"db.t2.xlarge": 1800,
"db.t2.2xlarge": 3600,
"db.t3.micro": 125,
"db.t3.small": 250,
"db.t3.medium": 450,
"db.t3.large": 900,
"db.t3.xlarge": 1800,
"db.t3.2xlarge": 3600,
}
これが多分ちょっとあやしいので確認したい。
現状していない。
やればできると思うが、こいつらの 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 両方で設定できるのだが
あとに設定したほうが有効になるということ。知らんわ。
今回作った 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 するやつの予定。
docs.aws.amazon.com
なんかいろいろ考えてたけど忘れた。このへんか。