<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title>redbluemagenta</title>
  <link href="http://redbluemagenta.com/atom.xml" rel="self"/>
  <link href="http://redbluemagenta.com/"/>
  <updated>2012-01-08T22:39:15-08:00</updated>
  <id>http://redbluemagenta.com/</id>
  <author>
    <name>Christian Paredes</name>
    
  </author>

  
  <entry>
    <title>RunDeck</title>
    <link href="http://redbluemagenta.com/2012/01/08/rundeck-use-cases-and-why-its-great/"/>
    <updated>2012-01-08T21:50:00-08:00</updated>
    <id>http://redbluemagenta.com/2012/01/08/rundeck-use-cases-and-why-its-great</id>
    <content type="html">&lt;p&gt;There&amp;#8217;s times when we need to enforce adhoc control over our machines. &lt;a href=&quot;http://dev2ops.org/blog/2011/2/16/peanut-butter-in-my-chocolate-convergence-vs-ad-hoc-control.html&quot;&gt;This blog post by Alex Honor&lt;/a&gt;
does a way better job than I could to explain why we still need to worry about
adhoc command execution, but a quick summary would probably be the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sometimes, we just need to execute commands ASAP - unplanned downtime
and adhoc information gathering both spur this activity.&lt;/li&gt;
&lt;li&gt;We need to orchestrate any set of commands across many machines - things
like getting your DB servers up and prepped before your web servers come
online is one example of this.&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;&lt;a href=&quot;http://rundeck.org/&quot;&gt;RunDeck&lt;/a&gt; can handle these two scenarios perfectly.  It&amp;#8217;s
a central job server that can execute any given set of commands or scripts
across many machines.  You can define machines via XML, or use web servers that
respond with a set of XML machine definitions (see
&lt;a href=&quot;https://github.com/opscode/chef-rundeck&quot;&gt;chef-rundeck&lt;/a&gt; for a good example of
this.)  You can code in whatever language you want for your job scripts -
RunDeck will run them on the local machine if the execute bit is set (or, if
you&amp;#8217;re running jobs across many machines, it will SCP them onto the machine and
execute them via SSH.)&lt;/p&gt;

&lt;p&gt;You can define multiple job steps within a job (including using other jobs as a
job step) - thus, you can, for example, have a job step that pulls down your
web application code from git across all web application servers, another job
step that pulls down dependencies, then one more to start the web application
across all of those machines, all of which is coordinated by the RunDeck
server. As another example, you can also coordinate scheduled jobs that
provision EC2 servers at a certain time of the day, run some kind of processing
job across all of those machines, then shut all of them down as soon as the job
is finished.&lt;/p&gt;

&lt;p&gt;There&amp;#8217;s another way these jobs can be started, not only just by manual button
pushing and cron schedules: they can also be started by hitting a URI via the
provided API with an auth token.  To expand on the previous example, if say you
don&amp;#8217;t have a reliable way to check to see if the processing is finished from
RunDeck&amp;#8217;s point of view, you can probably have some kind of job that&amp;#8217;s fired
from the workers, which hits the API and tells RunDeck to run a &amp;#8216;reap workers&amp;#8217;
job.&lt;/p&gt;

&lt;h2&gt;mcollective vs. RunDeck?&lt;/h2&gt;

&lt;p&gt;A few people have asked me how this compares with mcollective.&lt;/p&gt;

&lt;p&gt;I would probably say that they&amp;#8217;re actually complimentary with each other -
mcollective is incredibly nice, in that it has a bit of a better paradigm for
executing commands across a fleet of hosts (pub/sub vs. SSH in a for loop.) You
can actually use mcollective as an execution provider in RunDeck, by simply
specifying &amp;#8216;mco&amp;#8217; as the executor in the config file (&lt;a href=&quot;https://github.com/phobos182/rundeck-mcollective/blob/master/framework.properties&quot;&gt;here&amp;#8217;s a great example of this.&lt;/a&gt;)
RunDeck is nice, in that you can use arbitrary scripts with RunDeck and it&amp;#8217;ll
happily use them for execution - plus, it has a GUI, which makes it nice if you
need to provide a &amp;#8216;one button actiony thing&amp;#8217; for anyone else to use. RunDeck
can also run things &amp;#8216;out of band&amp;#8217; (relative to mcollective) - for example,
provisioning EC2 machines is an &amp;#8216;out of band&amp;#8217; activity (though you can
certainly implement this with mcollective as well, mcollective&amp;#8217;s execution
distribution model doesn&amp;#8217;t seem to &amp;#8216;fit&amp;#8217; well with actions that are meant to be
run on a central machine.)&lt;/p&gt;

&lt;p&gt;But again, you can tie mcollective with RunDeck, and they&amp;#8217;ll both be happy
together.  I can see right away that the default SSH executor will likely
be a pain in the ass once you get to about 100+ machines or so.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;RunDeck is pretty damn nice. We&amp;#8217;ve been putting it through its paces in our
staging environment, and it&amp;#8217;s held up very nicely with a wide variety of
tasks that we&amp;#8217;ve thrown at it. The only worries I have are the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Default SSH command executor will likely start sucking after getting to
about 100+ machines.&lt;/li&gt;
&lt;li&gt;Since it can execute whatever you throw at it, it&amp;#8217;s possible that you
might end up with yet another garbled mess of shell and Perl scripts.
This is probably better solved with team discipline, however.&lt;/li&gt;
&lt;li&gt;There doesn&amp;#8217;t seem to be a clear way to automate configuration changes for
RunDeck - thus, be sure to keep good backups for now (though, this is probably
because of my own ignorance - the API is pretty full featured, and I believe
you can add new jobs via the API, but it would&amp;#8217;ve been awesome to be able
to just edit job definitions in a predictable location on the disk.)&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Despite these worries, I highly recommend RunDeck - it&amp;#8217;s helped us quite a bit
so far, it&amp;#8217;s quick to get setup, and quick to start coding against for fleet
wide adhoc control.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Transitioned to Octopress</title>
    <link href="http://redbluemagenta.com/2011/10/03/transitioned-to-octopress/"/>
    <updated>2011-10-03T16:20:00-07:00</updated>
    <id>http://redbluemagenta.com/2011/10/03/transitioned-to-octopress</id>
    <content type="html">&lt;p&gt;So, I&amp;#8217;ve transitioned from &lt;a href=&quot;https://github.com/mojombo/jekyll&quot;&gt;Jekyll&lt;/a&gt; to
