$shibayu36->blog;

クラスター株式会社のソフトウェアエンジニアです。エンジニアリングや読書などについて書いています。

CloudFormationでEC2の立ち上げをした

CloudFormationでVPCを構築し、CloudFormationに入門する方法を知った - $shibayu36->blog; の続き。今回は「Amazon Web Services 基礎からのネットワーク&サーバー構築 改訂版」のChapter3に従って、EC2の立ち上げとセキュリティグループの設定をした。


設定したPRは https://github.com/shibayu36/aws-network-basis/pull/2 。今回はそんなに難しくなかったのだけど、はまったところとしては

  • コンソールでの操作の流れと違い、セキュリティグループは先に作り、EC2に割り当てるという風にしないといけない
    • コンソールだと、EC2作成の時にセキュリティグループを新しく作成できる
  • ImageIdはami-***というのを直接指定したほうが楽
    • なんかマッピングを作ってそこから取り出すとかやっているところもあった
  • VPC内に作るEC2にセキュリティグループを割り当てるときは、NetworkInterfacesの設定の中にセキュリティグループ割当の設定を書く

という感じ。


終わり。

CloudFormationでVPCを構築し、CloudFormationに入門する方法を知った

最近CloudFormationに入門しようとしている。それで、AWS CloudFormation への入門に「Amazon Web Services 基礎からのネットワーク&サーバー構築」を使ってみた - えいのうにっきの記事をみて、これはいい入門の仕方だなあと思い、「Amazon Web Services 基礎からのネットワーク&サーバー構築 改訂版」を購入して、CloudFormationで構築するということをやっている。

今回はChapter2の「ネットワークを構築する」をCloudFormationでやってみた。

CloudFormationの概念や使い方を理解するには

やってみようとすると、まずCloudFormationの概念を理解するのに戸惑う。公式のチュートリアルを見ても、???となるだけだった。そこで参考にしたのが以下の資料。

dev.classmethod.jp

ただし、これを読んだだけだと、「入門3 VPCにサブネットやルーティングテーブルやインターネットゲートウェイを構築する」の設定ファイルの記述量がそこそこある & 僕はVPCをちゃんと触ったことが無かったなどの理由から、ちゃんと理解は出来なかった。

そこで、一気にVPCを全部構築するのではなくて、「Amazon Web Services 基礎からのネットワーク&サーバー構築 改訂版」で解説されているコンソールでの操作を模倣するように、一つずつリソース定義して実行を繰り返してみた。これをすると、だいぶ理解が進んで、自分で考えてCloudFormationの設定ができるようになった。

こういう感じで進めていくのがおすすめ。また https://github.com/a-know/aws-network-basicid:a-know さんが構築していった記録が残っているので、これを見ると作ってく様子をトレースできるのでおすすめ。

CloudFormationでVPCの設定

YAMLで定義した。https://github.com/shibayu36/aws-network-basis/pull/1 のPRのとおり。

どういう流れで進めていったかというと、

  • 例えば、本でVPCを作る操作をしているのを見るとすると
  • 本の操作をコンソールで実際にやってみて、VPCを作る
  • 「cloudformation vpc」でググると、AWS::EC2::VPC - AWS CloudFormationが出て来る
  • これに従って、自分で定義を書いてみる
  • CloudFormationで実行する
  • 自分でコンソールで作ったのと、CloudFormationで作ったものの情報を見比べて、同じものが出来ていることを確認する

という流れで、パブリックサブネット作成や、インターネットゲートウェイの作成・アタッチなどなどを一つずつ行った。一気にやると何がおかしくなったのかわからなくなるので、一つずつ記述して実行してみるというのがポイント。

まとめ

今回は「Amazon Web Services 基礎からのネットワーク&サーバー構築 改訂版」のChapter2の「ネットワークを構築する」をCloudFormationでやってみた。CloudFormationの考え方を理解できて非常に良かった。

PostgreSQLでSQLチューニングや障害状況調査に使ったクエリ達まとめ

最近PostgreSQLSQLチューニングや、DBが詰まった時の状況調査をいろいろやった。その時に便利だったクエリ達をまとめていく。PostgreSQLのバージョンは9.6系です。

SQLチューニングなどに便利だったクエリ達

それ以降に実行するSQLの実行時間を表示する。参考 https://morumoru00.wordpress.com/2011/05/08/postgresql-sql%E5%87%A6%E7%90%86%E6%99%82%E9%96%93%E3%82%92%E8%AA%BF%E3%81%B9%E3%82%8B%EF%BC%88timing/

\timing


実際にクエリを実行して実行計画や実行時間を表示する。クエリが実行されるので破壊的な操作も実行されてしまうことに注意。トランザクション張って最後にROLLBACKしましょう。参考 https://www.postgresql.jp/document/9.6/html/sql-explain.html

BEGIN; EXPLAIN ANALYZE ...; ROLLBACK;


テーブルサイズや行数など、色んな情報込みで眺める。テーブルの肥大化やインデックスの肥大化などの様子を知ることが出来る。参考 https://qiita.com/awakia/items/99c3d114aa16099e825d

