SEEDS Creator's Blog

git revert で本番反映をすぐ打消

こんにちは、エンジニアの西山です。

またクリエイターズブログの記事を書かせていただきます。

基本のGitの操作 commit, pull, push 等に慣れ作業を進めている時
本番サイトに反映した修正内容を、すぐ取り消して欲しいという要望も時にはあると思います。

修正ファイルや箇所が多く、急いで直している最中に限って
以下の事がよく起こります。

  • Slackでダイレクトチャットが飛んでくる
  • 隣の席の上司に声をかけられる
  • 先輩が息抜きにちょっかい出しにやってくる
  • 内線で呼び出される
  • 作業依頼をしていた方から質問を受ける
  • 別案件の緊急対応依頼

エンジニアあるあるですね。
どこまで直していたかを確認する為、時間を使い焦っていく。

そんな時に救ってくれるのが git revert です。

revert は リバートと読みます。
修正した内容を打ち消すコミットを行い、修正前の状態に戻してくれます。

早速、例を元に使っていきましょう。

■1. マージしていないコミットを打ち消し

テキストファイルを作成し
下記の内容を記載しコミットします。

コミットメッセージ 「太郎の最初のメッセージ」

僕は太郎です。花子さんが好きです。

文を追記し、コミットします。

コミットメッセージ 「花子さんと付き合えた」

僕は太郎です。花子さんが好きです。
花子さんと付き合うことになりました。

2行で付き合えるなら誰も苦労しませんね。
revert します。

まずは コミットの履歴を見ます。

Fumi-Mac:love fumi$ git log --graph
* commit 7a17b856e2af85b3d4b057614fdab832833748f1 (HEAD -> master)
| Author: Fumitaka Nishiyama <xxxxx@gmail.com>
| Date:   Thu Jan 24 02:25:52 2019 +0900
| 
|     花子さんと付き合えた
| 
* commit 4723d015c345e0dd0016bd91df69aced7db0f6f9
| Author: Fumitaka Nishiyama <xxxxx@gmail.com>
| Date:   Thu Jan 24 02:24:26 2019 +0900
| 
|     太郎の最初のメッセージ
| 

「花子さんと付き合えた」というコミットのハッシュ値は
「7a17b856e2af85b3d4b057614fdab832833748f1」です。
打ち消したい内容であるこのハッシュ値を指定し、下記のコマンドを叩きます。

git revert 7a17b856e2af85b3d4b057614fdab832833748f1

ファイルを確認してください。「花子さんと付き合うことになりました。」という文が消えて
下記の状態になりました。

僕は太郎です。花子さんが好きです。

太郎は再び1人になりました。

■2. マージしたコミットを打ち消し

より実践的な例を見てみましょう。

実際の作業では修正用のブランチを作成し、修正内容をコミットします。
そして、本番反映時にブランチ「master」にマージするのがよく行われる流れかと思います。

ブランチ「master」から、ブランチ「hanako」を作成し
ブランチ「master」と、ブランチ「hanako」にそれぞれコミットを追加します。
最後に、ブランチ「hanako」を、ブランチ「master」にマージしました。

めでたく結ばれました。

全体のログ

Fumi-Mac:love fumi$ git log --graph
*   commit 46303cedb6e5ab634ee1f6b7f0ae28863d84868a (HEAD -> master)
|\  Merge: 88b202c a12f7c9
| | Author: Fumitaka Nishiyama <xxxxx@gmail.com>
| | Date:   Thu Jan 24 02:52:10 2019 +0900
| | 
| |     Merge branch 'hanako'
| | 
| * commit a12f7c9de1f18ac891e88d65c82453ae5acaee92 (hanako)
| | Author: Fumitaka Nishiyama <xxxxx@gmail.com>
| | Date:   Thu Jan 24 02:50:32 2019 +0900
| | 
| |     花子コミット2
| | 
| * commit 6a9bbbdf79c7d914ef214e614ca448aecedb899a
| | Author: Fumitaka Nishiyama <xxxxx@gmail.com>
| | Date:   Thu Jan 24 02:50:17 2019 +0900
| | 
| |     花子コミット1
| | 
* | commit 88b202c57a61f877a54fef5aeb4d31b850c25ebb
|/  Author: Fumitaka Nishiyama <xxxxx@gmail.com>
|   Date:   Thu Jan 24 02:48:15 2019 +0900
|   
|       太郎コミット1

マージの箇所

*   commit 46303cedb6e5ab634ee1f6b7f0ae28863d84868a (HEAD -> master)
|\  Merge: 88b202c a12f7c9
| | Author: Fumitaka Nishiyama <xxxxx@gmail.com>
| | Date:   Thu Jan 24 02:52:10 2019 +0900
| | 
| |     Merge branch 'hanako'

