Mackerel と diff-detector を組み合わせてファイルの変更検知を実現する

背景

去年,モニタリングサービスを Zabbix から Mackerel に移行したときに,ファイルの変更検知(例えば /etc/passwd など)を Mackerel でうまく実現できなくて,諦めてしまっていた経緯があった.もしかしたら公式機能であるのかも...?

Zabbix だと

Zabbix から公式に提供されている「Template OS Linux」の中に /etc/passwd の変更検知をする設定がある.ちなみに,今回は Zabbix 2系を前提にしている.

  • アイテム
    • 名前 : Checksum of /etc/passwd
    • キー : vfs.file.cksum[/etc/passwd]
  • トリガー
    • 名前 : /etc/passwd has been changed on {HOST.NAME}
    • 条件式 : {Template OS Linux:vfs.file.cksum[/etc/passwd].diff(0)}>0

仕組みをザックリと説明すると,Zabbix で vfs.file.cksum を使うとファイルのチェックサム(例えば 1938292000 のような数値)を取得できるため,その値をメトリクスとして保持している.さらに Zabbix のトリガー条件式では .diff という「前回のメトリクスと違った場合」を検知する関数があるので,チェックサムが変更された場合にアラートを鳴らすことができる.逆に言うと「変更されたことを検知できる」だけであって「どのように変更されたか?は検知できない」ことに注意する.

メルカリの事例

最近開催されていた Mackerel DAY の資料を見ていたら,メルカリでは diff-detector という独自ツールを使って /etc/passwd の変更検知を Mackerel で実現しているとのことで,さっそく試してみようと思った.diff-detector 以外でも,メルカリの Mackerel 活用事例が圧倒的で非常に勉強になった!スゴすぎ...!

diff-detector を読んだ

まずは diff-detector 単体の機能を把握するために,実装を読んでみた.Go と Perl 版があるけど,今回は Go を選んだ.実装としては,少し書き捨てっぽい印象も受けたけど(go fmtgoimports を流すと結構変更点が出た...w),必要十分な機能は揃っていた.

github.com

  • 特徴
    • ファイルの変更検知ではなく「標準出力の変更検知」ができる
    • 「標準出力の変更検知」ができるので,検知の対象としてコマンドを指定する(例えば cat /etc/hosts など)
    • 一次ディレクトリに新旧の標準出力を含めたファイルを保持しているため「どのように変更されたか?」の具体的な変更点も確認できる
    • 初回実行と変更なしの場合は 0 が返り,変更ありの場合は 1 が返る
  • 実装
    • コマンドオプションの終点を意味する -- をパースするために flags.NewParser(opts, flags.PassDoubleDash) を使っている
    • 標準出力(旧)は os.TempDir() で取得している
      • /tmp/500-diff-detector-c9f995bb55ec9fc62e0ca720b3ebfbad のような絶対パスになる
    • 標準出力(新)は ioutil.TempFile() で取得している
      • /tmp/temp766915122 のような絶対パスになる
    • 一次ディレクトリに保持するファイル名に使うハッシュにソルト値を含めたい場合は --identifier オプションが使える
    • 変更検知は diff -U 1 を使っている
      • -U-u と同じで,差分の前後の行数を指定することができる

具体的には以下のように実行する.

# 初回実行
$ diff-detector -- cat /etc/passwd
Notice: first time execution command: 'cat /etc/passwd'

# 変更なし
$ diff-detector -- cat /etc/passwd
OK: no difference: ```root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:...```

# 変更あり
$ diff-detector -- cat /etc/passwd
NG: detect difference: ```@@ -31 +31,2 @@
 jenkins:x:502:502::/home/jenkins:/bin/bash
+kakakakakku:x:503:503::/home/kakakakakku:/bin/bash```

Mackerel と diff-detector を組み合わせる

