Windows10のWSLで開発環境を整える

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

サーバはLinux上で動かしたいけど、エディタはWindowsのものを使いたい。そんな環境を作ります。

まず、Windows10のストアからUbuntu18.04をインストールします。

ファイル共有

/etc/wsl.confで以下を設定します。
これはWindowsのドライブを自動でマウントしないようにする設定です。というのも、デフォルトパーミッションが777でやりとりされちゃうからです。あと、間違ってWSL側でWindowsのシステムファイルをrmしちゃうのも怖いので。

/etc/wsl.conf
[automount]
enabled = false

Windowsとファイル共有をするには、drvfsという形式でマウントしますが、これはドライブ単位でしかマウントできません。試しにsubstコマンドで仮想ドライブを作ってみましたが、エラーが出てmountできませんでした。
そういうわけで、Windows側のパーティションをちょっといじって、50GB程度の共有用のドライブを作ります。

/etc/fstabに自動マウントする設定を入れます。metadataは必須、uidgidは自分のユーザーを指定。umaskを設定することで、パーミッション755でやりとりされるようになります。

/etc/fstab
E: /mnt/wsl drvfs defaults,metadata,uid=1000,gid=1000,umask=022 0 0
dfの結果
$ df -h
Filesystem Size Used Avail Use% Mounted on
rootfs 217G 75G 142G 35% /
none 217G 75G 142G 35% /dev
none 217G 75G 142G 35% /run
none 217G 75G 142G 35% /run/lock
none 217G 75G 142G 35% /run/shm
none 217G 75G 142G 35% /run/user
E: 49G 342M 49G 1% /mnt/wsl

GHQのディレクトリをここに設定することで、WindowsとLinux両方でGitできるし、直接ファイルもいじれるし快適です。今はここにいろいろなレポジトリをcloneして、VSCodeやIntelliJ、EmEditorで編集しています。

参考:

Beep音がうるさい

~/.inputrcで以下を設定します。

set bell-style none

Windowsストア版のSlackを使うとプチフリする

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

SlackのクライアントをWindowsストア版を使ったら、スタートメニューなどの表示が非常に遅くなりプチフリーズ状態になりました。

UWP(ユニバーサルWindowsプラットフォーム)のアプリ全てを巻き込んでフリーズするようです。
UWP版じゃないものを使えば大丈夫でした。

ひどい目にあった.. 😑

LG GRAM 購入

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

Windows10のノートPCを購入しました。LgGramという機種です。

購入の決め手は、次の3点です。

  • メモリが16GB以上積めること
  • バッテリーが長持ちすること
  • 軽いこと

お値段は 155,300円から12,000円引いてもらって、143,300円。これにポイントが10%がついて14,330ポイントなので、実質 128,970円 です。ヨドバシで買いました。

メモリ

この機種は、増設メモリが1スロットあり、SSDも1つ増設することができます。そのため、16GBのモジュールを追加すれば24GBにすることができます。SSDも256GBに加えて、1TBなり2TBなり追加することができます。公式の増設サービスがありますが、それだとメモリ16GBのモジュールは扱っていないので、自分で分解して増設しました。

バッテリー

公称値は27時間となっています。実際は27時間は持ちませんし、増設することでその分消費電力が増えますがそれでも10時間は持つのではないでしょうか。
今仕事で使っているMacが3時間くらいしか持たないので、全然良いと思います。

軽い

1キロ未満。超軽いです。バッテリー入っているのかなと思うくらい軽いです。

だめなところ

キーボードがちょっと打ちにくいです。キーの大きさがすべて同じではなく、右側の記号のところが狭くなっています。文章書くのには困りませんが、プログラムを書くときは結構戸惑います。

増設しよう

※サポート対象外になりますので自己責任で。

増設のために購入したもの。ドスパラで買いました。SSDはWDではなくSAMSUNGにしましたが、理由としてはスペックシートを見た感じでは消費電力が低かったからです。

  • CFD D4N2400CM-16G (DDR4 PC4-19200 SO 16GB) / 19,780円
  • SAMSUNG 860EVO MZ-N6E1T0B/IT(M.2 2280 1TB) / 31,800円

SSDはSATA接続のものを買いました。NVMeもサポートしていますが、その場合はBootDiskが左右逆になります。元々のDiskがSATAなので、NVMeにすると既存のSSDからコピーしないといけなくて面倒なのと、SSDの方が消費電力が半分くらいなのでSATAのままです。

