Kapacitor : Alerting for your timeseries

I already talk about monitoring docker with Telegraf, InfluxDB and Grafana. It’s nice, we have pretty dashboards, but it doesn’t do alerting ! Unless you sit in front of your screen all the day, you will not be warned when a container is crashing or when a friend connect on your Teamspeak channel !

Fortunaletly, in the TICK Stack of Influxdata, there is the « K » of Kapacitor.

Kapacitor is an Open source framework for processing, monitoring, and alerting on time series data.

To do that, Kapacitor use TickScripts, small scripts written in a custom DSL Langage, very simple to understand and deploy.

For exmple, if you want to send a warning level alert on your Slack Channel, when the CPU usage of one of your servers is greater than 70%, and a critical level alert when above 85% :

stream
    |from()
        .measurement('cpu_usage_idle')
        .groupBy('host')
    |window()
        .period(1m)
        .every(1m)
    |mean('value')
    |eval(lambda: 100.0 - "mean")
        .as('used')
    |alert()
        .message('{{ .Level}}: {{ .Name }}/{{ index .Tags "host" }} has high cpu usage: {{ index .Fields "used" }}')
        .warn(lambda: "used" > 70.0)
        .crit(lambda: "used" > 85.0)

        // Slack
        .slack()
        .channel('#alerts')

With this kind of DSL langage, we can create any rule we want. By requesting InfluxDB with InfluxQL queries then aggregating metrics by host or any tag, adding a filter based on any criteria (between 8am. and 7pm. from monday to friday for example), etc..

When the alert rule is ready, Kapacitor can use any alerting system, like :

  • sending an email,
  • post to slack or mattermost,
  • write in a log file,
  • send a pager duty message,
  • upscale or downscale a docker swarm/kubernetes stack
  • or simply execute a custom bash script.

Here is an example of alert generated by Kapacitor in Slack :

kapacitor alerting slack

And for thoses who doesn’t want to get their hands dirty, there is Chronograf (the « C » in TICK Stack).

chronograf dashboard

Chronograf is an open-source web application written in Go and React.js designed to visualize your monitoring data from influxDB.

We are far from a Grafana in term of features (and community), but it’s getting better every day. It allow you to explore your data very efficiently :

chronograf data explorer

My favorite feature is the web based interface to easily create alerting and automation rules for Kapacitor.chronograf kapacitor ruleOf course the web interface limits you in term of Kapacitor DSL langage (an expert mode is on the way), but you can easily, in 3 clics, create simple rules like a threshold, detect a delta during a time period or even send a alert when there is no data (deadman) !

So, theses tools are pretty youngs, but are very interestings : I’ll keep a watch on it !

Kapacitor : l’outil d’Alerting pour vos time series

J’ai déjà parlé du monitoring docker avec Telegraf, Influxdb et Grafana. C’est bien jolie, on a des beaux graphes, mais ça ne fait pas d’alerting. A moins de rester le nez devant les écrans toutes la journées, on ne sera pas prévenu en cas de crash d’un des conteneurs ou lorsqu’un pote se connecte au Teamspeak aperogeek !

Heureusement, dans la TICK Stack de influxdata, il y a le K de Kapacitor.

Kapacitor est un outil de stream processing, capable d’analyser au fil de l’eau les métriques qui arrivent dans influxDB.

Pour cela, Kapacitor utilise des TickScripts : des petits script dans un langage DSL propre a kapacitor, super simple à comprendre et mettre en place.

Par exemple pour envoyer un warning lorsque le cpu d’un des serveurs est utilisé a plus de 70%, et un gros warning à plus de 85% :

stream
    |from()
        .measurement('cpu_usage_idle')
        .groupBy('host')
    |window()
        .period(1m)
        .every(1m)
    |mean('value')
    |eval(lambda: 100.0 - "mean")
        .as('used')
    |alert()
        .message('{{ .Level}}: {{ .Name }}/{{ index .Tags "host" }} has high cpu usage: {{ index .Fields "used" }}')
        .warn(lambda: "used" > 70.0)
        .crit(lambda: "used" > 85.0)

        // Slack
        .slack()
        .channel('#alerts')

