読者です 読者をやめる 読者になる 読者になる

WonderPlanet DEVELOPER BLOG

ワンダープラネットの開発者ブログです。モバイルゲーム開発情報を発信。

Amazon EC2上のJenkinsをマスターにし、NAT内にあるMacをスレーブにする

AWS Jenkins

最近、インフラ周りに手を出し始めているアプリエンジニアの岩原です。
今回は、勝手に不可能だと思っていた「NAT内にあるMacをJenkinsのスレーブにする」方法をご紹介したいと思います。
ついでに、マスターノードをAmazon EC2上(Amazon Linux)に建て、今どきな感じにしてみましょう。

【用意するもの】

  • Amazon EC2のインスタンス(Amazon Linux)
    • ElasticIPにて、固定IP割り振り済み
    • InboundのポートはTCP:8080(jenkins)とTCP:9000(slave用)と22(SSH)を開けておく
  • Mac(JDK7以上インストール済み)

Jenkinsのインストール

まずはJDKをインストールします。
Oracleのサイトからダウンロードするのは面倒なので、OpenJDKをインストールします。
バージョンは7以上であれば何でも良いので、今回はJDK7をインストールします。

sudo yum install -y java-1.7.0-openjdk-devel.x86_64  

次にJenkinsをインストールします。
RedHat Repository for Jenkinsより引用

sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo  
sudo rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key  
sudo yum install -y jenkins  

これで、Jenkinsがサービスとしてインストールされます。
起動と停止は以下のとおりです。

sudo service jenkins start  
sudo service jenkins stop  

なお、このJenkinsはJetty上で動作しているようです。

Jenkinsへのアクセス

http://IPアドレス:8080/でアクセス可能です。
IPアドレスは確保しているIPアドレスになります。

だれでもアクセスできる状態になっているので、
Jenkinsの管理→グローバルセキュリティの設定から、「セキュリティの有効化」にチェックを入れ、アクセス制御を行いましょう。
Role Strategy Pluginなんかもオススメです。

スレーブに使うポートの固定

デフォルトでは、毎回ランダムなポートを使用して、スレーブとの通信を行いますが、
あまりポートをガバガバにしているのも面倒&問題なので、スレーブとの通信に使うポートを固定化します。
今回はスレーブ用に予め開けておいた9000番を使用することにします。

1.「Jenkinsの管理」から「グローバルセキュリティの設定」を選択します。(画像クリックで拡大)
0a2c975d-6e97-265c-d3fc-d31d67b8a0e8

2.「セキュリティを有効化」にチェックを入れます。(画像クリックで拡大)
c011e14d-947d-54cf-0c37-23e4254a784c

3.「JNLPスレーブ用TCPポート番号」で「固定」を選択し、9000を入力します。(画像クリックで拡大)
da3e4f62-fe38-e8cb-7642-0f5491ef83c1

4.「保存」ボタンを押します。

スレーブの設定

1.いったん、Jenkinsの管理に戻り、「ノードの管理」を選択します。(画像クリックで拡大)
c25f8552-edfd-2dc1-9723-9399c75e6162

2.「新規ノード作成」を選択します。(画像クリックで拡大)
4628ab02-94c0-6b1d-ff2b-8b3763aca513

3.「ノード名」は任意です。わかりやすい名前をつけましょう。名前を入力後、「ダムスレーブ」を選択し「OK」ボタンを押します。(画像クリックで拡大)
d5b5b433-6ff3-899f-1fc4-eaddf72d8d95

4.詳細情報を入力します。入力後、保存ボタンを押します。(画像クリックで拡大)
23641d05-1c32-29af-59e6-2955b7d4cb37

ヘルプボタン(?マーク)を押すと、大体の説明が載っておりますが、一応、以下に簡単な説明を。
太字部分は今回の設定値です。

項目名 内容
ノード名 さっき入力したヤツ
説明 このスレーブの説明
同時ビルド数 このスレーブの同時ビルド数
リモートFSルート このスレーブ上のワークディレクトリ(絶対パス)
ラベル 複数のスレーブをまとめるためのラベル。スペース区切りで複数設定可
用途 スレーブの用途。「このマシーンを特定ジョブ専用にする」にする
起動方法 JNLP経由でスレーブを起動を選択
可用性 可能な限りオンラインのままにするを選択

スレーブの起動

次は、NAT内にあるMacをスレーブとして起動します。
Mac上でブラウザを起動し、Amazon EC2上に建てたJenkinsにアクセスします。

Jenkinsの管理から「ノードの管理」を選択します。
そして、先ほど作成したノードをクリックします。(画像クリックで拡大)
39210743-5a7a-bc3a-cfb1-38746b1b8049

「Launch」ボタンを押すと、Slave用のJNLPファイルがダウンロードされます。(画像クリックで拡大)
1f036198-4598-9dec-042d-49e23fe0af9c

ダウンロードしたJNLPファイルを実行します。
しばらくすると以下の様なウィンドウが表示されると思います。
「Connected」になっていれば、マスターノードとの接続に成功しています。(画像クリックで拡大)
727eced6-4511-a929-a199-df24080a94ca

またJenkinsの管理から「ノードの管理」を選択します。
スレーブの情報が表示されていればOKです。(画像クリックで拡大)
13fa5f86-1ef3-6f36-5ebc-28bbf26dd716

これで、マスターとスレーブの接続が完了しました。
なお、マスターへの接続方法はコマンドでも行うことが出来ます。
一旦切断し、「Launch」ボタンがある画面にてコマンドを確認することが出来ます。
実運用ではそちらのほうが都合がよいでしょう。

特定のスレーブでJOBを実行する

では、作成したスレーブに特定のJOBを任せたいと思います。

JOBの設定で「実行するノードを制限」にチェックを入れ、
「ラベル式」にスレーブの名前を入力します。(画像クリックで拡大)
bded3dbe-f837-6d97-4327-a2880e4b4be7

これで、特定のJOBを特定のスレーブで実行することができます。

どういう時に使うのか?

主に考えられるのは以下ような事例だと思います

  • iOSアプリのビルドをMacのスレーブに任せる
  • 負荷分散のために、分散ビルドを行う
  • Unityアプリのビルド

注意

ワークスペースは各スレーブ内に作成されますが、成果物はマスターのストレージ内に保存されます。
気をつけないとマスターのストレージがパンパンになってビルドができなくなるので注意してください。

(参考)弊社の事例

現在、弊社では以下の様な構成でJenkinsのマスター&スレーブを構築しております。
以前は社内のMacにて構築していましたが、徐々にEC2上のJenkinsに移行しています。

項目名 内容
Jenkins Google Login プラグインによる認証。ドメインにより社内の人間のみアクセス可能。
マスターノード Amazon EC2上に構築。S3のバケットをストレージとしてマウント済み。ビルドの成果物はそこに保存するようにしている。ビルドは基本的に行わない。
スレーブ1 社内のMac。開発中のiOSアプリとAndroidアプリをビルド。Xcodeの仕様により、並列ビルドはせず、同時ビルド数は1つ。
スレーブ2 Amazon EC2上に構築。Dockerインストール済。社内用Webアプリのテスト&デプロイを行う。