ここからやっと本題で,Mackerel と diff-detector を組み合わせる.基本的には diff-detector をチェックプラグインとして使えるようにするだけで良かった.オプションなどは公式ドキュメントを見てカスタマイズすると良さそう(例えば /etc/passwd のインターバルをもう少し長くするなど).

mackerel.io

設定は簡単で /etc/mackerel-agent/mackerel-agent.conf に以下を追加した.

[plugin.checks.diff_etc_passwd]
command = "/usr/local/bin/diff-detector -- cat /etc/passwd"

この状態で変更検知を起こすと,以下のようにアラートが Slack に通知された.Zabbix のときには実現できていなかった「変更点」も確認できるので,非常に便利だった.

f:id:kakku22:20171019183454p:plain

関連する公式チェックプラグイン

id:Soudai さんに教えて頂いたファイル関連の公式チェックプラグインも紹介しておこうと思う.今回の変更検知の要件には合わなかったが,知っておくといざ必要になったときに良さそう.

まとめ

  • Mackerel でファイルの変更検知を実現するために diff-detector を試してみた
  • 「変更されたこと」だけではなく「どのように変更されたか?」も検知できるので,非常に便利だった
  • diff-detector のような汎用的なチェックプラグインが Mackerel 公式であっても良さそう 🙏
  • Mackerel の監視設定は現在「閾値」しか設定できないので,Zabbix の .diff のような「前回のメトリクスと違った場合」を設定できると,監視設定の幅が広がりそう 🙏

関連記事

メルカリの Mackerel 活用事例を詳細に解説されている.すごく参考になった!

blog.a-know.me

Treasure 2017 の研修資料は Go を学ぶのに最高だった

Go 関連の本を読んだり,サンプルコードを写経するだけではなく,もっと実践的に勉強したいなと思って調べていたら,VOYAGE GROUP の Treasure 2017 と言うインターンシップの研修資料が GitHub に公開されていることを知って,さっそく挑戦してみた.数日間取り組んでみて,とにかく素晴らしかったので,紹介したいと思う.suzuken 先生,素晴らしすぎます!

学べるテーマ

Go の研修資料とは言え,幅広いテーマで Go を学ぶことができる点が素晴らしかった.ザッと挙げるとすると以下のようになる.テーマを見るだけで,もうワクワクしてくるのではないだろうか?

  • アルゴリズム実装とテストコード
    • フィボナッチ数
    • スタック
    • CLI
  • net/http
    • curl 実装
    • スクレイピング実装
  • コンカレンシー
    • goroutine
    • Data Race
    • du 実装
  • ウェブアプリケーション
    • Wiki 実装 / Go
    • TODO 実装 / Go + React

テーマ以外で,個人的に良いなと思った点があった.

  • TDD を尊重し,テストコードを書くことが前提になっていること
  • 基本課題に加えて,発展課題も多く提供されていて,もう一歩深く学べる仕組みになっていること
  • 独学というよりは,チームで学んでいくスタイルを前提に研修が組まれていること

感想

実際に取り組んでみた感想をまとめておこうと思う.

フィボナッチ数

アルゴリズム実装としては一般的だけど,インクリメンタルに実装を進めていくプロセスが非常に楽しかった.実装,テスト,リファクタリング,CLI を流れるように学べるので,非常に実践的で資料としても素晴らしかった.

  • フィボナッチ数を返す関数 fib() を実装し,適当に main() から呼び出せるようにする
  • マイナス値などの異常値が入ったときのエラーハンドリングを実装する
  • testing パッケージを使ってテストコードを書くことで,安心してリファクタリングが行える体験をする
  • TableDrivenTests を使ってテストコードをさらに DRY に書き換える
  • os.Args を使って,フィボナッチ数を返す CLI を実装する

スタック