Avec ce type de langage, on est capable de créer n’importe quel type de règle, en interrogeant influxDB via des requêtes InfluxQL, de faire des agrégations par groupe de serveur, ou n’importe quel tag, en filtrant sur n’importe quel critère (du lundi au vendredi, entre 8h et 19h), etc..

Une fois la règle générée, Kapacitor est capable d’envoyer l’alerte n’importe où, comme :

  • envoyer une mail,
  • poster dans slack / mattermost,
  • écrire dans un fichier de log,
  • envoyer un message pager duty,
  • upscaler/downscaler une stack docker swarm/kubernetes
  • ou tout simplement exécuter un script maison.

Exemple d’alerting Slack :

kapacitor alerting slackEt pour ceux qui ne souhaitent pas mettre les mains dans le cambouis, il y a Chronograf (le « C » de TICK Stack).

chronograf dashboard

Chronograf et avant tout un outil de visualisation des métriques stockées dans influxDB. On est encore loin d’un Grafana en terme de fonctionnalités (et de communauté), mais ça avance petit à petit. Il permet d’explorer de de grapher rapidement une base influxdb :

chronograf data explorer

Enfin, le gros avantage est qu’il offre justement une interface graphique pour créer des règles Kapacitor !

chronograf kapacitor ruleAlors bien sur, on est limité dans le langage DSL, mais cela permet en 3 clics de créer des règles simples, comme un dépassement de seuil sur une période données, de détecter un écart significatif sur une plage de temps, ou encore d’alerter en cas d’absence de mesure !

Bref, ce sont des outils encore jeunes, mais très prometteurs, à surveiller !

Zabbix – Send alerts to Slack

Today I’ve configured my Zabbix Server to automatically send alerts to the #alerting channel of my slack team.

To to this, you have to create un new Incoming WebHook in your slack Team.

  • Click on your team, select App and Integration.
  • Search for Incoming Webhook
  • Click « Add a configuration »
  • Configure the webhook with the default destination topic, etc..
  • Copy the generated URL in your clipboard, you will need it later. The webhook url is something like https://hooks.slack.com/services/ABCDEFGHIJKJMNOPQRSTUVWXYZ

Next Go to your Zabbix Server.

Edit the /etc/zabbix/zabbix_server.conf file to specify a correct Path for AlertScriptPath, for example :

AlertScriptsPath=/usr/share/zabbix/alertscripts

Then go to the /usr/share/zabbix/alertscripts directory and create a tiny shell script post_to_slack.sh :

#!/bin/sh

webhook_url=$1
message=$2

curl -k -X POST -d "payload={\"username\":\"zabbix\", \"text\":\"$message\"}" $webhook_url

Then Go to The Zabbix IHM and add a new media type of type script, with the script name you created before (Administration > Media Types > create media type)

Add 2 parameters for your script :

  1. The first one is the Slack Webhook URL you generated in step 1,
  2. the second is the Alert Subject.

Then, Configure a Zabbix Actions (Configuration > Actions) to send a message to slack media for the admin user.

Set a correct Subject message to get all the information you need. For example :

[{HOST.HOST}] {TRIGGER.SEVERITY}: {TRIGGER.NAME}

Finaly edit the Zabbix admin user and add a new media of type slack.

That’s It !

Now all your Zabbix Alerts are sent to your slack #alerting Channel \o/

PS : You can configure multiple slack media type to send alerts to multiple webhooks, according to the Host group.

 

 

Monitoring Docker with Telegraf, InfluxDB and Grafana

A small post to talk about telegraf and influxdb (aka Tick Stack, without Chronograf and Kapacitor)

Telegraf

Telegraf is a metrics collect tool written in Go which can collect system metrics like cpu, memory disk, and also application metrics (apache, nginx, elasticsearch, jmx, etc..)

Telegraf collect metrics from « input » plugins, parse it to the correct format (influxdb line protocol / json) then send it to « output » plugins. There is a lot of input and output plugins, you just have to activate them in the telegraf config file.

Here I’m using the Docker input plugin to fetch all the stats from my docker daemon (number of running containers, cpu / memory usage per container, etc..)

Here is the configuration for the docker input plugin :

