/var/log/laughingman7743.log

I thought what I'd do was, I'd pretend I was one of those deaf-mutes or should I?

CloudwatchLogsのデータをKinesisを経由して、LambdaでDatadogLogsに送る

DatadogLogsを使い始めていて、ECSのログをCloudwatchLogsにログを集約して経路を作ったりしています。 ログをいろいろな出力先に出し分けしたいのですが、CloudwatchLogsのサブスクリプションフィルタはなんと1つのロググループに1つしか付けれないです😇 *1

出し分けをしたい場合は一旦Kinesisを経由して、KinesisからLambdaで出し分けすると良いです。
DatadogのGitHubオーガナイゼーション*2を見ると、DatadogLogsに送るLambda*3が見つかりますが、Kinesisには対応していないです😭

公開されているLambdaをベースに、雑に書いてみました。

sourceやsourcecategory、tags等は適当です。JSON形式で送れるのは非常に楽ですね。
WARNやINFOといったログレベルは、DatadogLogsのパイプライン機能でパースして付加すると良いと思います。*4
DatadogLogs結構良さそうですね。

Enjoy!

オレオレTerraform構成

もともとは同僚がシェルで書いていたラッパーです。シェルつらいかつ、CIが回せなかったのでPythonで書き直したものです。
こういったのもこそGoで書くのが良さそうですね。Terraformつらいって感じが伝われば😩

ラッパースクリプト自体はTerraformのコマンドとオプションを指定できるようにして、サブプロセスでTerraformを実行しているだけです。 ロールは カテゴリ/ロール 形式で指定します。Slackへの通知は、SNSをSlackに投げるLambdaを作成しています。SNSには整形したメッセージを投げ、Lambdaはトークンを追加してSlackに投げるだけの非常に簡単なものです。

実行環境はPipenv*1を使うと楽に構築できます。Pipenvちょー便利です!

ディレクトリ構成は以下

ステートの管理はS3、カテゴリやロールといった概念を導入して、全体・カテゴリ単位で共通に使える変数やバックエンド、プロバイダ、バージョン等の設定をテンプレートとして切り出しています。 カテゴリはVPCVPCに依存しないリソースを、VPC名やS3やSNSといったAWSのリソース名をつけて管理することを想定しています。ロールはサブネット名や適当な利用用途や業務用途の名前をつけて管理することを想定しています。ステージングとプロダクションの2つの環境を、変数値を変えることによって構築をすることを想定した構成です。カテゴリの共通変数には別カテゴリに属するロールのリモートステートを定義したりすると色々と捗ります。
テンプレートファイルは実行時に各ロールのディレクトリにコピーされるので、gitignoreファイルは以下の様にしています。IntelliJのHCLプラグイン*2はモリモリ補完が効くのでオススメです。

CIはJenkinsでGHPRB*3とMultibranchPipeline*4を併用して、プルリクではステージングとプロダクションのplanを実行してSlackに通知、developブランチではステージング環境のみapplyを実行してSlackに通知、masterブランチではプロダクション環境のみplanを実行してSlackに通知をしています。プルリクコメントに所定の形式でロール名を書くと、そのロールのみ実行するようなこともできるようにしています。

JenkinsはMasterノードのみDockerで上げて(EFS早く東京リージョンに来て欲しい)、実行自体はCodeBuildを使っています。CodeBuildもちょー便利です!

Terraformが利用するAWSAPIキーは全てのリソースをさわるのでAdmin権限が必要になります。CodeBuildはパラメータストアの値を簡単に取ってこれるので、パラメータストアにセキュアストリングで格納しています。APIキーの発行はしたくなかったのですが、AssumeRoleを使うとリモートステートへのアクセスが上手く行かなくなったので、仕方なくAPIキーの発行をしています😭

もうTerraformなしでは生きられない体に。。。素敵なTerraformライフを。

Enjoy!

Amazon ECRのCLIツール作った

Dockerログインめんどくさいかつ、レジストリのURL長杉ってことでCLIツール作りました。便利!

使い方は README 参照してください。

TODO

  • プログレスバーの表示がおかしくなる。tqdm*1 の使い方の問題かなと。
  • Vacuumコマンドとして、CLIからオレオレライフサイクルポリシーでイメージを削除できるような実装。
  • テスト😭

Enjoy!

BigQueryのデータセット管理ツール作った

BigQuery のデータセットも Terraform で管理*1ができるのですが、権限の管理に対応していない。。。
ぶっちゃけ Terraform じゃなくて、もっとシンプルな形 (ステートファイルを持たず、設定ファイルのみ管理する形) で管理したいなと思い作ってみました。

使い方は README 参照してください。Terraform 的なコマンドとなっています。
YAMLファイルは GIT 等で管理して、CI回すと良いと思います。

テーブルの管理にも対応するかな。

Enjoy!

PyAthenaでRedashのクエリランナー書いた

プルリクマージされました。ありがとうございます。
これでカジュアルにAthenaにクエリ投げまくりですね。

Enjoy!

AWS請求レポートをPyArrowでParquet+Snappyに変換する

AWSコストの可視化として、請求レポート*1をAthena*2でクエリを投げられる形式に変換して、Redash*3でダッシュボードを作成していたりします。 元データがCSV+ZIPと非常に扱いにくい形式なのでCSV+GZIPに変換していたのですが、カラムナー形式に変換すると良さそうだなと思い、PyArrow*4を使ってParquet*5+Snappy*6に変換してみました。

以下のスクリプトはS3に出力されている請求レポートをダウンロードしてきて、Parquet+Snappyに変換、Athenaで扱いやすいパス(Hiveのパーティショニング形式)にアップロードするようなPython3のスクリプトの例です。
少し形は違いますが、同じようなことをAirflow*7を使って毎日ぶん回しています。月初にはパーティションを追加、4〜5日目ぐらいまでは前月のデータも更新されるので当月分と合わせて変換するような事をしています。パーティションの追加にはもちろんPyAthena*8を使っています。マルチアカウントで請求情報を集約している場合は ratecostblended_rateblended_costunblended_rateunblended_cost になります。タグも合わせて出力する設定にしている場合は、resource_id の後ろにタグの情報が追加されます。

PyArrowはPandas*9のDataFrameから簡単にParquet形式のデータを出力できます。オンメモリの処理になるので、解凍したファイルのサイズ+αのメモリが必要となります。

Athenaのテーブル定義は以下です。

日付はtimestamp型で持ちたいのですが、文字列型でないとエラーが発生しました。日付型を上手く扱う方法は正直よくわかってないです。。。

カラムナー形式にすることでスキャン量をかなり減らすことができます。クエリの実行速度が速くなることは期待していなかったのですが、意外と速くなりました。CSV+GZIPと比べてクエリにもよりますが、スキャン量は10分の1、速度は5分の1ぐらいになりました。

PyArrow非常に便利ですね。請求レポート以外にもETL処理で色々と使い所はありそうです。
Apache Arrow*10PythonだけでなくRubyもサポートされて始めています*11。素敵なETLライフを。

Enjoy!

Amazon AthenaのPythonクライアント書いた

AthenaがAPI/CLIに対応した*1ので boto3*2で少し使ってみたのですが、クエリ実行結果のパースが非常にめんどくさい。
もっとカジュアルにクエリを投げたいなってことで、PEP249*3に準拠したクライアント書きました。

使い方はJDBC*4と変わらないです。コードもほとんど流用する形です。
ポーリング中のリトライ処理は実装した方が良かったかも。。。
asyncio*5対応とかしたいですね。

Enjoy!