Featured image of post kubectlで時間範囲を指定してPod情報を取得する

kubectlで時間範囲を指定してPod情報を取得する

Podがいっぱいあると調査するのが大変

KubernetesクラスタのPod情報を取りたいときに,
Podの起動日時を指定して取る方法がわかんなかったのでメモ.


まとめ

Podが起動した時刻を範囲指定して情報を取得する例

# 2020-04-15の14:01:00~14:09:00(UTC)の間に作成されたPodだけ取り出してみる
$ kubectl get pods -o custom-columns="NAME:{.metadata.name},CREATED-AT:{.metadata.creationTimestamp}" | awk '{if (NR==1) print; else if ("2020-04-15T14:01:00Z" < $2 && $2 < "2020-04-15T14:09:00Z") print}'
NAME                     CREATED-AT
sleep-1586959500-7pf6c   2020-04-15T14:05:06Z

やりかた

事前準備

何個かPodを作っておきたいのでCronJobを作成する.
せっかくなのでyaml無しでkubectl createでつくってみる.

# 5分毎に起動して30秒sleepするCronJob
$ kubectl create cronjob test-job --image=busybox --schedule="*/5 * * * *" --restart=Never -- /bin/sh -c 'date; sleep 30; date'
cronjob.batch/sleep created

$ kubectl get cronjob sleep -o yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
  creationTimestamp: "2020-04-15T13:59:57Z"
  name: sleep
  namespace: default
  resourceVersion: "8570399"
  selfLink: /apis/batch/v1beta1/namespaces/default/cronjobs/sleep
  uid: a199da04-7fdc-11ea-b34b-42010a800054
spec:
  concurrencyPolicy: Allow
  failedJobsHistoryLimit: 1
  jobTemplate:
    metadata:
      creationTimestamp: null
      name: sleep
    spec:
      template:
        metadata:
          creationTimestamp: null
        spec:
          containers:
          - command:
            - /bin/sh
            - -c
            - date; sleep 30; date
            image: busybox
            imagePullPolicy: Always
            name: sleep
            resources: {}
            terminationMessagePath: /dev/termination-log
            terminationMessagePolicy: File
          dnsPolicy: ClusterFirst
          restartPolicy: Never
          schedulerName: default-scheduler
          securityContext: {}
          terminationGracePeriodSeconds: 30
  schedule: '*/5 * * * *'
  successfulJobsHistoryLimit: 3
  suspend: false
status:
  active:
  - apiVersion: batch/v1
    kind: Job
    name: sleep-1587039720
    namespace: default
    resourceVersion: "8570397"
    uid: df56a4d7-7fdc-11ea-b34b-42010a800054
  lastScheduleTime: "2020-04-15T14:00:00Z"

# 15分以上放っておくとPodが3つできている(successfulJobsHistoryLimit: 3)
$ kubectl get pods | awk '{if (NR==1) print; else if ($1 ~ /sleep/) print}'
NAME                     READY   STATUS      RESTARTS   AGE
sleep-1586959200-m8q7b   0/1     Completed   0          11m
sleep-1586959500-7pf6c   0/1     Completed   0          6m14s
sleep-1586959800-wgmpd   0/1     Completed   0          74s

# CronJobを止めておく
$ kubectl patch cronjob sleep -p '{"spec":{"suspend":true}}'
cronjob.batch/sleep patched

Pod情報を取得する

普通にgetしてみる.

$ kubectl get pods
NAME                     READY   STATUS      RESTARTS   AGE
sleep-1586959200-m8q7b   0/1     Completed   0          14m
sleep-1586959500-7pf6c   0/1     Completed   0          9m21s
sleep-1586959800-wgmpd   0/1     Completed   0          4m21s

これだとAGEしかわかんないので,
例えばhh時mm分~hh時nn分に作成されたPodだけほしいってときに困る.

Pod.metadata.creationTimestampには起動した時間が記述されているので,
これを表示するようにしてみる.

# columnにPod名と起動時間を指定してみる
$ kubectl get pods -o custom-columns="NAME:{.metadata.name},CREATED-AT:{.metadata.creationTimestamp}"
NAME                     CREATED-AT
sleep-1586959200-m8q7b   2020-04-15T14:00:05Z
sleep-1586959500-7pf6c   2020-04-15T14:05:06Z
sleep-1586959800-wgmpd   2020-04-15T14:10:06Z

いい感じ.
これで各Podがいつ起動したかがわかる.

ちょっと調べた(kubectl get pods --help見ただけ)けど
時間の範囲を指定して表示するオプションとかがなかったので,
ここからはawkでしこしこやっていく.

.status.startTimeのフォーマットがYYYY-MM-DDThh:mm:ssZなので,
これに従って範囲を指定してみる.
参考 : https://ja.wikipedia.org/wiki/ISO_8601

# 2020-04-15の14:01:00~14:09:00(UTC)の間に作成されたPodだけ取り出してみる
$ kubectl get pods -o custom-columns="NAME:{.metadata.name},CREATED-AT:{.metadata.creationTimestamp}" | awk '{if (NR==1) print; else if ("2020-04-15T14:01:00Z" < $2 && $2 < "2020-04-15T14:09:00Z") print}'
NAME                     CREATED-AT
sleep-1586959500-7pf6c   2020-04-15T14:05:06Z

時刻の範囲を指定してPod名が取得できた.
やったぜ.

プラグイン化してみる

毎度毎度コマンドを組み立てるのも大変なので, かんたんなプラグインをつくってみる.

kubectl-timerange

#!/bin/sh

func() {
  if [[ $# -lt 2 || $# -gt 3 ]]; then
    echo 'args: resource time_from time_to'
    exit 1
  fi

  local resource="$1"
  local time_from="$2"
  local time_to

  if [[ $# -lt 3 ]]; then
    time_to=$(date -u +%Y-%m-%dT%k:%M:%SZ)
  else
    time_to="$3"
  fi

  kubectl get "${resource}" -o custom-columns="NAME:{.metadata.name},START_TIME:{.metadata.creationTimestamp}" | awk '{if (NR==1) print; else if ('\"${time_from}\"' < $2 && $2 < '\"${time_to}\"') print}'

}

func "$@"

作ったプラグインを読めるようにする.
ファイル名がkubectl-hogeのスクリプトがPATHの通った場所にあると,
kubectl hogeで呼び出すことができる.
Extend kubectl with plugins

# スクリプトを記述
$ vim /usr/local/bin/kubectl-timerange

# 実行できるようにする
$ chmod +x /usr/local/bin/kubectl-timerange

# 有効なプラグインを確認する
$ kubectl plugin list
The following compatible plugins are available:

/usr/local/bin/kubectl-timerange

# 実際に使ってみる
$ kubectl timerange pod '2020-04-15T14:01:00Z' '2020-04-15T14:09:00Z'
NAME                     CREATED-AT
sleep-1586959500-7pf6c   2020-04-15T14:05:06Z

できた.
毎回awkのスクリプトを書くのも大変なのでこっちのほうが使いやすい.
はず…

おわり

CronJobを扱う機会が多いので, Jobが連続して失敗したときなんかに調査用に使っていきたい.
というかawkが便利なのでもうちょっと使いこなせるようになりたい.

おまけ

ぐにゃぐにゃねこ