&lt;a href=&quot;http://octopress.org&quot;&gt;Octopress&lt;/a&gt;.  It comes with a really nice default HTML5
template that I&amp;#8217;ve edited a bit (changed some fonts, colors, etc.), and has a
decent fallback for mobile devices, all of which was lacking in my last site
design with Jekyll (if anyone&amp;#8217;s interested, the &lt;a href=&quot;https://github.com/cparedes/redbluemagenta-new&quot;&gt;old site&lt;/a&gt; is still on my GitHub account.)&lt;/p&gt;

&lt;p&gt;What&amp;#8217;s awesome about Octopress, anyway?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It comes with a nice set of Rake tasks for handling common tasks, such as generating a new site and rsync&amp;#8217;ing the pages over to a server. Also comes with Rake tasks for creating new posts and pages.&lt;/li&gt;
&lt;li&gt;The repository is very well laid out, with nice separation between themes and content.&lt;/li&gt;
&lt;li&gt;The default theme comes with scss files, which is way better to deal with than regular old css.&lt;/li&gt;
&lt;li&gt;Comes with a sane set of plugins that make things look awesome, such as code snippets, image embedding, and HTML5 video embedding (with Flash video fallback.)&lt;/li&gt;
&lt;/ul&gt;


&lt;p&gt;Anyway, the site looks way better now that it&amp;#8217;s on Octopress, and it&amp;#8217;s a bit
easier to maintain as well.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Converting Puppet Modules to Chef Cookbooks</title>
    <link href="http://redbluemagenta.com/2011/09/20/converting-puppet-modules-to-chef-cookbooks/"/>
    <updated>2011-09-20T00:10:00-07:00</updated>
    <id>http://redbluemagenta.com/2011/09/20/converting-puppet-modules-to-chef-cookbooks</id>
    <content type="html">&lt;p&gt;Over a couple of caffeine induced nights, I&amp;#8217;ve converted a handful of our
Puppet modules over to Chef cookbooks (by hand) to see how it&amp;#8217;d all turn out.
We&amp;#8217;ve not yet decided whether we will actually use Chef in production, but I
figure that if I&amp;#8217;ve lowered the bar of entry, it would make the decision much
easier (we&amp;#8217;d still have to worry about whether the technical merits justify
putting in time to transition everything over to Puppet, but at least the
initial cost of converting things over isn&amp;#8217;t as painful as it would&amp;#8217;ve been.)&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s a sample snippet of Puppet code that I&amp;#8217;ll be referring to for the rest
of the article:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;16&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;17&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;18&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;19&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;20&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;21&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;22&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;23&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;24&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;25&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;26&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;27&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;28&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;29&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;30&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;31&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;32&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;33&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;34&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;ruby&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foobar&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;vg&quot;&gt;$version&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1.0.0&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;vg&quot;&gt;$tarball&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;foobar-${version}.tar.gz&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;vg&quot;&gt;$url&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;http://example.com/${tarball}&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/opt/foobar&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;k&quot;&gt;ensure&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;directory&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt;   &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0755&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;download tarball&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/bin:/usr/bin:/sbin:/usr/sbin&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;cwd&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/opt/foobar&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;wget ${url}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;creates&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/opt/foobar/${tarball}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;nb&quot;&gt;exec&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;extract tarball&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;path&lt;/span&gt;    &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/bin:/usr/bin:/sbin:/usr/sbin&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;cwd&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/opt/foobar&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;tar zxvf ${tarball}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;creates&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/opt/foobar/foobar-${version}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;before&lt;/span&gt;  &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;no&quot;&gt;File&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;/opt/foobar/foobar-${version}/config.cfg&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/opt/foobar/foobar-${version}/config.cfg&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;content&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;template&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;foobar/config.cfg.erb&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;file&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/opt/foobar/foobar-${version}/staticfile&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;puppet:///modules/foobar/staticfile.${hostname}&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;                &lt;span class=&quot;s2&quot;&gt;&amp;quot;puppet:///modules/foobar/staticfile&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Puppet resources port pretty well over to Chef resources - you simply have to
make sure that you&amp;#8217;re using the right Chef resource when rewriting it (for
example, you use &amp;#8220;file&amp;#8221; in Puppet for templates, regular files transferred from
the server, regular files managed only locally, and directories - these are all
separate things in Chef, with resources such as &amp;#8220;cookbook_file&amp;#8221;, &amp;#8220;template&amp;#8221;,
&amp;#8220;file&amp;#8221;, &amp;#8220;directory&amp;#8221;, and &amp;#8220;remote_directory.&amp;#8221;)  As for variables, this might be
a bit of a judgment call - I&amp;#8217;ve mostly thrown tunables into node attributes,
and leave temporary recipe-specific variables where they were in Puppet.  In
this case, I&amp;#8217;d likely throw $version into &amp;#8220;node[:foobar][:version]&amp;#8221; as an
attribute - the tarball name, if the naming convention doesn&amp;#8217;t change between
versions, could probably stay inside the recipe itself.  The URL might be a
tunable too, and so could probably be stuffed into &amp;#8220;node[:foobar][:url]&amp;#8221; - what
if you had mirrors of these files in each geographical area?&lt;/p&gt;

&lt;p&gt;Here&amp;#8217;s what our code will look like so far, given the above:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;16&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;17&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;18&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;19&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;ruby&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# foobar/attributes/default.rb:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:foobar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:version&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;1.0.0&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:foobar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:tarball&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;foobar-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:foobar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:version&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;.tar.gz&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;default&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:foobar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;     &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;http://example.com/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:foobar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:tarball&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# Replaces the following Puppet code:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# $version = &amp;quot;1.0.0&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# $tarball = &amp;quot;foobar-${version}.tar.gz&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# $url     = &amp;quot;http://example.com/${tarball}&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# foobar/recipes/default.rb:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;directory&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/opt/foobar&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;0755&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# Replaces the following Puppet code:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# file { &amp;quot;/opt/foobar&amp;quot;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;#   ensure =&amp;gt; directory,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;#   mode   =&amp;gt; 0755,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# }&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Now, what do we do with the exec resources?  There&amp;#8217;s still a few things that
make sense to port directly to Chef&amp;#8217;s &amp;#8220;execute&amp;#8221; resources - things like
updating database users, running a program to alter configuration (think &amp;#8220;make&amp;#8221;
for creating sendmail database files), or extracting tarballs.  However, we do
have one exec resource that can be replaced by a regular Chef resource - the
exec resource that downloads a tarball onto local disk.  This is supplanted by
the &amp;#8220;remote_file&amp;#8221; resource - keep in mind that we likely do not want to keep
downloading the file on each Chef run (we guarantee this in Puppet with some
kind of command in the &amp;#8220;onlyif&amp;#8221; or &amp;#8220;unless&amp;#8221; statement - test -f? Current
downloaded file md5sum hash matches? etc.)  Probably the simplest way to deal
with this is to use a SHA256 hash in the remote_file resource - that&amp;#8217;s what
we&amp;#8217;ll do in this next code example:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;ruby&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# foobar/recipes/default.rb:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;remote_file&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/opt/foobar/&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:foobar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:tarball&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:foobar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:url&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;0644&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;checksum&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;deadbeef&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# Replaces the following Puppet code:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# exec { &amp;quot;download tarball&amp;quot;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;#   path    =&amp;gt; &amp;quot;/bin:/usr/bin:/sbin:/usr/sbin&amp;quot;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;#   cwd     =&amp;gt; &amp;quot;/opt/foobar&amp;quot;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;#   command =&amp;gt; &amp;quot;wget ${url}&amp;quot;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;#   creates =&amp;gt; &amp;quot;/opt/foobar/${tarball}&amp;quot;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# }&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;There isn&amp;#8217;t a way to do a simple existence check for the file before attempting
to download it (like what we&amp;#8217;ve done in our Puppet code above), but this is a
bit more robust for dealing with remote files.&lt;/p&gt;

&lt;p&gt;The tarball extraction exec resource in Puppet is easy to port over, and we&amp;#8217;ll
just go ahead and just do a straight translation over to Chef:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;16&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;17&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;18&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;19&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;20&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;21&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;22&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;23&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;24&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;25&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;26&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;ruby&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# foobar/recipes/default.rb:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;execute&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;extract tarball&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;cwd&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/opt/foobar&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;command&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;tar zxvf &lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:foobar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:tarball&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;creates&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/opt/foobar/foobar-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:foobar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:version&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# We&amp;#39;ll go ahead and throw in the template, too:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;template&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/opt/foobar/foobar-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:foobar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:version&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/config.cfg&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;config.cfg.erb&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# Replaces the following Puppet code:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# exec { &amp;quot;extract tarball&amp;quot;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;#   path    =&amp;gt; &amp;quot;/bin:/usr/bin:/sbin:/usr/sbin&amp;quot;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;#   cwd     =&amp;gt; &amp;quot;/opt/foobar&amp;quot;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;#   command =&amp;gt; &amp;quot;tar zxvf ${tarball}&amp;quot;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;#   creates =&amp;gt; &amp;quot;/opt/foobar/foobar-${version}&amp;quot;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;#   before  =&amp;gt; File[&amp;quot;/opt/foobar/foobar-${version}/config.cfg&amp;quot;],&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# }&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;#&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# file { &amp;quot;/opt/foobar/foobar-${version}/config.cfg&amp;quot;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;#   content =&amp;gt; template(&amp;quot;foobar/config.cfg.erb&amp;quot;),&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# }&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Since Chef executes things in order, we don&amp;#8217;t have to specify that the tarball
extraction step must come before writing the template file - we simply place it
before the template creation step.&lt;/p&gt;

&lt;p&gt;Also, Chef doesn&amp;#8217;t require you to specify a global &amp;#8220;Path&amp;#8221; variable in the top
level of your class hierarchy - it uses the PATH variable that&amp;#8217;s sourced in the
shell that&amp;#8217;s running Chef.  If you need to override this, you can by setting
the &amp;#8220;path&amp;#8221; attribute in the execute resource.&lt;/p&gt;

&lt;p&gt;Lastly, dealing with the regular static file at the end of the Puppet module is
a bit simpler in Chef than in Puppet - sometimes, we need to have specific
files for specific hosts or operating systems, and the way we do this is by
throwing the file into different directories, instead of coming up with a
naming convention and trying to stick with it throughout Puppet module
development.  In this case, we have file specificity broken up by hosts,
and so we can create the following folders and files in our Chef cookbook:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;foobar/files/host-host1.example.com/staticfile
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;foobar/files/host-host2.example.com/staticfile
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;foobar/files/default/staticfile&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;We then write the following in our recipe:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;ruby&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# foobar/recipes/default.rb:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;cookbook_file&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/opt/foobar/foobar-&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:foobar&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:version&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;/staticfile&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;staticfile&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# Replaces the following Puppet code:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# file { &amp;quot;/opt/foobar/foobar-${version}/staticfile&amp;quot;:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;#   source =&amp;gt; [ &amp;quot;puppet:///modules/foobar/staticfile.${hostname}&amp;quot;,&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;#               &amp;quot;puppet:///modules/foobar/staticfile&amp;quot; ],&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# }&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;All in all, it&amp;#8217;s not too tough to port things over to Chef - there&amp;#8217;s nothing
like &lt;a href=&quot;https://github.com/relistan/chef2puppet&quot;&gt;chef2puppet&lt;/a&gt; for converting
things automatically to Chef, but Chef resources map pretty well to Puppet
resources, and so the task isn&amp;#8217;t nearly as hard as it could have been.  Chef
has a bit more structure in place for stashing tunables separate from what
actually executes, but it could possibly be a bit more constraining than what
others could decide on with structuring their Puppet modules.&lt;/p&gt;

&lt;p&gt;If anyone has any questions about this, don&amp;#8217;t hesitate to let me know via email
or through the comments section below.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Modern Log Management and Monitoring</title>
    <link href="http://redbluemagenta.com/2011/08/19/modern-log-management-and-monitoring/"/>
    <updated>2011-08-19T05:29:00-07:00</updated>
    <id>http://redbluemagenta.com/2011/08/19/modern-log-management-and-monitoring</id>
    <content type="html">&lt;p&gt;We&amp;#8217;ve come a long way with monitoring in general - we have groups such as
##monitoringsucks on Freenode who are discussing how to break down monitoring
into pieces so that we can come up with better tools to handle each component.
We have tools such as &lt;a href=&quot;http://logstash.net&quot;&gt;logstash&lt;/a&gt; that can structure our
logs, &lt;a href=&quot;http://graylog2.org&quot;&gt;graylog2&lt;/a&gt; for presenting them in real time, and
backends such as &lt;a href=&quot;http://elasticsearch.org&quot;&gt;elasticsearch&lt;/a&gt; for storing them in
a way that makes it easy to search for the logs again.&lt;/p&gt;

&lt;p&gt;We&amp;#8217;re looking at problems differently than how it was seen before.  Currently,
at Seattle Biomed, we have an installation of logwatch that&amp;#8217;s on a centralized
rsyslog host that cuts down noise and sends us an email every hour, showing us
the log entries that might seem useful to us.  Unfortunately, this can
sometimes be very useless - it&amp;#8217;s easy to add in a filter that gets rid of a
bunch of noise, yet those same logs can end up being incredibly useful down the
road for catching a recurring bug.&lt;/p&gt;

&lt;p&gt;We see this with other related tools as well: RRD&amp;#8217;s are usually used to store
metrics on events that we collect, yet it has become the de facto standard for
storing time series data, while assuming too much about how we want to store
our data (sometimes, we &lt;em&gt;don&amp;#8217;t&lt;/em&gt; want to rotate our data, or we want to rotate
our data in some other way.  There&amp;#8217;s other issues too, such as assuming that
all metrics are gathered regularly - what if I wanted to graph irregular Puppet
runs?)&lt;/p&gt;

&lt;p&gt;The tools we now have on the table look at the problem differently: collect as
much data as possible, and make them useful.  Split away functionality as much
as possible, so we have a bit more of a loosely coupled system.&lt;/p&gt;

&lt;p&gt;What we&amp;#8217;re implementing right now in Seattle Biomed is the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;logstash, for structuring different log formats into JSON, and shipping them
off to other services&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;graylog2, for presenting real time logs and divvying up the view of these
logs into different &amp;#8220;streams&amp;#8221;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;elasticsearch + logstash web, for long term archival of logs and search&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;rabbitmq, for storing application log events from logstash-forwarders and
for forwarding logs between networks&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;To be honest, I was a bit leery about setting all of this up - I was afraid
it&amp;#8217;d add a lot more complexity to our network.  And perhaps it did, but now
that we have something that structures any crappy logs I throw at it, something
to visualize &lt;em&gt;all&lt;/em&gt; of our logs (not just syslog events), something to store
these events for long-term archival, and an AMQP broker that can also be used
for other applications, I think this little bit of added complexity has paid
off.&lt;/p&gt;

&lt;p&gt;To show how all of this hooks up together, I hope this ASCII art drawing
tides everyone over:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;syslog events
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;&gt; LOGSTASH &#8212;&#8211;&gt; GRAYLOG2
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;                   /       \_____&gt; ELASTICSEARCH
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;app events    AMQP
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&#8212;&#8212;&#8212;&#8212;&#8211;/&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;It&amp;#8217;d be nice to throw everything into AMQP before having it processed by
logstash, but it looked like it required either another logstash agent (to grab
all of the syslog events and throw them into AMQP), or agents running on all
machines that watches a bunch of files.  For now, I&amp;#8217;d rather not implement
either solution - if anyone else has other ideas, I&amp;#8217;m all ears.  The way we
have it setup seems to work just fine though, but YMMV.&lt;/p&gt;

&lt;p&gt;Logstash comes with support for &amp;#8216;grok&amp;#8217;, which is a library that allows you
to group regex&amp;#8217;s into macros, so you can write a pattern like this:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;%{TIMESTAMP} %{USER} %{SYSLOGPROG} %{MESSAGE}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;instead of writing a huge, ugly regex for everything.  You can also assign
names to a macro, which is used to structure the logs in logstash:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;%{TIMESTAMP:timestamp} %{USER:user} %{SYSLOGPROG:program} %{MESSAGE:message}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;The subsequent structure for the event will now look like this, assuming
we wrote our macros as we did above:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;{
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  @message =&gt; &amp;lt;whatever was matched in MESSAGE and assigned to @message&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  @fields =&gt; {
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;               &quot;timestamp&quot; =&gt; &amp;lt;TIMESTAMP&amp;gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;               &quot;user&quot; =&gt; &amp;lt;USER&amp;gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;               &quot;program&quot; =&gt; &amp;lt;SYSLOGPROG&amp;gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;             }
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;(the patterns I&amp;#8217;ve used above aren&amp;#8217;t exactly what&amp;#8217;s included in logstash, but
hopefully it gets the point across as to how powerful grok + logstash can be.)&lt;/p&gt;

&lt;p&gt;Logstash can prevent events from going through the rest of the pipeline, but
I&amp;#8217;ve decided to simply write grok patterns that structure incoming events, and
do any filtering later on in the pipeline (right now, we don&amp;#8217;t filter away
&lt;em&gt;anything&lt;/em&gt; - to me, it seems better to have every message available and be able
to drill down to what entries might be relevant, instead of getting rid of a
bunch of INFO/DEBUG messages and find out later that I really needed to see
that information.)&lt;/p&gt;

&lt;p&gt;After structuring the data with logstash, we ship the structured events off to
both elasticsearch and graylog2 using logstash&amp;#8217;s elasticsearch and GELF output
plugins.&lt;/p&gt;

&lt;p&gt;graylog2 can match against any arbitrary key that&amp;#8217;s in the event, so if we
wanted to look at only Puppet runs, we can create a stream called &amp;#8220;Puppet Runs&amp;#8221;
that matches against &amp;#8220;program=puppet-agent&amp;#8221;.  We can setup alarms and stream
subscriptions for that specific stream, thereby giving us the same sort of
functionality that we expect from logwatch and swatch.  Right now, I have three
streams for Puppet runs: &amp;#8220;Puppet Runs&amp;#8221; (aggregate of all Puppet Run logs),
&amp;#8220;Puppet Runs - Changes&amp;#8221; (if anything looks like a Puppet action, we stuff it
into this stream), and &amp;#8220;Puppet Runs - Error&amp;#8221; (anything that has severity level
ERROR and is a Puppet Run.)&lt;/p&gt;

&lt;p&gt;Elasticsearch stores &lt;em&gt;every&lt;/em&gt; log entry.  We capture as much as possible, so we
can look back at an entire history of logs and correlate events together a bit
better.  Again, I&amp;#8217;d rather worry about disk space than drop log entries that
might&amp;#8217;ve been a bit noisy at one point but end up being useful down the road.
Elasticsearch has a fairly rich language for querying the database, so I&amp;#8217;d
imagine it&amp;#8217;s possible to come up with an expression strong enough to get
exactly what you need.&lt;/p&gt;

&lt;p&gt;Down the road, my wish is to have logstash pull certain metrics out of events,
and throw them over to graphite for visualization (this is already implemented
in logstash 1.0.16, but there&amp;#8217;s a few showstopping bugs that prevented me from
keeping 1.0.16 installed.)&lt;/p&gt;

&lt;p&gt;Anyway, log monitoring has advanced quite a bit over the past few years in OSS
software - this solution, while more complex to setup than something like
Splunk, also costs absolutely nothing in upfront costs, and covers much of the
same ground as Splunk.  This is also a way better way to view logs than using
tools such as swatch or logwatch, where you do your filtering right at the
source, rather than gather as much as possible and filter at the tail end of
your pipeline (where you&amp;#8217;re more likely to have a bit better judgment as to
whether those INFO logs were spewing a bunch of crap or not.)&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>mcollective</title>
    <link href="http://redbluemagenta.com/2011/08/19/mcollective/"/>
    <updated>2011-08-19T04:41:00-07:00</updated>
    <id>http://redbluemagenta.com/2011/08/19/mcollective</id>
    <content type="html">&lt;p&gt;Once we&amp;#8217;re hitting the magic spot of roughly 50 - 100 machines or more, we
usually need to start looking at ways on how to manage all of these machines a
bit more easily.&lt;/p&gt;

&lt;p&gt;Configuration management is for keeping servers in spec with what you&amp;#8217;ve
written down.  You deploy packages, configuration, and start services with
configuration management.  For the most part, we&amp;#8217;ve gotten to the point where
we can describe enough in our configuration management language so that we
don&amp;#8217;t have to login directly to our machines to change anything.&lt;/p&gt;

&lt;p&gt;But if say we want to grab information, execute an action, or test something
out on several machines at once, we likely have to look at solutions that can
log into several machines at once and execute an action.  We have applications
such as ClusterSSH and dsh for controlling several SSH sessions at the same
time, general helper applications such as GNU Parallel, and good ol&amp;#8217; SSH in a
for loop.  However, we&amp;#8217;ll also likely have to maintain lists of different
classes of machines depending on what OS it is (what if we wanted to run
&amp;#8220;apt-get install foo&amp;#8221; on all of our Linux machines, yet we have a few CentOS
machines?), as well as lists of machines belonging to different roles (we
likely don&amp;#8217;t want to install &amp;#8220;apache2&amp;#8221; on our DB servers, for instance.)&lt;/p&gt;

&lt;p&gt;Further, we might not be interested in stdout output of the commands we run,
nor even the stderr output - we just want to know whether the command succeeded
or failed, and maybe some useful information to go along with it (aside from
attempting to grep out a few things from stdout/stderr.)&lt;/p&gt;

&lt;p&gt;mcollective helps with all of these issues.  It&amp;#8217;s much more than &amp;#8220;SSH in a for
loop&amp;#8221; - it uses a STOMP broker such as ActiveMQ or RabbitMQ (with the STOMP
plugin) as a pubsub broker, and allows you to use metadata straight from the
server as filters (so you can classify servers in different groups as needed,
and since the server itself is reporting its metadata, information is always up
to date.)  One example of using mcollective is to collect inventory information
and compile a report:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;inventory.mc  &lt;/span&gt;&lt;/figcaption&gt;
 &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;ruby&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;inventory&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;nb&quot;&gt;format&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;%s:&lt;/span&gt;&lt;span class=&quot;se&quot;&gt;\t\t\t&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;%s&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;fields&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;identity&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;facts&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;s2&quot;&gt;&amp;quot;lsbdistdescription&amp;quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;




&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;mco command &lt;/span&gt;&lt;/figcaption&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;mco inventory &#8211;script=inventory.mc&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;




&lt;figure class=&#8217;code&#8217;&gt;&lt;figcaption&gt;&lt;span&gt;Sample Output &lt;/span&gt;&lt;/figcaption&gt;
&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;foobar1.example.com: CentOS release 5.5 (Final)
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;foobar2.example.com:  Ubuntu 11.04&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Another example is to kick off a Puppet run on all machines with the
&amp;#8220;country=us&amp;#8221; fact, with no more than three concurrent runs at a time:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;mc-puppetd runonce -W country=us 3&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;&lt;a href=&quot;http://www.threedrunkensysadsonthe.net&quot;&gt;Three Drunken SysAds&lt;/a&gt; also has a nice
article on &lt;a href=&quot;http://www.threedrunkensysadsonthe.net/2011/05/deploy-and-roll-back-system-configs-with-capistrano-mcollective-and-puppet/&quot;&gt;using capistrano and
mcollective&lt;/a&gt;
for updating code on the Puppet master, and kicking off a subsequent Puppet run
on all of the machines in the fleet with mcollective.&lt;/p&gt;

&lt;p&gt;All we had to do in order to query all of these nodes intelligently is not by
maintaining a list of machines on the client, but by directly querying all of
the servers in the fleet, with any server satisfying the filter replying back
to the client.  The servers themselves &lt;em&gt;are&lt;/em&gt; the source of truth, not anything
else.&lt;/p&gt;

&lt;p&gt;&amp;#8211;&lt;/p&gt;

&lt;p&gt;There&amp;#8217;s a few caveats that I&amp;#8217;ve run into that should be taken into
consideration:&lt;/p&gt;

&lt;h2&gt;Security&lt;/h2&gt;

&lt;p&gt;By default, security is through a preshared key that&amp;#8217;s distributed between the
clients and all of the servers.  This is bad, especially if you plan on having
mcollective do anything useful, such as run privileged commands or kicking off
Puppet runs.  We&amp;#8217;ve decided to use the &lt;a href=&quot;http://docs.puppetlabs.com/mcollective/reference/plugins/security_aes.html&quot;&gt;AES + RSA security
plugin&lt;/a&gt;
for encrypting traffic between clients and servers, which is much more secure
than using a PSK.&lt;/p&gt;

&lt;p&gt;We&amp;#8217;ve enabled RPC Auditing as well, just to make sure that nothing&amp;#8217;s amiss.
It&amp;#8217;d be nice to centralize all of the logs in one place: we haven&amp;#8217;t found a
good way to do this yet (mcollective does have a logstash plugin, though it
stuffs all of the audit logs in the STOMP server, which, at this point in time,
can&amp;#8217;t be pulled from logstash due to a bug in jruby.)  For now, it might be
worth it to install the centralized log audit plugin, pull an aggregate log
file from a single machine, and run logstash against that particular file.&lt;/p&gt;

&lt;p&gt;Further, you&amp;#8217;ll likely want to implement an authorization plugin.  We use the
&lt;a href=&quot;http://code.google.com/p/mcollective-plugins/wiki/ActionPolicy&quot;&gt;ActionPolicy
plugin&lt;/a&gt; for
authorizing specific users to be able to do certain actions.  For ActionPolicy
to work, you have to make sure your client&amp;#8217;s computer has UID&amp;#8217;s synced with the
servers you are querying, since the RPC client grabs the UID from your client
machine, and ships it over as &amp;#8220;request.caller&amp;#8221; to the server (UPDATE: this is
not true for the SSL and AES + RSA security plugins, only for the PSK security
plugin.)  Since mcollective basically gives you root level access to each
system it runs on (even if it only exposes a few hooks to the client), you&amp;#8217;ll
want to make sure that you only give just enough permissions to mcollective
that a person (or system user) might need.&lt;/p&gt;

&lt;p&gt;Keep in mind that if you&amp;#8217;re using AES + RSA security or SSL security with
ActionPolicy, you&amp;#8217;ll want to use &amp;#8220;cert=&lt;certname&gt;&amp;#8221; instead of &amp;#8220;uid=&lt;uid&gt;&amp;#8221; - the
AES + RSA security plugin sends the cert name in the &amp;#8220;caller&amp;#8221; section of the
RPC request, which you can confirm if you enable RPC auditing and drill into
the logs.&lt;/p&gt;

&lt;h2&gt;STOMP&lt;/h2&gt;

&lt;p&gt;This was a little annoying, since we already had a rabbitmq server up and
running for logstash and I didn&amp;#8217;t want to spin up another machine just for
mcollective.  Thankfully, &lt;a href=&quot;http://www.rabbitmq.com/stomp.html&quot;&gt;rabbitmq has a STOMP
connector&lt;/a&gt; - we installed it on our
RabbitMQ server, and have it churning through both mcollective and logstash
requests just fine.&lt;/p&gt;

&lt;p&gt;You can also code a different connector plugin for mcollective agents - I
haven&amp;#8217;t yet seen code out in the wild for connecting with an AMQP broker (or
anything else for that matter), but the option is out there, if you really
don&amp;#8217;t want to run a STOMP broker.&lt;/p&gt;

&lt;h2&gt;mcollective from tarball&lt;/h2&gt;

&lt;p&gt;There&amp;#8217;s no mcollective gem to be found anywhere, so in order to get a
consistent installation across all of our machines, we resorted to using the
tarball.  A couple of things to keep in mind if you choose to go this route:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Be sure to set RUBYLIB to point to the lib directory in the tarball.&lt;/li&gt;
&lt;li&gt;Install the STOMP gem.&lt;/li&gt;
&lt;li&gt;If you&amp;#8217;re using the applications directly (as an mcollective client for
example), add the unpacked mcollective directory to your PATH (or copy over
the Ruby binaries over to a bin folder of your choice.)&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;Configuration files&lt;/h2&gt;

