Visualizza su TensorFlow.org | Esegui in Google Colab | Visualizza l'origine su GitHub | Scarica quaderno |
Panoramica
Questa esercitazione carica CoreDNS metriche da un Prometheus server in un tf.data.Dataset
, quindi utilizza tf.keras
per la formazione e l'inferenza.
CoreDNS è un server DNS con particolare attenzione alla individuazione dei servizi, ed è ampiamente utilizzato come una parte del kubernetes cluster. Per questo motivo è spesso monitorato da vicino dalle operazioni di devops.
Questo tutorial è un esempio che potrebbe essere utilizzato dai devop che cercano l'automazione nelle loro operazioni attraverso l'apprendimento automatico.
Configurazione e utilizzo
Installa il pacchetto tensorflow-io richiesto e riavvia il runtime
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
Installa e configura CoreDNS e Prometheus
Per demo scopi, un server CoreDNS a livello locale con la porta 9053
aperta a ricevere le query DNS e la porta 9153
(defult) aperto per esporre le metriche per raschiare. Quanto segue è una configurazione di base per corefile CoreDNS ed è disponibile per scaricare :
.:9053 {
prometheus
whoami
}
Maggiori informazioni su l'installazione potrebbe essere trovato su di CoreDNS documentazione .
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 &')
Il passo successivo è quello di server di Prometheus di installazione e utilizzare Prometeo a metriche CoreDNS raschiatura che sono esposti sulla porta 9153
dall'alto. Il prometheus.yml
file di configurazione è disponibile per anche per scaricare :
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 &')
Al fine di mostrare una certa attività, dig
di comando potrebbe essere usato per generare un paio di query DNS contro il server CoreDNS che è stata messa a punto:
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
Ora un server CoreDNS le cui metriche vengono raschiate da un server Prometheus e pronte per essere utilizzate da TensorFlow.
Crea set di dati per le metriche CoreDNS e utilizzalo in TensorFlow
Creazione di un set di dati per CoreDNS metriche che è disponibile da server PostgreSQL, potrebbe essere fatto con tfio.experimental.IODataset.from_prometheus
. Al minimo sono necessari due argomenti. query
viene passato al server Prometheus per selezionare le metriche e length
è il periodo che si desidera caricare nel set di dati.
Si può iniziare con "coredns_dns_request_count_total"
e "5"
(sec) per creare il set di dati di seguito. Dal momento che in precedenza nel tutorial due query DNS sono stati inviati, si prevede che le metriche per "coredns_dns_request_count_total"
saranno "2.0"
alla fine della serie di tempo:
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
Esaminando ulteriormente le specifiche del set di dati:
(
TensorSpec(shape=(), dtype=tf.int64, name=None),
{
'coredns': {
'localhost:9153': {
'coredns_dns_request_count_total': TensorSpec(shape=(), dtype=tf.float64, name=None)
}
}
}
)
È ovvio che il set di dati è costituito da un (time, values)
tupla cui il values
di campo è un dict pitone espanso in:
"job_name": {
"instance_name": {
"metric_name": value,
},
}
Nell'esempio di cui sopra, 'coredns'
è il nome del processo, 'localhost:9153'
è il nome di istanza, e 'coredns_dns_request_count_total'
è il nome della metrica. Si noti che, a seconda della query Prometheus utilizzata, è possibile che vengano restituiti più lavori/istanze/metriche. Questo è anche il motivo per cui python dict è stato utilizzato nella struttura del Dataset.
Prendete un'altra query "go_memstats_gc_sys_bytes"
come esempio. Dal momento che entrambi CoreDNS e Prometheus sono scritti in Golang, "go_memstats_gc_sys_bytes"
metrica è disponibile sia per "coredns"
di lavoro e "prometheus"
di posti di lavoro:
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
Il creato Dataset
è pronto per essere passato a tf.keras
direttamente sia per scopi di addestramento o di inferenza ora.
Usa il set di dati per l'addestramento del modello
Con metriche Dataset creato, è possibile passare direttamente il set di dati per tf.keras
per la formazione modello o inferenza.
A scopo dimostrativo, questo tutorial utilizzerà semplicemente un modello LSTM molto semplice con 1 funzione e 2 passaggi come input:
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')
Il set di dati da utilizzare è il valore di 'go_memstats_sys_bytes' per CoreDNS con 10 campioni. Tuttavia, poiché una finestra scorrevole di window=n_steps
e shift=1
sono formati, sono necessari ulteriori campioni (per ogni due elementi consecute, la prima è preso come x
e la seconda è preso come y
per la formazione). Il totale è 10 + n_steps - 1 + 1 = 12
secondi.
Il valore del dato è anche scalata a [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>
Il modello addestrato sopra non è molto utile in realtà, poiché il server CoreDNS che è stato configurato in questo tutorial non ha alcun carico di lavoro. Tuttavia, questa è una pipeline funzionante che può essere utilizzata per caricare le metriche da veri server di produzione. Il modello potrebbe quindi essere migliorato per risolvere il problema del mondo reale dell'automazione devops.