Книга Облачная экосистема - читать онлайн бесплатно, автор Евгений Сергеевич Штольц. Cтраница 5
bannerbanner
Вы не авторизовались
Войти
Зарегистрироваться
Облачная экосистема
Облачная экосистема
Добавить В библиотекуАвторизуйтесь, чтобы добавить
Оценить:

Рейтинг: 0

Добавить отзывДобавить цитату

Облачная экосистема


essh@kubernetes-master:~/prometheus$ cat << EOF > ./prometheus.yml

global:

scrape_interval: 1s

evaluation_interval: 1s


scrape_configs:

– job_name: 'prometheus'


static_configs:

– targets: ['127.0.0.1:9090', '127.0.0.1:9100', '127.0.0.1:9323']

labels:

group: 'prometheus'

EOF


essh@kubernetes-master:~/prometheus$ docker rm -f prometheus

prometheus


essh@kubernetes-master:~/prometheus$ docker run \

–d \

–-net=host \

–-restart always \

–-name prometheus \

–v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml

prom/prometheus

7dd991397d43597ded6be388f73583386dab3d527f5278b7e16403e7ea633eef


essh@kubernetes-master:~/prometheus$ docker ps \

–f name=prometheus

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES

7dd991397d43 prom/prometheus "/bin/prometheus –c…" 53 seconds ago Up 53 seconds prometheus

Теперь доступно 1702 метрики хоста:

essh@kubernetes-master:~/prometheus$ curl http://localhost:9100/metrics | grep -v '#' | wc -l

1702

из всего разнообразия сложно искать нужные для повседневных задач, например, используемое количество памяти node_memory_Active. Для этого есть агрегаторы метрик:

http://localhost:9090/consoles/node.html

http://localhost:9090/consoles/node-cpu.html

Но лучше использовать Grafana. Установим и её, пример можно посмотреть:

essh@kubernetes-master:~/prometheus$ docker run \

–d \

–-name=grafana \

–-net=host

grafana/grafana

Unable to find image 'grafana/grafana:latest' locally

latest: Pulling from grafana/grafana

9d48c3bd43c5: Already exists

df58635243b1: Pull complete

09b2e1de003c: Pull complete

f21b6d64aaf0: Pull complete

719d3f6b4656: Pull complete

d18fca935678: Pull complete

7c7f1ccbce63: Pull complete

Digest: sha256:a10521576058f40427306fcb5be48138c77ea7c55ede24327381211e653f478a

Status: Downloaded newer image for grafana/grafana:latest

6f9ca05c7efb2f5cd8437ddcb4c708515707dbed12eaa417c2dca111d7cb17dc


essh@kubernetes-master:~/prometheus$ firefox localhost:3000

Введем логин admin и пароль admin, после чего нам предложат изменить пароль. Далее нужно выполнить последующую настройку.

В Grafana первоначальный вход по логину admin и такому паролю. Сперва на предлагается выбрать источник – выбираем Prometheus, вводим localhost:9090, выбираем подключение не как к серверу, а как к браузеру (то есть по сети) и выбираем, что аутентификация у нас базовая – все – нажимаем Save and Test и Prometheus подключен.

Понятно, что всем раздавать пароль и логин от админских прав не стоит. Для этого нужно будет завести пользователей или интегрировать их внешней базой данных пользователей, такой как Microsoft Active Directory.

Я выберу во вкладке Dashboard активирую все три перенастроенных дашборда. Из списка New Dashboard верхнего меню выберу дашборд Prometheus 2.0 Stats. Но, данных нет:

Кликну на пункт меню "+" и выберу "Dashboard", предлагается создать дашборд. Дашборд может содержать несколько виджетов, например графики, которые можно располагать и настраивать, поэтому нажимаем на кнопку добавления графика и выбираем его тип. На самом графике выбираем редактировать, выбрав размер, нажимаем редактировать, и тут самое главное – выбор демонстрируемой метрики. Выбираем Prometheus

Полная сборка доступна:

essh@kubernetes-master:~/prometheus$ wget \

https://raw.githubusercontent.com/grafana/grafana/master/devenv/docker/ha_test/docker-compose.yaml