「88b202c」「a12f7c9」という2つの数字が記載されています。
これは親番号のハッシュ値です。
2つのブランチからマージされるので、それぞれの最後のコミットのハッシュ値の一部が記載されています。

ブランチ「master」の箇所

* | commit 88b202c57a61f877a54fef5aeb4d31b850c25ebb
|/  Author: Fumitaka Nishiyama <xxxxx@gmail.com>
|   Date:   Thu Jan 24 02:48:15 2019 +0900
|   
|       太郎コミット1

ブランチ「hanako」の箇所

| * commit a12f7c9de1f18ac891e88d65c82453ae5acaee92 (hanako)
| | Author: Fumitaka Nishiyama <xxxxx@gmail.com>
| | Date:   Thu Jan 24 02:50:32 2019 +0900
| | 
| |     花子コミット2

今回はブランチ「hanako」のマージを打ち消し
ブランチ「master」で「太郎コミット1」が反映されている状態にします。

現在のファイル内容

花子コミット1の内容です
花子コミット2の内容です
太郎です。
太郎コミット1の内容です

エラーになるリバート方法

git revert <マージコミット>

Fumi-Mac:love fumi$ git revert 46303cedb6e5ab634ee1f6b7f0ae28863d84868a
error: commit 46303cedb6e5ab634ee1f6b7f0ae28863d84868a is a merge but no -m option was given.
fatal: revert failed

ただマージコミットのハッシュ値を指定するだけでは
-m のオプションがないとエラーになります。

-m オプションが必要な理由

まず、「太朗コミット1」から「マージコミット」になった時に、どのような差がでているか確認します。

git diff <太郎コミット1> <マージコミット>

git diff 88b202c57a61f877a54fef5aeb4d31b850c25ebb 46303cedb6e5ab634ee1f6b7f0ae28863d84868a 

下記のように表示され、マージによりブランチ「hanako」の「花子コミット1」と「花子コミット2」により 文が2つ追加されているのが分かります。

+花子コミット1の内容です
+花子コミット2の内容です
 太郎です。
 太郎コミット1の内容です

実際にリバートをして説明いたします。
マージの箇所を確認します。

*   commit 46303cedb6e5ab634ee1f6b7f0ae28863d84868a (HEAD -> master)
|\  Merge: 88b202c a12f7c9

「補足」
88b202c の時は 1  ※ブランチ「master」のハッシュ値の一部 「太朗コミット1」
a12f7c9 の時は 2  ※ブランチ「hanako」のハッシュ値の一部 「花子コミット2」

git revert にオプション「-m」をつけ、ブランチ「master」の「太朗コミット1」の方を選ぶよう「1」を設定します。 マージコミットのハッシュ値「46303cedb6e5ab634ee1f6b7f0ae28863d84868a」を設定します。

リバートするコマンド

git revert -m 1 46303cedb6e5ab634ee1f6b7f0ae28863d84868a

実際にリバートした後のログを確認すると下記のようになります。

commit 9d9d9ece3d237065b87c81b963057a0ec069eb8d (HEAD -> master)
Author: Fumitaka Nishiyama <xxxxx@gmail.com>
Date:   Wed Feb 13 23:53:27 2019 +0900


    Revert "Merge branch 'hanako'"
    
    This reverts commit 46303cedb6e5ab634ee1f6b7f0ae28863d84868a, reversing
    changes made to 88b202c57a61f877a54fef5aeb4d31b850c25ebb.

マージコミットとリバートコミットの差分を確認し
リバートでどのように変更されたか確認してみましょう。

git diff <マージコミット> <リバートコミット>

git diff 46303cedb6e5ab634ee1f6b7f0ae28863d84868a 9d9d9ece3d237065b87c81b963057a0ec069eb8d

リバートコミットにより、文が削除されているのが分かります。 マージにより追加された文が削除されています。

-花子コミット1の内容です
-花子コミット2の内容です
 太郎です。
 太郎コミット1の内容です

これにより、リバートとは 「マージコミット」と「戻すべきコミット」の差分を取得して、それとは逆のコミットを行うことが分かります。

その為、
「マージコミット」と「戻すべきコミット」との差分を取得するために
-m のオプションで、どのコミットが「戻すべきコミット」かを指定する必要があるのですね。

【マージをリバートするコマンド】

git revert -m <1や2等、戻すべきコミットを指定する数値> <マージコミット>

「参考」

例)git revert -m 1 46303cedb6e5ab634ee1f6b7f0ae28863d84868a

「マージの箇所」
*   commit 46303cedb6e5ab634ee1f6b7f0ae28863d84868a (HEAD -> master)
|\  Merge: 88b202c a12f7c9

