Docker Swarm, Telegraf, InfluxDB, Grafana ile Metrik İzleme (MQTT Örneğiyle)

Bu yazıda sunucuların, servislerin yada çok farklı gözükse de aslında yakın olan sensörlerin verilerini canlı olarak takip edip görselleştirmeye, görselleştirmeleri de özelleştirmeye olanak sağlayan birkaç teknolojiden bahsedeceğiz. Kullanacağımız teknolojiler isim olarak Telegraf ile metrik toplama, InfluxDB ile zaman serisi veritabanında depolama, Grafana ile görselleştirme ve bu işlemleri Docker Swarm Modu üzerinden gerçekleştirmeyi içeriyor. Örnek olarak sunucunun işlemci ve hafıza kullanımıyla alakalı birkaç veriyi ve rastgele üretip MQTT’den göndereceğimiz verileri nasıl görselleştireceğimize bakacağız. Benzer şekilde Nginx, HAProxy, Graylog, Kubernetes, Docker, MySQL, MongoDB, Redis, Apache, RabbitMQ gibi yaygın kullanılan birçok servis hakkındaki kullanım bilgilerini toplayabilir, istediğimiz sürede saklayabilir ve görselleştirme/analiz yapabilir ve istediğimiz durumlarda uyarı oluşturabiliyoruz. İstediğimiz servis desteklenenler arasında olmasa ya da kendi yazdığımız bir servis olsa bile herhangi bir programlama dilinde yazacağımız ufak bir kod ile istediğimiz metrikleri Telegraf’a TCP üzerinden gönderebiliriz.

Bu temel bilgilerin ardından kuruluma başlayalım. Bu kurulumlar sırasında bir sanal makine üzerinde Docker kurarak ilerlemenizi tavsiye ederim. Daha önce Docker kurmadıysanız Centos 7 kullandığınız bir sistemde(aslında daha başka birçok dağıtımda da aynı) root kullanıcısı olarak veya sudo yetkisi bulunan bir kullanıcının komut satırından şunu yazmanız yeterli:

curl -sSL https://get.docker.com/ | sh

Bunu yazdıktan sonra, eğer root değilseniz ve sudo yetkisi için parola giriyorsanız, kısa bir süre sonra size makine bu parolayı soracaktır.

Bu işlem bittikten sonra artık Docker kurulmuş olacak. Eğer root dışında bir kullanıcı üzerinden işlem yapıyorsanız, şu komutu da yazdıktan sonra bir daha Docker işlemleri için sudo kullanmanıza gerek kalmayacak:

sudo usermod -aG docker <KULLANICI ADI>

Bu komut ile kullanıcıyı docker grubuna eklemiş oluyoruz. Ardından, Docker ile birden fazla makine arasında servis ve yük paylaşımının yapılabildiği “Docker Swarm Mode” adı verilen özelliği aktifleştireceğiz. Bunu yapmak için:

docker swarm init --advertise-addr <IP_ADRESİ>

IP adresi olarak Docker’ı kullanacağımız arayüzün IP adresini yazmamız gerekiyor. Bu, özellikle birden çok IP adresine sahip makinelerde önem taşıyor. Ayrıca birden fazla sunucunun bir Swarm içinde ortaklaşa çalışmalarını istediğimizde de birbirlerine bu IP adresleri üzerinden bağlanacaklarını söyleyelim. Dikkat etmemiz gereken, aynı ağ üzerinde bulunan makineler birbirine bağlanırken eğer varsa iç ağdaki IP adreslerini kullanabiliriz. Ancak dışarıdan bir makineyi de Swarm’a dahil etmek istediğimizde sorun yaşayacağımız eğer bu ihtimal varsa Public IP’leri kullanarak bu bağlantıyı sağlamak daha sağlıklı olacaktır. Eğer sanal makine üzerinde kendi bilgisayarımızda çalışıyorsak özel bir ayar yapmadığımızda VirtualBox üzerinde loopback(lo) arayüzü dışında bir tane daha arayüz olacağı için onunkini yazarak devam edebiliriz. Örnek olarak enp0s3 arayüzüne ait IP adresini yazabiliriz. Ardından, komutun son hali ‘docker swarm init –advertise-addr 192.168.99.100’ şeklinde olacaktır:

