tjinjin's blog

インフラ要素多めの個人メモ

Re:dashインスタンスを意識高く運用する話

About

Re:dashインスタンスを使ってログデータを確認できるようにしましたが、普通に運用しているだけではつまらなかったのでいろいろ仕込んでみました。細かいことはいいから全体の構成だけ知りたいという方は構成図をご覧下さい。

話さないこと

  • Re:dashの使い方
  • Re:dashでどういうデータを表示させているか(勉強中です)

lambdaを使って定時内だけ閲覧できるようにする

EC2インスタンスをずっと動かしておくとその分課金されてしまいます。余ったお金はその分ポケモンGOに投資したいので、lambdaを使って定時内だけインスタンスを起動させておきます。こちらの記事を参考に設定しました。

dev.classmethod.jp

Route53のfailoverを使って定時後にはSorryページを表示させる

定時後などはインスタンスが落ちてしまうためアクセスができませんが、なんでサーバが落ちているのか利用者にはわかりません。そこでRoute53を使ってfailoverさせ、S3のSorryページを見せることにしました。

Web hosting機能を有効にする

まず、S3の準備をします。設定したいドメインに合わせたS3バケットを作ります。管理画面上からwebhosting機能を有効化した後にポリシーを設定します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadForGetBucketObjects",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<bucket_name>/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "xxx.xxx.xxx.xxx/32"
                }
            }
        }
    ]
}

今回Re:dashインスタンスIPアドレス制限をしているため、バケットについても同じ制限をしています。

f:id:cross_black777:20160805210934p:plain

設定できたら作ったindex.htmlをアップロードしておきます。今のところ設定しているhtmlは素朴な感じです。

本日の運用は停止しましたm(__)m

cloudwatchを設定する

次にfailoverする仕組みを設定します。Route53のヘルスチェックには以下の3つの定義ができます

  • cloudwatchでの監視
  • エンドポイントの監視(IPアドレスとポート)
  • 他のサービスのヘルスチェックと連携(ELBなど)

今回の場合インスタンスIPアドレス制限をしているので、エンドポイントに対する監視は全てfailになってしまいます。従って、今回はcloudwatchでEC2インスタンスが落ちたことを検知し、failoverさせる仕組みにしました。Re:dashインスタンスがELBに紐付いていればELBでのヘルスチェックがベターかなと思いますが、ELB代がもったいなかったのでEC2インスタンスを直接cloudwatchで監視することにしました。監視項目としてはStatus Check Failedを選択し、Re:dashインスタンスに設定します。

Route53上でHealth checkを定義する

cloudwatchの準備ができたので、Route53上のhealth checkと紐付けを行います。設定画面もわかりやすいので、そこまで複雑な部分はないかと思います。

f:id:cross_black777:20160805211052p:plain

Route53にfailoverの設定をする

事前準備ができたのでRoute53のレコードにfailoverの設定をしていきます。

詳細の画面をのせることはできないですが、簡単に言葉で説明すると同じ名前のレコードを2つ作成作成し、primary/secondaryを決め前者はRe:dashのインスタンスのIPを、後者はS3のALIASを設定します。

f:id:cross_black777:20160805211149p:plain f:id:cross_black777:20160805211147p:plain

サーバ起動時に自動でIPアドレスを書き換える

上記まででインスタンスが落ちた際に、Sorryページを見せるところまでいきました。が、このままだとEC2が起動した際にEIPを付けていない限りIPアドレスが変わってしまい、ヘルスチェックが成功しても画面が表示されません。そこで、cloud-initを利用してサーバ起動時に自分のIPを取得してRoute53の設定を書き換えるようにしました。

$ cat /var/lib/cloud/scripts/per-bootset_hostname.sh
#!/bin/bash
jq=/usr/local/bin/jq
aws=/usr/local/bin/aws
hosted_zone_id=XXXXXXXX
domain=XXXXXXX
hostname=XXXXXXX
export AWS_DEFAULT_REGION=ap-northeast-1

instance_id=$(curl -s http://169.254.169.254/latest/meta-data/instance-id)
json=$($aws ec2 describe-instances --instance-ids $instance_id)
public_ip_address=$(echo $json | $jq -r '.Reservations[0].Instances[0].PublicIpAddress')

# register to Route53
cat > /etc/cloud/cloud.cfg.d/set_hostname.json <<EOF
{
  "Comment": "${hostname}",
  "Changes": [
    {
      "Action": "UPSERT",
      "ResourceRecordSet": {
        "Name": "${hostname}.${domain}",
        "Type": "A",
        "TTL" : 60 ,
        "SetIdentifier" : "XXXXXXXXX-Primary" ,
        "ResourceRecords": [
         {
           "Value": "${public_ip_address}"
         }
        ],
        "Failover": "PRIMARY",
        "HealthCheckId": "XXXXXXXXXXX"
      }
    }
  ]
}
EOF
echo "\$ cat /etc/cloud/cloud.cfg.d/set_hostname.json"
cat /etc/cloud/cloud.cfg.d/set_hostname.json
echo "\$ $aws route53 change-resource-record-sets --hosted-zone-id $hosted_zone_id --change-batch file:////etc/cloud/cloud.cfg.d/set_hostname.json"
$aws route53 change-resource-record-sets --hosted-zone-id $hosted_zone_id --change-batch file:////etc/cloud/cloud.cfg.d/set_hostname.json

qiita.com

/var/lib/cloud/script/per-bootに任意のスクリプトを入れておくとサーバの起動時に毎回処理が走ります。例えばset_hostname.shというようなスクリプトを置いて、内部でawscliを使ってmetadataからpublic_ipを取得し、Route53のレコードを書き換えています。

https対応のためS3の前段にCloudfrontを導入する

ここまでで一応の構成はできました。しかし、S3のWebhosting機能ではhttpsに対応していないため、httpsでアクセスはできません。せっかくSorryページを作ったのにアクセスできず悲しいので、若干大げさと思いつつ前段にCloudfrontをおきます。

カスタムのSSL証明書を設定したい場合は、cloudfrontは初期費用が高いイメージがありますが、SNIを使っていればカスタム証明書の設置代はかからないので安く運用できます。今回は事前に証明書を取得済みなのでACMは使っていません。cloudfrontの設定ができたら最後に、Route53の向き先をcloudfrontのALIASにすることでhttpsでS3バケットにアクセスできます。

最終的な全体の構成図

最後に全体の構成を貼っておきます。

f:id:cross_black777:20160805214308p:plain

まとめ

ほぼほぼRe:dash関係ない話でしたが、httpsにもできて個人的には満足しました!インスタンスの監視にStatusCheckFailedを使っていますが、若干反応が遅いのでもっと即時に反映できるように監視項目の変更なり調整をしていきたいと思います。

参考