Webエンジニアとして大事な仕事の進め方 3選(社会人4年目を前に考えたこと)【雑記】

これは何

そろそろ社会人4年目になろうという3月半ばである。 主に、これからの自分のために今まで仕事をしてきて考えたことを記録しておく。

振り返った時に、ここに書いてあることが正しいと思うのか、後から振り返った時に間違っていると思うのか。 間違っていると思ったらなら、それはおそらくその時に成長しているということだと思う。

目次

はじめに

対象読者

以下のタイプの人にはこの記事は役に立たないと思われる。

  • 常に限界突破できる
  • 常にモティーベーションが高い
  • 人生が楽しすぎて仕方がない

なんとかだましだまし仕事をしてそこそこ楽しく生きていきたい人にとっては少し役に立つかもしれない。 同じ労力をかけていても、信頼される人/されない人、仕事が進んでいるように見える人/見えない人 がいる。 楽をして楽しく仕事がしたいじゃないか。

背景

仕事辛い => なんとかなる までの道のり

丸3年仕事をしてきて、今でこそ辛さはかなり減ってきた。 辛い時期も結構多かったので、軽くだけども辛かった時期について触れておきたいと思う。

今は主にインフラエンジニアとして、小さくないサービス(月間億単位のPVがある)の主インフラ担当として日々膨大なアクセスをさばくサーバたちを管理している。 物理マシンの調達依頼から始まり、OSやネットワークの設定、ミドルウェアのインストールや設定、必要ならアプリをデプロイしての動作確認までが私の仕事。

最初はHTTPのリクエストとレスポンスの違いもわからず、ほぼズブの初心者として入社した。研究室で書いていたのはクソPerlスクリプトFortranの死ぬほど汚いコードのみ。 研修は通常は4ヶ月のところが、直属の上司が忙しく放置気味でさらに追加で5ヶ月くらいひたすら”研修資料を作る研修”を行っていた。

1年目の終わりごろに先輩からいくつかの細々としたタスクをもらってこなしていた。 楽、だけど自分でタスクコントロールしているわけじゃないし、お給料分働けていない。 しかし2年目に入る頃ぐらいに所属部署が解体された。インフラとしてまとまっていたチームメンバが各開発部に散り散りに。私も開発部へ放り込まれることに。その時点で、まともに仕事がこなせない素人である。

2年目の半ばには、やっとなんとか仕事が回せるようになった。しかしプルリクを出せばコメントが大量につき炎上状態、口頭で上司に話をしに行けば私の理解力の無さに上司がヒートアップしてしまう。辛い日々。 「いや、だって、先輩たちがドキュメントの一つも残していないのに、突然放り込まれた私の身にもなっておくれ」などと思っていた。

3年目に入ったころから信頼もされ始め、インフラ周りの仕事は作業は大量ではあるが大体どのように進めればスムーズにいくのか肌感覚でわかってきた。 お給料もやっとここら辺で上がり始める。よかった。 給料分の仕事をしている感。

3年目の終わりごろ、担当サービスのインフラのトラック係数を上げるために後輩と同期への技術共有をしなければならず、また奮闘中。 主インフラ担当が一人でタスクをこなすのはそこそこ仕事は早く進むが、私がトラックにはねられるとインフラ仕事の大幅鈍化が予想される状態。 教えることに時間を取られて辛い以外は、割と楽しく仕事をしている。

辛さをなくす方法

基本は、以下のことを考えていたように思える

  • 必要な情報を自ら取りに行く
  • キーパーソンに信頼されるためにはどうすればいいのかを考える
  • 会社やチームに(最小労力で)提供できる価値は何か考える

重要なのはこれだけで、以下に書くことは各論でしかない。 パッと思いついたことを三つだけ載せておく(3選とは。別にタイトルに意味はない。)

1.期限を確認する

インフラの仕事は2種類あると思っている

  • 期限のかっちりしたプロダクトリリースに密接に関連した仕事。新規サービスや機能拡張のためのインフラ仕事。
  • 期限が比較的緩やかな冗長化や可用性の向上などのための改善業務。サーバ構築自動化やCacheやDBのクラスタリングを組むなど。

