Carica metriche dal server Prometheus

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.