物欲メモ

  • このエントリーをはてなブックマークに追加

最近、これが欲しいっ!という物欲が無いけど、まぁ欲しいと言われれば欲しいかも思うものをメモ。

テレビ(KJ-55X9500E)

今使ってるの10年くらい前のFullHDのテレビで別に困ってないけど、55インチにしても横幅殆ど変わらないのと、4Kにしても今のやつと省電力が変わらないっぽい。
Huluは解約しちゃったけど、Amazon primeがテレビから直接見れるのは良いかも(AppleTV操作しづらいし..)

オーブンレンジ

今使っているやつは学生の時から使っている2万円もしなかったやつで、もう17年以上は使っているわけです。それでも壊れてはいないし、グラタンもクッキーも現役で作れます。

今の不満点はワット調整が出来ない。

なんだかんだで新しい方がスチームの機能があったり、高温でパンが焼けたりと、技術の進歩を実感出来そう。

どのメーカーのものを買えばいいのか結局わからない。

パソコン

LG gram が良さそう。今の開発PCはメモリが8GBしか無い。LG gramはカスタムでメモリ16GBまで出来る。

そして軽いのと、バッテリーが十分に持つというのがよさそう。

13インチか14インチ。

カメラのレンズ

今持っている単焦点レンズがF1.8/50mm。APS-Cなので75mm換算。

こういう変態レンズが1つあると便利っぽい。
https://www.sigma-global.com/jp/lenses/cas/product/art/a_18_35_18/

いがいとあった。

GKEでMount情報がリソースリークする

  • このエントリーをはてなブックマークに追加

GKEでcronJobを使っているときに、このようなエラーが出て実行が止まってしまいました。

1
MountVolume.SetUp failed for volume "service-account" : mount failed: exit status 1 Mounting command: systemd-run Mounting arguments: --description=Kubernetes transient mount for /var/lib/kubelet/pods/cd987559-252d-11e8-8bea-42010a920fe9/volumes/kubernetes.io~secret/service-account --scope -- mount -t tmpfs tmpfs /var/lib/kubelet/pods/cd987559-252d-11e8-8bea-42010a920fe9/volumes/kubernetes.io~secret/service-account Output: Failed to start transient scope unit: Argument list too long

こちらのIssueにWorkaroundがあり、ノード(GCE)上で次のコマンドを打つと解決します。

問題の状態を確認。なお上記が発生した時は2^17くらいの数まで溜まっていました。

1
systemctl list-units --all | wc -l

次のコマンドで綺麗になります。

1
systemctl daemon-reload

Systemdの問題か?

systemdの問題で、このPRで直っていると思います。これが取り込まれているのがv237です。

私の手元のGCEのsystemdはv232でした。
新しいk8sクラスタを作るとどのバージョンになるのかはまだ確認していないです。

参考

SSHが切断させるとdocker processが残る件について

  • このエントリーをはてなブックマークに追加

SSH Loginしたサーバ上でdocker runでプロセスを動かしている時に、sshのconnectionが切れるとdocker processが動きっぱなしになる現象が発生しました。

具体的には次のような感じです。

1
2
3
4
5
6
7
8
9
10
ssh server

[on server]
bash hoge.sh

[hoge.sh]
docker run --rm -it xxx ruby fuga.rb

[fuga.rb]
loop { sleep 1 }

通常であればsshが切断されると全てのプロセスが終了するはずですが、何故かdocker processが残ってしましました。これは、次のようにdocker runの実際のプロセスがdockerdの下にぶら下がっているからだと思います。hoge.shは終了しますが、docker-containerd-shimのtreeの方は終了しません。fuga.rbの方にはシグナルは何も飛んできませんでした。

1
2
3
4
5
6
7
8
9
ssh
bash
hoge.sh
docker run ...

/usr/bin/dockerd
docker-containerd
docker-containerd-shim
ruby fuga.rb

特殊なシグナルは飛びませんがhoge.sh自体は終了するので、hoge.shに次のコードを仕込んで解決しました。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
cidfile="$(mktemp --dry-run "/tmp/nodelist.tmp.XXXXXXXXXX")"
function on_exit() {
if [ -f "${cidfile}" ]; then
cid="$(cat ${cidfile})"
if [ -z "${cid}" ]; then
return
fi
docker inspect ${cid} 2>/dev/null 1>/dev/null
if [ $? -eq 0 ]; then
docker kill ${cid} -s QUIT
fi
rm -f "${cidfile}"
fi
}

