ツールの導入のメリットを説明する難しさ

残念ながらこの記事の結論は「難しいよね」で終わっており、同様の問題を抱える人に明快な解答を提供するものではない。


色々モダンなツールを導入するにしても、商用サービスの開発にそれを導入することによるメリット (開発コストが下がるとか、サービスのユーザビリティが高まるとか)を示すのって難しいと思う。 定量的に「これだけ工数を減らせます」とか言えると良いのだけれど、それは難しい。 ただモダンなツール使いたかったっていう、自己満足で片付けられかねない。

もちろんそういった自己満足もあるため、尚のこと困る。

開発メンバー全員が導入に乗り気ならそれでもよいかもだけど、 乗り気じゃない人を説得するときにただの自己満足では説得できない。

後は自分の業績としてツールを導入したことにしたくても、 ツールを導入したことで非エンジニア・ディレクターとか人事の人とかそういう人にも分かるメリットがないと辛い。

以前積極的にツールを導入しているという話を非エンジニアの上司の方にした際に、

「それのメリットって結局の所時間(短縮)なの?」

って言われてちょっと困ったことがある。

もちろん時間的メリットもあるとは思うが、 別に1時間の作業が10分で終わるからという理由でWebpackなどに魅力を感じているわけではないし、 時間をかけてもそれを使わないと得られないメリットが絶対あると思う。

後は導入コストもかかるし、 導入するツールに既に精通しているならまだしも精通していないとトラブルとかに見舞われて 調査に時間使ったりとかもあるし、そう考えるとあまりプラスにならない、ってこともあるかもしれない。

とまぁ色々後ろ向きなことを書いたが、 これは自分がそういったツールを積極的に導入したいからこそ困っている。

インフラにおけるデプロイツールなんかは作業時間減るし、誰でもデプロイ出来るようになるとか メリットが分かりやすい。

今一番難しいと思っているのは jQueryでゴリゴリ開発していて、それに慣れてしまっている人、大きなストレスを感じていない人に フロントエンド系のツールの導入を説得する場合。

困る根本の原因は魅力を感じる、ツールを評価する観点の違いか

上記の話に真っ向から対立するわけだが、 自分みたいなエンジニア(エンジニアみんながそういうわけではない)は

  • ダンなツールを使いたい
  • コマンド一発でビルドされていくの気持ちいい
  • require() でnpmのモジュール取り込めるとか便利すぎる
  • terraformとか名前からしてカッコよすぎる

とか、定量的なメリットがなくてもそれだけでも説得できちゃったりする。

ツールの公式サイトとか、エンジニアの備忘録とかで 謳われるのはこういうメリットだと思う。 そういったサイトやブログで「工数がこんだけ減ります」とか「人件費をこれだけ削減できます」とか見たことない。

いや、PaaSやSaaS, IaaSではあるか。まぁそれは置いておこう。

そういった謳い文句に魅力を感じて導入したいと思うからこそ、 そういった謳い文句に魅力を感じない人を説得するのに困るという、そこが根本の原因なのかなと、この記事を書きながら思った。

結論

難しいけど、ちゃんと考えないといけない。 尤も、これは各人を取り囲む環境・チームの文化などに大きく依存するところではある。

docker rm, rmiを楽にするためのツールを作った

少し前に作ったツールの紹介

github.com

モチベーション

Docker Engineを使っていると不要なイメージやコンテナがどんどん出来てきて、 邪魔だし容量圧迫したりするので時々削除している。

それまでどうやっていたかと言うと

  1. docker ps -a, docker imagesで要らなそうなイメージ、コンテナを確認
  2. docker rm, rmi で削除

数が多いと削除対象のidやnameを覚えてdocker rm, rmiの引数として指定するのは結構しんどい。行を見間違えることもあるし。 もっと楽に出来ないものかと作った。 そんなツール既にあるだろとは思うが、ちょっと見つからなかったので作った。

インストール

ちゃんとしたインストール方法は用意していない。 ただのシェルスクリプトなので、PATHが通っているところにおいて実行権限与えればよい。

使い方

$ dckrm  # コンテナの削除
$ dckrmi  # イメージの削除