これにより、ブランチ「hanako」のコミットが反映されていない状態になりました。
実際の業務で、ブランチ「master」にマージした修正ブランチの内容を打ち消した事と同様です。

あとがき

これで、基本のrevertの使い方を説明することができました。

git revert する時は緊急な時が多いので
コマンド1つで打ち消すことができて、感動しました!

私もこの記事を書くことによって、麻雀で負けた分を打ち消すことができました。
半荘が1回とは限らないのです。

以上、西山でした。

AWS Cloud9 を使った開発環境構築

こんにちは。
エンジニアの西山です。

今回、初めてクリエイターズブログを書かせていただきます。

ところで、プログラミングを学び始めた人が最初につまずくのは
ifでもforのループでもなく開発環境の構築だと考えています。

プログラムを動かして楽しみたいと思っても
まずは動かすことが出来る環境を作らなければ始まりません。

XAMPP? Docker?
様々な選択肢があるとは思いますが
クラウドサーバーを使ってみる機会にもなると思いますし
AWS Cloud9を使った方法を紹介いたします。

私は以前、AWSに組み込まれる前のCloud9のサービスで
練習で関数の使い方等、簡単なプログラムを書いていました。

AWSに組み込まれてからは使ったことがなかったので、挑戦してみます。

プログラマもサーバーの事を知らなければいけない時代
私自身もAWSの使い方をもっと使って学んでいかなければ・・・。

AWSのアカウント作成は下記のページで詳細に説明しています。
https://aws.amazon.com/jp/register-flow/
※1年間の無料枠を使うことができます(使いすぎると費用も掛かってくるので気をつけてください)

アカウントが作成できましたら
AWS マネジメントコンソールへログインします。

早速Cloud9の開発環境作るぞ、と思いましたが
下記のページを見ると
https://docs.aws.amazon.com/ja_jp/cloud9/latest/user-guide/setup-express.html

AWS アカウントのルートユーザーとして AWS Cloud9 を使用することは可能ですが、
これは AWS セキュリティのベストプラクティスではありません。
代わりに IAM ユーザーとして AWS Cloud9 を使用することをお勧めします。

rootは神 というのはサーバーで最初に学んだ事なので、何でもかんでもやらせたらよくないです。
神が乗っ取られたら破壊神になるし。

まずはチームとユーザーの追加を行なっていきます

AWS Cloud9 のチームセットアップ
「ステップ 2.1: コンソールで IAM グループを作成する」
https://docs.aws.amazon.com/ja_jp/cloud9/latest/user-guide/setup.html#setup-create-iam-resources-group-console

  下記の動画も参考になります。
  https://www.youtube.com/watch?v=XMi5fXL2Hes

グループ「Cloud9Group」というのを作成しました。

その後は「ステップ 2.2: IAM ユーザーを作成して、コンソールでグループにユーザーを追加する」
https://docs.aws.amazon.com/ja_jp/cloud9/latest/user-guide/setup.html#setup-create-iam-resources-user-console

ユーザー作成が完了したページで、下記の記載があるCSVがダウンロードできますので必ずダウンロードしてください。

  • アクセスキー ID
  • シークレットアクセスキー
  • パスワード
  • コンソールへのログインURL

ユーザー「Cloud9User」というのを作成しました。

そして「ステップ 3: グループに AWS Cloud9 アクセス権限を追加する」
https://docs.aws.amazon.com/ja_jp/cloud9/latest/user-guide/setup.html#setup-give-user-access

権限をつけて使えるようにしたので
「ステップ 4: AWS Cloud9 コンソールへのサインイン」
https://docs.aws.amazon.com/ja_jp/cloud9/latest/user-guide/setup.html#setup-sign-in-ide

改めて作ったアカウントでサインインし直します。
https://console.aws.amazon.com/cloud9/

さあ、いよいよAWS Cloud9を使い始めます。

まだリージョンに東京がないので
アジアパシフィック (シンガポール)を選択しました。

f:id:seeds-std:20181211204323p:plain

「Create environment」ボタンを押して

f:id:seeds-std:20181211204355p:plain

「Name」に作業環境の名前をつけます「practice」とつけました。
「Next step」ボタンをクリック

f:id:seeds-std:20181211204415p:plain

「Environment type」は「Create a new instance for environment (EC2)」を選択

費用を抑える為、
「Instance type」は「t2.micro」
「Cost-saving setting」は「After 30 minutes」にします。

※Cloud9 が接続する新しい Amazon EC2 インスタンスを作成します
 IDE を開いたときに自動的に起動します。
 インスタンスは IDE を終了して 30 分後に停止する設定になります

「Next step」ボタンをクリックし
確認画面で「Create environment」をクリックして環境を作成

f:id:seeds-std:20181211204440p:plain

