Masteries

技術的なことや仕事に関することを書いていきます.

他のチームに「技術的支援」をする時に気をつけていること

自分が働いているGaiaxのように, 社内に複数の事業があり, それぞれにエンジニアが所属して働いている場合, 「ねえ, ○○のチームの××って仕組み, どうやってるの? うちのチームでもやってみたい!」といったコミュニケーションから, 他のチームに対して「技術的支援」をする機会が生まれる事が多々あります.

最近の例だと, 社内の新規事業の立ち上げや, オンプレからクラウドへの移管のタイミングで, Infrastructure as Codeやデプロイ施策, ChatOpsなど整えたいので, 相談に乗って欲しい! という声を何度か頂いた事がありますし, よくよく考えると今やっているPhotosynthへの留学も, 見方を変えれば「Photosynthへの技術支援」と言えるかもしれません.

そういった「技術的支援」をする時に気をつけている事についてFacebookにつぶやいた所, 思ったより反響があった(ような気がした!?)ので, 備忘録として, そして自戒としてブログにも綴っておこうと思います.

「自分のこだわりや考えを, 一方的に押し付けない」

何かしらの「技術的支援」をするということは, そこに「支援する人」と「支援される人(チーム)」という関係が生まれます(なお, 以後"支援する人"を"支援者", "支援される人(チーム)"を"支援先"と呼ぶことにします). そして, 支援をする「何らかの技術領域」において, 支援者は支援先よりも深く取り組んでいて, 一日の長があるはずです(だからこそ, その知見を活かすべく支援先は支援者に技術的支援をお願いするからです).

そういう時に, 気をつけないとやってしまいがちなのは, 支援者が過去の経験から導いた解決策(支援先に存在する課題を解決するための手段)を, 一方的に支援先に押し付ける, というやり方です.

このような技術的支援がうまく成果に繋がるパターンも多々あると思います. しかし, 場合によっては支援先の課題を解決するはずの技術的支援が, 支援先に新しい課題を生み出しているパターンがあると思います.

1つは, 支援者が提案した解決策が, 支援先が使っている言語, フレームワーク, ミドルウェア, インフラ, ツールなどの文化や慣習に則っていないパターンです. この場合, 支援先が支援者の解決策をそのまま鵜呑みにして実施していったところ, 支援先で既に利用している何かしらの技術的要素の文化や習慣に則っていないが故に, 新しい別の問題が生じてしまう, という結論に行き着きがちです.

もう1つは, 理想と現実の壁が出来上がるパターンです. 支援者が一方的に解決策を押し付ける場合, その解決策は支援先の現在の状況(支援先が利用している技術的要素に加え, 開発しているプロダクトの特徴であったり, そのチームの文化, 状況, 習慣であったり...)が考慮されていないパターンが多いはずです. そうなってしまうと場合, 支援先は支援者が提示する解決策(理想)と, 今の支援先の現状(現実)のギャップが大きすぎて, 解決策を実現する為に大きなコストを捻出しなければならなくなるはずです.

...また, 日本人は「変化を嫌う」とよく言われます. 「変化を嫌う」事に対する是非はともかくとして, このような大きなギャップを乗り越えに行こうとすると, チームの中でも賛否が別れる可能性は容易に想像出来るのではないでしょうか.

ここで支援者が解決策の実現を強行すると(例えば, 支援者が実際に手を動かして実装を始める, など), 言うまでもなく支援先の理解や納得のないまま作業が進んでいきます. 大抵, このパターンは中途半端な結末に終わる事が多いです.

例えば, 解決策の実現が中途半端に終わってしまうパターンもあるでしょうし, 無事完成まで至ったとしても, それが支援先に引き継がれない(使われない, 有効に利用されない)という事もあるでしょう.

「支援者」が気をつけるべきこと

ここまで, 技術的支援をするときに, 支援者が「自分のこだわりや考えを, 一方的に押し付け」た時に, 支援先に与えてしまう可能性のある悪影響について述べてきました.

ここでは, 逆にこれを防ぐ為に支援者はどのような取り組みができるのか? というところについて, 現時点の気付きを述べたいと思います.

...といっても, それは難しい事ではなく, 「自分のこだわりや考えを, 一方的に押し付ける」の反対のことをすればいいだけだと思っています. すなわち, 「自分のこだわりや考えを活かしつつ, 支援先と解決策を一緒に考える」ではないでしょうか.

支援者が成し遂げるべきは, 「支援者の理想を支援先に実現させる」ではなく, 「支援者の支援によって, 支援先の業務が最大効率で回るようにすること」です(但し, この2つがイコールになる場合もあると思います).

そのためには, 解決策を示す前に, 支援先の現状と課題をしっかり調査し, 理解に努めなければなりません. そして, そこから単純に解決策を提示するだけでなく, 一旦提示した解決策に対する反応を受けて, 更に解決策をブラッシュアップしていく必要もあるでしょう.

