Seite wählen

NETWAYS Blog

Icinga2 GitLab Health Check

GitLab
Neulich hatten wir bei einigen GitLab Updates auf die neueste Version das Problem, dass die Dienste nach dem Update zwar korrekt alle wieder gestartet wurden und daher unser alter Monitoring Check „Service: gitlab“ den Status „Gitlab OK: All services are running!“ zurückgeliefert hat, auch der Check „Service: http git.netways.de“ „HTTP OK: HTTP/1.1 200 OK“ geliefert hat, und daher hat ohne manuelle Prüfung niemand vermutet, dass im Hintergrund doch etwas schief gelaufen war (z.B. die Datenbank Migration während einem Update, oder ein vergessenes skip-XXX File im /etc/gitlab Verzeichnis).
Auch wenn man das Update direkt auf der command line ausgeführt hat, konnte man in der abschliessenden Meldung nicht sehen, ob noch alles o.k. ist.
Festgestellt hat man das dann erst, wenn man sich in der GitLab Admin Area unter „Health Check“ den Status angesehen hat.
Unten ein Beispiel wie es aussieht, wenn alles i.O. ist (Zur Info: Die Beispiel URL und Token gibt es nicht):
GitLab Status
D.h. ein neuer Check musste her, und den gibt es auch direkt bei GitLab zum Downloaden unter:
https://gitlab.com/6uellerBpanda/check_gitlab/blob/master/check_gitlab.rb
Der alte Check lief dabei direkt auf den einzelnen GitLab Hosts. Das war mit dem neuen Check allerdings ein Problem, weil er als Voraussetzung Ruby >2.3 hat, und wir z.B. noch einige Hosts unter Ubuntu Trusty betreiben.
Deshalb wird der neue Check direkt auf dem Monitoring Server (auch Ubuntu Trusty) ausgeführt, der zu diesem Zweck zusätzlich per rvm mit einem z.Zt. neuen Ruby 2.5.1 ausgestattet wurde, wobei im Ruby Skript das Shebang leider hardcoded eingetragen werden musste, weil es (zumindest unter Trusty) nicht anders funktioniert hatte (ohne grösseren Aufwand und vielen Änderungen an anderen Systemdateien):

#!/usr/local/rvm/rubies/ruby-2.5.1/bin/ruby

Nachdem die Token zum Zugriff im Bild oben seit einigen GitLab Versionen deprecated sind zugunsten einer IP Whitelist, hat das den Deploy des Checks zusätzlich erleichtert.
Der Aufruf des Checks sieht dann z.B. so aus:

root@icinga2-server:~# check_gitlab.rb -m health -s https://gitlab.netways.de -k
OK - Gitlab probes are in healthy state

Damit das dann auch funktioniert, muss auf der entfernten GitLab Instanz noch die IP Whitelist unter /etc/gitlab/gitlab.rb eingetragen werden:

gitlab_rails['monitoring_whitelist'] = ['127.0.0.1/8','10.XX.XX.XX/24']

Am besten checkt man natürlich nur über ein internes Netz, wie oben im Beispiel angegeben.
Das ganze kann man auch über ein GitLab Puppet Modul realisieren, indem man die Whitelist über Hiera oder Foreman verteilt:
Beispiel Hierarchie im Foreman:

gitlab:
    gitlab_rails:
      monitoring_whitelist:
      - 127.0.0.1/8
      - 10.XX.XX.XX/24
Stefan Gundel
Stefan Gundel
Senior Systems Engineer

Stefan ist ein Urgestein bei NETWAYS und arbeitet im Managed Services Team. Der internationale Durchbruch gelang Stefan als Fotomodel für den K+K Warenkorb. Nachdem er einige Jahre exklusiv für unseren Kunden StayFriends gearbeitet hat, darf er nun endlich auch wieder in anderen Projekten mitarbeiten.

Puppet 5 – how new is that!

Have you heard? In July this year Puppet released its‘ new software stack of the agent, server and db package to manage, control and orchestrate your IT infrastructure. Enough time has passed for us to test, upgrade and implement it in our environment. With this series we want to introduce some of the new features and inform you about the tasks you need to know or be aware of should you wish to upgrade.
Let us start with the basic changes in the new version. These are for example the switch from PSON to JSON encoding if the agent downloads his information, catalogues or metadata. This will help you to better integrate Puppet in your setup when it needs to communicate with other tools. You can also see an improved performance in handling facts and reports, especially when it matters to process larger quantities.
Another point to mention is the usage of the newer Ruby in version 2.4. Since version 4, Puppet ships all it needs in its‘ packages, so you need to reinstall your manually added Puppet agent gems.
And the last point for today should be the version numbering of the new packages. Puppet focuses on keeping all major versions of agent, server and db in one counter and follows the Semantic Versioning as closely as possible. Which is one of the reason for the huge jump in the Puppet server version.
Stay tuned to learn more. And if you need further help or want to learn more about Puppet take a look at our products or training course .