trap "on_exit" EXIT
1
docker run --rm -it --cidfile="${cidfile}" xxx ruby fuga.rb

trapしなくても普通にdocker runの後のexit codeを見ても良かったかな 🤔

GKEでDatadogを使う方法

  • このエントリーをはてなブックマークに追加

最近はAWSだけでなくGCPも使っています。

GCPのMonitoringにはStackdriverがあり、k8sのMonitoringはPrometheus+Grafanaが定番です。

とはいえアラートを含めたシステムのモニタリングツールは何種類も運用したくありません。出来れば1つにまとめたいところです。いまの会社ではDatadogを使っているので、GKE(1.8)+Datadogをやってみます。
またアプリケーションからcustom metricsを送りたいので、その対応も行います。

Datadogのセットアップ

  • Datadogのアカウントを取得します。
  • GCPのサービスアカウントを作成します(権限はProject/閲覧者あたり)
  • 連携させます

これで主要なSystem Metricsは連携され、いくつかのダッシュボードも見れるようになります。
これはAWSでいうところのRDS等のMetricsを見れるようにするのと同じ感じで、まだAgentは入れていません。

GKEのクラスタにAgentを入れる

ここにManualがあります

Agentはノード(GCE Instance)単位で入れるため、DaemonSetとして扱います。ただ、↑のマニュアルに書いてある記述は今時点では1.7の方法なので、1.8向けに書き直します。またAPIキーはManifestに直書きする事はせずに、Secretから取得するように直します。

修正前(マニュアルのまま) APIキーは伏せてます

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
name: datadog-agent
spec:
template:
metadata:
labels:
app: datadog-agent
name: datadog-agent
spec:
containers:
- image: datadog/agent:latest
imagePullPolicy: Always
name: datadog-agent
ports:
- containerPort: 8125
name: dogstatsdport
protocol: UDP
env:
- name: DD_API_KEY
value: ****
- name: KUBERNETES
value: "yes"
- name: DD_KUBERNETES_KUBELET_HOST
valueFrom:
fieldRef:
fieldPath: status.hostIP
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "250m"
volumeMounts:
- name: dockersocket
mountPath: /var/run/docker.sock
- name: procdir
mountPath: /host/proc
readOnly: true
- name: cgroups
mountPath: /host/sys/fs/cgroup
readOnly: true
livenessProbe:
exec:
command:
- ./probe.sh
initialDelaySeconds: 15
periodSeconds: 5
volumes:
- hostPath:
path: /var/run/docker.sock
name: dockersocket
- hostPath:
path: /proc
name: procdir
- hostPath:
path: /sys/fs/cgroup
name: cgroups

修正版

  • k8s1.8ではDaemonSetはapps/v1beta2になってました
    • apps/v1beta2ではspec.selectorが必須です
    • spec.selectorで指定するやつはspec.template.metadata.labelsと完全一致させないと怒られました..
  • 他のpodからcustom metricsをdogstats経由で送信したいため、8125/UDPをHost(ノード)に公開します
  • Traceの機能も同様に他のpodから使いたいため8126/TCPをHost(ノード)に公開します
  • API_KEYはSecretから取得します。作成コマンドは以下参照。
    • kubectl create secret generic datadog --from-literal=api_key=*****
datadog-agent.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
apiVersion: apps/v1beta2
kind: DaemonSet
metadata:
name: dd-agent
spec:
selector:
matchLabels:
app: dd-agent
template:
metadata:
labels:
app: dd-agent
name: dd-agent
spec:
containers:
- image: datadog/docker-dd-agent:latest
imagePullPolicy: Always
name: dd-agent
ports:
- containerPort: 8125
hostPort: 8125
name: dogstatsdport
protocol: UDP
- containerPort: 8126
hostPort: 8126
name: ddtracedport
protocol: TCP
env:
- name: API_KEY
valueFrom:
secretKeyRef:
name: datadog
key: api_key
- name: KUBERNETES
value: "yes"
- name: SD_BACKEND
value: docker
- name: KUBERNETES_KUBELET_HOST
valueFrom:
fieldRef:
fieldPath: status.hostIP
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "250m"
volumeMounts:
- name: dockersocket
mountPath: /var/run/docker.sock
- name: procdir
mountPath: /host/proc
readOnly: true
- name: cgroups
mountPath: /host/sys/fs/cgroup
readOnly: true
livenessProbe:
exec:
command:
- ./probe.sh
initialDelaySeconds: 15
periodSeconds: 5
volumes:
- hostPath:
path: /var/run/docker.sock
name: dockersocket
- hostPath:
path: /proc
name: procdir
- hostPath:
path: /sys/fs/cgroup
name: cgroups