特に前者の仕事では期日に間に合うことが重要である。 仕事のクオリティや将来のことを考えても、”とりあえずこの期限までに仕上げたい” という仕事である。 この仕事のデットラインを超えてしまうことは信頼をなくしてしまうことにつながる。 最初から無茶な仕事は投げ返すか新たに人をもらうなどの対応をすべきだが、最初に「自分一人でこの日までにできる」と言ってしまったならその日までに終わらせることが重要。

インフラの世界では Infrastracture as a code の実践が最近当たり前だが、それをやることが最優先ではない。手段である。 コード化されてなくても、再利用性が低くても、重要なリリースに間に合わせるのが最重要だった場合には、そういった手段の部分は妥協する場合がある。 10割構築自動化するのは手間がかかるので、8割自動化しておいて、2割は手作業で仕上げる。 しかし2割の部分も暗黙知にしてしまうのではなくてドキュメントに手順や懸念点を残しておくのは大切。 雑に作る予定の部分については上長にあらかじめ話を通しておき、リスク判断を自分だけの問題としない。 問題点が明らかになっていれば、期限を延ばしてその問題点を潰すべきか、無視できるならリリースするかは上長が判断できる。

2.進捗の報告はタスク内容で行う

よく 「その仕事はどこまで進んだのか?」と聞かれて「8割がた終わりました」などとざっくり答える人がいる。 大体そういう答え方をしている人の仕事は、実質5割までしか進んでいない(自分の中でも大体終わったなと思った仕事が長引くことも多い)。 エンジニアリングでは最後の詰めの部分で問題が発生することがよくある。詳細動作確認をしてみたら何かうまく動かないだとか、追加注文が入るだとか。 そういう場合に起こっている問題は解決に時間がかかるものだ。 よって、最初に見えていたタスクが8割終わっていても、2割の仕事がそこから増殖することになる。 はたから見ると、いつまでたっても仕事が終わらせられない人が出来上がる。

どこまで進んだかタスクの内容でチーム内で共有しておくと良い。 例えば

  • これとこれは終わって、後のタスクはこれ、チケットの個数でいうと8分の6終わっている。
  • だけど後のタスクで詰まるとしたらこういう可能性があるかもしれない
  • スムーズにいったら後2日だけど、バッファとして後6日欲しい

仮にざっくりパーセントで言うと、その人が何で詰まっているかもわからないし、一人で抱え込んでいるので潜在的リスクも発見されない。 他の人が見えているが自分が見えていないタスクやリスクも見えない。 ある程度細かい粒度で共有しておけば、何か困った時にアドバイスももらえるし、「それは確かに時間がかかるのもしょうがないね」と納得感も出る。

3.情報は再利用しやすいようにする

できるだけ同じことはしない。

エンジニアはコードについてはモジュールの再利用を考えてうまくやる人が多い。 私は技術調査についても同じことをした方が良いと考えている。

社内でもう詳細調査をした人がいるのに情報が公開されていない、検証過程・思考過程が見えない。そういうことはよくある。 自分が調査をしたら、その思考過程や意図を含めてドキュメントに残しておくべき。 一般的な話なら外部公開をしても良いし、社内秘が含まれるなら社内ドキュメントでも良い。

最低限殴り書きでもいい。何も残さないよりマシ。 有用な文章を残していくと、会社全体に役に立つ。 未来の自分にも役に立つ。後輩指導にも役に立つ。ちゃんと情報を出す人は信頼される。

まとめ

楽して楽しく仕事をしたい。そのためには周りに信頼されること、協力を得ること、それが大事だと思う。 どうやったら周りに信頼されるのかな? どうやったらもうちょっと少ない労力で仕事を進められるかな? というのを考えながらやっていきたい。

どこまで仕事を詰めてから人に確認してもらうか【雑記】

これは何