ペアプロでスタックを実装するという内容になっていて,組織文化の色が良く出ているなと感じた.今回は自分で実装もテストコードも書いたけど,職場のメンバーにもコードを見せて,アドバイスをもらったりもした.また「スタックに最大長を設定できるようにし,溢れた場合はキューのように FIFO でデータを削除する」という追加要件が出てくるのも良かった.仕事でも追加要件が出てくることは頻繁にあり,そういった状況を感じさせる,実践的なテーマだった.

net/http

仕事では Gin を使って API を書くこともあるけど,net/http を深く活用したコードは今まであまり書いたことがなく,curl 実装は考えることが多かった.CLI で指定された URL に GET リクエストを送る実装はしたけど,POST 対応はまだだし,本家 curl にあるオプションの実装もまだという感じで,発展課題には着手できていない.今後のタスクとして残している.また golang.org/x/net/htmlhtml.Parse() を使ったスクレイピングを自分で実装できたのも大きな収穫だった.

Wiki アプリケーション

Go で Rails のようなフルスタックなウェブアプリケーションを実装した経験もなかったので,実際に仕事で書くかどうかは別として,単純に楽しかった.以下の Wiki をベースにして「記事にコメントを登録できるようにする」という発展課題に挑戦してみた.

github.com

実際に comments テーブルをマイグレーションで追加して,記事に紐付くコメントを登録するエンドポイントを用意して,登録されたコメントを表示できるようにした.Router + MVC の流れだったり,html/template を使ったビューの実装を知れたのが収穫だった.以下の画像は,記事に紐付くコメントを表示できるようにしたところ.

f:id:kakku22:20171016050607p:plain

TODO アプリケーションも動作確認まではしたけど,フロントエンドの実装がわからなくて Go 以外の部分でハマりそうだったので,ここは着手せずにスキップしてしまった.

今後の残タスク

コンカレンシーの部分が,個人的にまだまだ理解が浅いなと感じている.du 実装の課題に着手できていないため,goroutine と channel あたりの理解を深めつつ,挑戦してみたいと思っている.他にも,curl のオプションを実装したり,Wiki の発展課題にも挑戦してみたいと思っている.なお,今回実装したコードは以下のリポジトリに push しておいた(参考にならないとは思うけど).

github.com

まとめ

  • Go の実装スキルをステップアップするために Treasure 2017 の研修資料が最高だった
  • 冒頭に書いた通り,幅広いテーマで Go を学べる点がとにかく良かった
  • 基本課題に加えて,発展課題も多く提供されているので,モチベーション次第でいくらでも挑戦できる仕組みになっているのも良かった

以下の記事には Treasure 2016 のレポートがまとまっていた.

techlog.voyagegroup.com

ポエム : 技術指導の今後とは

研修資料を GitHub で無料で公開をすることが一般的になった現代では,「研修資料を売る」というスタイルは古く,エンタープライズを含めても,今後どんどん減っていくのではないかと思う.誰でも学びたいときにすぐ学べる時代になっている.じゃあ技術指導は必要なくなるのか?と聞かれれば,そんなことはなく,今後最も価値があるのは「研修資料」ではなく「教える人(講師/テクニカルトレーナー/サポートエンジニアなど)」だと考えている.ようするに技術指導のメインコンテンツは「資料」ではなく「人」に推移しているということで,同じ資料を使っていたとしても,教える人のパフォーマンスによって学んでいる側の成長曲線が全く変わってくることを意味している.「教える技術」は属人性が高く,市場価値が高いとも言える.インターネットの普及により「学習の高速道路が整った」と言われることもあるけど,独学では実現不可能な速度で成長してもらうことが「教える人」の価値で,僕は技術指導にすごく興味関心がある.副業でプログラミング講師をしているのもそうだし,今まで個人的にハンズオン勉強会を実施してきたのも「教える」ということに対するモチベーションが高いからと言える.そういう背景もあり,今回の Treasure 2017 研修資料は「教える人」も含めて最高だと感じた.

Redash のユーザー削除が難しい

背景

