とあるサイトでDBが落ちたので調査
あるサイトのDBが落ちた。再起動で復旧したが、なぜ落ちたのか?を探っておきたい。DBログは初めて見る。
落ちるまでのログ
xxxxxx xx:12:54 mysqld_safe Number of processes running now: 0
xxxxxx xx:13:10 mysqld_safe mysqld restarted
xxxxxx xx:13:42 [Note] /usr/libexec/mysqld (mysqld 5.5.65-MariaDB) starting as process 22554 ...
xxxxxx xx:53:47 InnoDB: The InnoDB memory heap is disabled
xxxxxx xx:53:47 InnoDB: Mutexes and rw_locks use GCC atomic builtins
xxxxxx xx:53:47 InnoDB: Compressed tables use zlib 1.2.7
xxxxxx xx:53:47 InnoDB: Using Linux native AIO
xxxxxx xx:53:47 InnoDB: Initializing buffer pool, size = 128.0M
InnoDB: mmap(137756672 bytes) failed; errno 12
xxxxxx xx:53:47 InnoDB: Completed initialization of buffer pool
xxxxxx xx:53:47 InnoDB: Fatal error: cannot allocate memory for the buffer pool
xxxxxx xx:53:47 [ERROR] Plugin 'InnoDB' init function returned error.
xxxxxx xx:53:47 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
xxxxxx xx:53:47 [ERROR] mysqld: Out of memory (Needed 128917504 bytes)
xxxxxx xx:53:48 [Note] Plugin 'FEEDBACK' is disabled.
xxxxxx xx:53:48 [ERROR] Unknown/unsupported storage engine: InnoDB
xxxxxx xx:53:48 [ERROR] Aborting
xxxxxx xx:53:48 [Note] /usr/libexec/mysqld: Shutdown complete
xxxxxx xx:53:50 mysqld_safe mysqld from pid file /var/run/mariadb/mariadb.pid ended
mysqlのログからは追えない(ログの種類と出力方法が複数ある)
直接の原因はメモリ不足だということが解った。なぜメモリ不足が起きたのか?というのが次の問になるが、ここで壁に当たる。
mysqlのエラーログは5タイプあるらしい。しかし、初期設定では1つしか記録されない。残りの4つはそれぞれを有効化しないと記録されない。
これは困った。次回以降は必ず有効化しておこう。
mysqlからの調査はこれ以上できなさそう。なのでApacheログをみる。
Apacheでは特に異常無さそう
ログをざっと見たけれども、問題になりそうなログはなかった。しかし、もしかするとmysqlと同様、違うログファイルもあるのかも知れない。
メモリ使用率を確認してみる
freeコマンドでマシンのメモリ使用率を調べてみると、availableの値が全容量の半分しかない。これはスペックが足りない、という判断で良いのだろうか。
普段からメモリの割当が充分ではないという仮説は一つ立ち上がった。
過去のパフォーマンス指標と照らし合わせてみる
freeコマンドでメモリが充分でなさそうであることはわかった。過去の数値と照らしてみることができれば、突発的な事象であるかどうかは確認できそう。
そこで、過去のパフォーマンス指標を確認したく、検索をする。sarコマンドを使うと過去のパフォーマンス情報が見られるようだ。
確認してみると、やはりダウンしたタイミング(赤文字部分)で異常値がある。ただしこれはCPU使用率を表す数値なので、少し目的と異なっていた。
メモリはどうか。……これも、7日以上残す場合には設定がいるようだ。次回気をつけよう。今回は検証できる。
xx:40:01 CPU %user %nice %system %iowait %steal %idle
xx:10:01 all 3.18 0.00 0.09 0.01 0.16 96.56
xx:20:01 all 2.44 0.00 0.07 0.00 0.06 97.44
xx:30:01 all 4.26 0.00 0.08 0.00 0.11 95.54
xx:40:01 all 5.00 0.00 0.11 0.00 0.16 94.73
xx:50:52 all 12.27 0.00 3.88 22.79 0.64 60.42
xx:00:02 all 2.74 0.00 4.41 79.44 0.76 12.65
xx:10:01 all 2.66 0.00 0.10 0.23 0.12 96.89
xx:20:01 all 4.09 0.00 0.08 0.05 0.18 95.61
xx:30:01 all 4.35 0.00 0.11 0.01 0.19 95.33
xx:40:01 all 4.65 0.00 0.14 0.04 0.30 94.87
/var/log/saの中にはsa日付、sar日付というファイルがある。saではCPU、sarではさらに細かいデータが見られるようなので、試してみる。
cswch/sの値が激増している
発生時のcswch/sという数値が、通常時の20倍以上になっていることがわかった。
cswch/s = 1秒間に発生したコンテキスト切り替えの総数…との記載があったが、詳しいところはよくわからない。CPU使用率が上がるとこの数値も上がるようだ。
pswpin/s pswpoutの数値も激増
こちらは万倍レベルに上昇している。スワップのイン・アウトなので、メモリで抱えきれなくなった分をディスクに逃したりメモリに戻したりしている、ということ。どちらにせよ、オーバーフロー状態であることがわかった。
rd_sec/s wr_sec/sも激増
ここも万倍レベルで上昇。devは一つしかないので、そのデバイスへの書き込み、読み込みが急上昇したことになる。
ネットワーク関連
ネットワーク関連の数値は異常値と言えるものが見当たらなかった。
TCPソケットの数値に異常発見
tcpsckの値が通常時の100倍程度に上昇していた。DOS攻撃の類が濃厚となるのだろうか。
再度apacheログをみてみると、色々探られていることが発覚
行き詰まったので、再度Apacheのログを調べる。じっくり見ていくと、とあるIPからいろいろ探られていることが解った。
ただし、IPは大量ではないため、メモリ不足によるデータベースダウン、ということに落ち着いた。
結論としてどうか、先達に聞いてみたいものだ。身近にいないけど…。
ロードアニメーションを表示中、スクロールを禁止する
function disable_scroll(event) { event.preventDefault(); } if(navigator.userAgent.match(/iPhone|Android.+Mobile/)){ //SP = true document.addEventListener('touchmove',disable_scroll,{ passive: false }); flag = "SP"; }else{ //PC = true document.addEventListener('mousewheel', disable_scroll, { passive: false }); flag = "PC"; }; $(window).on('load',function(){ $(window).scrollTop(0); $('#wrap').fadeOut('fast',function(){ if(flag == "PC"){ // //PCスクロール禁止解除 document.removeEventListener('mousewheel', disable_scroll, { passive: false }); }; if(flag == "SP"){ // //SPスクロール禁止解除 document.removeEventListener('touchmove', disable_scroll, { passive: false }); } }); });
AWS hands on for beginners スケーラブルウェブサイトの構築の手順メモ
- VPC作成ウィザードからVPCとサブネットの作成
- VPC作成と同時にパブリックサブネットを一つ作成(パブリックサブネット-1a,10.0.0.0/24)
- パブリックサブネットをもう一つ作成(パブリックサブネット-1c,10.0.1.0/24)
- プライベートサブネットを作成(プライベートサブネット-1a,10.0.2.0/24)
- プライベートサブネットをもう一つ作成(プライベートサブネット-1c,10.0.3.0/24) - ルートテーブルの変更
- パブリックサブネットのルートテーブルを編集する
- 最初に作成されたパブリックサブネットには、インターネットゲートウェイへの設定がされたルートテーブルが渡されている
- そのルートテーブルをもう一つのパブリックサブネットに設定する
- EC2インスタンスを作成
- RDSの作成
- EC2ダッシュボードからDB用セキュリティグループを作成
- RDSダッシュボードからDBサブネットグループの作成
- データベースの作成
- ロードバランサーの設定
- 2台目のEC2を構築
- ロードバランサーとの紐付け
- RDSをマルチAZに変更
- wp-user1を選択
- マルチAZ配置を有効化して保存
- すぐに適用
- wp-user1を選択
AWSでWordPress環境を作る手順をチェックする
ハンズオンは知識の定着が弱い
完全に自分のための記事。AWSのハンズオンでWordPress環境を作ったけれどもその知識はどこまで自分に残っているのかを確認する。 確認方法は答えを見ずに手順をここに書き出し、再度ハンズオンを行って答え合わせするというアナログ方式。
構成
インターネットゲートウェイ > ロードバランサー > パブリックサブネットX2 > EC2X2とRDSX2の構成。ただし、公開後にはシングル構成にする。
手順の書き出し
- 基本のネットワーク
- EC2
- RDS
- RDSを作成
- マルチAZ構成にする
- RDSに適用するセキュリティグループを作成する
- RDSを作成
- 冗長化
以上がハンズオンの内容だったはず。 手順の抜け落ち、詳細の理解のためにこれからハンズオンを再度実施する。
ブロックエディタの制限や、知らなくて恥ずかしい思いをした関数など
Kindle Unlimited セールでインプット祭りの4冊目…かな?下記の書籍を読んだ。
結果、いくつかの関数について、恥ずかしながら知らなかったことや今後の制作に活かしていきたい知識がいくつかあり、今回はそれを読後録として書いておく。
wp_headでtitleが出力されること
知らなかった。いっつもtitleタグ書いてた。恥ずかしい…。
add_theme_support関連
html5を渡しておけば不要なtype属性を消せること バリデーションでいっつも怒られるやつ。
埋め込みブロックのレスポンシブ対応
add_theme_support('wp-block-style'); add_theme_support('responsive-embeds');
これで、埋め込みブロックはレスポンシブになるようだ。
ブロックのカラーパレットは限定できる
add_theme_support('editor-color-parret',array( array( 'name' => 'エディタで表示される色名', 'slug' => 'インラインスタイルで利用される色スラッグ', 'color' => 'カラーコード', ), ))
styleやscriptのキャッシュ対策
いつも、CSSとかJSのキャッシュが残ってしまって、時にはスーパーリロードでもダメで困っていた。
filetime関数にファイルへのパスを渡せば、ファイルパスにクエリ文字列としてファイル更新時の時間が追加されるので、キャッシュ対策になるようだ。これは嬉しい。
wp_enqueue_style('ハンドル',(get_stylesheet_uri(),array(),filetime(get_template_directory_uri().'/style.css'); wp_enqueue_script( 'my-script', get_theme_file_uri('/js/myscript.js') );
timeタグの属性を正しく出力する関数
get_the_date('W3C')
投稿タイプごとに利用できるブロックを指定できる
これは便利そう。ブロックエディタの自由度の高さが逆につらい部分と僕は考えている。 そういう意味で、テーマ側から制限できるのはありがたい。
function block_control(){ if($post -> post_type === 'post'){ return array( 'core/paragraph', 'core/image', ) } } add_filter('allowed_block_types','独自関数')
編集画面に、指定したブロック並びをつくる
さらに、これは複数のブロックを設置した状態で投稿画面を構成できる。カスタムフィールド製造業としてはありがたい機能。
function post_template(){ $obj = get_post_type_object('post'); $obj ->template_lock = 'all'; $obj -> template = array( array( 'core/heading', array( 'level' => '2', 'content' => 'h2見出しです', ), array( 'core/paragraph', array( 'placeholder' => 'ここには文章を書き込めます。', ), ) ) }
セキュリティグループとは
AWSで頻出するセキュリティグループというものがなんなのかよくわからない状態なので、自分の中での整理をする意味で書いていきたい。
「セキュリティグループとはファイアーウォールである」がわからない
AWS関連書籍などではよく「セキュリティグループとはファイアーウォールです」という説明がされている。ここで、ファイアーウォールに対する自分の理解の曖昧さに気付いた。
ウィキペディアによると、下記のように説明されている。
ファイアウォール(英: Firewall)は、コンピュータネットワークにおいて、ネットワークの結節点となる場所に設けて、コンピュータセキュリティ上の理由、あるいはその他[注釈 1]の理由により「通過させてはいけない通信」を阻止するシステムを指す。
どんな通信を許可するか?を設定できる
要は通信の監視をして、通過して良いものだけを通すということだろう。 AWSではセキュリティグループを作成し、EC2やRDSに紐付けて利用するようだ。
下の図は外から入ってくる(インバウンド)の通過許可ルールを設定する画面。プロトコルや、接続元のIPを指定していける。
例えばHTTPは全IPアドレスから許可するけれども、SSHは自分の自宅IPしか通信させない、というような設定をしていく。
サービスの数だけ適切な許可設定がある
今回、RDSにセキュリティグループを作ったときに感じたのは、セキュリティグループって、EC2だけのものじゃないんだ?ということだった。
ハンズオンでは、EC2だけでなく、ロードバランサーにもRDSにもそれぞれセキュリティグループを作り、紐付けしていた。
ロードバランサーにはHTTPだけを許可し、RDSでは開放するポートを限定していた。
当然といえば当然で、各機能ごとに必要な通信は変わるのだから、役割に応じた設定が必要。
well architected frameworkの中から特に大事な10項目(AWS公式動画の要約)
AWSの公式動画で、Well Architected FrameWorkの項目のうち、重要なのに漏れがちな10項目、というものがあった。
その内容を要約として残しておきます。
セキュリティ関連
ルートアカウントは最小限の利用にする
- MFAの有効化
- 普段使いにルートを利用しない
- アクセスキーは作らない、持たない
- 普段使いのアカウントはIAMで行う
ユーザーには最小限の権限を付与する
- IAMを利用する
- 共有アカウントにしない
- 各ユーザーに対して必要となる権限だけを付与する
- 最小限のアクセス権限から始め、必要に応じて権限を追加する
- 多くの権限を持つIAMユーザーに対してはMFAを設定する
- IAMの有効期限を設定する(退職者のIAM削除などは漏れてしまいがちだが、これで半自動化される)
- 認証情報を定期的にローテーションする(認証情報漏えい時のリスク軽減)
認証情報(アクセスキー)をハードコーディングしない
- プログラムからAWSリソースへのアクセスはIAMロールで管理する
- 認証情報はSTS(security token service)を利用するとローテーションも自動で行われるのでおすすめ。
- git-secretを利用すると、AWSの認証情報が含まれたコードをアップしようとするとエラーになる。アップロード済みのコードスキャンも可能
セキュリティ関連ログを一元管理する
- CloudTrailで操作ログの取得を設定する(基本的にONになっている)
- CloudTrailの保存期間を設定すること
- CloudTrail以外にもログの取得が可能なものもあるため、有効化すること
通知の自動化
- GuardDutyを利用すると、(明らかに)疑わしいアクティビティを検知して通知してくれる(取得したログの量に対する従量課金なので保存期間に留意)
アクセス設定を必要最低限に
- ネットワーク、各サービス、それぞれのレイヤーでアクセス権限を最低限にすること
- ネットワーク >> ネットワークACL,AWS WAF,AWS Shield
- EC2,RDSなど >> セキュリティグループ
信頼性
バックアップを取得して、定期的なリカバリテストでRTO・RPOを満たすことを確認する
- AMIの作成
- EBSのスナップシしておく
- 定期的に復旧テストを行い、手順を確認しておく
- RDSの自動バックアップ機能
- AWS BackUp
単一障害点の排除
コスト最適化
使用量の把握
- 請求ダッシュボードやAWS Cost Explorerで把握する
- IAMユーザーで請求情報を見られるように設定する(ルートで行う)
- コストエクスプローラーを有効化する(ルートで行う)
- AWS Budgetsの活用
メトリクスに基づき、リソースをサイジングする
- AWS CloudWatchでリソースの利用状況を把握する
- CloudWatchLogsでOSやアプリケーションのログを取得も可能
使用率が一定の場合
一定でない場合
- オートスケーリングなどを活用する
インスタンスタイプについて
インタンスファミリーはそれぞれ特性・世代・サイズで表現されている。定期的に見直して適切なものに変更していくことがコスト最適化に有効。
最新のインスタンスファミリーを利用する
- 最新のインスタンスファミリーの方が高性能かつ安価な場合は多い
利用率を分析し、購入オプションを検討する。また、リージョンごとの利用料金の差も考慮する
- リージョンによって価格が異なるため、ビジネス要件を踏まえた上でリージョンを選択する。
時間課金計
- オンデマンド - 柔軟性重視のもの。
- リザーブドインスタンス - 常時稼働しているサーバーむけ。
- スポットインスタンス - AWSで余剰状態のリソースを安価に提供するもの。
- -- コストエクスプローラーのリザーブドインスタンス推奨事項を参照
その他
この他にも長期利用の購入オプションがあるため、ニーズに合ったものを利用していく
- CloudFront
- DynamoDB