起動しているコンテナプロセスのLISTEN PORTを確認する方法です。
(やり方自体は他にも色々あるので一例ということで)
環境
kind:v0.11.1 + kubenetes:v1.23.0
kindイメージにはkindest/node:v1.23.0を使用しました。Dockerfile
事情はわかりませんがruncやcontainerdはkindがbuildしたものを使ってるみたいです・・・なんでだろ。
アプリケーションimage
gcr.io/google-samples/hello-app:1.0
hello world返すだけのイメージをデプロイしました。
runしたはいいですが、LISTEN PORTがわかりません。
試したこと
LISTEN PORTを確認するのに以下を行いました。
hello-appのドキュメント/ソースを探す
LISTEN PORTは何番だよ!みたいなドキュメントを期待してました。どこかにはあるのだろうと思いますがすぐには見つからず。ソースもすぐには見つからず。
kindノードでコンテナCLIを使う
コンテナランタイム実行ノードにシェルログインできる場合に可能。kind workerノードにはコンテナCLIとしてcrictlが入ってました。
サブコマンドinspect
コンテナID対象にinspectを実施すると
# crictl inspect c4c88276ca445 | jq -r '.info.runtimeSpec.process.env[]'
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=helloworld
PORT=8080
(以下略)
8080番だそうです。(もしかしたらbuild時のEXPOSEを見てるだけなのかも・・・)
サブコマンドlogs
ログ確認が一番手っ取り早いですかねー。出てないことがあるかも知れんですが。
hello-appはログに出してくれていました。
kubectlかコンテナCLIで確認です。
# crictl logs c4c88276ca445
2021/12/29 06:22:34 Server listening on port 8080
2021/12/29 08:18:18 Serving request: /
hello-appコンテナ内でconfigを探す
ポート番号を指定しているようなファイルを期待していましたが見つからず。goだからハードコードしてるんですかね。
hello-appコンテナ内でlsofを試す
busybox
デフォルトのlsofでは期待していた出力にならず、LISTEN PORTは表示されませんでした。busyboxだからですね。
# lsof
1 /hello-app 0 /dev/null
1 /hello-app 1 pipe:[1004247]
1 /hello-app 2 pipe:[1004248]
1 /hello-app 3 socket:[1004271]
1 /hello-app 4 anon_inode:[eventpoll]
23 /bin/busybox 0 /dev/pts/0
23 /bin/busybox 1 /dev/pts/0
23 /bin/busybox 2 /dev/pts/0
23 /bin/busybox 10 /dev/tty
別途インストールしたlsof
というわけで、別途lsofをパッケージインストールしてみます。
# cat /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.15.0
PRETTY_NAME="Alpine Linux v3.15"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://bugs.alpinelinux.org/"
# apk update
# apk add lsof
(1/1) Installing lsof (4.94.0-r0)
Executing busybox-1.34.1-r3.trigger
OK: 6 MiB in 15 packages
# lsof -i -P
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
hello-app 1 root 3u IPv6 1004271 0t0 TCP *:8080 (LISTEN)
8080だそうです。・・・TYPEがIPv6になってますね。
hello-appコンテナ内の/proc下でがんばる
面倒な方法ですが、何らかの理由でコンテナCLIでダメだったり、lsofをインストールできない場合もこれでいけます。
hello-appのfdを確認
hello-appのコンテナ内のPIDは1でした。/proc/1の下を覗きます。
# ls -l /proc/1/fd
total 0
lrwx------ 1 root root 64 Dec 29 06:22 0 -> /dev/null
l-wx------ 1 root root 64 Dec 29 06:22 1 -> pipe:[1004247]
l-wx------ 1 root root 64 Dec 29 06:22 2 -> pipe:[1004248]
lrwx------ 1 root root 64 Dec 29 06:22 3 -> socket:[1004271]
lrwx------ 1 root root 64 Dec 29 06:22 4 -> anon_inode:[eventpoll]
lsofで確認できたsocket(1004271)と同一ですね、当たり前ですが。
net/tcp6を確認
使用環境のk8sクラスタ内ではIPv6でお話しているようなので、/proc/1/net/tcpではなくて/proc/1/net/tcp6を見る必要がありました。
# cat /proc/1/net/tcp6
sl local_address remote_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
0: 00000000000000000000000000000000:1F90 00000000000000000000000000000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 1004271 1 0000000000000000 100 0 0 10 0
"local_address"の"00000000000000000000000000000000:1F90"というのがbindしているaddress:portになりそうです。一行しかエントリがないので自明ではありますが、"inode"がfdで確認したsocket番号1004271に一致しています。
10進に変換
1F90というのが16進数っぽいので、10進数に変換します。
> echo "ibase=16; 1F90" | bc
8080
というわけで、8080にbindしていることがわかります。
念の為確認
8080をcurlでつついてみます。
# curl 10.244.4.2:8080
Hello, world!
Version: 1.0.0
Hostname: helloworld
やりました。
番外編: port scan
たいへん行儀の悪い方法ですが、考えられなくはないということで。
# nmap 10.244.4.2
Starting Nmap 7.80 ( https://nmap.org ) at 2021-12-29 18:34 JST
Nmap scan report for 10.244.4.2
Host is up (0.000018s latency).
Not shown: 999 closed ports
PORT STATE SERVICE
8080/tcp open http-proxy
結論
コンテナプロセスのLISTEN PORTを確認するには、
- ドキュメントを当たる
- ソースを当たる
- コンテナランタイムに訊く
- アプリケーションコンテナ内でlsof
- アプリケーションコンテナ内で/procを漁る
番外: ポートスキャン
の順に試してみればよさそうです。