# # Read metrics about docker containers
[[inputs.docker]]
  ## Docker Endpoint 
  ## To use TCP, set endpoint = "tcp://[ip]:[port]" 
  ## To use environment variables (ie, docker-machine), set endpoint = "ENV"
  endpoint = "unix:///var/run/docker.sock" 
  ## Only collect metrics for these containers, collect all if empty 
  container_names = [] 
  ## Timeout for docker list, info, and stats commands 
  timeout = "5s" 
  ## Whether to report for each container per-device blkio (8:0, 8:1...) and 
  ## network (eth0, eth1, ...) stats or not perdevice = true 
  ## Whether to report for each container total blkio and network stats or not 
  total = false

InfluxDB

Next I tell telegraf to send all my metrics to InfluxDB, a time series database :

# Configuration for influxdb server to send metrics to
[[outputs.influxdb]]
 ## The full HTTP or UDP endpoint URL for your InfluxDB instance.
 ## Multiple urls can be specified as part of the same cluster,
 ## this means that only ONE of the urls will be written to each interval.
 # urls = ["udp://localhost:8089"] # UDP endpoint example
 urls = ["http://influxdb:8086"] # required
 ## The target database for metrics (telegraf will create it if not exists).
 database = "telegraf" # required
 ## Retention policy to write to. Empty string writes to the default rp.
 retention_policy = ""
 ## Write consistency (clusters only), can be: "any", "one", "quorum", "all"
 write_consistency = "any"
 ## Write timeout (for the InfluxDB client), formatted as a string.
 ## If not provided, will default to 5s. 0s means no timeout (not recommended).
 timeout = "5s"
 # username = "telegraf"
 # password = "metricsmetricsmetricsmetrics"
 ## Set the user agent for HTTP POSTs (can be useful for log differentiation)
 # user_agent = "telegraf"
 ## Set UDP payload size, defaults to InfluxDB UDP Client default (512 bytes)
 # udp_payload = 512

Docker compose

To start all of theses services I’m using docker-compose. I’ve just updated my docker-compose.yml file to add the following lines :

version: '2'
services:
[...]
  telegraf:
    image: telegraf
    hostname: telegraf
    container_name: telegraf
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /data/telegraf/telegraf.conf:/etc/telegraf/telegraf.conf
    labels:
      - "traefik.enable=false"

  influxdb:
    image: influxdb
    hostname: influxdb
    container_name: influxdb
    volumes:
      - /data/influxdb:/var/lib/influxdb
    labels:
      - "traefik.enable=false"
 
  grafana:
    hostname: grafana
    container_name: grafana
    image: grafana/grafana
    expose:
      - 3000
    volumes:
      - /data/grafana:/var/lib/grafana

I reload my compose file with the command :

docker-compose up -d

Grafana

Now, with my docker metrics stored into InfluxDB, I can create dashboards into grafana.

