Jenkinsを導入したEC2インスタンスの運用方法について考えてみた。

2015.02.18

はじめに

私が現在参画している案件では、Jenkinsを用いてCIを行おうとしています。

そういった際にJenkinsのインスタンスの運用をどのようにするかが問題となります。

今回、下記の方法で運用をすることにしました。

  • インスタンス立ち上げ時に、Jenkinsに割り当てられたIPを通知する。
  • インスタンスは指定された時間にSTOPする。

IP通知手順

立ち上がっているインスタンスのPublic IPはメタデータとして下記の立ち上がっているインスタンスから下記のアドレスにアクセスすることで取得可能です。

http://169.254.169.254/latest/meta-data/public-ipv4

通知先に関しては、各々の環境に依存するとは思いますが、弊社ではBacklogをプロジェクト管理用のツールとして使っているので、そちらのWikiに書き込むことにしました。

Backlogへの書き込みは下記のライブラリを用いて、Javaで作成しました。

nulab/backlog4j

通知用のプログラム自体は以下になります。

package classmethod.main;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;

import com.nulabinc.backlog4j.BacklogClient;
import com.nulabinc.backlog4j.BacklogClientFactory;
import com.nulabinc.backlog4j.api.option.UpdateWikiParams;
import com.nulabinc.backlog4j.conf.BacklogConfigure;
import com.nulabinc.backlog4j.conf.BacklogJpConfigure;

public class JenkinsAddressToBacklog {

    /**
     * @param args
     */
    public static void main(String[] args) {
        try {
            writeBacklog();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
    }

    public static String getIP() {
        String line;
        String address = "";
        try {
            URL url = new URL(
                    "http://169.254.169.254/latest/meta-data/public-ipv4");
            HttpURLConnection connection = null;

            try {
                connection = (HttpURLConnection) url.openConnection();
                connection.setRequestMethod("GET");

                if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
                    try (InputStreamReader isr = new InputStreamReader(
                            connection.getInputStream(),
                            StandardCharsets.UTF_8);
                            BufferedReader reader = new BufferedReader(isr)) {
                        while ((line = reader.readLine()) != null) {
                            address = line;
                        }
                    }
                }
            } finally {
                if (connection != null) {
                    connection.disconnect();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return address;
    }

    public static void writeBacklog() throws MalformedURLException {
        BacklogConfigure configure = new BacklogJpConfigure("yourSpaceId ")
                .apiKey("yourApiKey ");
        BacklogClient backlog = new BacklogClientFactory(configure)
                .newClient();
        UpdateWikiParams param = new UpdateWikiParams(yourTargetWikiID);
        // 現在日時を取得する
        Calendar c = Calendar.getInstance();

        // フォーマットパターンを指定して表示する
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日 E曜日",
                Locale.JAPAN);

        param.name(sdf.format(c.getTime()) + "のJenkinsのアドレス");
        param.content("http://" + getIP() + "/jenkins/");
        backlog.updateWiki(param);
    }
}

上記のプログラムが動作すると、下記のような形でbacklogのwikiに書き込まれます。

Backlog Wiki

起動時に作ったプログラムを動かす方法は以下の記事が参考になります。

EC2で起動時やterminate時にシェルを実行する | Developers.IO

インスタンス停止

インスタンスの停止自体はAWS-CLIから行えますので、 停止用のシェルスクリプトをcronで実行させることとします。 *1

#!/bin/sh
aws ec2 stop-instances --instance-ids yourInstanceId

まとめ

EC2インスタンスのコストを抑えて運用するといった意味では、Jenkins以外にも適用できるネタかと思います。

脚注

  1. 正しく権限を付与する必要があります。EC2インスタンスにはIAM Roleの付与が推奨です。 IAMによるAWS権限管理運用ベストプラクティス (2) | Developers.IO