コマンドを実行するとコンテナ(イメージ)の一覧が出力された一時ファイルがDCKRM_EDITORで指定したエディタで開く。 削除しないコンテナ(イメージ)の行を削除ないし#でコメントアウト ファイルを保存して閉じると、本当に削除するか聞かれる。Noと答えれば何もしないし、Yesとすれば削除する。

たったこれだけ。

環境変数

  • DCKRM_EDITOR: 一時ファイルを編集するエディタを起動するコマンド(デフォルトはvi)
  • DCKRM_TEMPDIR: 一時ファイルを作成するディレクトリ(デフォルトは/tmp)

注意点

このツールは我ながら分かりにくいと思う部分がある。

  • 削除するものではなく、削除しないものに対応する行を編集する
  • ファイルを何も編集しないで閉じると、全削除しようとする -> これのために、確認を入れるようにした

仕方ないといえば仕方ないのだが、削除は取り返しがつかないかもしれないので要注意

TODO

このツールは自分で使うためにぱっと作っただけなので 全然作り込んでない。いけてない部分もあるけど、まぁいいかと放置している。

  • -f(--force)オプションのサポート
  • イメージ(コンテナ)の削除に失敗したときに一時ファイルも削除する(例外処理)
  • docker ps, imagesの --filterオプ本のサポート(一時ファイルに出力するイメージ(コンテナ)のフィルタリング) エディタの機能でフィルタリングも出来るとは思うけど、
  • 確認時に、削除するものと削除しないものの一覧を出力

ライセンス

MIT

自分のデスクトップ環境及び開発ツール群

2016/07/16現在

他にもインストールしているものは当然色々あるけど、代表的なものだけ抜粋

key value
OS Arch Linux
ログインマネージャ LightDM
ウィンドウマネージャ Openbox
タスクバー tint2
アプリケーションランチャー dmenu
ブラウザ chromium
ターミナルエミュレータ urxvt
エディタ vim
シェル zsh
ターミナルマルチプレクサ tmux
IM/IME Fcitx/Mozc
Node.jsのバージョン管理 nodebrew
プロジェクトの環境変数管理 direnv

デスクトップ環境の構築ではとにかく無駄のないミニマムな構成にしている。 Openboxは将来的にはXmonadに置き換えたいとか思っている(設定ファイルがHaskellで敷居が高い)。