--2019-10-30 07:29:52– https://raw.githubusercontent.com/grafana/grafana/master/devenv/docker/ha_test/docker-compose.yaml

Resolving raw.githubusercontent.com (raw.githubusercontent.com)… 151.101.112.133

Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.112.133|:443… connected.

HTTP request sent, awaiting response… 200 OK

Length: 2996 (2,9K) [text/plain]

Saving to: ‘docker-compose.yaml’


docker-compose.yaml 100%[=========>] 2,93K –.-KB/s in 0s


2019-10-30 07:29:52 (23,4 MB/s) – ‘docker-compose.yaml’ saved [2996/2996]

Получение прикладных метрик приложения

До этого момента мы рассматривали случай, когда Prometheus опрашивал стандартный накопитель метрик, получая стандартные метрики. Теперь попробуем создать приложение и отдавать свои метрики. Для начала возьмём сервер NodeJS и напишем под него приложение. Для этого, создадим проект NodeJS:

vagrant@ubuntu:~$ mkdir nodejs && cd $_


vagrant@ubuntu:~/nodejs$ npm init

This utility will walk you through creating a package.json file.

It only covers the most common items, and tries to guess sensible defaults.


See `npm help json` for definitive documentation on these fields

and exactly what they do.


Use `npm install < pkg> –save` afterwards to install a package and

save it as a dependency in the package.json file.


name: (nodejs)

version: (1.0.0)

description:

entry point: (index.js)

test command:

git repository:

keywords:

author: ESSch

license: (ISC)

About to write to /home/vagrant/nodejs/package.json:


{

"name": "nodejs",

"version": "1.0.0",

"description": "",

"main": "index.js",

"scripts": {

"test": "echo \"Error: no test specified\" && exit 1"

},

"author": "ESSch",

"license": "ISC"

}


Is this ok? (yes) yes

Для начала создадим WEB-сервер. Я воспользуюсь библиотекой для его создания:

vagrant@ubuntu:~/nodejs$ npm install Express –save

npm WARN deprecated Express@3.0.1: Package unsupported. Please use the express package (all lowercase) instead.

nodejs@1.0.0 /home/vagrant/nodejs

└── Express@3.0.1

npm WARN nodejs@1.0.0 No description

npm WARN nodejs@1.0.0 No repository field.


vagrant@ubuntu:~/nodejs$ cat << EOF > index.js

const express = require('express');

const app = express();

app.get('/healt', function (req, res) {

res.send({status: "Healt"});

});

app.listen(9999, () => {

console.log({status: "start"});

});

EOF


vagrant@ubuntu:~/nodejs$ node index.js &

[1] 18963

vagrant@ubuntu:~/nodejs$ { status: 'start' }


vagrant@ubuntu:~/nodejs$ curl localhost:9999/healt

{"status":"Healt"}

Наш сервер готов к работе с Prometheus. Нам нужно настроить Prometheus на него.

Проблема масштабирования Prometheus возникает, когда данные не помещаются на один сервер, точнее, когда один сервер не успевает записывать данные и когда обработка данных одним сервером не устраивает по перформансу. Thanos решает эту проблему, не требуя настройки федерации, предоставляя пользователю интерфейс и API, которые он транслирует на инстансы Prometheus. Пользователем доступен веб-интерфейс, аналогичный Prometheus. Сам он взаимодействует с агентами, которые установлены на инстансах как side-car, как это делает Istio. Он и агенты доступны как контейнера и как Helm-чарт. Например, агент может быть поднят как контейнер, настроенный на Prometheus, а Prometheus настраивается конфигом с последующей перезагрузкой.

docker run –rm quay.io/thanos/thanos:v0.7.0 –help

docker run -d –net=host –rm \

–v $(pwd)/prometheus0_eu1.yml:/etc/prometheus/prometheus.yml \

–-name prometheus-0-sidecar-eu1 \

–u root \

quay.io/thanos/thanos:v0.7.0 \

sidecar \

–-http-address 0.0.0.0:19090 \

–-grpc-address 0.0.0.0:19190 \

–-reloader.config-file /etc/prometheus/prometheus.yml \