Redash を運用していて,例えば退職者が出たタイミングなど,ユーザー削除って結局どうするんだっけ?という話題が出て,明確な回答ができなかったので,実際に試してみた.ユーザー削除だけじゃなく,権限管理など,今後 Redash の運用面の記事を書く機会が増えそう.なお,今回は Redash 3.0.0 を使って検証した(master を Docker で起動したため最新すぎる可能性もある).

Redash 画面

Redash 画面では,ユーザー追加とグループ管理ができる.ただし,公式ドキュメントにも記載が無いように,ユーザー削除の機能は提供されていなかった.admin 権限でログインした場合は,Redash 画面からユーザー削除ができるべきだと思う.

redash.io

Redash CLI

公式ドキュメントにも詳細な記載はないけど,Redash には Redash CLI と言うコマンド機能 (manage.py) がある.例えば users list を実行すると,登録済のユーザー一覧を取得することができる.

$ ./manage.py users list
Id: 1
Name: admin
Email: admin@example.com
Organization: test
--------------------
Id: 2
Name: user1
Email: user1@example.com
Organization: test
--------------------
Id: 4
Name: user3
Email: user3@example.com
Organization: test
--------------------
Id: 3
Name: user2
Email: user2@example.com
Organization: test

特殊な条件でユーザー削除ができる

この Redash CLI の users delete を使うと,ユーザー削除ができる.指定するのは,メールアドレスとなる.以下のように,問題なくユーザー削除ができた.ただし,これは特殊な条件で「そのユーザーが1度も Redash にログインしていないこと」が前提になる.そんなこと,ほぼ無いでしょうに...!

$ ./manage.py users delete user3@example.com
Deleted 1 users.

イベント(操作履歴)があると削除できない

Redash では,ユーザーごとの操作履歴をイベントとして events テーブルで管理している.このテーブルに対して外部キー制約が設定されているため,ユーザー削除は以下のようにエラーになった.

$ ./manage.py users delete user2@example.com
Traceback (most recent call last):
  (中略)
sqlalchemy.exc.IntegrityError: (psycopg2.IntegrityError) update or delete on table "users" violates foreign key constraint "events_user_id_fkey" on table "events"
DETAIL:  Key (id)=(3) is still referenced from table "events".
 [SQL: 'DELETE FROM users WHERE users.email = %(email_1)s'] [parameters: {'email_1': u'user2@example.com'}]

Redash 管理者画面で,イベントを削除することはできるけど,ユーザーを指定して削除することができないため,オペレーションとして現実的に不可能だと思う.

f:id:kakku22:20171014023637p:plain

ダッシュボードとクエリの所有ユーザーだと削除できない

もし,イベントを削除できたとしても,ダッシュボードとクエリの所有ユーザーだった場合は,今度は dashboards テーブルと queries テーブルの外部キー制約により,ユーザー削除はエラーになった.Redash を使っていればダッシュボードとクエリを作るのは一般的だし,今の仕様はかなり厳しいように感じた.

$ ./manage.py users delete user1@example.com
Traceback (most recent call last):
  (中略)
sqlalchemy.exc.IntegrityError: (psycopg2.IntegrityError) update or delete on table "users" violates foreign key constraint "dashboards_user_id_fkey" on table "dashboards"
DETAIL:  Key (id)=(2) is still referenced from table "dashboards".
 [SQL: 'DELETE FROM users WHERE users.email = %(email_1)s'] [parameters: {'email_1': u'user1@example.com'}]

ダッシュボードとクエリの所有ユーザーを変更する

ユーザー削除ができないとしても,退職者が所有ユーザーになったダッシュボードとクエリを運用し続けるのも微妙なので,そういう場合は Redash 管理者画面から所有ユーザーだけを変更することができる.そもそも Redash 管理者画面の存在を知らない人も多いはずで,このあたりはもうちょっと普及を進めたいと思っている.