&lt;p&gt;It&amp;#8217;s not immediately obvious that you can split your configuration files into
multiple files, but &lt;em&gt;only&lt;/em&gt; for plugin configuration.  If your server.cfg file
has entries such as &amp;#8220;plugin.foo.bar = blah&amp;#8221; and &amp;#8220;plugin.bar.baz = 20&amp;#8221;, you can
write the following cfg files in /etc/mcollective/plugin.d instead of stuffing
those previous entries in server.cfg:&lt;/p&gt;

&lt;p&gt;foo.cfg:&lt;/p&gt;

&lt;p&gt;bar = blah&lt;/p&gt;

&lt;p&gt;bar.cfg:&lt;/p&gt;

&lt;p&gt;baz = 20&lt;/p&gt;

&lt;p&gt;Again, it&amp;#8217;s not totally obvious from the documentation, but at least there&amp;#8217;s a
little bit of flexibility there for your configuration management system of
choice.&lt;/p&gt;

&lt;p&gt;&amp;#8211;&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m quite happy with mcollective - it&amp;#8217;s easily extensible and it gives me much
better control over our UNIX machines.  We have it running in production and it
makes it a hell of a lot easier to inventory and control several machines at
once.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Why XDA Developers Forums Suck</title>
    <link href="http://redbluemagenta.com/2011/06/12/why-xda-developers-forums-suck/"/>
    <updated>2011-06-12T14:36:00-07:00</updated>
    <id>http://redbluemagenta.com/2011/06/12/why-xda-developers-forums-suck</id>
    <content type="html">&lt;p&gt;I&amp;#8217;ve been a member of the &lt;a href=&quot;http://forum.xda-developers.com&quot;&gt;XDA Developers Forum&lt;/a&gt; forums for a few months,
and after following development forums for various phones (mostly the Nexus
S and the HTC Thunderbolt forums), I&amp;#8217;ve concluded that the XDA Developers
forums suck.  Perhaps an even stronger claim is that the Android developer
community sucks, but I won&amp;#8217;t be defending that claim in this post.&lt;/p&gt;

&lt;p&gt;So, why does the XDA Developers forums suck?&lt;/p&gt;