–-prometheus.url http://127.0.0.1:9090

Важной составляющей мониторинга являются уведомления. Уведомления состоят из триггеров срабатывания и провайдера. Триггер срабатывания пишется на PromQL как правило с условием в Prometheus. Когда сработал триггер (условие по метрике), Prometheus сигнализирует провайдеру отправить уведомление. Стандартным провайдером является Alertmanager и он способен отравлять сообщения в различные приёмники, такие как электронная почта и Slack.

, Например, метрика "up", принимающая значения 0 или 1, может быть использована, чтобы отравлять сообщение, если сервер выключен более 1 минуты. Для этого записывается правило:

groups:

– name: example

rules:

– alert: Instance Down

expr: up == 0

for: 1m

Когда метрика более 1 минуты равняется 0, то срабатывает этот триггер и Prometheus отравляет запрос на Alertmanager. В Alertmanager прописано, что делать с этим событием. Мы можем прописать, что при получении события InstanceDown нужно отравлять сообщение на почту. Для этого сконфигурируем Alertmanager это сделать:

global:

smtp_smarthost: 'localhost:25'

smtp_from: 'youraddress@example.org'

route:

receiver: example-email

receivers:

– name: example-email

email_configs:

– to: 'youraddress@example.org'

Сам Alertmanager воспользуется установленным протоколом на этом компьютере. Для того, чтобы он смог это сделать, его нужно установить. Возьмём, к примеру, протокол SMTP (Simple Mail Transfer Protocol). Для проверки, установим консольный почтовый сервер в параллель с Alert Manager – sendmail.

Быстрый и наглядный анализ логов системы

Для быстрого поиска по логам используется OpenSource движок полнотекстового поиска Lucene. На его основе были построены два низкоуровневых продукта: Sold и Elasticsearch, довольно сходных по возможностям, но отличающихся по удобству использования и лицензии. На их построены многие популярные сборки, например, просто набор поставки с ElasticSearch: ELK (Elasticsearch(Apache Lucene), Logstash, Kibana), EFK (Elasticsearch, Fluentd, Kibana), так и продукты, например, GrayLog2. Как GrayLog2, так и сборки (ELK/EFK) активно используются из-за меньшей необходимости настраивать не тестовых стендах, так, например, поставить EFK в кластере Kubernetes можно практически одной командой


helm install efk-stack stable/elastic-stack –set logstash.enabled=false –set fluentd.enabled=true –set fluentd-elastics

Альтернативой, пока не получившей большого рассмотрения являются системы, построенные на рассмотренном ранее Prometheus, например, PLG (Promtail(агент) – Loki(Prometheus) – Grafana).

Сравнение ElasticSearch и Sold (системы сопоставимы):

Elastic:

** Коммерческий с открытым кодом и возможность коммитить (через апрув);

** Поддерживает более сложные запросы, больше аналитики, поддержка из коробки распределенных запросов, более полный REST-full JSON-BASH, чейнинг, машинное обучение, SQL (платный);

*** Full-text search;

*** Real-time index;

*** Мониторинг (платный);

*** Мониторинг через Elastic FQ;

*** Машинное обучение (платно);

*** Простая индексация;

*** Больше типов данных и структур;

** Движок Lucene;

** Parent-child (JOIN);

** Scalable native;

** Документация с 2010;

Solr:

** OpenSource;

** Большая скорость при JOIN;

*** Full-text search;

*** Real-time index;

*** Мониторинг в админке;

*** Машинное обучение через модули;

*** Входные данные: Work, PDF и другие;

*** Необходима схемы для индексации;

*** Данные: вложенные объекты;

** Движок Lucene;

** JSON join;

** Scalable: Solar Cloud (настройка) && ZooKeeper (настройка);

** Документация с 2004.


В нынешнее время всё чаще применяется микро сервисная архитектура, которая позволяет за счёт слабой

связанности между своими компонентами и их простоты упростить их разработку, тестирование и отладку.

Но в целом систему из-за её распределённости становится сложнее анализировать. Для анализа состояния

в целом применяются логи, собираемые в централизованное место и преобразуемые в понятный вид. Также возникает

