<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="../assets/xml/rss.xsl" media="all"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Piecing things together (Posts about infrastructure)</title><link>https://wjoel.com/</link><description></description><atom:link href="https://wjoel.com/categories/infrastructure.xml" rel="self" type="application/rss+xml"></atom:link><language>en</language><lastBuildDate>Sun, 15 Oct 2023 18:25:37 GMT</lastBuildDate><generator>Nikola (getnikola.com)</generator><docs>http://blogs.law.harvard.edu/tech/rss</docs><item><title>Mesos container log forwarding with Filebeat</title><link>https://wjoel.com/posts/mesos-container-log-forwarding-with-filebeat.html</link><dc:creator>Joel Wilsson</dc:creator><description>&lt;div&gt;&lt;div id="outline-container-orgf9c5b70" class="outline-2"&gt;
&lt;h2 id="orgf9c5b70"&gt;The next level&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-orgf9c5b70"&gt;
&lt;p&gt;
In the previous post we managed to forward container logs to journald, but
we could have done the same thing and much more if we could have forwarded
the logs to &lt;code&gt;systemd-cat&lt;/code&gt; instead. We wouldn't have had to write any code
at all if that was possible.
&lt;/p&gt;

&lt;p&gt;
So we're going to make that possible by backporting an upcoming "external"
container logger, being developed for the next release of Mesos, as a module
compiled for the currently stable release. That's version 1.0.1 at the time
of writing.
&lt;/p&gt;

&lt;p&gt;
Then we'll use this module to set up log forwarding from Mesos containers
to &lt;a href="https://www.graylog.org/"&gt;Graylog&lt;/a&gt; using &lt;a href="https://www.elastic.co/products/beats/filebeat"&gt;Filebeat&lt;/a&gt; 1.3 and include additional fields from the
Mesos executor's environment.
&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;

&lt;div id="outline-container-org71d77a8" class="outline-2"&gt;
&lt;h2 id="org71d77a8"&gt;Mesos and external container loggers&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org71d77a8"&gt;
&lt;p&gt;
Apache Mesos has had support for a &lt;a href="https://mesos.apache.org/documentation/latest/logging/"&gt;LogrotateContainerLogger&lt;/a&gt; since version
0.27, but if you look at what that container logger you'll find that all it
does is receive input from standard input and standard error, counts the
number of bytes received, and writes to the &lt;code&gt;stdout&lt;/code&gt; and &lt;code&gt;stdout&lt;/code&gt; files in
the sandbox directory.
&lt;/p&gt;

&lt;p&gt;
It calls &lt;code&gt;logrotate&lt;/code&gt; once a configurable number of bytes has been received.
This logic is implemented by &lt;code&gt;mesos-logrotate-logger&lt;/code&gt; which is a
stand-alone program. Why do we need a separate module to feed logs to
this specific external program?
&lt;/p&gt;

&lt;p&gt;
&lt;a href="https://issues.apache.org/jira/browse/MESOS-6003"&gt;MESOS-6003&lt;/a&gt; was created to add a logging module for logging to any
external program. Thanks to the hard work of &lt;a href="https://github.com/wrouesnel"&gt;Will Rouesnel&lt;/a&gt;, shepherded by
&lt;a href="https://github.com/kaysoky"&gt;Joseph Wu&lt;/a&gt;, this is almost completed.
&lt;/p&gt;

&lt;p&gt;
What if we can't wait for the next release of Mesos? Maybe we're stuck on
1.0.1 for a while for reasons beyond our control, but we'd love to use Filebeat
for log forwarding. Unfortunately we can't, because the recommended setup
&lt;a href="https://github.com/elastic/beats/issues/2084"&gt;doesn't work&lt;/a&gt;.
&lt;/p&gt;

&lt;p&gt;
Even if it did we'd still be missing out on important context, like
what the Marathon app ID and the Mesos task ID are. Maybe there's a specific
version of the Marathon app which is having issues. It would be nice if we
could find all log messages from that application and version with a simple
search.
&lt;/p&gt;