これをdeployします。

1
kubectl create -f datadog-agent.yaml

他のPODからCustom Metricsを送る場合

上図のようにPOD間通信になりますが、アプリが起動しているノード上のdd-agentと起動したいので、ノードのIP:Portで通信する必要があります。localhost:8125ではないです。

status.hostIPでノードのIPを取得して環境変数に設定できるので、アプリのManifestに次の記述を入れます。これで環境変数_DD_NODE_HOSTにノードのIPが入ります。

1
2
3
4
5
env:
- name: _DD_NODE_HOST
valueFrom:
fieldRef:
fieldPath: status.hostIP

公式のJava Clientであれば次のように環境変数からIPを取得し、Clientを初期化します。

1
2
3
4
5
statsd = new NonBlockingStatsDClient(
null,
StringUtils.defaultIfEmpty(System.getenv("_DD_NODE_HOST"), "localhost"),
8125,
null);

これでCustom Metricsを送信できるようになりました。

課金

Datadogは5ノードまで無料、コンテナの場合は1ノードあたり10コンテナまで無料で超過分は1コンテナあたり1ドル/月です。(1ノードあたりは18ドル(年間契約だと15ドル))

maven releaseする前にバージョンをbumpupする方法

  • このエントリーをはてなブックマークに追加

Single Moduleであれば手で書き換えれば良いのですが、Multi moduleだとparentのversionを書き換えてsub moduleのバージョンを書き換えてと、数が多いと手で作業するのは大変です。

何も指定しないreleaseはパッチバージョンが上がります。0.0.1 -> 0.0.2
minorバージョンを上げたい場合はrelease:update-versions を使えば任意のバージョンにする事ができます。

例えば次のコマンドを実行すると、各pomファイルのバージョンを0.2.0-SNAPSHOTに書き換えてくれるので、それをコミットするだけ。

1
mvn --batch-mode release:update-versions -DdevelopmentVersion=0.2.0-SNAPSHOT

参考: http://maven.apache.org/maven-release/maven-release-plugin/examples/update-versions.html

心が変われば

  • このエントリーをはてなブックマークに追加

昔、とあるゲーム会社の社長がこういう事を社内BLOGに書いていて、出展どこだっけかなと調べたのでそのメモ。いくつかパターンがあるっぽいです。

心 が変われば 態度が変わる。
態度 が変われば 行動 が変わる。
行動 が変われば 習慣 が変わる。
習慣 が変われば 人格 が変わる。
人格 が変われば 運命 が変わる。
運命 が変われば 人生 が変わる。

意識が変われば行動が変わる。
行動が変われば習慣が変わる。
習慣が変われば人格が変わる。
人格が変われば運命が変わる。
運命が変われば人生が変わる。

参考: http://crd.ndl.go.jp/reference/modules/d3ndlcrdentry/index.php?page=ref_view&id=1000071866

腸閉塞になったのでその記録

  • このエントリーをはてなブックマークに追加

先日腸閉塞になってしまいました。2回目なのですが、お医者さんに前回のことを聞かれたときに何も覚えていなかったので、今回はきちんと記録を残そうと思いました。

2/12日(月) こんにゃくを沢山食べる。夜にお腹が痛くなる。1分に1回激しい痛みが来ては引いての繰り返し。痛みの場所はおへその上あたり。小腸らしい。あと吐き気が凄い。痛みで殆ど寝る事ができない。
症状的に腸閉塞だなと感じました。

2/13日(火) 会社を休む。病院へ行く。近所の内科へ。ひとまずレントゲンを撮って貰い、腸閉塞である事が確定。絶食を宣言される。ポカリはOK。お薬として漢方薬を貰う。ツムラの大建中湯(ダイケンチュウトウ) 100番。痛みがちょっと治まる。
もし痛みがやばくなったら救急車を呼ぶか、痛みに余裕があったら東京消防庁のテレホンサービスで救急医療機関の案内をしてもらうことを薦められる。

