ツナワタリマイライフ

日常ネタから技術ネタ、音楽ネタまで何でも書きます。

AWS RDS の Engine Version ごとの EOL 情報からアラート通知させる

これの続き。

blog.chaspy.me

解決したかった課題はこれ。

github.com

AWS RDS の Engine Version を Prometheus 形式で Export することで、今何のバージョンが何個あるかが可視化できるようになった。

あとは EOL 期限になったら、近づいたらアラート発砲できればいいんだが、どのように EOL 情報を取ってくればいいか、が課題だった。

残念ながら RDS の Recommendations は API が存在しない。し、Engine version outdated では過ぎたかどうかしかわからない。

docs.aws.amazon.com

どうする

こういう 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 となった。強制アップデートはまだ先だが、セキュリティパッチが当たらない日がこの日なので、この日に設定した。

aws.amazon.com

で、この日を過ぎると、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 で取得したい。

学びとか感想とか

結構めんどくさかった。

Version 比較

github.com

が便利だった。

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 以外にもいろいろある。

pkg.go.dev

CSV の構造体への Parse

最初普通に1行ずつ読んであれしようと思ったけど面倒になったので少し探すと csvutil という便利そうなライブラリがあったので使った。

github.com

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 で短くかけて良い。

github.com

Binary から見た読み込むファイルのパス

地味にハマった。こういう変更が必要だった。

github.com

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 をおいて、読み取るようにした。

なるべく絶対パスで書く方がいいんだろうな。

結果

ちゃんととれた。

f:id:take_she12:20210207185609p:plain

空白の string が返っているのは、csv に engine 名がない場合。undefined なのは事実なのでそれでいいかと思いこうしている。

ちなみに中身は Aurora MySQL

expired なのは RDS MySQL で、近々メンテ予定しています。

これで こういう Datadog Alert が作れる。

f:id:take_she12:20210207191441p:plain

ちゃんとアラート発火した。めでたしめでたし。

f:id:take_she12:20210207223105p:plain

なんか metric value 変だな。。。

課題

Aurora MySQL のサポートがまだ。

ただ、そもそも EOL 情報がよくわからんというのと、Aurora MySQL の場合 engine_version が以下の2パターンあってキモい。

  • engine_version="5.7.12"
  • engine_version="5.7.mysql_aurora.2.07.2"

パースしたくないでござる。

ので現状サポートできてないです。

おわりに

コード書くの、まだ楽しいにはならないけど、量が質に転嫁する部分もあるだろうし、書いていればネタが浮かんでまたコードを書くというループが起きることを感じているので、今後もコード書きは継続的に続けてみる。

おしまい。

Ruby sshkey gem で OpenSSH 6.8 以降のデフォルトで生成される形式の private key の initialize に失敗する

背景

OpenSSH 6.8 以降と以前では ssh-keygen で生成される private key の形式が変わっている。

haruyama.blog.jp

  • Add FingerprintHash option to ssh(1) and sshd(8), and equivalent command-line flags to the other tools to control algorithm used for key fingerprints. The default changes from MD5 to SHA256 and format from hex to base64.

    FingerprintHash オプションを ssh(1) と sshd(8) に追加する. また, 鍵の指紋のために使われるアルゴリズムを制御する他のツールに 同様の指定をするコマンドラインフラグも追加する. デフォルトが MD5 から SHA256 に, 形式が hex から base64 になる.

問題

社内の内製ツールで、CircleCI の sshkey や環境変数をコード管理して適用するツールがある。そのツールが sshkey gem を使っているが、上記新形式の private key を読み込むときに以下のエラーで失敗する。

irb(main):004:0> f = File.read(File.expand_path("./openssh"))
=> "-----BEGIN OPENSSH PRIVATE KEY-----\nbbbbbbbbb (snip) ssssssssssecret\n-----END OPENSSH PRIVATE KEY-----\n"

