VOYAGE GROUP エンジニアブログ

voyagegroup_techのブログ
VOYAGE GROUPエンジニアブログです。

2014年09月

ISUCON4の予選に参加して1日目4位になりました。(チーム:vg12)

こんにちは。
VOYAGE GROUPのシステム本部でインフラエンジニアとして働いている @s_tajima です。
先週末、
LINE株式会社さん主催のチューニングイベントであるISUCON4の予選に参加しました。
(失格にならなければ)4位で予選通過できるようです。

今回は、事前準備〜スコア提出までにやった事とその所感をお話しようと思います。

■ 前日まで

  • 同期の@misty320(業務ではアドテク事業のアプリ担当)と
    @at_grandpa(業務ではアドテクの事業の数値解析周り担当)を誘って参加することに。
    3人とも初参加。
  • 平日の業務終了後、3,4度集まって過去問をやってみて予習。
    3人で並行作業するための戦略もここで打ち合わせ。
  • 当日はおおまかにnginx + ruby構成にしようということを取り決め。
  • 細かい設定変更やアプリの改修はGithubのprivateリポジトリを使って共有することを取り決め。
  • 大きめの修正をした際にはAMIを作成。
  • メンバーのAWSアカウントに対してLaunchPermissionを設定してそこを基準にしてチューニングを再開。
  • 当日役に立ちそうなツール類の準備。★0
  • 前日に会社の会議室にモニター(各自の作業用)やプロジェクター(idobataやTwitter表示用)を用意。

■ 当日
9時
  • おにぎりを食べて会社に集合。開始前にお昼の寿司を頼もうと思ったが出前が営業時間外で断念。
  • 予選当日マニュアルが発表。テーマは銀行?らしい。
  • マニュアルの読み合わせ。(スコアリングの大まかな仕様、ルール等確認)
10時
  • 予選開始。それぞれ1台ずつ起動し状況を確認。
  • 当初の予定だとhttpd + perlの構成を、nginx + rubyにして計測、
    としようと思ったところだがすでにそうなっていた。
  • とりあえず初期状態のまま計測。スコアは1000程度。
  • 周りのベンチ結果を見ると軒並み1500程度はでているようなので、
    今回rubyはハズレなのでは..という空気に。
  • ここでPHPがhttpd + mod_phpではなく最初からnginx + php-fpmになっていることに気がつく。
  • ためしにphpで計測してみると、1500程度。
    (この時点ではスコアの規模感がわからなかったので大きな差に感じた。)
  • 今は3人ともあまり使っていないものの、
    比較的馴染みはあるのでphpに乗り換えることに。
11時
  • 計測スクリプト実行時のアクセスログや, slow query logを確認。
  • @misty320と@at_grandpaにアプリ周りの確認をしてもらう。
  • その間に、最初のAMIを作成。
    (事前に用意したツール類の展開。アプリケーションをphpに。MySQLの大まかな設定変更。)
  • AMIを共有(1回目)。
  • 引き続き@misty320と@at_grandpaにアプリやクエリの確認をお願い。
  • その裏でMySQLをOracle提供の5.6.20に入れ替えてみたが、
    スコアが下がった(1000程度)のでやめた。
12時
  • ブラウザでの表示が崩れていることに気がつく。
    画像の表示やコンテンツの取得に問題はないようだがなぜかcssだけがあたらない。
  • cssのContent-Typeがtext/plainになっていることに気がつく。
    nginxにinclude mime.types;を設定して対応。運営に報告。
  • @misty320が作ったindexを貼るとスコアが3000程に。★1
  • 計測のworkloadを増やしていくと順調にスコアが伸びていくので
    頭打ちになるところまで増やしてみることに。
  • 同時にphp-fpmをHHVMで置き換えるために準備開始。
    RPM落ちてるだろうと思ってたがなかった。仕方なく自分でビルド開始。
  • お昼ごはんにお寿司を注文。
13時
  • nginx, php-fpm, MySQL, OS周りの細かいチューニングをしつつ
    workloadをスコアが頭打ちになるまで上げていく。★2
  • @misty320が作った2つ目のindexも設定。★3
  • この時点でworkloadは30, スコアは35000程度。
     (多分計測の1分タイムアウトは正常に動いてた)
14時
  • ここから1時間程度は思うようにスコアが伸びず焦る。
15時
  • HHVMのビルドが完了。
    自動起動周りなどは気にせずとりあえず起動してベンチ。
  • この時点でのAMIを作成して3人で共有。
  • スループットはかなり上がっていそうだが、特定のPATHでエラーが多発。
    @misty320と@at_grantpaに調査を依頼。★4
  • 解消できることを信じて調査してもらっている間にHHVMのfast-cgiの設定や
    supervisordでの起動を設定していく。
16時
  • ★4の問題は解消。
    workloadを上げるとまたスコアが伸びるようになったので、頭打ちになるところを探していく。
  • スコアはかなり高くなるものの、計測のたびにエラーがでている状態。
    原因を調査し解消していく。★5
  • 事前にチームで計画していた予定に従い、
    16時30分時点で一旦手を止めて現状共有と終盤の方針について相談
    (終盤の混乱での崩壊を避けたかった)。
  • 結論は既にそれなりのスコアが出ているので、スコア向上は小さな調整のみに抑えて安定化、
    ルールの範疇に収まっているかのチェックを重視することに決定。
17時
  • この時点でworkloadは300, スコアは65000 ~ 75000くらいが安定して出せるように。
  • 計測が3分程度になっている気がしたが余り気にしていなかった。
    まさかバグだとは誰も認識していなかった...
  • 残り時間も少なくなってきたので、
    一旦スコアの提出は終了してAMIの調整に入ることに。
  • AMI起動時、自動起動でエラーになったり、運営が計測した時に不具合が。
    にみたいなことがないように調整。
  • AMIを作って3人で共有 -> 細かい不具合を発見 -> 修正したAMIを作成
    というのを何度も繰り返した。
18時
  • 予選終了。スコアの結果4位に入っていた。

■ 具体的な対応
★0
  • 以下のようなスクリプトを用意していた。 
  • 必要な設定ファイルを指定のディレクトリに集めてきて、元あった場所にシンボリックリンクを貼るスクリプト(git管理化をしやすくするため)
  • 計測の前後で必要そうな作業をするためのスクリプト
     計測前: OSのキャッシュクリア, 各種ログのトランケート(地味に重要), 各ミドルウェアの再起動 
     計測後: 各種ログの収集(git管理下のディレクトリに),設定ファイルのコミット(スコアをコミットメッセージにして)
  • AMIを作成するためのコマンド(awsコマンドを打つだけだけど、instance_idとかを調べてオプション渡すのが面倒だったので。) 

