Raccoon Tech Blog [株式会社ラクーン 技術戦略部ブログ]

株式会社ラクーン 技術戦略部より、tipsやノウハウなど技術的な話題を発信いたします。

インフラ

AWS LambdaとAPI Gatewayを利用し、PagerDutyのインシデント発生時にSlackに専用チャンネルを作成する #1

こんにちは、インフラ及びシステム運用を担当している田中です。

当社ではサーバーやネットワークに障害が発生した際に、障害対応の担当者へ通知を行う手段としてPagerDutyを利用しています。

担当者が障害を認知した後は障害内容を調査し、必要に応じて開発者や責任者へエスカレーションを行うことになります。

障害の発生が平日の日中帯であれば関係者間のコミュニケーションに問題はないのですが、夜間・休日の場合は関係者がそれぞれ別の場所に居ることになるため、障害ごとにSlackの専用チャンネルを作成して関係者間で情報を共有しています。

SlackにはPagerDutyのWebhookを受け、インシデントの内容を特定のチャンネルにpostすることができる機能が用意されています。
しかし、あくまでも特定のチャンネルにpostすることができるだけで、インシデントごとに専用のチャンネルを作成したりすることはできません。

そこで、AWSのAPI Gateway経由でLambdaファンクションを呼び出し、SlackのAPIを叩いて専用チャンネルを作成するようにしています。

今回から数回に分け、この仕組について説明したいと思います。
続きを読む

ローカルUnboundによる名前解決の冗長化の検証


こんにちは!はんだです。
今日はDNSサーバの可用性向上についてのエントリです。

DNSサーバの障害時の影響を防ぐ方法として、
単純にDNSサーバを複数設置して/etc/resolv.confに記入するという方法がありますが、
その方法には、タイムアウトの待ち時間という落とし穴があります。

/etc/resolv.conf
nameserver 192.168.0.11  //DNS1のIPアドレス
nameserver 192.168.0.12  //DNS2のIPアドレス

のように設定したとして、
1行目のDNS1が落ちた状態の場合、2行目のDNS2に移行するまでに、設定次第ですが問い合わせの度に毎回1~数秒のタイムアウトが発生します。名前解決の頻度が高いサービスの場合、この僅かな待ち時間がサービス全体へのパフォーマンスに影響してきます(この問題については[24時間365日]サーバ/インフラを支える技術(技術評論社)の 「DNSサーバの冗長化」の項が詳しいです)。

この問題への対策として、LVS+Keepalivedなどを利用して冗長性を高める方法がありますが、それに加え

複数のDNSサーバをローカルのUnboundの参照先として指定することで冗長性を高める

という方法を検証してみました。

(なお、今回の記事ではLVS構成の設定及び検証については言及しませんので、その部分については他の解説記事などをご参照下さい)

検証環境

検証用の環境として以下を準備しました。
sv-web01       192.168.0.1       Webサーバ。Unboundを導入
sv-dns-lvs01     192.168.0.11       node01とnode02でLVS。Keepalivedで死活監視
  sv-dns-node01  192.168.0.101     BIND
  sv-dns-node02  192.168.0.102     BIND
sv-dns-lvs02     192.168.0.12       node03とnode04でLVS。Keepalivedで死活監視
  sv-dns-node03  192.168.0.103     BIND
  sv-dns-node04  192.168.0.104     BIND

Unbound



sv-web01にはUnboundをインストールし、/etc/resolv.confには以下のようにnameserverを設定します。
nameserver 127.0.0.1       //ローカルのUnbound
nameserver 192.168.0.11    //sv-dns-lvs01
nameserver 192.168.0.12    //sv-dns-lvs02

Unboundの設定

Unboundとは、
  • シンプルな設計になっており高速で動作する。BINDより処理性能が良い(2~3倍)
  • 設定ファイルは1つのみ(unbound.conf)で内容もシンプルなため、設定が容易
  • キャッシュ汚染に対する耐性を強化した設計&DNSSECをサポート
  • デフォルト設定で高いセキュリティが確保された状態で動く
という特徴を持った、新定番となっているDNSキャッシュサーバです。

デフォルトの設定でもキャッシュサーバとして問題なく動作しますが、今回は社内の権威DNSサーバへ問い合わせを行いたいため、stub-zoneの設定を行います。
stub-zoneは、特定のドメインの名前解決について、指定したDNS権威サーバに問い合わせを行うための設定です。

/etc/unbound/unbound.confで、参照先DNSサーバとしてsv-dns-lvs01とsv-dns-lvs02を指定します。
 stub-zone:
        name:"example.com"
        stub-addr:192.168.0.11
        stub-addr:192.168.0.12
stub-zone:
        name: "0.168.192.in-addr.arpa"
        stub-addr:192.168.0.11
        stub-addr:192.168.0.12
Unboundはデフォルトではプライベートアドレスの問い合わせを行わないので、以下の設定を追加します。
private-domain: "example.com"
(中略)
local-zone: "0.168.192.in-addr.arpa" transparent

また、特定のドメインについて、指定したDNSキャッシュサーバに再帰問い合わせを行わせるときにはforward-zoneを設定します。
forward-zoneは、nameオプションに "." を指定することで、全ての問い合わせを転送することもできます。
自社ドメイン以外は別のDNSサーバ(外部DNSなど)を指定して直接問い合わせを行わせるような場合は、こちらで設定します。
forward-zone:
  name: "."
  forward-addr: 203.0.113.111

検証したいこと 

1. stub-zoneに複数DNSサーバを記述した場合、どのような問い合わせ順序になるか。先に書かれているものが優先なのか、ラウンドロビンなのか。

2. stub-zoneに書いたDNSサーバのうち1つが利用不可になった場合に、どのような挙動になるか。

3. 利用不可になった理由が、サーバ自体がダウンした場合と、DNSサービスが利用不可になった場合では、挙動に違いはあるか。resolv.confでは、サーバ自体のダウンではなくDNSサービスが落ちていた場合にタイムアウトまでに長くかかることがあるが、Unboundではどうか。

検証手順

0.事前準備
テスト用のスクリプトを作成します。sv-web01から他のサーバにnslookupを行い、最後にunboundのキャッシュを削除するというだけの単純なものです。
SERVER_LIST="sv-web02 sv-web03 sv-db01 ・・・・・ sv-db20"
while : ; do

    for SERVER in $SERVER_LIST; do
        echo $(date "+%F %H:%M:%S.%N") $(nslookup $SERVER | head -n 1)
    done

    unbound-control -q flush_zone example.com
    sleep 1

