これの続き。
解決したかった課題はこれ。
AWS RDS の Engine Version を Prometheus 形式で Export することで、今何のバージョンが何個あるかが可視化できるようになった。
あとは EOL 期限になったら、近づいたらアラート発砲できればいいんだが、どのように EOL 情報を取ってくればいいか、が課題だった。
残念ながら RDS の Recommendations は API が存在しない。し、Engine version outdated
では過ぎたかどうかしかわからない。
どうする
こういう csv を持つ。
- minimum_supported_version.csv
Engine,MinimumSupportedVersion,ValidDate mysql,5.7.0,2021-02-05 postgres,9.6.0,2021-02-16 postgres,9.7.0,2022-01-18 aurora-postgresql,10.4,2022-01-31
逐一送られてくる AWS からのメールをみたら、この CSV を更新する。1年前から余裕をもって何度も送ってくるので、どうにかして気付けるだろう。
これ、何を意味しているかというと、例えば RDS MySQL の 5.6 系が 2021-02-05 で EOL となった。強制アップデートはまだ先だが、セキュリティパッチが当たらない日がこの日なので、この日に設定した。
で、この日を過ぎると、5.6 が非推奨となるため、"Minimum Supported Version" はその1つ上、5.7.0 となる。
この情報をもとに、各 RDS の Engine, Engine Version を比較し、以下の4種類の string を eol_status tag につける。
- 期限切れ: expired
- 期限の1ヶ月以内: alert
- 期限の1ヶ月以上3ヶ月以内: warning
- 期限の3ヶ月以上: ok
これで、このタグを使って、expired, alert, warning の内容に応じてアラートをしかけることができる。
本当はこの csv の中身にあたる情報を API で取得したい。
学びとか感想とか
結構めんどくさかった。
めんどくさいことを解決するためのプログラミング、普通にめんどくさいので困る。
— Takeshi Kondo (@chaspy_) February 7, 2021
Version 比較
が便利だった。
func compareEngineVersion(rdsInfo RDSInfo, minimumSupportedInfo MinimumSupportedInfo) (bool, error) { engineVersion, err := version.NewVersion(rdsInfo.EngineVersion) if err != nil { return false, fmt.Errorf("failed to declare engine version: %w", err) } minimumSupportedVersion, err := version.NewVersion(minimumSupportedInfo.MinimumSupportedVersion) if err != nil { return false, fmt.Errorf("failed to declare minimum supported version: %w", err) } return engineVersion.LessThan(minimumSupportedVersion), nil }
LessThan 以外にもいろいろある。
CSV の構造体への Parse
最初普通に1行ずつ読んであれしようと思ったけど面倒になったので少し探すと csvutil という便利そうなライブラリがあったので使った。
type MinimumSupportedInfo struct { Engine string MinimumSupportedVersion string ValidDate string } func readEOLInfoCSV() ([]MinimumSupportedInfo, error) { var eolInfos []MinimumSupportedInfo csv, err := ioutil.ReadFile("minimum_supported_version.csv") if err != nil { return []MinimumSupportedInfo{}, fmt.Errorf("failed to read CSV file: %w", err) } if err := csvutil.Unmarshal(csv, &eolInfos); err != nil { return []MinimumSupportedInfo{}, fmt.Errorf("failed to unmarshal: %w", err) } return eolInfos, nil }
Unmarshal で短くかけて良い。
Binary から見た読み込むファイルのパス
地味にハマった。こういう変更が必要だった。
csv, err := ioutil.ReadFile("minimum_supported_version.csv")
こういう風にファイルを指定していて、実行バイナリは /app/
以下にあって、そこと同じ場所に csv をおいていた。
Dockerfile の最後らへん。
COPY minimum_supported_version.csv /app/minimum_supported_version.csv ENTRYPOINT ["/app/aws-rds-engine-version-prometheus-exporter"]
この場合、ファイルパスは Dockerfile の Workfir からの相対パスになるので、no such file or directory となった。まぁそれはそうか。
/etc/
以下に csv をおいて、読み取るようにした。
なるべく絶対パスで書く方がいいんだろうな。
結果
ちゃんととれた。
空白の string が返っているのは、csv に engine 名がない場合。undefined なのは事実なのでそれでいいかと思いこうしている。
ちなみに中身は Aurora MySQL
expired なのは RDS MySQL で、近々メンテ予定しています。
これで こういう Datadog Alert が作れる。
ちゃんとアラート発火した。めでたしめでたし。
なんか metric value 変だな。。。
課題
Aurora MySQL のサポートがまだ。
ただ、そもそも EOL 情報がよくわからんというのと、Aurora MySQL の場合 engine_version が以下の2パターンあってキモい。
- engine_version="5.7.12"
- engine_version="5.7.mysql_aurora.2.07.2"
パースしたくないでござる。
ので現状サポートできてないです。
おわりに
コード書くの、まだ楽しいにはならないけど、量が質に転嫁する部分もあるだろうし、書いていればネタが浮かんでまたコードを書くというループが起きることを感じているので、今後もコード書きは継続的に続けてみる。
おしまい。