Esta página foi traduzida pela API Cloud Translation.
Switch to English

Carregar métricas do servidor Prometheus

Ver no TensorFlow.org Executar no Google Colab Ver fonte no GitHub Baixar caderno

Visão geral

Este tutorial carrega métricas CoreDNS de um servidor Prometheus em umtf.data.Dataset , em seguida, usa tf.keras para treinamento e inferência.

CoreDNS é um servidor DNS com foco na descoberta de serviço e é amplamente implantado como parte do cluster Kubernetes . Por esse motivo, muitas vezes é monitorado de perto pelas operações devops.

Este tutorial é um exemplo que pode ser usado por desenvolvedores que buscam automação em suas operações por meio do aprendizado de máquina.

Configuração e uso

Instale o pacote tensorflow-io necessário e reinicie o tempo de execução

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

Instale e configure o CoreDNS e o Prometheus

Para fins de demonstração, um servidor CoreDNS localmente com a porta 9053 aberta para receber consultas DNS e a porta 9153 (padrão) aberta para expor as métricas para eliminação. A seguir está uma configuração básica de Corefile para CoreDNS e está disponível para download :

.:9053 {
  prometheus
  whoami
}

Mais detalhes sobre a instalação podem ser encontrados na documentação do 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 &')

A próxima etapa é configurar o servidor Prometheus e usar o Prometheus para extrair as métricas CoreDNS que são expostas na porta 9153 acima. O arquivo prometheus.yml para configuração também está disponível para download :

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

Para mostrar alguma atividade, o comando dig pode ser usado para gerar algumas consultas DNS contra o servidor CoreDNS que foi configurado:

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


Agora um servidor CoreDNS cujas métricas são removidas por um servidor Prometheus e prontas para serem consumidas pelo TensorFlow.

Crie conjuntos de dados para métricas CoreDNS e use-o no TensorFlow

Criar um conjunto de dados para métricas CoreDNS que está disponível no servidor PostgreSQL, pode ser feito comtfio.experimental.IODataset.from_prometheus . No mínimo, dois argumentos são necessários. query é passada ao servidor Prometheus para selecionar as métricas e a length é o período que você deseja carregar no Dataset.

Você pode começar com "coredns_dns_request_count_total" e "5" (segundos) para criar o conjunto de dados abaixo. Como no início do tutorial duas consultas DNS foram enviadas, espera-se que as métricas para "coredns_dns_request_count_total" sejam "2.0" no final da série temporal:

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

Analisando mais detalhadamente as especificações do conjunto de dados:

(
  TensorSpec(shape=(), dtype=tf.int64, name=None),
  {
    'coredns': {
      'localhost:9153': {
        'coredns_dns_request_count_total': TensorSpec(shape=(), dtype=tf.float64, name=None)
      }
    }
  }
)

É óbvio que o conjunto de dados consiste em uma tupla (time, values) que o campo de values é um dicionário python expandido para:

"job_name": {
  "instance_name": {
    "metric_name": value,
  },
}

No exemplo acima, 'coredns' é o nome do trabalho, 'localhost:9153' é o nome da instância e 'coredns_dns_request_count_total' é o nome da métrica. Observe que, dependendo da consulta do Prometheus usada, é possível que vários trabalhos / instâncias / métricas possam ser retornados. Este também é o motivo pelo qual python dict foi usado na estrutura do Dataset.

Pegue outra consulta "go_memstats_gc_sys_bytes" como exemplo. Como CoreDNS e Prometheus são escritos em Golang, a métrica "go_memstats_gc_sys_bytes" está disponível para os trabalhos "coredns" e "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

O Dataset criado está pronto para ser passado para tf.keras diretamente para fins de treinamento ou inferência agora.

Use o conjunto de dados para o treinamento do modelo

Com o Dataset de métricas criado, é possível passar diretamente o Dataset para tf.keras para treinamento do modelo ou inferência.

Para fins de demonstração, este tutorial usará apenas um modelo LSTM muito simples com 1 recurso e 2 etapas como entrada:

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')

O conjunto de dados a ser usado é o valor de 'go_memstats_sys_bytes' para CoreDNS com 10 amostras. No entanto, uma vez que uma janela deslizante de window=n_steps e shift=1 são formados, amostras adicionais são necessárias (para quaisquer dois elementos window=n_steps , o primeiro é considerado como x o segundo é considerado como y para treinamento). O total é 10 + n_steps - 1 + 1 = 12 segundos.

O valor dos dados também é escalado para [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>

O modelo treinado acima não é muito útil na realidade, pois o servidor CoreDNS que foi configurado neste tutorial não tem nenhuma carga de trabalho. No entanto, este é um pipeline de trabalho que pode ser usado para carregar métricas de verdadeiros servidores de produção. O modelo poderia então ser aprimorado para resolver o problema do mundo real da automação de devops.