irb(main):005:0> k = SSHKey.new(f, comment: "foo@bar.com")
Traceback (most recent call last):
        9: from /Users/chaspy/.rbenv/versions/2.6.5/bin/irb:23:in `<main>'
        8: from /Users/chaspy/.rbenv/versions/2.6.5/bin/irb:23:in `load'
        7: from /Users/chaspy/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
        6: from (irb):5
        5: from (irb):5:in `new'
        4: from /Users/chaspy/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/sshkey-1.9.0/lib/sshkey.rb:214:in `initialize'
        3: from /Users/chaspy/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/sshkey-1.9.0/lib/sshkey.rb:218:in `rescue in initialize'
        2: from /Users/chaspy/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/sshkey-1.9.0/lib/sshkey.rb:218:in `new'
        1: from /Users/chaspy/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/sshkey-1.9.0/lib/sshkey.rb:218:in `initialize'
OpenSSL::PKey::DSAError (Neither PUB key nor PRIV key)

上記 key は以下のコマンドで生成している。

ssh-keygen -t rsa -b 4096

なお、旧形式では成功する。

$ ssh-keygen -t rsa -b 4096 -m pem
irb(main):002:0> f = File.read(File.expand_path("./pem"))
=> "-----BEGIN RSA PRIVATE KEY-----\nbbbbbbb (snip) aaaaaaa\n-----END RSA PRIVATE KEY-----\n"
irb(main):003:0> k = SSHKey.new(f, comment: "foo@bar.com")
=> #<SSHKey:0x00007fa9ef87e6a0 @passphrase=nil, @comment="foo@bar.com", @directives=[], @key_object=#<OpenSSL::PKey::RSA:0x00007fa9ef87e5b0>, @type="rsa">

バージョン

  • Ruby 2.6.5
  • sshkey 1.9.0

調査

sshkey gem

エラーが発生している箇所は以下。

github.com

  # Create a new SSHKey object
  #
  # ==== Parameters
  # * private_key - Existing RSA or DSA private key
  # * options<~Hash>
  #   * :comment<~String> - Comment to use for the public key, defaults to ""
  #   * :passphrase<~String> - If the key is encrypted, supply the passphrase
  #   * :directives<~Array> - Options prefixed to the public key
  #
  def initialize(private_key, options = {})
    @passphrase = options[:passphrase]
    @comment    = options[:comment] || ""
    self.directives = options[:directives] || []
    begin
      @key_object = OpenSSL::PKey::RSA.new(private_key, passphrase)
      @type = "rsa"
    rescue
      @key_object = OpenSSL::PKey::DSA.new(private_key, passphrase)
      @type = "dsa"
    end
  end

最初の begin block でエラーとなり、resque でキャッチして DSA のところでこけてスタックトレースに出ている箇所が表示されているのだと思う。

OpenSSL::PKey::RSA.newRuby 標準ライブラリの openssl である。

github.com

が、issue を見ても似たような現象を見つけられず、そもそも Ruby のどのバージョンが openssl のどのバージョンを使っているかわかっていない。

Ruby の Version を変えてみる

irb(main):001:0> require 'sshkey'
=> true
irb(main):002:0> f = File.read(File.expand_path("./openssh"))
=> "-----BEGIN OPENSSH PRIVATE KEY-----\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAACFwAAAAdzc2gtcn\nNhAAAAAwEAAQAAAgE...
irb(main):003:0> k = SSHKey.new(f, comment: "foo@bar.com")
Traceback (most recent call last):
        9: from /Users/chaspy/.rbenv/versions/2.7.2/bin/irb:23:in `<main>'
        8: from /Users/chaspy/.rbenv/versions/2.7.2/bin/irb:23:in `load'
        7: from /Users/chaspy/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/irb-1.2.6/exe/irb:11:in `<top (required)>'
        6: from (irb):3
        5: from (irb):3:in `new'
        4: from /Users/chaspy/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/sshkey-1.9.0/lib/sshkey.rb:214:in `initialize'
        3: from /Users/chaspy/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/sshkey-1.9.0/lib/sshkey.rb:218:in `rescue in initialize'
        2: from /Users/chaspy/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/sshkey-1.9.0/lib/sshkey.rb:218:in `new'
        1: from /Users/chaspy/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/sshkey-1.9.0/lib/sshkey.rb:218:in `initialize'
OpenSSL::PKey::DSAError (Neither PUB key nor PRIV key)

再現する。

  • Ruby 2.7.2 / sshkey 2.0.0
irb(main):001:0> require 'sshkey'
=> true
irb(main):002:0> f = File.read(File.expand_path("./openssh"))
=> "-----BEGIN OPENSSH PRIVATE KEY-----\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAACFwAAAAdzc2gtcn\nNhAAAAAwEAAQAAAgE...
irb(main):003:0> k = SSHKey.new(f, comment: "foo@bar.com")
Traceback (most recent call last):
        9: from /Users/chaspy/.rbenv/versions/2.7.2/bin/irb:23:in `<main>'
        8: from /Users/chaspy/.rbenv/versions/2.7.2/bin/irb:23:in `load'
        7: from /Users/chaspy/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/irb-1.2.6/exe/irb:11:in `<top (required)>'
        6: from (irb):3
        5: from (irb):3:in `new'
        4: from /Users/chaspy/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/sshkey-2.0.0/lib/sshkey.rb:246:in `initialize'
        3: from /Users/chaspy/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/sshkey-2.0.0/lib/sshkey.rb:250:in `rescue in initialize'
        2: from /Users/chaspy/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/sshkey-2.0.0/lib/sshkey.rb:250:in `new'
        1: from /Users/chaspy/.rbenv/versions/2.7.2/lib/ruby/gems/2.7.0/gems/sshkey-2.0.0/lib/sshkey.rb:250:in `initialize'
OpenSSL::PKey::DSAError (Neither PUB key nor PRIV key)

再現する。

  • Ruby 3.0.0 / sshkey 2.0.0
irb(main):001:0> require 'sshkey'
=> true
irb(main):002:0> f = File.read(File.expand_path("./openssh"))
=> "-----BEGIN OPENSSH PRIVATE KEY-----\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAACFwAAAAdzc2gtcn\nNhAAAAAwEAAQAAAgE...
irb(main):003:0> k = SSHKey.new(f, comment: "foo@bar.com")
Traceback (most recent call last):
        9: from /Users/chaspy/.rbenv/versions/3.0.0/bin/irb:23:in `<main>'
        8: from /Users/chaspy/.rbenv/versions/3.0.0/bin/irb:23:in `load'
        7: from /Users/chaspy/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/irb-1.3.0/exe/irb:11:in `<top (required)>'
        6: from (irb):3:in `<main>'
        5: from (irb):3:in `new'
        4: from /Users/chaspy/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/sshkey-2.0.0/lib/sshkey.rb:246:in `initialize'
        3: from /Users/chaspy/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/sshkey-2.0.0/lib/sshkey.rb:250:in `rescue in initialize'
        2: from /Users/chaspy/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/sshkey-2.0.0/lib/sshkey.rb:250:in `new'
        1: from /Users/chaspy/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/sshkey-2.0.0/lib/sshkey.rb:250:in `initialize'