カバーの開け方はこちらの動画を参考にしました。

分解をします!

買った増設物

パチッとはめ込みます

こんな感じでパワーアップしました。

メモリ24GB

SSD1TB追加

Diskの性能を測ってみる

なんか書き込みが遅い…。けどまぁいいか。

rsyslogで処理が詰まらないようにする

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

auditdのログをrsyslogでリモートホストに転送しようとしたら、ちょっとログが流れるだけでSSHが出来なくなったりとrsyslogが詰まるせいで、auditdも詰まり、プロセスが起動できない状態になりました。

出力プラグインがメッセージを提供できない場合、メッセージはI先行のメッセージキューに保存されます。キューがいっぱいになると、いっぱいでなくなるまで入力がブロックされます。これにより、ブロックされたキューを使用して新しいメッセーがログに記録されることが回避されます。個別のアクションキューが存在しないため、SSH ロギングが阻止され、SSH アクセスが阻止されるなどの重大な問題が発生することがあります。したがって、ネットワークを介して転送される、またはデータベースに転送される出力専用アクションキューを使用することが推奨されます。

https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/system_administrators_guide/s1-working_with_queues_in_rsyslog

auditd自体の設定は何を記録したいかによるので、この記事では設定は省略して、rsyslogで処理が詰まらなくなる設定を紹介します。

Redhatのページによると、Mainキューで一度全てのログを受けて、ルール毎にActionキューに配置されて、出力されます。各キューにはワーカースレッドがあります。デフォルトの設定は、MainキューがFixedArray queue(10000), ActionキューがDirect queuesです。

/etc/rsyslog.conf

こんな感じに設定しました。
基本はインメモリーのキューを使います。
Mainのキューのサイズを10万に設定。Disk補助も使います。インメモリキューのサイズが5万を超えるとDiskを使い始めます。(Diskは遅いので差分の5万はメッセージバースト用です)。サイズが2万に下がるとDiskを使うのをやめます。

Actionも基本的には同じ戦略です。1桁少なくしています。こちらは確実に保存(転送)をしたいので、shutdown時にはDiskに書き出すようにして、Retryも延々と続ける設定です。

/etc/rsyslog.conf
$WorkDirectory /var/lib/rsyslog
$MainMsgQueueType LinkedList
$MainMsgQueueSize 100000
$MainMsgQueueHighWatermark 50000
$MainMsgQueueLowWatermark 20000
$MainMsgQueueSaveOnShutdown on
$MainMsgQueueFilename main_msg_pool
$MainMsgQueueMaxFileSize 10485760

$ActionQueueType LinkedList
$ActionQueueSize 10000
$ActionQueueHighWatermark 5000
$ActionQueueLowWatermark 2000
$ActionQueueFileName remote_spool
$ActionQueueMaxFileSize 10485760
$ActionQueueMaxDiskSpace 1g
$ActionQueueSaveOnShutdown on
$ActionResumeRetryCount -1

/etc/audisp/plugins.d/syslog.conf

active = yesにする事でaudit logをrsyslogで流すようにします

/etc/audisp/plugins.d/syslog.conf
active = yes
direction = out
path = builtin_syslog
type = builtin
args = LOG_INFO
format = string

/var/log/messagesにaudit logが流れてしまう

audit.logにlocal6を使っている場合、

/etc/rsyslog.conf ではこんな感じの設定になると思います。

/etc/rsyslog.conf
# auditd audit.log
$ModLoad imfile
$InputFileName /var/log/audit/audit.log
$InputFileTag tag_audit_log:
$InputFileStateFile audit_log
$InputFileSeverity info
$InputFileFacility local6
$InputRunFileMonitor

$template audit,"%timegenerated%,%syslogtag%,%hostname%,%msg%\n"
local6.* @@myhost.internal:514;audit
:syslogtag,contains,"tag_audit_log:" ~

# フィルタに local6.none を入れる
*.info;mail.none;authpriv.none;cron.none;local6.none /var/log/messages

↑のフィルタに local6.none を入れて、
/etc/audisp/plugins.d/syslog.confLOG_LOCAL6を入れます。

/etc/audisp/plugins.d/syslog.conf
active = yes
direction = out
path = builtin_syslog
type = builtin
args = LOG_INFO LOG_LOCAL6
format = string

あとは、rsyslogとauditdを再起動すればOKです。

参考

Redhatのページがとてもわかりやすいです。