[root@localhost ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 08:00:27:6d:e3:e4 brd ff:ff:ff:ff:ff:ff
    inet <span style="color: #ff0000;" data-mce-style="color: #ff0000;">192.168.99.100</span>/24 brd 192.168.99.255 scope global dynamic enp0s8
       valid_lft 1123sec preferred_lft 1123sec
    inet6 fe80::2a92:e92:76a8:874b/64 scope link 
       valid_lft forever preferred_lft forever
[root@localhost ~]# docker swarm init --advertise-addr 192.168.99.100
Swarm initialized: current node (7na2d7l9llswpq4qljg98xjp9) is now a manager.

To add a worker to this swarm, run the following command:

    docker swarm join \
    --token SWMTKN-1-19dssbso18o6lxw8c2mxuc5e17v2xoy8w5bn4wgsesipuiayxm-bgjyg77ucwd7ugbju357eea9v \
    192.168.99.100:2377

To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

Bu komutun çıktısı olarak bize Docker Swarm Mode için başka makinelerin Swarm’a dahil olabileceği bir token verilecek. Bunu şu an kullanmayacağımız için geçiyoruz. Eğer bu Token’daki sayı ve harflerin ne anlama geldiğini merak ediyorsanız şu yazıda bahsetmiştik.

Birden fazla cihazı, farklı veri merkezlerinden birbirine bağlamak istersek, ağ üzerinde servisler arasında oluşan trafiğin açık olarak(cleartext) gitmesi, hassas veriler için sorun olacaktır. Bu yüzden, bir ağ oluşturup şifrelemeyi aktifleştiriyoruz. Bu sayede, servislerin arasında TLS kurulumu yapmamıza gerek kalmayacak, sadece dışarı açtıklarımızda bu tür bir ihtiyacımız olacak. Aynı zamanda şifreleme için kullanılan anahtarların yenilenmesi(key rotation) Docker tarafından otomatik olarak gerçekleştirilecektir. Bu uygulamanın bir diğer artısı da, donanımsal kripto birimleri kullanılabildiğinde ağın şifrelenmesi için onlar kullanılacak ve performans konusunda ciddi artışlar yaşanacaktır. Bu amaçla, monitor_network adında bir ağ oluşturalım:

docker network create --driver overlay --opt encrypted monitor_network

Komut içerisinde verdiğimiz –driver overlay parametresi Docker içerisinde varsayılanda gelen birden çok cihaz destekleyen ağ sürücüsünü aktifleştirir. Bunu multi-host networking olarak İngilizce kaynaklarda görebilirsiniz. Docker ile birlikte birden çok ağ sürücüsü geldiği gibi, sonradan yüklenebilecek ve birden çok makineyi destekleyen farklı ağ sürücüleri de bulunmakta. İhtiyaç halinde bunları araştırarak farklı özelliklere denk gelebilirsiniz.

Komutta verdiğimiz –opt encrypted seçeneği, ağın şifrelemesini etkinleştirir. Bu parametrede yapacağımız olası yazım yanlışları için bize bir uyarı verilmez, zira komutun CLI üzerinden API ile Docker Engine’e aktarılması sırasında yazılan –opt parametresi kontrol edilmiyor. Bu yüzden, yanlış yazarsak şifreleme aktifleşmeyeceği gibi, bize bir uyarı veya hata da verilmeyecek. Bu konuda Docker dokümantasyonundan güncellemeleri takip edip, gerekli olduğunda ağda şifreleme olup olmadığını elle kontrol etmekte fayda var.

Son olarak, bu uygulama kapsamında tek bir ağ üzerinden gidiyoruz. Genellikle yayına alınan sistemlerde kurulan ağ sayısı birden fazla oluyor ve çalışan uygulamalarda birbiriyle haberleşmesi gerekmeyenlerin/istenmeyenlerin farklı ağlara konularak birbirlerinden izole olarak kalması sağlanıyor.

MQTT Sunucusunun Kurulması

Şimdi, esas veri kaynağımız olacak MQTT sunucusunun kurulumuna bakacağız. Bunun için bir Docker servisi oluşturup onu kullanacağız. Oluşturacağımız servis Mosquitto’yu çalıştırıp, 1883 numaralı portu dışarıya açacak.

$ docker service create --network monitor_network -p 1883:1883 --name mosquitto eclipse-mosquitto
57x2hq7ljpwi3a0jqoe73bhgx

Oluşturduğumuz servisi monitor_network ağına dahil ettik. Bunun sebebi veritabanı veya Telegraf gibi servislerle kapalı ve şifreli trafiğe sahip ağ üzerinden haberleşmesi ve dışarıya sadece görselleştirecek arayüz ile MQTT sunucusunu açmanın yeterli olması.

Bu işlemin ardından artık MQTT sunucusu çalışıyor olacak. Kontrol etmek için:

$ docker service ps mosquitto
ID                  NAME                IMAGE                      NODE               DESIRED STATE       CURRENT STATE           ERROR               PORTS
6gnqumvf7jyw        mosquitto.1         eclipse-mosquitto:latest   node1            Running             Running 6 minutes ago

State kısmında Running yazdığını görüyorsanız servis başlamıştır. En başta servisin çalıştırılması için, ilgili sunucuda imaj yoksa indirileceği için biraz sürebilir. Bu aşamada orda Preparing görmelisiniz. Aradan biraz geçince de beklendiği gibi Running olarak değişmeli.

Veritabanı Sunucusunun Kurulması

Öncelikle, kullanacağımız veritabanı olan InfluxDB’nin verilerini kalıcı olarak saklayabilmek için db_veriler isimli bir dizin oluşturuyoruz. Ardından serviste bir sorun olursa veya yedek almak istersek bu dizin üzerinden yeniden oluşturabilir veya dizini yedekleyebiliriz.

cd ~
mkdir db_veriler

Bunun ardından veritabanını oluşturabiliriz. Servisin adı monitor_db olacak ve bu servis de diğerleriyle birlikte monitor_network ağında olacak. Normalde açmamız gerekmiyor ancak örnek olarak dışardan gelen bazı sorguları deneyebilmek için 8083 ve 8086 portlarını açıyoruz. Son olarak da, bulunduğumuz dizindeki db_veriler dizinini /var/lib/influxdb altına bağlıyoruz.  Bu işlemin ardından veriler artık CoW(Copy on Write) dosya sisteminin dışında, bizim dosya sistemimizde db_veriler dizininde tutulacak.

docker service create --name monitor_db --network monitor_network -p 8083:8083 -p 8086:8086 --mount type=bind,source=$(pwd)/db_veriler,target=/var/lib/influxdb influxdb
ugu9i59wi8qplov2awb3md5eb

Artık bir sorun var mı yok mu diye kontrol etmek, aynı zamanda servisin durumunu sürekli izlemek için şu komutu kullanabiliriz:

$ docker service ps monitor_db --no-trunc                                            2017-05-01 20:06:54

ID                          NAME                IMAGE                         NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
7h1cna9yl9xudxv41z597z1jm   monitor_db.1        influxdb:latest@sha256:2684379df270d15e0c0f492ebc9046be950dfa4ff735d230dbf3c3454ff69fa6   node1               Running             Running 12 seconds ago

Bu komut çıktı olarak 2 saniyede bir, varsa hatayı yoksa da üstte gördüğünüz gibi servisin durumunu gösterir.

Veri Formatı

InfluxDB üzerinde veriler MeasurementTag SetField Set ve Timestamp olarak tutulur. Veri formatı, dokümantasyonunda yazıldığı üzere şu şekildedir:

<measurement>[,<tag-key>=<tag-value>...] <field-key>=<field-value>[,<field2-key>=<field2-value>...] [unix-nano-timestamp]

Bu formata göre örnek bir veri şöyle olacaktır:

cpu,host=sunucu1,region=Test value=3.25

Burdaki ölçüm(measurement) cpu, Etiketler(tag set) host=sunucu1 ve region=Test, alan olarak(field set) sadece value=3.25‘i içeriyor. Zaman değeri(timestamp) olarak bir şey sağlamadık. Bu durumda sunucunun zamanı veritabanı tarafından otomatik olarak ekleniyor. İstersek bir boşluk daha bırakıp biz de sağlayabilirdik.

Veritabanına Erişim

Şimdi veritabanı sunucusuna nasıl erişeceğimize bakalım. Örnek olarak oluşturduğumuz servise girecek ve bir veritabanı oluşturacağız. Bu işlem için öncelikle, bulunduğumuz makinede çalışan veritabanı sunucu servisini bulmamız gerekiyor. Bunu yapmak için:

$ docker ps
CONTAINER ID        IMAGE                      COMMAND                  CREATED             STATUS              PORTS               NAMES
6bc254d6b87b        influxdb:latest            "/entrypoint.sh in..."   36 minutes ago      Up 36 minutes       8086/tcp            monitor_db.1.7h1cna9yl9xudxv41z597z1jm
e0d492ee4287        eclipse-mosquitto:latest   "/docker-entrypoin..."   About an hour ago   Up About an hour                   mosquitto.1.6gnqumvf7jyw5k92jzbngtc7p

Bu çıktıda yer alan CONTAINER ID sütununda, InfluxDB’ye ait olan satırın sonunda konteynırın ismi yer alıyor. Konteynıra girip işlem yapmak için bu isme ihtiyacımız var. Şimdi ismini bildiğimiz konteynırın içine girelim ve bir terminal çalıştıralım:

$ docker exec -it monitor_db.1.7h1cna9yl9xudxv41z597z1jm /bin/bash
root@6bc254d6b87b:/#

Artık veritabanı sunucusu konteynırındaki servisteyiz. Veritabanı için olan kabuğu başlatıp komutlara bakabiliriz. Bunun için yazmamız gereken komut influx olacak:

root@6bc254d6b87b:/# influx
Connected to http://localhost:8086 version 1.2.3
InfluxDB shell version: 1.2.3
>

Veritabanı sunucusuna giriş yaptığımıza göre ilk olarak varolan veritabanlarına bakalım. Bunun için show databases yazmamız yeterli:

> show databases
name: databases
name
----
_internal

Çıktıda yer alan _internal isimli veritabanı InfluxDB’nin kendi iç kullanımı için. Biz, verilerimizi tutmak için yeni bir veritabanı oluşturacağız. Ancak öncesinde, bir kullanıcı oluşturup ona yetki verelim. admin kullanıcı adıyla yeni bir kullanıcı oluşturup kendisine tüm yetkileri veriyoruz. Parola olarak da alttaki komutta istediğimiz bir parolayı yazabiliriz:

create user admin with password 'PAROLA_TEK_TIRNAK_ICINDE' with all privileges

InfluxDB tabii ki sadece bir veritabanı üzerinde yazma yetkisi olan kullanıcıları oluşturmamıza imkan sağlıyor. Ancak şu anlık basitlik için bu şekilde devam edeceğiz. Dokümantasyondaki kullanıcı yönetimi kısmından farklı yetki seviyelerindeki kullanıcıların nasıl oluşturulacağına bakabilirsiniz. Şimdi oluşturduğumuz kullanıcıya bir bakalım:

> show users
user  admin
----  -----
admin true

InfluxDB, hiçbir kullanıcı tanımlı değilken dışardan bağlantı kabul etmiyor, sadece yönetici oluşturacak bağlantıları kabul ediyor. Haliyle bir kullanıcı oluşturarak başlamamız gerekti. Ayrıca, kullanıcı adı ve parola doğrulamasını aktifleştirmek isterseniz, dokümantasyonda belirtildiği üzere InfluxDB ayar dosyasından authentication‘ı aktifleştirmeniz gerekiyor. Yayına aldığınız bir sistemde dışarıya açtığınız bir veritabanı üzerinde bunu yapmazsanız herhangi birisi kullanıcı adı ve parola belirtmeden veritabanı sunucusuna giriş yapıp sorgu çalıştırabilir.

Şimdi, telegraf isimli bir veritabanı oluşturalım ve ardından var olan veritabanı listesine bakalım:

> create database telegraf
> show databases
name: databases
name
----
_internal
telegraf

Buraya kadar bir yanlışlık olmadıysa veritabanı gözüktüğü gibi listelenmeli. Bu aşamada farklı isimde bir veritabanı oluşturduysanız, ilerki aşamalarda ayarlar kısmında onu yazmanız gerekiyor.

Veri Örneği

Veritabanı da oluşturduğumuza göre henüz çıkış yapmadan, örnek bir veri ekleyelim ve işlerin zaman serisi veritabanında nasıl yürüdüğünü görelim. İlk olarak, hangi veritabanını kullanacağımızı söylememiz gerekiyor. Biz telegraf isimli veritabanını kullanacağız:

> use telegraf
Using database telegraf

Ardından örnek bir veri ekleyebiliriz. Ekleyeceğimiz verinin ölçüm adı(measurement) sicaklik olsun. Etiketleri ev ve mutfak olarak ayarlayalım. Değerine de 25 diyelim:

> INSERT sicaklik,yer=ev,konum=mutfak value=25

Artık bir veri eklemiş olduk. Şimdi hangi ölçüm türlerinin veritabanında var olduğunu görelim:

> show measurements
name: measurements
name
----
sicaklik

Eğer bir sorunla karşılaşmadıysanız, sicaklik adında bir ölçümün sizde de gözükmesi gerekiyor. Şimdi, sıcaklık ölçümündeki tüm değerleri görelim:

> select * from sicaklik
name: sicaklik
time                konum  value yer
----                -----  ----- ---
1493673872171875054 mutfak 25    ev

Kendi eklediği, mikrosaniye hassasiyetindeki zamanı da burda görebiliyoruz. Ancak zaman serisi veritabanı için daha çok ihtiyacımız olabilecek kısım, ‘son 5 dakikadaki veriler’ gibi sorgular olabilir. Bunun için hemen bir örnek yaparak, son 1 dakikadaki sıcaklık ölçümlerini soralım:

> select * from sicaklik where time> now() - 1m
>

Eğer biraz önceki insert komutunu yazdığınızın ardından 1 dakikadan fazla geçtiyse, bu çıktı sizde de boş olacaktır. Eğer boş değilse 1 dakika kadar bekleyip tekrar denemekte fayda var. Şimdi, son 5 dakikadaki ölçümleri soralım ve eklediğimiz ölçümü görelim. Eğer siz daha uzun bir süre önce eklediyseniz ona uygun bir zaman değeri yazabilirsiniz:

> select * from sicaklik where time> now() - 5m
name: sicaklik
time                konum  value yer
----                -----  ----- ---
1493673872171875054 mutfak 25    ev

Artık basit sorgularla temel işlemleri nasıl yaptığımıza örnek vermiş olduk. Detaylar için InfluxDB’nin dokümantasyonunda biraz gezinmenizi öneririm.

Şimdi veritabanı sunucusunun komut satırı istemcisinden CTRL+D ile çıkabiliriz. Konteynırın içinden de yine CTRL+D ile çıkabiliriz. Bunu yaptığımızda kendimizi tekrar işletim sistemimizin terminalinde görmemiz gerekiyor.

HTTP API Üzerinden Dışarıdan Ulaşım

InfluxDB’ye, HTTP API’ı üzerinden de ulaşabiliriz. Bunu denemek için curl kullanacağız.

$ curl -G http://localhost:8086/query --data-urlencode "q=SHOW DATABASES"
{"results":[{"statement_id":0,"series":[{"name":"databases","columns":["name"],"values":[["_internal"],["telegraf
"]]}]}]}

Bu komutta query endpointine bağlanıp ‘SHOW DATABASES’ sorgusunu gönderdik. InfluxDB, HTTP isteklerine cevabı JSON olarak verir. Aldığımız sonuçta, oluşturduğumuz telegraf isimli veritabanının olduğuna da dikkat edelim.

Telegraf’ın Kurulumu

Veritabanı hazır olduğuna göre, artık MQTT sunucusu ile veritabanı arasındaki iletişimi sağlayacak bir servis bulmamız gerekiyor. Bu amaçla Telegraf’ı kullanacağız. Telegraf, yazının başında da belirttiğimiz gibi çok miktarda servisten veri alabiliyor. Bunların arasında MQTT takip etme gibi servis olmayan ama veri alınabilen birkaç alternatif de mevcut. Kurduğumuz sunucudaki istediğimiz konulara abone olmasını ve mesaj geldiğinde bunları veritabanına kaydetmesini isteyeceğiz.

Telegraf, veri aldığı kaynakları input olarak, verileri yazdığı yerleri de output olarak tanımlar. Bizim uygulamamızda input olarak MQTT, output olarak da InfluxDB olacak. Ayrıca çalıştığı sunucunun işlemci ve RAM kullanımı gibi bazı bilgileri Telegraf varsayılanda otomatik olarak almaktadır. İstersek bir sonraki aşamada kullanacağımız ayar dosyasından bunu da düzenleyebilir veya kapatabiliriz.

Ayar Dosyasının Elde Edilmesi

İlk aşamada şablon olarak kullanabileceğimiz, mümkün olduğunca açıklamaları da içerecek bir ayar dosyasına ihtiyacımız var. Bunu, bir Telegraf konteynırı çalıştırıp, telegraf programından örnek ayar dosyası oluşturmasını isteyerek yapabiliriz. Komutun çıktısını da bir dosyaya kaydederek şu şekilde ayar dosyasını elde ederiz:

$ docker run --rm telegraf -sample-config > telegraf.conf

Bu komutun çıktısı olarak, bulunduğumuz dizinde telegraf.conf isimli bir dosya görmemiz gerekiyor:

$ ls
db_veriler     telegraf.conf

Ayarların Yapılması

Artık vimnano gibi istediğimiz bir editörle bu dosyayı açıp düzenlemeye başlayabiliriz.Dosya içerisinde ilk olarak, veritabanı sunucusunu güncellememiz gerekiyor. Docker Swarm Mode üzerinde yer alan servis bulma sunucusu, ayar dosyalarındaki servislerin adını direk adres olarak kullanmamıza izin veriyor. Bu sayede çalıştırdığımız servisler, diğer servislerin sadece isimlerini bilerek onlarla iletişim kurabiliyor. Böylece IP değişikliği veya yeni sunucu eklendiğinde ona da isteklerin aktarılması gibi durumlarla başetmekle uğraşmıyoruz.

Ayar dosyasında ilk olarak veritabanı ayarlarını yapacağız. Bunun için dosya içerisinde OUTPUT PLUGINS kısmında yer alan [[outputs.influxdb]] başlığına gelelim. Burda, veritabanı adresi ve adı gibi tanımlamalar varsayılan olarak tanımlanmış haldeler. Kendi bilgilerimizle güncelleyelim:

[[outputs.influxdb]]
  urls = ["http://monitor_db:8086"]
  database = "telegraf"
  username = "admin"
  password = "ADMIN_KULLANICISININ_PAROLASI"

Eğer veritabanı sunucusunun ayar dosyasında kullanıcı adı ve parola ile girişi aktifleştirmediyseniz, son iki satırı eklemenize gerek yok.

Son olarak, MQTT sunucusunun ayarlarını da yaparak Telegraf servisini ayağa kaldırmaya geçebiliriz. Ayar dosyasında [[inputs.mqtt_consumer]] kısmını bulup, takip etmek istediğimiz konuları da düzenleyerek şu hale getirelim:

[[inputs.mqtt_consumer]]
  servers = ["mosquitto:1883"]
  qos = 0
  topics = [
    "sensors/#",
  ]
  data_format = "influx"

Birden fazla konuya abone olmak isterseniz topics kısmını ona göre düzenleyebilirsiniz. Veri formatı olarak influx‘ı seçtik. Bu kısımda da JSON’ın da içinde bulunduğu birkaç alternatif mevcut. Açıklamaları takip ederek bu konuda daha detaylı bilgi edinebilirsiniz.

Telegraf Servisinin Çalıştırılması

Telegraf servisini artık ayağa kaldırabiliriz. Şimdi yapmamız gereken, ayar dosyasının yerini göstermek ve monitor_network ağına dahil etmekten ibaret. Ayrıca, sorun olursa rahat çözbilmek için, debug modunda çalıştırarak yaptığı işlemleri daha net izleyelim.

docker service create --name get_metrics --network monitor_network --mount type=bind,source=$(pwd)/telegraf.conf,target=/etc/telegraf/telegraf.conf telegraf:1.1 --debug

Servisin ne durumda olduğuna yine watch docker service ps telegraf ile bakabiliriz. Bizim için son derece kritik olansa ayakta olsa bile servisin metrikleri ve mesajları toplayıp toplayamadığıdır. Bunun için servisin çalıştığı makinede öncelikle docker ps ile konteynır listesinden Telegraf’a ait konteynırı bulup daha sonra docker logs KONTEYNIR_ISMI şeklinde logları görebiliriz. Eğer Docker’ın servis loglarını destekleyen bir versiyonunu veya son sürümlerinden birini deneysel(experimental) modda kullanıyorsanız şunu yazarak görebilirsiniz:

$ docker service logs --follow get_metrics
get_metrics.1.dtn3bwv6mikt@node1    | 2017/05/01 22:07:12 I! Using config file: /etc/telegraf/telegraf.conf
get_metrics.1.dtn3bwv6mikt@node1    | 2017/05/01 22:07:12 D! Attempting connection to output: influxdb
get_metrics.1.dtn3bwv6mikt@node1    | 2017/05/01 22:07:12 D! Successfully connected to output: influxdb
get_metrics.1.dtn3bwv6mikt@node1    | 2017/05/01 22:07:12 I! Starting Telegraf (version 1.1.2)
get_metrics.1.dtn3bwv6mikt@node1    | 2017/05/01 22:07:12 I! Loaded outputs: influxdb
get_metrics.1.dtn3bwv6mikt@node1    | 2017/05/01 22:07:12 I! Loaded inputs: inputs.cpu inputs.diskio
 inputs.processes inputs.swap inputs.system inputs.disk inputs.kernel inputs.mem inputs.mqtt_consumer
get_metrics.1.dtn3bwv6mikt@node1    | 2017/05/01 22:07:12 I! Tags enabled: host=ca9a0e7c7f2c
get_metrics.1.dtn3bwv6mikt@node1    | 2017/05/01 22:07:12 I! Agent Config: Interval:10s, Quiet:false, Hostname:"ca9a0e7c7f2c", Flush Interval:10s
get_metrics.1.dtn3bwv6mikt@node1    | 2017/05/01 22:07:12 I! MQTT Client Connected
get_metrics.1.dtn3bwv6mikt@node1    | 2017/05/01 22:07:20 D! Input [inputs.mqtt_consumer] gathered metrics, (10s interval) in 33.585µs

Telegraf’ın, veritabanına o an ulaşamasa bile istediğimiz miktarda mesajı hafızada tutmasını ve veritabanına ulaştığında öncekilerle birlikte yazmasını sağlayan bir özelliği var. Varsayılanda tutulacak maksimum mesaj sayısı 10000 olarak belirlenmiş. İstersek bunu değiştirebiliriz ancak şu an ihtiyacımız yok. Komut çıktılarından sizdeki değeri ve ne kadar dolu olduğunu kontrol edebilirsiniz.

Ölçümlerin Görselleştirilmesi

Bu yazının sanırım en çok beklenen kısmına geldik. Verileri Grafana ile görselleştireceğiz. Öncelikle, Grafana’nın kendi verilerini(mesela oluşturduğumuz panelleri, kullanıcıları) tutacağı bir dizin oluşturalım. Bu da aslında veritabanında yaptığımıza benzer bir mantıktan geliyor.

$ mkdir grafana_data
$ ls
db_veriler     grafana_data   telegraf.conf

Komutu incelerken/yazarken göz önünde bulundurmamız gerekenler:

  • Grafana’nın çalışacağı yolu kendisine parametre olarak veriyoruz. Eğer kendi bilgisayarınızda veya sanal makinede ve alan adında asıl dizinde bulunacaksa aşağıda olduğu şekliyle kullanabilirsiniz.
  • Grafana’yı dışarıya 3000 portu üzerinden açıyoruz.
  • Kullanıcı adı ve parola doğrulaması varsayılanda aktif. Kullanıcı adı admin ve parolayı parametre olarak vereceğiz.
  • Grafana, eklenti destekliyor ve bu eklentilerle olmayan görselleştirme araçları, veri kaynakları gibi özellikler eklenebiliyor. Biz sadece örnek olması açısından 2 eklentiyi kuruyoruz. Bunu da parametre vererek yaptık.
  • Grafana verilerini tutacağımız grafana_data dizinini /var/lib/grafana altına bağlıyoruz.
$ docker service create --name monitor --network monitor_network \
     -e "GF_SECURITY_ADMIN_PASSWORD=PAROLA" \
     -e "GF_SERVER_ROOT_URL=/" \
     -e "GF_INSTALL_PLUGINS=grafana-clock-panel,grafana-simple-json-datasource" \
     --mount type=bind,source=$(pwd)/grafana_data/,target=/var/lib/grafana \
     -p 3000:3000 \
     grafana/grafana
khmox3lm7v6vrhrbarwsz8ncg

Bunun ardından artık IP adresi veya alan adına 3000 portundan bağlanabiliriz. Örneğin, Grafana’nın çalıştığı makinenin IP adresi 192.168.50.99 ise şunu yazarak tarayıcıdan bağlanabiliriz:

http://192.168.50.99:3000

Karşımıza şöyle bir ekran gelmeli:

Bu ekranda kullanıcı adına admin, parola için de servisi oluştururken parametre olarak yazdığımız parolayı yazarak giriş yapabiliriz. Karşımıza kullanım aşamalarını gösteren şu ekran gelmeli:

Bu ekranda ilk aşama olan kurulumu zaten Docker kullanarak ve verdiğimiz parametrelerle yapmış olduk. Şimdi, Grafana’nın hangi veritabanına bağlanacağını söylememiz gerekiyor. Bu ayarı da Add data source butonuna basarak yapıyoruz. Ayarları yazılı haldeyken şöyle bir ekran olmalı:

Name kısmına istediğimiz bir ismi verebiliriz. URL kutusuna ise veritabanını yazıyoruz. Docker Swarm Mode içerisinde ve overlay network üzerinde olduğumuz için direk servis adını yazmamız yeterli oldu. Access kısmında, verileri izlerken Grafana’nın veritabanından çekip bize göstermesini istediğimiz için proxy seçili olarak kaldı. Son olarak da, veritabanı adı olarak telegraf yazdık. Eğer kullanıcı adı ve parola doğrulamayı aktifleştirdiyseniz o bilgileri de burda girebilirsiniz. Bunları yazıp Save butonuna basınca, alt kısımda şunu görmelisiniz:

Veri kaynağı çalıştığına göre, artık ölçtüğü verileri incelemeye geçebiliriz. Sol üst menüden, Dashboards -> New seçeneğine gelelim. Bizi şöyle bir ekran karşılayacak:

Bu ekranda yapacağımız görselleştirmenin türünü seçebiliriz. Bu uygulamada grafik çizeceğimiz için Graph‘ı seçiyoruz. Bize boş bir grafik gelmeli:

Yukarısında Panel Title yazısının üzerine tıklayarak Edit‘i seçelim. Şimdi gelen ekrandan neyi çizeceğimizi ve nasıl çizeceğimizi seçebiliriz. Altta Metrics sekmesinde yer alan SELECT sorgusunun üzerine bir kez tıkladığımızda bize seçim yapabileceğimiz bir form açılacak:

Seçimleri bu ekran görüntüsündeki gibi yaparsanız, işlemci kullanım grafiğini görmeniz gerekiyor. Bu sırada dikkat etmemiz gereken başka bir etkense, varsayılanda grafiklerin son 6 saat baz alınarak çizilmesi. Bunu sağ üst kısımda yazan Last 6 Hours yazısına tıklayarak değiştirebiliriz:

Yukarıdaki gibi ayarlarsanız, her 5 saniyede bir grafikler güncellenecek ve son 30 dakikayı gösterecektir. Ardından kaydediğimizde grafik son yarım saati gösterecek şekilde güncellenmiş olmalı.

Örnek olarak şuna benzer bir şey çıkabilir:

Düzenleme menüsündeki seçenekleri kurcalayarak ve dokümantasyon üzerinden farklı seçenekleri de deneyebilirsiniz. Şimdi esas kısım olan MQTT verilerinin görselleştirilmesine geçelim.

MQTT Test Verisi Üretmek

Bu uygulamada, belirli aralıklarla rastgele sayılar üretip bunları MQTT bağlantısını test ederken kullanacağız. Bunu yapabilmek için de mosquitto_pub isimli, Mosquitto’ya ait yayın yapmayı sağlayan istemciyi kullanacağız. Birçok Linux dağıtımında mosquitto-clients adlı paket bu komutu sağlamaktadır. Ubuntu üzerinde sudo apt install mosquitto-clients , CentOS üzerinde (epel reposu aktifken) yum install mosquitto  ve Alpine üzerinde apk add mosquito-clients yazarak kurabiliriz. Ardından, yeni bir komut satırı veya farklı bir makine üzerinde terminalden rastgele veri üretip gönderen şu komutu çalıştıralım:

while true;
do mosquitto_pub -h SUNUCU_IP_ADRESI \
-t "sensors/deneme" \
-m "sicaklik,konum=ev,yer=mutfak value=$RANDOM"; \
sleep 1; done

Başka bir terminal veya makine üzerinden de, bu verilere MQTT ile abone olarak gerçekten geldiklerinden emin olalım:

$ mosquitto_sub -h 10.0.21.3 -v -t "#"
/sensors/deneme sicaklik,konum=ev,yer=mutfak value=17896
/sensors/deneme sicaklik,konum=ev,yer=mutfak value=15397
/sensors/deneme sicaklik,konum=ev,yer=mutfak value=21365
/sensors/deneme sicaklik,konum=ev,yer=mutfak value=31901

Ardından, Grafana’ya dönerek yeni bir grafik oluşturalım ve bilgileri görmeye başlayalım:

Bazı Ek Noktalar

En son ulaştığımız kısımda artık verileri kaydediyor ve grafiklerini çizebiliyor durumdayız. Yapılabilecek veya yapılması gereken birçok ek işten birkaç tanesinden bahsedelim:

  • Verilerin kalıcılığı: Şu an tek makinede çalıştığımız için, yaptığımız bağlama işlemlerinde sorun yaşamadık. Birden çok makineden oluşan bir Swarm kurduğunuzda(ki Swarm kurmanın esas amacı büyük ihtimal bu olacaktır), bu dizinlerin makinelerin tamamından erişilebilir olması gerekiyor. Bunun için ağ üzerinden çalışan bir dosya sistemi kullanabilirsiniz. Sunucularınızı dışarıda tutuyorsanız, sunucu hizmeti aldığınız yer de bu konuda farklı çözümler içeriyor olabilir, sayfalarını kontrol etmekte fayda var. Ayrıca, Flocker‘ı bir araştırmanızı önereyim. Bu konuda birçok yerde çalışabilen bir depolama sürücüsü olarak çok kısa özetlemiş olayım.
  • Dışarı açılacak portların belirlenmesi: Veritabanı portlarını dışarı açmamızda, curl ile yapılan isteği göstermek dışında bir amaç yoktu. Gerekli olmadığı sürece portları dışarı açmanın bir faydası yok.
  • Veritabanı erişim kısıtlaması: Veritabanı için ayar dosyasını ve dokümantasyonu inceleyerek, kullanıcı adı ve parola olmadan girilmemesini ve verilen bilgiler doğru olmadan da yine giriş yapılamamasını sağlamak. Veritabanını dışarıya komple kapatınca bunun gerekliliği azalıyor olsa da, işleri düzgün tutabilmek adına önemli bir konu.
  • Ağların ayrılması: Mümkün olabildiğince, veritabanına bağlanmayacak servisleri onun ağından uzak tutmak gibi, alakasız servisleri farklı ağlara katmak. Örneğin bu uygulamada Mosquitto’nun veritabanı ile aynı ağda olması gerekli değil.

Eklemek, düzeltmek istediğiniz konuları ve yorumlarınızı yazı altına belirtmekten lütfen çekinmeyin.

 

 

 
comments powered by Disqus