OpenSSL::PKey::DSAError (Neither PUB key nor PRIV key)

再現する。

sshkey に類似 issue があったのでコメントしておいた。

github.com

openssl library

さて最新の Ruby でも再現するので、openssl library の問題の可能性が高い。こっちでも再現させる。

使っているのはこれである。

docs.ruby-lang.org

irb(main):001:0' require 'openssl'
=> true
irb(main):002:0> f = File.read(File.expand_path("./openssh"))
=> "-----BEGIN OPENSSH PRIVATE KEY-----\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAACFwAAAAdzc2gtcn\nNhAAAAAwEAAQAAAgE...
irb(main):003:0> OpenSSL::PKey::RSA.new(f)
Traceback (most recent call last):
        6: from /Users/chaspy/.rbenv/versions/3.0.0/bin/irb:23:in `<main>'
        5: from /Users/chaspy/.rbenv/versions/3.0.0/bin/irb:23:in `load'
        4: from /Users/chaspy/.rbenv/versions/3.0.0/lib/ruby/gems/3.0.0/gems/irb-1.3.0/exe/irb:11:in `<top (required)>'
        3: from (irb):3:in `<main>'
        2: from (irb):3:in `new'
        1: from (irb):3:in `initialize'
OpenSSL::PKey::RSAError (Neither PUB key nor PRIV key: nested asn1 error)