f:id:kakku22:20171014023658p:plain

要望など

当然ながら,ユーザー削除の要望は出ていて,開発予定はありそうだった.

github.com

github.com

Trello で管理されているロードマップでも "Accepted" レーンの1番目に位置しているため,次期リリースあたりで入って欲しいなーとは思う.

まとめ

  • Redash 画面では,現時点でまだユーザー削除の機能が提供されていなかった
  • Redash CLI を使うと,ユーザー削除ができた
    • ただし,PostgreSQL の外部キー制約に該当してレコードが消せないため,現実的にはユーザー削除はできないと言える
  • ダッシュボードとクエリの所有ユーザーを変更することはできるので,退職者が所有ユーザーになった状態は回避できる
  • Redash 管理者画面の存在を知らない人は多そう
  • 次期リリースあたりでちゃんとユーザー削除ができるようになることを祈る

「カンバン仕事術」には「始めるのをやめて,終わらせることを始める」ための実践的なアプローチが凝縮されていた

2016年に出版されて,読もう読もうと思いつつ積読になってしまっていた「カンバン仕事術」をやっと読んだ.

もう,とにかく良かった.カンバンに限らず,アジャイルな開発プロセスに興味がある人は全員読むと良いんじゃないかと思うほどオススメできる良書だった.僕が推進しているプロジェクトのメンバーに繰り返し,繰り返し説明している話(WIP,終わらせることを始める,振り返り,緊急など)も全て書かれていた.僕自身もっと早く読むべきだったし,メンバーにも読んでもらえば良かった ( ゚д゚)!!!

カンバン仕事術

カンバン仕事術

  • 作者: Marcus Hammarberg,Joakim Sundén,原田騎郎,安井力,吉羽龍太郎,角征典,?木正弘
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2016/03/26
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログ (7件) を見る

WIP 制限

仕掛りタスク (WIP) を減らすことによって,各タスクのリードタイムが減るという理論を知っている人は多いと思うけど,実際に実践できている人は少ないのではないかと思う.僕の経験的にも,WIP の定義が甘いなーと感じる場面が多くあった.例えば「実装する予定がないのに仕様を整理しているタスク」は WIP だし,「コードレビューまで終わってるのにリリースされずに残っているプルリク」も WIP だし,「すぐには影響が無さそうだけど気になるエラーログを調査するタスク」も WIP と言える.本当に優先順位が高いのであれば,すぐに着手するべきだけど,その場合は今まで着手していたタスクを完全に止めるか,完全に終わらせるか,どちらかに振り切る必要がある.基本的には完全に終わらせるべきで,本書では「始めるのをやめて,終わらせることを始めよう!」と書かれていた.本当に最高のスローガンだと思う.朝会の冒頭で,全員で「始めるのをやめて,終わらせることを始めよう!」と発声練習をするのも良さそう(笑)

そんな「WIP」に関して,ここまで詳細に多くのページが割かれている本を今まで読んだことが無かった.第一部はストーリー形式で書かれていて,第二部では理論的に書かれている点も良かった.また「タスクが同じ列から何日も動かないこと」を「付箋紙が臭っている」と表現しているコラムがあり,このあたりの感覚をメンバー全員に知ってもらうことが,プロセスマネジメント(スクラムマスターなど)の最重要項目の一つだと思う.よくある話で「プルリクを出したらすぐに次のタスクに着手してしまうのはなぜか?」というものがあり,結局のところ,リリースされるまで WIP なのだから,レビューで止まってるタスクがあれば流す必要があるし,リリースで止まってるタスクがあれば流す必要がある.常に「付箋紙が臭っていないか?」をチーム全体で把握することがプロセス改善の第一歩だと思う.

スウォーミング

