![]() |
![]() |
![]() |
![]() |
總覽
本教學課程會將 CoreDNS 指標從 Prometheus 伺服器載入到 tf.data.Dataset
,然後使用 tf.keras
進行訓練和推論。
CoreDNS 是以服務探索為重點的 DNS 伺服器,廣泛部署為 Kubernetes 叢集的一部分。因此,DevOps 作業通常會密切監控它。
本教學課程是一個範例,DevOps 人員可以藉此透過機器學習在作業中尋求自動化。
設定與使用方式
安裝必要的 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
為了示範目的,在本地端設定 CoreDNS 伺服器,連接埠 9053
開放接收 DNS 查詢,連接埠 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 指標建立 Dataset 並在 TensorFlow 中使用
為 PostgreSQL 伺服器提供的 CoreDNS 指標建立 Dataset,可以使用 tfio.experimental.IODataset.from_prometheus
完成。至少需要兩個引數。query
會傳遞至 Prometheus 伺服器以選取指標,而 length
則是您要載入 Dataset 的期間。
您可以從 "coredns_dns_request_count_total"
和 "5"
(秒) 開始,以在下方建立 Dataset。由於在本教學課程稍早時已傳送兩個 DNS 查詢,因此預期 "coredns_dns_request_count_total"
的指標在時間序列結束時會是 "2.0"
dataset = tfio.experimental.IODataset.from_prometheus(
"coredns_dns_request_count_total", 5, endpoint="https://127.0.0.1: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
進一步查看 Dataset 的規格
(
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 字典
"job_name": {
"instance_name": {
"metric_name": value,
},
}
在上述範例中,'coredns'
是工作名稱,'localhost:9153'
是執行個體名稱,而 'coredns_dns_request_count_total'
是指標名稱。請注意,根據使用的 Prometheus 查詢,可能會傳回多個工作/執行個體/指標。這也是為何在 Dataset 的結構中使用 Python 字典的原因。
以另一個查詢 "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="https://127.0.0.1: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
,以用於訓練或推論目的。
將 Dataset 用於模型訓練
透過建立的指標 Dataset,可以將 Dataset 直接傳遞至 tf.keras
以進行模型訓練或推論。
為了示範目的,本教學課程將僅使用一個非常簡單的 LSTM 模型,其輸入為 1 個特徵和 2 個步驟
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')
要使用的資料集是 CoreDNS 的 'go_memstats_sys_bytes' 值,包含 10 個樣本。但是,由於形成了 window=n_steps
和 shift=1
的滑動視窗,因此需要額外的樣本 (對於任何兩個連續的元素,第一個元素會被視為 x
,而第二個元素會被視為 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="https://127.0.0.1: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 伺服器沒有任何工作負載。但是,這是一個可行的管道,可用於從真實的生產伺服器載入指標。然後可以改進模型,以解決 DevOps 自動化的實際問題。