14Room

みんな泣きながらオトナになったんだ。

ゾンビDBの作り方 at AWS

概要

開発メンバーからの要望で毎日、本番DBから取ったバックアップを元にデータをリフレッシュするDBを作りました。 何度データを壊しても次の朝には復活してるので社内ではコレをゾンビDBと呼んでいます。

やってることは、

1.定期的に取ってるsnapshotからvolumeを作成 2.mysql止める 3.古いvolumeをアンマウント 4.古いvolumeをdetach 5.新しいvolumeをattach 6.新しいvolumeをマウント 7.mysql起動

やりたいことはシンプルですが、awsから必要な情報を取ってくるのが少々面倒です。

前提条件

  • aws cliがインストールされている
  • IAM roleで実行サーバにEC2フルアクセス権限がついてる
  • DB_backup_20141205xxxみたいなスナップショットが存在する

シェルスクリプト

#!/bin/bash

date=`date +%Y%m%d%H`
DESCRIPTION="DB_backup_$date"
instance=`curl http://169.254.169.254/latest/meta-data/instance-id`


# Create new DB volume
snap=`/usr/local/bin/aws ec2 describe-snapshots --filters Name=description,Values=$DESCRIPTION"*" --query Snapshots[*].SnapshotId --output text`
VAR="$snap"
ary=($VAR)

attach_volume=`/usr/local/bin/aws ec2 create-volume --availability-zone us-east-1d --volume-type gp2 --snapshot-id ${ary[0]} --query VolumeId --output text`

# Stop mysql
sleep 10
sudo /usr/sbin/service mysql stop
#/sbin/swapoff /var/lib/mysql/swap

# Unmount
sleep 10
sudo /bin/umount -f /var/lib/mysql

# Detach old volume
sleep 10
detach_volume=`/usr/local/bin/aws ec2 describe-volumes --filters Name=attachment.instance-id,Values=$instance Name=attachment.device,Values=/dev/sdf --query Volumes[].Attachments[].[VolumeId] --output text`

/usr/local/bin/aws ec2 detach-volume --volume-id $detach_volume --instance-id $instance

# Attach new volume
sleep 60
/usr/local/bin/aws ec2 attach-volume --volume-id $attach_volume --instance-id $instance --device /dev/sdf

# Remount volume
sleep 60
sudo /bin/mount -a

# Start mysql
sleep 10
sudo /usr/sbin/service mysql start

# Delete old volume
/usr/local/bin/aws ec2 delete-volume --volume-id $detach_volume

その他

前の処理が完全に終わってなかったりするので適当にsleepを入れてます。

capistranoでデバッグのため、ダミータスクを動かしてみる

概要

デプロイの処理を1個づつ試しながら確認したい場合が多々有ります。 そんな時はCapfileにダミータスクを追加して、そのタスクを直接動かして動作を確認してみましょう。

Capfile

例)GCPインスタンスリストをコマンドから取得する処理を確かめてみる。

namespace "hoge" do
   task :moge do
     run_locally do
       value = %x[ gcloud compute instances list ]
       print value,"\n"
     end
   end
end

実行

怖いので実行するstageはstagingとかが良いと思います。

bundle exec cap staging hoge:moge

結果

コマンドの結果が変数に入って出力できました。

$ bundle exec cap staging hoge:moge
DEBUG [9cfe186a] Running /usr/bin/env [ -d /usr/local/rbenv/versions/2.2.3 ] on staging
DEBUG [9cfe186a] Command: [ -d /usr/local/rbenv/versions/2.2.3 ]
DEBUG [9cfe186a] Finished in 0.296 seconds with exit status 0 (successful).
nativeapi-fix
nativeapi-newrelic
nativeapi-us-201510271040-bpvl
nativeapi-us-201510271040-li6e
nativeapi-us-201510271040-ptgw
nativeapi-us-201510271040-vqhe
nativeapi-us-201510271040-vy9v
nativeapi-us-201510271040-w804
nativeapi-us-201510271040-wo6y
nativeapi-us-201510271040-xqg8
nativeapi-us-201510271040-y0f4
nativeapi-us-201510271040-y5cf
nativeapi-us-201510271040-y79p
nativeapi-us-201510271040-ye7b
nativeapi-us-201510271040-yvoe
nativeapi-us-201510271040-zgbc

Google cloud shell使ってみました

Google cloud shellって?

日本語だと下記のページで概要を掴めるかと思います。

Google Cloud Platform Japan 公式ブログ: Google Cloud Shell の無料期間が 2016 年末まで延長

使ってみました

f:id:naked123:20151223182328j:plain

特に設定の必要も無くGCPのコマンドが使えますし、普通にlinuxとしても使えてSSHで他のサーバにログインなんてことも出来ました。

cronも使えました

crontabで一分ごとにloglogというファイルに日付を出力してみました。 コンソールからログアウトしている時間帯もちゃんと動いていたようです。

$ cat loglog
Wed Dec 23 09:23:01 UTC 2015
Wed Dec 23 09:24:01 UTC 2015
Wed Dec 23 09:25:01 UTC 2015
Wed Dec 23 09:26:01 UTC 2015
Wed Dec 23 09:27:01 UTC 2015
Wed Dec 23 09:28:01 UTC 2015
Wed Dec 23 09:29:01 UTC 2015
$ date
Wed Dec 23 18:29:42 TLT 2015

あとがき