「スウォーミング」の解説が入っているのも本書の素晴らしい点だと思う.スウォーミングとは,特定のタスクが止まっていて WIP 制限が詰まっているときに,チーム全体でそのタスクに取り組むことと表現できる.制約条件の理論 (TOC) と同じ考え方で,ボトルネックが目の前にあるのであれば,全員で取り除こうという思考と言える.スウォーミングが重要視されてなくて,特定のタスクを抱えている特定のメンバーだけが苦しんでいるチームは案外多いのでは?

スウォーミング,もしくはカンバンを知るのに1番良いのは以下の資料 (One day in Kanban land) だと思う.シンプルなコマ漫画なので,英語でも読めると思うけど,調べたら日本語版もあった.プロジェクトのメンバーには何度も繰り返し紹介しているほどに,大好きな資料.

One day in Kanban land のポイントは大きく以下と言える.

  • 8コマ目 : タスク A の問題にエンジニア2名が加わって,スタックトレースの調査を手伝う(= スウォーミング)
  • 10コマ目 : タスク A の問題にさらにエンジニア2名が加わって,再発防止策となるテストコードの実装を手伝う(= スウォーミング)
  • 11コマ目 : タスク A の問題にプロダクトオーナーが加わって,他の差し込みタスクが来ないように防波堤の役割を担う(= スウォーミング)

まさに「スウォーミング」の具体例と言えると思う.最高!

緊急とは

とは言っても,本番障害など緊急タスクが差し込まれることはあるので,それ自体を否定するわけではない.そうではなく,適切に緊急タスク(サービスクラスの一つ)を扱うことが重要で,その具体的な方法が解説されている点も素晴らしかった.サービスクラスという表現は今までに聞いたことが無かったけど,一般的なのだろうか?どのクラスも,実際のタスクにマッピングすることができ,議論をする材料としても面白いと思う.

  • 緊急(特急)クラス
  • 確定納期クラス
  • 通常クラス
  • 欠陥クラス
  • 無形クラス

ゲーム

13章にはカンバン(などのプロセス)を学ぶことができるゲームが紹介されていて,どれも経験したことがなく新鮮だった.スクラムマスターの研修でも似たようなゲームをしたことを思い出したりした.

  • コイン渡し
  • ナンバーマルチタスクゲーム
  • ドットゲーム
  • ボトルネックゲーム
  • getKanban
  • カンバンピザゲーム

最近だと Not My Fault! が流行ったりもしているし,チームビルディングでゲームを実施しながら学ぶというスタイルは非常に効果的だと思う.たまには勉強会じゃなくて,ゲームをしてみるのも良さそう.

Not My Fault! ~俺のせいじゃない!~

Not My Fault! ~俺のせいじゃない!~

まとめ

本当に良書だった.読みながらたくさん書き込んでしまったし,机に置いておいて定期的に読み直すことになりそう.12章に「タイムボックスは役に立つ」という解説があるのも非常に興味深かった.ようするに,スクラムだとスプリントというタイムボックスがあり,スプリントプランニングとか,レトロスペクティブとか決まったイベントがあるけど,カンバンにはそういう区切りがなくて苦手という印象を持っている人に対するメッセージだと読み取れた.結局のところは,必要に応じてレトロスペクティブをすれば良いし,レビューの場を設ければ良いし,それぞれのイベントに「強制力を持たせない」という点がカンバンの特徴と書かれていた.すごーく勉強になった.

アジャイルな開発プロセスに興味がある人,タスクのリードタイムが長いことに課題を感じている人,新任リーダーを任された人など,様々な人に読んでもらいたい!絶対に学びがあるはず!

カンバン仕事術

カンバン仕事術

  • 作者: Marcus Hammarberg,Joakim Sundén,原田騎郎,安井力,吉羽龍太郎,角征典,?木正弘
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2016/03/26
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログ (7件) を見る

関連記事

開発プロセスをうまく回すには,実はファシリテーションスキルも必要で,そのあたりを学びたい人には以下の書籍がオススメできる.

kakakakakku.hatenablog.com

