Kubernetes自体やその上で動くPodのステータスを監視したいのだけれどPrometheus等を使えない場合に、シェルスクリプトでkubectl get pod
等の結果を監視する方法を以下の記事に書いた。
同じように、kubectl CLIを使ってEventも監視したほうがよさそうなので、そのためのシェルスクリプトを作成したメモ。
Eventリソース
EventリソースについてのAPIリファレンスは以下。
kubectl get event
は以下の様な出力。
$ kubectl get event --all-namespaces -o wide
NAMESPACE LAST SEEN TYPE REASON KIND SOURCE MESSAGE SUBOBJECT FIRST SEEN COUNT NAME
kube-system 4m51s Warning FailedScheduling Pod default-scheduler 0/4 nodes are available: 1 Insufficient cpu, 3 node(s) didn't match node selector. 22h 1533 audit-logging-fluentd-ds-kz289.15b8347ed1d0dc1b
kube-system 12m Normal Pulled Pod kubelet, 9.188.124.25 Container image "mycluster.icp:8500/ibmcom/icp-management-ingress:2.3.0" already present on machine spec.containers{router} 9d 2860 monitoring-prometheus-collectdexporter-8c479ffcd-zwn4c.15b57dc4ecb4427d
kube-system 2m9s Warning BackOff Pod kubelet, 9.188.124.25 Back-off restarting failed container spec.containers{router} 9d 63243 monitoring-prometheus-collectdexporter-8c479ffcd-zwn4c.15b57efcbfec5d05
$
-
TYPE
という項目があり、Warning
を監視すればよさそう -
LAST SEEN
という項目があり、同じイベントはまとめて表示される - Eventリソースの存続時間は、apiserverの起動オプションの
--event-ttl
で指定されており、デフォルトは1時間。
個別のイベントを見てみると、以下の様な構造。
kubectl get event -n kube-system audit-logging-fluentd-ds-kz289.15b8347ed1d0dc1b -o yaml
apiVersion: v1
count: 1538
eventTime: null
firstTimestamp: "2019-08-06T02:29:49Z"
involvedObject:
apiVersion: v1
kind: Pod
name: audit-logging-fluentd-ds-kz289
namespace: kube-system
resourceVersion: "11688159"
uid: 343166a9-b101-11e9-b187-fa163e2fb2ab
kind: Event
lastTimestamp: "2019-08-07T01:25:33Z"
message: '0/4 nodes are available: 1 Insufficient cpu, 3 node(s) didn''t match node
selector.'
metadata:
creationTimestamp: "2019-08-06T02:29:49Z"
name: audit-logging-fluentd-ds-kz289.15b8347ed1d0dc1b
namespace: kube-system
resourceVersion: "11844265"
selfLink: /api/v1/namespaces/kube-system/events/audit-logging-fluentd-ds-kz289.15b8347ed1d0dc1b
uid: 107c1e3f-b7f2-11e9-b187-fa163e2fb2ab
reason: FailedScheduling
reportingComponent: ""
reportingInstance: ""
source:
component: default-scheduler
type: Warning
監視スクリプト
Pod等の状態監視と同じく、-o json
を使ってjson形式で出力し、jq
で処理をするのが楽と思われる。このシェルスクリプトをCron等で5分(300秒)に1回実行するとして、その5分以内に観測されたWarningのイベントを監視する。
jq
には日付を扱える便利な関数もある。マニュアルを参照。
kubectl
の側でも、--sort-by '{lastTimestamp}'
でソートしたり、--field-selector type=Warning
でフィルタリングすることは可能だが、jq
のほうができることが多いので、処理はjq
に寄せる。
以下の様なスクリプトを作成した。
#!/bin/bash
set -eu
set -o pipefail
# kubectl get nodeを実行して結果を変数に格納
# "jq -c"は結果を改行等で整形せずコンパクトにするオプション
json=$(kubectl get event --all-namespaces -o json | jq -c .)
# 結果を時刻でソートしてから、
# Warningでフィルタリングし、
# 300秒以内であるかでフィルタリング
warnings=$(echo ${json} | jq -c '.items
| sort_by( .lastTimestamp )
| .[]
| select( .type == "Warning" )
| select( now - ( .lastTimestamp | fromdate ) <= 300 )'
)
# 結果を整形
# <時刻> <Namespace名> <イベント名> <メッセージ>
# "jq -r"は出力をクオートしないオプション
warnings=$(echo ${warnings} | jq -r '.lastTimestamp + " "
+ .involvedObject.namespace + " "
+ .involvedObject.name + " "
+ .message')
# warnings が空文字の場合は正常
if [ -z "${warnings}" ]; then
echo "Warningはありません。"
else
IFS=$'\n'
for warning in "${warnings}"; do
echo "${warning}"
done
unset IFS
exit 1
fi
実行例は以下の通り。
$ ./check-events.sh
2019-08-07T03:00:33Z kube-system audit-logging-fluentd-ds-kz289 0/4 nodes are available: 1 Insufficient cpu, 3 node(s) didn't match node selector.
2019-08-07T03:03:16Z kube-system monitoring-prometheus-collectdexporter-8c479ffcd-zwn4c Back-off restarting failed container
$
その他
GKEだとStackdriverにEventを送るEvent Exporterがある。SlackにEventを送るOSSもいくつかある。