再現する。

さてここからは C の世界である。

トレースが出てないので、推測だが、初期化はここではないか。

github.com

raise されてるところはここではないか。

github.com

ただ、 nested asn1 error というのがどこで出ているのかわかっていない。

repository を検索すると別の部分で同じエラーが出ているようだ。

github.com

ここでお手上げ。

まとめ

  • OpenSSL::PKey::RSA.new に失敗する
    • OpenSSL::PKey::RSAError (Neither PUB key nor PRIV key: nested asn1 error)

  • Ruby Version は 3.0.0
  • OpenSSH 7.8 以降でデフォルトで生成される Key 形式は OpenSSL で読み取ることはできなさそう
    • 試したバージョン: OpenSSH_8.1p1, LibreSSL 2.7.3

AWS ECR の Image Scan 結果を Prometheus 形式で Export する OSS 作った

作った。

github.com

いい加減思っているのだけどタイトルが長くてつらい。

でも CloudProvider - Service - Items to export - prometheus - exporter

だとやむなし?

シリーズものです。Prometheus Exporter としては 4作目。

blog.chaspy.me

blog.chaspy.me

blog.chaspy.me

これは何

AWS ECR には Image Scan 機能があり、それを "Findings" として、脆弱性や Severity Level をみることができます。

dev.classmethod.jp

クラメソさんいつもありがとう。

解決したい課題

ECR Image Scan は便利だが、まぁかなりの量が出る。

で、Severity も Critical から Information level まで様々だ。

これが Repository ✖️ Image Tag 分あるというわけで、かなりの量になる。GUI でポチポチみるより、より簡単な方法で可視化したい。

また、Severity level で Filter したり、Repository で Filter して優先度をつけたりというコントロールができるようにならないかと考えている。

f:id:take_she12:20210131184547p:plain

工夫した点

工夫というほどではない(いつもの)

IMAGE_TAG 指定を必須にした

仕様の問題だが、IMAGE_TAG 指定を必須にしました。あと現状 Image Digest での Image 指定はサポートしていません。

ユースケースを考えても特定リポジトリに対応する特定の Tag だけ見れればいいはず&Image Tag を指定しての API Call はまとめてできないので、いっそ必須にしてしまった。

あとあとで触れるがパフォーマンスの問題があるので、Image Tag で絞り込まないと結構キツい。

Pagination Support

まぁ数が多いのでちゃんと追いかけるようにした。

NextToken があれば Set、なければ終わるとすればいいだけなので楽だった。

github.com

今後改善する点

Performance

地獄の For Loop をキメてしまっているので、API Call は並行で処理できるようにしてパフォーマンスを改善する

Error Handling

この部分を switch 使えだの errors.As を使えなどと linter が言ってくるんですが

github.com

正直どうすればいいかわかってない。型アサーションは errors.As でできそうだけど、そのあと Error Name? Code? ごとに例外をキャッチしていくのをどうすればいいのかわかってない。誰かペアプロしてください。

Attributes の取得

Attributes が Key と Value をそれぞれ持った struct の List なんだけど

ecr - Amazon Web Services - Go SDK

こんな風にぐるぐるまわして switch case で取らないといけないのマジ?ってなっている。でもそんなもん?

github.com

感想

RDS のやつよりは面倒でした。あとこれもまた metric 送って眺めて味ってみないと役に立つかどうかはまだわかりません。

次回作

aws-rds-max-connections-prometheus-exporter