&lt;p&gt;For one, the purpose of the forums is to centralize discussion and cooperation
of development projects for Android.  Based on what I&amp;#8217;ve seen so far on the
Nexus S and Thunderbolt forums, I believe that the forums have largely failed
at this task.  ROM&amp;#8217;s are largely developed independently with about over half
of the ROMs &lt;em&gt;maybe&lt;/em&gt; sharing source code to the community, with the biggest
offender being CM7 for Thunderbolt (the source code for most of the OS is
shared to the public, but the most important part that adds support for the
Thunderbolt&amp;#8217;s radio will &lt;em&gt;not&lt;/em&gt; be open sourced &amp;#8220;until it&amp;#8217;s done.&amp;#8221;) Worse,
there&amp;#8217;s a lot of prima donnas in the community - in most other dev communities,
most of the work is done in teams, though there may be benevolent dictators
or celebrities (but almost none of the things that are present in the XDA
community - witholding of source code and &amp;#8220;heroism.&amp;#8221;)  As much as slayher has
contributed to the community, it&amp;#8217;s telling when you see CM7 on Thunderbolt
completely contingent on him finishing his radio interface layer code, and
having to go to a channel called #slayher for CM7 Thunderbolt support.  Who
the fuck creates a channel based on their handle for a software project?&lt;/p&gt;

&lt;p&gt;Not only that, but the discussion that does take place on the forums around
development is almost always centered on end user support.  Many other
communities solve this with mailing lists in order to help focus branching
topics in a thread (most forums are notoriously bad at this, given that the
default view in most forums and the way that a forum focuses your conversation
often defaults to a flat hierarchy of posts.)  Any relevant developer
discussion is drowned in a sea of user support questions, and I would not blame
anyone who wishes to take their conversation elsewhere.&lt;/p&gt;

&lt;p&gt;What I propose as an alternative is the following:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;A site that is an aggregate of mailing lists for various phones, software
projects associated with each phone, etc.&lt;/li&gt;
&lt;li&gt;User support may be provided on this same site on forums, like how XDA
is setup right now.  The only difference is that dev discussion is separated
into mailing lists (and make it crystal clear that any developer related
discussion should be posted on the mailing lists.)&lt;/li&gt;
&lt;li&gt;This site should not post anything that doesn&amp;#8217;t have any source code freely
available under the GPL/BSD/Apache/etc. licenses.&lt;/li&gt;
&lt;/ol&gt;

</content>
  </entry>
  
  <entry>
    <title>Puppet vs. Chef</title>
    <link href="http://redbluemagenta.com/2011/05/21/puppet-vs-chef/"/>
    <updated>2011-05-21T12:25:00-07:00</updated>
    <id>http://redbluemagenta.com/2011/05/21/puppet-vs-chef</id>
    <content type="html">&lt;p&gt;I&amp;#8217;m approaching this from the view of a systems administrator - it&amp;#8217;s possible that
my world view is quite different from a developer, so my preferences might seem
a bit weird to a couple of people.  I&amp;#8217;m not going to outright say which one is
&amp;#8220;better&amp;#8221; than the other - in fact, both CM systems are quite awesome, it&amp;#8217;s just that
they both have different philosophies on how to approach configuration management.&lt;/p&gt;

&lt;p&gt;Puppet, for example, explicitly exposes the dependency graphs - if you want to
impose order, you are &lt;em&gt;required&lt;/em&gt; to declare how you&amp;#8217;re imposing it.  Is it
because of a dependency?  Is it because you&amp;#8217;ve grouped resources in different
stages and you want your resource to execute in one of those stages?  The DSL
forces the sysadmin to think about exactly how their system is built - ideally,
you&amp;#8217;d setup dependencies between various disparate resources, and each group
of resources should be able to execute independently of each other (for example,
I could setup a group of dependencies that describe a web server running Rails,
and another group of dependencies describing NFS services - unless the web server
depends on NFS, I should be able to setup the web service and the NFS service
independently from each other. If one set of resources fails to execute, the other
set should still be able to execute regardless of the state of the first set of
resources.)&lt;/p&gt;

&lt;p&gt;Puppet has a Ruby DSL - however, there&amp;#8217;s a lot of institutional momentum to continue
writing in the old Puppet DSL.  Writing manifests in the old Puppet DSL enables
us to write things more clearly, but at the cost of flexibility - for example,
the way I&amp;#8217;ve been applying an action on each element of an array is by using
&amp;#8220;definitions&amp;#8221;:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;ruby&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;define&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;c1&quot;&gt;# do something to ${name}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;vg&quot;&gt;$bar&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;[&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;one&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;two&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;three&amp;#39;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;vg&quot;&gt;$bar&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;In Chef, I&amp;#8217;d instead write it like this:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;ruby&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;sx&quot;&gt;%w{one two three}&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;c1&quot;&gt;# do something to #{foo}&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;For slightly harder things that rely on data structures such as arrays and hashes,
Puppet makes it harder to clearly express what I want.  But there&amp;#8217;s a danger
with Chef: you can write arbitrary Ruby code, which can sometimes obfuscate exactly
what you want to do on the system, or at the very least, can make it confusing to
read compared to equivalent Puppet code.&lt;/p&gt;

&lt;p&gt;Chef is much more conducive for programmers.  You can declare dependencies like
in Puppet, but by default, the resources execute in order as they&amp;#8217;re listed in
the Chef recipe.  You can write arbitrary Ruby code alongside Chef DSL code -
however, aside from the dangers outlined above, you&amp;#8217;ll also have to be very careful
about the execution order of Ruby code and Chef DSL code.  Ruby code always executes
during the compilation stage (unless you wrap the Ruby code within a &amp;#8220;ruby_block&amp;#8221;
resource declaration.)  The compilation stage executes before the execution stage -
this can lead to things like this:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;ruby&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# foobar.conf, before cookbook_file resource:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;hello&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# foobar.conf, as defined in cookbook:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;hi&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# Recipe:&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;cookbook_file&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;/etc/foobar.conf&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;foobar.conf&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;mode&lt;/span&gt; &lt;span class=&quot;mo&quot;&gt;0644&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;grab_state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%x[cat /etc/foobar.conf]&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;grab_state will only be &amp;#8220;hello&amp;#8221; on the first execution of this recipe - otherwise,
it will have the value &amp;#8220;hi&amp;#8221; in every other execution.  This might be confusing,
even if grab_state is located below &amp;#8220;cookbook_file&amp;#8221; in the recipe.&lt;/p&gt;

&lt;p&gt;This will do the right thing, if you expect &amp;#8220;grab_state&amp;#8221; to be given a value &lt;em&gt;after&lt;/em&gt;
&amp;#8220;cookbook_file&amp;#8221; does its thing:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;ruby&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;cookbook_file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;ruby_block&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;grab state&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;grab_state&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%x[cat /etc/foobar.conf]&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;This is because we&amp;#8217;ve now placed our arbitrary Ruby code within a Chef DSL resource,
which is executed &lt;em&gt;after&lt;/em&gt; the compilation phase.&lt;/p&gt;

&lt;p&gt;In short, the largest differences between Puppet and Chef is not only the language,
but also the way they approach configuration management.  Chef breaks the mold
by enforcing execution order - most other CM systems execute things
in random order, which is just simply a different way of looking at things
(the description is more important than &lt;em&gt;how&lt;/em&gt; we get there.)  Puppet, in my
opinion, is neither better nor worse than Chef, but simply different - there
are pains in programming in both.  Other issues, such as administering the server,
are also just &amp;#8220;different&amp;#8221; - Puppet has quite a bit fewer dependencies, but also
doesn&amp;#8217;t come with as many things that are taken for granted in Chef (such as
an external node classifier, and other things that make Chef a bit better
in larger deployments, such as a separate data store, queues, etc.)  Chef Server
is a pain in the ass to setup, and is totally overkill for small deployments,
but once you do get it setup, you do get a lot more language features out of
the box than you do in Puppet.&lt;/p&gt;

&lt;p&gt;VERDICT: DIFFERENT&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Presentation from CasITConf</title>
    <link href="http://redbluemagenta.com/2011/03/12/presentation-from-casitconf/"/>
    <updated>2011-03-12T12:17:00-08:00</updated>
    <id>http://redbluemagenta.com/2011/03/12/presentation-from-casitconf</id>
    <content type="html">&lt;p&gt;For those interested, &lt;a href=&quot;http://redbluemagenta.com/docs/casitconf.pptx&quot;&gt;I&amp;#8217;ve posted my presentation on my website&lt;/a&gt;.  I&amp;#8217;ve written it in PowerPoint 2011, so you might have to convert it down if you can&amp;#8217;t open pptx files.&lt;/p&gt;

&lt;p&gt;I talk about Chef in the presentation - was hoping there was an audio or video recording, but alas, all you can have is my slide deck. :)&lt;/p&gt;

&lt;p&gt;EDIT: It&amp;#8217;s also now on &lt;a href=&quot;http://www.scribd.com/doc/50726535/Chef-A-quick-look-at-central-state-management&quot;&gt;scribd&lt;/a&gt;.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>More thoughts on DevOps</title>
    <link href="http://redbluemagenta.com/2011/03/03/more-thoughts-on-devops/"/>
    <updated>2011-03-03T11:04:00-08:00</updated>
    <id>http://redbluemagenta.com/2011/03/03/more-thoughts-on-devops</id>
    <content type="html">&lt;p&gt;After working at a few places, watching interviews, and thinking about system
administration culture, I&amp;#8217;ve ended up slightly changing my views about the DevOps
movement.&lt;/p&gt;

&lt;p&gt;Automation, repeatability, consistent root cause analysis: these are all things
that any decent sysadmin strives for.  We are all problem solvers, and we all
either want to have good documentation, automation, or both!  This new culture
that&amp;#8217;s developing is a great thing - it&amp;#8217;s of my opinion that automation is key
for system administration, and that requires a bit of coding, as well as knowing
systems in and out.&lt;/p&gt;

&lt;p&gt;I was talking to a friend of mine who works at Amazon, and he mentioned that everyone
in the company is, indeed, a systems engineer in some capacity.  This is what
DevOps strives for - software engineers who have systems clue, or at the very least,
two groups who collaborate very closely with each other.&lt;/p&gt;

&lt;p&gt;HOWEVER: Amazon, Google, etc. have had to adopt this strategy because they were forced
to do so at the scale that they were operating at.  &lt;a href=&quot;http://nosqltapes.com/video/benjamin-black-on-nosql-cloud-computing-and-fast_ip&quot;&gt;Benjamin Black had a great
interview on NoSQL Tapes&lt;/a&gt; which covers roughly the same ground, though mostly on the
technology rather than the culture (to summarize what he said, you want to look at
your application and infrastructure, figure out what the problem might be, and then
fix it; similarly, before adopting new technology, see whether the semantics of the
new technology actually fits in with your infrastructure and application.)&lt;/p&gt;

&lt;p&gt;Similarly, DevOps tackles an issue that ought to be tackled, yet it&amp;#8217;s operating
at the &amp;#8220;wrong scale&amp;#8221;: we do need to automate stuff, but some sites might be fine
with just writing shell scripts, some sites might be fine with a few Puppet/Chef
recipes but might not to manage their entire site that way.  Some companies end
up assigning SA&amp;#8217;s to program stuff in applications, or vice versa - sometimes the
result is disastrous! (Why?  I &lt;em&gt;know&lt;/em&gt; I can&amp;#8217;t write clean code worth crap [sorry
folks who have to maintain my code], and I know of a few instances of
devs attempting to manage systems with Chef and neglecting certain operational
issues, such as performance tuning, packaging, or whatever else.)&lt;/p&gt;

&lt;p&gt;If we want to execute DevOps well, we should look at Amazon and Google for guidance,
but we should &lt;em&gt;also&lt;/em&gt; look at how they&amp;#8217;re organized, what sort of scale they&amp;#8217;re
operating at, and see if it actually makes sense to assign roles in the same way.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;d love to hear your guys&amp;#8217; thoughts on this, too.  Comment below. :)&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Why I switched to Android</title>
    <link href="http://redbluemagenta.com/2011/01/15/why-i-switched-to-android/"/>
    <updated>2011-01-15T00:00:00-08:00</updated>
    <id>http://redbluemagenta.com/2011/01/15/why-i-switched-to-android</id>
    <content type="html">&lt;p&gt;I&amp;#8217;ve had an iPhone 3GS for roughly six months; I bought it second hand from my brother after owning a Nokia N900 for a while.  I was pretty disenchanted with the Maemo platform, especially with Nokia&amp;#8217;s run-ins with the &lt;a href=&quot;http://en.wikipedia.org/wiki/Osborne_effect&quot;&gt;Osborne Effect&lt;/a&gt; (for those who don&amp;#8217;t know, roughly one or two months after the N900 was released, Nokia announced that they were developing Maemo 6, which was then merged with the Moblin project in order to give birth to the MeeGo project.  They then announced that MeeGo was not to be supported officially on the N900.)&lt;/p&gt;

&lt;p&gt;I love the iOS platform, don&amp;#8217;t get me wrong; the UI is quite polished and every behavior is consistent between every app, thanks to Apple&amp;#8217;s libraries and policies regarding UI design.  However, I was tired of not having a level of customization in an un-jailbroken phone as one would have on the Android platform, plus I was not happy with how notifications were handled, nor was I happy about the restrictions on iOS&amp;#8217;s multitasking abilities.  I had to cut costs somehow on my monthly bills as well, and after evaluating AT&amp;amp;T&amp;#8217;s exuberant costs for a 2 GB data plan along with unlimited texting and a decent amount of minutes, I decided that I need to hop on another provider who had much lower costs for data and texting (I don&amp;#8217;t care much for talking on the phone, so I don&amp;#8217;t really care how minutes I get in a mobile plan.)&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve heard about the Nexus S being released in December, so I decided to dive right in and buy the phone from Best Buy, along with switching over to T-Mobile.  T-Mobile, thankfully, offers a contract-free &amp;#8220;Even More Plus&amp;#8221; plan that costs only $60 per month for unlimited data (likely capped at 5 GB, which is then throttled for any usage beyond 5 GB), unlimited texting, and 500 minutes of voice.&lt;/p&gt;

&lt;p&gt;After buying the Nexus S, the very first thing I&amp;#8217;ve noticed was how graceful the notifications were handled on Android.  Every notification is stuffed in the notifications drawer on the top, which you can read at your own leisure.  The second thing I&amp;#8217;ve noticed was that the UI wasn&amp;#8217;t really that bad at all - sure, there&amp;#8217;s a bit of inconsistency between each application, but you can be assured that the four buttons on the bottom of the phone will each consistently do what they suggest they do in every app.  In short, there&amp;#8217;s a lot of FUD about how terrible the UX/UI is in Android, and really, it&amp;#8217;s still all very easy to use.&lt;/p&gt;

&lt;p&gt;The level of customization on the Android platform is amazing.  I&amp;#8217;ve switched out the software keyboard with &lt;a href=&quot;http://www.swiftkey.net/&quot;&gt;SwiftKey&lt;/a&gt;, which I think is an awesome software keyboard for the Android.  Some people like &lt;a href=&quot;http://swypeinc.com&quot;&gt;Swype&lt;/a&gt;.  Others like the plain old Android keyboard that comes stock on many phones.  The fact of the matter is, you&amp;#8217;re not stuck with one particular input method - you have the choice of switching out the keyboard, the home screen style, etc.  You have no such choice on iOS - you have to stick with everything Apple provides by default.&lt;/p&gt;

&lt;p&gt;Android&amp;#8217;s integration with the whole suite of Google web applications is awesome, too.  Being able to use the default phonebook and be able to call out to any number with Google Voice by default is extremely helpful.  On iOS, I would&amp;#8217;ve had to use yet another application which doesn&amp;#8217;t work so well as a default dialer.  Being able to check in with Google Latitude, integrating your list of contacts with GMail, etc. is handled very well on Android.&lt;/p&gt;

&lt;p&gt;I haven&amp;#8217;t noticed any issues with the Android App Market at all.  In fact, as a consumer, it&amp;#8217;s pretty awesome being able to get games/applications at a much lower price than on Apple&amp;#8217;s App Store.  It integrates with Google Checkout, which isn&amp;#8217;t any harder to use than using your Apple ID.&lt;/p&gt;

&lt;p&gt;My only complaints about Android have to do with device fragmentation and carrier restrictions, though I&amp;#8217;ve mostly avoided the whole question by getting a Nexus S.  When I bought my Nexus S, there was buzz about dual core processor phones coming out for the Android platform, and sure enough, at CES, there were a whole slew of them announced.  Am I jealous?  Sure I am, even though my Nexus S is plenty powerful.  With the Android platform, there&amp;#8217;s always new devices being announced that are way better than the previous set of phones, which hinders device satisfaction quite a bit.  iPhone users don&amp;#8217;t have this issue, as there&amp;#8217;s only one line of phones that are released fairly predictably every year.&lt;/p&gt;