雑記です。
エンジニアとして仕事を可能な限り効率よく進めるために、仕事をどこまで仕上げてから他の人に最終確認してもらうか、という点について考える。 「チームとして」仕事を効率的に進めること、「個人として」効率的に進めることの二つの視点で見る。

目次

背景

年末になり、諸々の仕事がたくさん降ってきた。締め切りが近い仕事が多い。 私は仕事を進めるにあたり、もともとできるだけ深く調べてやっていきたいタイプ。仕事は遅いが硬い仕事を好む。

何を優先しよう

チームとして効率的に進めること

エンジニア一人が仕事を進めることではなくて技術的興味からその仕事には不必要なまで技術調査をすると仕事は滞る。逆に難しいことは置いておいて、これで問題なく動くというところまでならそこまで労力はかからない。
例えば、プロダクトのappleのATS対応のために自サービスを全てhttps化したいシチュエーションがあるとする。ここでは詳しく述べないがATSの要件として必須となるCipher Suiteがある。インフラエンジニアが最低限仕事を進めるのに必要な知識としてはiOSクライアントがしゃべれるcipher suiteは何か、LBがしゃべれるcipher suiteは何か、という視点だけを持って”文字列”(例えば「ECDHE-RSA-AES256-SHA はクライアント、LBも両方とも使えるからOKだな」などと)の対応を見れば良いだけ。負荷については既に設定したものがどれくらい使っているかを見て、アクセス数で比を取れば大まかな値は見積もれる。
しかし、調べていくと例えば以下のような疑問が出てくる

  • Cipher Suiteってなんだ? 鍵交換の部分が楕円曲線暗号(ECDHE)を使えばRSAを使ったものと比べるとCPU処理が重くなるようだが、どういうアルゴリズムの違いがあるんだ? 比ではなくてLBのカタログ性能と見比べて数値的に見積もりできないの?とか。
  • LBのSSLをハードウェアで解く方法って裏で何やってるんだ? 

これらを深いレベルまで調べるのは大変に骨である。実際、今回限られた時間の中では本当にさわりしか学ぶことができなさそうだ。

さて、チームとして短期的に成果を上げるためには、上記のように概要を調べて => 大体こうだろうと文章を書いて => 詳しい人に聞いて大体OKを貰って => 上長の承認を得る(場合によっては情報不足によるやり直し) みたいな流れになる。
本当は次のようなプロセスを踏みたい(が、無限に時間がかかる) 概要を調べる => 疑問を満足するまで潰す => 詳しい人に聞いて裏取りして => 上長も一発承認。

前者のフローではその案件について詳しい人と上長には少し負荷はかかるが確認作業なので大きくない。私の作業量は小さいのでチームとしては割と小さな作業量で仕事を進めることができる。
後者のフローでは私個人の作業量は多いが、確認者の負担は小さい。しかしながら8割から10割に完成度を高めていく作業は0から8割にあげるのの5倍はかかる。

なので、チームとしては7〜8割の完成度の仕事まで自分で仕上げ、あとはうまく流していくという作戦がうまく行く。

個人として長期目線で見ると

上記のように、チーム目線で短期効率を求めて仕事を流していると絶対に自分は「詳しい人」にはなれない。 短期的には今ある仕事を回せばいいが、長期的に見れば会社としてもそれぞれがスキルアップした方が冗長化はできる。個人としても美味しい。裏の技術を知っているエンジニアは貴重だが、上辺だけなぞって仕事をそこそこ流せるエンジニアは割と沢山いる。 そうなると10割の完成度を目指し(実際には8〜9割の完成度だったとしても)満足いくまで裏の理解をした方が良い。とはいえ、あまりにも業務が進まないとお給金は上がらない。難しい。

まとめ

結局のところバランスを取るしかない。締め切りに追われている時には技術調査を少なめにして実験的手法が増えるのはしょうがない。時間があれば論理から攻めて深くまで理解して仕事をする。

追記