2/14日(水) 痛みは無くなったけど、おならも便も出ないので午前半休で病院へ。もう1回レントゲンを撮る。まだ詰まっている状態である。様子を見ることに。(この時、下剤とか欲しかった..)
絶食宣言は続く。(が、午後出社したらバレンタインデーだったので会社にあったスイーツを食べてしまう)

2/15日(木) 普通に仕事する。便は出ない。社食を少しだけ食べてしまう。

2/16日(金) 普通に仕事する。便は出ない。おならは出た。社食を少しだけ食べてしまう。

2/17日(土) 病院に行く。再度レントゲンを撮って貰う。極度の便秘状態らしい。お薬として、便を軟らかくする薬と、下剤を貰う。下剤は寝る前に処方するものらしいが、昼間に使う。効果が出るのは8時間後〜12時間後らしいので、寝る前にサインがあるはず。だがしかし便は出ない。
食事はおかゆとかそーいうの。でもおかゆはまだ重いらしいのでもっと軽いヤツじゃ無いとだめらしい。なので社食食べるのダメだったみたい。

2/18日(日) 便が出る。下剤の他にも酵素ドリンクを使って便意を促した。食事は軽めのものを。

絶好調というわけでは無いですが、食事はしばらく気を遣う必要がありそう。

あと左耳後ろのリンパが凄く痛い。

mavenマルチモジュールで特定のsub moduleだけビルドする方法

  • このエントリーをはてなブックマークに追加
1
mvn compile -pl {module} -am
  • packageする時はcompileではなくpackageにすれば良い。
  • -pl--projectの省略形でモジュールを指定する。
  • -ama--also-makeの省略形でつけると依存サブモジュールも一緒に処理してくれる(commonモジュールとか)。付けないと、-plで指定したモジュールだけ対象にする。

傷口を広げる対処法

  • このエントリーをはてなブックマークに追加

人は当事者で居るよりも一歩引いて俯瞰して状況を観察した方が全体感を見ることが出来るので、エンジニア組織とは別に例を挙げて物語形式で書いてみます。

※この物語はフィクションです

様々な要素(組織や職業、人物など)を置き換えてみてください。

序章

Aさんはとある会社で働く営業マン、社会人になって15年が経ちました。彼の仕事は、お堅い会社の役員を相手に営業を行います。優秀だった同期のBさん、Cさんは一身上の都合により会社を去ってしまい、優秀な同期を失ったAさんはテンションが下がりながらも、これまで通り自分の仕事を続けています。

この会社は新卒採用は行っておらず、営業マンは中途採用のみです。昨年は退職したBさん、Cさんの代わりにDさん、Eさんの2人が新たに入社しましたが、BさんCさんほどの実力は備えておらず、重要顧客との相手はAさんが殆ど対応している状況です。
Dさん、Eさん両名の待遇はAさんと同じですが、彼らの営業スキルは会社の平均水準には達してはいません。何かしら別の理由で採用に至ったようですが、Aさんはそれを知りません。

1
2
3
4
5
6
7
[営業1課]
Hさん -> 営業1課の課長
Aさん -> 優秀な人材(在籍中)
Bさん -> Aさんの同期で優秀な人材(退職済)
Cさん -> Aさんの同期で優秀な人材(退職済)
Dさん -> 中途採用/実力は平均以下
Eさん -> 中途採用/実力は平均以下

第2章

半年ほど経ったところでAさんにも心境の変化が出てました。そろそろ自分も同期と同じ道を選択しようと考えたのです。その理由は、社内の環境が大きく変わってしまったことです。彼が入社した当時はBさん/Cさんといった優秀な同期と共に仕事をすることが出来ましたが、最近はそれが叶わなくなっている事が大きな原因のようです。