RDS の max connections を metric として送る。

現状、Datadog Integration ではこれらは取れていない。

いまは Connection の Anomary Detection のAlert をつけているが、False Positive に飛んできたりする。

で、max connections は parameter group の中にあってそれは API で取得できるんだが

docs.aws.amazon.com

  • MySQL: {DBInstanceClassMemory/12582880}
  • PostgreSQL: LEAST({DBInstanceClassMemory/9531392}, 5000)

マジでこういう値が入っている。

これを Parse し、Instance Class とその Memory size を取得して計算するというロジックを実装しないといけない。だるそう。

とはいえこれができると、現状の connection 数が max_con に達しそうだよ〜ってアラートが作れるので、役に立つ可能性は高いのでやる。

おしまい。

女性エンジニアのキャリアストーリーを集めた womeneng.jp 立ち上げと Netlify & hugo でハマったこと

背景

この記事を読んで

note.com

こう思い浮かんで

あおいさんとやるかーってなって

womeneng.jp 立ち上げました。

womeneng.jp

ちょっと前にこの業界の男女比であったり、男女でいうところ事実上女性がマイノリティであることであったり、そのマイノリティがゆえの不利益を何かしら被っていることであったりを考えた時期がありました。

~ Girls 系のイベントであったり、最近だと大平さん、菜穂子さん、ちょまどさんが Code Polaris を立ち上げたり、既に活躍されてる女性がこの問題の解決に向かって動いています。

chomado.com

note.com

この男女比の偏りは長期的に是正されるべきだと思います。しかしそのために、業界における圧倒的マジョリティ(情報系大学、大学院卒で、男性で、Software Engineer としてキャリアを重ねている)である自分個人に何ができるだろうとずっと考えていました。

その頃あおいさんに何かできることないですかね、って雑に相談してたことがあったりして。結局その時は何も浮かばなかったのですが、

wiroha さんの note が公開され、

ただなるべくハードルを取り除いて、自信とチャンスを与えられればもっと増えるかなぁと思ったりしています。

この考えに強く共感しました。

その頃、別の女性エンジニアの方から以下の TED の動画を教えてもらいました。

www.tedxtokyo.com

女性がエンジニアリングを職業にする割合が低いのは、その素養を養う、幼少期に与えられるおもちゃの段階で Gender 差が生まれている、それを解決するために自ら女性のためのおもちゃ会社を立ち上げた女性のエピソードでした。

wiroha さんのキャリアストーリーの共有も同様に"選択肢"を増やしてくれる取り組みだと思いました。

きっとこのムーブは続きそうだ、と思い、Static Web Site の Hosting ぐらいなら自分でもできる、と思い、あおいさんに相談して今回立ち上げに至りました。

あおいさんが寄稿してくれなかったら、やろうと言ってくれなかったら自分一人ではできなかったと思います。心から感謝します。

今後

womenengjp は GitHub の Open Repository です。Pull Request で Contribution できます。

github.com

今後は見つけ次第 Link を追加していくのをぼちぼちやろうと思っています。

また、現状は個人を特定できる形で、勇気ある方が書いてくれていますが、全員がそうではないと思っています。インタビュー形式のように、語り手の負担を下げる取り組みであったり、より匿名性が高い形でのエピソード掲載ができないか、という話をあおいさんとしています。

少しずつでいいのでキャリアストーリーの数が増え、将来、女性エンジニアになるかもしれないひとの選択肢を知る手段として役に立ち、"女性エンジニア"というくくりが必要ない世の中になればいいなと思います。

おわりに

ストーリー書いてもいいよ!とか、書いたよ!っていうひとは連絡くれたり、PR で追加いただけたり、このサイト自体を広めてくれると嬉しいです。

womeneng.jp

それでは以降は Netlify & hugo のハマりです。

ハマり

本当はもっと爆速で公開したかったのに5日間もかかってしまったのでハマったことををまとめます。

Netlify での HTTPS が有効にならない