First create an influxdb datasource pointing to the influxdb container (http://influxdb:8086)

Then import some dashboards available from the grafana catalog.

Here is a screenshot of the result.

 

Jenkins : One Jobs to Create them All [EN]

Today, I will talk about a Jenkins plugin called  « Jenkins Job DSL. »

It’a a plugin that allow you to create jenkins jobs from a jenkins job !

You just have to create a grovvy script to describe your job.

Install the Job DSL Plugin on Jenkins

To install the plugin, download the latest release here, then install it (Administration > Plugin management)

Create a « seed » job

The next step is to create a seed job. For this, create a new « free-style » job, and select :

  • Source code : clone your git repository where your DSL groovy scripts will be stored.
  • Build : Select « process Job DSL » build type.
    • Look on filesystem : « dsl/*.groovy »

Create Groovy Jobs

Now, create a git repository whith some groovy scripts to define all your jenkins jobs:

Here is an example of groovy script to deploy projects with ansible :

job('ansible_deploy') {
    description('Ansible deploy')

    wrappers {
        colorizeOutput()
        preBuildCleanup()
    }

    parameters {
        stringParam('GIT_REPO', 'https://git.company.com/project/ansible.git', 'Nom du repo git')
        stringParam('GIT_BRANCH', 'master', 'Git branch')       
        stringParam('ANSIBLE_INVENTORY', 'inventory/env/hosts', 'Ansible inventory file')
        stringParam('ANSIBLE_TAGS', '', 'Ansible tags')       
        stringParam('ANSIBLE_LIMITS', '', 'Ansible limits') 
        stringParam('ANSIBLE_USER', 'deploy', 'Ansible user')
        stringParam('ANSIBLE_EXTRA_VARS', '', 'Ansible extra vars')
    }

    environmentVariables {
        keepSystemVariables(true)
        keepBuildVariables(true)
    }

    scm {
        git($GIT_REPO, $GIT_BRANCH)
    }

    steps {
        shell(readFileFromWorkspace('shell/ansible_deploy.sh'))
    }
}

This job will clone a git repo where ansible roles and playbooks are stored.

Then the shell script will execute the ansible-playbook command with the corrects options according to the specified parameters in the job.

The script can also install additional roles with ansible galaxy

ansible-galaxy install -r requirements.yml
ansible-playbook -i $ANSIBLE_INVENTORY -u $ANSIBLE_USER -e "$ANSIBLE_EXTRA_VARS" -l "$ANSIBLE_LIMITS" -t "$ANSIBLE_TAGS" play.yml

 

Now you can create all your jobs with groovy script to do whatever you want ! (build maven stuff, deploy with ansible, package projects, generate documentation, etc..)

The documentation is very complete :

https://github.com/jenkinsci/job-dsl-plugin/wiki

https://jenkinsci.github.io/job-dsl-plugin/#path/job

Run the Seed Job

Once all your jobs scripts are pushed to your « jenkins-dsl-jobs » git repository, you can run the seed job.

The advantages are :

  • All your jenkins jobs are versionned, no more broken job because someone have modified it
  • Your Jenkins users don’t need write permission on jenkins jobs !

Monitoring Docker avec Télégraf, InfluxDB et Grafana

Monitoring Docker avec Télégraf, InfluxDB et Grafana

Un petit post pour parler de Telegraf et InfluxDB (aka TICK stack).

Telegraf

Telegraf est un outil de collecte de métriques écrit en Go qui permet de collecter aussi bien des métriques systèmes (cpu, ram, disques) que des métriques applicatives (apache, nginx, elasticsearch, jmx, etc..)

Pour cela, telegraf collecte des métriques via des plugins « input », les transforme si besoin et les envoie dans des plugins « output ».

Il existe une tonne de plugins input et output, il suffit juste de les paramétrer dans la configuration telegraf.

Ici, j’utilise le plugin Input Docker pour récupérer toutes les statistiques de mon démon docker (nombre de containers, cpu / memory usage par container, etc..).

Voici la configuration telegraf pour le plugin input docker :

# # Read metrics about docker containers
[[inputs.docker]]
  ## Docker Endpoint 
  ## To use TCP, set endpoint = "tcp://[ip]:[port]" 
  ## To use environment variables (ie, docker-machine), set endpoint = "ENV"
  endpoint = "unix:///var/run/docker.sock" 
  ## Only collect metrics for these containers, collect all if empty 
  container_names = [] 
  ## Timeout for docker list, info, and stats commands 
  timeout = "5s" 
  ## Whether to report for each container per-device blkio (8:0, 8:1...) and 
  ## network (eth0, eth1, ...) stats or not perdevice = true 
  ## Whether to report for each container total blkio and network stats or not 
  total = false

InfluxDB

Ensuite, je dit a telegraf d’envoyer toutes mes métriques dans une base de données timeseries InfluxDB :

# Configuration for influxdb server to send metrics to
[[outputs.influxdb]]
 ## The full HTTP or UDP endpoint URL for your InfluxDB instance.
 ## Multiple urls can be specified as part of the same cluster,
 ## this means that only ONE of the urls will be written to each interval.
 # urls = ["udp://localhost:8089"] # UDP endpoint example
 urls = ["http://influxdb:8086"] # required
 ## The target database for metrics (telegraf will create it if not exists).
 database = "telegraf" # required
 ## Retention policy to write to. Empty string writes to the default rp.
 retention_policy = ""
 ## Write consistency (clusters only), can be: "any", "one", "quorum", "all"
 write_consistency = "any"
 ## Write timeout (for the InfluxDB client), formatted as a string.
 ## If not provided, will default to 5s. 0s means no timeout (not recommended).
 timeout = "5s"
 # username = "telegraf"
 # password = "metricsmetricsmetricsmetrics"
 ## Set the user agent for HTTP POSTs (can be useful for log differentiation)
 # user_agent = "telegraf"
 ## Set UDP payload size, defaults to InfluxDB UDP Client default (512 bytes)
 # udp_payload = 512

Docker compose

Pour lancer tous ces services, j’utilise docker-compose. J’ai donc rajouté quelques services dans mon fichier docker-compose.yml :

version: '2'
services:
[...]
  telegraf:
    image: telegraf
    hostname: telegraf
    container_name: telegraf
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /data/telegraf/telegraf.conf:/etc/telegraf/telegraf.conf
    labels:
      - "traefik.enable=false"

  influxdb:
    image: influxdb
    hostname: influxdb
    container_name: influxdb
    volumes:
      - /data/influxdb:/var/lib/influxdb
    labels:
      - "traefik.enable=false"
 
  grafana:
    hostname: grafana
    container_name: grafana
    image: grafana/grafana
    expose:
      - 3000
    volumes:
      - /data/grafana:/var/lib/grafana

maintenant, il ne reste plus qu’a lancer les services avec un petit :

docker-compose up -d

Grafana

Maintenant que les métriques docker remontent dans une base influxDB, il ne reste plus qu’à grapher tout ça avec un grafana

J’ai juste importé quelques templates disponibles dans le catalogue grafana et je peux maintenant visualiser en live l’état de mes conteneurs.

 

 

 

Jenkins : One Jobs to Create them All

Salut !

Aujourd’hui je vais vous parler du plugin Jenkins Job DSL.

C’est un plugin qui permet de creéer des jobs Jenkins à partir d’un fichier de conf au format groovy.

installer le plugin Job DSL sur votre jenkins

Pour installer le plugin, télécharger le plugin ici, puis installez le dans votre jenkins (Administrer Jenkins > Gestion des plugins).

créer un jobs « seed » qui va créer les autres jobs

Pour cela, il faut créer un job « free-style » :

  • Source code : sélectionner votre repo git contenant les scripts DSL
  • Build : faire un build de type « process JOB DSLs »
    • Look on Filesystem : *.groovy

créer des scripts groovy de creation de jobs

Voici un exemple pour déployer avec ansible :

job('ansible_deploy') {
    description('Déploiement avec ansible')

    wrappers {
        colorizeOutput()
        preBuildCleanup()
    }

    parameters {
        stringParam('GIT_REPO', 'https://git.company.com/project/ansible.git', 'Nom du repo git')
        stringParam('GIT_BRANCH', 'master', 'Branche du projet')       
        stringParam('ANSIBLE_INVENTORY', 'inventory/env/hosts', 'Fichier inventaire à utiliser')
        stringParam('ANSIBLE_TAGS', '', 'tags ansible')       
        stringParam('ANSIBLE_LIMITS', '', 'Limiter les hosts') 
        stringParam('ANSIBLE_USER', 'deploy', 'Utilisateur ansible')
        stringParam('ANSIBLE_EXTRA_VARS', '', 'extra vars')
    }

    environmentVariables {
        keepSystemVariables(true)
        keepBuildVariables(true)
    }

    scm {
        git($GIT_REPO $GIT_BRANCH)
    }

    steps {
        shell(readFileFromWorkspace('shell/ansible_deploy.sh'))
    }
}

Ce Jobs va cloner un repo git contanant des playbooks  ansible. Ensuite le script shell va lancer la commande ansible-playbook avec les bonnes options en fonction des paramètres renseignés dans le job.

A vous de créer vos propres jobs en rapport avec votre activité ! la doc est plutot complète pour Job DSL :

https://github.com/jenkinsci/job-dsl-plugin/wiki

https://jenkinsci.github.io/job-dsl-plugin/#path/job

lancer le jobs « seed »

Enfin, il ne reste plus qu’à lancer le job « seed », qui va créer les autres jobs à partir de tous les fichier groovy se trouvant dans votre repo git.

L’avantage, c’est que maintenant tous vos jobs jenkins seront versionnés, et vous n’avez plus besoin de donner un accès en modification a vos users Jenkins.

Meetup Zabbix à Lyon

Salut à tous !

avec @SteveDestivelle, on organise un Meetup Zabbix à Lyon !

meetupzabbix_logo_500x131

Ça se passe à l’envers des pentes, un petit bar avec video projecteur et des canapés.

Au programme :

  • Une présentation de Steve sur les nouveautés de Zabbix 3.2
  • Une présentation de moi même sur un Patch de la Java gateway pour interroger du weblogic ou tu jboss.

Si vous êtes sur Lyon, n’hésitez pas a venir nous voir 🙂

Y’aura des bières et du saucisson !

Wetty : un terminal dans ton navigateur

J’avais déjà fait un article sur GateOne, il y a un moment déjà. Mais celui-ci était plutôt lourd et difficile à installer.

wetty

Et la dernièrement je suis tombé sur Wetty, une web app codée en NodeJS permettant d’avoir un terminal dans le navigateur !

Idéal pour pouvoir accéder à son serveur depuis le boulot quand tous les ports sont bloqués 😉

Du coup, j’ai créé une petite image Docker dont voici le dockerfile :

FROM alpine:edge

RUN apk --update add git nodejs python build-base openssh-client

WORKDIR /usr/share/webapps

RUN git clone https://github.com/krishnasrinivas/wetty && \
    cd wetty && \
    npm install

RUN apk del build-base

WORKDIR /usr/share/webapps/wetty

RUN addgroup seuf
RUN adduser -G seuf -h /home/seuf -s /bin/ash -D seuf

RUN echo "seuf:PassWordSecretAChanger" | chpasswd

RUN chown -R seuf:seuf /home/seuf/.ssh

CMD node app.js -p 3000

Ensuite je rajoute une petite section wetty dans mon docker compose :

  wetty:
    image: seuf/wetty
    hostname: wetty
    container_name: ssh
    expose:
      - "3000"
    restart: always

Et hop, grâce à Traefik j’ai un client web ssh dans mon terminal en https !

Je n’ai plus qu’à me connecter dessus pour atterrir dans un conteneur Alpine Linux. Je peux ensuite rebondir en ssh sur n’importe quel autre serveur ssh.

Traefik : HTTP reverse proxy / Load balancer pour Docker

traefik.logo

Lors de ma formation Docker par @emilevauge, il nous avait rapidement montré son outil de reverse proxy et load balancer écrit en Go pour Docker : Træfɪk

La conf est super simple, il suffit de lui donner accès a l’API Docker (socket / port) ou n’importe quel autre Backend (Kubernetes, Etcd, consul, etc..) et traefik se débrouille tout seul pour automatiquement créer les routes vers les conteneurs !

Du coup, je l’ai utilisé pour mes propres besoin. L’avantage c’est qu’il gère aussi le https et même la génération des certificats avec Let’s Encrypt !

Comme j’utilise principalement docker-compose pour gérer les services, j’ai juste ajouté une entrée dans mon docker-compose.yml :

version: '2'

services:
  traefik:
    image: traefik
    hostname: traefik
    container_name: traefik
    command: --web --docker --docker.domain=aperogeek.fr  --logLevel=DEBUG --acme --acme.email=xxx@domain.com --acme.storagefile=/etc/traefik/acme.json --acme.entrypoint=https --acme.caserver='https://acme-staging.api.letsencrypt.org/directory' --acme.ondemand=true --entryPoints='Name:https Address::443 TLS:/etc/traefik/ssl/aperogeek.fr.pem,/etc/traefik/ssl/aperogeek.fr.key' --entryPoints='Name:http Address::80 Redirect.EntryPoint:https' --defaultentrypoints=http,https
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - "./ssl:/etc/traefik/ssl"
      - "/var/run/docker.sock:/var/run/docker.sock"
      - "/dev/null:/traefik.toml"
      - "/data/traefik/acme.json:/etc/traefik/acme.json"

Et voila !

Un coup de docker-compose up -d et traefik va détecter mes différents conteneurs et créer les routes qui vont bien 🙂

Ensuite, je n’avais plus qu’a créer des alias DNS pour pointer vers les bons sous domaines (foo.aperogeek.fr, etc..)