更に, 解決策はなるべく複数のフェイズに分離して, 少しずつ進められるように構築する方が良いでしょう. 言い換えれば, 支援先の課題を細かく分離して, 1つずつ解決していくように道筋を作るべきです. こうすることで, 支援先はその解決策によってどのような問題が解決され, どのようなメリットを得られるかが理解しやすくなります. 加えて, 一度に大きな変化を実現する場合と比べると, 細かい変化を繰り返す方が, その変化にかかるコストの見積もりもやりやすくなるでしょう.

まとめ

ここまでの話をざっくりまとめると, 技術的支援をするにあたって大切なのは, 支援する技術に対する知見だけではない, ということです. 何かしらの技術的支援をするエンジニアには, 支援先に対してより良い解決策を示せるようにするための工夫が求められます. その1つが「支援者と支援先の相互理解」であり, そのためにしっかりコミュニケーションを取り, 信頼関係を育んでいく事が大切, ...だと, 個人的には思っています.

いずれどこかのタイミングで詳しくお話しようと思いますが, GaiaxのRNDに新しく「Delivery Support Team(仮)」というチームが出来ることになりました. このチームは, 「エンジニアが開発したサービスと, そこからの生まれる価値を顧客に"届ける"」, という行為を「Delivery」と称して, そのために必要な全ての技術的要素(例えばCI環境の整備, デプロイフローの構築, ChatOps, Infrastructure as Code, IaaS/PaaS移行支援, ミドルウェアの導入/移行支援, チューニング, などなど...)を支援するチームです.

4月からは, この「Delivery Support Team」としての活動, すなわち他のチームへの技術的支援が業務の主になってくるので, 「自分のこだわりや考えを活かしつつ, 支援先と解決策を一緒に考える」を胸に刻んで取り組んでいきたいと思っています.

WEB+DB PRESS Vol.91の「Perl Hackers Hub」を書きました

...というわけで, 2月24日に発売されたWEB+DB PRESS Vol.91の「Perl Hackers Hub」コーナーに, 「PerlでInfrastructure as Code」というタイトルで8ページほど書かせて頂きました.

これまで何度か勉強会での発表やこのブログの記事としても紹介をしていますが, ここ最近自分が携わっているReactioという事業では, AWSやMackerel, GitHub, Slackといった様々なIaaSやSaaS, そしてJenkinsなどのツールを組み合わせて, インフラ周りの仕組みを構築しています. そして, これらのツール群の連携と操作は, PerlとCPANで公開されているモジュールを組み合わせて実施しています.

今回の記事で紹介したモジュールも, そのほとんどが実際にReactioのインフラを構成する為に使っているものですし, 本文中のサンプルコードもReactioで実際に使っているものを一部修正したものにしています. そういう意味では, 「Reactioの裏側大公開」という内容になっている... と言うことも出来るかもしれません.

拙い文章ではありますが, 是非お読み頂けると幸いです. ご意見ご感想など, お待ちしております!

PhotosynthにもJoinしました

...というわけで, 今日からPhotosynthで働くことになりました.

正確に言えば, GaiaxからPhotosynthへの「留学」という感じで, 今週1週間はガッツリ, それ以降は一旦3月末までを目処に週1ペースでPhotosynthで働く, という予定です. 個人的に最近とても興味を持っている, インフラ周りを中心としたエンジニアの業務の効率化, 自動化など, ガッツリ取り組んでいきたいと思っています.

GaiaxとしてもPhotosynthとしても, 「留学」というのは始めての試みですし, 現時点の自分のスキルでどこまで出来るかわからないこともあって, ワクワク半分ドキドキ半分という心境です!

経緯や成果などは, 適宜こちらのブログやGaiax Engineers' Blogなどで綴っていけたら... とおもっております. 乞うご期待!?

PerlでJSONを生成するときにJSONのキーの順番をソートする

今日はJSON.pmの小ネタをお送りします. ...といっても割と既知な情報では? という気がしているのですが, 自分は知らなくて10分くらいJSON.pmのドキュメント読んだりしてやっと見つけたので, 備忘録的に残しておきます.

さて, JSON.pmを使って, 普通にPerlのハッシュによるデータ構造をJSONに変換しようとすると, 生成されたJSONのキーの順序は生成する度に異なる順序になってしまいます.

use strict;
use warnings;

use JSON qw/ encode_json /;

my $json = encode_json({ a => 1, b => 2, c => 3 });
print "$json\n";

例えば, このコードをPerl 5.20で実行すると...

$ perl json.pl
{"c":3,"a":1,"b":2}
$ perl json.pl
{"a":1,"c":3,"b":2}
$ perl json.pl
{"b":2,"c":3,"a":1}

こんな感じで, 毎回キーの順番が異なってしまいます(例えば, 1回目はc, a, bの順番ですが, 2回目はa, c, bになっていますよね).

