Kubernetes スタイルの経過時間を秒数に変換して比較する方法

Kubernetes スタイルの経過時間を秒数に変換して比較する方法

から

kubectl get pods -o wide

出力は次のようになります

some-pod-name-with-numbers-123             1/1     Running   0          6d4h      192.168.0.23   node-name-abcdeft-host.domain   <none>           <none>
some-pod-name-with-numbers-1234            1/1     Running   0          4h38m      192.168.0.24   node-name-abcdeft-host.domain   <none>           <none>
some-pod-name-with-numbers-1235            1/1     Running   0          2m38s      192.168.0.25   node-name-abcdeft-host.domain   <none>           <none>

ポッドの経過時間は、4d3h15m3s のような形式で取得します (最大は 2 つの連続した単位、日と時間、時間分、分と秒のようですが、保証はできません)。

ポッドが何らかのしきい値 X より長く存在しているかどうかを確認する必要があります。

kubectl 経由でこのフィールドを秒として抽出する方法を見つけようとしましたが、見つかりませんでした。インターネットで事前に用意されたソリューションを検索しましたが、見つかりませんでした。

awk を使用して文字列を数値の秒数に変換し、それが > $X であるかどうかを比較できると考えています。この値は設定可能です。

答え1

Kubernetes の経過時間を秒単位で取得するためだけに、外部プロセスをフォークする必要はありません。以下の GNU awk コードには、fx()その変換を実行するユーザー定義関数があり、そこから比較目的で使用できます。

kubectl get pods -o wide |
awk '
BEGIN {
    a["d"] = 24*(\
    a["h"] = 60*(\
    a["m"] = 60*(\
    a["s"] = 1)));
  }
  {
    print fx($5); # kubernetes time elapsed in seconds 
  }
  function fx(ktym,    f,u,n,t,i) {
    n = split(ktym, f, /[dhms]/, u)
    t = 0
    for (i=1; i<n; i++) {
      t += f[i] * a[u[i]] 
    }
    return t
  }
'

bash でユーザー定義関数を使用する場合は、次の操作を実行できます。 1 つの引数 (Kubernetes 形式での経過時間) を必要とする関数 fx() があり、これは秒単位で時間を出力します。

fx() {
echo "$1" |
sed -Ee '
  s/[1-9][0-9]*[dhms]/&+ /g
  :a;s/[+]([^+].*)/\1+/;ta
  s/.$//
  :loop
    s/d/ 24h*/
    s/h/ 60m*/
    s/m/ 60s*/
    s/s//
  t loop
  s/.*/echo "&" | dc -e "?p"/e
'
}

Linuxユーティリティのコードを動的に生成しています。直流または、RPN の翻訳(逆ポーランド記法)。

答え2

私のように Python 関数を探している人のために、ここにあります:

def kubctle_dur_to_secs(kubectl_time:str) -> int:
    total_time = 0
    for t_char, sec_in_t in zip( ('d', 'h', 'm', 's'), (86400, 3600, 60, 1) ):
        if t_char in kubectl_time:
            t_index = kubectl_time.find(t_char)
            total_time += int(kubectl_time[:t_index])*sec_in_t
            kubectl_time = kubectl_time[t_index+1:]
    return total_time

答え3

これに少し時間を費やした結果、これを実現する最も簡単な方法は、sed replace を使用して時間をトークン化することだと分かりました。

sed -e 's/\([smhd]\)/\1 /g' | awk '{ b=0; for(i=1; i<=NF; ++i) { s=substr($i,1,length($i)-1); u=substr($i,length($i)); if (u=="s") b+=s; else if (u=="m") b+=s*60; else if (u=="h") b+=s*60*60; else if (u=="d") b+=s*60*60*24; else u=""; } if (b>1) printf "%d", b}'

これまでのところ、この分野では、100 日以上経過したポッドの場合でも、d、h、m、s 単位のみが使用されているのを確認しました。

sed コマンドは基本的にすべての単位をスペースで分割します。
次に、awk はフィールドをループし、文字列を単位 (u) と数値文字列 (s) に分割します。
連鎖された if-elseif-else ステートメントは、単位に基づいて値を秒数に変換し、秒数で保持される時間の合計に追加します。

このコマンドをスクリプト「kube_elapsed_to_seconds」に配置し、外部で別の awk とシステム コマンドを使用してこのフィールドでこのスクリプトを実行する予定です。

kubectl get pods -o wide | awk '{ system("echo " $5 " | kube_elapased_to_seconds"); print $0 }'

このコマンドを読みやすくしたり、podname や status などの時間に関連しない他のフィールドとよりうまくやり取りできるようにする方法についての提案をお待ちしています。

答え4

これらを理解するコマンドについては4d3h15m3s、dateutils のを参照してくださいdadd

$ TZ=UTC0 dateutils.dadd -f%s 1970-01-01T00:00:00 4d3h15m3s
357303

ここでは、その期間を Unix エポック時間の開始に追加し、UTC に 0 オフセットされたタイムゾーンで、結果を Unix エポック時間として出力します。

関連情報