数分待てば環境が出来るので待ちます。

f:id:seeds-std:20181211204453p:plain

左側の「README.md」などのファイルが表示されているエリアを右クリックして
「New File」
index.php という名前で動作確認のファイルを作成します。

文字表示だけでなく、きちんと計算も出来ているか見る為
計算式も入れています。

f:id:seeds-std:20181211204509p:plain

グロナビ「run」をまず押してWebサーバーが動く状態にします。

f:id:seeds-std:20181211204620p:plain

その後で、グロナビ「Preview」
「Preview Running Application」をクリックして結果表示します。

文字列と計算結果が表示されていますのでOK

料金は実際に使用した分に対してのみ発生し、最低使用料金や前払費用はありません。(無料利用枠内でしたら無料)

無料枠を超えた時の使用例

t2.micro Linux インスタンス で
デフォルトの設定 (30分間の自動休止状態を設定して
1か月に 20日間、1日 4時間 IDE を実行) を使用する場合
90時間の使用となった時

月額料金 1.85 USD 約200円!

AWS Cloud9 料金
https://aws.amazon.com/jp/cloud9/pricing/

ビール1本控えて、クラウドサーバー触れって事ですね。

AWS Cloud9には環境を他の人と共有する機能もあるようで
チームや指導で使う時にも便利な機能かと思われます。

まずはプログラムもサーバーも、色々動かして触ってみるのが重要だと思うので
手を動かす事を意識して頑張ります。

打つべし。打つべし。(課金には気をつけて)

以上、西山でした。

AWS IoT Enterprise Buttonを使ってSlackに通知を送ってみた

はじめまして!18年度新卒・WEBエンジニアの石田です。

弊社のコーヒーメーカーがリニューアルされ、コーヒーを淹れる機会がすごく多くなりました。 しかし、コーヒーメーカーができてから30分で保温が切れる設定で、
・追加で保温ができない…
・どうせならできたてが飲みたいけど、できたタイミングが分かりにくい…
・かといっていちいちSlackにコーヒーできましたって書くのもめんどくさい!
→自動投稿させたい!
→→ボタンワンクリックで済ませたい!

ということで、会社にAmazon「AWS IoT Enterprise Button」を買ってもらい、折角なのでクリエイターズブログに投稿することにしました!

f:id:seeds-std:20181105211732j:plain
新コーヒーメーカーと「AWS IoT Enterorise Button」

新コーヒーメーカーと「AWS IoT Enterorise Button」

AWS IoT Enterorise Button

ワンプッシュで商品が注文できる!と話題になった Amazon Dash Buttonをベースにした、自由にプログラムを動作させることのできるボタンです。 ボタンのクリックをトリガーに、AWSのサービスに接続できます。すごい。

f:id:seeds-std:20181105212349j:plain
ちっちゃいです

モバイルアプリを使ってWiFiの設定ができ、ステータスも確認可能。

f:id:seeds-std:20181105213458p:plainf:id:seeds-std:20181105221850p:plain
iOSアプリ「AWS IoT 1-Click」

何度か設定してみたのですが、デバイスリージョンはオレゴン一択なのでしょうか。東京リージョンに変更できませんでした。

そこからAWS IoT 1-Clickというサービスを選択し、プロジェクトを作成することでデバイスの動作を定義することができます。

選択できるのは
・SMSの送信
・Eメールの送信
・Lambda関数の選択
Slackに自動投稿したかったのでLambda一択でしたが、SMS・Eメール送信も色々使えそうで良いですね。

あとはLambdaでjavascriptを使ってwebhookにPOSTすれば投稿完了!

exports.handler = function(event, context) {
    const slack = (params) => {
      let https = require('https');
      let host = 'hooks.slack.com';
    
      let data = JSON.stringify({"text": params['message']});
    
      let options = {
        hostname: host,
        port: 443,
        path: params['path'],
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
          'Content-Length': Buffer.byteLength(data)
        }
      };
    
      let req = https.request(options, (res) => {
        console.log('status code : ' + res.statusCode);
        res.setEncoding('utf8');
        res.on('data', (d) => {
          console.log(d);
        });
      });
    
      req.on('error', (e) => {
        console.error(e)
      ;});
    
      req.write(data);
      req.end();
    };
    
    var post = function() {
      return slack({
        path: 'hogehogehogehogehoge',
        message: 'コーヒーができました:coffee:'
      });
    };

    setTimeout(post, (60 * 6 * 1000));
};

f:id:seeds-std:20181105221032p:plain
アイコンはデザイナー・コウノ氏が作ってくれました!かわいい

6分で完成するので、その分だけタイムアウトさせるようにしています。 起動時間は5分までだと思ってたからどうしようかな…と思っていたのですが、15分までいけるようになっていたのが驚きでした。