SELECT pgn.nspname, relname, pg_size_pretty(relpages::bigint * 8 * 1024) AS size, CASE WHEN relkind = 't' THEN (SELECT pgd.relname FROM pg_class pgd WHERE pgd.reltoastrelid = pg.oid) WHEN nspname = 'pg_toast' AND relkind = 'i' THEN (SELECT pgt.relname FROM pg_class pgt WHERE SUBSTRING(pgt.relname FROM 10) = REPLACE(SUBSTRING(pg.relname FROM 10), '_index', '')) ELSE (SELECT pgc.relname FROM pg_class pgc WHERE pg.reltoastrelid = pgc.oid) END::varchar AS refrelname, CASE WHEN nspname = 'pg_toast' AND relkind = 'i' THEN (SELECT pgts.relname FROM pg_class pgts WHERE pgts.reltoastrelid = (SELECT pgt.oid FROM pg_class pgt WHERE SUBSTRING(pgt.relname FROM 10) = REPLACE(SUBSTRING(pg.relname FROM 10), '_index', ''))) END AS relidxrefrelname, relfilenode, relkind, reltuples::bigint, relpages FROM pg_class pg, pg_namespace pgn WHERE pg.relnamespace = pgn.oid AND pgn.nspname NOT IN ('information_schema', 'pg_catalog') ORDER BY relpages DESC;

auto_explainを使って一定以上遅いクエリを自動でEXPLAIN ANALYZEしてログに表示する。MySQLのスロークエリログみたいなやつ。これは PostgreSQLでauto_explainを使ってどのクエリが遅いか把握する - $shibayu36->blog; に詳しく書きました。

PostgreSQLの現在の状況を把握するクエリ達

DBの障害時などに使うことができるクエリ達。

現在実行中のクエリ一覧。参考 https://www.postgresql.jp/document/9.6/html/monitoring-stats.html

SELECT * FROM pg_stat_activity where state != 'idle' order by query_start asc;


現在active状態で、1分以上実行されているクエリを探す。

SELECT pid,client_addr, query_start, query FROM pg_stat_activity WHERE state = 'active' AND query_start < ( current_timestamp - interval '1' minute ) AND pid <> pg_backend_pid() ORDER BY query_start;


現在のロック状況を見る。grantedがtならロックを獲得できているし、fならロック待ち状態。参考 https://www.postgresql.jp/document/9.6/html/view-pg-locks.html

SELECT locktype, pg_locks.pid, mode, relation::regclass, usename, application_name, client_addr, query_start, state_change, granted, state, query FROM pg_locks INNER JOIN pg_stat_activity ON pg_locks.pid = pg_stat_activity.pid WHERE pg_locks.pid <> pg_backend_pid();


ロック待ちで待機しているクエリを見る。

SELECT locktype, pg_locks.pid, mode, relation::regclass, usename, application_name, client_addr, query_start, state_change, granted, state, query FROM pg_locks INNER JOIN pg_stat_activity ON pg_locks.pid = pg_stat_activity.pid WHERE granted = false AND pg_locks.pid <> pg_backend_pid();


masterかslaveか確認。マスタとして動作していた場合はfalseが変えるし、slaveの時はtrue。レプリが切れていたら両方false。参考 http://tyawan080.hatenablog.com/entry/2014/05/12/234226

SELECT pg_is_in_recovery();


そもそもレプリケーションできているか。レプリケーションが出来ていないと空が返る。

SELECT * FROM pg_stat_replication;


特定のクエリが詰まっててDBに影響を及ぼしている場合に、指定したpidのクエリを殺す。

SELECT pg_terminate_backend(<pid>);


条件にマッチするクエリを一括で殺す。殺す範囲がでかいので自己責任で...以下の例は1分以上実行しているSELECT文を殺すもの。

SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE state = 'active' AND query LIKE 'select%' AND query_start < ( current_timestamp - interval '1' minute ) AND pid <> pg_backend_pid();

その他便利だったクエリ達

SELECTした結果をタブ区切りでファイルに出力する。

$ psql database_name -h ... -A -F $'\t' -c "SQL" > result.tsv


テーブルの特定のカラムの分布図を表示。参考 https://www.postgresql.jp/document/9.6/html/view-pg-stats.html

select most_common_vals, most_common_freqs, histogram_bounds from pg_stats where tablename = 'table' and attname = 'column';


テーブルの特定カラムのNULL値の割合を表示

select null_frac from pg_stats where tablename = 'table' and attname = 'column';


テーブルの特定カラムの統計情報をいろいろ表示。割合やdistinctした時の数など。

select * from pg_stats where tablename = 'table' and attname = 'column';


条件にマッチする設定パラメータを表示。

select name, setting, unit, short_desc from pg_settings where name LIKE '%autovacuum%';


oidをrelation名などに変換。pg_locksとかでどのrelationをロックしてるかとかはoidで出てくるのだけど、そのままだと意味不明なので、::regclassで変換してあげるといい。

select <oid>::regclass;

まとめ

今回はSQLチューニングや障害状況調査に最近使ったクエリ達をまとめてみました。他にもこういうのが便利というのがあったら是非教えてください。