Clustershell und Foreman-API

i-love-apisForeman bietet die Möglichkeit verschiedene Informationen über die Hosts einzusehen. Dazu gehören der Status, das Betriebssystem, Ressourcen etc. Möchte man nun, auf mehreren Hosts gleichzeitig ein Kommando absetzen, kann man sich auf jedem einzelnen einloggen oder eine Clustershell aufbauen.
Hierfür gibt es verschiedene Tools die dies erlauben. Eine Unbequemlichkeit die hier jedoch schnell aufkommt, ist das kopieren und einfügen der Hostnamen in die Commandline. Aus diesem Grund, habe ich etwas Zeit investiert und ein Ruby Script geschrieben, das es mir ermöglicht, mit festgelegten Filtern nach speziellen Listen von Hostnamen zu suchen und diese als eine einzige Ausgabe zu speichern. Ich habe für das erzeugen von Clustershells „csshX“ im Einsatz, welches ich auch direkt mit eingebunden habe.
Das get_hosts Script gibt es als GIST.
In diesem Script wird zunächst eine „config.yml“ geladen, in der die Foreman-URL und der Nutzername definiert sind. Eine Passwortabfrage erfolgt in diesem Script direkt auf der Commandline. Anschließend wird die Ausgabe der Foreman-API nach dem Auflisten aller Hostinformationen in JSON geparst und alle verfügbaren Parameter für die Hosts in das entsprechende Array gespeichert. Mit dem Parameter „-s / –server“ gibt man einen String an, nachdem speziell gesucht werden soll. Diese Ausgabe wird zusätzlich mit angehängt.
Gefiltert wird nach:
1) Reports enabled
2) OS Ubuntu 14.04 / Debian 8
3) Kein Match auf net-* oder netways.de (Als Beispiel)
Von den selektierten Hosts werden die Hostnamen in einer Commandline-Ausgabe mit einem Leerzeichen getrennt ausgegeben. Verschiedene werden sich eventuell fragen: „Wofür brauche ich das? Wieso sollte ich so ein Script verwenden?“
Die Antwort ist einfach: Bequemlichkeit und live Übersicht, was gerade passiert. Die Suchparameter lassen sich sehr leicht anpassen und die Ausgabe des Scriptes wird etwas an Zeit der administrativen Aufgaben sparen, vorallem dann, wenn man mehr als nur 2 oder 3 Server mit Puppet bespielen lassen möchte.
user@computer ~/Documents/ruby/foreman $ ruby script.rb
Enter password:
[ ] Trying to establish a connection...
[OK] Password correct
[OK] Connection established
[ ] Collecting data...
[OK] Data collected
[RESULTS]
Ubuntu
csshX --login root test1.test.de test2.test.de test34.test.de test19.test.de mail.test.de icinga-001.test.de
Debian
csshX --login root icinga-002.test.de db-003.test.de db-021.test.de
Finished succesfully

Wie bereits erwähnt, ist hierfür noch eine „config.yml“ Datei nötig, die gewünschte Parameter enthält. In diesem Fall die URL und den usernamen. Aber auch ein Gemfile, das sich in Ruby um bestimmte Versionen von Gems kümmert. (Mit einem „bundle install“ können diese installiert werden)
Die config.yml und das Gemfile gibt es ebenfalls als GIST.
Eingebaute „rescue Execptions“ im Script selbst, geben entsprechende Rückmeldung, sollte der Login oder eine der auszuführenden Verarbeitungsschritte fehlschlagen und brechen den Vorgang an dieser Stelle ab.

May I introduce the Rubocop

When you are into developing Ruby code, or even Ruby near stuff like Puppet modules, or Chef cookbooks, there is a nice tool you should have a look at.
The RuboCop can help you writing better Ruby code, it certainly did it for me.
In short words, RubyCop is a code analyzer that checks Ruby code against common style guidelines and tries to detect a lot of mistakes and errors that you might write into your code.
There are a lot of configuration options, and even an auto-correct functionality, that updates your code.

Simple usage

Either install the gem, or add it to your Gemfile:

gem 'rubocop', require: false

You can just run it without configuration, and it will look for all Ruby files in your work directory.

$ rubocop
Inspecting 19 files
....C............CC
Offenses:
lib/test/cli.rb:3:3: C: Missing top-level class documentation comment.
 class CLI
 ^^^^^
lib/test/cli.rb:36:1: C: Extra empty line detected at method body beginning.
lib/test/cli.rb:41:1: C: Extra empty line detected at block body beginning.
lib/test/cli.rb:45:4: C: Final newline missing.
end
bin/test:12:1: C: Missing space after #.
#api.login('username', 'Passw0rd') unless api.logged_in?
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
bin/test:15:3: C: Missing space after #.
 #puts response.code
 ^^^^^^^^^^^^^^^^^^^