めっちゃのんびり働きつつ、満足いくまで勉強しつつ、お給金も沢山もらいたいなあ、という話でした。家で無限に勉強時間をとることでこの問題を解決しているエンジニアもいるが、それは人生の浪費では、と個人的には思っている。人は仕事だけをするためだけに生きているわけではない。業務時間中には全力を出し、プライベートは可能なかぎり仕事から離れて楽しむのが良い。

kibanaで認証かけたいんだけど(nginxによるbasic認証)

背景

kibanaは認証もなくがら空きである。fluentで本番サーバのログをelasticsearchへ流してそれをkibanaでみる。本番のデータでいろいろ表に出ちゃいけない情報もあるので、社内であってもカジュアルすぎる感じで見られると嫌。 そういう訳でkibanaにnginx経由でアクセスを強制することでbasic認証を挟む。

やったこと

  • nginxインストール
  • nginx設定
  • パスワードファイルの配置
  • kibana設定

nginxインストール

詳しく書きません。tar ballからver 1.9のものをインストール。

nginx config

メインの設定は他のサーバと共通。なんでもいい。vhostに以下のような設定。ansibleで書いたやつ。

# basic authentification for kibana
upstream kibana {
    server localhost:5601;
}

server {
    listen       80;
{% if ENVIRONMENT == "production" %}
    server_name  kibana.o-in.hoge.jp
{% else %}
    server_name  kibana.dev.o-in.hoge.jp
{% endif %}
    charset utf-8;

    # allow ip
    include /usr/local/nginx/conf/common-ip.conf;
    deny all;

    error_log /var/log/nginx/nginx_kibana.error.log warn;
    access_log  /var/log/nginx/nginx_kibana.access.log  mylog;

    proxy_buffering off;
    
    # basic auth 
    auth_basic "Enter your ID and password." ;
    auth_basic_user_file "/usr/local/nginx/.htpasswd" ; 

    location / {
        proxy_pass http://kibana;
    }
}

パスワードファイルの配置

nginx 設定ファイルで .htpasswdを読み込んでいる。 apache付属のhtpasswd コマンドを用いる。今構築中のサーバにapache居なくてもOK。他のサーバで作ってコピペしてくればいい。

$ /usr/local/apache2/bin/htpasswd -c ./kibana_pass myloginid
New password:
Re-type new password:

作成したファイルは nginxユーザの持ち物で0600にでもしておく。他のユーザによって書き換えられても嫌だし、ハッシュ化されているとはいえ見られても嫌。

kibana設定

localhostのnginxからのみアクセスできるようにする。 kibanaのhomeディレクトリの下にconfig/kibana.ymlとかがあるので、

server.host: localhost

みたいな記述を入れる。そうするとlocalhostからのみのアクセスを受け付ける。

忘れずに

nginx. kibanaのrestartをして設定を反映する。

コメント

basic認証を初めて使ったけどそんなに難しくない。認証の経路を作って、直接のアクセス経路を断つのを忘れないようにするのが重要だと思った。

BIOSがバージョンアップできているか確認したい dmidecode コマンド

背景

サーバのfirmware のバージョンアップをやった。バージョンアップツールにBIOSのバージョンアップも同梱されているっぽい。実際にバージョンが上がっていることを確認した。導入が2011年ごとのサーバだったので2015年とか2016年に上がっていればOK。 (どのベンダーの物理サーバかはぼかして書いてます)

コマンド

dmidecode コマンドを使う。 このコマンドはハードウェア情報を取得するためのコマンド。BIOSの情報ものってる。

コマンド実行結果

$ sudo dmidecode | grep -A 3 "BIOS Information"
BIOS Information
        Vendor: HP
        Version: P68
        Release Date: 08/16/2015

OK good

コマンドがないんだけど? を解決するwhereis コマンド

背景

CentOS 5系のサーバとかだとコマンドにいろいろパスが通ってなかったりする。 今までは mlocateパッケージを入れて、locateコマンドで探していたりした。

コマンド

whereis コマンドはコマンドとかのありかを教えてくれる便利コマンド。

どのパッケージに入っているの? という話だが、 以下のようにrpmコマンドでファイルがどのパッケージに含まれるか見れる。