Netlify では Netlify DNS を使っていると custom domain に対して Let's Encrypt の SSL 証明書をボタンポチるだけで準備してくれます。超便利。

が、これが24時間経っても DNS Preparation が終わらない。

サポートに問い合わせるも Community に聞いてくれと言われ、早く出したかったので Pro Plan にあげて 1on1 サポートをつけてもらった。

原因

CAA Record の設定が必要だった(?)(ただ、過去は同じドメインレジストリ、同じ Netlify の設定で、CAA Record なしでできたケースもあったので謎)

対処

以下の要領で CAA Record を Netlify DNS で作成

$ dig CAA womeneng.jp

; <<>> DiG 9.10.6 <<>> CAA womeneng.jp
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 7517
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;womeneng.jp.           IN  CAA

;; ANSWER SECTION:
womeneng.jp.        7166    IN  CAA 0 issue "letsencrypt.org"

;; Query time: 21 msec
;; SERVER: 2404:1a8:7f01:b::3#53(2404:1a8:7f01:b::3)
;; WHEN: Sun Jan 31 02:09:01 JST 2021
;; MSG SIZE  rcvd: 74

最初設定してたときはこの Issuer が間違っていた。

学んだこと

作業ログはこちら。

github.com

Preview Site で CSS が適用されない

Netlify では Pull Request を作成するごとに Preview Site が Deploy される。めちゃ便利である。が、なぜか PR 環境の場合 CSS が適用されない。

CSS を要求する url が以下のようにスラッシュが欠けていた。 js/bundle.js の前ね。

Got: Request URL: https://deploy-preview-2--naughty-mcnulty-91e54f.netlify.appjs/bundle.js Want: Request URL: https://deploy-preview-2--naughty-mcnulty-91e54f.netlify.app/js/bundle.js

Issue と PR はこれ。

github.com

github.com

.netlify.conf で build 時のコマンドを設定するわけだけど、DEPLOY_PRIME_URL がなんと preview site の場合は末尾のスラッシュを含まない。マジかよ。

docs.netlify.com

というわけで入れた。ugly な hack な気がするがしょうがない。これみんなハマらないのかな。

画像が Responsive にならない

Issue

github.com

スマホとか Window size が小さいものでみた時に画像が横幅 100% の resize されず横スクロールが必要みたいになっていてイケてない。

これはまぁもしかしたら hugo theme の upstream に contribution できることなのかもしれない。あとで Issue 起票してみよう。

css 知識 2 の知能でなんとかしました。

github.com

hugo template が custom css 使えて助かった。

2021-01-31 追記

template のほうに PR を投げて merge されました。良い話だ。

github.com

AWS RDS の Engine と Engine Version を Prometheus 形式で Export する OSS 作った

作った。

github.com

きっかけとしては、1月いっぱいに RDS の upgrade をしろというお達しが AWS からきていた件。

  • 廃止対象の PostgreSQL マイナーバージョン - 9.6.8, 9.6.9, 9.6.11, 9.6.12, 最低限必要な推奨バージョン - 9.6.16

  • 廃止対象の PostgreSQL マイナーバージョン - 10.4, 10.5, 10.6, 10.7, 最低限必要な推奨バージョン - 10.11

  • 廃止対象の PostgreSQL マイナーバージョン - 11.4, 最低限必要な推奨バージョン - 11.6

で、あわててあげたわけだが、結構前から通知がきていた。

このバージョンが Datadog にきていればバージョンによってはアラートをつけたりできなくもない?っていうのが発想。でもまぁ結局その AWS のお達しに気付けなければどれがヤバいか気付けないし、何バージョン離れてたところでやばいとか判断できない気もするが。。。まぁとりあえず送ってみることに。

こんな感じ。

f:id:take_she12:20210128155230p:plain

工夫した点

特にない。。。。。。。。。

go-aws-sdk は EKS の認証するツール書く時に書いたことがあった。

取得するのは以下3つ - Cluster Identifier - Engine - Engine Version

こんな感じになる。

