読者です 読者をやめる 読者になる 読者になる

fluent-plugin-ping-messageプラグインを最新のを入れるとtd-agentがunstable versionになるためバージョン指定する話

これは何

https://rubygems.org/gems/fluent-plugin-ping-message/ という Fluentd の plugin を最新化すると、同時に td-agent 本体も unstable な最新の 0.14 系にあがってしまい、ログ転送がたまにできなくなる事象が発生する。 その対策。

原因

この現象はpluginの依存するfluentdのバージョンが指定されているので、gemで最新のplugin version1.0.0が入るとfluentdも v0.14が必要になり、強制的にあげられてしまうため。 参考: https://github.com/tagomoris/fluent-plugin-ping-message

対策

ansibleのtasksで書くならこんな感じ。-vで指定する。

- name: add fluent-plugin-ping-message
  shell: td-agent-gem install fluent-plugin-ping-message -v {{ FLUENT_PLUGIN_PING_MESSAGE_VERSION }}

stableなtd-agentのバージョンは? どこで確認する?

http://www.fluentd.org/download

  • stable v0.12 系
  • experimental version が v0.14となっている。

td-agent本体 version確認方法

$ which td-agent
/usr/sbin/td-agent
$ td-agent --version
td-agent 0.12.29

plugin version確認方法 

td-agent-gemで入れているので listコマンドから確認

$ td-agent-gem list  | grep ping
fluent-plugin-ping-message (1.0.0, 0.2.0)

左が新しいもの、右が古いversionっぽい。gemで入れると古いバージョンも残るらしい。 $ td-agent-gem list | grep ping fluent-plugin-ping-message (0.2.0)

入れなおし方法

  • sudo yum remove td-agentを実行する
  • rm -rf /opt/td-agentを実行して残存プログラムを完全消去する。これをやらないと/opt/td-agentにプログラム本体がいるっぽく yumで再インストールしてもversionが新しいプログラムのままになる。
  • td-agent再インストー

実験

plugin入れる前

$ td-agent --version
td-agent 0.12.31

入れてみる

$ sudo  td-agent-gem install fluent-plugin-ping-message
Fetching: strptime-0.1.9.gem (100%)
Building native extensions.  This could take a while...
Successfully installed strptime-0.1.9
Fetching: serverengine-2.0.4.gem (100%)
Successfully installed serverengine-2.0.4
Fetching: msgpack-1.1.0.gem (100%)
Building native extensions.  This could take a while...
Successfully installed msgpack-1.1.0
Fetching: fluentd-0.14.13.gem (100%)
Successfully installed fluentd-0.14.13   ★ここで fluentd 0.14 を入れている。
Fetching: fluent-plugin-ping-message-1.0.0.gem (100%)
Successfully installed fluent-plugin-ping-message-1.0.0
Parsing documentation for strptime-0.1.9
Installing ri documentation for strptime-0.1.9
Parsing documentation for serverengine-2.0.4
Installing ri documentation for serverengine-2.0.4
Parsing documentation for msgpack-1.1.0
Installing ri documentation for msgpack-1.1.0
Parsing documentation for fluentd-0.14.13
Installing ri documentation for fluentd-0.14.13
Parsing documentation for fluent-plugin-ping-message-1.0.0
Installing ri documentation for fluent-plugin-ping-message-1.0.0
Done installing documentation for strptime, serverengine, msgpack, fluentd, fluent-plugin-ping-message after 8 seconds
5 gems installed
$ td-agent --version
td-agent 0.14.13

haproxy設定の自分メモ(redisのrevproとして)

これは何

redis+sentinelの前段にhaproxyを置いてクライアントがあんまりnode poolを意識しなくてもよさそうな感じにしたい。 devだけで適用して本番には適用していないので甘いところはあるかも。

方針

redis slaveにgetを負荷分散したりするほど負荷は高くない系に使えるかも。 常にmasterに接続しに行き、slaveは待機系。

設定ファイル

ansible templateの形。

