kakakakakku blog

Weekly Tech Blog: Keep on Learning!

アクセスキーのコミットを抑止できて安全便利な awslabs/git-secrets

GitHub で awslabs のリポジトリを眺めてたら git-secrets という便利なツール(シェルで実装されてる)を発見した.

どんなものかを簡単に説明すると,アクセスキーなどを誤ってコミットすることを Git の hooks を使って未然に防ぐツールで,誤って GitHub に push してしまったために,AWS を不正利用されてしまった,みたいな事故もたまに聞くし,そういうのを防ぐことができる.非常に良かったので,一部のリポジトリに git-secrets を設定した.

github.com

インストール

make install でも良いけど,Mac なら brew が使える.

$ brew install git-secrets

インストールすると git secrets コマンドが使えるようになった.

$ git secrets
usage: git secrets --scan [-r|--recursive] [--cached] [--no-index] [--untracked] [<files>...]
   or: git secrets --scan-history
   or: git secrets --install [-f|--force] [<target-directory>]
   or: git secrets --list [--global]
   or: git secrets --add [-a|--allowed] [-l|--literal] [--global] <pattern>
   or: git secrets --add-provider [--global] <command> [arguments...]
   or: git secrets --register-aws [--global]
   or: git secrets --aws-provider [<credentials-file>]

    --scan                Scans <files> for prohibited patterns
    --scan-history        Scans repo for prohibited patterns
    --install             Installs git hooks for Git repository or Git template directory
    --list                Lists secret patterns
    --add                 Adds a prohibited or allowed pattern, ensuring to de-dupe with existing patterns
    --add-provider        Adds a secret provider that when called outputs secret patterns on new lines
    --aws-provider        Secret provider that outputs credentials found in an ini file
    --register-aws        Adds common AWS patterns to the git config and scans for ~/.aws/credentials
    -r, --recursive       --scan scans directories recursively
    --cached              --scan scans searches blobs registered in the index file
    --no-index            --scan searches files in the current directory that is not managed by Git
    --untracked           In addition to searching in the tracked files in the working tree, --scan also in untracked files
    -f, --force           --install overwrites hooks if the hook already exists
    -l, --literal         --add and --add-allowed patterns are escaped so that they are literal
    -a, --allowed         --add adds an allowed pattern instead of a prohibited pattern
    --global              Uses the --global git config

ちなみに,コマンド自体は /usr/local/bin/git-secrets にある.

$ which git-secrets
/usr/local/bin/git-secrets

セットアップ

git-secrets のセットアップはリポジトリ単位に行う.適当なリポジトリのルートディレクトリに移動して git secrets --install を実行すると,3種類の hooks が登録される.

$ git secrets --install
✓ Installed commit-msg hook to .git/hooks/commit-msg
✓ Installed pre-commit hook to .git/hooks/pre-commit
✓ Installed prepare-commit-msg hook to .git/hooks/prepare-commit-msg

ただし,既に hooks を使っている場合,エラーになる.この場合は --force オプションを付けて強制的に上書きする必要がある.

$ git secrets --install
.git/hooks/commit-msg already exists. Use -f to force

残念ながらマージする機能はないため,一度 hooks を退避した後に上書きして,戻す必要がありそう.

$ git secrets --install --force
✓ Installed commit-msg hook to .git/hooks/commit-msg
✓ Installed pre-commit hook to .git/hooks/pre-commit
✓ Installed prepare-commit-msg hook to .git/hooks/prepare-commit-msg

AWS アクセスキーのコミットを防ぐ場合

AWS 関連のリポジトリの場合は,デフォルトで用意されている git secrets --register-aws を使う.そうすると,アクセスキー/アカウントを対象にコミットを防ぐことができる.

$ git secrets --register-aws

--list オプションで,正規表現などの設定値を確認することができる.secrets.allowed に入ってる値は example AWS keys と README.md に書いてあった.

