1. At work, we have several geographically separated machines. This is no problem for puppet, one just declares a variable for the location and then proceed to factor out differencies between the locations. I just naively went along and choose one machine from each geo-location as the defining one in that location for generic services. We use OpenNTPd for our NTP services. Use geo-location to pick out the right DNS-name/IP-address and then proceed to set it in /etc/openntpd/ntpd.conf. Ensure that the package is installed, and the service is running on the host. Do the very same for the logcheck tool, though the configuration is less specialized to geo-locations. Go to lunch. When I come back, three hosts has tripped in the spider web of logcheck. All because they are off on the clock. The magic is that the streamlining of hosts happens automatically. You don't have to hunt for the discrepancies, you just have to specify what the hosts should contain. I had no idea that some machines were without NTP. It is not because system administrators are lazy and have bad memories. It is because you need better tools to maintain your server farm, ie, puppet. The next thing I do is to get apt to run via cron (There are several tools for this, pick your poison), get it to update the database and to download new updates. Then the following little piece of magic from the Puppet website does wonders:
     file { "/etc/update_initiator":
      group => root,
      owner => root,
      mode  => 640,
      source => "puppet:///dist/config/update_initiator",
     }
    
     exec { "/usr/bin/apt-get -y dist-upgrade":
      refreshonly => true,
      subscribe => File["/etc/update_initiator"],
     }
    
    When '/etc/update_initiator' is changed, then run the dist-upgrade. The update_initiator file also serves as the descriptive changelog of when an update was sent through to the machines. Update that file on the puppetmaster and then all machines happily install their updates.
    0

    Add a comment

  2. No, this is not a post about Guitar Hero 3. It is about system administration and puppetry! If you manage more than 5 hosts you will need configuration management automation. Either you write your own scripts (shudder), use CFEngine (more shudder) or you use Puppet from Reductive labs (There are .deb packages: puppet and puppetmaster). Choose a server that is going to be the puppetmaster. This guy should be fairly well protected as he will be the server handing out configuration to other machines. Give him a repository in /etc/puppet via either Subversion, Git, Hg, Bzr or your poison of preference. Make it such that a DNS lookup on puppet.[dnsdomainname] hits the puppetmaster. Enable the puppetmaster fileserver if not already done. Install puppet on the clients. Hand it the server address and it will try to communicate. It will fail miserably until you allow the clients Security CA's on the puppetmaster. Then you are ready for the fun: Assimilation! I started with something easy. Behold, sudo.pp:
    class sudo {
           package { sudo: ensure => installed }
    
     file { "/etc/sudoers":
      owner => root,
      group => root,
      mode  => 440,
      source => "puppet://puppet/dist/apps/sudo/sudoers",
                   require => Package[sudo]
     }
    }
    
    This incantation tells puppet that we need the 'sudo' package. Puppet is intelligent enough to use the right poison: portage, apt, aptitude, yum, pkg-install (Hi FreeBSD!), etc for installing the package. Next it will update /etc/sudoers with a file over the puppet protocol from the 'puppet' host (Remember the DNS setup? You'll love it in the long run ;) and take it from /dist/apps/sudo/sudoers. This path is prefixed with whatever is set in /etc/puppet/fileserver.conf and the file is copied, checksummed and configured. B00m! You now have centralized your sudo configuration. Next up: NTP!
    class openntpd {
     package { openntpd: ensure => installed }
    
           file { "/etc/openntpd/ntpd.conf":
         source => "puppet://puppet/dist/apps/openntpd/ntpd.conf",
               require => Package[openntpd]
     }
    
     service { openntpd:
         ensure => running,
         enable => true,
         pattern => "ntpd",
         subscribe => [Package[openntpd], File["/etc/openntpd/ntpd.conf"]]
     }
    }
    
    Note we have a declaration 'require' that orders the dependencies among things. We'll be sure things trigger in the right order. Next we define that openntpd needs a service 'openntpd' which should be running and enabled. The 'pattern' part tells puppet that it should look for a program 'ntpd' to discern whether openntpd is running or not. Puppet is intelligent enough to force the enabling via 'update-rc.d' on my Ubuntu/Debian boxes. Final thing: Locales (shudder).
    class locales {
     package { locales: ensure => installed }
    
     file {
     "/etc/environment":
      owner => root,
      group => root,
      mode => 644,
      source => "puppet://puppet/dist/config/environment",
      require => Package[locales];
     "/etc/locale.gen":
      owner => root,
      group => root,
      mode => 644,
      source => "puppet://puppet/dist/config/locale.gen",
      require => Package[locales],
      before => Exec["generate locales"];
     }
    
     exec { "locale_gen":
      command => "/usr/sbin/locale-gen",
      alias => "generate locales",
      subscribe => File["/etc/locale.gen"],
      refreshonly => true
     }
    }
    
    The new thing is the 'exec' declaration that will call '/usr/sbin/locale-gen' if our subscription '/etc/locale.gen' were updated (refreshed). Now you add the classes to the machines that need them through the 'node' facility of puppet. And then you have centralized control over ntpd and locales as well. Of course, puppet can also do things depending on host-types, fill in config-file templates, discriminate configuration in every conceivable way and so on. I can live with the fact it is written in Ruby. It happens to be brilliant. If you want to start using it, I recommend going straight to the root of a complete setup, and use that as a base for yours.
    0

    Add a comment

Blog Archive
About Me
About Me
What this is about
What this is about
I am jlouis. Pro Erlang programmer. I hack Agda, Coq, Twelf, Erlang, Haskell, and (Oca/S)ML. I sometimes write blog posts. I enjoy beer and whisky. I have a rather kinky mind. I also frag people in Quake.
Popular Posts
Popular Posts
  • On Curiosity and its software I cannot help but speculate on how the software on the Curiosity rover has been constructed. We know that m...
  • In this, I describe why Erlang is different from most other language runtimes. I also describe why it often forgoes throughput for lower la...
  • Haskell vs. Erlang Since I wrote a bittorrent client in both Erlang and Haskell, etorrent and combinatorrent respectively, I decided to put ...
  • A response to “Erlang - overhyped or underestimated” There is a blog post about Erlang which recently cropped up. It is well written and pu...
  • The reason this blog is not getting too many updates is due to me posting over on medium.com for the time. You can find me over there at thi...
  • On using Acme as a day-to-day text editor I've been using the Acme text editor from Plan9Port as my standard text editor for about 9 m...
  • On Erlang, State and Crashes There are two things which are ubiquitous in Erlang: A Process has an internal state. When the process crashes,...
  • When a dog owner wants to train his dog, the procedure is well-known and quite simple. The owner runs two loops: one of positive feedback an...
  • This post is all about parallel computation from a very high level view. I claim Erlang is not a parallel language in particular . It is not...
  • Erlangs message passing In the programming language Erlang[0], there are functionality to pass messages between processes. This feature is...
Loading
Dynamic Views theme. Powered by Blogger. Report Abuse.