Slide 1

Slide 1 text

External node classification, the CFEngine way The classification problem: challenges and solutions Marco Marongiu (@brontolinux)

Slide 2

Slide 2 text

Acknowledgements All the images and logos used in this presentation are shown for didactic purposes only, in the belief that it constitutes a fair use of these resources. I don't claim any right on the images and products shown in this presentation. If you are the owner of any material used in this presentation and you believe that I am abusing it, please let me know and I'll promptly remove it from all my sources.

Slide 3

Slide 3 text

Agenda ➔ Why classification is critical ➔ Why classification is difficult ➔ How we can make it sane ➔ Final take-aways

Slide 4

Slide 4 text

Part 1: the problem

Slide 5

Slide 5 text

!!! !!! !!! !!! !!! !!! !!!

Slide 6

Slide 6 text

Configuration management «Configuration Management is the process of identifying and defining the items in the system, controlling the change of these items throughout their life-cycle, recording and reporting the status of items and change requests, and verifying the completeness and correctness of items» -- IEEE Glossary of Software Engineering Terminology (Standard 729-1983)

Slide 7

Slide 7 text

Configuration management «Configuration Management is the process of identifying and defining the items in the system, controlling the change of these items throughout their life-cycle, recording and reporting the status of items and change requests, and verifying the completeness and correctness of items» -- IEEE Glossary of Software Engineering Terminology (Standard 729-1983)

Slide 8

Slide 8 text

In configuration management you don't apply a configuration to a system, you rather apply it to classes of systems!

Slide 9

Slide 9 text

Part 2: challenges

Slide 10

Slide 10 text

Exceptions are the rule

Slide 11

Slide 11 text

Generic settings, the same for all systems Amsterdam DNS server NTP server Syslog server SSH configs Oslo Other random exceptions Seattle Iceland

Slide 12

Slide 12 text

Internal classification doesn't scale definitions explosion difficult reporting «The business should define what systems belong in which classes. The Cfengine administrator should build policy. Once the Cfengine administrator is left to manually defining classes within policy, you become a bottleneck» -- M.Svoboda, LinkedIn human bottleneck

Slide 13

Slide 13 text

Definitions explosion class1 exception1 exception2

Slide 14

Slide 14 text

Definitions explosion class1 exception1 exception3 exception2 c1&!(ex1|ex2|ex3) ex1&!(ex2|ex3) ex2&!(ex1|ex3) ex3&!(ex1|ex2) (ex1&ex2)&!ex3 (ex2&ex3)&!ex1 ex1&ex2&ex3 (ex1&ex3)&!ex2

Slide 15

Slide 15 text

Reporting ✔ take an infrastructure of 30000 nodes (LinkedIn-size!) ✔ try to report on something using SSH in a loop ✔ if no problem happens, and it takes ~3s per server on average, it takes 90000 seconds (>24h) ✔ if you do it with 10 parallel proceses, it's still 2.5h ✗ ...and you haven't started analysing the data yet ✗ ...and you haven't made it available to management yet ✗ ...and you need an up-to-date inventory of all nodes to provide accurate results ✗ ...and since not everybody has SSH access to the nodes or to the inventory, you are the only one (and the bottleneck) who can make that report! ✗ ...and it's an ideal case!

Slide 16

Slide 16 text

Your task is building policies, not defining classes

Slide 17

Slide 17 text

What if you had the ability to write a policy and use a class within that policy -- but the business could control which machines were associated with that class external to Cfengine? [...] The business can deploy an application to a machine, and Cfengine automatically responds in its policy because new classes have been set on the client automatically. Other business units can create classes of machines, and file a ticket for you to implement XYZ against the class they created. You are allowing your business to work the way it wants to. -- M.Svoboda, LinkedIn

Slide 18

Slide 18 text

Part 3: Solutions

Slide 19

Slide 19 text

Infrastructure complexity low complexity high complexity Technical skills well versed non technical Basic interface & basic backend Basic interface & sophisticated backend Sophisticated interface & sophisticated backend Sophisticated interface & basic backend

Slide 20

Slide 20 text

Puppet and ENC An external node classifier is an arbitrary script or application which can tell Puppet which classes a node should have [...] that can be called by puppet master; it doesn’t have to be written in Ruby. Its only argument is the name of the node to be classified, and it returns a YAML document describing the node. [...] To tell puppet master to use an ENC, you need to set two configuration options: node_terminus has to be set to “exec”, and external_nodes should have the path to the executable.