彼と同じ組織の営業マンである、Dさん、Eさんの普段の仕事を見てみましょう。A/D/Eさんの上司であるHさんも登場させてみます。

  • 9時AM チームの朝礼にて(参加者はH,A/D/E)
    • Hさん「今日はこれから重要な案件でAさんとN食品に行ってきます。16時頃に戻ってきますが、何かあったらきちんと私にメールかLINEで連絡を入れてください。」
  • 11時AM
    • PRRRR(お客様からの電話が鳴る音)
    • Dさん『はいもしもし? え?Hさんですか。今居ないっすね』
    • Dさん『じゃぁAさん? Aさんも居ないっす』
    • Dさん『え?緊急の用事っすか? でも今居ないのでどうしようもないっすね』
    • Eさん「緊急なら俺が対応するっすよー」
    • Eさん『お電話変わりました、M商事さんですね。なるほどー、提案書の内容の一部を変更して欲しいという事ですね。』
    • Eさん (まぁたいした変更でもないだろうし、重要そうなお客さんっぽいから今返事しておくか)
    • Eさん『かしこまりました、ではそのように変更して進めさせていただきますね。それでは失礼します』
    • Eさん (ついでに提案書を直しておいたぞ)
  • 16時AM
    • Hさん「ただいま戻りました。私が居ない間に何かありましたか?」
    • Dさん「いつも通りっすー」
    • Eさん「特に問題はありませんでした」

翌日

  • 9時AM チームの朝会にて
    • Aさん「今日は11時にN食品、15時にM商事さんに打ち合わせに行ってきます」
  • 9時10分AM
    • Aさん(提案書を印刷して持っていかないとな。あれ? ファイルの更新日が新しくなっているぞ?)
    • Aさん(提案書が書き換わっているし、しかも変更内容が法律で禁止されている事案じゃないか)
    • Aさん「誰かM商事向けの提案書を更新しましたか?」
    • Eさん「あ、昨日M商事から電話があって直して欲しいって言われたので直しておきました」
    • Hさん「昨日何も無いって言ったじゃないか」
    • Eさん「特にトラブルはありませんでしたよ。重要顧客っぽいのでその場で対応しましたし、提案書もきちんと更新していますよ。変更はたいしたものじゃなさそうでしたので」
    • Hさん「そういうの、ちゃんと相談や報告をして欲しいな..」
    • Hさん「M商事には私から謝罪しておくから、Aさんは提案書を直してものでM商事の打ち合わせに行ってくれるかね」
    • Aさん「これからN食品に行かないといけないので、修正する時間あるかな… 移動中に修正します」

第3章

そんな日が続き、HさんもAさんも重要顧客への対応がパツパツになって行き、特にAさんは2章のような日常に疲弊しているようです。それを見かねた営業2課のGさんは、「HさんもAさんも重要顧客への対応がパツパツで疲れているじゃないか。このままではいけない。」

『重要顧客への対応は通常の顧客とは異なり、打ち合わせの準備や接待なども大変なので、もっと負荷分散してみんなで行うべきだ。AさんもHさんも最近仕事に疲れているじゃないか。Dさん、Eさんも加わって頑張りましょう』

Dさん「重要顧客?まぁ敬語?使えるから問題ねっす。接待もまぁ出来るっしょー」

Eさん「そのとおりです、重要顧客への営業に行って沢山契約してきますね!!」

終章

後は何が起きるか、結末は自分で想像してみてください。

あとがき

営業部長「大変そうだから、人を採用したよ。紹介するぞ。Jくんだ。彼は営業経験は殆どないが、素晴らしい志を持っている。Aさん、彼に営業のイロハを教えてあげてくれ。Jくん、挨拶よろしく。」

Jさん「ちょりっす」

営業部長「あれ、Aさんは今日は体調不良で休みか。弛んでるな。」

クリティカルシンキング

表面的な事象を根本原因として捉えてしまう例を挙げてみました。根本原因を考察して問題解決を図る方法に、クリティカルシンキングという分野があります。批判的思考と訳される事が多いですが完全に誤訳だと思います。次の本は私が10年以上前に読んだ本(私が読んだのは第1版)ですが、思考法の1つを学ぶのにとても良い本だと思います。

Moshの再アタッチは出来ない

  • このエントリーをはてなブックマークに追加

回線状況が悪いときにSSHを使うとイライラするので、Moshを使っています。特に海外のホテルから作業する時はSSHだとブチブチ切れてしまう事が多いのでMoshを愛用しています。会社のBastionサーバにもMoshが入っています。

Moshを使っているときにMacがいきなり再起動しちゃったりすると、mosh-serverが残ってしまうときがあり、次のメッセージが出てしまいます。

1
Mosh: You have a detached Mosh session on this server (mosh [20257]).

screenのように再アタッチできないのかなと思ったら、セキュリティの理由によりそんな事は出来ないぜ!との事です。

そのため、素直に表示されたPIDをKILLしてもう1回再接続するしかないようです。

参考: https://stackoverflow.com/questions/17857733/how-do-i-reattach-to-a-detached-mosh-session