バックアップは「ショー用」ではありません。 パート1:監視、データベースのバックアップとレプリカ

バックアップスクリプトの作成は、常に単純で退屈な非常に一般的なタスクのようです。 スクリプトを書き、それを冠に入れ、それが機能したことを確認します-すべてが正しいように見えるでしょうか? しかし、これは氷山の一角にすぎず、膨大な数の問題が水面下に隠されています。 データ削除操作がバックアップで実行されなかったことが判明したときのgitlabの最近の問題を誰もが覚えていますが、メインデータベースサーバーでは、バックアップのサイズは0バイトであることが判明し、S3のバックアップは利用できませんでしたが、幸いなことに、バックアップは他のサーバー。



画像



バックアップが本当に機能することを確認する方法は? また、スクリプトが機能していても、アーカイブにデータはありますか? バックアップに必要なものは何ですか? 統計によると、バックアップの問題は21日ごとに1回発生します。 この時間よりも長くバックアップをチェックしていない場合は、問題が発生している可能性があります。 投稿では、2,000台のマシンの異種インフラストラクチャでバックアップシステムを作成した経験、さまざまなシステムの20テラバイトの毎日のバックアップ、途中で遭遇した問題、およびそれらの解決方法について説明します。



長い間、私たちはクライアントとのバックアップの体系的な組織化に対処していませんでした。 誰かが自分でそれをやっている、誰かがリポジトリに「スクリプトのカップル」をセットアップするように私たちに尋ねた、誰かが古い管理者からのスクリプトを持っていた-私たちはそれらが本当に存在することを確認し、この知識で生き続けました。 それは顧客の数が百を超えるまででした。 ほとんどすべてのプロジェクトは活発な生活を送っており、他のエンジニアリングプロジェクトと同様に、クライアントに問題を引き起こす主な要因は人的要因です。 データを誤って削除することはまれですが、最も不快な例です。



クライアントはほとんどいませんでしたが、これは非常にまれであり、状況は個別に静かに処理されましたが、多数の理論が機能しました。 gitlabのような誰かが、生産システムとフェールオーバーシステムを混乱させ、誰かが統計計算スクリプトを誤って実行し、商品がオンラインストアで誤ってアンロードされました(誤った価格が読み込まれ、在庫のある商品が削除され、誤った数量情報が届きました)商品)。 毎回、ルーチンはより複雑になりました。ホストのftpストレージにバックアップがあったり、誰かが誤ってrm -rfを実行したS3または同じサーバーにバックアップしたものもありました。



場合によっては、商品の写真(商品の写真のないオンラインストアが必要な人)を削除した後、300ギガバイトのデータをダウンロードして解凍するのに何時間もかかったことが判明しました。 最悪の場合、データフォルダーが通知されずに別の場所に移動されたことが判明しました。 もはやそのように生きることはできないことが明らかになり、遅かれ早かれ、多数の理論は私たちを打ち負かすことになるでしょう。 バックアップ、統一されたバックアップ方法、データストレージ、バックアップの監視とチェックを扱う特別な部門を作成しました。 この部門の作業中に発見したことを共有してみましょう。



私たちは独自のスクリプトを書き始めました。 誰もがそうであるように、私たちは車輪の再発明が大好きです。 既存のサービスを使用しなかったのはなぜですか? 既存のプロジェクトは不必要な機能でかなり過負荷になり、スマートになりがちで、外部パッケージのインストールが必要になります。これは、サーバー構成のさまざまなタイプと形式を考えると、かなりマイナスです。



バックアップスクリプトの記述は、既存の動物園を理解するよりもはるかに簡単でした。 主にbashはpythonとは異なり、依存関係を必要とせず、私たちにバインドしないため、bashはすべてのものであるため、bashで記述することが決定されました。bashはすべてのシステム管理者が理解できます。



最初は、データベースダンプが最初に順番に作成され、次にサイトファイルがバックアップされたスクリプトが1つしかありませんでした。 時間が経つにつれて、それを3つに分割しました。そのうちの1つが失敗した場合、最初に関係なく、もう1つが引き続き開始されます。



まず、3つの簡単なスクリプトを作成しました。





監視について



独自の監視システムがあるため、スクリプトを組み合わせて、バックアップの作成時に障害に関するアラートを受信することをお勧めします。 最初のステップは、出口デコレーターを追加することでした。



tar(ファイルアーカイブ)の場合:



die_if_tar_failed() { exitcode=$? #1 is ok [ $exitcode -eq 0 -o $exitcode -eq 1 ] && return 0 echo `date +"%Y-%m-%d-%H%M%S"` $1 exitcode $exitcode >>${ERROR_LOG} exit 1 }
      
      





他のすべての場合:



 die() { exitcode=$? echo `date +"%Y-%m-%d-%H%M%S"` $1 exitcode $exitcode >>${ERROR_LOG} exit 1 }
      
      





失敗した場合、終了コードエラーがログに記録されます。 ログ内のエントリの存在は監視エージェントによってチェックされ、監視エージェントはその番号をアラートにプッシュします。 文字による通知を設定することにより、監視なしで同じロジックを使用できます。たとえば、スクリプトの最後またはクラウンに追加できる小さなスクリプトです。



 #!/bin/bash if [ $(wc -l /backup/logs/error.log | awk '{print $1}') -gt 0 ] ; then mail -s "Backup alert" mail@example.ru < /backup/logs/error.log fi
      
      





問題が修正された後、エラーをリセットすることを忘れないでください:



 echo -n > /backup/logs/error.log
      
      





時間が経つにつれて、単純なアラートだけでは十分ではなくなり、ストレージ内のバックアップをさらに確認し始めました。これについては次の投稿で説明します。



DBMSとレプリカのバックアップについて



私たちはどういうわけかこれについて私たちのブログ( ここここ )で詳しく話しました。



バックアップはすぐにストアにストリーミングします:



 /usr/bin/innobackupex --defaults-extra-file=/root/.my.cnf --no-timestamp $DIR/$DT --slave-info --parallel=1 --stream=tar 2>> $LOG | gzip -c | ssh ${SSH} "cat -> ${REMOTE_PATH}/${BACKUP_NAME}" || check_in innobackupex
      
      





バックアップはローカルに保存されます:



 /usr/bin/innobackupex --defaults-extra-file=/root/.my.cnf --slave-info --no-timestamp --stream=tar ./ 2>>$LOG | gzip - > ${BACKUP_NAME}; check_in innobackupex
      
      





または、gzipの実行中にクライアントがすべてを処理する場合は、リポジトリで圧縮できます。



 /usr/bin/innobackupex --defaults-extra-file=/root/.my.cnf --no-timestamp $DIR/$DT --slave-info --parallel=1 --stream=tar 2>> $LOG | ssh ${SSH} "gzip - > ${REMOTE_PATH}/${BACKUP_NAME}" || check_in innobackupex
      
      





クライアントが独自の個別のストレージまたはクラウドにバックアップを保存する場合、これは次のようになります。



 /usr/bin/innobackupex --defaults-extra-file=/root/.my.cnf --no-timestamp $DIR/$DT --slave-info --parallel=1 --stream=tar 2>> $LOG | gzip -9 | s3cmd put - s3://${BACKET}/${BACKUP_NAME} || check_in innobackupex
      
      





同様に、これはBitrixの例を使用して、ファイルバックアップに対して機能します。



 tar czhf - /home/bitrix/www/ --exclude=bitrix/{managed,local,stack}_cache --exclude=bitrix/backup --exclude=upload/resize_cache | ssh ${SSH} "cat -> ${REMOTE_PATH}/${BACKUP_NAME}" \; >>$LOG 2>&1 || die_if_tar_failed files_tar
      
      





Xtrabackupは、ダンプの作成中に便利で詳細なログを書き込みます。成功した場合、最後の行に常にエントリがあります。



 innobackupex: completed OK!
      
      





したがって、タイプデコレータも作成されました。



 check_in() { if [ -z "`tail -1 ${LOG} | grep 'completed OK!'`" ] then echo `date +"%Y-%m-%d-%H%M%S"` $1 >> ${ERROR_LOG} exit 1 fi }
      
      





驚くべきことに、xtrabackupバックアップを作成する際の最も一般的な間違いは、mysqlにログインできないことです。 次のオプションを使用できます。



 innobackupex --user=DBUSER --password=SECRET
      
      





ただし、設定を使用する方が便利です。



 /root/.my.cnf
      
      





機能があります:パスワード認証を使用しない場合、xtrabackupは接続できないと誓います。 この場合、構成に書き込むことができます:



 [client] user = root password =
      
      





標準的な手段によるその他のDBMSバックアップ。 例:



MongoDBでは 、バージョンが3.2以上であればすべてが簡単です。



 /usr/bin/mongodump --authenticationDatabase admin --username DBUSER --password=SECRET --archive --gzip | ssh ${SSH} "cat -> ${REMOTE_PATH}/${BACKUP_NAME}.tgz" \;
      
      





PostgreSQLの場合、ほとんどの場合、データベース全体をダンプします。



 su postgres -c pg_dumpall -U postgres | 2>>$LOG | ssh ${SSH} "gzip - > ${REMOTE_PATH}/${BACKUP_NAME}" || die_if_tar_failed
      
      





PostgreSQLのバイナリバックアップが必要な場合があります



 su postgres -c pg_basebackup -D - -Ft 2>> $LOG | ssh ${SSH} "gzip - > ${REMOTE_PATH}/${BACKUP_NAME}" || die_if_tar_failed
      
      





Redisバックアップでは、次の構成を使用します。



 echo "[`date`] backup redis 6383 started" >>$LOG CLI="redis-cli -p 6383 -h 127.0.0.1" if [ -f ~/.redispass ]; then CLI="${CLI} -a $(cat ~/.redispass)" fi dump=$(echo "CONFIG GET dir" | ${CLI} | grep ^/)/redis.rdb echo bgsave | ${CLI} >> $LOG try=10 save_complete=0 sleep 10 while [ $try -gt 0 ] && [ $save_complete -eq 0 ] ; do BG=$(echo 'info' | ${CLI} | awk -F: '/bgsave_in_progress/{sub(/\r/, "", $0); print $2}') if [[ "${BG}" = "0" ]] ; then save_complete=1 echo "Saving dump is finish" >> $LOG else echo "Wait save dump" >> $LOG try=$((try - 1)) sleep 60 fi done if [ $save_complete -eq 1 ];then tar czhf - ${DUMP} | ssh ${SSH} "cat -> ${REMOTE_PATH}/${BACKUP_NAME}" \; >>$LOG 2>&1 || die_if_tar_failed redis_6383_tarring else die redis_6383_bgsave_timeout fi
      
      





次の投稿では、サーバーとGitの設定、サイトファイル、および大容量のバックアップの整理、バックアップチェックについて説明します(パフォーマンスのチェックは必ず行います)。 そして、後で決定をオープンソースに投稿します。



All Articles