&lt;p&gt;Even with the above in mind, I&amp;#8217;m satisfied with the Nexus S and Android platform, even more so than the iPhone I&amp;#8217;ve had for a little while.  It&amp;#8217;s shaping up to be a very strong competitor to Apple&amp;#8217;s iOS platform.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Chef as a system integration tool, with a few examples.</title>
    <link href="http://redbluemagenta.com/2010/12/02/chef-as-a-system-integration-tool/"/>
    <updated>2010-12-02T08:40:00-08:00</updated>
    <id>http://redbluemagenta.com/2010/12/02/chef-as-a-system-integration-tool</id>
    <content type="html">&lt;p&gt;I haven&amp;#8217;t been using configuration management tools for too long, but for
my particular use case (if I was directly managing a fleet of machines),
I am usually fine with just having an easier to use interface for managing
my machines.&lt;/p&gt;

&lt;p&gt;However, I was tasked with building a Chef deployment that was to be a
&amp;#8220;lights out&amp;#8221;, fully automated deploy that would not only setup the machines
automatically with their particular roles, but to also have said machines
gather system state from &lt;em&gt;other&lt;/em&gt; machines and compute exactly what to do
based on other system states.  This required a lot of introspection: what
sort of things do I do when configuring machines to talk to each other?
Most of this is all second nature to me, and I tend to err on the side of
caution when configuring multiple services to talk to each other.  For
this particular project of which I have almost no experience in doing,
I figure that if I can at least write down my steps, I can automate those steps
in code.&lt;/p&gt;

&lt;p&gt;Setting up MySQL machines is a good example of the differences between the
two methods of managing machines with a tool like Chef.  You can setup
my.cnf on each machine with Chef and have my.cnf be configured so that it
properly sets up MySQL to be a slave or a master depending on any attributes
that the user provides, along with any system specific tuning depending on
the output of ohai.  The additional steps required for the second method
is to actually setup replication automatically - this requires the system
to know exactly which systems are configured as masters, where the masters
are at in its binlogs, and what sort of credentials it needs in order
to communicate with the server.&lt;/p&gt;

&lt;p&gt;In general, you must know your application before proceeding - as an example,
if you haven&amp;#8217;t worked with MySQL replication at all, then it&amp;#8217;s easy to
screw everything up, doubly so if you automate your ignorance into the code.&lt;/p&gt;

&lt;p&gt;What helps for me is to first document exactly what steps I&amp;#8217;ve taken to
setup said application, then document how the application ties with any
other service on the network.  Then redo your documentation in your favorite
configuration management system.  Figure out if you need each machine to
know every other machine&amp;#8217;s state; if so, then you might want to look into
chef-server, the Opscode platform, or Puppet + mcollective.&lt;/p&gt;

&lt;p&gt;Once you&amp;#8217;ve determined that you do need some sort of way to grab machine
states for each machine, you can now sit down and start writing your recipes
with the assumption that you&amp;#8217;ll be using chef-server or Puppet + mcollective.&lt;/p&gt;

&lt;p&gt;Since I&amp;#8217;ve been working with chef-server the most lately, I&amp;#8217;ll talk about
how I automated MySQL replication with chef-server.&lt;/p&gt;

&lt;p&gt;In the recipes I&amp;#8217;ve written, I&amp;#8217;ve used the &amp;#8220;search&amp;#8221; feature of chef-server
quite extensively in order to gather collections of nodes that match certain
criteria.  For instance, I have two roles, &amp;#8220;db-master&amp;#8221; and &amp;#8220;db-slave&amp;#8221; which
set attributes on the nodes (that can be later pulled with ohai, knife, etc.)
that says exactly what database role that was applied to the machine.  For
instance, role[db-master] sets node[:mysql][:server][:role] = master, and
similarly, role[db-slave] sets node[:mysql][:server][:role] = slave.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 1: A slice of the role file for configuring the node&amp;#8217;s DB role.&lt;/em&gt;&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;ruby&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;default_attributes&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;mysql&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;server&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;role&amp;quot;&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&amp;gt;&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;slave&amp;quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;When the role is thrown into the run_list of a particular node, these
attributes will be set under mysql.server and will be stored by chef-server.&lt;/p&gt;

&lt;p&gt;Now, let&amp;#8217;s say I want to collect all of the slaves that are known by
chef-server, so I can update the binlog positions/log file on each slave,
or at the very least, setup slave replication if it isn&amp;#8217;t already setup.
I use the search facility in chef-server in order to poll chef-server,
grab the results and stuff them into a variable.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 2: An example on using search in order to collect all of the DB slaves
known to chef-server, then doing something to each of these nodes.&lt;/em&gt;&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;ruby&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;db_slaves&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;mysql_server_role:slave&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;db_slaves&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slave&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;c1&quot;&gt;# execute CHANGE MASTER TO query&#8230;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;c1&quot;&gt;# or maybe, puts &amp;quot;ohai #{slave[:fqdn]}!&amp;quot;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Now, of course, we need a way to &lt;strong&gt;know&lt;/strong&gt; which binlog position and log file
the slaves need to use from the master server.  Further, we need to allow
the replication user to connect to the master server for each slave machine
that&amp;#8217;s known by chef-server (you really don&amp;#8217;t want to blow open your
permissions with &amp;#8216;replication&amp;#8217;@&amp;#8217;%&amp;#8217;, someone can guess the password and
stream your data from your server.  Not a tractable solution.)  It ends
up that we can assign values to attributes in the recipes as well: we simply
grab the master status from the master, put the values into new attributes
that&amp;#8217;s pushed onto chef-server (and can be pulled with knife/ohai/etc.), and
then pull those attributes out again on the slave machines.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Figure 3: Grab the master status from the master MySQL machine and throw them
into attributes, then on the slave machines, pull those attributes out again
and apply the changes to the slaves.&lt;/em&gt;&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt; &lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;14&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;15&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;16&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;17&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;18&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;19&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;20&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;21&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;22&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;23&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;24&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;25&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;26&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;27&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;28&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;29&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;30&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;31&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;32&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;33&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;34&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;35&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;36&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;37&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;38&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;39&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;40&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8217;ruby&#8217;&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# Recipe snippet applied to master DB node&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;ruby_block&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;master-log&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;logs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;sx&quot;&gt;%x[mysql -u root -e &amp;quot;show master status;&amp;quot; | grep mysql]&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;strip&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;split&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:mysql&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:log_file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;node&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:mysql&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:log_pos&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;logs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:create&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# Make sure that we create replication users for each slave machine known&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# by chef-server.&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;slaves&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;mysql_server_role:slave&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;ruby_block&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;create-replication-users&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;slaves&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;each&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slave&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;      &lt;span class=&quot;c1&quot;&gt;# slave_ip = &amp;lt;favorite mechanism to get IP address from hostname&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;      &lt;span class=&quot;sx&quot;&gt;%x[mysql -u root -e &amp;quot;GRANT REPLICATION SLAVE ON *.* TO &amp;#39;replication&amp;#39;@&amp;#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;slave_ip&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;&amp;#39; IDENTIFIED BY &amp;#39;password&amp;#39;;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:create&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# Recipe snippet applied to slave DB nodes&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;masters&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;search&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:node&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;s1&quot;&gt;&amp;#39;mysql_server_role:master&amp;#39;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;c1&quot;&gt;# Let&amp;#39;s assume we only have one master for now&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;n&quot;&gt;ruby_block&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&amp;quot;import-master-log&amp;quot;&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;block&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;do&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;c1&quot;&gt;# master_ip = &amp;lt;favorite mechanism to figure out an IP address \&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;                   &lt;span class=&quot;n&quot;&gt;from&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;hostname&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;master_log_file&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;masters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:mysql&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:log_file&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;n&quot;&gt;master_log_pos&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;masters&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:mysql&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:server&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;][&lt;/span&gt;&lt;span class=&quot;ss&quot;&gt;:log_pos&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;sx&quot;&gt;%x[mysql -u root -e &amp;quot;CHANGE MASTER TO master_host=&amp;#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;master_ip&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;&amp;#39;, master_port=3306, master_user=&amp;#39;replication&amp;#39;, master_password=&amp;#39;password&amp;#39;, master_log_file=&amp;#39;&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;master_log_file&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;&amp;#39;, master_log_pos=&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;#{&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;master_log_pos&lt;/span&gt;&lt;span class=&quot;si&quot;&gt;}&lt;/span&gt;&lt;span class=&quot;sx&quot;&gt;;&amp;quot;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &lt;span class=&quot;sx&quot;&gt;%x[mysql -u root -e &amp;quot;START SLAVE;&amp;quot;]&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;  &lt;span class=&quot;n&quot;&gt;action&lt;/span&gt; &lt;span class=&quot;ss&quot;&gt;:create&lt;/span&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Of course, you should REALLY add in checks to make sure you don&amp;#8217;t accidentally
clobber your data - you really shouldn&amp;#8217;t be applying these things if the
machine already &lt;em&gt;has&lt;/em&gt; the required info in place.  You&amp;#8217;ll definitely
want to add in checks to make sure that you don&amp;#8217;t apply master binlog
positions if the slave machine is already streaming updates from a master.&lt;/p&gt;

&lt;p&gt;Another example is configuring a service that needs to have information of
multiple machines on the network; mysql-mmm is a great example of this.
As far as I know, with mysql-mmm conf files, you cannot have a conf.d folder
with individual configurations for each machine you want to provision, plus
you have defined sections in each mysql-mmm configuration file that cannot
easily be split apart.  You&amp;#8217;ll definitely need to use something that can
gather all of that info into a single place, then generate the conf file
based on some kind of central store&amp;#8217;s knowledge of the state of every machine.&lt;/p&gt;

&lt;p&gt;If you guys have any questions on any of the above, don&amp;#8217;t hesitate to let me
know.&lt;/p&gt;

&lt;p&gt;Hope this article helps!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Further Reading:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Chef Search Syntax - &lt;a href=&quot;http://wiki.opscode.com/display/chef/Search&quot;&gt;http://wiki.opscode.com/display/chef/Search&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Solr - &lt;a href=&quot;http://lucene.apache.org/solr/&quot;&gt;http://lucene.apache.org/solr/&lt;/a&gt; (the search engine powering chef-server&amp;#8217;s search capabilities)&lt;/li&gt;
&lt;li&gt;Slides from Orchestration Panel at Cloud Connect 2010 - &lt;a href=&quot;http://www.slideshare.net/dev2ops/orchestration-panel-at-cloud-connect-2010&quot;&gt;http://www.slideshare.net/dev2ops/orchestration-panel-at-cloud-connect-2010&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

</content>
  </entry>
  
  <entry>
    <title>Yet another site redesign</title>
    <link href="http://redbluemagenta.com/2010/10/24/yet-another-site-redesign/"/>
    <updated>2010-10-24T00:00:00-07:00</updated>
    <id>http://redbluemagenta.com/2010/10/24/yet-another-site-redesign</id>
    <content type="html">&lt;p&gt;So, I&amp;#8217;ve decided to cut out all of the distracting fancy stuff and just go
with a very, very minimal site design this time around.  My intention is that
the content is at the forefront, and that all of the space should only be
used to house content, and nothing else.&lt;/p&gt;

&lt;p&gt;I can easily revert back to the previous site design if people don&amp;#8217;t like this
one.  Also, as always, I&amp;#8217;ve made the site available on &lt;a href=&quot;http://github.com/cparedes/redbluemagenta-new&quot;&gt;GitHub&lt;/a&gt; if you wish
to use the site design.  The site design is licensed under the 3-clause BSD
licensed, for the exception of anything in the &lt;em&gt;plugins directory (for now)
and anything in the &lt;/em&gt;posts and _drafts directories.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>UNIX and Literacy</title>
    <link href="http://redbluemagenta.com/2010/10/22/unix-and-literacy/"/>
    <updated>2010-10-22T12:56:00-07:00</updated>
    <id>http://redbluemagenta.com/2010/10/22/unix-and-literacy</id>
    <content type="html">&lt;p&gt;I was reading through &lt;a href=&quot;http://theody.net/elements.html&quot;&gt;this article&lt;/a&gt; on UNIX as literature a while ago;
it resonated with me very strongly, if only because I studied philosophy
(and math, which required a lot of prose writing as well) and decided to
hop into system administration as my career.&lt;/p&gt;

&lt;p&gt;I started thinking about how UNIX has affected my thoughts on computing and
how I express my thoughts on paper (or, as is the case these days, on the
internet.)  Perhaps it was the &amp;#8220;UNIX way&amp;#8221; of using pipes between programs
and transmitting clear, parsable text that helped me understand computing on
a different level than, say, doing things the &amp;#8220;Windows way&amp;#8221;; with Windows, as
a regular user or even as a sysadmin, your main method of expression is through
the mouse: you point and grunt at things, and that&amp;#8217;s about the extent of your
grammar when communicating with your computer.  On the other hand, with UNIX,
your grammar is expanded quite a bit; you operate on entire sentences, phrases,
and words, and the way you tell your machine to do anything is by writing
things in the command line.&lt;/p&gt;

&lt;p&gt;Yes, you might have the same experience in DOS as you might in UNIX; after
all, you do have pipes in DOS and that gets you most of the way there. UNIX
applications, however, often do one thing really really well, and it takes
a bit of knowledge and tinkering in order to figure out how to really use
each program to its full potential.  sed and awk are probably two of the most
powerful programs in the whole UNIX suite of programs, but most people don&amp;#8217;t
realize it until they start digging deeper.  Hell, I still use sed as a simple
string replacement program, without considering any of the other features
that&amp;#8217;s available in sed.&lt;/p&gt;