One day in Kanban land など,社内でカンバン勉強会(何度も何度も再演している)をするときに使っている資料は以下にある.これは「カンバン ソフトウェア開発の変革」をベースに資料を用意したけど,今回「カンバン仕事術」を読んだし,改めて資料を作り直したいと思った.

kakakakakku.hatenablog.com

Aurora v1.13 から使える SELECT INTO OUTFILE S3 を試した

Aurora v1.14 の強制アップデートがあったりして,改めて Aurora のリリースノートを読み直していたら,Aurora v1.13 から SELECT INTO OUTFILE S3 が使えるようになっていることに気付いた(今さら!).今まで試したことが無かったので,実際に試してみた.

大きめのデータ抽出が必要なときなど,MySQL だと SELECT INTO OUTFILE でファイルに書き出すシチュエーションがあるため,Aurora でも使えるようになるのは非常に良いことだと思う.むしろ v1.13 まで無かったんだ...?という感じ.

docs.aws.amazon.com

事前準備

S3 と IAM ロールを作成する

事前に RDS 用の IAM ロールと IAM ポリシーを用意しておく.必要最小限のアクションは以下のドキュメントにまとまっている.今回は SELECT INTO OUTFILE S3 に必要なアクションだけを許可した.あと S3 も作成しておく.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "Stmt1506948517000",
            "Effect": "Allow",
            "Action": [
                "s3:AbortMultipartUpload",
                "s3:DeleteObject",
                "s3:GetObject",
                "s3:ListBucket",
                "s3:ListMultipartUploadParts",
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::xxx",
                "arn:aws:s3:::xxx/*"
            ]
        }
    ]
}

docs.aws.amazon.com

Aurora クラスターに IAM ロールをアタッチする

次に Aurora クラスターに IAM ロールをアタッチする必要があり,今回は管理コンソールで実施した.これだけではダメで,さらにパラメータグループ(クラスター)も修正する必要がある.今回は aurora_select_into_s3_role パラメータに作成した IAM ロールの ARN を登録した.詳しくはドキュメントに載っている.

docs.aws.amazon.com

ちなみに aurora_select_into_s3_role パラメータを修正し忘れると,以下のエラーが出る.

ERROR 1871 (HY000): S3 API returned error: Both aurora_select_into_s3_role and aws_default_s3_role are not specified, please see documentation for more details

GRANT

基本的に RDS のマスタユーザーを使うことはないと思うので,SELECT INTO OUTFILE S3 を実行するユーザーに SELECT INTO S3 権限を付与しておく必要がある.ここは公式ドキュメントの通りで良い.

mysql> GRANT SELECT INTO S3 ON *.* TO user@domain-or-ip-address

サンプルデータ

MySQL が公開している world database を使う.

world.sql を流し込んで,3テーブル存在していれば,問題なし.

mysql> SHOW TABLES;
+-----------------+
| Tables_in_world |
+-----------------+
| city            |
| country         |
| countrylanguage |
+-----------------+
3 rows in set (0.01 sec)

SELECT INTO OUTFILE S3

事前準備が多くなってしまったが,やっと本題に入る.既に用意している city テーブルのデータを S3 に出力してみた.

mysql> SELECT * FROM city INTO OUTFILE S3 's3://xxx/city';

S3 にファイルを出力できた.

$ aws s3 ls xxx
2017-10-02 22:34:29     143565 city.part_00000

ファイルも問題なく確認できた.

$ head -n 10 ~/city.part_00000
1  Kabul   AFG Kabol   1780000
2  Qandahar    AFG Qandahar    237500
3  Herat   AFG Herat   186800
4  Mazar-e-Sharif  AFG Balkh   127800
5  Amsterdam   NLD Noord-Holland   731200
6  Rotterdam   NLD Zuid-Holland    593321
7  Haag    NLD Zuid-Holland    440900
8  Utrecht NLD Utrecht 234323
9  Eindhoven   NLD Noord-Brabant   201843
10 Tilburg NLD Noord-Brabant   193238