$ rpm -qf `which whereis`
util-linux-2.13-0.47.el5

どうやら util-linuxというやつに入っているらしい。core groupに入っている。

使ってみると

$ whereis ifconfig
ifconfig: /sbin/ifconfig /usr/share/man/man8/ifconfig.8.gz

MySQLで他のサーバからdataディレクトリコピーしてきたけど動かない(innodb_log_file_size設定)【問題と解決】

目次

背景

新たにMySQL Slaveサーバを構築したい。既存のSlaveサーバを一旦とめて、dataディレクトリごとコピーして配置。普段だったらmaster.infoとかも入っているし、すんなり動くが、今回はなんか動かなかった。

エラー

mysqld start時に以下のエラー

Starting MySQL.. ERROR! The server quit without updating PID file (/usr/local/mysql/data/seiga-s01b.pid).

対応

順に問題をつぶしていく。

  • pidファイルが書けないのか? Permissionがないとか? => mysqlユーザになり、touchで該当箇所にファイル作成できる。
  • errログがPermissionが原因ではけないとダメという事例も? => mysqlユーザの持ち物になっててOK
  • errorログをtail -fして起動してみる。error log に以下のエラーが出力されている。
InnoDB: Error: log file /usr/local/mysql/data/ib_logfile0 is of different size 0 268435456 bytes

問題はこれだな。ib_logfileはサイズと個数が設定と一致してないとダメだった。設定では128M, 実体は他のサーバから持ってきたので256Mになっていた。 削除して起動してやると問題なく起動。ib_logfileも新たに作成されている。

おわりに

前にファイル側ではなくて設定変更したときに公式ドキュメントに書いてあった知識が役にたった。 innodb_log_file_size の値を変えるときには、MySQLサーバ停止後にファイルを消して起動するべし、とのこと。

MySQL脆弱性 CVE-2016-6662 について (2016 09 13現在)

これは何

MySQLにリモートでコード実行される可能性のある脆弱性 CVE-2016-6662 が発覚。その概要と対応をまとめる。

目次

  • これは何
  • 目次
  • 資料
  • 対象バージョン
  • ざっくり言うと?
  • 設定ファイルが書き換えられるとなぜ攻撃になる?
  • 今回の脆弱性
    • my.cnfに追記する
    • ファイルが無い状態から作る
  • 対応方針案

資料

CVE-2016-6662  http://legalhackers.com/advisories/MySQL-Exploit-Remote-Root-Code-Execution-Privesc-CVE-2016-6662.html

対象バージョン

2016 09 13日現在の全てのバージョン。 具体的に言うと、現時点での最新のバージョンの以下を含む、それ以前のバージョンに脆弱性が存在。

  • 5.7.15
  • 5.6.33
  • 5.5.52

要するにパッチがまだない。 MySQL cloneの MariaDBとPerconaDBにも影響。

ざっくり言うと?

SQLインジェクションを使って、 my.cnf を上書きできる。 攻撃するには以下の条件が必要

設定ファイルが書き換えられるとなぜ攻撃になる?

mysqld_safeがrootプロセスで起動して、mysqldプロセスがmysqlユーザに落として起動される。mysqld_safeのスクリプト(配置場所によるが、例えば /usr/local/mysql/bin/mysqld_safe)のset_malloc_lib()でshared library がmysqlサーバ起動前に読み込まれて--malloc-lib=LIB へセットされる。 設定ファイルを書き換えられるということは、この変数で読み込む値を my.cnfの [mysqld]か[mysqld_safe]セクションで好きに設定できるということ。そうすると、任意のライブラリ(任意コード)がmysqlサーバ起動時にroot権限でされる(mysqld_safe実行時なので)。 3.23.55以前のバージョンだと

SELECT 'malicious config entry' INTO OUTFILE '/var/lib/mysql/my.cnf'

このコマンドでファイルが作れて、設定ファイルとして読み込むことができる。ファイル作成の例としては /tmp/ 下に作成してみると