&lt;p&gt;But the biggest thing that distinguishes UNIX from all other operating systems
is that &lt;em&gt;words&lt;/em&gt; and &lt;em&gt;sentences&lt;/em&gt; are of the primary focus in the OS; it&amp;#8217;s only
later in the history of UNIX that you start seeing windowing systems, but
even then, text is at the forefront of all interactions in the system.&lt;/p&gt;

&lt;p&gt;Powershell, though a valiant effort (and a &lt;em&gt;better&lt;/em&gt; shell than bash, from
what I hear), is ultimately disappointing.  Why?  The things you operate on
in Powershell are &lt;em&gt;objects&lt;/em&gt;, not words, and definitely not sentences. This may
be a bit better if we&amp;#8217;re talking about our perception of the world, for we
at least observe objects before we can ever talk about them with language
(this is a separate topic for a different field, this can be debated for eons),
but we wield words as easily as we move our arms around, and so it is much
more natural to operate on words on a computer than it is to operate on
objects that are constructed artificially.&lt;/p&gt;

&lt;p&gt;As the article asserts, it&amp;#8217;s freeing to be able to use language to express
your thoughts to a computer; I feel the same exact way, too.  It&amp;#8217;s hard as hell
to get used to it, especially since a lot of us have grown up using Windows,
but once you&amp;#8217;ve mastered how to express your thoughts on a UNIX system, it&amp;#8217;s
extremely hard to go back to any other paradigm.&lt;/p&gt;

&lt;p&gt;All I have to say is:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;$ echo &quot;woot&quot; | cowsay
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    _____
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;   &amp;lt; woot &gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;    &#8212;&#8211;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;         \   ^__^
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;          \  (oo)\_______
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;             (__)\       )\/\
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;                 ||&#8212;-w |
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;                 ||     ||&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;



</content>
  </entry>
  
  <entry>
    <title>Web Security 101</title>
    <link href="http://redbluemagenta.com/2010/10/22/web-security-101/"/>
    <updated>2010-10-22T10:12:00-07:00</updated>
    <id>http://redbluemagenta.com/2010/10/22/web-security-101</id>
    <content type="html">&lt;p&gt;A friend of mine recently asked me what sort of security issues she should
keep in mind when she&amp;#8217;s designing web pages and uploading them to a web server.&lt;/p&gt;

&lt;p&gt;Note that I&amp;#8217;m differentiating between a web designer and a web developer, the
latter of which would mostly work with writing code in some sort of
language/framework that&amp;#8217;s meant to be used in a web application, such as
Javascript, Ruby, Python, Java, etc.  This article is meant for web designers,
who usually mock up UI prototypes and write the presentational stuff for a
given website.&lt;/p&gt;

&lt;p&gt;The short answer is, &amp;#8220;not too much.&amp;#8221;  If you&amp;#8217;re only designing static pages
in HTML and CSS, there&amp;#8217;s really not too much you&amp;#8217;d have to be worried about -
the language, for instance, dictates only structure, content, and presentation,
and doesn&amp;#8217;t touch upon anything that would interact with the system in any
significant way.  The only scenario that I could think of that could really
screw with a web designer is if you&amp;#8217;re writing up a web form that talks with
a database, or if you&amp;#8217;re writing up a web form that transmits passwords over
the internet, to which you have to worry about sanitizing your inputs for
any strings that may try to execute an arbitrary SQL statement, or making
sure that the web form is strictly communicating over SSL.&lt;/p&gt;

&lt;p&gt;The long answer is, &amp;#8220;well, sure, there&amp;#8217;s a few.  You can&amp;#8217;t be too cautious.&amp;#8221;
The biggest issue that could arise is improper file permissions on your files.
I&amp;#8217;ll go ahead and enumerate each issue under a different header and explain
a few of the basic things that one needs to keep in mind when uploading stuff
to a server, and writing up static web pages.&lt;/p&gt;

&lt;h2&gt;File Permissions&lt;/h2&gt;

&lt;p&gt;Most web servers these days are hosted on a UNIX platform; there&amp;#8217;s a small
number that are hosted off of Windows, but more likely than not, when you&amp;#8217;re
signing up for a web server at a random company, it&amp;#8217;ll be on a UNIX system.&lt;/p&gt;

&lt;p&gt;Therefore, you&amp;#8217;ll need to learn a few basics of UNIX permissions, at least
enough to know what to do.&lt;/p&gt;

&lt;p&gt;There&amp;#8217;s three groups of people that UNIX recognizes for permissions:
&amp;#8220;owner,&amp;#8221; &amp;#8220;group,&amp;#8221; and &amp;#8220;the world.&amp;#8221;  As you might expect, the owner of the file
is a single user that has complete ownership over the file.  Groups are simply
groups of users on a UNIX system that are named explicitly on the UNIX system.
Finally, &amp;#8220;the world&amp;#8221; is simply everyone else that is both not the owner of the
file nor a part of the group that owns the file.&lt;/p&gt;

&lt;p&gt;On UNIX, this is expressed in a three digit number attached to each file and
directory.&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;7    7    7
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;|    |    |
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;owner group world&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;These numbers specify exactly what sort of permissions are applied to the file
for each user, group, and everyone else.  (In this particular case, 777 =
read/write/execute for the user, group, and world.)&lt;/p&gt;

&lt;p&gt;How do these numbers specify the individual permissions for users, groups,
and the world?&lt;/p&gt;

&lt;p&gt;UNIX adds up three different numbers (4, 2, and 1), with each specifying
a different permission type.&lt;/p&gt;

&lt;p&gt;4 signifies read access for the file/directory.
2 signifies write access for the file/directory.
Finally, 1 signifies execute access for the file/directory.&lt;/p&gt;

&lt;p&gt;You can also deny all permissions by simply using &amp;#8220;0&amp;#8221; for the specific
permission bit - say we only want read/write/execute for the owner,
but not for anyone else.  Then we apply the permission &amp;#8220;700&amp;#8221; to the file,
where &amp;#8220;7&amp;#8221; is for the owner, the second digit is for the group and the
third digit is for the world.&lt;/p&gt;

&lt;p&gt;If I wanted read/write access for all users, then I add 4 + 2 together to get
6 (since I want both read (4) and write (2) access), and then I use that number
for every single group of people.  Therefore, I get 666. :)&lt;/p&gt;

&lt;p&gt;If I wanted read/write/execute for the owner, but only read only access for
everyone else, then I use 744. For the first bit, 4 + 2 + 1 = 7, and then
I use 4&amp;#8217;s for the other people for read-only access.&lt;/p&gt;

&lt;p&gt;In most FTP clients, you can right click the file and set the permissions
within the FTP interface.  If you have a UNIX shell, you can execute
the following command to change permissions on a specific file:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;$ chmod 744 [filename]&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;How does this affect security when you&amp;#8217;re uploading HTML/CSS files to a web
server?&lt;/p&gt;

&lt;p&gt;If you have 777 permissions on &lt;em&gt;every&lt;/em&gt; file, then that means you&amp;#8217;re also
granting full access to everyone on the system, &lt;em&gt;including&lt;/em&gt; anyone who
decides to hack the web server.  The latter scenario isn&amp;#8217;t totally
implausible, but the former scenario is even more likely - since most shared
web servers (usually the ones costing roughly $5-$10 per month) don&amp;#8217;t have
much separation between each user on the system, that means any other customer
can easily muck up your website without as much having explicit access to
&lt;em&gt;your&lt;/em&gt; account.&lt;/p&gt;

&lt;p&gt;When in doubt, use &amp;#8220;644&amp;#8221; permissions on your files.  That sets the file to be,
as you might guess by now, read/write for the owner, and read only for everyone
else.  For directories, use &amp;#8220;755&amp;#8221; permissions.  If you set directories to not
have the execute permission set for a specific user/group, then you won&amp;#8217;t be
able to change over to that directory in the future (this is easily fixed by
setting the permissions back to 755.)&lt;/p&gt;

&lt;h2&gt;Firewalls&lt;/h2&gt;

&lt;p&gt;Typically, if you&amp;#8217;re using another web provider like A Small Orange or
whoever else, you won&amp;#8217;t have to worry too much about this - they usually take
care of those issues for you.&lt;/p&gt;

&lt;p&gt;However, if you&amp;#8217;re using a &amp;#8220;virtual private server&amp;#8221; (VPS) provider like
Linode, prgmr, Slicehost, or Blue Box Group (yeah, sorry, shameless plug :)),
or even your own server in your house, then you&amp;#8217;ll have to worry about setting
up a firewall.&lt;/p&gt;

&lt;p&gt;Usually, you can setup the firewall to block all incoming traffic BUT the
specific set of traffic associated with someone browsing a website.  The
best way to determine, uniquely, whether someone&amp;#8217;s browsing a website or not,
is by looking at what port they&amp;#8217;re trying to use.  For web traffic, the port
number is port 80.  If you&amp;#8217;re serving secure content through HTTPS, then you&amp;#8217;ll
have to open up port 443 as well.&lt;/p&gt;

&lt;p&gt;I can&amp;#8217;t possibly cover all of the different firewall products out there, so
all I can say is that you should take a look at your firewall/router manual
and see how you can do port forwarding for a particular machine.&lt;/p&gt;

&lt;h2&gt;HTTPS&lt;/h2&gt;

&lt;p&gt;&lt;a href=&quot;http://en.wikipedia.org/wiki/HTTPS&quot;&gt;This wikipedia article&lt;/a&gt; does a way
better job of explaining the issue than I ever could.&lt;/p&gt;

&lt;p&gt;In short, you want to make sure that the server is vouched by some sort
third party as a &amp;#8220;legitimate website&amp;#8221;, and you want to make sure that any
sensitive information (like passwords and the like) are transmitted in
HTTPS.  HTTPS guarantees that any data being transferred between two
parties (in this case, you and the server) is not transmitted in clear text.&lt;/p&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;

&lt;p&gt;This article ended up being much longer than I thought. :)  If anyone needs
any clarification on any of the concepts, let me know.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>MySQL Replication - master slave replication with multiple R/O masters</title>
    <link href="http://redbluemagenta.com/2010/10/12/mysql-replication--master-slave-replication-with-multiple-ro-masters/"/>
    <updated>2010-10-12T13:41:00-07:00</updated>
    <id>http://redbluemagenta.com/2010/10/12/mysql-replication&#8211;master-slave-replication-with-multiple-ro-masters</id>
    <content type="html">&lt;p&gt;(NOTE: I know, the blog post says that I&amp;#8217;m working with multiple R/O masters.
The guide doesn&amp;#8217;t tell you how to do such a thing.  However, the principles
are quite the same, and you can easily extend this guide to make one of your
other R/O slaves to be an R/O master.)&lt;/p&gt;

&lt;p&gt;So, after battling MySQL for a couple of days, I&amp;#8217;ve come out with a bit more
experience with replication and a few pitfalls that I&amp;#8217;ve encountered that you
may encounter as well.&lt;/p&gt;

&lt;p&gt;The MySQL installation I was wrestling with consisted of a single R/W master,
a couple of R/O slaves, a R/O slave that also acted as an R/O master, and
several R/O slave machines slaving off of the R/O master.&lt;/p&gt;

&lt;p&gt;Apologies for the ASCII art:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;* - R/W Master
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;                 |
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;                /|\
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;               / | \
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt; R/O slave  - *  *  * - R/O slave
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;                 |\_ R/O slave/master
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;                 |
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;                /|\
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;               * * * - R/O slaves&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;We assume that the R/W master already has a bunch of data, and that we need
to copy all of the data over to each machine.&lt;/p&gt;

&lt;p&gt;The biggest thing to keep in mind is that it&amp;#8217;s REALLY REALLY easy to mess
this up - if your replication settings are off by just a little bit on
the slave machines, then you&amp;#8217;re going to corrupt your data on the slave
machines.&lt;/p&gt;

&lt;p&gt;Also, when we do the data copy to each machine, we will want to wipe out any
relay logs, any master binary logs, the master.info file, and the
slave-relay-bin.info file on the slave machines.  We&amp;#8217;ll recreate the
master.info file through the MySQL CLI.&lt;/p&gt;

&lt;p&gt;So, without further ado, here&amp;#8217;s how you set everything up:&lt;/p&gt;

&lt;h2&gt;Step 1: Create a backup and ship it off to all of the slave machines.&lt;/h2&gt;

&lt;p&gt;You&amp;#8217;ll have to make sure that either an existing slave server, or your master
server, either has a lock on all tables (for mysqldump), or the daemon is
switched off completely (for raw data backup with tar.)  In either case,
you&amp;#8217;ll need to make sure you can read all of the data without it being written
to at the same time.&lt;/p&gt;

&lt;p&gt;In my particular case, I&amp;#8217;ve shut off the daemon and grabbed a snapshot using
tar, since I had a spare slave server with an up to date copy of the data.
I streamed the compressed tar data over SSH to the slave servers:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;cd /var/lib ; tar -czf - mysql | \
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;ssh &amp;lt;host&gt; &quot;tar -C /destination/folder -zxvf -&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Depending on how large your database is, it may or may not be popcorn time. :)&lt;/p&gt;

&lt;h2&gt;Step 2: Remove existing relay logs, master.info, etc.&lt;/h2&gt;