done | tee test.log
このスクリプトを実行しながらサーバやサービスを落として、どのサーバで名前解決が行われているかを確認します。
DNSサーバに何の問題も起こっていない時点では以下のようなログになります。
127.0.0.1、つまりローカルのUnboundで名前解決が行われているのがわかります。
test.log

2016-03-23 10:01:47.710318602 Server: 127.0.0.1
2016-03-23 10:01:47.720166753 Server: 127.0.0.1
2016-03-23 10:01:47.730168114 Server: 127.0.0.1
2016-03-23 10:01:47.739930041 Server: 127.0.0.1
2016-03-23 10:01:47.750394444 Server: 127.0.0.1
2016-03-23 10:01:47.760969879 Server: 127.0.0.1
2016-03-23 10:01:47.770984202 Server: 127.0.0.1
2016-03-23 10:01:47.780918869 Server: 127.0.0.1
2016-03-23 10:01:47.791561248 Server: 127.0.0.1
2016-03-23 10:01:47.802000414 Server: 127.0.0.1
2016-03-23 10:01:47.812778410 Server: 127.0.0.1
2016-03-23 10:01:47.823340386 Server: 127.0.0.1
2016-03-23 10:01:47.833941263 Server: 127.0.0.1
2016-03-23 10:01:47.844795349 Server: 127.0.0.1



検証1. 
問い合わせ順序の確認

各LVSサーバでDNSサービスへの接続状態を確認しながら検証用スクリプトを実行してみます。
[root@i-dns-lvs01 ~]# watch ipvsadm -Ln

IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
UDP 192.168.0.11:53 rr
-> 192.168.0.101    Route     0 0 271 
-> 192.168.0.102     Route    0 0 272
[root@i-dns-lvs02 ~]# watch ipvsadm -Ln

IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
UDP 192.168.0.12:53 rr
-> 192.168.0.103    Route     0 0 269 
-> 192.168.0.104     Route    0 0 271 

InActConn(一定時間以内の接続数)がほぼおなじ数字で推移しています。
結論:stub-zoneに複数のDNSサーバを記入した場合、順番に均等に問い合わせが割り振られる 。


検証2.ローカルのUnboundのstub-addrに登録してあるsv-dns-lvs0xのどちらかが落ちた場合


上記スクリプトを実行した状態で、片方のLVS(sv-dns-lvs01)を落としてみます。
[root@sv-dns-lvs01 ~]# service network stop
2016-03-23 11:02:39.654407380 Server: 127.0.0.1
2016-03-23 11:02:39.666387084 Server: 127.0.0.1
2016-03-23 11:02:39.678305469 Server: 127.0.0.1
2016-03-23 11:02:39.690497052 Server: 127.0.0.1
2016-03-23 11:02:39.702769957 Server: 127.0.0.1
2016-03-23 11:02:39.714040967 Server: 127.0.0.1
2016-03-23 11:02:39.725401558 Server: 127.0.0.1
2016-03-23 11:02:39.736123310 Server: 127.0.0.1
2016-03-23 11:02:39.746930229 Server: 127.0.0.1
2016-03-23 11:02:39.758402234 Server: 127.0.0.1
2016-03-23 11:02:39.769120682 Server: 127.0.0.1
2016-03-23 11:02:39.781072673 Server: 127.0.0.1
2016-03-23 11:02:41.296289719 Server: 127.0.0.1
2016-03-23 11:02:41.308759832 Server: 127.0.0.1
2016-03-23 11:02:41.422097623 Server: 127.0.0.1
2016-03-23 11:02:41.434119357 Server: 127.0.0.1
2016-03-23 11:02:42.849200158 Server: 127.0.0.1
2016-03-23 11:02:42.861381999 Server: 127.0.0.1
2016-03-23 11:02:42.873155039 Server: 127.0.0.1
2016-03-23 11:02:42.884901850 Server: 127.0.0.1
2016-03-23 11:02:42.896203445 Server: 127.0.0.1
2016-03-23 11:02:42.906861984 Server: 127.0.0.1
2016-03-23 11:02:42.917331042 Server: 127.0.0.1
2016-03-23 11:02:42.927999125 Server: 127.0.0.1
2016-03-23 11:02:42.938445488 Server: 127.0.0.1
2016-03-23 11:02:42.948876159 Server: 127.0.0.1
2016-03-23 11:02:42.959507049 Server: 127.0.0.1
2016-03-23 11:02:42.970042488 Server: 127.0.0.1

LVSサーバを落としたタイミングで若干処理スピードの低減が発生しましたが、ほぼタイムラグなくsv-dns-lvs01を切り離して引き続きUnboundで名前解決を行ってくれるようです。

結論:stub-addrとして指定した複数のDNSのうち一つが落ちた場合でも、Unbound内で切り離しをして名前解決が続行される。



検証3. sv-dns-lvs0x自体が落ちている場合と、sv-dns-lvs0xにぶらさがっている2つのnodeの両方のDNSサービスが利用不可の場合とで挙動は変わるか


LVS用のサーバが落ちた場合、Unboundがうまく切り離してくれることがわかりました。
では、LVSサーバではなく、node側のDNSサービスが両方落ちた場合はどうでしょうか。

sv-dns-lvs01で利用している、sv-dns-node01とsv-dns-node02の両方で、namedサービスを停止してみます。
[root@sv-dns-node01 ~]# service named stop 
[root@sv-dns-lvs01 ~]# ipvsadm -Ln 