$ mysql -uroot -p -e "SELECT 'malicious config entry' INTO OUTFILE '/tmp/my_temp'"
$ ls -ltr /tmp/my_temp
-rw-rw-rw- 1 mysql mysql 23 Sep 13 16:50 /tmp/my_temp
$ cat /tmp/my_temp
malicious config entry

今はこの脆弱性は修正されている。MySQLは 0666 permissionsのファイル(というかotherに書き込み権限がある場合)を設定ファイルとして読み込まないようになっている。具体的には以下のエラーが出て読み込まない。

Warning: World-writable config file '/etc/my.cnf' is ignored

しかし、MySQL logging関数で出力されたファイルは 0660 になっているので、設定ファイルとして読み込むことができる。これが今回の問題 

今回の脆弱性

my.cnfに追記する

仮に my.cnfが以下の様なmysqlユーザの持ち物だった場合(例えば以下のようなパーミッションだった場合)

root@debian:~/# ls -l /etc/my.cnf
-rw-r--r-- 1 mysql mysql 72 Jul 28 17:20 /etc/my.cnf

以下の内容をファイルに追記できる。

mysql> set global general_log_file = '/etc/my.cnf';
mysql> set global general_log = on;
mysql> select '
    '>
    '> ; injected config entry
    '>
    '> [mysqld]
    '> malloc_lib=/tmp/mysql_exploit_lib.so
    '>
    '> [separator]
    '>
    '> ';
mysql> set global general_log = off;

ファイルが無い状態から作る

/etc/ 以下にmy.cnfが無い場合には、/etc/ ディレクトリのパーミッションで縛られる。root かつ 0644 だったばあいには mysqlユーザは作ることができない。 どのようなファイルが作られるか、/tmp/以下で試してみる。この方法で作られたファイルは以下のようなPermissionになる 。

$ ls -ltr /tmp/my_temp.txt
-rw-rw---- 1 mysql mysql 685074 Sep 13 16:33 /tmp/my_temp.txt

しかし、この脆弱性だけでは、my.cnfに loggingの最初の行(version情報など)が入ってしまい、設定ファイルとして機能しない。 さらに他の脆弱性 CVE-2016-6663 (2016 09 13現時点では詳細非公開) を使用すると、(余計な情報を消して?)FILE権限なしに、任意の内容を書き込むことができる。

一次対応策

MySQL 5.5だと以下のような設定ファイルが置ける  参考: http://dev.mysql.com/doc/refman/5.5/en/option-files.html

/etc/my.cnf         Global options
/etc/mysql/my.cnf   Global options
SYSCONFDIR/my.cnf   Global options
$MYSQL_HOME/my.cnf  Server-specific options
defaults-extra-file The file specified with --defaults-extra-file=file_name, if any
~/.my.cnf   User-specific options
  • /etc/my.cnf がmysqlユーザで書き込み権限がないこと(例えば rootで 0644 )を確認する
  • /usr/local/mysql 直下が mysqlユーザの書き込み権限がないこと (例えば以下のようになっていること。mysqlユーザはここにmy.cnfを配置できない)を確認する
$ ls -ltrd /usr/local/mysql/
drwxr-xr-x 13 root mysql 4096 Sep 13 17:27 /usr/local/mysql/
  • ファイルを置く権限がある場合には、 root パーミッションで作った my.cnf をダミーとして置いておく。作成も上書きも出来ないように。
  • /etc/mysql/ ディレクトリが存在しないことを確認する
  • /etc/sysconfig/ が mysql ユーザの権限がないことを確認する
$ ls -ltrd /etc/sysconfig/
drwxr-xr-x. 7 root root 4096 Sep 13 17:17 /etc/sysconfig/
  • extra fileとして /home/simainte/my.cnf がある場合はそれが root 0600 になっていることを確認する
  • /home/mysql/ に root 0600 で my.cnfを配置しておく。または /home/mysql/ を削除する

根本対応

パッチはまだない。mysqld_safe で shared_libraryを読み込まないという手もある。