★1 
  • 以下のindexを設定。
CREATE INDEX `login_user_idx` ON `login_log` (`user_id`);

★2
  • nginxはworker数や, workerのコネクション数の調整。
  • php-fpmとの接続をunixドメインソケットに。
  • php-fpmはpm*serversあたりのパラメータを調整。
  • MySQLはinnodb_*みたいな定番のパラメータを調整。
  • 具体的な設定ファイルは余力があれば後で公開します。

★3
  • 以下のindexを設定。
 CREATE INDEX `login_ip_idx` ON `login_log` (`ip`);
 
★4
  •  HHVMだとindex.html.phpのflash_now()の処理がうまく動かなかった模様。
  •  値をcookieに持たせるように修正して対処。

★5
  • file descriptor周りの調整がメイン。
  • nginxのfile descriptorを設定したあと、
    親workerのlimitsを見て設定反映されないなあとかちょっとだけハマった。あほ。
  • 計測スクリプトのfile descriptorにも気を配らないといけないのも
    ちょっと気がつくのに時間がかかった。

■ 感想
  • 事前に3人で打ち合わせを数回してから望めたのはよかった。
    同期なのでコミュニケーションもとりやすかった。
  • 当日役に立ちそうなスクリプトを作っておいたのもよかった。
  • HHVM、はじめてビルドしたし触ったのもはじめてだったけど動いてくれてよかった。
    (正直fast-cgiもそれほど詳しくはない)
  • 節目節目でAMIを作って共有して作業できたのはとてもよかった。
    不具合があった時には @at_grandpa が最新のAMIを立ちあげて検証のサポートを
    その間に @misty320 が1つ前のAMIでチューニングをという役割分担ができた。  
  • @misty320のブログ
    (
    http://misty320.hatenadiary.jp/entry/2014/09/29/010956)
    にもある通りとても楽しいイベントでした。
  • (もし失格にならなければ)本戦頑張ります!
■ 余談
  • たしかに少なからずうちのチームは計測スクリプトのbugを踏んでいた模様。
  • 提出時そのままの状態でv2を使うとスコア35000くらいだった。
  • その後小細工をして計測したら30分くらいの作業で57000くらいには伸びたので歯ブラシでも十分に戦えそうだということじゃないかなあと。

チームが変わるふりかえり!

こんにちは。VOYAGE MARKETINGの @yohxxです。
ポイント交換サービス PeXの開発や、環境改善などを担当しています。

最近自分のチームではメンバーの入れ替えや増員があり、大半のメンバーがまっさらな状態でスタートしました。
開発の進め方や、運用フローなど随時見直していくために定期的なふりかえりを実施して改善を進めています。

PeXで実施してるふりかえりについてまとめてみます。
ふりかえりは以下2つ。
  • 開発についてのふりかえり  
  • 運用フローについてのふりかえり  

どちらもKPTをしています。  
KPTの具体的なやり方については割愛しますが、特に気をつけていることは以下です。

KPTをする上で気をつけていること
ルールを守ること
はじめにグランドルールを作成してそれを守るようにしています。  
  •  積極的に話すこと
  • 1人で話しすぎないこと
  • 謝罪不要(悪いのはプロセスなので改善について話そう)
テンポよく進める
話しすぎが起きないように、テンポ良く切るようにしています。
議論が必要な場合は別で時間を設ける。(PeXではみんなでランチを食べながら話すことが多いです)

必ず具体的なアクションと担当を決めて行動する
TRYで上がったものから今週アクションするものを選択し、具体的なアクションと担当者を決めます。
TRYそのままでなく具体的なアクションにするのが重要です。


開発についてのふりかえり
  • 週1回
  • 開発メンバー全員参加
  • その週の開発に関すること、改善すべきことなど主に開発に関わることについて話す

運用についてのふりかえり
  • 月1回
  • 開発、プロデューサー、営業、デザイナが参加
  • サービス開発に関わること全般について
  • スケジュールや案件優先度の決め方、運用フローの見直しなど

2つのふりかえりを行うことで何を得たのか?

皆が抱えていることが共有できた  
新しいメンバーが多いチームで特に大事なことで、抱えている課題や今後進めたいことなど明確に話し合うきっかけになりました。  
課題の共有だけでなく、うまくいったこと、これからも継続したいことを話せるのも良い機会です。

課題に対して具体的に改善アクションを取れるようになった
KPTであがったProblem(問題)に対する具体的なアクション、担当者を決めることで毎回改善アクションをとるようになりました。  
アクションと担当者を明確にすることが重要です。

二つのふりかえりを行うことで進め方自体の改善ができた
開発チーム内の問題だけでなく、ステークホルダー全員を巻き込むことで運用も含めた
サービス開発の進め方についても改善するきっかけができました。  
この場で話しあう中で、実施する施策に関する背景なども共有できたりと良いコミュニケーションが生まれました。

ステークホルダーを巻き込むコツ
突然KPTするからと、色んな職種の方を呼ぶだけだとなかなか一体になったふりかえりができなかったりします。
事前にふりかえりをする目的をそれぞれに話しておくことが必要だと思います。
プロデューサー、営業、エンジニア、デザイナそれぞれのリーダーを捕まえて個別にふりかえりの目的と、手段にについて説明をすること。
そこであがった懸念などは事前に改善策を検討しておきましょう。
皆が改善に向けてふりかえりをしやすいように事前相談は必要不可欠です。

まとめ
開発チームだけでなく、ステークホルダーを巻き込むことでサービス開発全体が良い方向に進む。
運用フローなど、進め方自体のふりかえりをすることで、チームの成長に合わせて仕組み自体も成長させていくことができる。

まだまだチームとして動き始めて間もないですが、日々前進している良いチームになっている実感があります。
これから新しいチームで動き出す人も、長く同じチームで動いてる人もステークホルダーを巻き込んだふりかえりをしてみてはいかがでしょうか。
いつもとは違う何かが見えてくるかもしれません。


ふりかえりがうまくいくとこんな意欲的な笑顔で働けるようです。
image-min

QUnit+PhantomJS+JenkinsでJavaScriptの品質を改善!

はじめまして!cosmiRelationshipSuiteの開発者であるマルィシェフ・ドミトリーと申します。
 
世の中で、Webベースシステムが増えており、管理画面の開発を担当している、エンジニアの視野から抜けがちであるJavaScriptのテストについてお話します。
最近の数年、TDD概念が非常に流行っており、Model(ビジネスロジック)をテストするJUnitやPHPUnitの利用は当たり前のようなことになりました。
それと同じく、JS(要するに、Front側のロジック)のテストがをしっかりできる環境として、QUnit+PhantomJS+Jenkinsの組み合わせを紹介したいと思います。

初めに
この度、localhostで開発・テスト・本番環境を設定し、開発→テスト→本番マシンへの展開を再現し、
JavaScriptのTDDを実践で試してみましょう。

利用するツールに関して 

Jenkins
CI(Continuous Integration→継続的インテグレーション)のツールです。
Jenkinsの詳しい資料は、http://jenkins-ci.org/にあります。

PhantomJS
PhantomJSはJavaScript APIで動くヘッドレスWebKitです。要するに、ブラウザーがなくてもJavaScriptが実行できる仕組みを提供していただいております。
PhantomJSについて、http://phantomjs.org/ をお読みください。

QUnit
QUnitはJavaScriptのUnit Testing Frameworkです。その大きなメリットは、
  • 非常にlightweightである
  • 学習コストが安い
  • 豊富なpluginが用意されている
  • synchronous/asynchronous callbackのテストが可能
  • モジュール定義により、htmlファイル毎にJSテストを分けることもできる
QUnitの利用に関して、詳しくはhttp://qunitjs.com/cookbook/#introductionをご覧ください。

早速、環境を用意しましょう。。。

前提条件
gitがマシンに既にインストールされていて、GitHubのアカウントを保有していること。

1. PhantomJSをインストール

ローカルフォルダーの下にgit cloneでPhantomJSを取得し、下記の手順に従い、ビルドしてください。
私の場合、/myprojects/phantomjsにgithubからcloneしました。
mkdir /myprojects
cd /myprojects
git clone git://github.com/ariya/phantomjs.git
そこからQUnitを実行するスクリプトを呼び出します。でも、それについて、後程。。。

そして、PhantomJSをインストールします。
sudo apt-get update 
sudo apt-get install phantomjs
ビルドに関して、http://phantomjs.org/build.html に書いてあります。
※ ビルドは数時間かかる場合もございます。 

2. Jenkinsをインストール

wget -q -O - https://jenkins-ci.org/debian/jenkins-ci.org.key | sudo apt-key add -
sudo sh -c 'echo deb http://pkg.jenkins-ci.org/debian binary/ > /etc/apt/sources.list.d/jenkins.list'
sudo apt-get update
sudo apt-get install jenkins
今回は、Ubuntuでインストールしましたので、その他のシステムのJenkinsインストール手順に関して、
https://wiki.jenkins-ci.org/display/JENKINS/Installing+Jenkinsをご覧ください。

デフォルトでJenkinsはhttp://127.0.0.1:8080で見れます。

3. JenkinsとGitHubを連携

必要となるpluginをインストールします。
「Jenkinsの管理」→「プラグイン管理」で、「利用可能」タブで、「Git Plugin」、「Parameterized trigger Plugin」、「GitHub pull request builder plugin」、「GitHub Plugin」を検索し、インストールしてください。

pluginインストールが完了したらJenkinsを再起動してください。
sudo service jenkins restart
JenkinsとGitHubを連携する際、必要となる鍵を生成しましょう。jenkinsユーザ(Jenkinsインストール時に自動的に作成されるユーザ)の権限で、鍵を生成しなければなりません。
sudo su -l jenkins
ssh-keygen -t rsa -C "jenkins@hogehoge.com"
鍵を生成する際、デフォルトのまま進めてください。
Generating public/private rsa key pair.
Enter file in which to save the key (/var/lib/jenkins/.ssh/id_rsa):
Created directory '/var/lib/jenkins/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /var/lib/jenkins/.ssh/id_rsa.
Your public key has been saved in /var/lib/jenkins/.ssh/id_rsa.pub.
The key fingerprint is:
09:b6:79:a6:b4:9d:5b:d0:ab:36:fb:93:ea:a4:62:7e jenkins@hogehoge.com
生成された鍵、Ubuntuの場合、デフォルトで/var/lib/jenkins/.sshに生成されます。
できた鍵をknown_hostsに追加します。
eval $(ssh-agent)
ssh-add /var/lib/jenkins/.ssh/id_rsa
その後、GitHubの「Settings」→「SSH keys」→「Add SSH Key」を開きます。
Titleに適当な名前を入力して、/var/lib/jenkins/.ssh/id_rsa.pub(生成されたJenkins公開鍵Jenkinsのデフォルト保存場所)の内容をコピーして、Keyに貼り付けます。

GitHubの鍵生成の詳しくは、https://help.github.com/articles/generating-ssh-keysを参照できます。

4. GitHubのリポジトリーを作成
GitHubでtestrepoリポジトリーを作成します。

5. 開発環境の用意
testrepoをローカルの作業フォルダーにcloneします。
mkdir /workdir
cd workdir/
git clone --recursive https://github.com/d-malyshev/testrepo.git 
apacheのconfファイルに作業フォルダーパスを追加<VirtualHost *:80>
    DocumentRoot /workdir/testrepo/public_html
    ServerName work.myserver.com

    ErrorLog "/var/log/apache2/work_server-error_log"
    CustomLog "/var/log/apache2/work_server-access" common
</VirtualHost>
/etc/hostsに開発用のサーバを追加

127.0.0.1 work.myserver.com

6. プロジェクトのソースコードを実装
開発フォルダーのtestrepoの下で、加算・引き算をする簡単なファイルを実装しましょう。
それより、先にGitHubのtest_branchのブランチを作成します。
cd /workdir/testrepo
git checkout -b test_branch
プロジェクトは以下のファイル構造になります。
/public_html
    /index.html -> indexファイル
    /add.html -> 足し算の処理
    /subtract.html -> 引き算の処理
    /js -> JavaScriptフォルダー
        /test -> ここでJavaScript用のUnit Testの.jsファイルを保存します
            /unit_test.js -> 実際のUnit Test
まずは、htmlページを実装します。

index.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Calculation Page</title>
</head>
<body>
    <p>Welcome to calculation site!</p>
    <p><a href="add.html">Addition</a></p>
    <p><a href="subtract.html">Subtraction</a></p>
</body>
</html>
add.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Calculation Page: addition</title>
</head>
<body>
    <script>
    function calculateAdd(a, b)
    {
        var result = a + b;
        return result;
    }
    </script>
    <script>
    var res = calculateAdd(1, 2);
    document.write("1 + 2 = " + res);
    </script>
</body>
</html>
subtract.html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Calculation Page: subtraction</title>
</head>
<body>
    <script>
    function calculateSubtract(a, b)
    {
        var result = a - b;
        return result;
    }
    </script>
    <script>
        var res = calculateSubtract(2, 1);
        document.write("2 - 1 = " + res);
    </script>
</body>
</html>
 
今回、テストしたいJavaScriptのロジックはadd.htmlとsubtract.htmlのページに実装していきます。
QUnitでテストできるには、ソースコードに数行を追加しなければいけません。

QUnitのライブラリjsとその表示用のcssをhtmlのheadに追加します。

<link rel="stylesheet" type="text/css" href="//code.jquery.com/qunit/qunit-1.15.0.css">
<script src="//code.jquery.com/qunit/qunit-1.15.0.js"></script>

QUnitのテスト結果が表示されるqunitとqunit-fixtureのidを持っているdivもhtmlのbody追加します。
<div id="qunit"></div>
<div id="qunit-fixture"></div>
そして、QUnitのUnit Testも実装します。
QUnit.test("calculateAdd test", function(assert) {
    var value = calculateAdd(1, 2);
    var expected = 3;
    assert.equal(value, expected, "We expect addition result to be " + expected);
});
すべてを組み合わせると、以下のようになります。
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Calculation Page: addition</title>
  <link rel="stylesheet" type="text/css" href="//code.jquery.com/qunit/qunit-1.15.0.css">
  <script src="//code.jquery.com/qunit/qunit-1.15.0.js"></script>
</head>
<body>
    <script>
    function calculateAdd(a, b)
    {
        var result = a + b;
        return result;
    }
    </script>
    <script>
        var res = calculateAdd(2, 1);
        document.write("1 + 2 = " + res);
    </script>
   <script>
      QUnit.test("calculateAdd test", function(assert) {
        var value = calculateAdd(1, 2);
        var expected = 3;
        assert.equal(value, expected, "We expect addition result to be " + expected);
    });
    </script>
    <div id="qunit"></div>
    <div id="qunit-fixture"></div>
</body>
</html>
ブラウザで見ると、この感じになります。

jenkins35
CLIでもテストできます。
そのために、phantomjsから、QUnitを実行するrun-qunit.jsを呼び出します。
phantomjs /myprojects/phantomjs/examples/run-qunit.js http://work.myserver.com/add
.html
'waitFor()' finished in 220ms.
Tests completed in 20 milliseconds.
1 assertions of 1 passed, 0 failed.
※ run-qunit.jsのパスはPhantomJSのソースコードの保存先によって変わります。

QUnitテストのソースコードをテスト専用のjs/test/unit_test.jsに移行しましょう。または、各htmlファイルにQUnit用のcssやdiv.qunitとdiv.qunit-fixtureを追記しないように、それを動的に生成するようにしましょう。
さて、unit_test.jsは以下のようになります。
// Test環境のみで必要な結果表示用のdivやcssを追加
var d = document;
var qd = d.createElement('div');
qd.id = "qunit";
d.body.appendChild(qd);

var qfd = d.createElement('div');
qfd.id = "qunit-fixture";
d.body.appendChild(qfd);

//QUnitのstylesheetを追加
var head = d.getElementsByTagName('head')[0];
var css = d.createElement("link")
css.setAttribute("rel", "stylesheet")
css.setAttribute("type", "text/css")
css.setAttribute("href", "//code.jquery.com/qunit/qunit-1.15.0.css");
head.appendChild(css);

// 足し算Testを実行
QUnit.test("calculateAdd test", function(assert) {
    var value = calculateAdd(1, 2);
    var expected = 3;
    assert.equal(value, expected, "We expect addition result to be " + expected);
});
add.htmlも修正します。
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Calculation Page: addition</title>
    <script src="//code.jquery.com/qunit/qunit-1.15.0.js"></script>
</head>
<body>
    <script>
    function calculateAdd(a, b)
    {
        var result = a + b;
        return result;
    }
    </script>
    <script>
    var res = calculateAdd(1, 2);
    document.write("1 + 2 = " + res);
    </script>
    <script src="js/test/unit_test.js"></script>
</body>
</html>
ただし、subtract.htmlのQUnitのテストjs/test/unit_test.jsを追加すると...
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>Calculation Page: subtraction</title>
    <script src="//code.jquery.com/qunit/qunit-1.15.0.js"></script>
</head>
<body>
    <script>
    function calculateSubtract(a, b)
    {
        var result = a - b;
        return result;
    }
    </script>
    <script>
        var res = calculateSubtract(2, 1);
        document.write("2 - 1 = " + res);
    </script>
    <script src="js/test/unit_test.js"></script>
</body>
</html>
...subtract.htmlのUnit Testは失敗します。
phantomjs /myprojects/phantomjs/examples/run-qunit.js http://work.myserver.com/subtract.html
'waitFor()' finished in 208ms.
Tests completed in 34 milliseconds.
0 assertions of 1 passed, 1 failed. 
失敗の理由は、subtract.htmlでテストしようとしているcalculateAddの関数がないからです。
もちろん、subtract.htmlの関数のみのUnit Testのjsを実装すれば、subtract.htmlのUnit Testは成功します。
しかし、各htmlファイル用のUnit Testのjsを用意するのが非常に面倒です。

そのために、QUnitでModuleという仕組みが設けられ、複数htmlページの関数テストを一つのjsファイルでまとめて、モジュール毎の呼び出しは可能です。

足し算処理のテストと引き算処理のテストをそれぞれ、add_testとsubtract_testに分けます。
// モジュールadd_testを作成(public_html/add.htmlページのJSテスト用)
QUnit.module("add_test");

// 足し算Testを実行
QUnit.test("calculateAdd test", function(assert) {
    var value = calculateAdd(1, 2);
    var expected = 3;
    assert.equal(value, expected, "We expect addition result to be " + expected);
});

// モジュールsubtract_testを作成(public_html/subtract.htmlページのJSテスト用)
QUnit.module("subtract_test");

// 引き算Testを実行
QUnit.test("subtract_test calculateSubtract test", function(assert) {
    var value = calculateSubtract(2, 1);
    var expected = 1;
    assert.equal(value, expected, "We expect subtraction result to be " + expected);
});
できたモジュールをもう一度、呼び出してみます。モジュール毎のUnit Testは、http://yourdomain/filename?module=moduleName形式で呼び出されます。
足し算のテスト
phantomjs /myprojects/phantomjs/examples/run-qunit.js http://work.myserver.com/add.html?module=add_test
'waitFor()' finished in 216ms.
Tests completed in 17 milliseconds.
1 assertions of 1 passed, 0 failed.
引き算のテスト
phantomjs /myprojects/phantomjs/examples/run-qunit.js http://work.myserver.com/subtract.html?module=subtract_test
'waitFor()' finished in 207ms.
Tests completed in 19 milliseconds.
1 assertions of 1 passed, 0 failed.
最後には、unit_test.jsにもう少し手を加えましょう。

実は、その開発環境でも本番環境でもQUnitのJavaScriptは毎回呼ばれるのが困ります。
結局、テスト用のマシンのみQUnitを実行したいわけです。そのため、QUnit.config.autostartの設定項目が存在しています。そもそも、QUnit.config.autostartはtrueになっているから、ページがロードされる度にUnit Testは走ります。
そこで、テスト用のtest.myserver.comでのみ実行できるようにQUnit.config.autostartを工夫します。

QUnit.config.autostart = (window.location.href.indexOf("test.myserver.com") > -1) ? true : false;
 
最終的に、Unit Test用のjs/test/unit_test.jsファイルは下記の形をとります。
// テスト環境のみで実行
QUnit.config.autostart = (window.location.href.indexOf("test.myserver.com") > -1) ? true : false;

// Test環境のみで必要なdivやcssを追加
if (QUnit.config.autostart != false) {
    // 結果表示divを追加
    var d = document;
    var qd = d.createElement('div');
    qd.id = "qunit";
    d.body.appendChild(qd);

    var qfd = d.createElement('div');
    qfd.id = "qunit-fixture";
    d.body.appendChild(qfd);

    //QUnitのstylesheetを追加
    var head = d.getElementsByTagName('head')[0];
    var css = d.createElement("link")
    css.setAttribute("rel", "stylesheet")
    css.setAttribute("type", "text/css")
    css.setAttribute("href", "//code.jquery.com/qunit/qunit-1.15.0.css");
    head.appendChild(css);
}

// モジュールadd_testを作成(public_html/add.htmlページのJSテスト用)
QUnit.module("add_test");

// 足し算Testを実行
QUnit.test("calculateAdd test", function(assert) {
    var value = calculateAdd(1, 2);
    var expected = 3;
    assert.equal(value, expected, "We expect addition result to be " + expected);
});


// モジュールsubtract_testを作成(public_html/subtract.htmlページのJSテスト用)
QUnit.module("subtract_test");

// 引き算Testを実行
QUnit.test("subtract_test calculateSubtract test", function(assert) {
    var value = calculateSubtract(2, 1);
    var expected = 1;
    assert.equal(value, expected, "We expect subtraction result to be " + expected);
});
できたソースコードをGitHubのtest_branchにpushしましょう。
git add .
git commit -m "Initial commit"
git push origin test_branch
7. Jenkinsのjobを作成
こちらで、ソースコードをbuild/test/deployするjobを作成します。

status_update_job: build状態をGitHubに知らせるjobを作成

プロジェクトをビルドするjobはそれを参照するので、先に作ります。

「新規ジョブ作成」で
「フリースタイル・プロジェクトのビルド」にチェック
「プロジェクト名」→ status_update_job
「OK」で作成画面に入ります。

ジョブ作成画面で
「ビルドのパラメータ化」にチェック
「ビルドのパラメータ化」→「パラメータの追加」→「文字列」で3つのパラメータを作成し、それぞれの「名前」にCOMMIT_STATUS、UPDATE_COMMIT、REPOSITORY_NAMEを入力
「ソースコード管理」→「なし」にチェック
「ビルド」→「シェル実行」を選択します。
「ビルド」→「シェルスクリプト」にビルドされたcommitの状態(successまたは、failure)をGitHubに通知する処理
curl -i -H 'Authorization: token abcdef0123456789abcdef012345fc2b6142d8a7' \
    -d '{"state": "'${COMMIT_STATUS}'"}' \
    https://api.github.com/repos/${REPOSITORY_NAME}/statuses/${UPDATE_COMMIT}
tokenはOAuth用に生成してください。

GitHubの「Settings」→「Applications」→「Generate new token」でOAuthトークンを生成し、その文字列をどこかで保存してください。トークンを作成する際、repoにチェックが入っていることを、確認してください。

build_job: プロジェクトをビルドするjobを作成

「新規ジョブ作成」で
「フリースタイル・プロジェクトのビルド」にチェック
「プロジェクト名」→ build_job
「OK」で作成画面に入ります。

ジョブ作成画面で
「ソースコード管理」→「Git」にチェック
「Repositories」→「Repository URL」にgit@github.com:{githubのアカウント}/{あなたのリポジトリ―}(私の場合、git@github.com:d-malyshev/testrepo.gitです)
「Repositories」→「Credentials」で「なし」を選択
「Branches to build」に2つのbranchを「Add Branch」で追加してください。それぞれの「Branch Specifier」に「*/master」と「*/release」を入力してください。
「Additional Behaviors」で「Strategy for choosing what to build」を選択し、その中から「Inverse」にしてください。
「ビルド・トリガー」→「SCMをポーリング」にチェック
「ビルド・トリガー」→「スケジュール」に常に起動するように設定
 
* * * * *

「ビルド」→「シェル実行」を選択します。
「ビルド」→「シェルスクリプト」にPhantomJS+QUnitのモジュールテストを指定します
phantomjs /myprojects/phantomjs/examples/run-qunit.js http://test.myserver.com/add.html?module=add_test
phantomjs /myprojects/phantomjs/examples/run-qunit.js http://test.myserver.com/subtract.html?module=subtract_test
「ビルド後の処理」→「Trigger parametrized build on other projects」を選択
「Add trigger」で2つのBuild Triggersを追加
その二つは、以下のようになります

1番目
「Projects to build」→ status_update_job
「Trigger when build is」→「Stable or unstable but not failed」を選択
「Predefined parameters」に
COMMIT_STATUS=success
UPDATE_COMMIT=${GIT_COMMIT}
REPOSITORY_NAME=あなたのアカウント/あなたのリポジトリ―(私の場合、d-malyshev/testrepo)
2番目
「Projects to build」→ status_update_job
「Trigger when build is」→「Failed」を選択
「Predefined parameters」に
COMMIT_STATUS=failure
UPDATE_COMMIT=${GIT_COMMIT}
REPOSITORY_NAME=あなたのアカウント/あなたのリポジトリ―(私の場合、d-malyshev/testrepo)

mergeされたリポジトリ―を本番サーバにdeployするjobを作成

「新規ジョブ作成」で
「フリースタイル・プロジェクトのビルド」にチェック
「プロジェクト名」→ deploy_job
「OK」で作成画面に入ります。

ジョブ作成画面で
「ソースコード管理」→「なし」にチェック
「ビルド・トリガー」→「定期的に実行」にチェック
「ビルド・トリガー」→「スケジュール」に常に起動するように設定。5分毎にmergeされたプロジェクトを確認したい場合、以下のように記述
*/5 * * * *
「ビルド」→「シェル実行」を選択します。本番サーバに最新のソースコードをpullします
if [ -d /myserver/testrepo ]; then
    cd /myserver/testrepo
    git pull origin master
else
    cd /myserver
    git clone --recursive https://github.com/d-malyshev/testrepo.git
fi

8. 本番環境の用意
GitHubでbranchがmasterにmergeされた後、本番環境にソースコードをdeployします。
今回、開発環境や本番環境は同じマシンになっていますので、本番環境は別のマシンになる場合、rsyncなどをご利用ください。
/myserverフォルダーを作成してください。
apacheのconfファイルに作業フォルダーパスを追加
<VirtualHost *:80>
    DocumentRoot /myserver/testrepo/public_html
    ServerName prod.myserver.com

    ErrorLog "/var/log/apache2/prod_server-error_log"
    CustomLog "/var/log/apache2/prod_server-access" common
</VirtualHost>
/etc/hostsに開発用のサーバを追加
 
127.0.0.1 prod.myserver.com 

9. Jenkinsでのテスト環境の用意
PhantomJSはQUnitをテスト用のサーバで実行するので、先ほど作成されたJenkinsのbuild_jobはtest.myserver.comテストサーバのDocumentRootになるように、apacheのconfファイルに下記を追記します。
<VirtualHost *:80>
    DocumentRoot "/var/lib/jenkins/jobs/build_job/workspace/public_html"
    ServerName test.myserver.com

    ErrorLog "/var/log/apache2/test_server-error_log"
    CustomLog "/var/log/apache2/test_server-access" common
</VirtualHost>
/etc/hostsにも開発用のサーバを追加
 
127.0.0.1 test.myserver.com


10. PhantomJS+QUnit+Jenkinsの実践
これで、やっと開発・テスト・本番環境が揃いました。

本番環境にはまだ何もdeployされていないので、本番サーバはこの感じです。

とりあえず、add.htmlを修正し、bugを仕込みましょう。

bugを入れる前
function calculateAdd(a, b)
{
    var result = a + b;
    return result;
}
bugを入れた後
function calculateAdd(a, b)
{
    var result = a + b;
    // Unit Testを通らないようにbug
    return result+1;
}
そして、そのソースコードを、先作成してきたtest_branchに pushします。
git add .
git commit -m "Created bug"
git push origin test_branch
GitHubでtest_branchのPull Requestを作成してみます。
それをやってみると、最近の当ブランチにpushされたcommitのbuild_jobが失敗したことが分かります。

jenkins16

ブランチをクリックすると、ビルドが失敗したcommitを見れます。

jenkins17

Jenkinsのjob一覧画面を見ると、build_jobの#8が失敗したことが分かります。
そのbuild_jobをクリックし、job結果一覧画面に移動します。

jenkins22

失敗した#8の詳細ページに行って、Console Outputでbuildの失敗した原因を調べることもできます。
 
jenkins23
jenkins21

build_jobの次に、status_update_jobが起動し、GitHubでcommitの状態をfailureに設定しました。

jenkins39


では、仕込んできたbugを修正し、またtest_branchにpushしましょう。

bugを修正した後
function calculateAdd(a, b)
{
    var result = a + b;
    return result;
}
そして、test_branchにpushします。
git add .
git commit -m "Fixed bug"
git push origin test_branch
今度、build_jobは成功し、GitHub上の結果はこのとおりとなります。

jenkins19

test_branchを「Merge pull request」→「Confirm merge」でmasterにmergeし、最後に「Delete branch」でtest_branchを削除します。その後、deploy_jobは起動し、masterから最新版のソースコードを本番サーバにpullします。
 
そして、先ほど設定した本番サーバのhttp://prod.myserver.comにアクセスし、ソースコードは問題なく表示されていることをご確認ください。

まとめ
「使いやすさと良き見映えは成功の8割」と言われるWeb画面ですが、
そのJavaScriptのバグは、ユーザーエクスペリエンスを低下させ、お客様からの多くのクレームの原因にもなります。 
そこで、QUnit+PhantomJS+Jenkinsを利用したら、Front側JSの品質向上に充分貢献できるかと思います。
 


PyCon JP 2014 ジョブフェアのちょっとだけ補足 #pyconjp

9/14(日)に行われたPyCon JP 2014ジョブフェアのパネルディスカッションで登壇してきました @makogaです。

さっそくメディアスポンサーでもあるエンジニアtypeでレポートが公開されました。
とてもコンパクトにまとまっていて素晴らしいですね。

パネルディスカッションということで資料なしでのトークだったので、ちょっとだけ補足したいと思います。

横串の情報共有はSlackが人気
はい、Slack大人気です。ぼくも大好き! 
Slackはbotが簡単に作成できることや、Emojiやアイコンが使えて柔らかい雰囲気を作れるのがいいですね。

プロジェクト単位ではGitHubのissue
プロジェクト管理はチームごとに最適なツールを使っています。
最近はTrelloが人気ですし、結局Redmineに落ち着くチームもあります。

毎日のランチミーティング
あー、私の説明が分かりづらかったですね。
ほとんどのチームがDaily meetingをやってるという話と、ランチ時間に弁当食べながら各チームの事例を紹介する話が混ざったっぽい。。

導入はトップダウンではなく、個人レベルから始まります。徐々に広がって、定着しそうであれば会社として導入するというスタンスです。
これは本当にそのとおりで、GitHub、Slackはまさに徐々に広がって定着しました。

新しい技術の導入提案は、コンテストのような社内イベントとして実施
これは毎回イベントを開催しているわけではなく、最近そういうことをやってみたという話でした。
事例としては、アドテク系のサーバーサイドでボトルネックになっている箇所の性能改善をやろうという話で、チームメンバー各々が業務時間の一部を使ってプロトタイプを開発し、最も評価が高かった技術を採用しました。
検討した言語は、D言語、Scala、Go、Lua、Rustで、前評判どおりGoが勝ちました。Goはえー!


PyCon JPでジョブフェアを行うのは今回が初めてということでしたが、立ち見が出るくらいの大盛況でした。
その後のmeetupでもお話できたので、来年もジョブフェアがあれば参加したいと思います。
関係者のみなさま、ありがとうございました。


[PR]
VOYAGE GROUPには無料シェア会議室 PORT社内バー AJITOがあり、勉強会などに無料で貸し出しています。
さらに期間限定で、5〜10分の企業PRタイムをいただくことで、寿司・ピザスポンサーも行っております。
ご興味ある方は @makoga に気軽にご連絡ください。
 

Amazon VPC と仮想プライベートゲートウェイを使わずに繋いでみたかったのでやってみた

こんにちは、adingo で Fluct という広告配信まわりのインフラやってる あわいいしま (@katz_arc) です。
月間200億超のインプレッションを捌くSSP である Fluct を支えるべく、日夜頑張っております。

今回はタイトルの通り、Amazon VPC で使える仮想プライベートゲートウェイを使わずにオンプレのデータセンター (以下 IDC) と VPC の間を VPN 接続したお話です。

前提

過去には仮想プライベートゲートウェイを利用して VPN 接続を構築したこともあります。
それが何故、その VPN 接続を使わずに自前で構築しようと考えたか、そこには2つほど理由がありました。

1. ゲートウェイを作成するたびに Global IP アドレスが変更されてしまうのが困る

VPN  接続を行うために重要なパラメータとなる IP アドレスが変更されると、それに伴い IDC 側 L3 スイッチの ACL を修正する必要があります。
これは何度もやりたい (やるべき) 作業ではありません。

2. 自分で1から設定する事により AWS  のネットワーク的挙動を確認したかった

VPN 接続を行おうとすると、通常の EC2 インスタンスを利用するだけであれば知らなくても困らない設定を行う必要がでてきます。
それにより AWS 独特な挙動、特にネットワークまわりをより知ることができるかもしれないという期待がありました。

材料

今回 VPN 接続に利用するのは VyOS です。
VyOS は Vyatta という OSS なソフトウェアルータが Brocade に買収され、無償版である Vyatta Core の新規開発が終わってしまった際に無償版からフォークして生まれました。
詳細は wikipedia の VyattaVyOS の頁を見てください。

IDC 側は専用のサーバは準備せず、KVM を利用して VyOS を立ち上げました。
自分の環境では bridge インタフェースを作るにあたり、bonding インターフェース直から VLAN インタフェースへの切り替えなど、いくつかホスト側の設定変更が必要になりました。

AWS 側は Community AMIs に VyOS 1.0.4 があるのでそれを利用しています。(作業時は ami-ad590eac on apne)
Community AMI ですし、利用にあたってはご自身の責任の元でお願いします。

レシピ図

VPN 接続の構成を簡単に図で、今回は vti (仮想トンネルインタフェース) は利用していません。
IDC_VPN_AWS

手順

1. IDC 側 VyOS の準備

KVM を使っての OS インストールは本題ではないので割愛します。
設定に必要な情報はレシピの図を参考にしてください。

1つ補足すると、VyOS は debian ベースであるものの、ソフトウェアルータですのでネットワークの設定などすべて専用コマンドで設定していきます。例として、console に繋いで IP アドレス、default gateway、ssh のサービスを設定するのであれば以下のようにします。
configure
set interfaces ethernet eth0 address 172.16.100.1/24
set interfaces ethernet eth1 address 192.168.100.1/24
set system gateway-address 192.168.100.254
set service ssh listen-address 172.16.100.1
commit
save
ここから VPN の設定を入れ込んでいきます
set vpn ipsec ipsec-interfaces interface eth1
set vpn ipsec ike-group to_AWS lifetime 28800
set vpn ipsec ike-group to_AWS proposal 1 encryption aes128
set vpn ipsec ike-group to_AWS proposal 1 hash sha1
set vpn ipsec esp-group to_AWS lifetime 3600
set vpn ipsec esp-group to_AWS proposal 1 encryption aes128
set vpn ipsec esp-group to_AWS proposal 1 hash sha1
set vpn ipsec site-to-site peer 192.168.200.1 authentication mode pre-shared-secret
set vpn ipsec site-to-site peer 192.168.200.1 authentication pre-shared-secret vpnsecret
set vpn ipsec site-to-site peer 192.168.200.1 authentication id @idc01
set vpn ipsec site-to-site peer 192.168.200.1 authentication remote-id @aws01
set vpn ipsec site-to-site peer 192.168.200.1 default-esp-group to_AWS
set vpn ipsec site-to-site peer 192.168.200.1 ike-group to_AWS
set vpn ipsec site-to-site peer 192.168.200.1 local-address 192.168.100.1
set vpn ipsec site-to-site peer 192.168.200.1 tunnel 1 local prefix 172.16.100.0/24
set vpn ipsec site-to-site peer 192.168.200.1 tunnel 1 remote prefix 10.0.200.0/24
commit
save
これで IDC 側の設定は完了です

2. AWS 側 VyOS の準備


インスタンス作成にあたり幾つか注意点を
  • VPN を利用するために SecurityGroup の設定で IDC 側 VyOS からの IKE(UDP:500)/ESP(IP:50) を開放する必要があります。
  • VyOS はともかく、その先の本来接続したいサーバ (今回であれば AWS Manager) にとっては IDC 宛はプライベート IP アドレス同士での接続となるため、ルーティングテーブルをなんらかの方法で設定する必要があります。これは subnet に付与する rtb で対応します。
インスタンス起動については割愛します。IKE/ESP 以外の SG は環境に合わせて設定してください。
IDC 側プライベートアドレスへのルーティング設定は Management Console で設定できなかったため、以下の様にして設定しました。(awscli 利用)
aws ec2 create-route --route-table-id rtb-(public subnet の rtb-id) --destination-cidr-block 172.16.100.0/24 --network-interface-id eni-(VyOS インスタンスの eth0 に attach された eni-id)
上記以外は特に難しいところはありません。
configure
set interface eth0 address dhcp

set vpn ipsec ipsec-interfaces interface eth0
set vpn ipsec ike-group to_IDC lifetime  28800
set vpn ipsec ike-group to_IDC proposal 1 encryption aes128
set vpn ipsec ike-group to_IDC proposal 1 hash sha1
set vpn ipsec esp-group to_IDC lifetime  3600
set vpn ipsec esp-group to_IDC proposal 1 encryption aes128
set vpn ipsec esp-group to_IDC proposal 1 hash sha1
set vpn ipsec site-to-site peer 192.168.100.1 authentication mode pre-shared-secret
set vpn ipsec site-to-site peer 192.168.100.1 authentication pre-shared-secret vpnsecret
set vpn ipsec site-to-site peer 192.168.100.1 authentication id @aws01
set vpn ipsec site-to-site peer 192.168.100.1 authentication remote-id @idc01
set vpn ipsec site-to-site peer 192.168.100.1 default-esp-group to_IDC
set vpn ipsec site-to-site peer 192.168.100.1 ike-group to_IDC
set vpn ipsec site-to-site peer 192.168.100.1 local-address 10.0.200.1
set vpn ipsec site-to-site peer 192.168.100.1 tunnel 1 local prefix 10.0.200.0/24
set vpn ipsec site-to-site peer 192.168.100.1 tunnel 1 remote prefix  172.16.100.0/24
commit
save
これで AWS 側の設定は完了です

3. 接続確認

両方の設定が完了したので接続の確認をしてみます。

まず IPSec の接続性を確認してみます

on IDC
vyos@vyos:~$ show vpn ipsec sa
Peer ID / IP                            Local ID / IP
------------                            -------------
192.168.200.1                            192.168.100.1

    Tunnel  State  Bytes Out/In   Encrypt  Hash  NAT-T  A-Time  L-Time  Proto
    ------  -----  -------------  -------  ----  -----  ------  ------  -----
    1       up     0.0/0.0        aes128   sha1  no     3098    3600    all
on AWS
vyos@vyos:~$ show vpn ipsec sa
Peer ID / IP                            Local ID / IP
------------                            -------------
192.168.100.1                         10.0.200.1

    Tunnel  State  Bytes Out/In   Encrypt  Hash  NAT-T  A-Time  L-Time  Proto
    ------  -----  -------------  -------  ----  -----  ------  ------  -----
    1       up     1.3K/1.3K      aes128   sha1  no     449     3600    all
IDC からみた時の Peer ID/IP と AWS 側の Local ID/IP に差がある (EIP or Private IP) ことがわかります

VyOS 同士での ICMP 疎通を確認します (ping のオプション設定が通常の Linux 違います)

on IDC
vyos@vyos:~$ ping 10.0.200.1 count 5
PING 10.0.200.1 (10.0.200.1) 56(84) bytes of data.
64 bytes from 10.0.200.1: icmp_req=1 ttl=64 time=7.61 ms
64 bytes from 10.0.200.1: icmp_req=2 ttl=64 time=7.74 ms
64 bytes from 10.0.200.1: icmp_req=3 ttl=64 time=7.71 ms
64 bytes from 10.0.200.1: icmp_req=4 ttl=64 time=7.75 ms
64 bytes from 10.0.200.1: icmp_req=5 ttl=64 time=7.83 ms

--- 10.0.200.1 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4008ms
rtt min/avg/max/mdev = 7.611/7.731/7.834/0.071 ms
on AWS
vyos@vyos:~$ ping 172.16.100.1 count 5
PING 172.16.100.1 (172.16.10.40) 56(84) bytes of data.
64 bytes from 172.16.100.1: icmp_req=1 ttl=64 time=7.74 ms
64 bytes from 172.16.100.1: icmp_req=2 ttl=64 time=7.90 ms
64 bytes from 172.16.100.1: icmp_req=3 ttl=64 time=7.57 ms
64 bytes from 172.16.100.1: icmp_req=4 ttl=64 time=7.63 ms
64 bytes from 172.16.100.1: icmp_req=5 ttl=64 time=7.87 ms

--- 172.16.100.1 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4006ms
rtt min/avg/max/mdev = 7.574/7.748/7.905/0.130 ms
ネットワーク的な疎通は問題なさそうです。
それでは本来の目的である VyOS の先にあるサーバ (インスタンス) 同士の接続を確認します
(IDC Manager には事前に 10.0.200.0/24 へのルートを 172.16.100.1 で設定してあります)
[root@IDC_Manager ~]# traceroute 10.0.200.2
traceroute to 10.0.200.2 (10.0.200.2), 30 hops max, 60 byte packets
 1  172.16.100.1 (172.16.100.1)  0.380 ms  0.492 ms  0.583 ms
 2  10.0.200.1 (10.0.200.1)  8.565 ms  8.817 ms  8.904 ms
 3  10.0.200.2 (10.0.200.2)  9.095 ms !X  9.274 ms !X  9.395 ms !X
traceroute に global ip address (今回であれば 192.168.100.x or 192.168.200.x) が出てこないことがわかります

最後に ssh です (SG の設定で 172.16.100.0/24 からの ssh を許可してあります)
[root@IDC_Manager ~]# slogin -i (aws の鍵) 10.0.200.2
[root@AWS_Manager ~]#
できました

まとめ

出来上がってしまえば一般的な LAN 間 VPN と同様な感覚で利用可能な環境ができました。

実際の利用環境では VyOS を設置した public subnet の裏に private subnet があり、その接続のために VyOS インスタンスへの ENI 追加、private subnet で利用する rtb に IDC 宛の接続設定なども行っており、環境によっては少し手間がかかることもあるかもしれません。

とは言え、VyOS を稼働させるのに必要なインスタンスもそれほどスペックは必要ありませんし、一度試してみては如何でしょうか。自分は次に VyOS のような専用 OS ではなく、汎用 Linux 上の OpenVPN での接続も試してみようと企んでいます。

お知らせ

最後にお約束となりますが、弊社には ajito という社内バーがあり、エンジニアが夜な夜な出現してビールを飲んだり技術的な話をしたりと楽しい場になっています(#ajiting といいます)。弊社エンジニアに一声掛けてくださると、無料でビールを飲みつつ歓談できるかと思います。また、勉強会の場としても提供していたりするので、アドテクに興味ある方もそれほど興味ない方もどんどんお声掛けください
記事検索
QRコード
QRコード