&lt;p&gt;By default, these files are stored in /var/lib/mysql.&lt;/p&gt;

&lt;p&gt;Remove all of them:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;cd /var/lib/mysql ; rm mysql-bin* slave-relay-bin* \
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;relay-log* mysqld-relay-bin* master.info&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;h2&gt;Step 3: Setup my.cnf on the master and all slave machines.&lt;/h2&gt;

&lt;p&gt;Okay, so I know this is pedantic, but we know for sure how to identify
different machines from each other in some way or another, either by an
IP address, a hostname, or some other metadata.  MySQL uses an internal
identification scheme for identifying different machines in an MySQL
replication environment.  You can define this ID under the [mysqld] section
in my.cnf (usually located in /etc/mysql/my.cnf), using the configuration
option &amp;#8220;server-id&amp;#8221;.  These must be unique for every machine in the entire
set of machines that&amp;#8217;s participating as either a master or a slave in
the replication setup.&lt;/p&gt;

&lt;p&gt;I usually start my numbering from the master, and work my way down.  For
instance, I&amp;#8217;ll number my R/W master as server-id = 1, my R/O master as
server-id = 2, one of the slaves as server-id = 3, etc.&lt;/p&gt;

&lt;p&gt;We&amp;#8217;ll split this step into two parts: first part will be for master
machines (R/W and R/O), and R/O slave machines.&lt;/p&gt;

&lt;p&gt;R/W and R/O masters:&lt;/p&gt;

&lt;p&gt;You&amp;#8217;ll want to make sure that the following are defined in my.cnf:&lt;/p&gt;

&lt;p&gt;log-bin = /var/log/mysql/mysql-bin.log&lt;br/&gt;
log-bin-index = /var/log/mysql/mysql-bin.index&lt;br/&gt;
log-slaves-updates&lt;/p&gt;

&lt;p&gt;For the R/O master, you&amp;#8217;ll want to also set read_only = 1.&lt;/p&gt;

&lt;p&gt;R/O slave:&lt;/p&gt;

&lt;p&gt;relay-log = /var/log/mysql/slave-relay.log&lt;br/&gt;
relay-log-index = /var/log/mysql/slave-relay.index&lt;br/&gt;
relay-log-info = /var/log/mysql/slave-relay.info&lt;br/&gt;
replicate-ignore-db = mysql&lt;br/&gt;
read_only = 1&lt;/p&gt;

&lt;p&gt;One more note: make sure skip-slave-start is set on all slave machines in
my.cnf for now; we&amp;#8217;ll delete the line later, but this is necessary so we
can have as much time as possible in setting up the slave machines.&lt;/p&gt;

&lt;h2&gt;Step 4: Setup MySQL replication on all slaves.&lt;/h2&gt;

&lt;p&gt;We&amp;#8217;re now ready to set up MySQL replication on all of the slave machines.&lt;/p&gt;

&lt;p&gt;We&amp;#8217;re going to set up grants on the R/W master to the two slave machines
and the R/O master, and then we&amp;#8217;re going to set up grants on the R/O
master for each of its slaves.&lt;/p&gt;

&lt;p&gt;Let&amp;#8217;s assume that the IP address scheme is as such:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;R/W Master: 10.0.0.1
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;|_ R/O Slave: 10.0.0.2
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;|_ R/O Slave: 10.0.0.3
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;|_ R/O Master: 10.0.0.4
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt; \_ R/O Slave: 10.0.0.11
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt; |_ R/O Slave: 10.0.0.12
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt; |_ R/O Slave: 10.0.0.13&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Alright, let&amp;#8217;s login to the R/W master and grant replication rights to its
three slaves:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;rwmaster# mysql -u root
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;mysql&gt; GRANT REPLICATION SLAVE ON *.* TO \
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&#8217;replicate&#8217;@&#8217;10.0.0.2&#8217; IDENTIFIED BY &#8216;foobar&#8217;;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;mysql&gt; GRANT REPLICATION SLAVE ON *.* TO \
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&#8217;replicate&#8217;@&#8217;10.0.0.3&#8217; IDENTIFIED BY &#8216;foobar&#8217;;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;mysql&gt; GRANT REPLICATION SLAVE ON *.* TO \
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&#8217;replicate&#8217;@&#8217;10.0.0.4&#8217; IDENTIFIED BY &#8216;foobar&#8217;;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;mysql&gt; FLUSH PRIVILEGES;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;mysql&gt; \q&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Stop the master&amp;#8217;s daemon:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;rwmaster# /etc/init.d/mysql stop&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Now, let&amp;#8217;s login to the R/O master and grant replication rights to its three
slaves:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;romaster# mysql -u root
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;mysql&gt; GRANT REPLICATION SLAVE ON *.* TO \
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&#8217;replicate&#8217;@&#8217;10.0.0.11&#8217; IDENTIFIED BY &#8216;barfoo&#8217;;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;mysql&gt; GRANT REPLICATION SLAVE ON *.* TO \
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&#8217;replicate&#8217;@&#8217;10.0.0.12&#8217; IDENTIFIED BY &#8216;barfoo&#8217;;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;mysql&gt; GRANT REPLICATION SLAVE ON *.* TO \
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&#8217;replicate&#8217;@&#8217;10.0.0.13&#8217; IDENTIFIED BY &#8216;barfoo&#8217;;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;mysql&gt; FLUSH PRIVILEGES;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;mysql&gt; \q&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;We grab the master status from the R/W master and the R/O master, and note
it down for later usage:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;8&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;9&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;10&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;11&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;12&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;13&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;rwmaster# mysql -u root
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;mysql&gt; SHOW MASTER STATUS\G
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&#8230;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;File: mysql-bin.log.000500
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;Position: 5150150
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&#8230;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;romaster# mysql -u root
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;mysql&gt; SHOW MASTER STATUS\G
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&#8230;
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;File: mysql-bin.log.000001
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;Position: 4
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;&#8230;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Again, note these down.  The R/W master binlog file and position will be
needed for its immediate slaves and the R/O master, and the R/O master file
and position will be relevant for its immediate slaves.  Also note down
the passwords and username for each grant: we&amp;#8217;re going to use this information
to connect to the respective masters in order to start replication.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;YOU CANNOT USE THE SAME BINLOG FILE AND INFORMATION FOR ANY SLAVES NOT
DIRECTLY CONNECTED TO THE MASTER.&lt;/strong&gt;  If you do, expect replication to break.
I&amp;#8217;ve learned this the hard way.  Always assume that any replication you&amp;#8217;re
setting up is relevant only for any direct connection between a master/slave.&lt;/p&gt;

&lt;p&gt;With these binlog files and positions in mind, you&amp;#8217;ll now set up each slave
to connect to its direct master.&lt;/p&gt;

&lt;p&gt;We&amp;#8217;re going to start with the R/W master&amp;#8217;s direct slaves.&lt;/p&gt;

&lt;p&gt;Connect to each slave and enter in the following information:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;mysql&gt; CHANGE MASTER TO \
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;MASTER_HOST=&#8217;10.0.0.1&#8217;, \
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;MASTER_PORT=&#8217;3306&#8217;, \
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;MASTER_LOG_FILE=&#8217;mysql-bin.log.000500&#8217;, \
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;MASTER_LOG_POS=&#8217;5150150&#8217;, \
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;MASTER_USER=&#8217;replicate&#8217;, \
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;MASTER_PASSWORD=&#8217;foobar&#8217;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;where MASTER_LOG_FILE and MASTER_LOG_POS is grabbed from the output of
&amp;#8216;SHOW MASTER STATUS\G&amp;#8217; on the R/W master.&lt;/p&gt;

&lt;p&gt;Now, connect to the R/O slaves that are connected directly to the R/O slave,
connect to the MySQL daemon, then type in the following:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;2&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;3&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;4&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;5&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;6&lt;/span&gt;
&lt;span class=&#8217;line-number&#8217;&gt;7&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;mysql&gt; CHANGE MASTER TO \
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;MASTER_HOST=&#8217;10.0.0.4&#8217;, \
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;MASTER_PORT=&#8217;3306&#8217;, \
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;MASTER_LOG_FILE=&#8217;mysql-bin.log.000001&#8217;, \
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;MASTER_LOG_POS=&#8217;4&#8217;, \
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;MASTER_USER=&#8217;replicate&#8217;, \
&lt;/span&gt;&lt;span class=&#8217;line&#8217;&gt;MASTER_PASSWORD=&#8217;barfoo&#8217;;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;In order to be extra cautious about the data on each slave, we want to start
from the least significant slaves (the ones attached to the R/O master, since
they won&amp;#8217;t receive their updates until the R/O master receives its updates
from the R/W master), and then work our way up until we get to the R/W master.
(Reason why we&amp;#8217;re being paranoid about this is because it&amp;#8217;s very possible, if
we worked in the opposite direction, for the R/W master to get too ahead of
the slaves for us to actually set up the slaves for replication.  In this
case, we&amp;#8217;d have to start over from scratch and create a new snapshot of the
data.  Not good.)&lt;/p&gt;

&lt;p&gt;Go to the R/O master&amp;#8217;s slaves and type the following in:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;mysql&gt; START SLAVE;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Then go to the R/O master and the R/W master&amp;#8217;s slaves and type the following
in:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;mysql&gt; START SLAVE;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;Now start the R/W master&amp;#8217;s daemon back up:&lt;/p&gt;

&lt;figure class=&#8217;code&#8217;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td class=&quot;gutter&quot;&gt;&lt;pre class=&quot;line-numbers&quot;&gt;&lt;span class=&#8217;line-number&#8217;&gt;1&lt;/span&gt;
&lt;/pre&gt;&lt;/td&gt;&lt;td class=&#8217;code&#8217;&gt;&lt;pre&gt;&lt;code class=&#8221;&gt;&lt;span class=&#8217;line&#8217;&gt;rwmaster# /etc/init.d/mysql start&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&lt;/div&gt;&lt;/figure&gt;


&lt;p&gt;You can run &amp;#8216;SHOW SLAVE STATUS;&amp;#8217; on each slave machine to see if it&amp;#8217;s
replicating normally.&lt;/p&gt;

&lt;p&gt;If not, you can check /var/log/mysql/mysqld.log (or mysqld.err) and see
what&amp;#8217;s breaking.&lt;/p&gt;

&lt;p&gt;That&amp;#8217;s it!&lt;/p&gt;

&lt;p&gt;Let me know if this guide has been helpful for you guys. :)&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Quick update on everything as of late</title>
    <link href="http://redbluemagenta.com/2010/10/09/quick-update-on-everything-as-of-late/"/>
    <updated>2010-10-09T16:52:00-07:00</updated>
    <id>http://redbluemagenta.com/2010/10/09/quick-update-on-everything-as-of-late</id>
    <content type="html">&lt;p&gt;Hey guys.&lt;/p&gt;

&lt;p&gt;I haven&amp;#8217;t been posting all too much lately - I&amp;#8217;ve recently started over at
&lt;a href=&quot;http://bluebox.net&quot;&gt;Blue Box Group, LLC&lt;/a&gt; and have hit the ground running.&lt;/p&gt;

&lt;p&gt;Now that I have my breath from working here for two weeks, I can go over a few
things that&amp;#8217;s been happening as of late (not necessarily work related.)&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Again, I&amp;#8217;ve been hired by Blue Box Group as a senior system administrator.
This job is really fucking awesome - I&amp;#8217;ve had several projects thrown at me
since I&amp;#8217;ve started, and I&amp;#8217;m learning quite a bit about everything. Things
are excellent on this front. This is to no detriment to my previous employer,
&lt;a href=&quot;http://3tier.com&quot;&gt;3TIER&lt;/a&gt;.  They&amp;#8217;re an excellent group to work for, and they&amp;#8217;re awesome people
in general.  I just think, at this point in time, I need to get my feet
very much wet - this means going in head first into crazy problems right away.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I&amp;#8217;ve been reading a lot of things&amp;#8230; and I really should stop doing that.
Why? Because my mind is way too scatterbrained to keep focus on many things.
I think the one thing I need to sit down with, until I&amp;#8217;m at a really good
point to stop, is probably &amp;#8220;Structure and Interpretation of Computer Programs.&amp;#8221;
I&amp;#8217;m not even through the first chapter; it&amp;#8217;s a challenging book, but a good one
to read, and I hope to learn a bit of much needed computer science training
that I&amp;#8217;ve skipped over when I was in college.  While I was reading this book,
I&amp;#8217;ve also found a bunch of tutorials and a few other books that I should read;
the two that stick out for me at the moment are &amp;#8220;Web Operations,&amp;#8221; and
&amp;#8220;Let&amp;#8217;s Build a Compiler.&amp;#8221;  &amp;#8220;Web Operations&amp;#8221; will likely be the next thing
I&amp;#8217;ll concentrate on, though I&amp;#8217;ve read through half of the book so far.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;I&amp;#8217;ve finally ordered my tickets for LISA &amp;#8216;10!  I&amp;#8217;ve my hotel and flight
booked already, and so I&amp;#8217;m all set for this year&amp;#8217;s LISA!  There&amp;#8217;s a chance
I&amp;#8217;ll speak about the LOPSA Mentorship Program at LISA at one of the BoF&amp;#8217;s,
but we&amp;#8217;ll see.  Can&amp;#8217;t wait to meet all of you guys in the flesh. :)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Finally, I&amp;#8217;ve whittled down a few outstanding holes in my knowledge that
I really need to work on.  First, I&amp;#8217;m extremely weak with databases. I&amp;#8217;ve
only a cursory understanding of MySQL replication, I haven&amp;#8217;t crafted many
statements longer than a &amp;#8220;SELECT * FROM TABLE&amp;#8221;, and I also haven&amp;#8217;t seen many
of the problems that can go wrong in a database.  Second, I&amp;#8217;m extremely weak
with essential computer science concepts.  I don&amp;#8217;t know too many data
structures nor algorithms, which hampers a lot of things when it comes to
performance tuning and optimization of code.  The way I plan to tackle these
two deficiencies is to both tackle a ton of projects that involve exercising
both skills, and also attend conferences and read books on the subject.
I&amp;#8217;ve signed up for the basic databases tutorial at LISA &amp;#8216;10, and while this
will obviously not be exhaustive, it&amp;#8217;ll at least get the ball rolling. I
imagine a lot more reading and a lot more programming will help me with
my comp-sci-fu.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;