設定ファイルのGitHubリポジトリはソフトウェアごとにsuzuki-shunsuke/*.conf にある。 1つのリポジトリ.dotfilesにまとめるほうが楽なのかもしれないけど、 各ソフトウェアの設定って基本独立したものだし、1つのリポジトリで管理するものじゃない気がしている。

最後に - Arch Linuxの勧め

Arch Linuxpacman, yaourtを使えば最新のソフトウェアがパッケージマネージャでインストールできて良い。 Ubuntuのときは最新のインストールするためにソースコードからビルドしてたのが、コマンド一発でインストールできる (パッケージマネージャからインストールすれば当然管理も楽)。

また、最初には無駄なものがほぼインストールされていない(Xすらない)ので、本当に自分好みのミニマムな環境が作れる。

あと、Wikiがかなり充実している。良い

自分とLinuxの付き合い

自分がデスクトップOSとしてLinuxを使うようになってから4年ちょっとになる(2016年7月現在)。 そんな自分とLinuxのこれまでの付き合いについて書く。

Linuxとの出会い、最初はUSBブート

元々WindowsでEcpliseを使って開発していた自分がLinuxに触るようになったのは5年ほど前で、 最初はKnoppixをUSBにインストールしてUSBブートして使っていた。

当時の趣味もとい日課は書店で技術書のコーナーをぶらぶらし立ち読みし、興味のあるものを買って読むことだった。 Linuxに関する書籍を読んでみて、エンジニアならLinux使えないとなと思い、使い出した。

それからKnoppix以外の色々なディストリビューションを試した気がする。 Ubuntu, Fedore, Kubuntu, Lubuntu, CentOS, Debian, Puppy Linux, TinyCore Linux, etc もっともほとんどはインストールしてみただけだけど、それが楽しかった気がする。

WindowsUbuntu/Unityをデュアルブート

そして大学院に進学してから本格的にLinuxで開発しようと思いUbuntu/Unityをデュアルブートした。 Ubuntuにしたのは単に一番メジャーなディストリビューションだったから。 Fedoraとか他のも試したけど、Ubuntu/Unityが一番使いやすかった。 WindowsからUbuntuへの移行ではほとんど困ることはなかった。

Ubuntuは初めて使うLinuxディストリビューションとしては一番オススメである。 ユーザが多いので大抵ググればわかるし、初心者でも使えるように設計されているので、 極端な話ターミナルエミュレータ全く使わなくてもなんとかなると思う。

先輩の一言でLinux力を更に高めることに

Ubuntuでは当初ターミナルエミュレータEclipseをそれぞれ別の仮想デスクトップ上に表示して開発していた。 ただ、GUIに頼り切った開発をする自分を見たWindowsユーザの先輩が一言

Linux向いてなんじゃないの?

と言った。これは多分一生忘れない。

先輩としては元Windowsユーザの自分に対し、「無理してLinux使わないでWindows使ったほうがいいんじゃない?」という優しい助言だったのかと思うが、

とても悔しかった。 見てろ、もっとLinux使いこなしてやると思い、Eclipseを16階から外に放り出し、vimに乗り換えた。

Eclipseからvimというのは相当な変化な気もするが、あまり困らなかった気がする。

それからはほとんどCLIによる操作が基本でGUIにはあまり頼らなくなった。

因みに今自分が起動するGUIは基本

だけである(とかいいつつまれにファイラーとか起動しているときがあるかもだけど、見なかったことにしてほしい)。

更に因むと、Windowsでは

  • Git Bash(VagrantでArch Linux起動)
  • Chrome
  • Slackアプリ(なんかChromeだと動作おかしいことがあるので仕方なく使っている)
  • MSオフィス(基本Windows使うのはMSオフィス開かないと駄目なときなので使っている)

長きに渡るUbuntuとの付き合い(4年弱)

それから長いことUbuntuを使っていた。

ただ、Ubuntuは初心者に優しいディストリビューションで、無駄なソフトウェアが最初からインストールされてたりするし、 もっとギークよりのディストリビューションが使いたいと思うようになっていた。 いや、思うだけなら割と早い段階で思っていた。Gentoo に憧れていた時期もあった。

ただ、そんなギークよりのディストリビューションに移行するのは結構ハードルが高く、 Ubuntuで困っているわけでもなかったので結局移行できなかった。

ついにArch Linuxへ移行。今に至る

一念発起してArch Linuxに乗り換えたのは4ヶ月ほど前である。 Arch Linuxに乗り換える際は結構入念に準備した。

KVM上にArch Linuxをインストールし、手順をWikiにまとめたり、 AnsibleのPlaybookやシェルスクリプトを作成したりした。 KVMだけでなく、使わなくなった実機にもインストールし色々準備した。

github.com

github.com

Arch Linuxの魅力の一つは、ベースには必要最低限のものしかインストールされておらず、 自分で好きなようにデスクトップ環境を構築できることである。 UnityやGNOMEKDEなどをインストールしてしまうのが多分簡単なのだと思うが、 それではつまらないし、とにかく無駄のないミニマムな環境を作りたかったので

  • LightDM - ログインマネージャ
  • Openbox - ウィンドウマネージャ

というかなりミニマムな構成になっている。 ミニマム過ぎて困ることも多少あるが、概ね快適である。

本当はタイル型ウィンドウマネージャにしたかったんだけど、 Xmonadもawesomeもうまく行かなくてOpenboxにした。

TerraformでGCPのオーケストレーションをした

GCPでWebコンソールからGUIで操作しているとミスするし、効率が悪い。 GCEインスタンス作ったもののリージョン間違えたので作り直し。作り直したけどベースイメージ間違えて作り直し。。。 orz

それに、操作ミスで本番サーバを停止したりしかねない。

そこでTerraformでオーケストレーションするようにした。 Infrastructure as Code

www.terraform.io

www.terraform.io

Terraformでは*.tfという設定ファイルを作って

$ terraform plan  # テスト
$ terraform apply #  リソース作成
$ terraform destroy  # リソース削除

terraformコマンドを実行すると実行前後の状態を表すファイルが生成される。 これを元に差分を検知し、リソースを操作するため、これらのファイルもバージョン管理必須。

terraformを使う場合、

terraformで出来ることはterraformでやる(Webコンソールとかからやらない)

ことが大事である。上記の通り、terraformは現在の状態をファイルで管理し、それを元に実行する操作を決定しているため、 ローカルのファイルに記録されている状態と実際の状態が異なるとコマンド実行時におかしなことになりかねない。

terraform使って思ったこと

$ terraform apply

でリソースが生成・更新されるのは気持ちいい。

ただ、設定ファイルの文法が分かりにくい。

www.terraform.io

GCP Provisionerのオプションなんかでも公式ドキュメント読んでもどう設定すればよいのか良くわからなかったりする。 ドキュメントは充実しているとは思うので、そのオプションを使ったサンプルコードがあると良いと思う。

あと、terraform applyを実行すると設定していない項目まで変更されるというよくわからない挙動が見られた。

最後に

GitHubにサンプルのリポジトリを作れたら良かったなと思う。

Google Apps Scriptで業務効率化ツールを作った思い出話

1年ぐらい前にGoogle Apps Script(以下GAS)で カスタマーサポート(以下CS)のための電話対応記録ツールを作ったときの話について書く。

作ることになった経緯

当時自分は企業向けのSaaSを開発する新卒エンジニアだったのだが、 新卒エンジニアにもCS業務を1週間ほど体験させようという話になった。

週明けからCS業務を行うことになった週末土曜日、 自分はCS業務を行う自分をシミュレーションしていた。 その際に思ったことは

「電話対応で手書きでメモ取りたくない」

ということだった。

従来電話対応では各人が手書きでメモを取るようになっていた(別にルールではないけど自然とそうなってた)。

自分の手書きの字は汚くて読めないし、アナログて嫌だ。

だいたい手書きのメモなんて紛失したりするし、いつ書いたものかも分からない。 書いただけでは他人に共有できない。 問い合わせがあったこととその内容を共有することは極めて大事。 電話対応した人が病欠したとしても問い合わせ内容を共有できていれば他の人が対応するのが容易。

作ったもの

Google Apps Scriptで問い合わせ記録フォームを作った。 Google Formを使うのではなく、HTMLとBootstrap使ってフォームを作った。 電話対応しながらフォームに必要事項を記入していき、 終わったら送信ボタンを押す。 送信ボタンを押すとGoogle スプレッドシートに内容が記入され、 同時にチームのメーリスにメールが送信されるようにした。

早速提案・導入

週明けにCSの方に「こんなもん作ってみたけどどうですか?」と相談してみたところ じゃぁ使ってみようかとあっさり導入できた。 良いチームだと思う。

効果

情報がきちんと共有されるようになった。 CSチームだけでなく、営業チームの方にもメールが行くので 顧客の担当営業が問い合わせを営業トークにも活用でき、顧客から良い反応をもらえたこともあったそうだ。 あと、問い合わせで聞いておくべき項目が予めフォームの項目として含まれているので、 それを聞きそびれることも減った(例えば利用しているブラウザとそのバージョンとか)。 後はGoogle スプレッドシートを使って集計なんかも出来るようになった。

技術的な話

技術的にそんな難しい話はない。

公式ドキュメントを参考にすれば割と簡単に作れると思う。

developers.google.com

HTML Service: Create and Serve HTML  |  Apps Script  |  Google Developers

最後に

今は上記のプロジェクトには関わっていないのだが、今でも使われているようで嬉しい。 エンハンスをするとしたらSlackに通知したりするのが良い気がする。

開発サーバで複数バージョンのアプリケーションを動作させるための施策

  • プルリクをマージする前に開発サーバで動作確認したい
  • 本番にデプロイする前に開発サーバで動作確認したい

といったニーズを満たすために行った施策を紹介する。

前提の説明

GitHub Flowで複数人の開発者が開発している。 upstreamのリポジトリを各人がForkし、チケットごとにブランチを切り、upstream/masterにプルリクを投げる。 レビューしてOKだったらマージする。というフローを取っている。

実現すること

開発者fooのhogehogeブランチを開発サーバで動作確認したい場合、 開発サーバにそれをデプロイし、

http://hogehoge.foo.(開発サーバのドメイン)

のようにURLを割り当てるようにする。 タグやリビジョン番号で同様に

http://(タグ名・リビジョン番号).(開発サーバのドメイン)

みたいにURLを割り当ててもよいかもしれないが、今の所それはやっていない。

使用した主なツールなど

  • Docker Engine - 複数のアプリケーションをコンテナとして動かす
    • nginx-proxy - サブドメインによってリクエストを各コンテナに割り振る
  • Fabric - デプロイサーバから開発サーバにデプロイする

構成の概要図

draw.ioで図にしてみた。

f:id:kics:20160715011728p:plain

デプロイ時に具体的にやること

$ ssh デプロイサーバ  # 開発者がデプロイサーバにSSHログイン
$ su deployer  # デプロイ用のユーザになる。これは本当にこれで良いのか
$ cd デプロイスクリプトがあるディレクトリ  # fabコマンドを実行するために移動
$ fab --set repo=foo/hoge build deploy  # デプロイ対象を指定してビルド・デプロイ

詳細

自分はアプリケーションを動かす場合基本的にDockerコンテナ上で動かすようにしている。 複数のアプリケーションを動かす場合、各アプリケーションの依存ライブラリ及びそのバージョンとかが異なったりするが、 各アプリケーションをコンテナとして動かせば困らない。 いらなくなったらコンテナごと削除すればよいので楽。

各コンテナにサブドメインを割り振るのだが、これは

github.com

を使えば簡単。

Dockerを使ったデプロイではソースコードをイメージに含めてビルドし、デプロイのたびにコンテナ作り直すようにすることも出来るが、 毎回イメージをビルド、pullするのは辛いので、ソースコードをホストにデプロイし、コンテナにマウントするようにしている。 依存ライブラリもデプロイ時にインストールしているのだが、完全に1からインストールすると時間がかかってとても効率が悪いので 少し前のリビジョンの依存ライブラリをインストール済みのDockerイメージを使用し、それに足りないものだけを毎回インストールするようにしている。 このイメージは必要に応じて更新する。 GitHubとDocker Hubを連携してプルリクやマージのたびにイメージを自動でビルドするようにし、それを使うのもありかもしれない。

(余談だが、依存ライブラリのインストールをイメージに含めてしまわないのはDockerの使い方としてどうなのかという意見もあるかもしれないが、 ビルドやpullのコストを考えると、現実的にはありだと自分は思っている。)

ソースコードCSSやJSをビルドする必要があるが、それは開発サーバで行うのではなく、デプロイサーバ上で行い、 ビルドしたものをFabricのrsync_projectで転送するようにしている。 そうすれば開発サーバにNode.jsとかいらない。

デプロイは各開発者がデプロイサーバにSSHログインし、Fabricでデプロイするようにしている。この辺は

複数プロジェクトを抱えるチームでのデプロイ自動化 | SOTA

を参考にしている。

タスクとして以下のようなものを作成している。

  • build # git pull(clone), CSS/JSなどのビルド
  • deploy # デプロイ
  • destroy # コンテナやDBスキーマを削除
  • stop # コンテナの停止
  • restart # アプリケーションの再起動

最後に

以上のような方法で今の所うまく行っている。 ただ、本当にこれで良いのか、もっとうまい方法がないかと言うと、分からない。

今回の施策を打つのには結構な工数をかけていて、 GAEみたいなPaaSなんかだと自分がやったことはうまいこと勝手にやってくれたりするらしい(そんなこと聞いた気がする)ので、 そういう点ではPaaSは便利だなと思う。

qiita.com An Overview of App Engine  |  App Engine standard environment for Python  |  Google Cloud Platform