IP Virtual Server version 1.2.1 (size=4096)
Prot LocalAddress:Port Scheduler Flags
-> RemoteAddress:Port Forward Weight ActiveConn InActConn
UDP 192.168.0.11:53 rr
-> 192.168.0.101    Route     0 0 0 
-> 192.168.0.102     Route    0 0 0 
2016-03-23 11:26:07.253176732 Server: 127.0.0.1
2016-03-23 11:26:07.263412675 Server: 127.0.0.1
2016-03-23 11:26:07.375477267 Server: 127.0.0.1
2016-03-23 11:26:07.385581955 Server: 127.0.0.1
2016-03-23 11:26:07.395923909 Server: 127.0.0.1
2016-03-23 11:26:07.507452435 Server: 127.0.0.1
2016-03-23 11:26:09.022468808 Server: 127.0.0.1
2016-03-23 11:26:09.635581100 Server: 127.0.0.1
2016-03-23 11:26:09.646748991 Server: 127.0.0.1
2016-03-23 11:26:10.712805036 Server: 127.0.0.1
2016-03-23 11:26:10.725051359 Server: 127.0.0.1
2016-03-23 11:26:10.734853913 Server: 127.0.0.1
2016-03-23 11:26:10.744873105 Server: 127.0.0.1
2016-03-23 11:26:10.754697333 Server: 127.0.0.1
2016-03-23 11:26:10.764829874 Server: 127.0.0.1
2016-03-23 11:26:10.877325395 Server: 127.0.0.1
2016-03-23 11:26:10.887888348 Server: 127.0.0.1
2016-03-23 11:26:10.898024415 Server: 127.0.0.1
2016-03-23 11:26:10.907979399 Server: 127.0.0.1
検証2と同様、若干の処理速度低下はありますが、その後は引き続きUnboundでの名前解決が継続されました。

結論:LVS自体が落ちている場合とサービスが使用不可の場合で挙動は変わらない

まとめ 

検証により、DNSサーバ障害時のパフォーマンスへの影響をローカルUnboundを導入することによりより減らすことができるだろうという結論が得られました。
ここで一度、Unboundを導入することのメリット・デメリットを整理したいと思います。

ローカルにUnboundを導入するメリット
・サーバ障害時も、キャッシュに保存されている分はTTL内(社内サーバなら1時間)であればローカルで名前解決ができる。
・DNSサーバを冗長化しておいた場合に、1台のみの障害であればresolv.confに列記するだけの場合よりもパフォーマンスへの影響を小さくできる。
・ローカルのネットワーク流量やDNSサーバの負荷を抑制できる。
・ローカルで名前解決ができることによるパフォーマンス向上が期待できる。

ローカルにUnboundを導入するデメリット(懸念事項)
・導入コスト(各サーバへの設定)
・運用コスト(local-dataを使う場合はサーバ追加時のlocal-dataの再配布、ドメイン&セグメント追加時のunbound.conf設定修正)
・キャッシュが新しいトラブルの原因になったり、トラブル時の切り分けがしづらくなる可能性
・サーバ負荷軽減やパフォーマンス向上については、名前解決の問い合わせが少ないサーバや、新しい名前解決が多いサーバの場合には、効果が小さい。

これを踏まえ、弊社では、
・TTL内での名前解決が多く発生し、キャッシュにより問い合わせが大きく減らせる
・DNS障害時のタイムラグがサービスのパフォーマンスに影響を与えることが想定できる
など、Unbound導入によるメリットが大きいサーバから順に導入していくことになりました。
また、導入・運用のコストについては、AnsibleやFabricといった自動化ツールを導入することである程度カバーできると考えています。

参考URL

・5分でわかるUnbound http://gihyo.jp/admin/feature/01/unbound/0001
・Unboundサーバ運用Tips http://gihyo.jp/admin/feature/01/unbound/0004
・キャッシュサーバの設定 http://dnsops.jp/event/20140626/cache-config.pdf

CORECを支える技術 ~ログ監視編~ fluentd-AmazonSNS連携

こんにちは。なべです。
CORECの開発を担当しています。
CORECを支える技術 ~チケット駆動編~』に続き、『CORECを支える技術』シリーズの第2弾としてCORECのログ監視について書きたいと思います。

旧ログ監視の問題と対策

当初、CORECのログ監視はログ集約にくっつける形で始まりました。
ログ集約はログファイルを一定時間ごとにバックアップする仕組みで、各サーバーのログをfluentdで集め、1時間ごとに圧縮しS3に格納しています。
ログ監視は、その集約されたログを社内の監視システムで取得し、エラーログがあった場合にメールとIRCで通知するというものです。

この仕組には大きく以下の2つの問題がありました。

  • タイムラグ
    ログの監視をできるタイミングがS3に圧縮ファイルがアップされた後なので、検知するまで1時間のタイムラグが発生する可能性がある。
  • サービスレベル
    ログ監視を社内のサーバーに配置していて、消防点検や停電または、サーバーメンテナンス時に監視できないなどサービスレベルにも問題がある。

これらの問題に対応するためfluentdに集めたタイミングでエラーログを抽出し、AmazonSNS経由でメール通知することにしました。
これにより、社内のサーバーも経由しなくなり、タイムラグの問題・サービスレベルの問題を同時に解消できました。

CORECログ監視概要図

実施内容

この対応で実施したことは以下の4つです

  1. fluentdにプラグイン追加
  2. AmazonSNSに通知用Topic作成
  3. メールBody整形用のERB追加
  4. fluentdの設定ファイル記述

1. fluentdにプラグイン追加

以下の2つのプラグインを追加しました。

fluent-plugin-sns
Amazon SNS通知用
fluent-plugin-rewrite-tag-filter
エラーのフィルタ・レベルごとの分岐処理用
fluentdはrubyで動いているのでRubyistならお馴染みのgemコマンドでインストールできます。
この時fluentdが使っているrubyの環境を指定する必要があります。
特にfluentdにバンドルされたrubyを使用している場合は注意してください。
sudo /usr/lib/fluent/ruby/bin/gem install fluent-plugin-sns
sudo /usr/lib/fluent/ruby/bin/gem install fluent-plugin-rewrite-tag-filter

2. AmazonSNSに通知用Topic作成

Amazonの管理コンソールからSNSサービスを選択し、画面に従ってTopic及びSubscritionを作成します。 特に迷うことはないかと思いますが、注意するポイントは以下の2点です。

  • メールアドレスを登録するとメールがくるのでクリックして認証すること
  • 作成したTopicの権限設定を確認する
    権限設定とは作成したTopicに対して、通知に利用するAWSアカウントがこのトピックに投稿する権限のことです。もし権限がない場合には、[ポリシーの編集]から許可を与えてください。

3. メールBody整形用のERB追加

CORECの場合、fluentdが受け取るレコードは改行が\nにエスケープされていて読みづらいため、テンプレートで改行コードに変換しました。
以下のコードをerbファイルとして保存しておきます。
これだけのコードですが受け取った側の負担がだいぶ違います。特にスタックトレースで威力を発揮します。

<%record.each do |k,v|%>
<%="#{k}:#{v.to_s.gsub(/\\n/,"\n")}" %>
<%end%>

