目的
コンテナのエラーログとロードバランサーの500系のレスポンスを時系列で見比べたい
やること
gcloud logging
コマンドでStackdriverからk8sコンテナとロードバランサーのログを期間指定して、tsv形式で出力する
テンプレート
PROJECT_ID=my-project
START_UTC_TIME_PRIOD="2019-11-13T01:00:00Z"
FRESHNESS="23h"
TAB=`echo "\t"`
gcloud beta logging read \
'(
resource.type=k8s_container
resource.labels.cluster_name=[CLUSTER_NAME]
resource.labels.namespace_name=[NAMESPACE]
resource.labels.container_name=[CONTAINER_NAME]
severity>=WARNING
timestamp>="'"$START_UTC_TIME_PRIOD"'"
) OR (
resource.type=http_load_balancer
resource.labels.forwarding_rule_name=[LOADBARANCER1]
resource.labels.forwarding_rule_name=[LOADBARANCER2]
httpRequest.status>=500
httpRequest.status<=599
httpRequest.userAgent!="Slackbot-LinkExpanding 1.0 (+https://api.slack.com/robots)"
timestamp>="'"$START_UTC_TIME_PRIOD"'"
)' \
--project=$PROJECT_ID \
--order=asc \
--format='csv[separator="'"$TAB"'"]
(
timestamp,
httpRequest.status,
httpRequest.requestUrl,
textPayload,
resource.labels.cluster_name,
resource.labels.container_name,
resource.labels.location,
resource.labels.namespace_name,
resource.labels.pod_name,
resource.labels.project_id,
resource.type,
labels."k8s-pod/app",
labels."k8s-pod/pod-template-hash",
logName,
insertId,
receiveTimestamp
)' \
--freshness="$FRESHNESS" \
| gsed -z "s/\n\"/\"/g" \
> gcloud-logging.tsv
説明
gcloud logging read
でログエントリの取得ができる。
フィルタ
第1引数はフィルタを指定する。コンソールの Stackdriver logging のフィルタと同様に、フィールド名が同じ条件は暗黙的にANDで結合され、そうでない場合はORで結合される。今回はリソースが違うログを結合するために、コンテナに関する条件とロードバランサーに関する条件をそれぞれ ( )
でくくって OR
で結合した。この OR
は明示的に書かなければならない。
また、時間の指定はオプションではなくフィルタで行う。例えば、2019年11月1日 12時34分56秒から
という条件は↓のように書く。また、:
はエスケープしなければならないため、ダブルクォートで囲む
timestamp>="2019-11-01T3:34:56Z"
JSTからUTCに変換しないといけないことに注意する。
httpRequest.userAgent!="Slackbot-LinkExpanding 1.0 (+https://api.slack.com/robots)"
の部分についてだが、Slackでリンクを共有した際にサムネイルを表示するためにSlackがアクセスしてエラーのレスポンスを返すログへの対策である。
期間の指定
期間の終了時間を指定せずに期間の長さを指定したいときは --freshness
オプションを付ける。 --freshness="3h"
を付けると直近3時間のみを取得する。
最新のログまでを取得したい場合は適当に大きい値を指定しておけばいい。
出力フォーマット
--format='csv[separator="'"$TAB"'"](...)
は出力をタブ区切りに指定するオプション。--format='value[separator="'"$TAB"'"](...)
でも可能だが、ヘッダーが付加されないのと、quoteを指定しないとタブや改行の区切り文字が含まれているときにダブルクォートでくくってくれないという問題がある。 ( )
の中は出力するkeyの名前を列挙する。たくさんある場合はStackdriverで確認しながらだと捗る。
TAB変数を宣言しているのは、色々と試行錯誤しているうちにタブ文字が気づいたらスペースになってしまい、出力ファイルのスペースをタブに変換するために十数分待つ羽目になるという自体を防ぐ目的がある。やってしまうと結構辛い。
その他
--project=$PROJECT_ID
はフィルタの後に渡す。 gcloud
の直後に指定するとログの取得ができなかった。
デバッグ中は --freshness
を小さくしたり、 --limit
で出力件数を少なくすると多少はレスポンスが早くなる。
ログの整形
gsed -z "s/\n\"/\"/g"
は ダブルクォートの前にある改行を消すというスクリプトである。本来はtextpayloadの途中の改行コードも変換できるように \t"[^\t]*\n[^\t]*"\t
のようなマッチングをしたかったが、うまくいかず断念した。
所感
loggingのフィルタは慣れればそこまで書きづらいとは感じなかった。
出力フォーマットの指定はその機能無いんですか的なのが多いと感じた。
値のエスケープとか。csvを指定したときにとりあえず全部のフィールドをシリアライズして出して!みたいなことができたら楽。
そもそもコンソールから300件以上のダウンロードができるようにしてほしい。