&lt;p&gt;Yep. :)&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Experiences with leading teams</title>
    <link href="http://redbluemagenta.com/2010/09/27/experiences-with-leading-teams/"/>
    <updated>2010-09-27T08:11:00-07:00</updated>
    <id>http://redbluemagenta.com/2010/09/27/experiences-with-leading-teams</id>
    <content type="html">&lt;p&gt;I&amp;#8217;ve been chairing the &lt;a href=&quot;http://lopsa.org/mentor&quot;&gt;LOPSA Mentorship Program&lt;/a&gt; for the past few months;
I was approached by Lois Bennett about leading the program, and so I took
the helm, without much of any experience whatsoever.  I didn&amp;#8217;t really use
any methodologies that are already established as &amp;#8220;best practices&amp;#8221;; the Agile
framework definitely was an influence, but my style is to not be heavy handed
with much of anything.&lt;/p&gt;

&lt;p&gt;I think the biggest thing that I learned to do is to always, always let the
team decide the best course of action.  My role is to only guide the
discussion, and make sure that any meetings don&amp;#8217;t last too long.  If I had
an opinion, I would throw it into the ring, but more often than not, it would
be torn apart by the rest of the team members; this is good, the best ideas
win when things are done this way, in my opinion.  If a discussion went on
for too long, I&amp;#8217;d guide people to talk about it either on IRC or on the
mailing list, so we can get the meeting done faster.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I never try to assert my position of power.&lt;/strong&gt;  I&amp;#8217;ve never once considered
myself to be &amp;#8220;above&amp;#8221; anyone else - everyone else in the team are considerably
more experienced than me, and even if they weren&amp;#8217;t, it would do no one good
if I asserted my power at every discussion.  People need to be autonomous
and be able to say, without fear, what their opinion is.&lt;/p&gt;

&lt;p&gt;We communicated over the phone once a week with a free conference call
provider, sussed out any minute details on our mailing list, and if anyone
wished, they could also talk to us through IRC.  The way we communicated was
already established before I started leading the program, and so it was
important to keep it the same.&lt;/p&gt;

&lt;p&gt;I think, what&amp;#8217;s also important, is to always delegate the work.  This does
several things for you: one, it frees up your time so you can prepare for
more discussion; two, the people on the team are now accountable for getting
the things done, which, I suppose in theory, should empower the people on the
team.  It&amp;#8217;s not exactly good to be the leader and hog all the work.&lt;/p&gt;

&lt;p&gt;I think, what I personally need to work on, is better organization, and
just simple &amp;#8220;thank you&amp;#8217;s&amp;#8221; to people.  Everyone&amp;#8217;s done a really great job,
and I&amp;#8217;m not sure if I did such a great job in letting everyone know that.&lt;/p&gt;

&lt;p&gt;Any sort of suggestions are welcome - I see my career sticking on the technical
track, but I figure that I&amp;#8217;ll be leading teams of people at work sometime
down the road.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>Why work in system administration?</title>
    <link href="http://redbluemagenta.com/2010/09/22/why-work-in-system-administration/"/>
    <updated>2010-09-22T20:10:05-07:00</updated>
    <id>http://redbluemagenta.com/2010/09/22/why-work-in-system-administration</id>
    <content type="html">&lt;p&gt;I will admit right away: system administration is really not a sexy field
to be in, at least compared to the other technical fields out there.
However, I personally feel quite at home in system administration, and based
on my limited exposure so far, it can also be one of the most fulfilling fields
to work in.&lt;/p&gt;

&lt;p&gt;The range of responsibilities may vary between teams and different companies,
but at its core, we manage multiple machines, whether they be hooked into a
network or not. Some departments employ sysadmins in order to not only look
over the network and systems of computers, but also to administer any other
device that hooks into a computing device, like a network printer, fax
machines, etc.  Other roles are far removed from the actual physical hardware,
to which the sysadmin takes more on a role of ensuring that such systems
of computers are actually doing what they&amp;#8217;re supposed to do (which is to
serve that website you always go to, or to let you login with your username
and password without compromising security, etc.)&lt;/p&gt;

&lt;p&gt;But why work as a system administrator rather than as a software developer,
or as a lawyer, doctor, etc.?&lt;/p&gt;

&lt;p&gt;The biggest reason that the field appeals to me is that I get to solve
interesting problems, day after day; it&amp;#8217;s awesome to solve issues involving
hundreds, or even thousands, of computers. It&amp;#8217;s a natural extension of the
knack that one gains when they&amp;#8217;re fixing a single computer - now
that you&amp;#8217;re working with hundreds/thousands of machines, you now have to think
about picking a solution that is tractable to deploy to a whole system of
computers.&lt;/p&gt;

&lt;p&gt;The system administrator often keeps his nose as close to the particular inner
workings of a system, and thus, usually is the domain expert on weird issues
that happen with machines.  As of late, this knowledge is not necessarily
valued as much as it was before, but it&amp;#8217;s still ever more important - for
instance, when deploying things to EC2 or even bare metal, you need to know
how to measure IOPs, and you even need to know &lt;em&gt;why&lt;/em&gt; you&amp;#8217;re measuring that in
the first place (maybe you&amp;#8217;re deploying an I/O intensive service?)  When
deploying services in the cloud, more often than not, you&amp;#8217;re working with
machines that are significantly underpowered compared to what you can get
as a bare metal machine; therefore, these weird things that you&amp;#8217;ve been
learning about file system performance and whatever else suddenly become
important.&lt;/p&gt;

&lt;p&gt;No matter what anyone says, the system administrator is, more often than
not, one of the most important roles in a company, especially when your company
is providing large amounts of computing resources for customers.  They are
the guys who both make sure your desktop is running smoothly, and make sure
that your high traffic website doesn&amp;#8217;t fall under the pressure of traffic,
nor under the pressure of system crackers.  They&amp;#8217;re responsible for all
computing resources, all the way up (but not necessarily including) the
application level, where the software developers thrive (I&amp;#8217;m not saying that
software devs aren&amp;#8217;t concerned about system-level issues, it&amp;#8217;s just that it&amp;#8217;s
not usually their central focus point, and it&amp;#8217;s something that most devs
aren&amp;#8217;t responsible for in production environments.)&lt;/p&gt;

&lt;p&gt;It&amp;#8217;s not sexy, but it&amp;#8217;s extremely fulfilling. I encourage everyone to take
a look at the field and see if it&amp;#8217;s for you.&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>LOPSA Mentorship Program</title>
    <link href="http://redbluemagenta.com/2010/09/22/lopsa-mentorship-program/"/>
    <updated>2010-09-22T19:01:30-07:00</updated>
    <id>http://redbluemagenta.com/2010/09/22/lopsa-mentorship-program</id>
    <content type="html">&lt;p&gt;We&amp;#8217;ve launched the &lt;a href=&quot;http://lopsa.org/mentor&quot;&gt;LOPSA mentorship program&lt;/a&gt; about a week ago, and we&amp;#8217;re
now soliciting for proteges and mentors to sign up for the program.&lt;/p&gt;

&lt;p&gt;Why sign up for the LOPSA mentorship program even if you have great mentors
at work already?  We think that it only helps you, as a system administrator,
to have several mentors (if you already have one or two guiding you through
your career); if you don&amp;#8217;t already have a mentor, then you&amp;#8217;ll benefit greatly
by signing up for the program, no matter your skill level.&lt;/p&gt;

&lt;p&gt;And for those wondering whether you should be a mentor or not, you don&amp;#8217;t
have to worry about where your skill level is at, either - you don&amp;#8217;t have to
have 10-15 years of experience in the field to help someone else.  It&amp;#8217;s also
one of the better ways to learn more about your field - helping someone with
a particular problem can also solidify your own skills in that particular
problem domain.&lt;/p&gt;

&lt;p&gt;So, if you&amp;#8217;re wanting to be a protege, you don&amp;#8217;t have to be a LOPSA member -
it&amp;#8217;s totally free.  If you&amp;#8217;re wanting to be a mentor, you &lt;strong&gt;do&lt;/strong&gt; have to be
a LOPSA member, though for a short period of time, you can &lt;a href=&quot;http://lopsa.org/register&quot;&gt;register&lt;/a&gt; for
only $35.&lt;/p&gt;

&lt;p&gt;Thanks everyone!  And be sure to &lt;a href=&quot;http://lopsa.org/mentor&quot;&gt;sign up&lt;/a&gt; if you&amp;#8217;re interested!&lt;/p&gt;

&lt;p&gt;Official press release:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;http://lopsa.org/mentor_program_PR&quot;&gt;http://lopsa.org/mentor_program_PR&lt;/a&gt;&lt;/p&gt;
</content>
  </entry>
  
  <entry>
    <title>My foray into Lisp, SICP, and emacs</title>
    <link href="http://redbluemagenta.com/2010/09/12/my-foray-into-lisp-sicp-and-emacs/"/>
    <updated>2010-09-12T07:40:45-07:00</updated>
    <id>http://redbluemagenta.com/2010/09/12/my-foray-into-lisp-sicp-and-emacs</id>
    <content type="html">&lt;p&gt;So, after many jokes between me, my coworkers, and various friends, I&amp;#8217;ve
finally decided to break down and learn emacs.  This is a bit after I decided
to learn a bit of material from &lt;a href=&quot;http://mitpress.mit.edu/sicp&quot;&gt;Structure and Interpretation of Computer
Programs&lt;/a&gt;, which uses Lisp as its primary programming language.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ll first go over the history of what editors I&amp;#8217;ve used over the years.&lt;/p&gt;

&lt;p&gt;When I first started using Linux back in high school, it was quite hard for
me to wean myself away the Windows Way of doing things.  &amp;#8220;You mean I have to
learn how to use the terminal?!?&amp;#8221;  I did get away with just using &lt;strong&gt;gedit&lt;/strong&gt;,
which was a comfortable text editor to use when I was in front of a Linux
machine with GNOME installed.&lt;/p&gt;

&lt;p&gt;However, I eventually had to work on remote machines with no GUI at all, which
means I had to learn some sort of terminal text editor for me to be somewhat
productive.  Thus, the next easiest thing for me to use at the time was
&lt;strong&gt;nano&lt;/strong&gt;.  It was very simple to adapt to, in the sense that I didn&amp;#8217;t have
to memorize a ton of different key combinations, nor did I have to figure out
how to insert text into a document.  I just typed stuff and it worked as
I expected it to.&lt;/p&gt;

&lt;p&gt;I forgot exactly when I started using &lt;strong&gt;vi(m)&lt;/strong&gt;, but I realized that I had to
learn it, since it&amp;#8217;s usually included by default on all UNIX systems.  It took
me a while to get used to the way vi(m) worked (&lt;em&gt;especially&lt;/em&gt; alternating
between command mode and insert mode), and it took me a while to also figure
out that it was The Better Way compared to &lt;strong&gt;nano&lt;/strong&gt;.  I became a bit more
fluent in it, and was able to edit files with a lot more ease than with
&lt;strong&gt;nano&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;So anyway, I switched between &lt;strong&gt;nvi&lt;/strong&gt; and &lt;strong&gt;vim&lt;/strong&gt; for a while because I thought
BSD vi was a lot better, it didn&amp;#8217;t impose any stupid syntax highlighting rules
which didn&amp;#8217;t work half the time in vim, etc.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;ve now just learned that &lt;strong&gt;emacs&lt;/strong&gt; handles syntax highlighting &lt;em&gt;way&lt;/em&gt; better
than vi(m).  Plus, it&amp;#8217;s easy to extend!  It&amp;#8217;s all in Lisp; I figure this is
a good way to sink my teeth into Lisp along with learning Lisp through SICP.&lt;/p&gt;

&lt;p&gt;SICP is a great text by the way - I&amp;#8217;m not through the first chapter quite yet,
but the problem sets seem to be both challenging and deep in its concepts
that it&amp;#8217;s trying to convey.  It&amp;#8217;s taking me a while to really understand how
Lisp works; there&amp;#8217;s a lot of &amp;#8220;unlearning&amp;#8221; I have to do in order to really
grok Lisp.&lt;/p&gt;

&lt;p&gt;Anyway, that&amp;#8217;s really about it.  I heavily recommend SICP to anyone else
who&amp;#8217;s wanting a great introduction to programming and computer science.&lt;/p&gt;

&lt;p&gt;I&amp;#8217;m not quite sure yet if I would recommend emacs over vi(m) quite yet -
I don&amp;#8217;t want to incite a religious war. :)&lt;/p&gt;
</content>
  </entry>
  
</feed>

