istio-proxy(envoy) のアクセスログをパースして任意の形式で出力するツールを作った

この記事は CODE BASE OKINAWA Advent Calendar 2022 - Adventar の12日目の記事です。

adventar.org

今日は、普段のお仕事を少しだけ楽にするツールを書いたので、紹介していきたいと思います。


普段運用している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 というツールを作成しました。

github.com

使い方

ログを標準入力から受け取り、任意の形式で出力することができます。

echo '<Istio Proxy Access Log>' | istio-axslog [flags]

現在サポートされている出力形式は、jsonltsvです。

--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
...

もちろん、jqlltsv などの他のツールと組み合わせて使うこともできます。

仕組み

仕組みはめちゃくちゃシンプルで、ログを標準入力から受け取り、1行ずつ正規表現を用いてパースして、 構造体 を生成しています。ログはこちらの Default access log format を元にパースしています。

構造体にしてしまえば、あとは標準パッケージや外部のパッケージなんかを使って構造体を簡単にjsonなりltsvの形式に変換することができるので、それらを繰り返し標準出力に出すだけです。めちゃくちゃシンプル。

最後に

インストールもmacOSならhomebrewからインストールできるようにしており、他の環境でも こちら からバイナリを落としてくるだけで使えるようになっています。

冒頭でも挙げたように、istio-proxyのアクセスログがパッと分かりづらいと思っている方がいらっしゃいましたら、是非使ってみてください!(もちろんフィードバックやPRもお待ちしております)

github.com