JJUG CCC 2018 Springでレビューに関する話をしました

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

発表スライドが映らなくてめっちゃ焦りました。スタッフの人がとても親切で何種類かの変換コネクタを用意してくれたりと、とても親切で助かりました。

お陰様で満席で立ち見も出て、見に来てくださった方々ありがとうございます。

私はオタクなのでとても早口になってしまい、またマイクも上手く使えずに反省点が多かったなと思います。(資料の枚数が少ないと、ゆったり喋るんですがあのペースで話さないと間に合わなかったorz)

何事に置いてもそうなのですが、対象となる組織、文化、背景、状況が異なれば大事にするべき観点は異なります。制度や仕組み、プログラムやパラメータなど、そのまま持っていくのでは無く、エッセンスを抽出して咀嚼してから必要な養分を取り込むという事が大事です

質問に関する補足です

その前に、
スライドに社名をいくつか出していますが、宣伝目的ではなくて、一般的な広告システムと違って組み合わせ最適化のフェーズ(Allocation)があるから処理が大変なんだよという事を言いたかったのです。宣伝はしてないです!!

レビューの観点には冪等性も大事やぞという指摘

その通りだと思います!!

撤退可能ってどういう事?

ロールバック可能な単位で設計やリリースをしましょうという事です。

具体的には、一度投入して問題があった時に例えば外部リソース(DB)の値を変に上書きしちゃって戻すに戻せないとか、ぶっつけ本番+お客さんにプレス打って戻しづらいとかが無いようにする事です。

ロールバック出来る事と、お金(リソース投入)でスケールする事の2つが担保されていると、失敗時の戦術も増え、比較的気軽に投入できます。

AtomicLongは何故問題なの?

LongAdderというクラスがあるので、そちらを使って欲しいのです。前提としては、readとwriteの比率のうち、writeが圧倒的に多い場合です。

パフォーマンスカウンタを例にすると、Writeは大量に発生しますが、Readは定期的な吸い上げで良いのでそういうケースに効果覿面です。

ELBの後ろにnginxがあるのは何故?

いくつか理由があります。

  • 同じドメインで静的コンテンツをいくつか配信している
  • Gzip処理をアプリケーションの外に逃がすため(アプリケーションの本来の責務ではないため)
  • もぐら叩き対策

もぐら叩きは私が勝手に名付けた現象です。負荷が高まったときにアプリケーションサーバのHTTPスレッドが枯渇すると、ELBのヘルスチェックにも応答が出来なくなってしまいます。アプリケーションサーバは2つのPortをListenしており、ServiceポートとAdminポートがあります。また、ServiceポートだけをInstanceの外部に公開しています。

ELBのヘルスチェックに失敗すると、ELBからInstanceが外れてしまいます。只でさえリソースが足りないのにELBから外れるとさらに状態がきつくなります。複数のInstanceがELBから抜ける、入るを繰り返し行うようになります。このようにシステム全体がなかなか復帰しない状態に陥っていまう事が多々ありました。

これを避けるために(被害を少しでも抑えるために)、

  • NGINXのレイヤーでヘルスチェックを終えてしまう
  • もしくはnginxのreverse proxyでadminポートのpingを叩くようにします。(adminの1つのendpointだけを外に公開する)

もちろん超高負荷時にはHTTPスレッドが枯渇している事に変わりはないので、アプリケーションサーバ側のバックログにも積めない状態になればnginxの408エラーが発生します。ただし、ELBから抜けることは無いので全体の処理量はそのままを維持することが出来、結果的に早く復帰します。

これを個人的にもぐら叩き対策と呼んでいます。

自前実装するのはなんで?

ソースが公開されているものは多いですが、遅かったり、該当のケースに適用しづらいのが殆どです。無ければ作れば良いじゃんの精神です。

例えばJavaのcommonsの実装なんて遅いので、そういうのは自前で実装し直します(主に僕の隣に座っている人が)。昔、”よくこれでcommonsを名乗れるな”と過激な発言をしていた事もありますが、もう大人になりました。

参考↓

ガチレビューするとリリース遅くならないの?

遅くはなりますが、参考までに結構前の資料ですがリリース頻度のグラフです。

レビューが細かすぎない?

オンライン処理、バッググラウンド処理、リクエストの最初の1回だけ、Filterや予測処理のループの中なのかで、ある程度指摘するレベルを変えています。
また局所最適化と思われるかもしれませんが、こういう細かい内容が積み重なってボディーブローのように性能を引きずります。それとは別にアルゴリズムの改善や、アーキテクチャの変更は随時行っています。そういう話はJavaとは関係ない話なのでセッションの中では省きました。