4. fluentdの設定ファイル記述

それでは最後にメインとなるfluentdの設定ファイルの編集をします。
変更/追加のポイントは以下の3点です。

4-a. copyプラグインで処理を2系統に分岐する
4-b. rewrite_tag_filterプラグインでエラーレベルごとにフィルタリングして、新しいタグを設定する
4-c. snsプラグインで通知するためのmatchディレクティブを追加する

それぞれ簡単に説明します。

4-a. copyプラグインで処理を2系統に分岐する

fluentdは最初にマッチしたmatchディレクティブだけを実行しますので、同じレコードに対して複数の処理をしたい場合にはcopyプラグインを使用します。
※copyプラグインは標準のプラグインなのでインストールをする必要はありません。

matchディレクティブと同等の内容をstoreタグに書くことができ、同じレコードに対して処理を複数記述できるようになります。
今回の対応では従来のS3への送信する処理をcopyで分岐し、SNSに送信する処理を追加します。

<match tag.log>
  type copy
  <store>
        従来の処理
  </store>
  <store>
        追加したい処理
  </store>
</match>

4-b. rewrite_tag_filterプラグインでエラーレベルごとにフィルタリングして、新しいタグを設定する

ただ単に前項の「追加したい処理」にSNS送信のディレクティブの内容を書いてしまうと、アプリケーションが出力したログすべて(エラーでないものも含めて)通知されてしまいます。
そこでログの内容によって処理を振り分けるにはrewrite_tag_filterプラグインを使用します。
レコードのキーを指定して、検索する文字列または正規表現を指定し、それにマッチした場合に新しいタグを指定する仕組みです。
今回はログレベルがFATALもしくはERRORの場合にシステム通知がしたかったので、ログレベルが格納されているキー(lebel)に対して、FATAL・ERRORそれぞれルールを作成しました。
複数のルールを設定するにはrewriteruleの後の数字をインクリメントして記述します。

  <store>
    type rewrite_tag_filter
    rewriterule1 level FATAL corec.rails.sns_fatal
    rewriterule2 level ERROR corec.rails.sns_error
  </store>

4-c. snsプラグインで通知するためのmatchディレクティブを追加する

typeにsnsを指定して、内容にはAWSユーザーにはお馴染みのパラメータ群を設定していきます。 sns_body_templateのパスはtd-agentが参照可能な場所にERBを配置して指定してください。

<match corec.rails.sns_fatal>
  type sns
  sns_topic_name for_system_notice_topic
  aws_key_id xxxxxxxxxx
  aws_sec_key xxxxxxxxxx
  sns_endpoint sns.ap-northeast-1.amazonaws.com
  sns_subject [COREC ALERT]corec/rails
  sns_body_template /etc/td-agent/erb/sns_body_template.erb
</match>

fluentd設定ファイルイメージ(全体)

変更前後の設定ファイルは以下のとおりです。
行はだいぶ増えていますが、それぞれの設定内容に難しいところはありませんでした。

  • 設定ファイル:修正前
<match corec.rails>
    S3に送信する設定(省略)
</match>
  • 設定ファイル:修正後
<match corec.rails>
  type copy
  <store>
        従来のS3に送信する設定(省略)
  </store>
  <store>
    type rewrite_tag_filter
    rewriterule1 level FATAL corec.rails.sns_fatal
    rewriterule2 level ERROR corec.rails.sns_error
  </store>
</match>
<match corec.rails.sns_fatal>
  type sns
  sns_topic_name for_system_notice_topic
  aws_key_id xxxxxxxxxx
  aws_sec_key xxxxxxxxxx
  sns_endpoint sns.ap-northeast-1.amazonaws.com
  sns_subject [COREC ALERT]corec/rails
  sns_body_template /etc/td-agent/erb/sns_body_template.erb
</match>
<match corec.rails.sns_error>
 (省略)
</match>

設定ファイル修正後、fluentdを再起動すれば反映されます。
※fluentdの連携をしている場合には送信元のfluentdも再起動することをおすすめします。
 私が設定した時には送信側が受信側を見失ってログの送信が止まってしまいました。

新たな問題

前項までの対応により、旧ログ監視の問題は解消し、 リアルタイムで、かつサービスレベルの高い仕組みができました。
が、新たな問題がいくつか発生しました。

  1. フィルタリングが無くなったのでERROR・FATALのレベルのログが全部飛んでくる
  2. 異常が発生するとガンガンメールがくる
  3. IRCに通知されない

新たな問題 1. ERROR・FATALのレベルのログが全部飛んでくる
→ 対策: 随時チケット化してエラーログの根本原因を潰す!

実はログを検索してメールを飛ばす処理の中でホワイトリストでフィルタリングして、通知するものを絞っていました。
その仕組みが無くなったのでERROR・FATALのレベルのログが全部飛んでくるようになってしまいました。 fluentdでフィルタリングするという選択肢もありましたが、対応の必要のないFATALやERRORを出すシステム側を修正すべきということで、チケット化してエラーの根本対応を実施。

新たな問題 2. 異常が発生するとガンガンメールがくる
→ 対策: 覚悟しておく!

従来のログ監視は1時間に1回ログを検索してメールを飛ばす処理だったため過去1時間に何件エラーが発生していても1通の通知にまとまっていました。
それがリアルタイムでエラー1件毎に通知されるため、異常事態にはメールが大量に送信されてしまいます。
実際に外部ベンダー側にトラブルがあり、復旧までに4時間かかった際に断続的に300通送信されてきました。orz
しかし、異常が発生しているのだから通知はあるべきでそれを止めるのは本末転倒ということで受け入れることにしました。

新たな問題 3. IRCに通知されない
→ 対策:社内で導入を進めている新監視システムへ

メールと同時にIRCに通知して、業務時間中はメールよりも気づきやすいように対策していましたが、IRCは社内サーバーで稼働しているため利用できませんでした。
現状は通知のために旧監視システムと並行稼動をしていますが、実際にはリアルタイムに飛んでくるメールに十分に気づけています。
今後は社内で進めているSlackのサービスを利用した障害対応フローに移行する予定です。
AmazonSNSに通知先を増やすだけで対応できるはずです。