Slide 21

Slide 21 text

modules! ENC in CFEngine means...

Slide 22

Slide 22 text

The LinkedIn solution M.Svoboda - LinkedIn "Leveraging In-Memory Key Value Stores for Large-Scale Operations"

Slide 23

Slide 23 text

our implementation: hENC power & simplicity config info in plain text files module protocol a simple Perl script

Slide 24

Slide 24 text

No content

Slide 25

Slide 25 text

CFEngine's module protocol +activated_class -cancelled_class =my_var=my value =@my_list={ 'list','of','4','values'} =my_array[element]=value @my_array[list]={ 'list','of','4','values'}

Slide 26

Slide 26 text

#!/bin/sh /bin/egrep -h ^[=@+-] $* 2> /dev/null

Slide 27

Slide 27 text

#!/usr/bin/perl use strict ; use warnings ; my %class ; # classes container my %variable ; # variables container # Silence errors (e.g.: missing files) close STDERR ; while (my $line = <>) { chomp $line ; my ($setting,$id) = ( $line =~ m{^\s*([=\@+-])(.+)\s*$} ) ; # line didn't match the module protocol next if not defined $setting ; # add a class if ($setting eq '+') { # $id is a class name, or should be. $class{$id} = 1 ; } # undefine a class if ($setting eq '-') { # $id is a class name, or should be. $class{$id} = -1 ; } # define a variable/list if ($setting eq '=' or $setting eq '@') { # $id is "variable = something", or should be my ($varname) = ( $id =~ m{^(.+?)=} ) ; $variable{$varname} = $line ; } # discard the rest } # print out classes foreach my $classname (keys %class) { print "+$classname\n" if $class{$classname} > 0 ; print "-$classname\n" if $class{$classname} < 0 ; } # print variable/list assignments, the last one wins foreach my $assignment (values %variable) { print "$assignment\n" ; }

Slide 28

Slide 28 text

read general defaults read location defaults read environment defaults read node settings

Slide 29

Slide 29 text

oslo_public:: "enc_subdir" policy => "overridable", string => "$(enc_basedir)/pub" ; on_private_net_only:: "enc_subdir" policy => "overridable", string => "$(enc_basedir)/priv" ; oslo:: "henclist" policy => "overridable", slist => { "$(enc_basedir)/_default_", "$(enc_basedir)/_oslo_", "$(enc_subdir)/_oslo_", "$(enc_subdir)/$(sys.domain)/$(sys.fqhost)", } ; }environment- dependent settings } general defaults } location defaults } environ. defaults

Slide 30

Slide 30 text

methods: "ENC" comment => "External node classification", usebundle => henc("site.henclist") ; vars: "motd_file" string => "$(henc.motd_file)", policy => "overridable" ;

Slide 31

Slide 31 text

bundle agent henc(enclist_name) { vars: henc_has_list:: "enclist" slist => { "@($(enclist_name))" } ; "enc_fullpath" slist => maplist("$(site.inputs)/$(this)","enclist") ; "encargs" string => join(" ","enc_fullpath") ; classes: "henc_has_list" expression => isvariable("enclist_name") ; "henc_has_args" expression => isvariable("encargs") ; "henc_can_classify" and => { "henc_has_list","henc_has_args" } ; files: "$(site.lmodules)/henc" comment => "Copy/update hierarchical merger", copy_from => digest_cp("$(site.modules)/henc"), perms => mog("0755","root","root") ; henc_has_list:: "$(site.inputs)/$(enclist)" comment => "Cache henc files locally", copy_from => digest_cp("$(site.masterfiles)/$(enclist)") ; commands: henc_can_classify.!henc_classes_activated:: "$(site.lmodules)/henc" comment => "Hierarchical classification for $(sys.fqhost)", args => "$(encargs)", classes => always("henc_classes_activated"), module => "true" ; }

Slide 32

Slide 32 text

final take-aways smart classification is crucial... ...but doesn't need to be complicated... ...unless your infrastructure is. sometimes, even plain text is good enough!

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

comments? @brontolinux [email protected] http://syslog.me http://no.linkedin.com/in/marcomarongiu/

Slide 35

Slide 35 text

THANK you