- PVSM.RU - https://www.pvsm.ru -
В начале моего изучения Docker и Kubernetes мне нехватало простого и понятного примера, с которым можно было бы «поиграться», изучая особенности этой среды. Этой статьей хотелось бы закрыть этот пробел. Здесь я расскажу об интеграции .NET Core приложения с Telegraf и Grafana, о том, как шлются метрики и как деплоить в Docker и Kubernetes. Примеры в статье расчитаны на тех, кто начинает изучать данную область, но базовыми понятиями желательно обладать, чтобы полностью понять статью. В ней описано, как развернуть контейнер, в котором есть StatsD, InfluxDB и Grafana, а также, как отправлять метрики различных типов из приложения.
Примеры в этой статье выполнялись на Kubernetes, идущем с Docker for Windows. Но если у вас Windows Home Edition, то вам не удастся его поставить. Если у вас Windows Professional, то проблем возникнуть не должно. Тут [1] есть пара советов по установке kubernetes на Windows. На Linux должно всё работать нормально, проверял на Ubuntu, 18.04 LTS.
Сперва, давайте посмотрим, как всё, о чем буду рассказывать, выглядит в действии. В этом примере вы запустите два приложения: одно отправляет запросы другому, второе выполняет некоторую сложную задачу, и оба приложения отправляют некоторые StatsD метрики, которые вы увидите в Grafana. Перед выполнением шагов, описанных здесь, вам необходимо убедиться, что Kubernetes установлен на вашем компьютере. Далее просто следуйте приведенным ниже инструкциям, и вы увидите некоторый результат. Правда, некоторые настройки вам нужно будет выполнить самостоятельно.
$ git clone https://github.com/xtrmstep/DockerNetSample
$ cd .DockerNetSample
$ kubectl apply -f .srcStatsDServerk8s-deployment.yaml
$ .build.ps1
$ .run.ps1
Теперь в браузере можно загрузить URL localhost [2]:3003 и, используя учетные данные root/root, можно получить доступ к интерфейсу Grafana. Метрики уже отправляются, и вы можете попробовать добавить свой дэшбоард. После некоторой настройки вы можете получить что-то вроде этого.
Когда вы решите всё остановить и очистить ресурсы, просто закройте два окна с рабочими процессами и выполните следующие команды, которые очистят объекты в Kubernetes:
$ kubectl delete svc stats-tcp
$ kubectl delete svc stats-udp
$ kubectl delete deployment stats
Теперь давайте поговорим, что произошло.
Не так давно открыл для себя, что DockerHub имеет много полезных и уже подготовленных образов. В своём примере я использую один из таких. Репозиторий с образом вы можете найти здесь [3]. Этот образ содержит InfluxDB, Telegraf (StatsD) и Grafana, которые уже настроены для совместной работы. Есть два распространенных способа деплоя образов: первый — это используя docker-compose в Docker, и второй — это деплой на Kubernetes. Оба способа дают возможность деплоить сразу несколько компонетов (образов), описывать настройки сети и другие параметры. Я кратко расскажу о docker-compose, но более детально остановлюсь на развертывании в Kubernetes. Кстати, недавно стало возможным деплоить docker-compose в Kubernetes [4].
Docker-compose распространяется вместе с Docker для Windows. Но вам нужно проверить, какую версию вы можете использовать в своем YAML. Для этого надо узнать версию установленного Docker и по матрице совместимости [5] найти нужную версию. Я установил Docker версии 19.03.5, поэтому я могу использовать файл версии 3.x. Но я буду использовать 2 для совместимости с прошлыми версиями Docker. Вся необходимая информация для написание docker-compose файлы уже есть в описании репозитория: имя образа и порты.
version: '2'
services:
stats:
image: samuelebistoletti/docker-statsd-influxdb-grafana:latest
ports:
- "3003:3003"
- "3004:8888"
- "8086:8086"
- "8125:8125/udp"
В секции ports я делаю видимыми порты из контейнера через порты хост-системы. Если я этого не сделаю, я не смогу получить доступ к ресурсам в контейнере из хост-системы, потому что они будут видны только внутри Docker. Грубо говоря, я не смогу загрузить Grafana в браузере. Подробнее о маппинге портов вы можете почитать здесь [6]. После составления файла, можно его задеплоить. По умолчанию, docker-compose ищет файл docker-compose.yaml в текущей папке, поэтому вы можете запустить его с минимальными параметрами, просто выполнив команду docker-compose up. Это развернет контейнер в Docker. Я буду использовать дополнительные параметры для явного указания файла и запуска контейнера в фоновом режиме.
$ docker-compose -f docker-compose.yaml up -d
$ docker-compose stop
На первый взгляд, развертывание в Kubernetes выглядит несколько сложнее, поскольку вам необходимо определить Deployment, Service и другие параметры. Я прибегаю к небольшой хитрости, которая экономит мне время на написание YAML-файлов для Kubernetes. Сначала я деплою все в минимальной конфигурации в кластер, используя kubectl. А затем экспортирую нужные мне объекты, как YAML и уже потом дописываю необходимые настройки.
Заметка о Kubernetes, устанавливаемом на виртуальных машинах в GCP
Я пытался использовать Kubernetes, который развернут на Compute Engine в GCP и столкнулся с проблемой при развертывании сервиса LoadBalancer. Он остаётся в состоянии pending и не получает внешний IP-адрес. Это обстоятельство препятствует доступу к сервису из Интернета, даже если вы настроили сеть. Для этого есть решение, которое требует установки ingress сервиса и использования NodePort, согласно совету на Stackoverflow [7].
Итак, давайте создадим развертывание из образа. Имя stats — это имя развертывания, которое я сам дал для этого объекта. Вы можете использовать другое имя.
$ kubectl run stats --image=samuelebistoletti/docker-statsd-influxdb-grafana:latest --image-pull-policy=Always
Эта команда создаст Deployment, который, в свою очередь, создаст Pod и ReplicaSet в k8s. Чтобы получить доступ к Grafana, мне нужно создать сервис и выставить порты. Это можно сделать с помощью службы NodePort или LoadBalancer. В большинстве случаев вы будете создавать службы LoadBlancer. Почитать больше об этом можно тут [8].
$ kubectl expose deployment stats --type=LoadBalancer --port=3003 --target-port=3003
Эта команда также сопоставит порт хоста 3003 (--port) с портом в контейнере (--target-port). После выполнения команды вы сможете получить доступ к Grafana, загрузив URL localhost [2]:3003 в браузере. Вы можете проверить созданные объекты в k8s с помощью этой команды:
$ kubectl get all
Вы должны увидеть что-то, как на это картинке:
На данный момент, развернутая система ещё не то, что мне нужно, но я могу использовать её, как черновик. Экспортируем конфигурацию YAML:
$ kubectl get deployment,service stats -o yaml --export > exported.yaml
Экспортированный файл будет содержать определения Deployment и Service с текущей конфигурацией. Мне нужно будет удалить ненужные настройки и добавить маппинг портов. Окончательный минималистский вариант может выглядеть следующим образом:
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: stats
spec:
replicas: 1
selector:
matchLabels:
run: stats
template:
metadata:
labels:
run: stats
spec:
containers:
- image: samuelebistoletti/docker-statsd-influxdb-grafana:latest
imagePullPolicy: Always
name: stats
---
apiVersion: v1
kind: Service
metadata:
name: stats-tcp
spec:
type: LoadBalancer
ports:
- name: grafana
protocol: TCP
port: 3003
targetPort: 3003
- name: influxdb-admin
protocol: TCP
port: 3004
targetPort: 8888
- name: influxdb
protocol: TCP
port: 8086
targetPort: 8086
selector:
run: stats
---
apiVersion: v1
kind: Service
metadata:
name: stats-udp
spec:
type: LoadBalancer
ports:
- name: telegraf
protocol: UDP
port: 8125
targetPort: 8125
selector:
run: stats
Заметка об использовании протоколов TCP/UDP
Вы не сможете создать службу типа LoadBalancer, которая поддерживает протоколы TCP и UDP. Это известное ограничение, и сообщество пытается найти какое-то решение [9]. Между тем вы можете создать два отдельных сервиса для каждого из типов протоколов.
Перед использованием нового файла очистите существующие ресурсы в Kubernetes, а затем используйте команду kubectl apply.
$ kubectl delete svc stats
$ kubectl delete deployment stats
$ kubectl apply -f k8s-deployment.yaml
Вы только что задеплоили образ в Kubernetes с правильными настройками портов. Используя URL, упоминавшийся выше, вы можете открыть Grafana, но теперь еще можно слать и метрики StatsD. В следующем разделе я немного расскажу про метрики.
Протокол StatsD очень прост, вы, даже, можете создать свою собственную клиентскую библиотеку, если это очень нужно. Здесь [10] вы можете прочитать больше о датаграммах StatsD. Этот протокол поддерживает такие метрики, как счетчики (counter), время (timing), измерения (gauge) и т.д.
counter.name:1|c
timing.name:320|ms
gauge.name:333|g
Counters используются для подсчета количества некоторых событий. Обычно, вы просто всегда увеличиваете некоторый счетчик (bucket в StatsD). Агрегация делается на более низком уровне, поэтому когда вы будете получать значение за секунды, минуты, вам не придется заниматься дополнительными подсчетами, и в Grafana вы увидите число в секундах, минутах и так далее, как пожелаете.
Timing используется для измерения продолжительности какого-либо процесса. Например, этот показатель просто идеально подходит для измерения продолжительности веб-запроса.
Gauge используется, чтобы сделать замер некоторого текущего состояния ресурса. Например, количества доступной память или число свободных потоков.
Вам понадобится пакет NuGet JustEat.StatsD [11]. Он имеет хорошее описание на GitHub. Так что, просто следуйте его инструкциям, чтобы сделать свою собственную конфигурацию и зарегистрироваться в IoC.
В качестве примера, давайте возьмем API, где некоторый метод, когда вызван, ставит расчет в очередь потоков, используя ThreadPool. Логика API допускает только определенное количество параллельно выполняемых вычислений. Допустим, вы хотите знать следующее о вашем сервисе:
Вот как может выглядеть сбор метрик в коде:
public override async Task<FactorialReply> Factorial(FactorialRequest request, ServerCallContext context)
{
// Obtain the number of available threads in ThreadPool
ThreadPool.GetAvailableThreads(out var availableThreads, out _);
// The number of available threads is the example of Gauge metric
// Send gauge metric to StatsD (using JustEat.StatsD nuget)
_stats.Gauge(availableThreads, "GaugeAvailableThreads");
// Increment a counter metric for incoming requests
_stats.Increment("CountRequests");
// The method _stats.Time() will calculate the time while the _semaphoreSlim.WaitAsync() were waiting
// and send the metric to StatsD
await _stats.Time("TimeWait", async f => await _semaphoreSlim.WaitAsync());
try
{
// Again measure time length of calculation and send it to StatsD
var result = await _stats.Time("TimeCalculation", async t => await CalculateFactorialAsync(request.Factor));
// Increment a counter of processed requests
_stats.Increment("CountProcessed");
return await Task.FromResult(new FactorialReply
{
Result = result
});
}
finally
{
_semaphoreSlim.Release();
}
}
В коде количество одновременных вычислений контролируется классом SemaphoreSlim. Если число параллельных выполнений превысит максимальное, оно остановит выполнение и будет ждать завершения какого-либо другого потока.
Автор: Aleksandr Goida
Источник [12]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/net/345138
Ссылки в тексте:
[1] Тут: http://binary-notes.ru/hints-about-installation-of-kubernates-on-windows-and-deploying-to-cluster/
[2] localhost: http://localhost
[3] здесь: https://github.com/samuelebistoletti/docker-statsd-influxdb-grafana
[4] деплоить docker-compose в Kubernetes: https://www.docker.com/blog/simplifying-kubernetes-with-docker-compose-and-friends/
[5] матрице совместимости: https://docs.docker.com/compose/compose-file/compose-versioning/
[6] здесь: https://docs.docker.com/compose/compose-file/compose-file-v2/#ports
[7] совету на Stackoverflow: https://stackoverflow.com/questions/44110876/kubernetes-service-external-ip-pending
[8] тут: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types
[9] сообщество пытается найти какое-то решение: https://github.com/kubernetes/kubernetes/issues/23880
[10] Здесь: https://github.com/statsd/statsd/blob/master/docs/metric_types.md
[11] JustEat.StatsD: https://github.com/justeat/JustEat.StatsD
[12] Источник: https://habr.com/ru/post/486172/?utm_source=habrahabr&utm_medium=rss&utm_campaign=486172
Нажмите здесь для печати.