&lt;p&gt;
We'll make that possible by backporting the external container logging module
to Mesos 1.0.1 and setting it up to use a small wrapper around Filebeat to
create configuration which includes the task's environment variables
and forwards the log messages to Graylog. It will also work if you are using
Logstash.
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://wjoel.com/posts/mesos-container-log-forwarding-with-filebeat.html"&gt;Read more…&lt;/a&gt; (5 min remaining to read)&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;</description><category>containers</category><category>filebeat</category><category>infrastructure</category><category>logging</category><category>mesos</category><guid>https://wjoel.com/posts/mesos-container-log-forwarding-with-filebeat.html</guid><pubDate>Sun, 02 Oct 2016 08:17:00 GMT</pubDate></item><item><title>A Mesos logging module for journald</title><link>https://wjoel.com/posts/mesos-logging-module-for-journald.html</link><dc:creator>Joel Wilsson</dc:creator><description>&lt;div id="outline-container-org15e03bb" class="outline-2"&gt;
&lt;h2 id="org15e03bb"&gt;A short introduction to Mesos&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-org15e03bb"&gt;
&lt;p&gt;
We're going to send logs from Mesos containers to systemd-journald by
writing a container logging module in C++. You can skip this section
if you already know what Mesos is.
&lt;/p&gt;

&lt;p&gt;
&lt;a href="https://mesos.apache.org/"&gt;Apache Mesos&lt;/a&gt; describes itself as a distributed systems kernel, which is appropriate
in a lot of ways. For some it may sound a bit intimidating and complicated, and I
think that's a bit unfortunate, because it can be explained very simply without
losing too much.
&lt;/p&gt;

&lt;p&gt;
Mesos offers resources in a cluster. Resources types include CPU cores, memory,
disk space, network ports, GPUs, etc. Let's say I'm a developer and I want to run
my application on the cluster. I get an offer from Mesos of 4 CPU cores,
8 GBs of memory, 40 GBs of disk space and a range of ports from 10000-20000.
&lt;/p&gt;

&lt;p&gt;
I don't need all of it, and reply that accept 1 CPU core, 2 GBs of memory,
200 MBs of disk space and one port, port 10000, and I want to fetch
&lt;a href="https://wjoel.com/foo-standalone.jar"&gt;https://wjoel.com/foo-standalone.jar&lt;/a&gt; (a self-contained "fat JAR" with no
external dependencies) and run it with the command
&lt;code&gt;java -jar foo-standalone.jar&lt;/code&gt;. Mesos will create a container
using &lt;a href="https://en.wikipedia.org/wiki/Cgroups"&gt;cgroups&lt;/a&gt; (if running on Linux) to enforce limits based on the resource
constraints I accepted. The container is also known as a sandbox, and we
get to play in it as long as we stay within the resource limits.
&lt;/p&gt;

&lt;p&gt;
Developers typically don't want to bother with resource offers
from Mesos. Programs that respond to resource offers from Mesos are called
frameworks. One such framework is Mesosphere's &lt;a href="https://github.com/mesosphere/marathon"&gt;Marathon&lt;/a&gt;, and its application
&lt;a href="https://mesosphere.github.io/marathon/docs/application-basics.html"&gt;specifications&lt;/a&gt; are essentially lists of resources and the command to run.
Marathon can also ensure that applications are restarted if they die for
any reason, do rolling updates, and many other useful things that developers
like to have.
&lt;/p&gt;

&lt;p&gt;
You may have noticed that I told Mesos to run my JAR file using
Java, but didn't specify that I wanted Java to be downloaded. Hence, my
application will only run if Mesos decides to run it somewhere where Java is
already installed.
&lt;/p&gt;

&lt;p&gt;
I could create a Docker image which includes &lt;code&gt;foo-standalone.jar&lt;/code&gt;, Java, and
any other dependencies I might need. Mesos can run Docker containers as well,
either on its own or using by Docker for isolation. Alternatively, I could
have included an additional URL in my reply, containing the location of an
archive with a full Java installation and used that instead, all from within
the container.
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://wjoel.com/posts/mesos-logging-module-for-journald.html"&gt;Read more…&lt;/a&gt; (4 min remaining to read)&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;</description><category>containers</category><category>infrastructure</category><category>logging</category><category>mesos</category><guid>https://wjoel.com/posts/mesos-logging-module-for-journald.html</guid><pubDate>Thu, 29 Sep 2016 19:23:00 GMT</pubDate></item><item><title>Creating Jenkins pipelines with Ansible, part 2</title><link>https://wjoel.com/posts/ansible-jenkins-pipeline-part-2.html</link><dc:creator>Joel Wilsson</dc:creator><description>&lt;div id="outline-container-orga6bcbf8" class="outline-2"&gt;
&lt;h2 id="orga6bcbf8"&gt;The job-dsl and Pipeline plugins&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-orga6bcbf8"&gt;
&lt;p&gt;
This is a continuation of the &lt;a href="https://wjoel.com/posts/ansible-jenkins-pipeline-part-1.html"&gt;previous post&lt;/a&gt;.
For each project there are only two things we want to do.
&lt;/p&gt;