bin/test:19:1: C: Missing space after #.
#session.save(file)
^^^^^^^^^^^^^^^^^^^
18 files inspected, 7 offenses detected

You can add it as a rake job to your Rakefile:

require 'rubocop/rake_task'
RuboCop::RakeTask.new
task default: [:spec, :rubocop]

And run the test via your rake tests:

$ rake
$ rake rubocop

Configuration galore

There are a lot of options to modify the behavior and expectations of RuboCop.
Here is a short example I used with recent Puppet module.

require: rubocop-rspec
AllCops:
  TargetRubyVersion: 1.9
  Include:
    - ./**/*.rb
  Exclude:
    - vendor/**/*
    - .vendor/**/*
    - pkg/**/*
    - spec/fixtures/**/*
# We don't use rspec in this way
RSpec/DescribeClass:
  Enabled: False
RSpec/ImplicitExpect:
  Enabled: False
# Example length is not necessarily an indicator of code quality
RSpec/ExampleLength:
  Enabled: False
RSpec/NamedSubject:
  Enabled: False

Where to go next

Getting started Opennebula API

In wenigen Tagen starten die OpenNebula Techdays welche von Netways gesponsort werden. Da auf diesen einige interessante Dinge gezeigt werden gibt es hier jetzt eine kleine Einführung in die API.
Wenn man die API von OpenNebula benutzen möchte, gibt es zwei Möglichkeiten. Einmal „RPC XML“ und zweitens mit einem Ruby Binding. In meinem Beispiel werde ich mich auf das Ruby Binding beziehen.
Um mit der API rumspielen zu können benötigen wir erstmal eine passende OpenNebula Umgebung. Hierfür können wir uns ganz einfach eine vorinstallierte VM als VirtualBox image herunterladen.
Um nun auch auf die API zugreifen zu können, muss man noch eine Portweiterleitung für den Port „26330“ einrichten (Port 9869 ist optional, sollte man auch auf das Web-interface zugreifen wollen). Die Weiterleitung kann unter Setting > Network > Advanced > Port Forwarding eingerichtet werden.
Jetzt kann man anfangen sich gegen die API zu connecten. Als erstes fügt man die benötigten Ruby Gems hinzu. Dies wird mit

require 'opennebula'
include OpenNebula

gemacht.
Danach erstellt man Variablen für die login credentials und den Endpoint. Ich benutze dafür die default Username und Passwort Kombination.

CREDENTIALS = "oneadmin:opennebula"
ENDPOINT    = "http://<DeineVBoxIP>:26330/RPC2"

 
Nachdem dies erledigt ist, kann man eine Verbindung zur API festlegen. Hierfür legt man wieder eine Variable fest. (Bitte beachtet, das die credentials und endpoint variablen genauso heißen, wie oben festgelegt!)

client = Client.new(CREDENTIALS, ENDPOINT)

 
Als nächstes initialisiert man den Virtual Maschine Pool. Dafür wird die Variable vm_pool angelegt.

vm_pool = VirtualMaschinePool.new(client, -1)

 
Um mögliche Fehler abzufangen kann man eine kurze Fehlerabfrage einrichten. Diese gibt uns, im Falle eines Fehlers, gleich den richtigen Fehler Code zurück.

rc = vm_pool.info
if OpenNebula.is_error?(rc)
     puts rc.message
     exit -1
end

 
Damit jetzt jede Virtuelle Maschine gestoppt wird, richtet man eine kleine Schleife ein die uns pro VM, die sich im vm_pool befindet, eine Funktion ausführt.

vm_pool.each do |vm|
     rc = vm.shutdown
end

 
Mit der oben eingerichteten Fehlerabfrage kann man sich hier auch gleich noch den aktuellen Status bzw eine Success oder Fehlermeldung ausgeben lassen. Dafür fügt man ein paar Zeilen zu seiner Schleife hinzu.

vm_pool.each do |vm|
     rc = vm.shutdown
     if OpenNebula.is_error?(rc)
          puts "Virtual Machine #{vm.id}: #{rc.message}"
     else
          puts "Virtual Machine #{vm.id}: Shutting down"
     end
end

 
Das ganze noch mit einem sauberen

exit 0

abschließen und das erste Script ist fertig!
 
Um das Endprodukt testen zu können, muss man noch eine VM in OpenNebula erstellen. Hierfür kann man ein schon vorgefertigte Template nutzen.
OpenNebula API
Dieses einfach instantiieren und warten bis die VM hochgefahren ist. (Meist ca 10 Sekunden).
Wenn man jetzt das Ruby Script ausführt sollten man folgende Ausgabe erhalten:

Virtual Machine 1: Shutting down

 
Wie man an diesem Beispiel sehen kann, ist es sehr einfach eigene Scripte für Opennebula zu schreiben. Noch mehr spannende Dinge gibt es auf den diesjährigen TechDays!