podのログの監視ツール作成みたいな作業をしているときに「任意のログをpod内に発生させたい!」ということがあったので、その方法について。
TL;DR
ログを発生させたい対象podのシェル上(kubectl exec -it ... -- sh
などで)で、/proc/1/fd/1
に対して発生させたいログ文字列を書き込む
echo "sample log" > /proc/1/fd/1
こんな感じ。
echo 'foo' > /proc/1/fd/1
— Takayoshi Kimura (@nekop) 2020年6月9日
nekopさんありがとうございました。
解説
man proc
より。
/proc/[pid]/fd/ This is a subdirectory containing one entry for each file which the process has open, named by its file descriptor, and which is a symbolic link to the actual file. Thus, 0 is standard input, 1 standard output, 2 standard error, and so on.
プロセスごとのファイルディスクリプタがこのディレクトリ配下に存在している。
- 0: 標準入力
- 1: 標準出力
- 2: 標準エラー出力
など。
(プロセスが開いているファイルやソケットなども存在する)
つまり、/proc/1/fd/1
というのは、「PID1のプロセスの標準出力」ということになる。
pod(の中で動いているコンテナ)は、(通常は)PID1でアプリケーションが動作し、そのプロセスの標準出力への出力がコンテナのログとして扱われるため、/proc/1/fd/1
への書き込みがpodのログとして出力される、という動作になる。
podで動作確認
こんな実行状態とする。
[zaki@k8s-master01 ~]$ kubectl get pod NAME READY STATUS RESTARTS AGE sample-web-7dbc56cb5b-gxj6l 1/1 Running 0 79s
sample-web(中身はhttpdサーバ)のログを表示
[zaki@k8s-master01 ~]$ kubectl logs -f sample-web-7dbc56cb5b-gxj6l AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.244.219.194. Set the 'ServerName' directive globally to suppress this message AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.244.219.194. Set the 'ServerName' directive globally to suppress this message [Sat Jun 13 13:17:38.991237 2020] [mpm_event:notice] [pid 1:tid 140014371525760] AH00489: Apache/2.4.43 (Unix) configured -- resuming normal operations [Sat Jun 13 13:17:38.991616 2020] [core:notice] [pid 1:tid 140014371525760] AH00094: Command line: 'httpd -D FOREGROUND'
この状態で、別のターミナルでシェルを起動し、シェル上で/proc/1/fd/1
へ文字列を書き込み
[zaki@k8s-master01 ~]$ kubectl exec -it sample-web-7dbc56cb5b-gxj6l -- bash root@sample-web-7dbc56cb5b-gxj6l:/usr/local/apache2# echo "sample log" > /proc/1/fd/1 root@sample-web-7dbc56cb5b-gxj6l:/usr/local/apache2#
すると、podのログに書き込んだ文字列が出力されるのを確認。
[zaki@k8s-master01 ~]$ kubectl logs -f sample-web-7dbc56cb5b-gxj6l AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.244.219.194. Set the 'ServerName' directive globally to suppress this message AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.244.219.194. Set the 'ServerName' directive globally to suppress this message [Sat Jun 13 13:17:38.991237 2020] [mpm_event:notice] [pid 1:tid 140014371525760] AH00489: Apache/2.4.43 (Unix) configured -- resuming normal operations [Sat Jun 13 13:17:38.991616 2020] [core:notice] [pid 1:tid 140014371525760] AH00094: Command line: 'httpd -D FOREGROUND' sample log
普通のLinux OS上で確認
仕組み自体はLinux一般の話なので、そもそも素のLinux OS上でも確認できるはず。
ターミナル1で引数無しでcat
を実行
[zaki@manager-dev ~]$ cat
とうぜん標準入力が何も無いので出力も何もない。
ここでターミナル2でcat
のPIDを調べる
[zaki@manager-dev ~]$ ps -u USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND zaki 103986 0.0 0.1 116860 3508 pts/0 Ss 20:17 0:00 -bash zaki 104015 0.0 0.1 116732 3240 pts/1 Ss 20:17 0:00 -bash zaki 104142 0.0 0.0 108072 356 pts/1 S+ 22:31 0:00 cat zaki 104143 0.0 0.0 155472 1848 pts/0 R+ 22:31 0:00 ps -u
104142
であることが確認できたので、それを指定してecho
を実行。
[zaki@manager-dev ~]$ echo "nya-n" > /proc/104142/fd/0 [zaki@manager-dev ~]$
するとcat
のプロセスが"nya-n"とう標準入力を受け取るという動作になるため、cat
実行中のターミナルに文字列が出力される。
[zaki@manager-dev ~]$ cat nya-n