IoT ButtonやLambdaを触ったのははじめてだったので時間がかかりましたが、セットアップからSlackに投稿できるようになるまで1時間ほど。すごく簡単でした。 他にもいろいろな使い方ができそうですね。シーズでは早速、更に2台のIoT Buttonを追加購入しました(笑) 社内でアイデアを募ってどういう使い方をしようかと思案中です!

弊社コーポレートサイトリニューアルとその裏側

お久しぶりとなってしまいました。原口です。

10/1に弊社コーポレートサイトがリニューアルされました。

www.seeds-std.co.jp

今回、社長より「技術的な部分は自由にやっていいよ」という事でしたので自由にやらせていただきましたので、 このサイトにおける技術的な部分にフォーカスして紹介をしていきたいと思います。

システムコンセプト

通常コーポレートサイトといいますとwordpressなどのCMSの導入をする事がほとんどです。 弊社でもこれまではwordpressを利用していましたが運用するうちに気づいた事として管理が非常に面倒という点がありました。 サイトの更新よりもwordpressのアップグレード回数の方が多かった・・・となる月もザラにあり、 更新の簡単さと差し引いても目に見えにくい人的コストが高い状態は否めませんでした。

そのため、リニューアルにあたっては早いうちから、管理コストの少ない構成とする事は決めていました。 できる限り静的ファイルのみでの公開をし、お問い合わせフォームなどの、どうしてもプログラムの必要な部分は サーバーレスアーキテクチャを採用するという方針を決定致しました。

バックエンド

インフラ構成は以下の通りです

f:id:cs_sonar:20181009211159p:plain

サイトの大部分はs3で公開されています。 デプロイは開発者のローカル環境より

npm run prod

といったビルドコマンドでs3に同期するような仕組みです。

大部分はs3で公開されている為、s3は静的ホスティングとしています。 前段にcloudfrontをかませていますが、これは独自ドメインにてSSLを使いたかったが為に使用しています。 そのためキャッシュ及びネガティブキャッシュのTTLは0です。 SSLはACMで取得しました。

唯一お問い合わせフォームがシステムに絡む部分となりますので こちらはAPI gatewayとlambdaを利用しています。 この部分は一括して、リードプログラマの川勝さんに担当していただけました。

lambdaはvalidateと、SMTP-AUTHにて別のサーバーにメールリレーするだけの簡単なプログラムとなっています。 サーバレスといいつつ、唯一メールサーバーのみ弊社データセンタを利用していますが、 こちらも本来はAWS SESを利用しても問題はないかと思います。

この構成で約10日間ほど運用していますが現在で総額 $1.5ほどの費用となります。 TOPページに動画を使っている関係かこのうちの$1.2は転送量(cloudfront)です。 このままでおおよそ$5/monthほどのコストで運用できるのではないでしょうか。

この低コストに加えて、サーバー機の保守やOS、ミドルウェア、アプリケーションの脆弱性など、 まったく考えなくてもよいという見えない人的コストも大きく削減されています。

フロントエンド

フロントエンド側では弊社フロントチームに新卒で参加した寺澤さんがコーディングから実装までほぼすべてを行いました。 モバイルファーストを考え、スマフォの際はできるだけ転送量がかからないようjsやcssをminifyを行ったり、モバイル端末の際はTOP動画をgifアニメにするなどの変更を行っています。PC側の動画の圧縮なども作業いただきました。

静的ファイルを生成するという構成上、テンプレートエンジンの利用は当初より考えていてPugを使用しています。 ビルドはgulpを利用していて、ビルド時のコマンドで生成したhtml、css、画像、jsをs3へ持っていく形としています。

jsフレームワークはVue.jsです。スライダーやページの動きはこちらで実装し、一部ページ(newsや制作実績、お問い合わせページ)ではSPAっぽいもので構成しています。

1点、起こった問題として、s3静的サイトホスティングではmod_rewriteのようにURLの書き換えができない点がありました。 リダイレクトは可能なのですがリライトはできないのですね・・・。 前述の通り一部ページはSPAでの実装を行っていたのですが、 s3での運用に際し、この点はURLが少し不格好となってしまいますがクエリストリングで対応するようにしました。

デザイン

昨年、弊社に入社されたデザイナーの河野さんが全て取り仕切って行ってくれました。 モバイルファーストと呼ばれるこの時代・・・レスポンシブデザインをベースに スマフォでいかに見やすいか、という点を注意してデザインいただけました。

TOPにて背景動画を流したり、遊び心のあるイラスト(河野さんの自作!)など、素敵なデザインになったと思います。 イラストの一部にシーズ社員数名が紛れ込んでいるので、是非探してみてください。

終わりに