定期的にGCPのコマンドが実行できるので、バッチサーバでやっていた定期バックアップとかの処理をgoogle cloud shellにまかせるとサーバレス環境に一歩近づけそうですね。

local-ssdを積んだインスタンスのサイズ変更はできない

概要

local-ssdを積んだインスタンスのサイズ変更はできないので、気をつけましょう。

(local-ssdについては下記を見てもらうと雰囲気はつかめるかと思います。)

Google for Work Japan 公式ブログ: [GCP] Local SSD がどなたでも利用できるようになりました。

そもそもstop出来ない

local-ssdを積んだインスタンスはstopしてサイズ変更しようとしても、そもそも「stop」がグレーアウトして実行できません。 f:id:naked123:20151222110949p:plain

強引に起動しようとすると

マネージコンソールからはstop出来ないようになっていますが、実際にインスタンスにログインしてshutdownすることは可能です。しかし、起動しようとすると下記のようなエラーが発生します。

f:id:naked123:20151222111053p:plain

どうやら一度落とすと再度立ち上げることはできないようです。

まとめ

爆速で有名なGCPのlocal-ssdですが、local-ssdを積んだインスタンスはサイズ変更ができなくなるので使いどころを考えて利用しましょう。

あとがき

ちなみにどうしてもインスタンスサイズを変更したければ、

  1. local-ssdのデータを別ディスクに退避
  2. クローン
  3. 元のインスタンス削除
  4. 元のインスタンス名でクローン
  5. 別ディスクからデータを戻す

という手も考えられますが、面倒ですね。

GCPでサブネットが使えるようになった。

概要

AWSでは「VPC内でサブネットを切ってAPPのネットワークとDBのネットワークを分ける」みたいなことができますが、GCPでは出来ませんでした。が、いつの間にかGCPでもサブネットを切ることが出来るようになったようです。

GCPのnetworks

  • 以前のGCPではnetworkを複数のサブネットに分けることはできなかったのですが、出来るようになりました。下記のように新規作成時に複数のサブネットを作成することが出来ます。

f:id:naked123:20151221140917p:plain

  • 新規作成時だけでなく、後からメンテナンスも出来るようです。

f:id:naked123:20151221141239p:plain

ただし、昔作ったネットワークは置いてけぼり。

  • しかし、以前に作ったネットワークを見てみると・・「add subnetworks」が無い・・・。既存ネットワークをサブネットで切れないのは既にネットワークに散らばったインスタンスのIPをどうするか?が難しいからでしょうかね。 f:id:naked123:20151221141447p:plain

あとがき

引き続き、昔作ったネットワークでもサブネットが使えるようになるのを期待したいところです。

GCEのインスタンスサイズを変更する

概要

EC2だとインスタンス停止後、change instance sizeで一発ですが、gceでは下記の手順を踏んでインスタンスサイズの変更を実施します。 流れは下記の通りです。ここではmanageというインスタンスのサイズを変更してみます。

  1. サイズを変更したいインスタンスのsnapshotを取る。
  2. サイズを変更したいインスタンスを削除する。
  3. サイズを変更したいインスタンスと同じ名前のインスタンスを先ほどのsnapshotから作成(この時、希望のサイズに変更する)

snapshot取得

Snapshotsの「Create a new snapshot」でコピー元のOSが入ったディスクをSource diskに指定してsnapshotを取得。

f:id:naked123:20151217180603p:plain

インスタンスを削除する

Deleteする前に下記のデータを必ず忘れずに書き留めておくこと。

インスタンス再構築

Nameにサイズ変更したいインスタンス名を入れ、Boot diskは「Create a new disk」で先ほど作ったsnapshotをSource snapshotに指定して新規Diskを作成。zoneも忘れずに。

f:id:naked123:20151217182752p:plain

「Management, disk, networking, access & security options」をクリックして先ほどメモった内容を入力します。

  • tags f:id:naked123:20151217183401p:plain

  • network f:id:naked123:20151217183459p:plain

  • permissions f:id:naked123:20151217183518p:plain

最後に「create」をクリックして完成です。

あとがき

インスタンスサイズを変更する」、というより「同じ名前でインスタンスを再構築する」と言った方が相応しいような気がしますね(汗)

さらにあとがき(2015/12/21)

と思ったら、インスタンスを[stop]して[edit]したら下記のようにインスタンスサイズを変更できるようになっていました(汗)

f:id:naked123:20151221162813p:plain

slackにslow query数を出してみた

概要

注意しなきゃいけ無いんだけど、気が付いたらslow queryがいっぱい出ていた・・・・。なんて事を回避するために、とりあえず毎日slackにslow query数を出すようにしてみました。

Webhook URL

slackにslow query数を投げるためのWebhook URLを取得します。詳しくは下記を参照してください。 Slack

スクリプト

前日分のslow logから件数を数えてslack(上記で取得したWebhook URL)に投げています。

#!/bin/bash
date=`date '+%Y-%m-%d'`
server_name=`hostname`
url="https://hooks.slack.com/services/zzzzzzz/xxxxxx/123456789aaa?parse=full"

num=`/bin/gzip -dc /var/log/mysql/mysql-slow.log.1.gz|grep Query_time|wc -l`
message="($date)  $server_name のslow-query数は$num です。"
payload="payload={\"text\": \"${message}\", \"username\": \"tabby\", \"icon_emoji\": \":tabby6:\"}"
curl --data "${payload}" ${url}

実行

各DBサーバ上のcronで毎朝9:10に定期実行させます。

10 0 * * * /root/work/slack.sh