APIを実装していて, ユーザに対してJSONを返す場合であれば, これでも特に問題はありません. しかし, 何かしらのマスターデータからJSON形式のデータを生成してファイルに保存する... という場合, 生成後のJSONのキーの順番が毎回バラバラだと, 例えばJSONが書き込まれたファイルをGitで管理している場合, (JSONのキーの順序がJSONを生成する度に変化するので)毎回不要な差分が生じてしまい, 不便です.

こういう時は, JSON.pmのCanonicalモードを使えばいいそうです.

use strict;
use warnings;

use JSON;

my $json = JSON->new->utf8->canonical->encode({ a => 1, b => 2, c => 3 });
print "$json\n";

こういう感じにしてやると...

$ perl json.pl
{"a":1,"b":2,"c":3}
$ perl json.pl
{"a":1,"b":2,"c":3}
$ perl json.pl
{"a":1,"b":2,"c":3}

何度JSONを生成しても, 毎回同じキーの順序になっていることがわかります!

余談

ちなみに, canonicalだけでなくutf8も通しているのは, canonicalを有効にしながら, encode_jsonと同じようにJSONを生成したいからです.

要するに, JSON.pmを普通に使う場合の,

use strict;
use warnings;

use JSON qw/ encode_json /;

my $json = encode_json({ a => 1, b => 2, c => 3 });
print "$json\n";

というコードは,

use strict;
use warnings;

use JSON;

my $json = JSON->new->utf8->encode({ a => 1, b => 2, c => 3 });
print "$json\n";

と同じ事をしている, というわけです.

以上, PerlのJSON.pmについての小ネタでした.

あわせてよみたい

Jenkinsの設定をバックアップする

私が今所属しているReactioチームでは日々, デプロイにテストにバックアップにと便利にJenkinsを使っている訳ですが, 形あるものはいずれ壊れる運命にあります. もし, Jenkinsが壊れてしまったら... 考えたくないですね.

というわけで, Jenkinsが壊れてしまう前に, Jenkinsの設定をバックアップする仕組みを導入することにしました.

方法

Jenkinsの設定をバックアップする方法はいくつかあるようですが, 今回は@sue445さんのsue445/jenkins-backup-scriptを使ってみることにしました.

今回参考にさせて頂いたJenkinsのバックアップとリストアについてメモ - Qiitaという記事では, 他にもthinBackupというJenkinsのプラグインも紹介されていました. こちらはJenkinsのプラグインなので, ブラウザからポチポチとバックアップや復元が出来るのが嬉しいですが, プラグインの設定についてはバックアップの対象外とのことだったので断念しました.

導入

忘備録として残しておきますが, sue445/jenkins-backup-scriptのREADME.mdが画像付きで非常に丁寧に導入方法を解説しているので, こちらを見れば十分に導入することができます.

「Exclusive Execution Plugin」をインストールする

まず, Execlusive Execution Pluginをインストールします. このプラグインは, 名前の通りジョブを排他実行するためのプラグインです.

バックアップ用のジョブを作成する

続いて, Jenkinsで適当なバックアップ用のジョブを作成し, 設定します.

f:id:papix:20160208191155p:plain

  • ビルド・トリガ
    • 「定期的に実行」で, 適当なタイミングでジョブが実行されるようにしておく

f:id:papix:20160208191204p:plain

  • ビルド環境
    • 「Exclusive Execution Plugin」のインストールが成功していると, 「ビルドを排他的に実行」というチェックボックスが追加されるので, これをオンにする

f:id:papix:20160208191215p:plain

  • ビルド
    • 「シェルの実行」を追加し, 以下のスクリプトを実行するようにする
./jenkins-backup.sh $JENKINS_HOME /tmp/jenkins_backup_`date +"%Y%m%d%H%M%S"`.tar.gz

これで設定は完了です. ジョブを実行すると, /tmp以下にtar.gzで固められたバックアップデータが生成されるはずです.

なお, ここではとりあえずの動作確認用に/tmp下にバックアップを配置するように記述していますが, 実際に利用する場合は言うまでもなく適当なディレクトリに配置するようにしましょう.

復元

README.mdに書かれている通りにすれば, 大丈夫と思われます(幸いにもまだJenkinsが壊れていないので試していない...).

バックアップの設置場所や, Jenkinsのインストール先は適宜読み替える必要があります.

sudo /etc/init.d/jenkins stop
cd /path/to/backup_dir
tar xzvf backup.tar.gz
sudo cp -R jenkins-backup/* /path/to/jenkins/
sudo chown jenkins:jenkins -R /path/to/jenkins/
sudo /etc/init.d/jenkins start

まとめ

上記の設定では, バックアップデータはJenkinsが設置されているサーバにのみ存在することになるので, サーバそのものが壊れてしまった場合復元できなくなってしまいます. 念には念を入れるのであれば, 生成したtar.gzをS3などにコピーしておくなどの処理が必要でしょう.

とにもかくにも, これだけの作業量でJenkinsのバックアップが簡単に取得出来るのは非常にありがたいです. Jenkinsのバックアップをしていない方はこの機会に是非導入してみるのはいかがでしょうか?