טען מדדים משרת פרומתאוס

הצג באתר TensorFlow.org הפעל בגוגל קולאב צפה במקור ב-GitHub הורד מחברת

סקירה כללית

המון הדרכה זו מדדי CoreDNS מתוך פרומתאוס שרת לתוך 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 (defult) וחושפים מדדים עבור גרידה. להלן תצורה בסיסית Corefile עבור CoreDNS והוא זמין להורדה :

.: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 &')

השלב הבא הוא שרת הגדרת פרומתאוס ולהשתמש פרומתאוס למדדי CoreDNS לִמְלוֹל חשוף ביציאה 9153 מלמעלה. 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 הפקודה יכול לשמש כדי ליצור כמה שאילתות DNS מול שרת CoreDNS כי כבר ההתקנה:

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

צור מערך נתונים עבור מדדי CoreDNS זמין שירת PostgreSQL, יכול להיעשות עם tfio.experimental.IODataset.from_prometheus . במינימום יש צורך בשני טיעונים. query מועבר לשרת פרומתאוס כדי לבחור את המדדים length היא התקופה שאתה רוצה לטעון לתוך בסיס הנתונים.

אתה יכול להתחיל עם "coredns_dns_request_count_total" ו "5" (שניות) כדי ליצור את בסיס הנתונים שלהלן. מאז מוקדם יותר לשאילתות 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) tuple שבו values השדה הוא נחש פיתון 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 ו פרומתאוס כתוב 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 לאימונים או היסק מודל.

למטרות הדגמה, הדרכה זו רק תשתמש במודל LSTM פשוט מאוד עם תכונה אחת ו-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')

מערך הנתונים שבו יש להשתמש הוא הערך של 'go_memstats_sys_bytes' עבור CoreDNS עם 10 דוגמאות. עם זאת, מאז חלון הזזה של window=n_steps ואת shift=1 נוצרות, דגימות נוספים נדרשים (עבור כל שני אלמנטים consecute, הראשון נלקח כמו 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="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 שהוגדר במדריך זה אין עומס עבודה כלשהו. עם זאת, זהו צינור עובד שיכול לשמש לטעינת מדדים משרתי ייצור אמיתיים. לאחר מכן ניתן לשפר את המודל כדי לפתור את בעיית העולם האמיתי של אוטומציה של devops.