まとめ

  • fluentdにプラグインを追加することで簡単にAmazonSNS経由の通知を実現できました。
    こういったプラグインが充実しているのもfluentdの魅力だと思います。(fluentdの導入については『fluentd(td-agent) の導入』を参照してください。)

  • ログ監視も即時性・対障害性の高いシステムを構築して確実で迅速な検知が必要です!
    ログ監視は最後の砦であり将来発生する障害の芽を発見するアンテナだと思っています。これからもCORECとともにCORECを支える運用システムもブラッシュアップしていきます。

  • 無駄なログは技術負債。根本から除去しましょう!
    無駄なログがたくさん通知されてくると、本来拾わなければいけないログを見落としてしまう可能性があります。そのために通知するログを絞ることは大切ですが、安易にフィルタリングをするのではなく、一つ一つ原因を突き止めて対応すべきところはプログラムで対応し、技術負債を残さないようにしたいですね。

iptablesを利用してNATサーバを構築

こんにちは、えのもとです。

弊社では本番リリース直前検証環境として、ステージング環境を利用しています。
この環境が古くなってしまったため、環境再構築を実施することになりました。

再構築する上で、今後のこともあるので再構築しやすい環境に切り替えることにしました。
構築上でポイントとなったのは以下の2つです。
  • 本番環境はVMで稼働しているので、そのバックアップを活用する
  • サーバ設定(ネットワーク設定など)はできる限り変更したくない
これらを達成するため、閉鎖されたネットワークを構築しその中に環境を構築することにしました。そこで問題となるのは閉鎖された環境内外との通信なのですが、iptablesを利用してnatサーバを構築することで解決しました。今回はこのiptablesの検証の様子を紹介します。

NATとiptablesについて

今回環境を構築するに当たり、以下を参考にしました。

@IT:第10回 IPパケットの構造とIPフラグメンテーション
@IT:natテーブルを利用したLinuxルータの作成

要点だけ羅列すると以下のような内容になります。
  • パケット内IPヘッダに送信元アドレスと宛先アドレスが記載されている。
  • 送信元アドレスを変換するNATのことをSNAT
    宛先アドレスを書き換えるNATのことをDNATと呼ぶ。
  • iptablesのSNATはPOSTROUTINGチェインで、DNATはPREROUTINGチェインで行う。


検証内容と環境の紹介


存在しないIPアドレス宛てのパケットをiptablesでnatし、別のIPアドレスで受けとることができるか検証しました。検証には以下のような環境を利用しました。

セグメント
  1. A(192.168.100.0/24)
  2. B(192.168.200.0/24)
仮想マシン
  1. vm01           eth0:【 192.168.100.1 】
  2. vm02           eth0:【 192.168.100.2 】 eth1:【 192.168.200.2 】
  3. vm03           eth0:【 192.168.200.3 】
  4. gateway_A   eth0:【 192.168.100.254 】
  5. gateway_B   eth0:【 192.168.200.254 】

eno_2015120901

vm01から存在しないIP【 192.168.100.3 】 宛にパケットを送り、
vm02でNATさせてvm03のIP【 192.168.200.3 】へ届けます。
vm01からするとIP【 192.168.100.3 】 が存在するように見えます。(赤線)
実際はvm02を経由してセグメントBにいるvm03へ届きます。(青線)

eno_2015120902


事前確認

iptablesに余計な設定があると誤作動の原因になるので、一旦どのサーバもクリアしておきます。

# iptables クリア
iptables -F
iptables -F -t nat
# iptables 確認
iptables -L
iptables -L -t nat
# iptables 保存
service iptables save

また、vm02はパケットを転送する必要があるので以下の設定を加えます。
vi /etc/sysctl.conf
#net.ipv4.ip_forward=0
net.ipv4.ip_forward=1

sysctl -p



ステップ 1 : vm01にルーティング追加

手始めにvm01から【 192.168.100.3 】宛のpingを実行し、その様子をvm01とvm02の両方でtcpdumpを使いパケットをキャプチャして確認します。

# vm01
[root@vm01 ~]# ping 192.168.100.3
PING 192.168.100.3 (192.168.100.3) 56(84) bytes of data.
From 192.168.100.1 icmp_seq=2 Destination Host Unreachable
From 192.168.100.1 icmp_seq=3 Destination Host Unreachable
From 192.168.100.1 icmp_seq=4 Destination Host Unreachable

# vm02
[root@vm02 ~]# tcpdump -i any src host 192.168.100.1 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
13:28:24.003479 ARP, Request who-has 192.168.100.3 tell 192.168.100.1, length 46
13:28:25.003469 ARP, Request who-has 192.168.100.3 tell 192.168.100.1, length 46
13:28:26.003479 ARP, Request who-has 192.168.100.3 tell 192.168.100.1, length 46
13:28:28.004484 ARP, Request who-has 192.168.100.3 tell 192.168.100.1, length 46

vm01から【 192.168.100.3 】へパケットを送る場合、同一セグメント内なのでゲートウェイなどは経由せず直接通信することになります。直接通信するためには相手のMACアドレスを知る必要があります。ARPリクエストをブロードキャストへ送信しMACアドレスを探している様子が確認できました。

これを無理やりvm02へ送るようにvm01にスタティックルーティングを追加します。

# vm01
[root@vm01 ~]# ip route add 192.168.100.3 via 192.168.100.2 dev eth0
[root@vm01 ~]# ip route show
192.168.100.3 via 192.168.100.2 dev eth0
192.168.100.0/24 dev eth0  proto kernel  scope link  src 192.168.100.1
169.254.0.0/16 dev eth0  scope link  metric 1002
default via 192.168.100.254 dev eth0

再度vm01から【 192.168.100.3 】へpingを実行し確認します。

# vm01
[root@vm01 ~]# ping 192.168.100.3
PING 192.168.100.3 (192.168.100.3) 56(84) bytes of data.
From 192.168.100.2: icmp_seq=2 Redirect Host(New nexthop: 192.168.100.3)
From 192.168.100.2: icmp_seq=3 Redirect Host(New nexthop: 192.168.100.3)
From 192.168.100.2: icmp_seq=4 Redirect Host(New nexthop: 192.168.100.3)
From 192.168.100.2 icmp_seq=2 Destination Host Unreachable
From 192.168.100.2 icmp_seq=3 Destination Host Unreachable
From 192.168.100.2 icmp_seq=4 Destination Host Unreachable