global
  {# chroot内で動いているため/dev/logへアクセスできない。そのためUDP経由でrsyslogにログを渡す。-#}
  log         127.0.0.1 local2
  chroot      {{ HAPROXY_JAIL_DIR }}
  user        {{ HAPROXY_USER }}
  group       {{ HAPROXY_GROUP }}
  daemon
  {# maxconn: redisで設定しているものより大きければよい。このレイヤでは特に制限はかけない。 -#}
  maxconn     10000

{# stats: haproxyのステータスを取れるようにするための設定 -#}
listen stats 
  {# bind: ポート9000への外部からの経路はないが念のためback側からのみ疎通可能としておく。-#}
  bind :9000 interface eth0
  mode http
  stats enable
  stats uri /haproxy_stats 
  {# refresh: stats画面の自動リフレッシュを有効にする -#}
  stats refresh 10    

defaults
  mode                    tcp
  log                     global
  option                  dontlognull
  {# retries: バックエンドサーバへ接続失敗した時の再試行回数-#}
  retries                 3
  {# timeout queue: maxconnを超えたリクエストはキューに入る。そのキューに入った接続を開放するまでの時間。そんなに待たせても意味が無いのであまり大きな値じゃなくてよい。 -#}
  timeout queue           10s
  {# timeout connect: haproxyのbackendへの接続のタイムアウト。近いネットワークにいれば基本的に短い時間で接続できるはず。 -#}
  timeout connect         5s 
  {# timeout check: コネクションが確立したあとの追加のヘルスチェックのタイムアウト。これに時間がかかるということはラグの大きなサーバなので、長い時間待つ必要はない。-#}
  timeout check           5s
  {# timeout client-fin/server-fin: 正しく接続断しなかった場合に切る(こちらからFIN送信したがクライアントがFINを送ってこなかった場合)。FIN_WAIT状態が続くのを防ぐ。 -#}
  timeout client-fin      10s
  timeout server-fin      10s

{# その他入れない設定について。いれるのが推奨のようなので要検討。
* timeout client: 非活性なクライアントからの接続を切る設定。redis設定に合わせて設定しない。 
* timeout server: haproxyから非活性backendへの接続を切る時間。redis設定に合わせて設定しない。 
-#}


frontend  main
  bind *:5000
  default_backend             myredis

backend myredis
  {# balance: どれか1台だけがコネクションを受け付ける設定(first)。id設定があれば一番値が小さいもの。なければリストの1番上から優先される。負荷分散よりも1台のmasterにキャッシュがのることを優先する。 -#} 
  balance    first
  {# 通常時のヘルスチェック間隔はredisのマスター昇格のタイムスケールにあわせて秒単位でよい。haproxyのreload直後などでヘルスチェックをしていない場合には即座に行う(fastinter)。-#}
  {% for srv in HAPROXY_BACKEND_LIST -%}
  server  redis{{ loop.index }} {{ srv }} check inter 1s fall 2 rise 1 fastinter 10ms
  {% endfor %}

  option tcp-check
  tcp-check connect
  tcp-check send info\ replication\r\n
  tcp-check expect string role:master
  tcp-check send QUIT\r\n
  tcp-check expect string +OK

ちなみに rsyslog設定のansible taskはこんな感じ

# haproxyのログ出力のためのrsyslog設定
- name: enable UDP log acceptance for rsyslog for haproxy 
  lineinfile:
    dest: "/etc/rsyslog.conf"
    line: "{{ item }}"
  with_items:
    - "$ModLoad imudp"
    - "$UDPServerRun 514" 
    - "local2.* {{ HAPROXY_LOG_DIR }}/haproxy.log"

redis設定について自分メモ

これはなに

redis設定をした時の検討項目。 devで設定したのみでまだ本番で使っていないのであまいところはあるかも。

設定diff

以下は redis-3.2.8 に同梱されていた設定ファイルとplaybook template とのdiff。

diff /tmp/redis.conf roles/install_redis/templates/redis.conf.j2
1c1,3
< # Redis configuration file example.
---
> # USAGE: {{ item.USAGE }}
> # Redis configuration file.
> # This configuration is based on redis-3.2.8 default configuration file.
61c63,64
< bind 127.0.0.1
---
> {# bind: 特に認証はかけない。やるならサーバが居るネットワークセグメントごとに裏からのみ疎通できるようにするなどの設定をいれる。 -#}
> # bind
80c83,84
< protected-mode yes
---
> {# protected-mode: キャッシュサーバはインターネットに直接露出しなければ切っておいてもよいかもしれない -#}
> protected-mode no
84c88,89
< port 6379
---
> {# port: 同一サーバ内に別ポートで複数インスタンスを立ち上げることができるようにしておきたい -#}
> port {{ item.PORT }}
93c98,99
< tcp-backlog 511
---
> {# tcp-backlog: これと一緒にsomaxconnもsysctlで設定しておく必要がある。TCPの接続要求を格納するキューの最大長なので、front系サーバapacheがある程度詰まっても大丈夫な値にしておくのがよさそう -#}
> tcp-backlog 2500
104a111
> {# timeout: idle状態のコネクションはタイムアウトさせない(デフォルト設定)。アプリケーションが側できちんと切断処理がされていれば問題にならないはず-#}
127a135
> {# daemonize: 直接redis-serverコマンドにこの設定ファイルを食わせて起動した場合にはデバッグのためにdaemonize noでよい。systemctlで起動した場合にはこの設定に関わらずデーモン化される -#}
150c158,159
< pidfile /var/run/redis_6379.pid
---
> {# pidfile: 一応設定しているが、systemdではpidファイルは不要 -#}
> pidfile /var/run/redis_{{ item.PORT }}.pid
163c172,173
< logfile ""
---
> {# logfile: redisユーザに権限があるディレクトリにログを吐くようにしておく。ローテートも忘れずに。redisはログを吐くごとにファイルを開き直すのでSIGHUPなどは不要。 -#}
> logfile "{{ REDIS_LOG_DIR }}/redis.log"
177a188
> {# database: keyspaceが独立したdatabaseを何個にするか。使えるDatabaseがの数が大きくてもデフォルトは0が使われるので細かい値はなんでもよさそう。dev, productionとかで使う用途を想定しているみたい。-#}
201c212,216
<
---
> {# save: redisが死んでて復旧した時にRDBには古いデータが残っている。しかしexpireは実時間基準なのできちんと古いデータは消えておいてくれる。
> RDBを取る時に親プロセスがやるのは子プロセスをforkさせるだけなので、親インスタンスにdisk I/Oが発生して待ちになることはないとのこと。あまりにもデータが大きいもしくはCPUがいまいちな場合にはforkに時間かかるのでclientへのレスポンス遅れることもあるらしい。
> RDBの方がAOFをよりも起動が早く、データサイズも小さいのがメリット。マスタデータはredisには無ければ厳密に永続化を考えなくても良い。パフォーマンスが落ちない程度に使う方針。
> 設定はデフォルトで問題なさそうならそのまま。
> -#}
219c234,235
< stop-writes-on-bgsave-error yes
---
> {# stop-writes-on-bgsave-error: persistentが止まるよりもwriteが止まるほうが不都合。TODO 適切な監視はほしい。 -#}
> stop-writes-on-bgsave-error no
224a241
> {# rdbcompression: 多少CPUを使っていても圧縮しておいてくれた方が良い。あまりにCPU不可が高くなりそうなら変えても良い。 -#}
233a251
> {# rdbchecksum: 10%程度の性能劣化はあるがRDBファイルの破損の検知は入れたままでもよさそう。 -#}
247c265,266
< dir ./
---
> {# dir: ファイル名はデフォルトで良いが、保存先は適切なpermissionの場所に配置しなければならない。-#}
> dir {{ REDIS_DATABASE_DIR }}
265c284,288
< # slaveof <masterip> <masterport>
---
> # slaveof <masterip> <masterport>
> {# slaveof: 設定に書かないでDBと同じようにコマンドで指定するのもあり。ただしmysqlの場合にはchange master toではその設定がファイルに保存される。redisの場合には設定に書いてないと再起動時に消えてしまうと思われる。意図せず消えてしまうか、意図しないmasterを向いているかで比較的後者の方が事故が少ないと考えてファイルに記載する。原則としてシステムに組み込むときにはmasterノードがどれか確認してから組み込むのがよい。 -#}
> {% if REPL_NODE=="slave" %}
> slaveof {{ REDIS_MASTER_NAME }} {{ REDIS_MASTER_PORT }}
> {% endif %}
284a308
> {# slave-serve-stale-data: レプリケーション遅延で多少古いデータが帰ってしまったとしてもエラーを返すよりマシかもしれない(デフォルト) -#}
300a325,326
> {# slave-read-only: masterとの再同期によりslaveのみに保持されたデータは削除されるのでslaveに一時的に書き込みたいデータを書いておく用途に使える。特に使いたい理由がなければreadonlyのほうがよい(デフォルト)。
> -#}
414c440,441
< slave-priority 100
---
> {# slave-priority: 基本的には変更しないが、仮にmasterにしたくないslaveを作ることになったらansible EXTRA_VARSで0に設定できるようにしておく。-#}
> slave-priority {{ REDIS_SLAVE_PRIORITY | default("100") }}
511a539
> {# maxclients: 十分に大きいのでデフォルトのままでよい。pconnect使うならそれを意識して増やしておいたほうがよい。コネクションの数の監視も必要だろう-#}
537a566,570
> {% if ENVIRONMENT == "production" -%}
> maxmemory {{ item.MAXMEMORY }}
> {% else %}
> maxmemory 1G
> {% endif %}
592c625
<
---
> {# appendonly: redisにはマスタデータは乗らなければ永続化より性能を重視してOffにしておく。 -#}
623,624c656,657
< appendfsync everysec
< # appendfsync no
---
> # appendfsync everysec
> appendfsync no
834a868
> {# slowlog-log-slower-than: デフォルトでも秒に直すと0.01秒なので十分小さいのでそのままでよい。-#}
838a873
> {# slowlog-max-len: ここで設定した以上古いログは消えてしまう。まずはデフォルトで良い。あとで値を上げたければCONFIG SETコマンドを用いて設定できる。ログを見るためにはSLOWLOG GETコマンドを用いる -#}
905a941
> {# notify-keyspace-events: TODO 何かに使えそう。更新されたらPUBされるので他のサーバが更新を検知できる。サーバリストなど。PUBされた時にSUBしているサーバが接続していなければ受け取れないので注意が必要。pub/subを使いつつ、定期的に値を見直すなどを使えば信頼性をあるていど担保できるかもしれない。 -#}

nginxによるgzip圧縮について【技術メモ】

これは何

nginxでproxyするときにgzip圧縮してレスポンスする方法を学んだのでメモ書き。 nginx versionは 1.11.10。

動作確認

レスポンスヘッダに以下のものが含まれる

  • Vary: Accept-Encoding
  • Content-Encoding: gzip

設定内容

  • gzip_buffers 1000 64k ;   
    • 配信する最大サイズと対応させる。
    • 「マスタリングNginx」によれば、bufferが足りないと巨大なファイルは途中で切れてしまう現象が発生するとのこと。デフォルトだと(確か)128kまでしか圧縮できない。
    • 実際に使う分だけそのとき割り当てられる。
  • gzip_types
    • text/html はデフォルト。他のmime typeに対して使うなら追加する。
  • gzip_proxied any;
    • プロキシしているレスポンスについても必ず圧縮をかける。
  • gzip_vary on;  
    • Accept Encoding に gzip入れていないものについては別のキャッシュが使われる
  • gzip_comp_level;  
    • スマホなどで見ることも多い場合は基本は圧縮したほうがよい。「マスタリングNginx」によれば圧縮速度とサイズのトレードオフでバランスのとれた圧縮は4か5。圧縮にさけるリソースはそこまでないと考えれば1とか。(1でも9でも圧縮率には大差ないという情報も)。
  • gzip_disable msie6; 
    • msie4 ~ 6はAccept Encodingを送ってくるがちゃんとgzipを扱えないことがあるという情報も。msie6はIEのver 4~6に対応したエイリアスっぽい。一応入れておくほうがよさそう。

メモ

配信サーバの画像のgzip圧縮しようかと思って調べたけど、そもそもjpegは圧縮されたフォーマットだったのだった。 結局使わなかった設定。

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