今回の構成では今後できるだけ手間をかけない、可能な限り今後の運用が低コストとなるよう考えて制作しました。 通常CMSと考えるとwordpressやサーバー、そしてデータベースの準備などなど、、、様々な事がデファクトスタンダードとして存在しますが、 規模に対して過剰な設備であったり、本来注視すべきコンテンツ以上にこれらの対応で時間が取られる事もしばしばあります。 本当にそこまで必要なのか?本当にそれらを準備しないと目的が達成できないのか? という観点は通常のシステム開発でもとても重要なものであると改めて思いました。

同様の事例でお困りの事があれば是非、ご相談下さい!

ISUCON7に「ガトリンガー葉の仲間たち」で参加して今年も惨敗しました

毎年恒例のISUCONに参加してまいりました。
毎年今年こそは!と心に闘志を燃やして参加するのですが、今年も予選敗退でした。残念。

ISUCONとは「いい感じにスピードアップコンテスト」の略で
与えられたお題のWEBアプリケーションをできるだけ早くし、ベンチマークの出す点数で競うコンテストです。

isucon.net

今回は社内の方々にお誘い活動を行って捕まえたkawakattsun、luccafortと僕(cs_sonar)の3名で参加しました。
僕はISUCON1から参加していて、kawakattsun、luccafortは今回がISUCON初参加でしたので
裏テーマとして二人がISUCONを本気で楽しんでもらえたら嬉しいなーと思っていたのですが
実際はものごっつい楽しんでもらえたようで結果は惨敗でしたがそういう意味ではとても成功だったと思います。

順位は暫定55位で点数は72,285。言語はPHPです。

そういえばISUCON1は複数台構成だったなぁと思い出しました。

事前準備

業務の忙しさにかまけてあまり事前準備してなかったです。 2ヶ月前くらいにみんなでPixivのISUCON問題をじっくり解きましたので 今回非常構成が似ていたのでそれがよかったです

・とりあえずベンチ回す
・レギュレーションを熟読する
・git
・phpに切り替え
・SSH簡易接続設定
・mysqlのdata dir をコピー
・アクセスログ解析(analog)
・netdataつかってみる?
・app armor注意
・プログラムDBで明らかに重いところを潰す
・インフラ関連のチューニングを行う
・ある程度のチューニングができたら抜本的な構造変更の対策を検討

ボトルネックを常に潰していく
同時に改修は行わない。
なにがよくて何がだめだったかがわからなくなるから

という方針だけ前日10分くらいでざっくり作って共有。

本番での流れ

もうあたふたしてたので詳細は覚えてないですが・・・

  • 9:30 会社に到着。会社にいた方がエナジードリンクを差し入れしてくれた。
  • 10:00 開始が遅れるらしい。 これはこれで非常に有意義な時間だった。お祭り感。
  • 11:30 もう今日はないのでは?と、昼から飲みに行く気に半分くらいなってた
  • 13:00 開始・・・されない。このズコーー!がお祭り感がさらに加速。
  • 13:10 本当開始!とりあえずSSH鍵認証。
  • 13:12 初期ベンチ pythonで6189
  • 13:30 各サーバーどこからでも ssh {web1|web2|db}で接続できるように設定
  • 13:30 DBサーバーのID/PASSをあふあふ探す
  • 13:30 PHPに切り替えてベンチで4157
  • 14:00 DBが重かったので簡単にチューニング。innodb_flush_log_at_trx_commit = 0 くらいですが。6397
  • 14:15 さくっとanalogでアクセス数だけ確認。loginとadd_channelとかが多い
  • 15:00 slow_logから明らかに画像の部分がボトルネックなので静的に書き出し、nginxでiconsから返すように設定。8293
  • 16:00 mysqlのINDEX貼る、N+1改善、php-fpmプロセス数上げる、などなどで12000
  • 17:00 疲れが見え始めた所に社内の方が差し入れでお菓子とジュースをくれる。ありがたい。余ったけど。
  • 17:10 nginx <=> php-fpmをunix domain socketに変更するのに僕が結構はまる。20000
  • 18:00 php-fpm <=> DB をスレッドプールするようにした。mysql-pdoでいうparsistantの設定。点数はメモってなかった
  • 18:30 静的ファイルの接続でエラー出るので帯域でつまってる事にやっと気づく。

じゃぁ3台から返せばいいんじゃね?という事でこの時間で大きな構成変更をした。ベンチ対象は全台に変更。