$ git secrets --list
secrets.providers git secrets --aws-provider
secrets.patterns [A-Z0-9]{20}
secrets.patterns ("|')?(AWS|aws|Aws)?_?(SECRET|secret|Secret)?_?(ACCESS|access|Access)?_?(KEY|key|Key)("|')?\s*(:|=>|=)\s*("|')?[A-Za-z0-9/\+=]{40}("|')?
secrets.patterns ("|')?(AWS|aws|Aws)?_?(ACCOUNT|account|Account)_?(ID|id|Id)?("|')?\s*(:|=>|=)\s*("|')?[0-9]{4}\-?[0-9]{4}\-?[0-9]{4}("|')?
secrets.allowed AKIAIOSFODNN7EXAMPLE
secrets.allowed wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

--list オプションは git config を参照しているので,直接 git config を叩いても,同じ情報が確認できる.同じく secrets.allowed に入ってる値は example AWS keys だから問題なし.

$ git config -l | grep secrets
secrets.providers=git secrets --aws-provider
secrets.patterns=[A-Z0-9]{20}
secrets.patterns=("|')?(AWS|aws|Aws)?_?(SECRET|secret|Secret)?_?(ACCESS|access|Access)?_?(KEY|key|Key)("|')?\s*(:|=>|=)\s*("|')?[A-Za-z0-9/\+=]{40}("|')?
secrets.patterns=("|')?(AWS|aws|Aws)?_?(ACCOUNT|account|Account)_?(ID|id|Id)?("|')?\s*(:|=>|=)\s*("|')?[0-9]{4}\-?[0-9]{4}\-?[0-9]{4}("|')?
secrets.allowed=AKIAIOSFODNN7EXAMPLE
secrets.allowed=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

実際にアクセスキーをコミットしてみる

正規表現に合致する ABCDEFGHIJKLMN123456 というアクセスキー(サンプル)を README.md に書いてコミットしようとすると,以下のエラーが出てコミットできないようになった.

$ git commit -m'Added access key'
README.md:50:ABCDEFGHIJKLMN123456

[ERROR] Matched one or more prohibited patterns

Possible mitigations:
- Mark false positives as allowed using: git config --add secrets.allowed ...
- Mark false positives as allowed by adding regular expressions to .gitallowed at repository's root directory
- List your configured patterns: git config --get-all secrets.patterns
- List your configured allowed patterns: git config --get-all secrets.allowed
- List your configured allowed patterns in .gitallowed at repository's root directory
- Use --no-verify if this is a one-time false positive

今回は AWS の例を試したが,--add オプションを使えば,任意の正規表現も登録できるため,他の SaaS などを使ってる場合などにも簡単に対応できる.

スキャン機能

--scan オプションを使うと,リポジトリを対象に既にコミットされていないかをスキャンすることができる.

$ git secrets --scan

さらにこのオプションでは git secrets --aws-provider で取得した ~/.aws/credentials の値を対象にチェックもしてくれるため,気が利いている.

まとめ

git-secrets は,地味な感じもあるけど,非常に便利なツールだった.AWS としても,誤ってコミットされてしまって事故が起きてしまうことは望んでないだろうし,もっと普及すると良さそう.git-secrets をまだ使ってない人はすぐ使いましょう!

SRE Tech Talks #2 に参加してサービス運用の事例を聞いてきた

先週 SRE Tech Talks #2 に参加してきた.僕も仕事ではウェブオペレーションをメインで担当しているけど,他社の事例を聞くのは刺激になるし,まだまだできてないことが多くあるなと感じた.特に「オペレーションの効率化をソフトウェアエンジニアリングで実現する」という価値観が凄い良い表現で刺さった.

eventdots.jp

On-call Engineering @cubicdaiya

  • SRE のミッション
    • Operation(サービスの信頼性を向上させる)
    • Software Engineering(サービスをスケールさせるためのツールなどを開発する)
  • On-call
    • SRE でローテーションしている
    • 1週間毎に交代する
    • SRE 全員が電車通勤中であることを避けるために On-call 担当は自宅待機して時差出勤する
    • On-call 当番の負担は大きい
      • 精神的なプレッシャー
      • 同居人への負担
      • 深夜問わず
    • 振休や手当を支給している
    • Slack Bot を活用して PagerDuty 経由で電話をかけられるようにしている
    • Slack がダウンしている場合も考慮して Wiki にも電話番号をまとめている

質疑応答が大量に出てて,1番盛り上がっていた.「オンコール」という誰しも興味のあるテーマだったのも良かったんだと思う.

「オンコール」の運用としては,非常に徹底した運用をしているなと感じた.特に意図的に時差出勤をしているという話は今まで聞いたことがなかった.Slack と PagerDuty を活用してオンコールを自動化してるのは素晴らしくて,真似したいところ.質疑応答にもあったけど,各 SRE が全ての機能を把握できるわけではないため,困ったら他のメンバーに連絡して助けてもらうこともあるし,障害対応後にはドキュメントを整理して振り返ることができるようにしているとのことだった.

speakerdeck.com

cybozu.com のデータバックアップとリストア、それを活用したリハーサル @toshi_pp

  • サイボウズのアーキテクチャ
    • マルチテナント
    • マルチアプリケーション
    • マルチバックエンド
  • ミドルウェアに依存しないようにディスクを増分バックアップして管理している
  • アップデートのリハーサル
    • 実際にバックアップが必要になることが少なくてもリハーサルをする
    • 全ては安心のため

発表を聞いていたら「独自の…」「カスタマイズした…」といった部分が多くあるらしく,運用が大変そうだなぁと客観的に感じた.復旧手順をリハーサルするのは素晴らしいと思ったし,昔 SIer で働いていたときに様々なリハーサルをしたことを思い出した.特にディザスタリカバリ系のリハーサルは「本当に起きるのかねぇ」と半信半疑だったけど,正常にフェールオーバーできたり,リストアできることの安心感は重要だと思う.まさに数日前に GitLab の障害があって,バックアップ&リストアを見直した人も多そう.

www.slideshare.net

cookpad.com 全 HTTPS 化の軌跡 @kani_b

  • インフラストラクチャー部
    • SRE グループ
    • 社内 IT インフラグループ
    • データ基盤グループ
    • セキュリティグループ
  • 今までは http と https の混在環境
  • なぜ HTTPS 化したのか
    • セキュリティ
      • 保護できるならする
    • プラットフォーム
      • ATS (iOS)
      • 検索エンジンも HTTPS を優遇する
    • 新技術
      • HTTP/2
      • ServiceWorker
  • パフォーマンス
    • TLS Handshake と暗号化のオーバーヘッドは確実に存在する
    • ただ回線の高速化で体感できるほどの差ではない
  • 検索エンジン
    • 信じるしか無い
  • Mixed Content をひたすらに消していく
  • 全社にアナウンスをした
    • 何かあったらすぐにアラートしてくれる

「レシピサイトに暗号化が必要なのか?」という話は深かった.ユーザーがもしかしたら「閲覧したことを知られたくないかもしれない」なんて考えたことも無かったし.Windows XP も公式にサポートする姿も素晴らしかった.プラットフォームとして大きく成長して,ユーザーを第一に考えていることの証だなぁーと.

speakerdeck.com

SREグループができてこの半年間やってきたこと @isaoshimizu

  • XFLAG(主にモンストを運用している)
  • SRE はウェブオペレーション,デプロイ,モニタリングなどを担当する
  • オンコール当番は11名で2人ごとにローテーションしている
  • 年末年始の対策をした
  • innodb_io_capacity
    • レプリケーション遅延を緩和できるように
  • innodb_spin_wait_delay
    • os_waits を減らせた
  • Transparent HugePages 問題
    • OFF にすると良い

MySQL をカリカリにチューニングしている話で勉強になった.約1300台のサーバを管理しているって…モンストの規模大きいなぁ…!

speakerdeck.com

Arukasの運用事例と、末永くインフラ運用していくためのTips @uzyexe

  • “Hope is not a strategy”
  • 見積もっていた10倍の速度でサービスが成長しているため,運用が追い付かない
  • オンコールは PagerDuty を使っている
  • プロビジョニングは Chef や Ansible を使わずに Terraform for Sacloud + CoreOS + Cloud-Config を使っている
  • Mesos + Marathon でリソースの制御をしている
  • 99.999 %
    • 可用性における5番目の “9” はヒューマンエラー

最近知ったんだけど Arukas って逆から読むと Sakura なんだよなー!気付いたときは驚いた.見積もった10倍で成長してしまうのは厳しい気もするけど,最終的にはビジネス的に招待予約制を導入して,成長を抑える判断になっているのは,サービスの信頼性の観点でも良いと思った.Mesos + Marathon の話は知識がなくてよく理解できなかった.

www.slideshare.net

関連記事

タイミング良く無料公開となった SRE 本!まだ読めてないけど,必ず読もうと思う.SRE 本の輪読会やってる会社もあるらしく,良いなぁ!

MySQL on EC2 → Aurora にレプリケーションをしてみた

既にサービスで稼働している MySQL on EC2 を Aurora に移行するために,以下のようなレプリケーション環境を検証用に構築して試した.Percona Xtrabackup でリストアをすると高速にできるらしいけど,今回は環境の制約もあって mysqldump 経由でリストアをする設計を選んだ.

f:id:kakku22:20170203185237j:plain

レプリケーション環境を構築する手順は以下のドキュメントに詳しくまとまっていた.

バイナリログを出力する

今回は dbs on EC2 → Aurora Writer にレプリケーションをするため,スレーブ環境でもバイナリログを出力しておく必要があった.詳細は割愛するが /etc/my.cnflog-bin を追記して対応した.

mysqldump に --master-data=2 オプションを追加した

mysqldump で取得したバックアップをベースラインとしてレプリケーションをする場合に CHANGE MASTER TO で合わせるポジションを把握する必要がある.そのためには mysqldump に --master-data オプションが必要で,今回は CHANGE MASTER TO をコメント状態で出力するために --master-data=2 とした.--master-data のまま出力してしまうとリストア時に CHANGE MASTER TO も流れてしまうため --master-data=2 にしておくと良い.

-- Position to start replication or point-in-time recovery from
--

-- CHANGE MASTER TO MASTER_LOG_FILE='bin.000001', MASTER_LOG_POS=12345;

Aurora Writer でレプリケーションを開始するときに CHANGE MASTER TO は使えない

出力したバックアップを Aurora にリストアしたら,次はポジションを合わせてレプリケーションを開始する.ただし RDS では CHANGE MASTER TOSTART SLAVE が実行できないようになっていて,実行しようとすると,権限のエラーが出る.

mysql> CHANGE MASTER TO MASTER_HOST='xxx',
    -> MASTER_USER='replication',
    -> MASTER_PASSWORD='password',
    -> MASTER_LOG_FILE='bin.000001',
    -> MASTER_LOG_POS=12345;
ERROR 1227 (42000): Access denied; you need (at least one of) the SUPER privilege(s) for this operation

mysql> START SLAVE;
ERROR 1045 (28000): Access denied for user 'xxx'@'%' (using password: YES)

どうするかと言うと,RDS 側に登録されているストアドプロシージャを使う必要がある.

実際に発行するコマンドとしては以下のようになる.ストアドプロシージャに与える値は CHANGE MASTER TO と同じなので,特に困ることは無いかと思う.ただ1点,ホスト名に Private IP を指定する必要があった.今の構成だと EC2 に hosts を配ってるため,ホスト名で参照できていたが,Aurora から見ると参照できなかった.

mysql> CALL mysql.rds_set_external_master ('1.2.3.4', 3306, 'replication', 'password', 'bin.000001', 12345, 0);
mysql> CALL mysql.rds_start_replication;
mysql> SHOW SLAVE STATUS\G

あとは Read_Master_Log_Pos あたりの値を見ながらモニタリングすれば大丈夫かと.ちなみに,レプリケーションを停止するときは,以下のストアドプロシージャを実行する.

Aurora Writer の Seconds_Behind_Master は CloudWatch で見れなかった

dbs on EC2 → Aurora Writer のレプリ遅延をモニタリングしたかったけど,CloudWatch では難しそうだった.Aurora では「Aurora バイナリログレプリカの遅延 : AuroraBinlogReplicaLag」メトリクスがあるけど,これは Aurora Writer → Aurora Reader のレプリ遅延のことで,Aurora Writer のメトリクスではなかった.よって,取り急ぎ Aurora Writer で SHOW SLAVE STATUS; を実行して,Seconds_Behind_Master の値を確認するようにしている.

CloudWatch で取得してるメトリクスに関しては,以下のドキュメントに詳しく載っている.

docs.aws.amazon.com

まとめ

稼働中の MySQL on EC2 を Aurora にレプリケーションする構成を簡単に構築できた.レプリケーションの階層は多いけど,特に気になるレプリ遅延は無かった.引き続き検証を続けていく!

Aurora のパラメータグループで max_connections の値が計算値と合わない

最近 Aurora の検証をしているので,今後は Aurora 関連の記事を書く機会が増えそう.

前提

  • RDS (Aurora MySQL)
  • インスタンスタイプ : db.t2.medium

DBInstanceClassMemory とは

RDS のパラメータグループでは,特定の変数と演算子を使った動的な値設定ができる.今回は変数 DBInstanceClassMemory に関して調べたことと,計算が合わずに困ったことを書いておこうと思う.

DBInstanceClassMemory は,名前だけを見るとインスタンスタイプごとに搭載されたメモリサイズのように思えるけど,実際には違っていて,RDS プロセスに割り当てられたメモリサイズのことを意味する.よって,搭載されたメモリサイズよりは確実に小さい値となる.その点はドキュメントにも書いてある.

DBInstanceClassMemory
現在の DB インスタンスに関連付けられている DB インスタンスクラスに割り当てられたメモリのバイト数を返します。このメモリは、インスタンスを管理する Amazon RDS プロセスによって使用されるメモリよりも小さくなります。 docs.aws.amazon.com

DBInstanceClassMemory を参照しているパラメータ

デフォルトのパラメータグループ "default.aurora5.6" で,以下の4パラメータが DBInstanceClassMemory を参照している.特に innodb_buffer_pool_sizemax_connections などは,ワークロードに応じてチューニングが必要なので,Aurora クラスタのデフォルト値を理解しておくことは重要だと考えている.

  • innodb_buffer_pool_size
  • max_connections
  • query_cache_size
  • thread_cache_size

f:id:kakku22:20170202172100j:plain

逆算して DBInstanceClassMemory を知る

まず,デフォルトのパラメータグループのまま起動したクラスターの Aurora Writer で,上記のパラメータの値を確認してみた.

mysql> SHOW VARIABLES LIKE 'innodb_buffer_pool_size';
+-------------------------+------------+
| Variable_name           | Value      |
+-------------------------+------------+
| innodb_buffer_pool_size | 1610612736 |
+-------------------------+------------+
1 row in set (0.00 sec)

mysql> SHOW VARIABLES LIKE 'max_connections';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 90    |
+-----------------+-------+
1 row in set (0.01 sec)

mysql> SHOW VARIABLES LIKE 'query_cache_size';
+------------------+----------+
| Variable_name    | Value    |
+------------------+----------+
| query_cache_size | 89498624 |
+------------------+----------+
1 row in set (0.01 sec)

mysql> SHOW VARIABLES LIKE 'thread_cache_size';
+-------------------+-------+
| Variable_name     | Value |
+-------------------+-------+
| thread_cache_size | 2     |
+-------------------+-------+
1 row in set (0.00 sec)

まず最初に innodb_buffer_pool_size の値から逆算して DBInstanceClassMemory を調べてみた.db.t2.medium のメモリサイズは 4GB なので,以下の式に当てはめて逆算すると,DBInstanceClassMemory は 2GB だとわかった.よって db.t2.medium においては,メモリサイズの 50% が DBInstanceClassMemory に割り当てられていることがわかった.

innodb_buffer_pool_size = {DBInstanceClassMemory*3/4} = 2147483648 * 3 / 4 = 1610612736

ちなみに,この割合は固定値ではなく,インスタンスタイプが良くなればなるほど,上がっていく.以下の記事を見ると,最高スペックの db.r3.8xlarge だと 96.4% が DBInstanceClassMemory に割り当たっていることがわかる.

query_cache_sizethread_cache_size も同様に逆算する

同様に query_cache_sizethread_cache_size も値から逆算すると,DBInstanceClassMemory は 2GB だとわかった.よって,db.t2.medium だと DBInstanceClassMemory は 2GB だとほぼ断定できそう.

query_cache_size = {DBInstanceClassMemory/24} = 2147483648 / 24 = 89478485.3333333
thread_cache_size = {DBInstanceClassMemory/1005785088} = 2147483648 / 1005785088 = 2.135131723

あれれ max_connections の計算が合わないぞ?

やっと今回の本題に入る.max_connections の式は以下のようになっていて,GREATEST 関数に含まれてる値の中で,一番大きい値が割り当たるようになっている.

GREATEST({log(DBInstanceClassMemory/1073741824)*45},{log(DBInstanceClassMemory/8187281408)*1000})

よって DBInstanceClassMemory を 2GB だとすると,以下の計算となり,値は 45 だと推測できる.

{log(DBInstanceClassMemory/1073741824)*45} = log(2147483648/1073741824) * 45 = 45
{log(DBInstanceClassMemory/8187281408)*1000} = log(2147483648/8187281408) * 1000 = -1930

でも実際には 90 だった.計算が合わない.

mysql> SHOW VARIABLES LIKE 'max_connections';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| max_connections | 90    |
+-----------------+-------+
1 row in set (0.01 sec)

デフォルトの式で max_connections を 90 にするには DBInstanceClassMemory が 4GB である必要があって,そうすると db.t2.medium に搭載されたメモリサイズと一致してしまう.となると,パラメータによって DBInstanceClassMemory の値が違う?そんなはずは無いだろう.うーん謎だ.

{log(DBInstanceClassMemory/1073741824)*45} = log(4294967296/1073741824) * 45 = 90

AWS サポートに問い合わせた

AWS サポートに問い合わせたところ,原因が判明した.

  • まず db.t2.mediumDBInstanceClassMemory は 2GB ではなく 2.0004 GB "程度" であること
    • innodb_buffer_pool_size の値から逆算すると気付けなかった
  • 2.0004 GB の前提で log 計算をすると log(2147913144.7296/1073741824) = 1.00028 となる
  • 1.00028 を 2.0 に "切り上げ" てから 45 を乗算するため 2 * 45 = 90 となる

結論として,ドキュメントに書かれていないロジックになっていて,逆算することは難しかった.今後 max_connections の計算式をもっと簡単にする予定があるらしく,今後に期待!(まぁ実際の運用を考えると max_connections をデフォルト値で運用することは無さそうなんだけど...)

Black Belt

www.slideshare.net

golang.tokyo #3 に参加してパフォーマンスの話を聞いてきた

先週 golang.tokyo #3 に参加した.抽選倍率2倍だったからダメかもなぁ…!と思って申し込んだら当たった.

テーマは「パフォーマンスチューニング」だったけど,「パフォーマンスチューニング」とは違うような話もあった.エウレカの話も聞きたかったから残念!

golangtokyo.connpass.com

Accelerating real applications in Go @cubicdaiya

  • GitHub - kazeburo/chocon
    • Golang 標準の net/http で簡単にプロキシサーバを立てられる
    • ただ細かくパラメータをチューニングするためには net/http/client.gonet/http/transport.go を使う
    • 特に MaxIdleConnsPerHost はデフォルト値 2 だから小さくなっている
  • GitHub - mercari/gaurun: General push notification server in Go
    • goroutine 数やチャネルのサイズをメトリクスとして取得できるようにしている
    • モニタリングできるようにしている

メルカリのプロダクション環境に導入されているソフトウェアの話で非常に深かった.パパあるあるだと思うけど「チョコン」って聞くと「コッシーの友達のチョコン」のことを考えてしまうので,発表中に変にニヤニヤしてしまった…w

PERFORMANCE OPTIMIZATIONS / Carlo Alberto Ferraris

  • サーバ費用より人を雇う方がコストが高い
  • オプティマイズするよりスケールアウトした方が良い
  • The Twelve-Factor App
  • 失敗する前提で考える

Golang の話ではなく,サービス開発の思想的な話だった.途中から Golang の話しになるのかなぁーと思って聞いてたらそのまま終わった.話は凄く面白かった.

Stream の扱い方 / jun06t

  • ioutil.ReadAll で全て []byte に変換するとメモリを食ってしまう
  • io.Readerio.Writer を引数としている場合は Stream のまま使うと良い
  • API リクエストを decode する場合 json.Unmarshal でなく json.NewDecoder を使うと高速になる

1番テーマに沿ってる気がした.実際に同じようなコードを書くときがあったら気を付けたい.今回 Slides ってサービスが多かったけど,人気なのかな?あまり見たことがなかった.

git-schemlex と ddl-maker を使った DB migration の紹介 @Konboi

タイミング良くマイグレーションツールの調査をしていたので参考になった.Golang 製だと Goose も人気かなと思うけど,既存スキーマに対してエクスポートができないという点に困ってて,うまく運用にハマる気がしてない.そうなると Ruby 製だけど GitHub - thuss/standalone-migrations: A gem to use Rails Database Migrations in non Rails projects かなぁ…と考えているところ.

speakerdeck.com

database/sql とコネクション / Talos208

  • database/sql を使う場合 db.Close() はするべきではない
  • 1度 Open したらそのままにして Open と Close のコストを下げることができる
  • ソースを追うとよくわかる
  • Golang 1.6 から入った SetConnMaxLifetime() で期限切れのコネクションを再利用しなくなった

www.slideshare.net

関連記事

既に参加者の記事が上がっていた!

kysnm.hatenablog.com

developers.cyberagent.co.jp

裏番組

mackerelio.connpass.com

実は裏番組で Mackerel Meetup #9 もあった.Mackerel 活用してるから参加したかったし,お世話になってる @ariarijp の LT も見たかったけど,golang.tokyo #3 を選んでしまった!たまたま抽選当たったから…w

ハッシュタグを見てたら「アノテーション機能」の話が流れてきて,あまりに待望の機能だったので,1人で興奮してた!

mackerel.io

次回の Mackerel Meetup は参加しまっす!