&lt;ul class="org-ul"&gt;
&lt;li&gt;Check out the source code.&lt;/li&gt;
&lt;li&gt;Run the pipeline in the Jenkinsfile at the root of the repository.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;
This can be accomplished with the job-dsl plugin. It takes a definition
of Jenkins jobs we want, and creates or updates them, as necessary.
Somewhat confusingly, job-dsl itself needs to be run from a Jenkins job,
known as a seed job.
&lt;/p&gt;

&lt;p&gt;
The &lt;b&gt;only&lt;/b&gt; reason for this job to exist is so that job-dsl can run,
and &lt;b&gt;every&lt;/b&gt; other job should be created with job-dsl. Yes, it is a bit
mind bending, but if you don't think of it as a job but as a script which
you run from Jenkins it gets easier.
&lt;/p&gt;

&lt;p&gt;
In our case, every other job will look the same. They'll all be Pipeline
jobs which run a Jenkinsfile after checking out a git repository from the
same git host.
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="o"&gt;{%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;jenkins_git_repositories&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%}&lt;/span&gt;
&lt;span class="n"&gt;pipelineJob&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'{{ repository }}'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;definition&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;cpsScm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;scm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;git&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;remote&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'{{ jenkins_git_user }}@{{ jenkins_git_host }}:'&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;
&lt;span class="w"&gt;                &lt;/span&gt;&lt;span class="s1"&gt;'{{ jenkins_git_path }}/{{ repository }}.git'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;branch&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'master'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;scriptPath&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Jenkinsfile'&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;{%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;endfor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;%}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;a href="https://wjoel.com/posts/ansible-jenkins-pipeline-part-2.html"&gt;Read more…&lt;/a&gt; (5 min remaining to read)&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;</description><category>ansible</category><category>infrastructure</category><category>jenkins</category><guid>https://wjoel.com/posts/ansible-jenkins-pipeline-part-2.html</guid><pubDate>Wed, 10 Aug 2016 19:52:00 GMT</pubDate></item><item><title>Creating Jenkins pipelines with Ansible, part 1</title><link>https://wjoel.com/posts/ansible-jenkins-pipeline-part-1.html</link><dc:creator>Joel Wilsson</dc:creator><description>&lt;div id="outline-container-orgdc2700c" class="outline-2"&gt;
&lt;h2 id="orgdc2700c"&gt;Introduction&lt;/h2&gt;
&lt;div class="outline-text-2" id="text-orgdc2700c"&gt;
&lt;p&gt;
Infrastructure as code, continuous integration (CI),
continuous delivery (CD), and version control
(also known as source control management, or SCM) are good things.
In this post and the next we'll automate the deployment of a
system to do CI/CD in what I consider a proper way, where the definition of
your build and deployment pipelines live alongside your code in
git repositories on some server you have SSH access to.
&lt;/p&gt;

&lt;p&gt;
We'll use &lt;a href="https://jenkins.io"&gt;Jenkins&lt;/a&gt; for CI/CD and &lt;a href="https://www.ansible.com/"&gt;Ansible&lt;/a&gt; to install it.
Jenkins has been around for more
than a decade, created before anyone had ever uttered the word "devops".
Since it's old, Jenkins has a lot of features, most of them provided as plugins.
The core itself isn't bad, and is stable and relatively free from bugs
because it has been in use by a lot of people for such a long time.
All those years
have created a graveyard of plugins, though, yet some plugins are essential if
you want to use Jenkins "properly". Want a timestamp for your builds? There's
a plugin for that. Actually, there's more than one plugin for that.
&lt;/p&gt;

&lt;p&gt;
Jenkins comes from a time when people thought it
was great to have easy to use web interfaces to configure their build systems.
The web interface gets in the
way of infrastructure as code, where configuration is version controlled
and changed by editing text files, not by clicking buttons.
&lt;/p&gt;

&lt;p&gt;
Pipeline is a "new" feature of Jenkins 2.0, but it is based on a plugin
which used to be known as Workflow. Using Pipeline we can describe
how to test, build and deploy our project using text. That description is
typically saved in a file named Jenkinsfile. We'll also use the job-dsl plugin
to create the Pipeline jobs, but everything else will be done with shell
scripts and kept as simple as possible.
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://wjoel.com/posts/ansible-jenkins-pipeline-part-1.html"&gt;Read more…&lt;/a&gt; (4 min remaining to read)&lt;/p&gt;&lt;/div&gt;&lt;/div&gt;</description><category>ansible</category><category>infrastructure</category><category>jenkins</category><guid>https://wjoel.com/posts/ansible-jenkins-pipeline-part-1.html</guid><pubDate>Sat, 06 Aug 2016 18:49:00 GMT</pubDate></item></channel></rss>