この記事は CODE BASE OKINAWA Advent Calendar 2022 - Adventar の12日目の記事です。
今日は、普段のお仕事を少しだけ楽にするツールを書いたので、紹介していきたいと思います。
普段運用しているKubernetesクラスターでIstioを導入しています。
手元から Kubectl logs
コマンドや stern コマンドを使って、istio-proxyのアクセスログを確認したい場面が多々あるのですが、出力されるログの形式が以下のようになっており、どれがどの値か分からん!となって、よくログとドキュメントを行ったり来たりしています。
$ kubectl logs -l app=sleep -c istio-proxy [2020-11-25T21:26:18.409Z] "GET /status/418 HTTP/1.1" 418 - via_upstream - "-" 0 135 4 4 "-" "curl/7.73.0-DEV" "84961386-6d84-929d-98bd-c5aee93b5c88" "httpbin:8000" "10.44.1.27:80" outbound|8000||httpbin.foo.svc.cluster.local 10.44.1.23:37652 10.0.45.184:8000 10.44.1.23:46520 - default
ref: Istio / Envoy Access Logs
そこで、上記のログのパースして、別の形式で見れると何かと便利じゃないかなぁと思い、Goを用いてistio-axslog というツールを作成しました。
使い方
ログを標準入力から受け取り、任意の形式で出力することができます。
echo '<Istio Proxy Access Log>' | istio-axslog [flags]
現在サポートされている出力形式は、json
とltsv
です。
--output json (デフォルト)
$ kubectl logs -l app=sleep -c istio-proxy | istio-axslog {"start_time":"2020-11-25T21:26:18.409Z","method":"GET","path":"/status/418","protocol":"HTTP/1.1","response_code":"418","response_flags":"-","response_code_details":"via_upstream","connection_termination_details":"-","upstream_transport_failure_reason":"-","bytes_received":"0","bytes_sent":"135","duration":"4","x_envoy_upstream_service_time":"4","x_forwarded_for":"-","user_agent":"curl/7.73.0-DEV","x_request_id":"84961386-6d84-929d-98bd-c5aee93b5c88","authority":"httpbin:8000","upstream_host":"10.44.1.27:80","upstream_cluster":"outbound|8000||httpbin.foo.svc.cluster.local","upstream_local_address":"10.44.1.23:37652","downstream_local_address":"10.0.45.184:8000","downstream_remote_address":"10.44.1.23:46520","requested_server_name":"-","route_name":"default"} {"start_time":"2020-11-25T21:27:20.503Z","method":"GET","path":"/status/418","protocol":"HTTP/1.1","response_code":"418","response_flags":"-","response_code_details":"via_upstream","connection_termination_details":"-","upstream_transport_failure_reason":"-","bytes_received":"0","bytes_sent":"135","duration":"4","x_envoy_upstream_service_time":"4","x_forwarded_for":"-","user_agent":"curl/7.73.0-DEV","x_request_id":"84961386-6d84-929d-98bd-c5aee93b5c88","authority":"httpbin:8000","upstream_host":"10.44.1.27:80","upstream_cluster":"outbound|8000||httpbin.foo.svc.cluster.local","upstream_local_address":"10.44.1.23:37652","downstream_local_address":"10.0.45.184:8000","downstream_remote_address":"10.44.1.23:46520","requested_server_name":"-","route_name":"default"} {"start_time":"2020-11-25T21:28:39.399Z","method":"GET","path":"/status/418","protocol":"HTTP/1.1","response_code":"418","response_flags":"-","response_code_details":"via_upstream","connection_termination_details":"-","upstream_transport_failure_reason":"-","bytes_received":"0","bytes_sent":"135","duration":"4","x_envoy_upstream_service_time":"4","x_forwarded_for":"-","user_agent":"curl/7.73.0-DEV","x_request_id":"84961386-6d84-929d-98bd-c5aee93b5c88","authority":"httpbin:8000","upstream_host":"10.44.1.27:80","upstream_cluster":"outbound|8000||httpbin.foo.svc.cluster.local","upstream_local_address":"10.44.1.23:37652","downstream_local_address":"10.0.45.184:8000","downstream_remote_address":"10.44.1.23:46520","requested_server_name":"-","route_name":"default"} ...
--output ltsv
$ kubectl logs -l app=sleep -c istio-proxy | istio-axslog -o ltsv start_time:2020-11-25T21:26:18.409Z method:GET path:/status/418 protocol:HTTP/1.1 response_code:418 response_flags:- response_code_details:via_upstream connection_termination_details:- upstream_transport_failure_reason:- bytes_received:0 bytes_sent:135 duration:4 x_envoy_upstream_service_time:4 x_forwarded_for:- user_agent:curl/7.73.0-DEV x_request_id:84961386-6d84-929d-98bd-c5aee93b5c88 authority:httpbin:8000 upstream_host:10.44.1.27:80 upstream_cluster:outbound|8000||httpbin.foo.svc.cluster.local upstream_local_address:10.44.1.23:37652 downstream_local_address:10.0.45.184:8000 downstream_remote_address:10.44.1.23:46520 requested_server_name:- route_name:default start_time:2020-11-25T21:27:19.409Z method:GET path:/status/418 protocol:HTTP/1.1 response_code:418 response_flags:- response_code_details:via_upstream connection_termination_details:- upstream_transport_failure_reason:- bytes_received:0 bytes_sent:135 duration:4 x_envoy_upstream_service_time:4 x_forwarded_for:- user_agent:curl/7.73.0-DEV x_request_id:84961386-6d84-929d-98bd-c5aee93b5c88 authority:httpbin:8000 upstream_host:10.44.1.27:80 upstream_cluster:outbound|8000||httpbin.foo.svc.cluster.local upstream_local_address:10.44.1.23:37652 downstream_local_address:10.0.45.184:8000 downstream_remote_address:10.44.1.23:46520 requested_server_name:- route_name:default start_time:2020-11-25T21:29:18.129Z method:GET path:/status/418 protocol:HTTP/1.1 response_code:418 response_flags:- response_code_details:via_upstream connection_termination_details:- upstream_transport_failure_reason:- bytes_received:0 bytes_sent:135 duration:4 x_envoy_upstream_service_time:4 x_forwarded_for:- user_agent:curl/7.73.0-DEV x_request_id:84961386-6d84-929d-98bd-c5aee93b5c88 authority:httpbin:8000 upstream_host:10.44.1.27:80 upstream_cluster:outbound|8000||httpbin.foo.svc.cluster.local upstream_local_address:10.44.1.23:37652 downstream_local_address:10.0.45.184:8000 downstream_remote_address:10.44.1.23:46520 requested_server_name:- route_name:default ...
もちろん、jq や lltsv などの他のツールと組み合わせて使うこともできます。
仕組み
仕組みはめちゃくちゃシンプルで、ログを標準入力から受け取り、1行ずつ正規表現を用いてパースして、 構造体 を生成しています。ログはこちらの Default access log format を元にパースしています。
構造体にしてしまえば、あとは標準パッケージや外部のパッケージなんかを使って構造体を簡単にjsonなりltsvの形式に変換することができるので、それらを繰り返し標準出力に出すだけです。めちゃくちゃシンプル。
最後に
インストールもmacOSならhomebrewからインストールできるようにしており、他の環境でも こちら からバイナリを落としてくるだけで使えるようになっています。
冒頭でも挙げたように、istio-proxyのアクセスログがパッと分かりづらいと思っている方がいらっしゃいましたら、是非使ってみてください!(もちろんフィードバックやPRもお待ちしております)