aws_custom_rds_cluster_count{cluster_identifier="postgres-aya-production-a",engine="aurora-postgresql",engine_version="9.6.16"} 1
aws_custom_rds_cluster_count{cluster_identifier="postgres-aya-release-1595371533",engine="aurora-postgresql",engine_version="9.6.16"} 1
aws_custom_rds_cluster_count{cluster_identifier="postgres-aya-report-1611765597",engine="aurora-postgresql",engine_version="9.6.16"} 1
aws_custom_rds_cluster_count{cluster_identifier="postgres-rdev-02-a",engine="aurora-postgresql",engine_version="9.6.16"} 1
aws_custom_rds_cluster_count{cluster_identifier="recommendation-develop-a",engine="aurora-mysql",engine_version="5.7.12"} 1
aws_custom_rds_cluster_count{cluster_identifier="recommendation-edge-a",engine="aurora-mysql",engine_version="5.7.mysql_aurora.2.07.2"}

まぁ現状どのバージョンが残ってるかとかを探しやすくはなるし、どれぐらい残ってるかは見易くはなる気がする。

Deploy

いつものように Kubernetes Deployment として動かすが、AWS へのアクセスが必要。DescribeDBClusters を実行できる必要があるので。

で、IRSA 対応をはじめて手を動かしながらやってみている。

IAM Role 作って serviceaccount と紐づけて、deployment から serviceaccount を参照させる感じ。

おわりに

次回作は aws-ecr-image-scan-findings-prometheus-exporter の予定。ECR の image scan findings の結果を、Severity とかを送る。

木曜金曜はオフなので毎日新作リリースはおやすみ。土曜にでも出そうと思う。

GitHub の Issue の数を prometheus 形式で export する OSS 作った

作った。

github.com

github.com

これのお友達。

なぜ作ったか

Quipper では基本 Issue で仕事をしている。で、適当に Label も活用している。

もともとの Motivation は Open になってる Postmortem Issue が放置されてることだったりする。

結局いまだに放置されていてその問題は解決していないのだけれど....

f:id:take_she12:20210127054456p:plain

こんな風に metric として可視化されると、n 件たまったらアラートとかできる。するかはまだわからない。

そもそも今 Workload の管理というか、Issue 管理全然できてるとは言えない。が、まぁなんにせよ見えるようにして長期トレンドを見て何かアクションする、みたいなことはできる可能性がある。この手の可視化、metric 化はそれによって意味のあるアクションが取れるか、意味のある意思決定がとれるかは、とってみて眺めて味わう、というフェーズがないとなんとも言えんので、しばらくはちょっとでも「あると便利かも?」と思ったものはバンバン送ろうと思っている。

工夫した点

Label Filtering

Issue は多い。開きっぱなしのものも多い。しかも Quipper の場合は quipper/quipper にかなりの割合のメンバーが issue を作成しているので多い。3k とか 5k とかある。ので、取得時点で Label でフィルタリングできるようにしている。

github.com

GITHUB_LABEL という環境変数からとってきて、ListOption にいれる。

で、ないならないで良いようにもした。

github.com

Pagination

工夫というほどでもないけど。GitHub API は default で 30件、max 100件しか取れない。

ちゃんと Pagination 対応した。

github.com

ただ数k になると結構時間かかって、Ticker の Interval 以内に取得できないケースもある。

次回作

Github 編は終わり。次は AWS の RDS Engine Version を Prometheus 形式で Export するやつを作る。これまた役に立つか、Alert つけるにせよどのバージョンがアウトかを管理する必要があるので、そのへんどうできるかは不明だが、とりあえず作る。

GitHub の Repository の Pull Request の数を prometheus 形式で export する OSS 作った

昨日のこれ

blog.chaspy.me

自分の発表では prometheus 形式で export したら Datadog の Kubernetes Autodiscovery で datadog-agent が勝手に取ってくれて便利だよなんて言ったんですが

docs.datadoghq.com

prometheus 形式で export するのに個別にタグつけて export できないと思ってたんですが