необходимость в анализе других данных, например, access_log NGINX, для сбора метрик о посещаемости, лога почты,

почтового сервера для выявления попытки подбора пароля и т.д. Примером такого решения возьмём ELK. Под ELK понимается

связка трёх продуктов: Logstash, Elasticsearch и Kubana, первый и последний из который сильно заточены на центральный и

обеспечивают удобство работы. Более обобщённо ELK называют Elastic Stack, так как инструмент подготовки логов Logstash

может быть заменён аналогом, например Fluentd или Rsyslog, а средство визуализации Kibana – на Grafana. Например, хоть и

Kibana предоставляет большие возможности для анализа, Grafana предоставляет отправку уведомлений при возникновениях событий, и

может использоваться совместно с другими продуктами, например, CAdVisor – анализа состояния системы и отдельных контейнеров.

Продукты EKL могут быть установлены самостоятельно, скачаны в виде самодостаточных контейнеров, для которых нужно настроить

связь или в виде одного контейнера.


Для нормальной работы Elasticsearch нужно, чтобы данные приходили в формате JSON. Если данные предавать в

текстовом формате (лог пишется одной строкой, отделяется от предыдущий переносом строки), то он сможет

предоставить только полнотекстовый поиск, так как они будут восприниматься одной строкой. Для передачи

логов в формате JSON имеется два варианта: или настроить исследуемый продукт выдавать в этом формате,

например, для NGINX имеется такая возможность. Но, зачастую это невозможно, так как имеется уже

накопленная база логов, а традиционно они пишутся в текстовом формате. Для таких случаев необходима

пост обработка логов из текстового формата в JSON, которой занимается Logstash. Важно заметить, что если

есть возможность сразу же передавать данные в структурированном виде (JSON, XML и других), то следует это

сделать, так как если сделать детальный парсинг, то любое отклонение одностороннее отклонение от формата

приведёт с неработоспособности, а при поверхностном – теряем ценную информацию. В любом случае парсинг в

этот системе является узким горлышком, хотя может ограниченно масштабироваться до сервиса или лога

файла. К счастью, всё больше и больше продуктов начинают поддерживать структурированные логи, например,

последние версии NGINX поддерживает логи в JSON формате.


Для систем, не поддерживающих данный формат можно использовать преобразование к нему с помощью таких

программ, как Logstash, File bear и Fluentd. Первый из них входит в стандартную поставку Elastic Stack от вендора

и может быть установлен одним образом ELK в Docker – контейнер. Он поддерживает получение данных от файлов, сети и

стандартного потока как на входе, так и на выходе, а главное нативно внутренний протокол Elastic Search.

Logstash мониторит log-файлы на основе даты изменения или получает по сети данные по telnet от распределённой

системы, например, контейнеров и после преобразования отравляет на выход, обычно, в Elastic Search. Он прост и

входит в стандартную поставку с Elastic Stack, благодаря чему просто и беспроблемно настраивается. Но благодаря

Java машине внутри тяжёл и не сильно функционален, хотя и поддерживает плагины, например, синхронизации с MySQL

для отправки новых данных. Чуть больше возможностей предоставляет Filebeat. Энтерпрайзным инструментом на все

случаи жизни может служить Fluentd благодаря высокой функциональности (чтение логов, системных журналов и т.д.),

масштабируемости и возможности раскатки по кластерам Kubernetes с помощью Helm чарта, и мониторинг всего

дата-центра в стандартной поставке, но об этом соответствующем разделе.


Для управления логов можно воспользоваться Curator, который сможет архивировать из ElasticSearch старые

логи или их удалять, повышая эффективность его работы.


Процесс получения логов логичен осуществляется специальными сборщиками: logstash, fluentd, filebeat или

другими.

fluentd наименее требовательный и более простой аналог Logstash. Настройка

производится в /etc/td-agent/td-agent.conf, который содержит четыре блока:

** match – содержит настройки передачи полученных данных;

** include – содержит информацию о типах файлов;

** system – содержит настройки системы.

Logstash представляет гораздо более функциональный язык конфигураций. Logstash демон агента – logstash мониторит