# vm02
[root@vm02 ~]# tcpdump -i any src host 192.168.100.1 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
13:48:19.136230 IP 192.168.100.1 > 192.168.100.3: ICMP echo request, id 28934, seq 1, length 64
13:48:20.135528 IP 192.168.100.1 > 192.168.100.3: ICMP echo request, id 28934, seq 2, length 64
13:48:21.135501 IP 192.168.100.1 > 192.168.100.3: ICMP echo request, id 28934, seq 3, length 64
13:48:22.135497 IP 192.168.100.1 > 192.168.100.3: ICMP echo request, id 28934, seq 4, length 64

【 192.168.100.3 】宛のパケットがvm02へ届くようになりました。



ステップ2 : vm02にDNAT設定を追加

次に存在しない宛先IPアドレス【 192.168.100.3 】をvm03【 192.168.200.3 】変換するため、vm02のiptablesにDNATの設定を追加します。

# vm02
[root@vm02 ~]# iptables -t nat -A PREROUTING -d 192.168.100.3 -i eth0 -j DNAT --to-destination 192.168.200.3
[root@vm02 ~]# iptables -L -n -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DNAT       all  --  0.0.0.0/0            192.168.100.3       to:192.168.200.3

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination


vm01から【 192.168.100.3 】へpingを実行し、vm02とvm03で確認します。

# vm01
[root@vm01 ~]# ping 192.168.100.3
PING 192.168.100.3 (192.168.100.3) 56(84) bytes of data.

# vm02
[root@vm02 ~]# tcpdump -i any src host 192.168.100.1 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
13:55:28.318556 IP 192.168.100.1 > 192.168.100.3: ICMP echo request, id 30982, seq 1, length 64
13:55:28.318586 IP 192.168.100.1 > 192.168.200.3: ICMP echo request, id 30982, seq 1, length 64
13:55:29.318498 IP 192.168.100.1 > 192.168.100.3: ICMP echo request, id 30982, seq 2, length 64
13:55:29.318513 IP 192.168.100.1 > 192.168.200.3: ICMP echo request, id 30982, seq 2, length 64
13:55:30.318483 IP 192.168.100.1 > 192.168.100.3: ICMP echo request, id 30982, seq 3, length 64
13:55:30.318496 IP 192.168.100.1 > 192.168.200.3: ICMP echo request, id 30982, seq 3, length 64
13:55:31.318515 IP 192.168.100.1 > 192.168.100.3: ICMP echo request, id 30982, seq 4, length 64
13:55:31.318529 IP 192.168.100.1 > 192.168.200.3: ICMP echo request, id 30982, seq 4, length 64

# vm03
[root@vm03 ~]# tcpdump -i any src host 192.168.100.1 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
13:55:28.381794 IP 192.168.100.1 > 192.168.200.3: ICMP echo request, id 30982, seq 1, length 64
13:55:29.381711 IP 192.168.100.1 > 192.168.200.3: ICMP echo request, id 30982, seq 2, length 64
13:55:30.381702 IP 192.168.100.1 > 192.168.200.3: ICMP echo request, id 30982, seq 3, length 64
13:55:31.381730 IP 192.168.100.1 > 192.168.200.3: ICMP echo request, id 30982, seq 4, length 64

vm03にvm01のPINGが届いていることが確認できました。



ステップ3 : vm02にSNAT(NAPT)設定を追加

vm01から送るpingは無事vm03へ届けることができたのですが、vm03がセグメントAの情報を持っていないため、送信元であるvm01に返信することができません。そのため、vm02へSNAT(NAPT)を追加します。

# vm02
[root@vm02 ~]# iptables -t nat -A POSTROUTING -o eth1 -s 192.168.100.0/24  -j MASQUERADE
[root@vm02 ~]# iptables -L -n -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
DNAT       all  --  0.0.0.0/0            192.168.100.3       to:192.168.200.3

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  192.168.100.0/24     0.0.0.0/0

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

確認します。

# vm01
[root@vm01 ~]# ping 192.168.100.3
PING 192.168.100.3 (192.168.100.3) 56(84) bytes of data.
64 bytes from 192.168.100.3: icmp_seq=1 ttl=63 time=0.235 ms
64 bytes from 192.168.100.3: icmp_seq=2 ttl=63 time=0.164 ms
64 bytes from 192.168.100.3: icmp_seq=3 ttl=63 time=0.164 ms

# vm02
[root@vm02 ~]# tcpdump -i eth0 src host 192.168.100.1 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes
14:04:40.915680 IP 192.168.100.1 > 192.168.100.3: ICMP echo request, id 35078, seq 1, length 64
14:04:41.915507 IP 192.168.100.1 > 192.168.100.3: ICMP echo request, id 35078, seq 2, length 64
14:04:42.915500 IP 192.168.100.1 > 192.168.100.3: ICMP echo request, id 35078, seq 3, length 64
14:04:43.915525 IP 192.168.100.1 > 192.168.100.3: ICMP echo request, id 35078, seq 4, length 64

# vm02
[root@vm02 ~]# tcpdump -i eth1 src host 192.168.200.2
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 65535 bytes
14:04:40.915714 IP 192.168.200.2 > 192.168.200.3: ICMP echo request, id 35078, seq 1, length 64
14:04:41.915522 IP 192.168.200.2 > 192.168.200.3: ICMP echo request, id 35078, seq 2, length 64
14:04:42.915513 IP 192.168.200.2 > 192.168.200.3: ICMP echo request, id 35078, seq 3, length 64
14:04:43.915546 IP 192.168.200.2 > 192.168.200.3: ICMP echo request, id 35078, seq 4, length 64

# vm03
[root@vm03 ~]# tcpdump -i any src host 192.168.200.2 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on any, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
14:04:40.978924 IP 192.168.200.2 > 192.168.200.3: ICMP echo request, id 35078, seq 1, length 64
14:04:41.978721 IP 192.168.200.2 > 192.168.200.3: ICMP echo request, id 35078, seq 2, length 64
14:04:42.978718 IP 192.168.200.2 > 192.168.200.3: ICMP echo request, id 35078, seq 3, length 64
14:04:43.978754 IP 192.168.200.2 > 192.168.200.3: ICMP echo request, id 35078, seq 4, length 64

無事にpingが返ってくることが確認できました。



まとめ

作成した環境を利用して、どんなサービスが利用できるのかも検証しました。

動作OK : ssh http https dns mysql
動作NG : ftp oracle

ipヘッダ以外でipのやり取りをするものについては正常に動作しないのですが、動作したものについては、特に問題もなく使えることが分かりました。