godoc.org

In addition to the fundamental metric types Gauge, Counter, Summary, and Histogram, a very important part of the Prometheus data model is the partitioning of samples along dimensions called labels, which results in metric vectors. The fundamental types are GaugeVec, CounterVec, SummaryVec, and HistogramVec.

できる(できる)

ということを8億年前から知っていた @yuya-takeyama に教えてもらったので書き直しました。一応前のは残して別の repository に書きました。

github.com

つぎはぎだらけでだいぶ雑な気がしますがまぁ動いているからいいのだ。

これは何

prometheus 形式で Github の指定した repository の pull request の数を author, reviewer, label をタグとしてつけて export する君です。

f:id:take_she12:20210126035051p:plain

github.com

こっちは push のアプローチで、この中で Datadog に対して metrics を投げつけるんですが、

今回作った github-pr-prometheus-exporter は Datadog 関係ないです。prometheus 形式で、 8080:/metrics で metrics を export するだけ。

で、こういう annotation 書けば datadog-agent が取ってくれるので便利。pull 型のアプローチですね。使ってる manifest そのまま晒しちゃいます。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: github-pr-prometheus-exporter
  namespace: monitor
  labels:
    name: github-pr-prometheus-exporter
    owner: sre
spec:
  replicas: 1
  selector:
    matchLabels:
      app: github-pr-prometheus-exporter
  template:
    metadata:
      labels:
        app: github-pr-prometheus-exporter
      annotations:
        ad.datadoghq.com/github-pr-prometheus-exporter.check_names: |
          ["prometheus"]
        ad.datadoghq.com/github-pr-prometheus-exporter.init_configs: |
          [{}]
        ad.datadoghq.com/github-pr-prometheus-exporter.instances: |
          [
            {
              "prometheus_url": "http://%%host%%:8080/metrics",
              "namespace": "github-pr-prometheus-exporter",
              "metrics": ["*"]
            }
          ]
    spec:
      containers:
      - image: chaspy/github-pr-prometheus-exporter:v0.1.0
        name: github-pr-prometheus-exporter
        ports:
        - name: http
          containerPort: 8080
        livenessProbe:
          initialDelaySeconds: 1
          httpGet:
            path: /metrics
            port: 8080
        resources:
          limits:
            memory: 32Mi
          requests:
            cpu: 10m
            memory: 32Mi
        env:
          - name: GITHUB_TOKEN 
            valueFrom:   
              secretKeyRef:  
                name: "github-secret" 
                key: GITHUB_TOKEN
          - name: GITHUB_REPOSITORIES  
            value: "quipper/kubernetes-clusters,quipper/server-templates,quipper/monorepo,quipper/monorepo-global,quipper/qs-terraform,quipper/aya-terraform,quipper/iam,quipper/aya-iam,quipper/dns,quipper/aya-dns"
        securityContext:
          readOnlyRootFilesystem: true
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
      imagePullSecrets:
        - name: docker-hub
      affinity:
        nodeAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
            nodeSelectorTerms:
            - matchExpressions:
              - key: quipper/type
                operator: In
                values:
                - system-components

別に push 方式でも全然いいんですが、Datadog 関係の secret を持つ必要がないって点が利点ですかね。

前作と同じく環境変数 GITHUB_REPOSITORIES で対象リポジトリを指定します。

     - name: GITHUB_REPOSITORIES  
       value: "quipper/kubernetes-clusters,quipper/server-templates,quipper/monorepo,quipper/monorepo-global,quipper/qs-terraform,quipper/aya-terraform,quipper/iam,quipper/aya-iam,quipper/dns,quipper/aya-dns"

もはやこれを deployment として浮かせることすらしたくない(どっかのサーバレスな何かに image だけ指定していい感じに動いて欲しい)ぐらいには怠惰になってきた。

まぁ何はともあれ、push 形式の前作を cronjob で定期実行するよりはこっちのアプローチのほうがいいかなと思い書き直したという話でした。

次こそはこれの issue ver を作る。