[app1]    [app2]    [app3]
web        web      web
app        app      db
  • app3への接続は静的ファイルはそのまま返し、それ以外はロードバランス的にapp1/app2 に振り分け。
  • iconsの共有はnfsを使用。app1をnfsサーバーにしてapp2/app3はnfsクライアントとしてmountする形に。
  • 静的ファイルを304で返せるように expire 10d;を追加。 (ここがpublicつけないといけなかったなどの話)
  • これで59000
  • 20:15 SQLのストリクトモード消したりして73160が出た。これが最高得点。
  • 20:30 ここからベンチガチャがあって15000 ~ 70000まで大きく振れまくる・・・304レスポンスの数で変わってたのかな
  • 21:00 再起動テストをする。nfsマウントしてたので起動順によってはマウントされない事態が発覚。autofs入れて対応。
  • 21:10 ベンチ&ベンチ&ベンチ&ベンチで72285が出たのでやめる

僕はプログラムをまったく見ておらずインフラばかり見てました。
php-fpmのsocket化の権限関係でえらいハマってしまい、プログラム見る時間がなかったです・・・
のでプログラム部分はkawakattsun、luccafortがいろいろとやってくれていたのだと思います!

アクシデント

  • gitのリポジトリのdbディレクトリを含めてしまい、復旧用dumpが含まれてしまった為にどえらい重いリポジトリに
  • 画像の静的化の時にDBをやらかしてしまいdumpから復元する事態に
  • php-fpmの設定ファイルのコメントが#ではない事に気づくのがかなり最後の方だった
  • 開始が3時間遅れたので、後に予定のあったluccafortが途中で抜けてしまう

アクシデントを含めてのISUCON!!

感想

開始が遅れるという所で、運営側が本当に大変だったんだな、と改めて感謝です。
毎年こんなにも楽しい時間をくれて頭が上がりません。

今回の問題も本当によく考えられてて本当に楽しかったです!
メモリ1GBしかない所なんてとても素敵でした。

今年はシーズからもう1チーム出てたのですが競技終了後に「あそこどうした?」みたいな反省会は本当に楽しい
問題のリポジトリも公開されましたので、これからも社内で2次会して楽しみたいと思います!

しかし、、、とっても悔しい!くやしーーー!!!
僕はこれからブラウザキャッシュの設定で Cache-Control: public の設定をしない事はないでしょう。

ISUCONは本当に最高です!

社内WindowsサーバーをAWSに移行する話1

経緯

シーズでは、見積書・請求書の発行などに社内にWindowsサーバーを立て弥生販売を使っていました。

複数拠点から複数人が同時に使うためネットワーク版5ライセンスです。

社内にサーバーを置くメリットとして、

*ギガビットLANでの高速アクセス

*社外との通信が発生しないためセキュリティーが高い

*売るほどサーバーラックがあるのでコストはあまり気にならない

といった利点がありましたが サーバー筐体費用、Windowsサーバー、SQLライセンスなどの初期費用(トータル約40万※構築費用は自前のため無料)がかかるうえ 毎年のライセンス更新や筐体保守費用、また毎月の電気代・空調費用も馬鹿になりません。 さらに、場所も取るし、空調にも気を使うし、なにかとメンテも大変なのでクラウドに行きたいと考えておりました。

要件

*AWSで24時間365日稼働(ただし夜間は止めるかも)

*OSはWindowsサーバー2012

*弥生販売ネットワーク版5ライセンスを動かす

*シーズ社内とVPNでセキュアに常時接続

特に最後のVPNで社内とシームレスかつセキュアに接続が一番重要ですね。

これらの要件をAWSでこのように準備しました。

AWS構成

*ec2インスタンス(Windows2012) t2.small $36.60

*EBS45GB $5.40

*VPC VPN接続 $36

合計 約78ドル=約8,424円 (1ドル108円)

f:id:panmizser:20161121214003p:plain

EBSボリューム、転送量、EIP、IOなど少額の従量制がありますが、それらを含んだとして、約8,500円です。

移行してどうだったか

結論としては、最高でした。

まず費用としては

サーバー1台をデータセンターでハウジング(月50,000相当,OSライセンス諸々込)として、それが月8,500円ポッキリになりました。(83%DOWNです!)

また弥生を使わない夜間止めることで更にコストダウンも可能です。

次に、回線速度やアプリの使用感ですが、こちらも全く問題ありません。

インスタンスタイプは最初 large → medium と様子を見ていきましたが最終的にはsmallまで落としても操作感に問題ありませんでした。

(ただし弥生インストール時はlargeでやったほうが効率がいいです)

回線速度は、AWSの提供するVPNサービスを利用することで全くストレスを感じません。 (以前、WindowsインスタンスからPPTPで会社ルーターに繋げたりしたことがありましたが、その場合、一応つながりますが、結構遅かったです。)

次回は、これらAWSの設定、社内VPNルーターの設定を含め詳しく解説していきたいと思います。

AWS 中国(北京)リージョンの利用でハマった所をご紹介します