以上です。何かの役に立てばと思います。

CORECを支える技術 ~チケット駆動編~

こんにちは。なべです。
CORECの開発を担当しています。
これから何回かに分けて、『CORECを支える技術』と題してCORECの開発について書いてみようかと思います。
今回はチケット管理と構成管理との連携についてCORECでの取り組みをご紹介したいと思います。
 
 
corec

毎週リリースのサイクルを維持するためのポイントは自動化

CORECは2014年3月17日に初回リリースをしてから、80回を超えるリリースを行っています。(2015年5月時点)
その内容は、機能追加からデザイン変更やバグフィックス、文言変更まで大小さまざまですが、ほぼ週1回のペースを守っています。それは、より早くフィードバックサイクルを回し、お客様に喜んでいただける機能の追加や改修をより早く届けたいと考えているからです。

このペースを維持するために、いくつかのツールを利用したりそれらを連携する仕組みを構築しています。
できるだけ自動化することによって生産性の向上ヒューマンエラーの極小化を目指します。
 

その一端を担うのがチケット管理と構成管理との連携です。
この仕組みがCORECの開発を飛躍的に安心・安全にしてくれます。

なぜ、チケット駆動開発と構成管理?

なぜ、チケット管理と構成管理が連携すると安心・安全になるのでしょうか?

「やった(ような気がする)」のヒューマンエラー

チケット駆動開発は、チケットが正しく完了しそれがリリースされる必要があります。
開発者にチケットを渡し、そのチケットの完了を各担当者に任せると、やはり人間ですからミスが発生することがあります。 たとえば、実装したつもりが実装していなかった、実装したがコミットせずにチケットを完了してしまった、といったことがあげられます。

チケットの対応確認は手間