ポイントなど

詳しくは公式ドキュメントに記載されているが,カスタマイズ可能なパラメータが一部ある.

docs.aws.amazon.com

S3 バケットのリージョン指定

出力する S3 のバケットが Aurora と別のリージョンにある場合,以下のようにリージョンを指定する構文がサポートされている.

s3-region://bucket-name/file-prefix

具体的には以下のようになる.

  • s3-us-west-1://
  • s3-ap-northeast-1://

ただし,デフォルトでは Aurora と同じリージョンになるため,特殊な要件がない限りはそのままで良いと思う.

region 値を指定しないと、Aurora は DB クラスターと同じリージョンの Amazon S3 にファイルを保存します。

FIELDS TERMINATED BYLINES TERMINATED BY

デフォルトではタブ区切りで出力されるが,必要に応じてカンマ区切りなどに変更することもできる.

mysql> SELECT * FROM city INTO OUTFILE S3 's3://xxx/city2'
    FIELDS TERMINATED BY ','
    LINES TERMINATED BY '\n';

S3 にファイルを出力できた.

$ aws s3 ls xxx
2017-10-02 22:34:29     143565 city.part_00000
2017-10-02 22:38:34     143565 city2.part_00000

ファイルもカンマ区切りになっていた.

$ head -n 10 ~/city2.part_00000
1,Kabul,AFG,Kabol,1780000
2,Qandahar,AFG,Qandahar,237500
3,Herat,AFG,Herat,186800
4,Mazar-e-Sharif,AFG,Balkh,127800
5,Amsterdam,NLD,Noord-Holland,731200
6,Rotterdam,NLD,Zuid-Holland,593321
7,Haag,NLD,Zuid-Holland,440900
8,Utrecht,NLD,Utrecht,234323
9,Eindhoven,NLD,Noord-Brabant,201843
10,Tilburg,NLD,Noord-Brabant,193238

マニフェストファイル

MANIFEST ON を指定すると .manifest というファイルも合わせて生成される.LOAD DATA FROM S3 コマンドを使って S3 から Aurora にデータをロードする場合に必要になる.なお,出力されるファイルの閾値は 6GB なので,巨大なテーブルを出力する以外は,基本的には1ファイルになると思う.

mysql> SELECT * FROM city INTO OUTFILE S3 's3://xxx/city3'
    FIELDS TERMINATED BY ','
    LINES TERMINATED BY '\n'
    MANIFEST ON;

S3 にファイルを出力できた.

$ aws s3 ls xxx
2017-10-02 22:34:29     143565 city.part_00000
2017-10-02 22:38:34     143565 city2.part_00000
2017-10-02 22:39:46        114 city3.manifest
2017-10-02 22:39:46     143565 city3.part_00000

マニフェストファイルは以下のような構造になっていた.

$ cat ~/city3.manifest
{
   "entries" : [
      {
         "url" : "s3://xxx/city3.part_00000"
      }
   ]
}

参考情報

SELECT INTO OUTFILE S3 を使うときに気になる secure_file_priv の値を Aurora で確認した.

mysql> SELECT @@aurora_version;
+------------------+
| @@aurora_version |
+------------------+
| 1.14.1           |
+------------------+
1 row in set (0.01 sec)

mysql> SELECT @@secure_file_priv;
+--------------------+
| @@secure_file_priv |
+--------------------+
| /tmp/              |
+--------------------+
1 row in set (0.00 sec)

まとめ

  • Aurora v1.13 から SELECT INTO OUTFILE S3 が使えるようになった
  • Aurora クラスターに IAM ロールをアタッチして,aurora_select_into_s3_role パラメータを修正する必要がある
  • データ抽出が必要なときに「Aurora → S3 に出力できる」と知っておくと良さそう