f:id:cs_sonar:20161118201515p:plain

原口です。

AWS China(Beijing) [中国(北京)リージョン] を触らせていただく機会がありまして触ってみた感じをお伝え致します。

中国リージョンは結構前から追加されていますが、通常のアカウントのリージョン一覧には出てきません。

中国リージョンを利用するには他のリージョンとは異なり、専用のアカウントを作成しなければ利用できません。

基本情報

[リージョン]
cn-north-1

[アベイラビリティゾーン]
cn-north-1a
cn-north-1b

無許可でのポート80 / 443 / 8080 のポートによるページ公開ができない

中国では、ウェブサイトを勝手に公開できないようで、AWS側にて上記のポートは接続できないようになっています。ICPライセンスというものを登録しなければ公開できません。基本的にはAWSアカウントにライセンスが紐づいているようでライセンスが紐づけば公開が可能となるようです。

注意点として、ELBやEC2などでは接続できないときはブラウザくるくるですが、s3の接続できないエラーは401レスポンス(UnauthorizedAccess)を返します。401(UnauthorizedAccess)はs3のgetObjectがない場合でも出すのでICPライセンスが原因である、、、という判別がつきにくいところでハマりやすいので注意です。

ちなみにELBやEC2は待ち受けポートを適当なポートに変えてやれば無理やり公開する事は可能でした。

ARNやドメインネームが変わっているので注意

ドメイン名は ec2.amazonaws.comec2.amazonaws.com.cnと、完全に別のドメインになっていますし、 ARNもarn:awsarn:aws-cn と変わっているので注意が必要です。

cloudformationやterraformのテンプレートなど既存のノウハウを生かそうと流用すると arnを直接指定している部分などではまります。

ないサービスが多い

以下の一覧でも確認できます

リージョン - グローバルインフラストラクチャ | AWS

今回は

  • route53
  • lambda
  • RDS(Aurora)

あたりがなかったので困りました。

既存リージョンからAMIはコピーできない

完全別サービスみたいな感じですので、既存のリージョンで作成していたAMIなどを共有する事ができません。
これはかなりつらかったので・・・以下のようにディスクイメージを作成してコピーする方法を用いました。

インスタンスコピーの手順

AmazonLinux (HVM)を使用した場合。

移行したいAMIのsnapshotからVolumeを作成し、適当なインスタンスにアタッチします。
アタッチしたボリュームをddコマンドでイメージファイル化します。
(/dev/xvdfとしてアタッチした場合)

dd if=/dev/xvdf of=image.img bs=1M

イメージファイルを中国側に作成したインスタンスに転送します

scp -i chn.pem ./image.img ec2-user@***.***.***.***:/home/ec2-user/

中国側インスタンスで空のVolumeを作成し、アタッチします。
この時、空のVolumeサイズはコピー元のVolumeサイズと同じにしてください。

このアタッチした空Volumeにddコマンドでイメージファイルを書き込みます
(/dev/xvdfとしてアタッチした場合)

dd if=./image.img of=/dev/xvdf bs=1M oflag=direct

※独自OSを使っている場合などはこの際にboot関連の項目を書き換えたりしないといけないかもしれないですがAmazonLinuxでは特に修正なくできました。

Volumeをデタッチしてsnapshotを作成します。
そしてsnapshotからAMIを作成。
この際のパラメータはHVM(Hardware-assited VM)に。
カーネルIDなどはデフォルトでOKです。

これで、既存リージョンのAMIを北京リージョンに持ってくる事ができた事になります。

このとき、作成したAMIを北京リージョンで立ち上げるとうまく立ち上がってこない事があります。
マネージメントコンソールからget_systemlogで見ると以下のようなのが出てる場合・・・

http://packages.ap-northeast-1.amazonaws.com/2016.09/main/20160901f6a8/x86_64/repodata/repomd.xml?instance_id=i-******************************&region=ap-northeast-1: [Errno 12]
Timeout on http://packages.ap-northeast-1.amazonaws.com/2016.09/main/20160901f6a8/x86_64/repodata/repomd.xml?instance_id=i-******************************&region=ap-northeast-1: (28, 'Connection timed out after 10000 milliseconds')
Trying other mirror.`

Amazon Linuxはcloud-initでyum update(セキュリティのみのもの)が走るのですがそれが途中で止まっているのが原因です。
止まってしまった場合は再起動すればOKです。
これはたぶん以下の変数が書き換わっていないからではないかと思います。

/etc/yum/vars/awsdomain
/etc/yum/vars/awsregion

同様にRDSのスナップショットも移動できないです。こっちはダンプ持ってく感じになりますね

よく接続切れる、またはめちゃくちゃ遅くなったりする

南北問題と言うらしいです・・・。

(参考) qiita.com