ですので、管理する側はチケットの内容がリリースされるかどうかを確認する必要があります。
CORECでは構成管理からリリース対象を抽出してリリースするフローになっているので、 管理する側から見てリリースされるかどうかを確認する一番確実な方法は構成管理を確認することです。 しかし、手作業でチケットの一覧と構成管理のログを突き合わせて確認するのは、根気と注意力のいる作業です。 少なくとも私には無理です(^^;

だから、自動化!

そこで、構成管理から自動的に連携します。
構成管理にコミットされたことをチケットに反映することによって、チケット管理システムで対応状況を正確に把握できるようになります。 副次的な効果として、開発者側も対応してコミットしたものが自動的に”対応済み”に変わっていくとちょっとした達成感が得られるという心理的効果もあり、 、それが、コミットコメントにチケット番号を含める動機にもなるので、ログで対応内容が把握しやすくなりました。


使用しているツール

まずはどのようなツールを使用しているかを説明します。

  • Backlog(チケット管理)
  • git
  • jenkins

Backlog

CORECではすべてのタスクをチケット化します。
そのチケットの管理にはBacklogというWebサービスを利用しています。

このチケットに割り振られたチケット番号がすべてのキーになります。

git

構成管理はgitを利用しています。
社内で管理しているサーバー上にあります。
CORECでは単純にgitを使うのではなく、git-flow()というブランチモデルを利用しています。

git-flowブランチモデル

このgit-flowはCORECのスピードを保つ一つの大きな役割を果たしています。
本番(master)・開発(develop)のブランチをキレイに保ちつつ、本番で発生した問題に対応するブランチ(hotfix)、 日々の機能開発をするブランチ(feature)が適正に管理できる素晴らしい仕組みです。
この仕組とgitの的確なマージのおかげで開発者は同時に走っている他の開発のことをほとんど意識することなく自分のペースで開発を進めていくことができます。

※参考:『いまさら聞けない、成功するブランチモデルとgit-flowの基礎知識』(http://www.atmarkit.co.jp/ait/articles/1311/18/news017.html)

gitのルール

git-flowを利用することでgitの使い方はおのずと決まってきますので、gitを使う上で決めているルールは以下の5点ほどです。

  • 開発作業はfeature/hotfixブランチで行うこと
  • feature/hotfixのブランチ名にはチケット番号を使用すること
  • コミットコメントにはチケット番号を含めること
  • finishは第三者が行うこと
  • developにマージするコードはテストが通るものであること

jenkins

皆さんご存知のCIツールです。 gitとBacklogの連携部分を担います。


連携の設定

corec-2015-06-006

featureがfinishされ、gitサーバーのdevelopにpushされると、git-hookからjenkinsのjobをキックしてビルドが開始します。
ビルドでは自動テストやメトリクスの取得など実施し、結果をIRCに通知します。
ビルドが成功した場合には、開発評価環境に自動的にデプロイします。
逆に失敗した場合にはBacklogに課題チケットが作成されるので他の開発者に冷ややかな目で見られることになります。

それでは実際の連携の方法を解説していきたいと思います。
すべて同じツールを利用していなくても、部分的にも利用できるところはあるかと思いますので、参考にしていただければと思います。

構成管理(git/git-hook)とジョブ管理(jenkins)

まずは構成管理が更新されたことをジョブ管理に通知します。

git(git-hook)側の設定

gitにはgit-hookというイベントトリガの仕組みが用意されています。
いろいろありますが、詳細はこちらを参照してください。
今回はpush後に呼ばれるpost-updateというトリガを利用します。
トリガを利用するには、gitリポジトリのルートパス以下のgithookフォルダにトリガの名称のファイルを置きます。
同じフォルダに.sampleファイルがあるのでリネームしてファイルを作成します。

[gitリポジトリのルートパス]/githook/post-update

例えば以下のようになります。この例ではブランチ名を取得してdevelopだったらjenkinsの”corec”jobをキックしています。

#!/bin/bash
BRANCH=$(git rev-parse --symbolic --abbrev-ref $1)
if [ "${BRANCH}" = "develop" ]; then
  curl http://[jenkins-host]/job/corec/build
fi

jenkinsのjobの実行にアクセス制限をしていない環境では、こんな簡単なcurlコマンド1行でjobを実行できます。

jenkins側の設定と認証付きの連携の設定

jenkinsのjobの実行にアクセス制限を設定する場合は以下の2つの方法があります。

  1. jenkinsそのものにユーザー認証をつける
  2. jobの実行にパスワードをかける

jenkinsそのものにユーザー認証をつけるには、jenkinsの Jenkinsの管理>グローバルセキュリティの設定から「セキュリティを有効化」して認証方法を選択・設定する必要があります。 その方法については、ここでは省略します。

以下、上記2つのアクセス制限を設定した場合のgit-hookとjenkinsの連携について説明します。

ユーザー認証情報(APIトークン)の取得方法

jenkinsそのものにユーザー認証をつけた場合、APIトークンが必要になります。
具体的には、APIトークンをパスワードとしてベーシック認証を行います。

  1. 実際にgitサーバーからアクセスするユーザでjenkinsにログインします。
  2. ヘッダーの右側にあるユーザ名のリンクをクリックすると、開発者というメニューが表示されます。
  3. 設定メニューをクリックします。
     
    corec-2015-06-002
     
  4. 右のペインに「APIトークン」のカテゴリが表示されます。
  5. APIトークンの表示をクリックすると、APIトークンが表示されるのでそれを控えておきます。
     
    corec-2015-06-003  
     
job実行の認証情報(認証トークン)の設定方法

jobの実行にパスワードをかける場合、認証トークンが必要になります。 実行パラメータに認証トークンを渡します。

  1. jobの設定画面を開きます。
  2. ビルド・トリガのリモートからビルドのチェックボックスをチェックし、表示された認証トークンのボックスに任意の文字列を設定します。
    ここに入力したものがそのままパスワードになります。
    ※ 認証トークンをjobに設定した時点で先ほどサンプルに書いたcurlコマンドではアクセスできなくなりますので、稼働中の仕組みを触る場合はご注意ください。
     
    corec-2015-06-001

認証付きでjenkinsのjobをリモートから実行する方法

最後に取得した情報を元に[repos]/githook/post-updateを編集します。
curlでベーシック認証&POSTするように以下のように書き換えます。

#!/bin/bash
BRANCH=$(git rev-parse --symbolic --abbrev-ref $1)
if [ "${BRANCH}" = "develop" ]; then
  # 認証トークンをパラメータとして送るのでPOSTにして、できればhttpsにしておいたほうが良い  
  curl -u corec_jenkins:[APIトークン] -X POST \
  http://[jenkins-host]/job/corec/build?delay=0sec&token=[認証トークン]
fi

ジョブ管理(jenkins)-チケット管理(Backlog)

次にジョブ管理から、構成管理の更新をBacklogに通知します。
仕組みとしては、ジョブ管理の中でシェル(プログラム)を起動し、Backlogの提供しているAPIを叩きます。
以下の2つのステップで実現しています。

  1. 更新する対象のチケットの取得
  2. Backlogへ通知

それではそれぞれ説明します

1.更新する対象のチケットの取得

更新する対象のチケット番号はjenkinsの変更履歴を解析して取得します。
gitのlogから取得しても良かったのですが、jenkinsは場合によっては複数のリビジョンをまとめて対象にする場合があるで、jenkinsのjobで管理されている変更履歴から取得する方法を採りました。
jenkinsの変更履歴の取得にはjenkinsのリモートAPIを利用します。
 
http://[jenkins-host]/job/corec/[build-no]/api/json
 
このURLのレスポンスでビルドの情報がJSONで取得できます。
取得したjsonのchangeSet以下が変更履歴のリストになるのでその中からチケット番号を拾い出しています。
 

2.Backlogへ通知

Backlogへの通知はコメント登録をすることによって実現しています。
Backlogへの接続にはスペースIDAPIキーが必要になりますが、取得方法は以下のとおりです。

  • スペースID
    Backlogのサブドメインの部分です。
    https://[スペースID].backlog.jp
     
  • APIキー
    Backlogの個人設定のAPIタブを選択して登録ボタンをクリックすると生成されます。
     
    corec-2015-06-004

BacklogのAPI

BacklogのAPIライブラリはこちらに各種言語のものが紹介されています。
CORECではBacklog4Jを利用しています。
Javaを選んだ理由は当時私が扱いやすいものを選びました(^^;

Backlog4Jでの接続とコメント登録は非常に簡単で数行で実装可能です。
その他、いろいろな操作ができますので、詳細はgithub - backlog4jを参照してください。

// Backlogへ接続
BacklogConfigure configure = new BacklogJpConfigure("[スペースID]").apiKey("[APIキー]");
BacklogClient backlogClient = new BacklogClientFactory(configure).newClient();

// ステータスを変更し、コメントを登録
UpdateIssueParams params = new UpdateIssueParams(issueKey);
params.status(Issue.StatusType.Resolved);  //ステータスを処理済みにする
params.assigneeId([担当者のID]); //担当者を変更する
params.comment(comment); //コメントを付加する
backlogClient.updateIssue(params);

ちなみにコメントは以下のように登録しています。
Backlogに登録するコメントにビルドURLを含めておくことで同時になにがコミットされたのか参照しやすくなるのでお勧めです。

変更がdevelopにコミットされました.

commiter:corec taro
commitId:xxxxxxxxxx9c6bc1adf5d3319f8cb49598
comment :COREC-999 jenkins自動登録機能

refer :http://[jenkins-host]/job/corec/[build-no]/changes

jenkins Backlogプラグイン(おまけ)

jenkinsにはBacklogプラグインがあります。

いくつか便利だと思った機能をご紹介します。お試しください!

  • jenkinsへのログインをBacklogユーザーで認証する。
  • 変更履歴にチケット番号があると自動的にBacklogへのリンクにしてくれる。
    先ほどのコメントのサンプルにあるようにBacklogに登録するコメントにビルドURLを含めておくと、Backlogとjenkinsの変更履歴が相互リンクできるようになります。
  • 失敗ビルドの場合Backlogにチケットを登録してくれる。
  • jobのメニューにBacklogへのリンクが表示される。
    クリックするとBacklogのスペースに飛んでくれます。  
    corec-2015-06-005

まとめ

CORECを支える仕組みとして、今回はチケット管理(Backlog)と構成管理(git)をjenkinsでつなぐ仕組みと その設定方法をご紹介しました。
それぞれの設定やコードは簡単なものだということがわかっていただけたかと思います。
しかし、これにより得られる生産性や安心感は絶大です。
もし、まだこのような連携をしていなければ、ぜひ試していただいて、得られる生産性や安心感を実感していただきたいと思います。
少しの手間を惜しんで多くの時間を無駄にしないように、自分の仕事の環境にこそITを導入しましょう!

次回の『CORECを支える技術』もお楽しみに!

記事検索