изменения в файлах. Если же логи находятся не локально, а на распределённой системе, то устанавливается logstash на каждый сервер и

запускается в режиме агента bin/logstash agent -f /env/conf/my.conf. Поскольку запускать

logstash только в качестве агента для пересылки логов расточительно, то можно использовать продукт от тех

же разработчиков Logstash Forwarder (ранее Lumberjack) пересылающий логи по протоколу lumberjack к

logstash серверу. Для отслеживания и получения данных с MySQL можно использовать агент Packetbeat

(https://www.8host.com/blog/sbor-metrik-infrastruktury-s-pomoshhyu-packetbeat-i-elk-v-ubuntu-14-04/).

Также logstash позволяет преобразовать данные разного типа:

** grok – задать регулярные выражения выдирания полей из строки, часто для логов из текстового формата в JSON;

** date – в случае архивных логов проставить дату создания лога не текущей датой, а взять её из самого лога;

** kv – для логов типа key=value;

** mutate – выбрать только нужные поля и изменить данные в полях, например, произвести замену символа "/" на "_";

** multiline – для многострочных логов с разделителями.

Пример, можно лог в формате "дата тип число" разложить на составляющие, например "01.01.2021 INFO 1" разложить в хэш "message":

filter {

grok {

type => "my_log"

match => ["message", "%{MYDATE:date} %{WORD:loglevel} ${ID.id.int}"]

}

}

Шаблон ${ID.id.int} берёт класс – шаблон ID, полученное значение будет подставлено в поле id и строковое значение будет преобразовано к типу int.

В блоке «Output» мы можем указать: выводить данные в консоль с помощью блока "Stdout", в файл – "File", передавать по http через JSON REST API – "Elasticsearch" или отравлять по почте – "Email". Также можно заказать условия по полям, полученным в блоке filter. Например,:

output {

if [type] == "Info" {

elasticsearch {

host => localhost

index => "log-%{+YYYY.MM.dd}"

}

}

}


Здесь индекс Elasticsearch (база данных, если проводить аналогию с SQL) меняется каждый день. Для создания нового индекса не нужно его специально создавать – так поступают БД NoSQL, так как нет жёсткого требования описывать структуру – свойство и тип. Но всё же описать рекомендуется, иначе все поля будут со строковыми значениями, если не задано число. Для отображения данных Elasticsearch используется плагин WEB-ui интерфейса на AngularJS – Kibana. Для отображения временной шкалы в её графиках нужно описать хотя бы одно поле с типом дата, а для агрегатных функция – числовое, будь то целое или с плавающей точкой. Также, если добавляются новые поля, для их индексации и отображения требуется произвести пере индексацию всего индекса, поэтому наиболее полное описание структуры поможет избежать очень трудозатратные операции – переиндексации.

Разделение индекса по дням сделано для ускорения работы Elasticsearch, а в Kibana можно выбрать несколько по шаблону, здесь log-*, также снимается ограничение в один миллион документов на индекс.

Рассмотрим более подробный плагин вывода у Logstash:

output {

if [type] == "Info" {

elasticsearch {

claster => elasticsearch

action => "create"

hosts => ["localhost:9200"]

index => "log-%{+YYYY.MM.dd}"

document_type => ....

document_id => "%{id}"

}

}

}


Взаимодействии с ElasticSearch осуществляется через JSON REST API, драйвера для которых есть для большинства современных языков. Но для того, чтобы не писать код, мы воспользуемся утилитой Logstash, которая также он умеет преобразовывать текстовые данные в JSON на основе регулярных выражений. Также есть заготовленные шаблоны, наподобие классов в регулярных выражениях, таких как %{IP:client } и других, которые можно посмотреть по https://github.com/elastic/logstash/tree/v1.1.9/patterns. Для стандартных сервисов со стандартными настройками в интернете есть множество готовых конфигов, например, для NGINX – https://github.com/zooniverse/static/blob/master/logstash— Nginx.conf. Более подобно описано в статье https://habr.com/post/165059/.

ElasticSearch – NoSQL база данных, поэтому не нужно задавать формат (набор полей и его типы). Для поиска ему он всё же нужен, поэтому он сам его определяет, и при каждом смене формата происходит пере индексации, при котором работа невозможно. Для поддержания унифицированной структуры в логгере Serilog (DOT Net) есть поле EventType в которое можно зашифровать набор полей и их типы, для остальных придётся реализовывать отдельно. Для анализа логов от приложения микро сервисной архитектуры важно задать ID пока выполнения, то есть ID запроса, который будет неизменен и передаваться от микросервиса к микросервису, чтобы можно было проследить весь путь выполнения запроса.

Установим ElasticSearch (https://habr.com/post/280488/) и проверим работу curl -X GET localhost:9200

sudo sysctl -w vm.max_map_count=262144

$ curl 'localhost:9200/_cat/indices?v'

health status index uuid pri rep docs.count docs.deleted store.size pri.store.size

green open graylog_0 h2NICPMTQlqQRZhfkvsXRw 4 0 0 0 1kb 1kb

green open .kibana_1 iMJl7vyOTuu1eG8DlWl1OQ 1 0 3 0 11.9kb 11.9kb

yellow open indexname le87KQZwT22lFll8LSRdjw 5 1 1 0 4.5kb 4.5kb

yellow open db i6I2DmplQ7O40AUzyA-a6A 5 1 0 0 1.2kb 1.2kb

Создадим запись в базе данных blog и таблице post curl -X PUT "$ES_URL/blog/post/1?pretty" -d'

Поисковой движок ElasticSearch

В предыдущем разделе мы рассмотрели стек ELK, который составляют ElasticSearch, Logstash и Kibana. В полном наборе, а часто его ещё расширяют Filebeat – более заточенный на работу с расширение Logstash, для работы с текстовыми логами. Несмотря на то, что Logstash выполняет быстро свою задачу без необходимости, не используют, а логи в формате JSON отравляют через API загрузки дампа прямо в Logstash.

Если же у нас приложение, то применяется чистый ElasticSearch, который используется как поисковой движок, а Kibana используется как средство написания и отладки запросов – блок Dev Tools. Хотя и базы реляционные данных имеют долгую историю развития, всё же остаётся принцип, что чем более данные деморализованы, тем они медленнее, ведь их приходится при каждом запросе объединять. Данная проблема решается созданием View, в которой хранится результирующая выборка. Но хоть современные базы данных обзавелись внушительным функционалом, вплоть до полнотекстового поиска, но всё же им не сравниться в эффективности и функциональности поиска с поисковыми движками. Приведу пример с работы: несколько таблиц с метриками, который объединяются в запросе в одну, и производится поиск по выбранным параметрам в админке, таким как диапазон дат, страница в пагинации и содержания в сроке столбца чата. Данный не много, на выходе получаем таблицу в пол миллиона строк, да и поиск по дате и части строки укладывается в миллисекунды. А вот пагинации тормозит, в начальных страницах её запрос выполняется около двух минут, в конечных – более четырёх. При этом объединить запрос на логичен данных и на получения пагинации в лоб не получится. А тот же зарос, при этом он не оптимизирован, в ElasticSearch выполняется за 22 миллисекунды и содержит как данные и, так и число всех данных для пагинации.

Стоит предостеречь читателя от отказа от необдуманной реляционной базы данных, хотя и ElasticSearch содержит в себе NoSQL базу данных, но она предназначена исключительно для поиска и не содержит полноценных средств для нормализации и восстановления.

ElasticSearch не имеет в стандартной поставке консольного клиента – всё взаимодействие осуществляется через http вызовы GET, PUT и DELETE. Приведём пример использования с использованием программы (команды) Curl из программной оболочки BASH ОС linux:

#Создание записей (таблица и база данных создаются автоматически)

curl -XPUT mydb/mytable/1 -d'{

....

}'


#Получен значения по id

curl -XGET mydb/mytable/1

curl -XGET mydb/mytable/1


#Простой поиск

curl -XGET mydb -d'{

"search": {

"match": {

"name": "my"

}

}

}'


#Удаление базы

curl -XDELETE mydb


Облачные системы, как источник непрерывного масштабирования: Google Cloud и Amazon AWS