この内容で収益を支えるってどういうこと?

広告業界には、トラブル時に3倍返しという良くわからない習慣があります。(目先の謝罪よりも貸しを作って未来に繋げる仕事をする方が私は好きなので、こういう習慣は嫌いですけどね)
また、ピーク時に一発障害を出すだけで、売上げは大きく下がりますし信用も落とします。それに加えて3倍の損害金。レビューを通して技術力(とビジネス力)を底上げし、プロダクトの品質を保つことが結果として収益を支える事に繋がります。

ある程度の防御力を備える事で、多少の無茶が出来るようになります。

もし、どうやって収益を上げるか、どうすれば収益が倍増するかのお話を期待していた方には申し訳ないです。(そういう話はどうやって広告パフォーマンスを最適化するかという話なので、また分野は別になります。他の場所で別のメンバーが話すかもしれません。)

フェーズにおける戦い方

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

仕事をする上で、会社/プロジェクト/チームのフェーズ/状況によって、また人のロールによって戦い方は変わってきます。

状況が違うのに、前と同じ戦い方をしていたらそれは戦術ミスとなります。上手くやってる人のやり方を真似しても上手くいきません。なぜなら状況が違うからです。

フェーズ

今そういうフェーズじゃないのに、なんでそのやり方しているんだろうというのがあります。また新規プロジェクトなのに、既存の大型Projectと同じやり方を持ち込もうとする人もいます。

例えば、大型Projectはお金があるけど新規Projectには予算が殆ど無い場合。お金をかけられないので、何でもかんでもお金で解決する事は出来ませんし、既存の大型Projectで何年もかけた叡智の水準をベースにする事は難しいです。
また、会社としてのリソース配分が決まっている状況下では、予算を大幅にオーバーするとそれはプロジェクトの弱点になったりもします。

会社の規模

会社が小さい時は、各々が何でもやらなければなりません。人が少ないと、成果は個人に対して結びつきやすいです。会社が大きくなり、チームが大きくなると、個人で戦う時代は終わりチームとして戦う時代がやってきます。

状況が変われば戦い方を変えなければなりませんが、この状況下でも個人で戦い続けようとする人は多いです。それは組織としてスケールしない戦い方をしているわけです。メンバーが何をやっているのか分からない/無関心であるチームは、チームである必要はあるのでしょうか?

ロール

個人に紐付くロールが変わっても戦い方は変わります。

一般的役職で言うと部長以上では、何をやっていくかを考える必要がありますが、マネージャーのように大枠のお題が与えられると思っていては物事は何も始まりません。

マネージャー,リード,メンバーによって戦い方は変わります。マネージャーが実務作業を抱えまくるのは簡単にブロッカーになるので最たる悪手です。

マネージャはチームの成果を最大化する事が責務である事が多いと思います。それなのに以前と同じようにマネージャが個人としての戦い方をしていると、一体なにをしているんだ?と思ってしまいます。

そのやり方、本当にチームとしてスケールするやり方ですか?
その行為、ただただメンバーが依存するだけで成長する機会を奪っているだけですよ?
何だったら自分のチームだけで無く、余所のチームの成長機会も奪っていますよ?

以下のページに良い事が書いてありました。

http://makonari.com/?p=275

強固な企業文化をつくるには、
リーダーが熱いスピーチをするのではなく、
社員が気付きを得られる環境を用意することのほうが重要です。

(ちなみに、熱いスピーチや叱咤激励で士気が高まって、うぉお!と動くのは依存なので、個を活かす企業文化つくりたいなら、程々にしておくべきではないでしょうか。何もしないよりは良いですが)

物欲メモ

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

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

テレビ(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を使っているときに、このようなエラーが出て実行が止まってしまいました。

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くらいの数まで溜まっていました。

systemctl list-units --all | wc -l

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

systemctl daemon-reload

Systemdの問題か?

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

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

参考

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

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

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

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

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の方にはシグナルは何も飛んできませんでした。

ssh
bash
hoge.sh
docker run ...

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

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

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
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キーは伏せてます

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
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します。

kubectl create -f datadog-agent.yaml

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

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

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

env:
- name: _DD_NODE_HOST
valueFrom:
fieldRef:
fieldPath: status.hostIP

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

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ドル))