「webで何か」作るブログ

35歳という遅すぎるスタートをなんとかする為のブログです。基本的に自分にとっての役立ちメモ。

とあるサイトで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インスタンスを作成
    • インスタンスを起動
      • Amazon Linux2
      • t2micro
      • ネットワーク
        • ネットワーク:先に作成したVPC
        • サブネット:パブリックサブネット1aを指定
        • 自動割当パブリックIP:有効
        • ユーザーデータ:WordPressのインストールスクリプト
      • ストレージの追加
        • デフォルト
      • タグの追加
        • キー:Name
        • 値:webserver#1-user-1 -セキュリティグループの設定
        • セキュリティグループ名:web-user-1
        • 説明:web-user-1
        • ルール:HTTP、HTTPSを追加。ソースの欄で「任意の場所」を選択
    • 起動
      • キーペアの作成は任意
  • RDSの作成
    • EC2ダッシュボードからDB用セキュリティグループを作成
      • セキュリティグループ名:db-user1
      • 説明:RDS for MySQL
      • VPC:冒頭で作成したVPC
      • ルール
        • タイプ:MYSQL/Aurora
        • ソース:EC2に設定したセキュリティグループ
    • RDSダッシュボードからDBサブネットグループの作成
      • DBサブネットグループ を作成
        • 名前:db-subnet-user1
        • 説明:RDS for MySQL
        • VPC:冒頭で作成したVPC
        • サブネットの追加
          • AZ:1aを選択
          • サブネット:プライベートサブネット1aを選択
          • AZ:1cを選択
          • サブネット:プライベートサブネット1cを選択
    • データベースの作成
      • 作成方法:標準構成
      • エンジンのオプション:MySQL
      • バージョン:デフォルト
      • テンプレート:無料利用枠
      • DBインスタンス識別子:wp-user1
      • マスターユーザー名:任意
      • スターパスワード:任意
      • マスターユーザー名:任意
      • 接続:冒頭に作成したVPC
      • 追加の接続設定:サブネットグループ欄へ、先に作成したDBサブネットグループを指定
        • パブリックアクセス:なし
        • VPCセキュリティグループ:DBセキュリティグループを指定
        • AZ:1a
      • 追加の設定
        • 最初のデータベース名:wordpress
        • 自動バックアップ:任意
      • エンドポイントをコピーしておく
    • ロードバランサーの設定
      • EC2ダッシュボードからアプリケーションロードバランサーを作成
        • 名前:elb-user1
        • スキーム:インターネット向け
        • IPアドレスタイプ:IPv4
        • リスナー:HTTP(S)
        • VPC:冒頭で作成したVPC
        • AZ:1a,1c
        • 名前:elb-user1
        • セキュリティグループの新規作成
          • 名前:elb-user1
          • 説明:elb-user1
          • ルール:ポート80全て
        • ルーティングの設定
          • ターゲットグループ:新しいターゲットグループ
          • 名前:target-user1 -プロトコル:HTTP(S)
          • ポート:80
            • ヘルスチェック
              • プロトコル:HTTP(S)
              • パス:ヘルスチェックに利用するファイルへのパス(/wp-includes/images/blank.gif)
        • ターゲットの登録
        • 動作の確認
    • 2台目のEC2を構築
      • 1台目のEC2を選択して、アクションからイメージの作成
        • イメージ名:wordpress-user1
        • イメージの作成
      • AMIからインスタンスの作成 
        • AMIのアクション > 起動
          • インスタンスの設定
            • ネットワーク:冒頭で作成したVPC
            • サブネット:パブリックサブネット1c
            • 自動割当パブリックIP:有効
          • ストレージ
            • ストレージ:初期状態
          • タグの追加
            • キー:Name
            • 値:webserver#2-user1
          • セキュリティグループの設定
            • web-user1を選択
      • キーペア:任意
    • ロードバランサーとの紐付け
    • RDSをマルチAZに変更
      • wp-user1を選択
        • マルチAZ配置を有効化して保存
        • すぐに適用

AWSでWordPress環境を作る手順をチェックする

ハンズオンは知識の定着が弱い

完全に自分のための記事。AWSのハンズオンでWordPress環境を作ったけれどもその知識はどこまで自分に残っているのかを確認する。 確認方法は答えを見ずに手順をここに書き出し、再度ハンズオンを行って答え合わせするというアナログ方式。

構成

インターネットゲートウェイ > ロードバランサー > パブリックサブネットX2 > EC2X2とRDSX2の構成。ただし、公開後にはシングル構成にする。

手順の書き出し

以上がハンズオンの内容だったはず。 手順の抜け落ち、詳細の理解のためにこれからハンズオンを再度実施する。

ブロックエディタの制限や、知らなくて恥ずかしい思いをした関数など

Kindle Unlimited セールでインプット祭りの4冊目…かな?下記の書籍を読んだ。

www.amazon.co.jp

結果、いくつかの関数について、恥ずかしながら知らなかったことや今後の制作に活かしていきたい知識がいくつかあり、今回はそれを読後録として書いておく。

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]の理由により「通過させてはいけない通信」を阻止するシステムを指す。

ファイアウォール - Wikipedia

どんな通信を許可するか?を設定できる

要は通信の監視をして、通過して良いものだけを通すということだろう。 AWSではセキュリティグループを作成し、EC2やRDSに紐付けて利用するようだ。

下の図は外から入ってくる(インバウンド)の通過許可ルールを設定する画面。プロトコルや、接続元のIPを指定していける。

例えばHTTPは全IPアドレスから許可するけれども、SSHは自分の自宅IPしか通信させない、というような設定をしていく。

f:id:pochiweb:20201211085330p:plain

サービスの数だけ適切な許可設定がある

今回、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

単一障害点の排除

  • 冗長化の準備をしておく
  • 例)RDS MultiAZデプロイメントオプションでは同期レプリケーションと自動フェイルオーバーを提供してくれる
  • マネージドサービスを利用する

コスト最適化

使用量の把握

  • 請求ダッシュボードやAWS Cost Explorerで把握する
  • IAMユーザーで請求情報を見られるように設定する(ルートで行う)
  • コストエクスプローラーを有効化する(ルートで行う)
  • AWS Budgetsの活用

メトリクスに基づき、リソースをサイジングする

  • AWS CloudWatchでリソースの利用状況を把握する
  • CloudWatchLogsでOSやアプリケーションのログを取得も可能
使用率が一定の場合
一定でない場合
  • オートスケーリングなどを活用する
インスタンスタイプについて

インタンスファミリーはそれぞれ特性・世代・サイズで表現されている。定期的に見直して適切なものに変更していくことがコスト最適化に有効。

最新のインスタンスファミリーを利用する
  • 最新のインスタンスファミリーの方が高性能かつ安価な場合は多い

利用率を分析し、購入オプションを検討する。また、リージョンごとの利用料金の差も考慮する

  • リージョンによって価格が異なるため、ビジネス要件を踏まえた上でリージョンを選択する。
時間課金計
その他

この他にも長期利用の購入オプションがあるため、ニーズに合ったものを利用していく

  • CloudFront
  • DynamoDB