TensorFlow.orgで表示 | Google Colab で実行 | GitHub でソースを表示{ | ノートブックをダウンロード/a0} |
注: このノートブックは python パッケージの他、sudo apt-get install
を使用してサードパーティのパッケージをインストールします。
概要
このチュートリアルでは、CoreDNS メトリクスを Prometheus サーバーからtf.data.Dataset
に読み込み、tf.keras
をトレーニングと推論に使用します。
CoreDNS は、サービスディスカバリに重点を置いた DNS サーバーであり、Kubernetes クラスタの一部として広くデプロイされています。そのため、通常、開発オペレーションによって綿密に監視されています。
このチュートリアルでは、開発者向けに機械学習による運用の自動化の例を紹介します。
セットアップと使用法
必要な tensorflow-io パッケージをインストールし、ランタイムを再起動する
import os
try:
%tensorflow_version 2.x
except Exception:
pass
TensorFlow 2.x selected.
pip install tensorflow-io
from datetime import datetime
import tensorflow as tf
import tensorflow_io as tfio
CoreDNS と Prometheus のインストールとセットアップ
デモ用に、9053
番ポートをローカルで開放し、DNS クエリを受信するための CoreDNS サーバーとスクレイピングのメトリックを公開するために9153
番ポート (デフォルト) を開放します。以下は CoreDNS の基本的な Corefile 構成であり、ダウンロードできます。
.:9053 { prometheus whoami }
インストールの詳細については、CoreDNS のドキュメントを参照してください。
curl -s -OL https://github.com/coredns/coredns/releases/download/v1.6.7/coredns_1.6.7_linux_amd64.tgz
tar -xzf coredns_1.6.7_linux_amd64.tgz
curl -s -OL https://raw.githubusercontent.com/tensorflow/io/master/docs/tutorials/prometheus/Corefile
cat Corefile
.:9053 { prometheus whoami }
# Run `./coredns` as a background process.
# IPython doesn't recognize `&` in inline bash cells.
get_ipython().system_raw('./coredns &')
次に、Prometheus サーバーをセットアップし、Prometheus を使用して、上記の9153
番ポートで公開されている CoreDNS メトリックを取得します。また、構成用のprometheus.yml
ファイルはダウンロードできます。
curl -s -OL https://github.com/prometheus/prometheus/releases/download/v2.15.2/prometheus-2.15.2.linux-amd64.tar.gz
tar -xzf prometheus-2.15.2.linux-amd64.tar.gz --strip-components=1
curl -s -OL https://raw.githubusercontent.com/tensorflow/io/master/docs/tutorials/prometheus/prometheus.yml
cat prometheus.yml
global: scrape_interval: 1s evaluation_interval: 1s alerting: alertmanagers: - static_configs: - targets: rule_files: scrape_configs: - job_name: 'prometheus' static_configs: - targets: ['localhost:9090'] - job_name: "coredns" static_configs: - targets: ['localhost:9153']
# Run `./prometheus` as a background process.
# IPython doesn't recognize `&` in inline bash cells.
get_ipython().system_raw('./prometheus &')
アクティビティを表示するためには、dig
コマンドを使用して、セットアップされている CoreDNS サーバーに対していくつかの DNS クエリを生成できます。
sudo apt-get install -y -qq dnsutils
dig @127.0.0.1 -p 9053 demo1.example.org
; <<>> DiG 9.11.3-1ubuntu1.11-Ubuntu <<>> @127.0.0.1 -p 9053 demo1.example.org ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53868 ;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 3 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ; COOKIE: 855234f1adcb7a28 (echoed) ;; QUESTION SECTION: ;demo1.example.org. IN A ;; ADDITIONAL SECTION: demo1.example.org. 0 IN A 127.0.0.1 _udp.demo1.example.org. 0 IN SRV 0 0 45361 . ;; Query time: 0 msec ;; SERVER: 127.0.0.1#9053(127.0.0.1) ;; WHEN: Tue Mar 03 22:35:20 UTC 2020 ;; MSG SIZE rcvd: 132
dig @127.0.0.1 -p 9053 demo2.example.org
; <<>> DiG 9.11.3-1ubuntu1.11-Ubuntu <<>> @127.0.0.1 -p 9053 demo2.example.org ; (1 server found) ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53163 ;; flags: qr aa rd; QUERY: 1, ANSWER: 0, AUTHORITY: 0, ADDITIONAL: 3 ;; WARNING: recursion requested but not available ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ; COOKIE: f18b2ba23e13446d (echoed) ;; QUESTION SECTION: ;demo2.example.org. IN A ;; ADDITIONAL SECTION: demo2.example.org. 0 IN A 127.0.0.1 _udp.demo2.example.org. 0 IN SRV 0 0 42194 . ;; Query time: 0 msec ;; SERVER: 127.0.0.1#9053(127.0.0.1) ;; WHEN: Tue Mar 03 22:35:21 UTC 2020 ;; MSG SIZE rcvd: 132
CoreDNS サーバーのメトリックが Prometheus サーバーによりスクレイピングされ、TensorFlow で使用する準備ができました。
CoreDNS メトリックのデータセットを作成し、TensorFlow で使用する
PostgreSQL サーバーから利用可能な CoreDNS メトリックのデータセットを作成します。これは、tfio.experimental.IODataset.from_prometheus
を使用して実行できます。少なくとも次の 2 つの引数が必要です。 query
はメトリックを選択するため Prometheus サーバーに渡され、length
は Dataset に読み込む期間です。
"coredns_dns_request_count_total"
と"5"
(秒)から始めて、以下のデータセットを作成します。チュートリアルの前半で 2 つの DNS クエリが送信されたため、"coredns_dns_request_count_total"
のメトリックは時系列の終わりに"2.0"
になると予想されます。
dataset = tfio.experimental.IODataset.from_prometheus(
"coredns_dns_request_count_total", 5, endpoint="http://localhost:9090")
print("Dataset Spec:\n{}\n".format(dataset.element_spec))
print("CoreDNS Time Series:")
for (time, value) in dataset:
# time is milli second, convert to data time:
time = datetime.fromtimestamp(time // 1000)
print("{}: {}".format(time, value['coredns']['localhost:9153']['coredns_dns_request_count_total']))
Dataset Spec: (TensorSpec(shape=(), dtype=tf.int64, name=None), {'coredns': {'localhost:9153': {'coredns_dns_request_count_total': TensorSpec(shape=(), dtype=tf.float64, name=None)} } }) CoreDNS Time Series: 2020-03-03 22:35:17: 2.0 2020-03-03 22:35:18: 2.0 2020-03-03 22:35:19: 2.0 2020-03-03 22:35:20: 2.0 2020-03-03 22:35:21: 2.0
データセットの仕様をさらに見てみましょう。
( TensorSpec(shape=(), dtype=tf.int64, name=None), { 'coredns': { 'localhost:9153': { 'coredns_dns_request_count_total': TensorSpec(shape=(), dtype=tf.float64, name=None) } } } )
データセットが(time, values)
タプルで構成されていることは明らかです。values
フィールドは、次のように展開された python dict です。
"job_name": { "instance_name": { "metric_name": value, }, }
上記の例では、'coredns'
はジョブ名、'localhost:9153'
はインスタンス名、'coredns_dns_request_count_total'
はメトリック名です。使用する Prometheus クエリによっては、複数のジョブ/インスタンス/メトリックが返される可能性があることに注意してください。これは、データセットの構造で python dict が使用されている理由でもあります。
別のクエリ"go_memstats_gc_sys_bytes"
を例として見てみましょう。CoreDNS と Prometheus はどちらも Golang で記述されているため、"go_memstats_gc_sys_bytes"
メトリックは、"coredns"
ジョブと"prometheus"
ジョブの両方で使用できます。
注: このセルは、最初に実行したときにエラーになる場合があります。もう一度実行すると、パスします。
dataset = tfio.experimental.IODataset.from_prometheus(
"go_memstats_gc_sys_bytes", 5, endpoint="http://localhost:9090")
print("Time Series CoreDNS/Prometheus Comparision:")
for (time, value) in dataset:
# time is milli second, convert to data time:
time = datetime.fromtimestamp(time // 1000)
print("{}: {}/{}".format(
time,
value['coredns']['localhost:9153']['go_memstats_gc_sys_bytes'],
value['prometheus']['localhost:9090']['go_memstats_gc_sys_bytes']))
Time Series CoreDNS/Prometheus Comparision: 2020-03-03 22:35:17: 2385920.0/2775040.0 2020-03-03 22:35:18: 2385920.0/2775040.0 2020-03-03 22:35:19: 2385920.0/2775040.0 2020-03-03 22:35:20: 2385920.0/2775040.0 2020-03-03 22:35:21: 2385920.0/2775040.0
作成されたDataset
は、トレーニングまたは推論のために直接tf.keras
に渡す準備ができています。
モデルトレーニングにデータセットを使用する
メトリクスのデータセットを作成すると、モデルのトレーニングや推論のためにデータセットをtf.keras
に直接渡すことができます。
デモのために、このチュートリアルでは、1 つの特徴と 2 つのステップを入力とする非常に単純な LSTM モデルを使用します。
n_steps, n_features = 2, 1
simple_lstm_model = tf.keras.models.Sequential([
tf.keras.layers.LSTM(8, input_shape=(n_steps, n_features)),
tf.keras.layers.Dense(1)
])
simple_lstm_model.compile(optimizer='adam', loss='mae')
使用するデータセットは、10 サンプルの CoreDNS の「go_memstats_sys_bytes」の値です。ただし、window = n_steps
およびshift = 1
のスライディングウィンドウが形成されるため、追加のサンプルが必要です (2 つの連続する要素の場合、最初のサンプルはx
で、2 番目はy
と見なされます) 。合計は10 + n_steps - 1 + 1 = 12
秒です。
また、データ値は[0、1]
にスケーリングされています。
n_samples = 10
dataset = tfio.experimental.IODataset.from_prometheus(
"go_memstats_sys_bytes", n_samples + n_steps - 1 + 1, endpoint="http://localhost:9090")
# take go_memstats_gc_sys_bytes from coredns job
dataset = dataset.map(lambda _, v: v['coredns']['localhost:9153']['go_memstats_sys_bytes'])
# find the max value and scale the value to [0, 1]
v_max = dataset.reduce(tf.constant(0.0, tf.float64), tf.math.maximum)
dataset = dataset.map(lambda v: (v / v_max))
# expand the dimension by 1 to fit n_features=1
dataset = dataset.map(lambda v: tf.expand_dims(v, -1))
# take a sliding window
dataset = dataset.window(n_steps, shift=1, drop_remainder=True)
dataset = dataset.flat_map(lambda d: d.batch(n_steps))
# the first value is x and the next value is y, only take 10 samples
x = dataset.take(n_samples)
y = dataset.skip(1).take(n_samples)
dataset = tf.data.Dataset.zip((x, y))
# pass the final dataset to model.fit for training
simple_lstm_model.fit(dataset.batch(1).repeat(10), epochs=5, steps_per_epoch=10)
Train for 10 steps Epoch 1/5 10/10 [==============================] - 2s 150ms/step - loss: 0.8484 Epoch 2/5 10/10 [==============================] - 0s 10ms/step - loss: 0.7808 Epoch 3/5 10/10 [==============================] - 0s 10ms/step - loss: 0.7102 Epoch 4/5 10/10 [==============================] - 0s 11ms/step - loss: 0.6359 Epoch 5/5 10/10 [==============================] - 0s 11ms/step - loss: 0.5572 <tensorflow.python.keras.callbacks.History at 0x7f1758f3da90>
このチュートリアルでセットアップされた CoreDNS サーバーにはワークロードがないため、上記のトレーニング済みモデルは実際にはあまり役に立ちませんが、これは実際の運用サーバーからメトリックを読み込むために使用できる作業パイプラインです。その後、モデルを改善して、開発の自動化という実際の問題を解決できます。