<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom"><title>Gerard Braad's blog</title><link href="https://blog.gbraad.nl/" rel="alternate"/><link href="https://blog.gbraad.nl/feeds/all.atom.xml" rel="self"/><id>https://blog.gbraad.nl/</id><updated>2016-11-08T00:00:00+08:00</updated><entry><title>Presentation: Atomic, FUDCon Phnom Penh</title><link href="https://blog.gbraad.nl/presentation-atomic-fudcon-phnom-penh.html" rel="alternate"/><published>2016-11-08T00:00:00+08:00</published><updated>2016-11-08T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-11-08:/presentation-atomic-fudcon-phnom-penh.html</id><summary type="html">&lt;p&gt;This is the presentation as given at the FUDCon Phnom Penh. In short it explains
what Project Atomic is, how to use Atomic Host, and some advanced use-cases;
deployment of a composed application, and customization of the Atomic images.
The presentation relied heavily on showing usage in the form of …&lt;/p&gt;</summary><content type="html">&lt;p&gt;This is the presentation as given at the FUDCon Phnom Penh. In short it explains
what Project Atomic is, how to use Atomic Host, and some advanced use-cases;
deployment of a composed application, and customization of the Atomic images.
The presentation relied heavily on showing usage in the form of a demo,
therefore please see the links to the other relevant articles on this blog.&lt;/p&gt;
&lt;h2&gt;Presentation&lt;/h2&gt;
&lt;iframe src="//gbraad.gitlab.io/presentation-fudcon-phnompenh/" width="1024" height="768"&gt;
  &lt;p&gt;Your browser does not support iframes.&lt;/p&gt;
&lt;/iframe&gt;

&lt;h2&gt;Feedback&lt;/h2&gt;
&lt;p&gt;If you have any suggestion, please discuss below or send me an email.&lt;/p&gt;</content><category term="Containers"/><category term="atomic"/><category term="ostree"/><category term="containers"/></entry><entry><title>Setup OpenStack Keystone for testing purposes</title><link href="https://blog.gbraad.nl/setup-openstack-keystone-for-testing-purposes.html" rel="alternate"/><published>2016-10-27T00:00:00+08:00</published><updated>2016-10-27T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-10-27:/setup-openstack-keystone-for-testing-purposes.html</id><summary type="html">&lt;p&gt;OpenStack can be seen as a set of projects which combined into a configuration
can deliver a management solution for different use-cases. However, several of
these projects can also exist on their own to provide a certain functionality,
such as Keystone, Ironic, etc. Some of these I will describe in …&lt;/p&gt;</summary><content type="html">&lt;p&gt;OpenStack can be seen as a set of projects which combined into a configuration
can deliver a management solution for different use-cases. However, several of
these projects can also exist on their own to provide a certain functionality,
such as Keystone, Ironic, etc. Some of these I will describe in articles on this
blog, but let's start with one of the most important one's that deal with
Authenticatioin, namely Keystone.&lt;/p&gt;
&lt;h2&gt;Keystone&lt;/h2&gt;
&lt;p&gt;Keystone is one of the core projects of OpenStack and is responsible for
providing Identity. It offersauthentication, authorization and service
discovery mechanisms via HTTP. Especially this last property, offering the API
to be accessed by HTTP as a ReSTful interface offers a lot of opportunities for
re-use. More about the Keystone project can be found on the
&lt;a href="http://docs.openstack.org/developer/keystone/"&gt;project homepage&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Containerized&lt;/h2&gt;
&lt;p&gt;To simplify the deployment process, I have containerized Keystone. The image can
be found at &lt;a href="https://gitlab.com/gbraad/openstack-keystone"&gt;GitLab&lt;/a&gt; and the
&lt;a href="https://hub.docker.com/r/gbraad/openstack-keystone/"&gt;Docker Registry&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;&lt;code&gt;Dockerfile&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;The image is based on a standard CentOS 7 cloud image. To install Keystone, I
used the packaged version from the &lt;a href="//www.rdoproject.org"&gt;RDO project&lt;/a&gt;. After
an update, it install the repository information pointing to mitaka, and then
it install the Keystone service, some useful utils to use with OpenStack and
the SELinux configuration files.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;RUN yum update -y &amp;amp;&amp;amp; \
    yum install -y centos-release-openstack-mitaka &amp;amp;&amp;amp; \
    yum install -y openstack-keystone openstack-utils openstack-selinux &amp;amp;&amp;amp; \
    yum clean all
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After this we expose the ports that Keystone uses for interaction.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;EXPOSE 5000
EXPOSE 35357
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As the &lt;code&gt;CMD&lt;/code&gt; it will run a simple initialization script. It takes care to setup
an admin token and use a MySQL connection. It then starts &lt;code&gt;keystone-manage&lt;/code&gt; to
provision the database with the schemas. And finally, it will use &lt;code&gt;keystone-all&lt;/code&gt;
to run the services on the exposed ports.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="nv"&gt;ADMIN_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;ADMIN_TOKEN&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;openssl&lt;span class="w"&gt; &lt;/span&gt;rand&lt;span class="w"&gt; &lt;/span&gt;-hex&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
openstack-config&lt;span class="w"&gt; &lt;/span&gt;--set&lt;span class="w"&gt; &lt;/span&gt;/etc/keystone/keystone.conf&lt;span class="w"&gt; &lt;/span&gt;DEFAULT&lt;span class="w"&gt; &lt;/span&gt;admin_token&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ADMIN_TOKEN&lt;/span&gt;
openstack-config&lt;span class="w"&gt; &lt;/span&gt;--set&lt;span class="w"&gt; &lt;/span&gt;/etc/keystone/keystone.conf&lt;span class="w"&gt; &lt;/span&gt;DEFAULT&lt;span class="w"&gt; &lt;/span&gt;use_stderr&lt;span class="w"&gt; &lt;/span&gt;True
openstack-config&lt;span class="w"&gt; &lt;/span&gt;--set&lt;span class="w"&gt; &lt;/span&gt;/etc/keystone/keystone.conf&lt;span class="w"&gt; &lt;/span&gt;database&lt;span class="w"&gt; &lt;/span&gt;connection&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONNECTION&lt;/span&gt;&lt;span class="p"&gt;-mysql://keystone:&lt;/span&gt;&lt;span class="nv"&gt;password&lt;/span&gt;&lt;span class="p"&gt;@dbhost/keystone&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
su&lt;span class="w"&gt; &lt;/span&gt;keystone&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;/bin/sh&lt;span class="w"&gt; &lt;/span&gt;-c&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;keystone-manage db_sync&amp;quot;&lt;/span&gt;

/usr/bin/keystone-all
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the rest of the article I will describe how to use this image to setup the
test environment. The first component you will need to use Keystone is the
database to store the credentials and other relevant information.&lt;/p&gt;
&lt;h3&gt;Setup database&lt;/h3&gt;
&lt;p&gt;As you saw in the &lt;code&gt;Dockerfile&lt;/code&gt;, we specified a MySQL connection. To make it
easy to deploy, we will also be using a container for this database server. I
prefer to use MariaDB, as this is also what normally would come with CentOS. For
this article I will be using MariaDB version 10.1.&lt;/p&gt;
&lt;p&gt;To start the container perform the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;keystone-database&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;MYSQL_ROOT_PASSWORD&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;secrete&lt;span class="w"&gt; &lt;/span&gt;mariadb:10.1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will pull the container and start a named instance as &lt;code&gt;keystone-database&lt;/code&gt;.
The &lt;code&gt;root&lt;/code&gt; password to configure the database is set using the environment
variable to &lt;code&gt;secrete&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Using this password and container name, we will create a database for Keystone
and grant priviliges:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;keystone-database&lt;span class="w"&gt; &lt;/span&gt;mysql&lt;span class="w"&gt; &lt;/span&gt;-psecrete&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;create database keystone;&amp;quot;&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;keystone-database&lt;span class="w"&gt; &lt;/span&gt;mysql&lt;span class="w"&gt; &lt;/span&gt;-psecrete&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;GRANT ALL ON keystone.* TO &amp;#39;keystone&amp;#39;@&amp;#39;%&amp;#39; IDENTIFIED BY &amp;#39;password&amp;#39;;&amp;quot;&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;keystone-database&lt;span class="w"&gt; &lt;/span&gt;mysql&lt;span class="w"&gt; &lt;/span&gt;-psecrete&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;GRANT ALL ON keystone.* TO &amp;#39;keystone&amp;#39;@&amp;#39;localhost&amp;#39; IDENTIFIED BY &amp;#39;password&amp;#39;;&amp;quot;&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;keystone-database&lt;span class="w"&gt; &lt;/span&gt;mysql&lt;span class="w"&gt; &lt;/span&gt;-psecrete&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;flush privileges;&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After this, all the setting for the database are done and we can just leave it
running without further configuration.&lt;/p&gt;
&lt;h3&gt;Generate token for API usage&lt;/h3&gt;
&lt;p&gt;Just like MariaDB, Keystone can use a token to perform the initial configuration.
It is preferred to make this admin token something that is random and not easily
guessable. A random token can be generated for instance with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;openssl&lt;span class="w"&gt; &lt;/span&gt;rand&lt;span class="w"&gt; &lt;/span&gt;-hex&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the rest of the article, this token will be used.&lt;/p&gt;
&lt;h3&gt;Start container&lt;/h3&gt;
&lt;p&gt;After the database has been setup, and a token has been decided, we can start
the Keystone services. &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;--link&lt;span class="w"&gt; &lt;/span&gt;keystone-database:dbhost&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;ADMIN_TOKEN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;5000&lt;/span&gt;:5000&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;keystone-server&lt;span class="w"&gt; &lt;/span&gt;gbraad/openstack-keystone:mitaka
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will link the keystone container to the database container. If all goes
well, the service will now be available on the exposed ports. The container
instance will be identified by the name &lt;code&gt;keystone-server&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;As mentioned earlier, when the container gets started, it will provision the
database with the schemas that are needed.&lt;/p&gt;
&lt;p&gt;In the following segment we will configure Keystone. &lt;/p&gt;
&lt;h3&gt;Create service entry&lt;/h3&gt;
&lt;p&gt;To finalize the Keystone configuration, we will insert the service and endpoints
for the Identity service.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;keystone-server&lt;span class="w"&gt; &lt;/span&gt;keystone&lt;span class="w"&gt; &lt;/span&gt;--os-token&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--os-endpoint&lt;span class="w"&gt; &lt;/span&gt;http://localhost:35357/v2.0/&lt;span class="w"&gt; &lt;/span&gt;service-create&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="o"&gt;=&lt;/span&gt;keystone&lt;span class="w"&gt; &lt;/span&gt;--type&lt;span class="o"&gt;=&lt;/span&gt;identity&lt;span class="w"&gt; &lt;/span&gt;--description&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Keystone Identity Service&amp;quot;&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;keystone-server&lt;span class="w"&gt; &lt;/span&gt;keystone&lt;span class="w"&gt; &lt;/span&gt;--os-token&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--os-endpoint&lt;span class="w"&gt; &lt;/span&gt;http://localhost:35357/v2.0/&lt;span class="w"&gt; &lt;/span&gt;endpoint-create&lt;span class="w"&gt; &lt;/span&gt;--service&lt;span class="w"&gt; &lt;/span&gt;keystone&lt;span class="w"&gt; &lt;/span&gt;--publicurl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http://localhost:5000/v2.0&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--adminurl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http://localhost:35357/v2.0&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--internalurl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;http://localhost:5000/v2.0&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note that these command are performed inside the keystone container.&lt;/p&gt;
&lt;h3&gt;Create admin user&lt;/h3&gt;
&lt;p&gt;To allow access to keystone without using the admin token, we will need to
create a user. The following commands will create a user named &lt;code&gt;admin&lt;/code&gt; with
the password &lt;code&gt;password&lt;/code&gt; and add this to a tenant called &lt;code&gt;admin&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;keystone-server&lt;span class="w"&gt; &lt;/span&gt;keystone&lt;span class="w"&gt; &lt;/span&gt;--os-token&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--os-endpoint&lt;span class="w"&gt; &lt;/span&gt;http://localhost:35357/v2.0/&lt;span class="w"&gt; &lt;/span&gt;user-create&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;admin&lt;span class="w"&gt; &lt;/span&gt;--pass&lt;span class="w"&gt; &lt;/span&gt;password
$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;keystone-server&lt;span class="w"&gt; &lt;/span&gt;keystone&lt;span class="w"&gt; &lt;/span&gt;--os-token&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--os-endpoint&lt;span class="w"&gt; &lt;/span&gt;http://localhost:35357/v2.0/&lt;span class="w"&gt; &lt;/span&gt;role-create&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;admin
$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;keystone-server&lt;span class="w"&gt; &lt;/span&gt;keystone&lt;span class="w"&gt; &lt;/span&gt;--os-token&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--os-endpoint&lt;span class="w"&gt; &lt;/span&gt;http://localhost:35357/v2.0/&lt;span class="w"&gt; &lt;/span&gt;tenant-create&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;admin
$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;keystone-server&lt;span class="w"&gt; &lt;/span&gt;keystone&lt;span class="w"&gt; &lt;/span&gt;--os-token&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$TOKEN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--os-endpoint&lt;span class="w"&gt; &lt;/span&gt;http://localhost:35357/v2.0/&lt;span class="w"&gt; &lt;/span&gt;user-role-add&lt;span class="w"&gt; &lt;/span&gt;--user&lt;span class="w"&gt; &lt;/span&gt;admin&lt;span class="w"&gt; &lt;/span&gt;--role&lt;span class="w"&gt; &lt;/span&gt;admin&lt;span class="w"&gt; &lt;/span&gt;--tenant&lt;span class="w"&gt; &lt;/span&gt;admin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;More detailed setups are possible, and for this I will refer you to the Keystone
documentation.&lt;/p&gt;
&lt;h3&gt;Getting a user token&lt;/h3&gt;
&lt;p&gt;To verify Keystone works, we will retrieve a token. First you need to know the
IP address that has been assigned to your container.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;inspect&lt;span class="w"&gt; &lt;/span&gt;--format&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;{{.NetworkSettings.IPAddress}}&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;keystone-server
&lt;span class="m"&gt;172&lt;/span&gt;.17.0.6
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This can be helpful to communicate between different containers on the same
Docker network. You could create a new container, or pull my
&lt;a href="https://gitlab.com/gbraad/openstack-client"&gt;OpenStack client&lt;/a&gt; container.&lt;/p&gt;
&lt;h4&gt;Using the OpenStack client&lt;/h4&gt;
&lt;p&gt;Using the OpenStack client you can retrieve a token using the following
configuration:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;keystonerc&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;OS_IDENTITY_API_VERSION=3
OS_AUTH_URL=http://172.17.0.6:5000/v3
OS_USERNAME=admin
OS_PASSWORD=password
OS_PROJECT_NAME=admin
OS_USER_DOMAIN_NAME=Default
OS_PROJECT_DOMAIN_NAME=Default
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When you use the following commands you will be given a token:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;keystonerc
$&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;token&lt;span class="w"&gt; &lt;/span&gt;issue
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Using cURL&lt;/h4&gt;
&lt;p&gt;Since Keystone uses a HTTP interface, you can also retrieve the token using the
cURL command. When using the &lt;code&gt;-i&lt;/code&gt; parameter, cURL will return all the headers
from the response. This will include the &lt;code&gt;X-SUBJECT-TOKEN&lt;/code&gt; we want.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;-H&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;Content-Type: application/json&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;
&lt;span class="s1"&gt;{ &amp;quot;auth&amp;quot;: {&lt;/span&gt;
&lt;span class="s1"&gt;    &amp;quot;identity&amp;quot;: {&lt;/span&gt;
&lt;span class="s1"&gt;      &amp;quot;methods&amp;quot;: [&amp;quot;password&amp;quot;],&lt;/span&gt;
&lt;span class="s1"&gt;      &amp;quot;password&amp;quot;: {&lt;/span&gt;
&lt;span class="s1"&gt;        &amp;quot;user&amp;quot;: {&lt;/span&gt;
&lt;span class="s1"&gt;          &amp;quot;name&amp;quot;: &amp;quot;admin&amp;quot;,&lt;/span&gt;
&lt;span class="s1"&gt;          &amp;quot;domain&amp;quot;: { &amp;quot;name&amp;quot;: &amp;quot;Default&amp;quot; },&lt;/span&gt;
&lt;span class="s1"&gt;          &amp;quot;password&amp;quot;: &amp;quot;password&amp;quot;&lt;/span&gt;
&lt;span class="s1"&gt;        }&lt;/span&gt;
&lt;span class="s1"&gt;      }&lt;/span&gt;
&lt;span class="s1"&gt;    },&lt;/span&gt;
&lt;span class="s1"&gt;    &amp;quot;scope&amp;quot;: {&lt;/span&gt;
&lt;span class="s1"&gt;      &amp;quot;project&amp;quot;: {&lt;/span&gt;
&lt;span class="s1"&gt;        &amp;quot;name&amp;quot;: &amp;quot;admin&amp;quot;,&lt;/span&gt;
&lt;span class="s1"&gt;        &amp;quot;domain&amp;quot;: { &amp;quot;name&amp;quot;: &amp;quot;Default&amp;quot; }&lt;/span&gt;
&lt;span class="s1"&gt;      }&lt;/span&gt;
&lt;span class="s1"&gt;    }&lt;/span&gt;
&lt;span class="s1"&gt;  }&lt;/span&gt;
&lt;span class="s1"&gt;}&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;http://172.17.0.6:5000/v3/auth/tokens
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;A response will follow. You need to set the value of &lt;code&gt;X-Subject-Token&lt;/code&gt; to
&lt;code&gt;OS_TOKEN&lt;/code&gt;, or use in cURL as the &lt;code&gt;X-AUTH-TOKEN&lt;/code&gt; header. More about this can
be found in the Keystone documentation: &lt;a href="http://docs.openstack.org/developer/keystone/api_curl_examples.html"&gt;API Examples using cURL&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;How this was used for development&lt;/h3&gt;
&lt;p&gt;For the &lt;a href="https://github.com/projectatomic/commissaire"&gt;Commissaire project&lt;/a&gt; I
added Keystone functionality using two methods; using
&lt;a href="https://github.com/projectatomic/commissaire-http/issues/21"&gt;password&lt;/a&gt; and
&lt;a href="https://github.com/projectatomic/commissaire-http/issues/28"&gt;token&lt;/a&gt;. The above
described container was used to allow easy deployment and testing.&lt;/p&gt;
&lt;p&gt;As I decided not to introduce unnecessary libraries as dependencies, the
communication from Commissaire happens over the HTTP ReST interface. To
authenticate using a basic authorization, using the password method, we only
need to construct a simple JSON object:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;{ &amp;quot;auth&amp;quot;: {
    &amp;quot;identity&amp;quot;: {
      &amp;quot;methods&amp;quot;: [&amp;quot;password&amp;quot;],
      &amp;quot;password&amp;quot;: {
        &amp;quot;user&amp;quot;: {
          &amp;quot;name&amp;quot;: &amp;quot;admin&amp;quot;,
          &amp;quot;domain&amp;quot;: { &amp;quot;name&amp;quot;: &amp;quot;Default&amp;quot; },
          &amp;quot;password&amp;quot;: &amp;quot;password&amp;quot;
        }
      }
    },
    &amp;quot;scope&amp;quot;: {
      &amp;quot;project&amp;quot;: {
        &amp;quot;name&amp;quot;: &amp;quot;admin&amp;quot;,
        &amp;quot;domain&amp;quot;: { &amp;quot;name&amp;quot;: &amp;quot;Default&amp;quot; }
      }
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In code we described this with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;        headers = {&amp;#39;Content-Type&amp;#39;: &amp;#39;application/json&amp;#39;}
        body = {&amp;#39;auth&amp;#39;: {&amp;#39;identity&amp;#39;: {}}}
        ident = body[&amp;#39;auth&amp;#39;][&amp;#39;identity&amp;#39;]

        ident[&amp;#39;methods&amp;#39;] = [&amp;#39;password&amp;#39;]
        ident[&amp;#39;password&amp;#39;] = {&amp;#39;user&amp;#39;: {
            &amp;#39;name&amp;#39;: user,
            &amp;#39;password&amp;#39;: passwd,
            &amp;#39;domain&amp;#39;: {&amp;#39;name&amp;#39;: self.domain}}}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To perform the authentication, we send a request:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;        response = requests.post(
            self.url,
            data=json.dumps(body),
            headers=headers)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;to the endpoint exposed at: &lt;code&gt;http://172.17.0.6:5000/v3/auth/tokens&lt;/code&gt;. When the
response includes the header &lt;code&gt;X-Subject-Token&lt;/code&gt; the authentication succeeded,
else we failed and send a 403 as status code.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;X-Subject-Token&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;response&lt;/span&gt;.&lt;span class="nv"&gt;headers&lt;/span&gt;:
&lt;span class="w"&gt;            &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;True&lt;/span&gt;

&lt;span class="w"&gt;        &lt;/span&gt;#&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;Forbid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;by&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;default&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;False&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The Implementation for authentication using a token is quite similar, instead
we will take the &lt;code&gt;X-Auth-Token&lt;/code&gt; from the request we received  and verify this
against Keystone using the following request:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;{
    &amp;quot;auth&amp;quot;: {
        &amp;quot;identity&amp;quot;: {
            &amp;quot;methods&amp;quot;: [
                &amp;quot;token&amp;quot;
            ],
            &amp;quot;token&amp;quot;: {
                &amp;quot;id&amp;quot;: &amp;quot;faa166abf235430e81c9fa12ad248533&amp;quot;
            }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Just like in the previous example, the endpoint is:
&lt;code&gt;http://172.17.0.6:5000/v3/auth/tokens&lt;/code&gt;. If the authentication is succesful
the response will contain the &lt;code&gt;X-Subject-Token&lt;/code&gt; header.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Keystone is powerful service to provide authentication for your infrastructure.
As you can see from this example, using a containerized (composed) environment,
it is easy to get a basic setup running. And using the ReST API it is also 
very simple to handle authentication outside of your own application. In future
articles more advanced scenarios will be given.&lt;/p&gt;
&lt;p&gt;At the moment, password authentication using Keystone and Commissaire is
possible and hopefully soon we will also have integrated the token based
authentication.&lt;/p&gt;
&lt;p&gt;If you have comments or suggestions, please leave them below or consider sending
a message to me on &lt;a href="http://twitter.com/gbraad"&gt;Twitter&lt;/a&gt;: @gbraad.&lt;/p&gt;</content><category term="OpenStack"/><category term="openstack"/><category term="keystone"/><category term="docker"/><category term="containers"/><category term="authentication"/></entry><entry><title>Flatpak; the road to CI/CD for desktop applications?</title><link href="https://blog.gbraad.nl/flatpak-the-road-to-cicd-for-desktop-applications.html" rel="alternate"/><published>2016-10-22T00:00:00+08:00</published><updated>2016-10-22T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-10-22:/flatpak-the-road-to-cicd-for-desktop-applications.html</id><summary type="html">&lt;p&gt;In this presentation I will introduce Flatpak and how it changes the software
distribution model for Linux. In short it will explain the negatives of using
packages, how Flatpak solves this, and how to create your own applications and
distribute them for use with Flatpak. This presentation was given at …&lt;/p&gt;</summary><content type="html">&lt;p&gt;In this presentation I will introduce Flatpak and how it changes the software
distribution model for Linux. In short it will explain the negatives of using
packages, how Flatpak solves this, and how to create your own applications and
distribute them for use with Flatpak. This presentation was given at the &lt;a href="//www.bjgug.org/events/gnome-3-22-party/"&gt;GNOME
3.22 release party&lt;/a&gt;, organized by the
Beijing GNOME User Group.&lt;/p&gt;
&lt;h2&gt;Presentation&lt;/h2&gt;
&lt;iframe src="//gbraad.gitlab.io/presentation-bjgug-flatpak/slides.html" width="1024" height="768"&gt;
  &lt;p&gt;Your browser does not support iframes.&lt;/p&gt;
&lt;/iframe&gt;

&lt;h2&gt;Feedback&lt;/h2&gt;
&lt;p&gt;If you have any suggestion, please discuss below or send me an email.&lt;/p&gt;
&lt;p&gt;Note: the original presentation can be found at: &lt;a href="https://gitlab.com/gbraad/presentation-bjgug-flatpak"&gt;GitLab: BJGUG Flatpak&lt;/a&gt;.
This is based on an earlier presentation about &lt;a href="/blog/software-distribution-for-a-new-era.html"&gt;Software Dsitribution for a new era&lt;/a&gt;&lt;/p&gt;</content><category term="CI / CD"/><category term="flatpak"/><category term="ostree"/><category term="gnome"/></entry><entry><title>"Task management and Personal Kanban: how I use GitLab Issues"</title><link href="https://blog.gbraad.nl/task-management-and-personal-kanban-how-i-use-gitlab-issues.html" rel="alternate"/><published>2016-10-09T00:00:00+08:00</published><updated>2016-10-09T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-10-09:/task-management-and-personal-kanban-how-i-use-gitlab-issues.html</id><summary type="html">&lt;p&gt;Working on personal and work-related tasks can be overwhelming, especially when
you lose sight of what actually needs to be done. What makes it more difficult
is that you are constantly interrupted. I have tried many different things, and
apps, but nothing really worked. Do not try to make your …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Working on personal and work-related tasks can be overwhelming, especially when
you lose sight of what actually needs to be done. What makes it more difficult
is that you are constantly interrupted. I have tried many different things, and
apps, but nothing really worked. Do not try to make your process of working to
fit the tool, but make sure you have a tool that fits the way you work.&lt;/p&gt;
&lt;h2&gt;Kanban&lt;/h2&gt;
&lt;p&gt;Kanban (or 看板) originated as a scheduling system to improving manufacturing
efficiency. The word literally means signboard in Japanese, and in Chinese it
can be read as 'Look board'. It emphasizes on visualization of tasks that need
to be done, are being worked on, and have finished.&lt;/p&gt;
&lt;p&gt;In software development you often see people use Trello or other kanban-like
boards to visualize work that is on their 'backlog', 'doing', 'done'. Although
these tools work quite well, it did not fit my workflow or where I do most of
my work.&lt;/p&gt;
&lt;h2&gt;GitLab issues&lt;/h2&gt;
&lt;p&gt;Quite recently, GitLab released a version of their sourcecode management tool
that allows to visualize issues on a board. And I started to evaluate it, as
GitLab is part of my workflow in general. I host many of my private
repositories there for backup purposes, use it to publish my resume with the
CI runners, etc. And I can tell you, that the issue boards was exactly what I
was looking for.&lt;/p&gt;
&lt;p&gt;Below is a screenshot of what it looks like:
&lt;img alt="" src="//cdn.gbraad.nl/images/blog/kanban-gitlab.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Note: the image shown here is from an early iteration and still has too
many items in 'doing'. This actually made me realize where my time was spent.&lt;/p&gt;
&lt;h3&gt;How to set-up&lt;/h3&gt;
&lt;p&gt;All you need to do is create a private repository. In my case, I created a
'personal' project. All the issues you create, will only be visible to you.
After you have done this, you can create a board from the Issues. Just start
with the defaults first and customize it along the way... This made it
work best for me.&lt;/p&gt;
&lt;h3&gt;Workflow&lt;/h3&gt;
&lt;p&gt;When you create an issue, just tag it accordingly. I use it to group
tasks for different topics or things I work on. Now when you open the
board, you will see your issue is on the 'backlog'. From there you can
drag it to a swimlane. I have several that helps to organize tasks,
such as 'blog' and 'urgent'. When you drag, it will assign the label
to the issue according to the name of the swimlane.&lt;/p&gt;
&lt;h3&gt;Offline use?&lt;/h3&gt;
&lt;p&gt;There is, however, a small issue with the setup. It only allows me to work
online. In the end I noticed this is actually not a big problem.&lt;/p&gt;
&lt;h2&gt;Single-tasking&lt;/h2&gt;
&lt;p&gt;Kanban helps you to visualize your tasks at hand, but it still requires 
discipline to actually make it work. Therefore, you need to understand that
'multi-tasking' does not exist! I recently read 'Singletasking: Get More
Done-One Thing at a Time', and it help me a lot to realize that I was
going the right direction with my personal kanban. However, I was still
trying to do too many things at once. Mostly due to interruptions. This
led me to appreciate the offline problem I have.&lt;/p&gt;
&lt;p&gt;If I have an interruption, or some other urgent matter, I would first
record it on my phone in a file called 'reminder', which lives in the same
personal repository. This file is synced using git, so it travels with me
and it allows me to use it as a general reminder/todo record keeping,
and decide later what to do with the entries.&lt;/p&gt;
&lt;h2&gt;Tools&lt;/h2&gt;
&lt;p&gt;On my desktop I only need to use a browser to keep track of tasks
being worked on. Even the reminder file can be opened from here.&lt;/p&gt;
&lt;p&gt;On my phone I use the following apps:
&lt;img alt="" src="//cdn.gbraad.nl/images/blog/kanban-apps-on-phone.jpg"&gt;&lt;/p&gt;
&lt;p&gt;Writeily Pro, SGit, and Labcoat. Using SGit I sync several important
repositories to my phone, such as my 'personal', 'knowledge-base',
and some private specific projects for training/teaching, etc.&lt;/p&gt;
&lt;p&gt;Writeily Pro opens the SGit repos folder as it's document folder:
&lt;code&gt;/sdcard/Android/data/me.sheimi.sgit/files/repo&lt;/code&gt; in my case. Writely's
usage was not without problems for me. Especially when dealing with
some 'larger' files.&lt;/p&gt;
&lt;p&gt;Using Labcoat I am able to create and change basic information of an
issue, such as closing it and adding comments. But I usually do all
interactions online now, and else use my offline reminder file. I
only use Labcoat only in rare cases. Probably also because the tool
misses some of the more wanted features as labelling and tagging
issues.&lt;/p&gt;
&lt;p&gt;I haven't found a good way to use the command line yet. I did start
with a small &lt;a href="https://gitlab.com/gbraad/gitlab-client"&gt;client&lt;/a&gt;, but so
far it only reads and doesn't filter anything. Hope I can allocate more
time to deal with this at some point. At the moment I do not really
need it.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Task management is not something you learn by just reading a book or
keeping a todo-list inside an application. It really is a discipline.
And it depends on you, how you will deal with it. This article does not
go into a lot of detail on my own process, as this is a personal quest.
Just experiment and see what works best for you.&lt;/p&gt;
&lt;p&gt;I have read several books, and in the section 'More information' below,
you can find these resources. It involves in keeping your tasks
&lt;em&gt;visualized&lt;/em&gt; and &lt;em&gt;limiting&lt;/em&gt; the amount you work on at the same time. It
is up to you how to balance private and work.&lt;/p&gt;
&lt;p&gt;I also learned that to keep things organized, I started to keep a public
&lt;a href="https://gitlab.com/gbraad/knowledge-base/"&gt;knowledge base&lt;/a&gt;. This way I
am better able to keep knowledge available and at hand. Before, I would
keep it in an earlier version of a reminder file and this cluttered
everything and actually not made me remember things. I am still working
on writing things done in a more general way, written towards possible
others who will read it. But this is a work-in-progress, as part of my
personal continous improvement.&lt;/p&gt;
&lt;p&gt;I will certainly refine my process over time, and might even change it
again completely. As long as it works for me. I'll keep you updated and
might write related articles about time management and knowledge
techniques I have used over the years. One I still love the most is
mind-mapping... and I have applied it to organizing work before. It is
a great way to organize thoughts.&lt;/p&gt;
&lt;h2&gt;More information&lt;/h2&gt;
&lt;p&gt;I suggest to read more about personal kanban.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.personalkanban.com/pk/personal-kanban-101/"&gt;Personal Kanban 101&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Knowledge-base: &lt;a href="https://gitlab.com/gbraad/knowledge-base/blob/master/books/personal-kanban.md"&gt;Personal kanban&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Knowledge-base: &lt;a href="https://gitlab.com/gbraad/knowledge-base/blob/master/books/singletasking.md"&gt;Singletasking&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://hguemar.fedorapeople.org/personal-kanban/"&gt;Presentation&lt;/a&gt; of a friend's experience with Personal Kanban&lt;/li&gt;
&lt;/ul&gt;</content><category term="Misc"/><category term="continuous improvement"/><category term="management"/><category term="knowledge"/><category term="kanban"/><category term="gitlab"/></entry><entry><title>Dear recruiter</title><link href="https://blog.gbraad.nl/dear-recruiter.html" rel="alternate"/><published>2016-10-08T00:00:00+08:00</published><updated>2016-10-08T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-10-08:/dear-recruiter.html</id><summary type="html">&lt;p&gt;As an engineer I love to work and talk about software and software development.
Looking for a new opportunity is not an easy task. There is a story behind every
choice people make, and in this article I will explain my vision and situation.
This is certainly not an employer …&lt;/p&gt;</summary><content type="html">&lt;p&gt;As an engineer I love to work and talk about software and software development.
Looking for a new opportunity is not an easy task. There is a story behind every
choice people make, and in this article I will explain my vision and situation.
This is certainly not an employer review, but rather a reflection on past and
maybe future choices.&lt;/p&gt;
&lt;h2&gt;Job-hopping&lt;/h2&gt;
&lt;p&gt;Just too often I have to explain why my resume looks like I have been hopping
between jobs. Part of this is true and the other has a story behind it. I love a
challenge and also do not mind when a company hires me for my knowledge, but I
also prefer to be employed for a longer period and be able to work on the stuff
that matters. Work needs to be meaningful and satisfying... &lt;/p&gt;
&lt;h2&gt;Netherlands&lt;/h2&gt;
&lt;p&gt;In the Netherlands I worked for an employer which provides consultancy. This
often involved on-site work. These clients, and consultants, like to work as
close as possible, as if you are employed by them. However, they keep the
flexibility to end a contract when the project you are assigned on ends or has
no budget. These assignments are usually short-term as they need hands or
knowledge to finish it. If you know 'the Mythical Man-month', you know that
introducing engineers late in a project often does not work as expected.
Although, wome of my assignments have dealt with longer term solutions, such as
software rewrite, knowledge hiring, etc. I loved my work as certainly felt very
appreciated.&lt;/p&gt;
&lt;h2&gt;China&lt;/h2&gt;
&lt;p&gt;After this, due to circumstances and a 'lost bet' with my wife, we moved to
China. Being employed in a foreign country involves sometimes with work of an
imperfect nature.&lt;/p&gt;
&lt;h3&gt;Projects&lt;/h3&gt;
&lt;p&gt;One of those is of having project based assignments, but unlike before I would
be directly hired by the employer. Which means that the contract will not last
longer than the allotted budget for the project. These project are challenging
as they often deal with a new technology or a changed environment for the
employer. I have been on at least two projects here in China and have learned a
lot from dealing with an inter-cultural environment and how to assist with
adopting a more 'Western' approach to management (agile methodology).
Re-assignments were discussed, but often involved a big change in work or other
less than ideal propositions. If in that case there is no fit anymore, it is
best to move on. This choice would be in the best of interest of both the
employer and employee.&lt;/p&gt;
&lt;h3&gt;Startups&lt;/h3&gt;
&lt;p&gt;The other situation is when dealing with startups. Startups often require an
employee that is able to be all-round, as this allows to keep a minimal
headcount. Again, the work is mostly challenging and benefits a lot from
multi-disciplined engineers. I have worked for several startups, and most of
the cases it is very enjoyable work. The experience has led to some good
success stories, although some of them have also disappeared. The work includes
a lot of uncertainty. While some startups might look like they have matured,
they can still hide unpleasant surprises when dealing with management or
decision-making. This can have an affect on how the atmosphere will be at work.
It can be a happy place one-day... and a poisonous one the other day.&lt;/p&gt;
&lt;h2&gt;Recruiters&lt;/h2&gt;
&lt;p&gt;I understand an assessment of a possible match is difficult. There are probably
many applicants, long resumes to wade through. Automated system exist to deal
with analysing a 'match' based on the resume provided. And often, theese
systems fail to understand what people really meant to say or provide a picture
of the working history. And I understand this is somehow needed.&lt;/p&gt;
&lt;p&gt;In my situation, the resume often happens to be sent to the local Chinese
branch. And here, my resume or application, disappears into an abyss; often the
recruiter does not reach out. &lt;/p&gt;
&lt;h2&gt;Recommendations&lt;/h2&gt;
&lt;p&gt;If you want to be employed into a group you like to work with, get noticed.
Work with them, and show your passion. This is why I work on Open Source
projects. It is what I like most, as it involves technology, but also an
essential soft skill (or perhaps a thick skin). Hopefully this can lead to a
recommendation. As this is still the best way to get hired.&lt;/p&gt;
&lt;h2&gt;What I want&lt;/h2&gt;
&lt;p&gt;At the moment I am looking for a new opportunity. As you have read, I am a
software engineer, but have worked in several different roles related to it.
Multi-disciplinary and professional. Knows a lot about Linux, Open Source and
China. If you want to know more about me, please have a look at:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gbraad.nl/resume"&gt;Resume&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://linkedin.com/in/gbraad"&gt;LinkedIn&lt;/a&gt; and the recommendations given.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gbraad.nl"&gt;Homepage&lt;/a&gt; and my &lt;a href="http://gbraad.nl/blog/"&gt;blog&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What I want is a great and challenging environment. This means that work is
meaningful and provides satisfaction. It should provide growth potential and
understand that people need to focus on continuous improvement. Agile taught
me one thing, we’re never really good enough. And third, and most important is
trust. Trust in colleagues, fairness and respect... without trust you can not
have a great work environment. But you also need trust that people dare to
admit when they are not experts at something yet, but you allow them to develop
themselves.&lt;/p&gt;
&lt;p&gt;Hope to hear from you. If you have a comment, please do not hesitate and leave
one below.&lt;/p&gt;</content><category term="About me"/><category term="recruitment"/><category term="employment"/><category term="about me"/><category term="startups"/><category term="projects"/><category term="choices"/></entry><entry><title>"Replace scripts with Ansible: package installation"</title><link href="https://blog.gbraad.nl/replace-scripts-with-ansible-package-installation.html" rel="alternate"/><published>2016-10-03T00:00:00+08:00</published><updated>2016-10-03T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-10-03:/replace-scripts-with-ansible-package-installation.html</id><summary type="html">&lt;p&gt;Installing and configuring software on one machine, for instance your own
developer's environment, is an 'easy' task. But how about your team? Or
production? Everything is documented and you only probably install some of the
components manually, or better, you automate this using a set of shell scripts.
The environment …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Installing and configuring software on one machine, for instance your own
developer's environment, is an 'easy' task. But how about your team? Or
production? Everything is documented and you only probably install some of the
components manually, or better, you automate this using a set of shell scripts.
The environment is now reproducible. Everything is fine.&lt;/p&gt;
&lt;p&gt;Running a set of scripts is not a bad idea, but often what lacks is the
maintenance on them or just the magic contained in them. I do not
have to make the case for general configuration management,
'configuration as code' or even #DevOps I hope? In this article I will show why
I use Ansible for almost all my scripts. Even small one of.&lt;/p&gt;
&lt;h2&gt;Environment&lt;/h2&gt;
&lt;p&gt;Although I have a preference for the operating system and distribution I use, I
have to deal with many different versions and variants. On my workstation I
prefer to use Fedora, but at work we deploy on CentOS. Some of my colleagues
tend to prefer Ubuntu (latest), and customers are stuck on LTS releases. A very
common situation. In one week, I had to deal with: Alpine, CentOS, Fedora,
Ubuntu, (Open)SUSE, Debian, Windows, etc. This is of course an extreme case.&lt;/p&gt;
&lt;p&gt;You would prefer to use a single environment for both development and
production. When the production environment is fixed, the solution is easier.
You will likely use a tool like Vagrant to stand up an environment, or some
other virtualization soltuion. But what if you develop for an environment where
both Ubuntu and CentOS are an option? In my case this happens a lot because of
work for OpenStack, or just general Linux tool development.&lt;/p&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;p&gt;Below I will discuss a small example of dealing with package installation. Let's
consider you have to use Ubuntu and Fedora. This means that you already have to
deal with two different package managers, oh wait, three; &lt;code&gt;apt&lt;/code&gt; on Ubuntu and
&lt;code&gt;yum&lt;/code&gt; or &lt;code&gt;dnf&lt;/code&gt; on Fedora.&lt;/p&gt;
&lt;h3&gt;Bash script&lt;/h3&gt;
&lt;p&gt;As a crude solution, you could do the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="nv"&gt;APTPKGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;git tmux zsh mc stow python-psutil&amp;quot;&lt;/span&gt;
&lt;span class="nv"&gt;RPMPKGS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;git tmux zsh mc stow python-psutil&amp;quot;&lt;/span&gt;

&lt;span class="c1"&gt;# Crude multi-os installation option&lt;/span&gt;
&lt;span class="k"&gt;if&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;-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/usr/bin/apt-get&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;apt-get&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$APTPKGS&lt;/span&gt;
&lt;span class="k"&gt;elif&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;-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/usr/bin/dnf&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;dnf&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$RPMPKGS&lt;/span&gt;
&lt;span class="k"&gt;elif&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;-x&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/usr/bin/yum&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="k"&gt;then&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;yum&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$RPMPKGS&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This basically checks if a certain executable is available, and will use that
with a defined list of packages to install. If both &lt;code&gt;yum&lt;/code&gt; and &lt;code&gt;dnf&lt;/code&gt; is
installed, it will in this case use &lt;code&gt;dnf&lt;/code&gt; as it resolves first. This is likely
what you want, but it is hidden logic. But what if you have installed &lt;code&gt;yum&lt;/code&gt; on
Ubuntu? Also, because of this case, &lt;code&gt;apt-get&lt;/code&gt; will resolve first. But again,
this is undocumented in this script. But this knowledge should not be needed.&lt;/p&gt;
&lt;p&gt;Note: in this case, the packages are the same for both platforms, but this is
not a guarantee. Therefore I use a variable for this.&lt;/p&gt;
&lt;h3&gt;Ansible playbook&lt;/h3&gt;
&lt;p&gt;Ansible solves this problem by offering a general &lt;code&gt;package&lt;/code&gt; module. You can use
&lt;code&gt;yum&lt;/code&gt; and &lt;code&gt;apt&lt;/code&gt; specific options, but I prefer to use &lt;code&gt;package&lt;/code&gt; instead. Below 
is a playbook that has the same behaviour as the above mentioned script:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Install list of required packages&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;package&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;name={{ item }} state=installed&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;become&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;yes&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;become_method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;sudo&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;with_items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;git&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;tmux&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;zsh&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;stow&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;python-psutil&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;mc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Because of the task name, it becomes clear what the intention is of the commands
that follow. In this case, this will use the package manager based on the OS
Family that Ansible will find. This means we do not need to have the knowledge
of what to pick first. There is however a problem. What if the packages have
different names?&lt;/p&gt;
&lt;h3&gt;Conditionals&lt;/h3&gt;
&lt;p&gt;For this Ansible offers conditionals which you can use with &lt;code&gt;when&lt;/code&gt;. Below is
an example that will install the development tools on Ubuntu or Fedora, based
on the &lt;code&gt;ansible_distribution&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;#!/usr/bin/env ansible-playbook&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;hosts&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;localhost&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;#remote_user: root&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;become_method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;sudo&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;tasks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Install Git&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;package&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;name=git state=installed&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;become&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;yes&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;install the &amp;#39;Development tools&amp;#39; package group&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;package&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;name=&amp;quot;@Development tools&amp;quot; state=present&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;when&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ansible_distribution == &amp;#39;CentOS&amp;#39; or&lt;/span&gt;
&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ansible_distribution == &amp;#39;Red Hat Enterprise Linux&amp;#39; or&lt;/span&gt;
&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ansible_distribution == &amp;#39;Fedora&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;become&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;yes&lt;/span&gt;

&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p p-Indicator"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;Install the &amp;#39;build-essential&amp;#39; meta package&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;package&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;name=&amp;quot;build-essential&amp;quot; state=present&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;when&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ansible_distribution == &amp;#39;Debian&amp;#39; or&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;ansible_distribution == &amp;#39;Ubuntu&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nt"&gt;become&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="l l-Scalar l-Scalar-Plain"&gt;yes&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can also use &lt;code&gt;ansible_os_family == "RedHat"&lt;/code&gt; to be less specific about the
distribution you are on.&lt;/p&gt;
&lt;h3&gt;Include&lt;/h3&gt;
&lt;p&gt;You can combine conditionals with almost anything in Ansible, for instance to
include or not another playbook. Below is a simple solution of this when you
want to split the install instructions into separate files.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;-&lt;/span&gt; include: install-centos.yml
  when: ansible_distribution == &amp;quot;CentOS&amp;quot;

&lt;span class="k"&gt;-&lt;/span&gt; include: install-ubuntu.yml
  when: ansible_distribution == &amp;quot;Ubuntu&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;With Ansible it is possible to create complex instructions that can be more
maintainable than when using just scripts. Of course, just using Ansible will
not act as a silver bullet. But because a playbook is more readable, the process
of refactoring is easier.&lt;/p&gt;
&lt;p&gt;In future articles I will talk about other aspects where the move to Ansible
helped me. However, the bootstrap process remains... I wish there was a way to
&lt;a href="https://github.com/gbraad/automate-everything"&gt;Automate everything&lt;/a&gt; ;-)&lt;/p&gt;
&lt;p&gt;Hope this article has been helpful to you. If so, please consider tweeting about
it. Or leave a comment if you have suggestions...&lt;/p&gt;</content><category term="DevOps"/><category term="deployment"/><category term="configuration"/><category term="ansible"/><category term="devops"/></entry><entry><title>Giving to your favourite content creators</title><link href="https://blog.gbraad.nl/giving-to-your-favourite-content-creators.html" rel="alternate"/><published>2016-09-29T00:00:00+08:00</published><updated>2016-09-29T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-09-29:/giving-to-your-favourite-content-creators.html</id><summary type="html">&lt;p&gt;It is hard to remember the time I really sat down in front of the TV, waiting
for a programme to show up, and really enjoy it. Mostly it was accompanied with
plenty of interruptions. It might have been Star Trek on the public channels
that I enjoyed the most …&lt;/p&gt;</summary><content type="html">&lt;p&gt;It is hard to remember the time I really sat down in front of the TV, waiting
for a programme to show up, and really enjoy it. Mostly it was accompanied with
plenty of interruptions. It might have been Star Trek on the public channels
that I enjoyed the most. But even Discovery Channel had many interruptions,
some &lt;a href="https://www.youtube.com/watch?v=at_f98qOGY0"&gt;were funny&lt;/a&gt;, or just
&lt;a href="https://www.youtube.com/watch?v=DP96w7DoH9U"&gt;slightly annoying&lt;/a&gt;, especially
when you have the TV on as background sound. With the advent of YouTube, and
other User Generated Content websites, or even streaming websites, it is almost
unimaginable there used to be a time without being able to watch your favorites.&lt;/p&gt;
&lt;p&gt;Some might not know, but I help(ed) a lot with music remixing and artwork. Too
bad I do not have the time now, but this is so much fun. Content creation is
probably the best people can do as it gives a lot of satisfaction. I consider
the teaching I do as a form of content creation. I produced a lot of documents,
notes, etc, and people enjoy the way I explain stuff. Even writing code is a
creative process:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;foreach step in I.take():
  step.move(DIRECTION_TOMORROW)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But remixing music, or posting artwork online, does not pay the bills. Unless
of course you are Tiesto, etc. And asking for a donation has not been my thing,
although I have received some. I am very thankful for this!&lt;/p&gt;
&lt;p&gt;And this is why I give to the content creators that create good stuff. I love
the cardgame Magic: the Gathering, and especially some of the youtube channels
for this. Patreon is a great idea... and if people create content you read
often, consider giving back. Even 1 USD is already good way to show you care.
It can buy someone a cup of coffee... and the more people who do, the easier
someone can take some time off to create the content you love!&lt;/p&gt;
&lt;p&gt;One of the projects I really want to work on again is &lt;a href="https://github.com/gbraad/gauth"&gt;Gauth&lt;/a&gt;.
it has been in a neglect, but I can't reserve enough time to do a rewrite...
I ask you, consider to become a Patron of my work and hopefully I can
improve by &lt;a href="https://www.patreon.com/posts/future-of-gauth-6738130"&gt;giving Gauth a new future&lt;/a&gt;,
allow me to create more content on my blog... and maybe in the future even more.&lt;/p&gt;
&lt;p&gt;&lt;a href="ps://www.patreon.com/gbraad"&gt;&lt;img alt="Support my work on Patreon" src="https://www.patreon.com/images/patreon_navigation_logo_mini_orange.png"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;And thank you to all who have donated in the past!&lt;/p&gt;</content><category term="About me"/><category term="donation"/><category term="patreon"/><category term="contributing"/><category term="content creation"/></entry><entry><title>Run an example application on OpenShift</title><link href="https://blog.gbraad.nl/run-an-example-application-on-openshift.html" rel="alternate"/><published>2016-09-29T00:00:00+08:00</published><updated>2016-09-29T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-09-29:/run-an-example-application-on-openshift.html</id><summary type="html">&lt;p&gt;In a &lt;a href="./deploy-an-openshift-test-cluster.html" title="Deploy an OpenShift test cluster"&gt;previous article&lt;/a&gt; I have written
on how easy it is to stand up a test environment of OpenShift. In this article
I will describe an example application from the sourcecode to the created image
and how this gets deployed. The steps are explained using manual steps, and how …&lt;/p&gt;</summary><content type="html">&lt;p&gt;In a &lt;a href="./deploy-an-openshift-test-cluster.html" title="Deploy an OpenShift test cluster"&gt;previous article&lt;/a&gt; I have written
on how easy it is to stand up a test environment of OpenShift. In this article
I will describe an example application from the sourcecode to the created image
and how this gets deployed. The steps are explained using manual steps, and how
OpenShift does it all automated. You will notice, at no point do you have to
write a &lt;code&gt;Dockerfile&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Preparation&lt;/h2&gt;
&lt;p&gt;For this article it is not necessary to have a working test environment, however
it does make things clearer. I would suggest you to use OpenShift Origin v1.3 on
CentOS 7. Although my previous article showed how to get it up and running on
Fedora 24, I experienced an issue with deployment not succeeding&lt;a href="https://lists.openshift.redhat.com/openshift-archives/users/2016-September/msg00198.html" title="Deployment of ruby-ex times out"&gt;*&lt;/a&gt;.
The steps in the deployment article can be performed by replacing &lt;code&gt;dnf&lt;/code&gt; with
&lt;code&gt;yum&lt;/code&gt;. &lt;/p&gt;
&lt;h2&gt;Description of the example&lt;/h2&gt;
&lt;p&gt;The OpenShift project publishes several test applications on GitHub, of which
one is a very simple Ruby applica8080. Please, have a look at: &lt;a href="https://github.com/openshift/ruby-ex" title="Ruby example"&gt;http://github.com/openshift/ruby-ex&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;You will see it consists of four files:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Gemfile&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Gemfile.local&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;config.ru&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;README.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The application itself is only described in &lt;code&gt;config.ru&lt;/code&gt; and the needed dependencies
are in &lt;code&gt;Gemfile&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Dependencies&lt;/h3&gt;
&lt;p&gt;To make the application work, we first need:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;gem&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;bundler
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will install &lt;code&gt;bundler&lt;/code&gt; that can install dependencies as described in the
&lt;code&gt;Gemfile&lt;/code&gt;. This file describes:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;source &amp;#39;https://rubygems.org&amp;#39;
gem &amp;#39;rack&amp;#39;
gem &amp;#39;puma&amp;#39;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The first line says &lt;code&gt;source&lt;/code&gt; which points to a gem repository, and each line
starting wih &lt;code&gt;gem&lt;/code&gt; are bundled packages containing libraries for use in your
project. To install all of the required gems (dependencies) from the specified
sources:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;bundle&lt;span class="w"&gt; &lt;/span&gt;install
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The file &lt;code&gt;Gemfile.lock&lt;/code&gt; is a snapshot of the Gemfile and is used internally.&lt;/p&gt;
&lt;h3&gt;config.ru&lt;/h3&gt;
&lt;p&gt;The application is specified in the file called &lt;code&gt;config.ru&lt;/code&gt;. If you open the
file you will see it contains route mappings, lines starting  with &lt;code&gt;map&lt;/code&gt;, for
three urls:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/health&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/lobster&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;&lt;code&gt;/health&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;This is a commonly used to provide a simple health-check for applications that
are automatically deployed. It allows to quickly test if the application got
deployed. In projects I worked on, we also did quick dependency checks, such as
a configuration file exists, or another needed endpoint is available. In this
application it will respond with a HTTP status code 200 and returns &lt;code&gt;1&lt;/code&gt; as
value.&lt;/p&gt;
&lt;h4&gt;&lt;code&gt;/lobster&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;This is a test provided by rack. It shows an ASCII-art lobster. By adding a
variable to the URL querystring &lt;code&gt;?flip=left&lt;/code&gt; the direction can be changed.&lt;/p&gt;
&lt;h4&gt;&lt;code&gt;/&lt;/code&gt;&lt;/h4&gt;
&lt;p&gt;This is the mapping to a bare route. It shows a greeting message on how to use
the application using OpenShift to trigger automated builds.&lt;/p&gt;
&lt;h3&gt;Rackup&lt;/h3&gt;
&lt;p&gt;Rack is an interface for using Ruby and Ruby frameworks with webservers. It
provides an application called &lt;code&gt;rackup&lt;/code&gt; to start the application:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;bundle&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;exec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;rackup&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;config.ru
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Using this command the webserver will bind to port 8080, according to the
description in the &lt;code&gt;config.ru&lt;/code&gt; file. To see what the mappings do, open:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://localhost:8080/health" title="Example health-check"&gt;http://localhost:8080/health&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://localhost:8080/lobster" title="Example lobster"&gt;http://localhost:8080/lobster&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://localhost:8080/" title="Example bare"&gt;http://localhost:8080/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Use the example with OpenShift&lt;/h2&gt;
&lt;p&gt;Deploying an application on OpenShift from source is very simple. A single
command can do this. First have a look&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;oc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;openshift&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;centos7&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="nl"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/[&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;]/&lt;/span&gt;&lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But before we do, I will explain what this command does. Oversimplified
OpenShift does two things:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Build&lt;/li&gt;
&lt;li&gt;Deploy&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Note: If you want to perform the command, go ahead. Please fork the repository
and change the &lt;code&gt;[username]&lt;/code&gt; in this command.&lt;/p&gt;
&lt;h3&gt;Build: source to image&lt;/h3&gt;
&lt;p&gt;OpenShift runs container images which are in the Docker format. It will run
the &lt;code&gt;CMD&lt;/code&gt; instruction for this. So, how does OpenShift know what to run?
Convention. Most frameworks have a standard way of doing things, and this is
as you noticed also the case with the Ruby example. The creation of the image
happens with a tool called source-to-image (S2I).&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/openshift/source-to-image/" title="Source-to-image"&gt;Source-to-Image (S2I)&lt;/a&gt; is a toolkit and workflow for building
reproducible Docker images from source code. It uses a base image, and will
layer the application on top, configures the runn command, which then results in
a containter image for use.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;s2i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/[&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;]/&lt;/span&gt;&lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;openshift&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;centos7&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;base image&lt;/h4&gt;
&lt;p&gt;The base image here is &lt;a href="https://hub.docker.com/r/openshift/ruby-20-centos7" title="Ruby base image"&gt;openshift/ruby-20-centos7&lt;/a&gt;. The source
of this image can be found at the following GitHub repository: &lt;a href="https://github.com/sclorg/s2i-ruby-container/" title="Ruby base image source"&gt;s2i-ruby-container&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you look at the &lt;code&gt;Dockerfile&lt;/code&gt; &lt;a href="https://github.com/sclorg/s2i-ruby-container/blob/master/2.0/Dockerfile" title="Ruby base Dockerfile"&gt;source&lt;/a&gt;, you will see
&lt;a href="https://www.softwarecollections.org/en/" title="Software Collections"&gt;Software Collections&lt;/a&gt; is used to install a specific Ruby version.
In this case version 2.0. Software collections solves one of the biggest
complaints of using CentOS (or RHEL) as a basis as part of your delivery. It
allows you to use multiple versions of software on the same system, without
affecting system-wide installed packages.&lt;/p&gt;
&lt;p&gt;The image also describes a label &lt;code&gt;io.openshift.expose-services="8080:http"&lt;/code&gt;
which inidcate that the application on port 8080 will be exposed as HTTP
traffic. This also means the container does not need root privileges as the port
assignment is above 1024. The application itself will be installed into the
folder: &lt;code&gt;/opt/app-root/src&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Running this container can be done with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;:8080&lt;span class="w"&gt; &lt;/span&gt;ruby-ex
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;[1] Puma starting in cluster mode...
[1] &lt;span class="gs"&gt;* Version 3.4.0 (ruby 2.0.0-p645), codename: Owl Bowl Brawl&lt;/span&gt;
&lt;span class="gs"&gt;[1] *&lt;/span&gt; Min threads: 0, max threads: 16
[1] &lt;span class="gs"&gt;* Environment: production&lt;/span&gt;
&lt;span class="gs"&gt;[1] *&lt;/span&gt; Process workers: 1
[1] &lt;span class="gs"&gt;* Phased restart available&lt;/span&gt;
&lt;span class="gs"&gt;[1] *&lt;/span&gt; Listening on tcp://0.0.0.0:8080
[1] Use Ctrl-C to stop
[1] - Worker 0 (pid: 32) booted, phase: 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Open the links as previously stated will yield the same results.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;http://localhost:8080/health
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The build process can be as simple as a copy for static content, to compiling
Java or C/C++ code.  For the purpose of this article I will not explain more
about the S2I process, but this will certainly be explained in future articles.&lt;/p&gt;
&lt;h2&gt;New application&lt;/h2&gt;
&lt;p&gt;If we now look at the previous command again:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;oc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;openshift&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;centos7&lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="nl"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/[&lt;/span&gt;&lt;span class="n"&gt;username&lt;/span&gt;&lt;span class="o"&gt;]/&lt;/span&gt;&lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ex&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;you can clear see the structure. The first element &lt;code&gt;openshift/ruby-20-centos7&lt;/code&gt;
describes the S2I container image for Ruby as hosted at the Docker hub. The
second part is the source code path pointing to a git repository.&lt;/p&gt;
&lt;p&gt;Please try the command now... OpenShift will create containers for each of the
stages used: &lt;code&gt;build&lt;/code&gt;, &lt;code&gt;deploy&lt;/code&gt; and the final running container. You can check
the containers using the command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;pod
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;NAME               READY     STATUS         RESTARTS   AGE
ruby-ex-1-build    0/1       Completed      0          1m
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Build stage&lt;/h3&gt;
&lt;p&gt;If you create this new application, a new container named &lt;code&gt;ruby-ex-1-build&lt;/code&gt;.
What happened is that the Source-to-image container got pulled which uses the 
base image and layers the source code on top.&lt;/p&gt;
&lt;p&gt;To see what happened, as with the previous command, you can see the build
configuration:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;bc/ruby-ex
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;Cloning&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;https://github.com/gbraad/ruby-ex&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="k"&gt;Commit&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f63d076b602441ebd65fd0749c5c58ea4bafaf90&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;Merge&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pull&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;#2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mfojtik&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;add&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;puma&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nl"&gt;Author&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Michal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Fojtik&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;mi&lt;/span&gt;&lt;span class="nv"&gt;@mifo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sk&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;Thu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Jun&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;47&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;53&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2016&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;0200&lt;/span&gt;
&lt;span class="c1"&gt;---&amp;gt; Installing application source ...&lt;/span&gt;
&lt;span class="c1"&gt;---&amp;gt; Building your Ruby application from source ...&lt;/span&gt;
&lt;span class="c1"&gt;---&amp;gt; Running &amp;#39;bundle install --deployment&amp;#39; ...&lt;/span&gt;
&lt;span class="n"&gt;Fetching&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gem&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;rubygems&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="p"&gt;...............&lt;/span&gt;
&lt;span class="n"&gt;Installing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;puma&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;3.4.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Installing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;rack&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.6.4&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;Using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bundler&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;1.3.5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Cannot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;write&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;changed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;lockfile&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;frozen&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;Your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;bundle&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;complete&lt;/span&gt;&lt;span class="err"&gt;!&lt;/span&gt;
&lt;span class="n"&gt;It&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;was&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;installed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;into&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bundle&lt;/span&gt;
&lt;span class="c1"&gt;---&amp;gt; Cleaning up unused ruby gems ...&lt;/span&gt;
&lt;span class="n"&gt;Pushing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nc"&gt;image&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;172.30.108.129&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5000&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;myproject&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;ruby&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nl"&gt;ex&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;latest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;Pushed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;complete&lt;/span&gt;
&lt;span class="n"&gt;Pushed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;complete&lt;/span&gt;
&lt;span class="n"&gt;Pushed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;49&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;complete&lt;/span&gt;
&lt;span class="n"&gt;Pushed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;complete&lt;/span&gt;
&lt;span class="n"&gt;Pushed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;complete&lt;/span&gt;
&lt;span class="n"&gt;Pushed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;complete&lt;/span&gt;
&lt;span class="n"&gt;Pushed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;61&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;complete&lt;/span&gt;
&lt;span class="n"&gt;Pushed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;71&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;complete&lt;/span&gt;
&lt;span class="n"&gt;Pushed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;complete&lt;/span&gt;
&lt;span class="n"&gt;Pushed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;99&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;complete&lt;/span&gt;
&lt;span class="n"&gt;Pushed&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;layers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;complete&lt;/span&gt;
&lt;span class="n"&gt;Push&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;successful&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The difference is that the resulting image will be placed in the &lt;code&gt;myproject&lt;/code&gt;
namespace, and pushed to the local repository.&lt;/p&gt;
&lt;h3&gt;Deployment stage&lt;/h3&gt;
&lt;p&gt;After the image has been composed, OpenShift will run the container image on the
scheduled node. What happens here can be checked with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;pod&lt;span class="w"&gt;                                                                                                                                                          &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;NAME              READY     STATUS      RESTARTS   AGE
ruby-ex-1-an801   1/1       Running     0          26s
ruby-ex-1-build   0/1       Completed   0          1m
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This means that the build succeeded, the image got deployed and now runs in the
a container identified with &lt;code&gt;ruby-ex-1-an801&lt;/code&gt;. Note: The container
&lt;code&gt;ruby-ex-1-deploy&lt;/code&gt; is not shown here as only the logs are of importance.&lt;/p&gt;
&lt;p&gt;The deployment configuration logs can be shown with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;logs&lt;span class="w"&gt; &lt;/span&gt;dc/ruby-ex
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;[1] Puma starting in cluster mode...
[1] &lt;span class="gs"&gt;* Version 3.4.0 (ruby 2.0.0-p645), codename: Owl Bowl Brawl&lt;/span&gt;
&lt;span class="gs"&gt;[1] *&lt;/span&gt; Min threads: 0, max threads: 16
[1] &lt;span class="gs"&gt;* Environment: production&lt;/span&gt;
&lt;span class="gs"&gt;[1] *&lt;/span&gt; Process workers: 2
[1] &lt;span class="gs"&gt;* Phased restart available&lt;/span&gt;
&lt;span class="gs"&gt;[1] *&lt;/span&gt; Listening on tcp://0.0.0.0:8080
[1] Use Ctrl-C to stop
[1] - Worker 0 (pid: 32) booted, phase: 0
[1] - Worker 1 (pid: 35) booted, phase: 0
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Events&lt;/h3&gt;
&lt;p&gt;To see the flow of execution, you can have a look at:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;events
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This can be helpful if an error occured.&lt;/p&gt;
&lt;h3&gt;Verify&lt;/h3&gt;
&lt;p&gt;Now that the application has been deployed on OpenShift, we need to look up the 
IP address that has been assigned. For this we use:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;svc
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;NAME      CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
ruby-ex   172.30.91.160   &amp;lt;none&amp;gt;        8080/TCP   21h
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we can open the application as &lt;code&gt;http://172.30.91.160:8080/&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;OpenShift allows you to run prebuilt images or applications based on source.
The Source-to-image tooling makes it possible to create reproducible images for
deployment of applications based on source. This tool itself is very helpful
and is certainly something I will be using, even outside the use of OpenShift.
There is no need to create or modify a &lt;code&gt;Dockerfile&lt;/code&gt;, which means that the
developer can focus on the development process.&lt;/p&gt;
&lt;p&gt;If you want to know more about the automated builds, please have a look at the
README of the &lt;a href="https://github.com/openshift/ruby-ex" title="Ruby example"&gt;Ruby example&lt;/a&gt;. In future articles more 
detailed descriptions about these topics will certainly be given. I hope this
has been helpful. Please consider leaving feedback or tweet this article.&lt;/p&gt;</content><category term="Containers"/><category term="containers"/><category term="openshift"/><category term="example"/><category term="ruby"/><category term="docker"/><category term="devops"/></entry><entry><title>Setup Docker storage to use LVM thin pool</title><link href="https://blog.gbraad.nl/setup-docker-storage-to-use-lvm-thin-pool.html" rel="alternate"/><published>2016-09-28T00:00:00+08:00</published><updated>2016-09-28T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-09-28:/setup-docker-storage-to-use-lvm-thin-pool.html</id><summary type="html">&lt;p&gt;If you install Docker on a new Fedora or CentOS system, it is very likely that
you use devicemapper. Especially in the case of Fedora cloud images, no special
configuration is done to the image. While Atomic images come pre-configured with
a dedicated pool. Using devicemapper with loopback can lead …&lt;/p&gt;</summary><content type="html">&lt;p&gt;If you install Docker on a new Fedora or CentOS system, it is very likely that
you use devicemapper. Especially in the case of Fedora cloud images, no special
configuration is done to the image. While Atomic images come pre-configured with
a dedicated pool. Using devicemapper with loopback can lead to unpredictable
behaviour, and while OverlayFS is a nice replacement, you will not be able to
use SELinux at the moment. In this short article I will show how to setup a pool
for storing the Docker images.&lt;/p&gt;
&lt;h2&gt;Preparation&lt;/h2&gt;
&lt;p&gt;For this article I will be using a Fedora 24 installation on an OpenStack cloud
provider&lt;a href="http://citycloud.com"&gt;*&lt;/a&gt;. It is a standard Cloud image, which means the
root is configured as 'ext4'. I will be attaching a storage volume to the
instance. Just like using Virtual Manager, the disk will be identified as
&lt;code&gt;/dev/vdb&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;First you need to stop the Docker process and remove the existing location. This
means you will loose the images, but if they are important, you can either
export or push them somewhere else.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;stop&lt;span class="w"&gt; &lt;/span&gt;docker
$&lt;span class="w"&gt; &lt;/span&gt;rm&lt;span class="w"&gt; &lt;/span&gt;-rf&lt;span class="w"&gt; &lt;/span&gt;/var/lib/docker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After this we will create a basic LVM setup which will use the whole storage
volume.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;pvcreate&lt;span class="w"&gt; &lt;/span&gt;/dev/vdb
$&lt;span class="w"&gt; &lt;/span&gt;vgcreate&lt;span class="w"&gt; &lt;/span&gt;docker_vol&lt;span class="w"&gt; &lt;/span&gt;/dev/vdb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We know have a &lt;code&gt;volumegroup&lt;/code&gt; named &lt;code&gt;docker_vol&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Setup Docker storage&lt;/h2&gt;
&lt;p&gt;Fedora comes with a tool that makes it easy to setup the storage for Docker,
called &lt;code&gt;docker-storage-setup&lt;/code&gt;. The configuration is done with a file, and in
our case it needs to contain the identification of the volume group to use:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;vi&lt;span class="w"&gt; &lt;/span&gt;/etc/sysconfig/docker-storage-setup&lt;span class="w"&gt; &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;VG=&amp;quot;docker_vol&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now you can run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker-storage-setup
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will create the filesystem and configures Docker to use the storage pool.
After this successfully finishes, it has configured the pool to use the xfs
filesystem.&lt;/p&gt;
&lt;h2&gt;Verify&lt;/h2&gt;
&lt;p&gt;To verify these changes, we will start Docker and run a basic image.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;docker
$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;info
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Storage&lt;span class="w"&gt; &lt;/span&gt;Driver:&lt;span class="w"&gt; &lt;/span&gt;devicemapper
&lt;span class="w"&gt; &lt;/span&gt;Pool&lt;span class="w"&gt; &lt;/span&gt;Name:&lt;span class="w"&gt; &lt;/span&gt;docker_vol-docker--pool
&lt;span class="w"&gt; &lt;/span&gt;Pool&lt;span class="w"&gt; &lt;/span&gt;Blocksize:&lt;span class="w"&gt; &lt;/span&gt;524.3&lt;span class="w"&gt; &lt;/span&gt;kB
&lt;span class="w"&gt; &lt;/span&gt;Base&lt;span class="w"&gt; &lt;/span&gt;Device&lt;span class="w"&gt; &lt;/span&gt;Size:&lt;span class="w"&gt; &lt;/span&gt;10.74&lt;span class="w"&gt; &lt;/span&gt;GB
&lt;span class="w"&gt; &lt;/span&gt;Backing&lt;span class="w"&gt; &lt;/span&gt;Filesystem:&lt;span class="w"&gt; &lt;/span&gt;xfs
&lt;span class="w"&gt; &lt;/span&gt;Data&lt;span class="w"&gt; &lt;/span&gt;file:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;Metadata&lt;span class="w"&gt; &lt;/span&gt;file:&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;Data&lt;span class="w"&gt; &lt;/span&gt;Space&lt;span class="w"&gt; &lt;/span&gt;Used:&lt;span class="w"&gt; &lt;/span&gt;37.75&lt;span class="w"&gt; &lt;/span&gt;MB
&lt;span class="w"&gt; &lt;/span&gt;Data&lt;span class="w"&gt; &lt;/span&gt;Space&lt;span class="w"&gt; &lt;/span&gt;Total:&lt;span class="w"&gt; &lt;/span&gt;21.45&lt;span class="w"&gt; &lt;/span&gt;GB
&lt;span class="w"&gt; &lt;/span&gt;Data&lt;span class="w"&gt; &lt;/span&gt;Space&lt;span class="w"&gt; &lt;/span&gt;Available:&lt;span class="w"&gt; &lt;/span&gt;21.41&lt;span class="w"&gt; &lt;/span&gt;GB
&lt;span class="w"&gt; &lt;/span&gt;Metadata&lt;span class="w"&gt; &lt;/span&gt;Space&lt;span class="w"&gt; &lt;/span&gt;Used:&lt;span class="w"&gt; &lt;/span&gt;53.25&lt;span class="w"&gt; &lt;/span&gt;kB
&lt;span class="w"&gt; &lt;/span&gt;Metadata&lt;span class="w"&gt; &lt;/span&gt;Space&lt;span class="w"&gt; &lt;/span&gt;Total:&lt;span class="w"&gt; &lt;/span&gt;54.53&lt;span class="w"&gt; &lt;/span&gt;MB
&lt;span class="w"&gt; &lt;/span&gt;Metadata&lt;span class="w"&gt; &lt;/span&gt;Space&lt;span class="w"&gt; &lt;/span&gt;Available:&lt;span class="w"&gt; &lt;/span&gt;54.47&lt;span class="w"&gt; &lt;/span&gt;MB
&lt;span class="w"&gt; &lt;/span&gt;Udev&lt;span class="w"&gt; &lt;/span&gt;Sync&lt;span class="w"&gt; &lt;/span&gt;Supported:&lt;span class="w"&gt; &lt;/span&gt;true
&lt;span class="w"&gt; &lt;/span&gt;Deferred&lt;span class="w"&gt; &lt;/span&gt;Removal&lt;span class="w"&gt; &lt;/span&gt;Enabled:&lt;span class="w"&gt; &lt;/span&gt;true
&lt;span class="w"&gt; &lt;/span&gt;Deferred&lt;span class="w"&gt; &lt;/span&gt;Deletion&lt;span class="w"&gt; &lt;/span&gt;Enabled:&lt;span class="w"&gt; &lt;/span&gt;true
&lt;span class="w"&gt; &lt;/span&gt;Deferred&lt;span class="w"&gt; &lt;/span&gt;Deleted&lt;span class="w"&gt; &lt;/span&gt;Device&lt;span class="w"&gt; &lt;/span&gt;Count:&lt;span class="w"&gt; &lt;/span&gt;0
&lt;span class="w"&gt; &lt;/span&gt;Library&lt;span class="w"&gt; &lt;/span&gt;Version:&lt;span class="w"&gt; &lt;/span&gt;1.02.122&lt;span class="w"&gt; &lt;/span&gt;(2016-04-09)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;pull&lt;span class="w"&gt; &lt;/span&gt;busybox
$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-it&lt;span class="w"&gt; &lt;/span&gt;--rm&lt;span class="w"&gt; &lt;/span&gt;busybox
/&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c1"&gt;# &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Configuration of storage has been really simplified and shouldn't be a reason
not to do this. However, still to many people are not aware of the issues with
devicemapper and loopback. Having to assign additional software to use Docker
can also be a reason why people do not consider doing this, but even OverlayFS
is not perfect. Using overlay with SELinux will be possible in the future, and
hopefully soon these steps will also not be needed. In any case, the steps
involved are simple and if you use Docker on Fedora, needed!&lt;/p&gt;
&lt;h2&gt;More information&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://www.projectatomic.io/blog/2015/06/notes-on-fedora-centos-and-docker-storage-drivers/"&gt;Friends Don't Let Friends Run Docker on Loopback in Production&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.projectatomic.io/docs/docker-storage-recommendation/"&gt;Setting up storage&lt;/a&gt; for Project Atomic&lt;/li&gt;
&lt;/ul&gt;</content><category term="containers"/><category term="docker"/><category term="containers"/><category term="atomic"/><category term="storage"/></entry><entry><title>Deploy an OpenShift test cluster</title><link href="https://blog.gbraad.nl/deploy-an-openshift-test-cluster.html" rel="alternate"/><published>2016-09-27T00:00:00+08:00</published><updated>2016-09-27T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-09-27:/deploy-an-openshift-test-cluster.html</id><summary type="html">&lt;p&gt;In my previous article I described how I used an Ansible playbook and a few roles
to stand-up a Kubernetes test environment. In that article I mentioned that to
deploy a production-ready environment some work more was required. Luckily, it
is now very easy to stand up a production and …&lt;/p&gt;</summary><content type="html">&lt;p&gt;In my previous article I described how I used an Ansible playbook and a few roles
to stand-up a Kubernetes test environment. In that article I mentioned that to
deploy a production-ready environment some work more was required. Luckily, it
is now very easy to stand up a production and enterprise-ready container
platform for hosting applications, called &lt;a href="https://www.openshift.com"&gt;OpenShift&lt;/a&gt;.
Through the years OpenShift has undergone a lot of changes, and the latest
version Origin v1.3 is very different from the original version. OpenShift sets
up a complete Kubernetes environment and with a set of tools it can take care of
the whole application lifecycle, from source to deployment. In this article I
will give an introduction to setting up a test environment for a developer.&lt;/p&gt;
&lt;h2&gt;Setup machine&lt;/h2&gt;
&lt;p&gt;I will setup the environment on a standard Fedora 24 installation. You can use a
cloud image as all the needed packages will be specified. After installing the
machine, you login as a standard user, which can do a password-less sudo.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ssh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fedora&lt;/span&gt;&lt;span class="mf"&gt;@89.42.141.96&lt;/span&gt;
&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;su&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;
&lt;span class="cp"&gt;#&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Install docker and client&lt;/h3&gt;
&lt;p&gt;From here all the commands will be run as root, unless otherwise specified.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;dnf&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;curl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will install the basic packages we need to setup the test cluster. Now from
a browser you open the following page: &lt;a href="https://github.com/openshift/origin/releases/tag/v1.3.0"&gt;https://github.com/openshift/origin/releases/tag/v1.3.0&lt;/a&gt;.
This shows the current deliverables for the OpenShift Origin v1.3 release. You
need to download the file called like &lt;code&gt;openshift-origin-client-tools-v1.3.0-[...]-linux-64bit.tar.gz&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;curl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;sSL&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;github&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;openshift&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;origin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;releases&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;download&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;openshift&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;origin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;ab7af3d097b57f933eccef684a714f2368804e7&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;linux&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="n"&gt;bit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gz&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;oc&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gz&lt;/span&gt;
&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;tar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;zxvf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;oc&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;tar&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;gz&lt;/span&gt;
&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mkdir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;openshift&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;
&lt;span class="o"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;./&lt;/span&gt;&lt;span class="n"&gt;openshift&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;origin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;tools&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;3.0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;ab7af3d097b57f933eccef684a714f2368804e7&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;linux&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;64&lt;/span&gt;&lt;span class="n"&gt;bit&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;oc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;opt&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;openshift&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;oc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note: I do not install the binary in &lt;code&gt;/usr/bin&lt;/code&gt; or &lt;code&gt;/usr/sbin&lt;/code&gt; to prevent a
conflict with a packaged version, but also because this makes it easier for me
to work on a different version of the application. E.g. the current packaged
version is v1.2 and does not provide the command we will be using in the next
step.&lt;/p&gt;
&lt;h3&gt;Configure docker&lt;/h3&gt;
&lt;p&gt;To allow OpenShift to pull and locally cache images, it will deploy a local
docker registry. But before docker would be able to use this, we need to
specify an insecure registry in the configuration. For this you need to add
&lt;code&gt;--insecure-registry 172.30.0.0/16&lt;/code&gt; to &lt;code&gt;/etc/sysconfig/docker&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;vi&lt;span class="w"&gt; &lt;/span&gt;/etc/sysconfig/docker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;OPTIONS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;selinux&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;enabled&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;driver&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;journald&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;insecure&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;172.30.0.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mh"&gt;16&lt;/span&gt;&lt;span class="p"&gt;&amp;#39;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After this we will setup to allow the standard user to communicate with the
docker daemon over the docker socket. This is not a necessary step, and does not
make the system more secure. It does make it easier not having to move between
user and using sudo all the time.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;groupadd&lt;span class="w"&gt; &lt;/span&gt;docker
$&lt;span class="w"&gt; &lt;/span&gt;usermod&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;-G&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;fedora
$&lt;span class="w"&gt; &lt;/span&gt;chgrp&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;/var/run/docker.sock
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Edit: I recently created an &lt;a href="https://github.com/gbraad/ansible-playbooks/blob/master/playbooks/enable-ansible-user-for-docker.yml"&gt;Ansible playbook&lt;/a&gt;
to perform these steps, as I had to do this on several Atomic hosts. I uses the
current Ansible user and adds it to a group, and changes the socket permissions.&lt;/p&gt;
&lt;p&gt;After this you can start docker and move on the actual installation of OpenShift.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker
$&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;docker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note: we will be running this environment with devicemapper as Storage Driver.
This is not an ideal situation. If you do further tests, consider changing the
storage with &lt;code&gt;docker-storage-setup&lt;/code&gt; to use a dedicated volume.&lt;/p&gt;
&lt;h2&gt;Running OpenShift&lt;/h2&gt;
&lt;p&gt;Since version 1.3 of OpenShift, the client provides a &lt;code&gt;cluster up&lt;/code&gt; commands
which stands up a very simple all-in-one cluster, with a configured registry,
router, image streams, and default templates.&lt;/p&gt;
&lt;p&gt;As the fedora user, you can check if you can access docker&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;ps
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;CONTAINER ID    IMAGE   COMMAND     CREATED     STATUS      PORTS   NAMES
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;No containers should be returned. This mean you can communicate with the docker
daemon. Now you are ready to start the test cluster. &lt;/p&gt;
&lt;h3&gt;&lt;code&gt;cluster up&lt;/code&gt;&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;:/opt/openshift/client/
$&lt;span class="w"&gt; &lt;/span&gt;./oc&lt;span class="w"&gt; &lt;/span&gt;cluster&lt;span class="w"&gt; &lt;/span&gt;up
--&lt;span class="w"&gt; &lt;/span&gt;Checking&lt;span class="w"&gt; &lt;/span&gt;OpenShift&lt;span class="w"&gt; &lt;/span&gt;client&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;OK
--&lt;span class="w"&gt; &lt;/span&gt;Checking&lt;span class="w"&gt; &lt;/span&gt;Docker&lt;span class="w"&gt; &lt;/span&gt;client&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;OK
--&lt;span class="w"&gt; &lt;/span&gt;Checking&lt;span class="w"&gt; &lt;/span&gt;Docker&lt;span class="w"&gt; &lt;/span&gt;version&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;OK
--&lt;span class="w"&gt; &lt;/span&gt;Checking&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;existing&lt;span class="w"&gt; &lt;/span&gt;OpenShift&lt;span class="w"&gt; &lt;/span&gt;container&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;OK
--&lt;span class="w"&gt; &lt;/span&gt;Checking&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;openshift/origin:v1.3.0&lt;span class="w"&gt; &lt;/span&gt;image&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;OK
--&lt;span class="w"&gt; &lt;/span&gt;Checking&lt;span class="w"&gt; &lt;/span&gt;Docker&lt;span class="w"&gt; &lt;/span&gt;daemon&lt;span class="w"&gt; &lt;/span&gt;configuration&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;OK
--&lt;span class="w"&gt; &lt;/span&gt;Checking&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;available&lt;span class="w"&gt; &lt;/span&gt;ports&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;OK
--&lt;span class="w"&gt; &lt;/span&gt;Checking&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;of&lt;span class="w"&gt; &lt;/span&gt;volume&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;Using&lt;span class="w"&gt; &lt;/span&gt;nsenter&lt;span class="w"&gt; &lt;/span&gt;mounter&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;OpenShift&lt;span class="w"&gt; &lt;/span&gt;volumes
--&lt;span class="w"&gt; &lt;/span&gt;Creating&lt;span class="w"&gt; &lt;/span&gt;host&lt;span class="w"&gt; &lt;/span&gt;directories&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;OK
--&lt;span class="w"&gt; &lt;/span&gt;Finding&lt;span class="w"&gt; &lt;/span&gt;server&lt;span class="w"&gt; &lt;/span&gt;IP&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;Using&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.5.0.27&lt;span class="w"&gt; &lt;/span&gt;as&lt;span class="w"&gt; &lt;/span&gt;the&lt;span class="w"&gt; &lt;/span&gt;server&lt;span class="w"&gt; &lt;/span&gt;IP
--&lt;span class="w"&gt; &lt;/span&gt;Starting&lt;span class="w"&gt; &lt;/span&gt;OpenShift&lt;span class="w"&gt; &lt;/span&gt;container&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;Creating&lt;span class="w"&gt; &lt;/span&gt;initial&lt;span class="w"&gt; &lt;/span&gt;OpenShift&lt;span class="w"&gt; &lt;/span&gt;configuration
&lt;span class="w"&gt;   &lt;/span&gt;Starting&lt;span class="w"&gt; &lt;/span&gt;OpenShift&lt;span class="w"&gt; &lt;/span&gt;using&lt;span class="w"&gt; &lt;/span&gt;container&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;origin&amp;#39;&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;Waiting&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;API&lt;span class="w"&gt; &lt;/span&gt;server&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;listening
&lt;span class="w"&gt;   &lt;/span&gt;OpenShift&lt;span class="w"&gt; &lt;/span&gt;server&lt;span class="w"&gt; &lt;/span&gt;started
--&lt;span class="w"&gt; &lt;/span&gt;Installing&lt;span class="w"&gt; &lt;/span&gt;registry&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;OK
--&lt;span class="w"&gt; &lt;/span&gt;Installing&lt;span class="w"&gt; &lt;/span&gt;router&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;OK
--&lt;span class="w"&gt; &lt;/span&gt;Importing&lt;span class="w"&gt; &lt;/span&gt;image&lt;span class="w"&gt; &lt;/span&gt;streams&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;OK
--&lt;span class="w"&gt; &lt;/span&gt;Importing&lt;span class="w"&gt; &lt;/span&gt;templates&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;OK
--&lt;span class="w"&gt; &lt;/span&gt;Login&lt;span class="w"&gt; &lt;/span&gt;to&lt;span class="w"&gt; &lt;/span&gt;server&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;OK
--&lt;span class="w"&gt; &lt;/span&gt;Creating&lt;span class="w"&gt; &lt;/span&gt;initial&lt;span class="w"&gt; &lt;/span&gt;project&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;myproject&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;OK
--&lt;span class="w"&gt; &lt;/span&gt;Server&lt;span class="w"&gt; &lt;/span&gt;Information&lt;span class="w"&gt; &lt;/span&gt;...&lt;span class="w"&gt; &lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;OpenShift&lt;span class="w"&gt; &lt;/span&gt;server&lt;span class="w"&gt; &lt;/span&gt;started.
&lt;span class="w"&gt;   &lt;/span&gt;The&lt;span class="w"&gt; &lt;/span&gt;server&lt;span class="w"&gt; &lt;/span&gt;is&lt;span class="w"&gt; &lt;/span&gt;accessible&lt;span class="w"&gt; &lt;/span&gt;via&lt;span class="w"&gt; &lt;/span&gt;web&lt;span class="w"&gt; &lt;/span&gt;console&lt;span class="w"&gt; &lt;/span&gt;at:
&lt;span class="w"&gt;       &lt;/span&gt;https://10.5.0.27:8443

&lt;span class="w"&gt;   &lt;/span&gt;You&lt;span class="w"&gt; &lt;/span&gt;are&lt;span class="w"&gt; &lt;/span&gt;logged&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;as:
&lt;span class="w"&gt;       &lt;/span&gt;User:&lt;span class="w"&gt;     &lt;/span&gt;developer
&lt;span class="w"&gt;       &lt;/span&gt;Password:&lt;span class="w"&gt; &lt;/span&gt;developer

&lt;span class="w"&gt;   &lt;/span&gt;To&lt;span class="w"&gt; &lt;/span&gt;login&lt;span class="w"&gt; &lt;/span&gt;as&lt;span class="w"&gt; &lt;/span&gt;administrator:
&lt;span class="w"&gt;       &lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;login&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;system:admin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And that was it! Now you are running an OpenShift environment. You can check
this as follows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;docker&lt;span class="w"&gt; &lt;/span&gt;ps
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;CONTAINER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;IMAGE&lt;/span&gt;&lt;span class="w"&gt;                                     &lt;/span&gt;&lt;span class="n"&gt;COMMAND&lt;/span&gt;&lt;span class="w"&gt;                  &lt;/span&gt;&lt;span class="n"&gt;CREATED&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="n"&gt;STATUS&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="n"&gt;PORTS&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="n"&gt;NAMES&lt;/span&gt;
&lt;span class="n"&gt;cebba70022a6&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;openshift&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;origin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;haproxy&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nl"&gt;router:&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="mf"&gt;.3.0&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/usr/bin/openshift-r&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mh"&gt;16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ago&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;Up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;15&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="w"&gt;                           &lt;/span&gt;&lt;span class="n"&gt;k8s_router&lt;/span&gt;&lt;span class="mf"&gt;.9426645&lt;/span&gt;&lt;span class="n"&gt;a_router&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;o3454_default_ba2e0814&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;8483&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;11e6&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;924&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;fa163e29da46_e9a13a8d&lt;/span&gt;
&lt;span class="mh"&gt;32&lt;/span&gt;&lt;span class="n"&gt;aa5e84a04d&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;openshift&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;origin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nl"&gt;registry:&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="mf"&gt;.3.0&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/bin/sh -c &amp;#39;DOCKER_R&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mh"&gt;17&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ago&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;Up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;15&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="w"&gt;                           &lt;/span&gt;&lt;span class="n"&gt;k8s_registry&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f0a205a4_docker&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;v57os_default_b9fc0130&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;8483&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;11e6&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;924&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;fa163e29da46_24863324&lt;/span&gt;
&lt;span class="mh"&gt;03&lt;/span&gt;&lt;span class="n"&gt;ee38d125cb&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;openshift&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;origin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nl"&gt;pod:&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="mf"&gt;.3.0&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/pod&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;                   &lt;/span&gt;&lt;span class="mh"&gt;18&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ago&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;Up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="w"&gt;                           &lt;/span&gt;&lt;span class="n"&gt;k8s_POD&lt;/span&gt;&lt;span class="mf"&gt;.4&lt;/span&gt;&lt;span class="n"&gt;a82dc9f_router&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;o3454_default_ba2e0814&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;8483&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;11e6&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;924&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;fa163e29da46_ea6d1d08&lt;/span&gt;
&lt;span class="mh"&gt;44&lt;/span&gt;&lt;span class="n"&gt;d6f8d2d9d6&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;openshift&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;origin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nl"&gt;pod:&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="mf"&gt;.3.0&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/pod&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;                   &lt;/span&gt;&lt;span class="mh"&gt;18&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ago&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;Up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;16&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="w"&gt;                           &lt;/span&gt;&lt;span class="n"&gt;k8s_POD&lt;/span&gt;&lt;span class="mf"&gt;.9f&lt;/span&gt;&lt;span class="n"&gt;a2fe82_docker&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;registry&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;v57os_default_b9fc0130&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;8483&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;11e6&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;924&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;fa163e29da46_76754271&lt;/span&gt;
&lt;span class="mf"&gt;60e7&lt;/span&gt;&lt;span class="n"&gt;cc5f4e5d&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;openshift&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;origin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nl"&gt;deployer:&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="mf"&gt;.3.0&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/usr/bin/openshift-d&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mh"&gt;21&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ago&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;Up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;19&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="w"&gt;                           &lt;/span&gt;&lt;span class="n"&gt;k8s_deployment&lt;/span&gt;&lt;span class="mf"&gt;.59&lt;/span&gt;&lt;span class="n"&gt;c7ba3f_router&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;deploy_default_b3660c7b&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;8483&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;11e6&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;924&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;fa163e29da46_8e02f47a&lt;/span&gt;
&lt;span class="n"&gt;f1fe993ddcac&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;openshift&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;origin&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nl"&gt;pod:&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="mf"&gt;.3.0&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/pod&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;                   &lt;/span&gt;&lt;span class="mh"&gt;22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ago&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;Up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;20&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="w"&gt;                           &lt;/span&gt;&lt;span class="n"&gt;k8s_POD&lt;/span&gt;&lt;span class="mf"&gt;.4&lt;/span&gt;&lt;span class="n"&gt;a82dc9f_router&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;1&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;deploy_default_b3660c7b&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;8483&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;11e6&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mh"&gt;924&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;fa163e29da46_9a38fe5e&lt;/span&gt;
&lt;span class="mh"&gt;72068&lt;/span&gt;&lt;span class="n"&gt;a244ac8&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="n"&gt;openshift&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nl"&gt;origin:&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="mf"&gt;.3.0&lt;/span&gt;&lt;span class="w"&gt;                   &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;/usr/bin/openshift s&amp;quot;&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mh"&gt;49&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ago&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;Up&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;48&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;seconds&lt;/span&gt;&lt;span class="w"&gt;                           &lt;/span&gt;&lt;span class="n"&gt;origin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Client connection&lt;/h3&gt;
&lt;p&gt;After running the command &lt;code&gt;oc cluster up&lt;/code&gt; you will be automatically logged in.
For this it writes the login configuration in &lt;code&gt;~/.kube/&lt;/code&gt;. If you want to change
you can login using:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;login
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The standard user provided is &lt;code&gt;developer&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Verify&lt;/h3&gt;
&lt;p&gt;Now we need to verify if we can deploy a simple application. However, without
changes, OpenShift will not run containers with a root-user process. For example
an nginx container would fail with a &lt;code&gt;permission denied&lt;/code&gt; error.&lt;/p&gt;
&lt;p&gt;Instead, we will for now run a simple Hello container:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;hello-openshift&lt;span class="w"&gt; &lt;/span&gt;--image&lt;span class="o"&gt;=&lt;/span&gt;docker.io/openshift/hello-openshift:latest&lt;span class="w"&gt; &lt;/span&gt;--port&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--expose
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;service &amp;quot;hello-openshift&amp;quot; created
deploymentconfig &amp;quot;hello-openshift&amp;quot; created
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This would create the container and schedule it. You can check the progress with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;pod
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;NAME                        READY     STATUS    RESTARTS   AGE
hello-openshift-1-xi7f0     1/1       Running   0          9m
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You will also see a &lt;code&gt;-deploy&lt;/code&gt; container. This is not needed for our verification.&lt;/p&gt;
&lt;p&gt;To check the application, we need to get the IP address that has been assigned
to the Pod. You can do this as follows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;pod&lt;span class="w"&gt; &lt;/span&gt;hello-openshift-1-xi7f0&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;yaml&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;grep&lt;span class="w"&gt; &lt;/span&gt;podIP
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;  podIP: 172.17.0.7
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;All you have to do now is open the endpoint:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;172&lt;/span&gt;.17.0.7:8080
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Hello OpenShift!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And that is it, you have a working OpenShift test cluster.&lt;/p&gt;
&lt;h3&gt;Teardown&lt;/h3&gt;
&lt;p&gt;If you are down with this, you simply do a:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;oc&lt;span class="w"&gt; &lt;/span&gt;cluster&lt;span class="w"&gt; &lt;/span&gt;down
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;and all the containers used in the deployment will be torn down.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Using OpenShift's &lt;code&gt;cluster up&lt;/code&gt; command you can easily setup an environment for
developers to run and test their applications. The current of OpenShift
provided with Fedora 24 does not offer this command, as the packaged version is
v1.2. However, this change is in Rawhide and is therefore expected to be
released as part of Fedora 25.&lt;/p&gt;
&lt;p&gt;In future articles I will detail more about how to create applications for the
OpenShift container platform, and how to check and maintain the life cycle of
the deployed application. For now, take a look at the other source of
information below.&lt;/p&gt;
&lt;h2&gt;More information&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;OpenShift &lt;a href="https://www.openshift.com/"&gt;Homepage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/openshift/origin"&gt;OpenShift Origin&lt;/a&gt; at GitHub&lt;/li&gt;
&lt;li&gt;Knowledge-base article about &lt;a href="https://gitlab.com/gbraad/knowledge-base/blob/master/technology/openshift.md"&gt;OpenShift&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Containers"/><category term="openshift"/><category term="kubernetes"/><category term="containers"/><category term="docker"/></entry><entry><title>Deploying Kubernetes using Ansible</title><link href="https://blog.gbraad.nl/deploying-kubernetes-using-ansible.html" rel="alternate"/><published>2016-09-26T00:00:00+08:00</published><updated>2016-09-26T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-09-26:/deploying-kubernetes-using-ansible.html</id><summary type="html">&lt;p&gt;Recently I did a lot of tests with Atomic, such as a &lt;a href="./deployment-of-ceph-using-custom-atomic-images.html"&gt;creating custom images&lt;/a&gt; for &lt;a href="./tag/ceph.html"&gt;Ceph&lt;/a&gt;, and ways to provide an immutable infrastructure. However, Atomic is meant to be a host platform for a container platform using Kubernetes. Their &lt;a href="http://www.projectatomic.io/docs/gettingstarted/"&gt;Getting Started guide&lt;/a&gt; describes how to setup a basic environment …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Recently I did a lot of tests with Atomic, such as a &lt;a href="./deployment-of-ceph-using-custom-atomic-images.html"&gt;creating custom images&lt;/a&gt; for &lt;a href="./tag/ceph.html"&gt;Ceph&lt;/a&gt;, and ways to provide an immutable infrastructure. However, Atomic is meant to be a host platform for a container platform using Kubernetes. Their &lt;a href="http://www.projectatomic.io/docs/gettingstarted/"&gt;Getting Started guide&lt;/a&gt; describes how to setup a basic environment to host containerized applications. However, this is a manual approach and with the help of Vincent&lt;a href="https://blog.vanderkussen.org/deploy-kubernetes-with-ansible-on-atomic.html"&gt;*&lt;/a&gt; I create a way to deploy this Kubernetes environment on Atomic and a standard CentOS installation using Ansible. In this article I will describe the components and provide instructions on how to deploy this basic environment yourself.&lt;/p&gt;
&lt;h2&gt;Requirements&lt;/h2&gt;
&lt;p&gt;To deploy the Kubernetes environment you will need either &lt;a href="http://www.projectatomic.io/download/"&gt;Atomic Host&lt;/a&gt; or a standard &lt;a href="https://www.centos.org/download/"&gt;CentOS&lt;/a&gt; installation. If you are using this for testing purposes, a cloud image on an OpenStack provider will do. The described Ansible scripts will work properly on both Atomic Host and CentOS cloud images. Although it has not been tested on Fedora, it should be able to make this work with minimal changes. If you do, please contribute these changes back.&lt;/p&gt;
&lt;p&gt;You will need at least 2 (virtual) machines. One will be configured as the Kubernetes master and the remaining node(s) can be configured as minions or deployment nodes. I have used at least 4 nodes; a general controller node to perform the deployment from (also configured to install the Kubernetes client), a master node and at least two deployment nodes. Take note that this deployment does not handle &lt;code&gt;docker-storage-setup&lt;/code&gt; and High Availability.&lt;/p&gt;
&lt;h2&gt;Setup for deployment&lt;/h2&gt;
&lt;p&gt;Almost all the deployments I perform are initiated from a short-lived controller node. This is a machine that allows
incoming and outgoing traffic, and mostly gets configured with an external Floating IP. This host can be seen as a jumphost. I will configure it with a dedicated set of SSH keys for communication with the other machines. You do not have to do this, and if you have limited resources, consider this host to be the same as the Kubernetes master node.&lt;/p&gt;
&lt;p&gt;On this machine do the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;yum&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;ansible&lt;span class="w"&gt; &lt;/span&gt;git
$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;https://gitlab.com/gbraad/ansible-playbook-kubernetes.git
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ansible-playbook-kubernetes
$&lt;span class="w"&gt; &lt;/span&gt;ansible-galaxy&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-r&lt;span class="w"&gt; &lt;/span&gt;roles.txt
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will install the Ansible playbook and the required roles:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;gbraad&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;
&lt;span class="n"&gt;gbraad&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;registry&lt;/span&gt;
&lt;span class="n"&gt;gbraad&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kubernetes&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;master&lt;/span&gt;
&lt;span class="n"&gt;gbraad&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kubernetes&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;
&lt;span class="n"&gt;gbraad&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;kubernetes&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;client&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Each of the roles take care of the installation and/or configuration of the environment. Do take note that the Docker and Kubernetes roles do not install packages on the Atomic hosts as these already come with the needed software.&lt;/p&gt;
&lt;h2&gt;Configure the deployment&lt;/h2&gt;
&lt;p&gt;If you look at the files &lt;code&gt;deploy-kubernetes.yml&lt;/code&gt; you will see three tasks for a different group of hosts. As mentioned before, they will each take care of the installation when needed.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;-&lt;/span&gt; name: Deploy kubernetes Master
  hosts: k8s-master
  remote_user: centos
  become: true
  roles:
  &lt;span class="k"&gt;-&lt;/span&gt; gbraad.docker
  &lt;span class="k"&gt;-&lt;/span&gt; gbraad.kubernetes-master

&lt;span class="k"&gt;-&lt;/span&gt; name: Deploy kubernetes Nodes
  hosts: k8s-nodes
  remote_user: centos
  become: true
  roles:
  &lt;span class="k"&gt;-&lt;/span&gt; gbraad.docker
  &lt;span class="k"&gt;-&lt;/span&gt; gbraad.kubernetes-node

&lt;span class="k"&gt;-&lt;/span&gt; name: Install kubernetes client
  hosts: k8s-client
  remote_user: centos
  become: true
  roles:
  &lt;span class="k"&gt;-&lt;/span&gt; gbraad.kubernetes-client
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Take notice of the setting of &lt;code&gt;remote_user&lt;/code&gt;. On an Atomic host this is a passwordless sudo user, which can also login with SSH using a passwordless key-based authentication. If you use CentOS, please configure a user and allow add an entry with &lt;code&gt;echo "username ALL=(root) NOPASSWD:ALL" &amp;gt; /etc/sudoers.d/username&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;Change the inventory&lt;/h3&gt;
&lt;p&gt;Ansible targets a playbook against a single or group of nodes that you specify in an inventory file. This file is named &lt;code&gt;hosts&lt;/code&gt; in this playbook repository. When you open it you will see the same set of names as specified above in the &lt;code&gt;hosts&lt;/code&gt; entry in the &lt;code&gt;deploy-kubernetes.yml&lt;/code&gt; playbook. For our purposes you will always have to deploy a master and a node. If you do not specify the master node, the installation will fail as some of the deployment variables will be used for configuration of the nodes.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;vi&lt;span class="w"&gt; &lt;/span&gt;hosts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;[k8s-master]&lt;/span&gt;
&lt;span class="na"&gt;atomic-01 ansible_ssh_host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10.5.0.11&lt;/span&gt;

&lt;span class="k"&gt;[k8s-nodes]&lt;/span&gt;
&lt;span class="na"&gt;atomic-02 ansible_ssh_host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10.5.0.14&lt;/span&gt;
&lt;span class="na"&gt;atomic-03 ansible_ssh_host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10.5.0.13&lt;/span&gt;
&lt;span class="na"&gt;atomic-04 ansible_ssh_host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10.5.0.12&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Group variables&lt;/h3&gt;
&lt;p&gt;At the moment the roles are not very configurable as they are mainly targeting a simple test environment. Inside the folder &lt;code&gt;group_vars&lt;/code&gt; you will find the configration for the Kubernetes nodes. These are as follows&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;skydns_enable&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;dns_server&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;10.254&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.10&lt;/span&gt;
&lt;span class="n"&gt;dns_domain&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;kubernetes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;local&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Perform the deployment&lt;/h2&gt;
&lt;p&gt;After changing the variables in the &lt;code&gt;hosts&lt;/code&gt; inventory file and the group variables, you are actually all set to perform the deployment. We will start with the following.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ansible-playbook&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;hosts&lt;span class="w"&gt; &lt;/span&gt;deploy-docker-registry.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This first step will install Docker on the master node and pull the Docker Registry container. This is needed to provide a local cache of container images that you have pulled.&lt;/p&gt;
&lt;p&gt;After this we can install the Kubernetes environment with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ansible-playbook&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;hosts&lt;span class="w"&gt; &lt;/span&gt;deploy-kubernetes.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Below I will describe what each part of the playbook does and some information about the functionality.&lt;/p&gt;
&lt;h2&gt;Playbook and role description&lt;/h2&gt;
&lt;p&gt;Below I will give a short description of what each part of the playbook and role does.&lt;/p&gt;
&lt;h3&gt;Role &lt;code&gt;gbraad.docker&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Each node in the playbook will be targeted with the following role: &lt;code&gt;gbraad.docker&lt;/code&gt;. This role determines if the node is an Atomic Host or not. This check is performed in the &lt;code&gt;tasks/main.yml&lt;/code&gt; file. It the node is not an Atomic Host, it will include &lt;code&gt;install.yml&lt;/code&gt; to perform additional installation tasks. At the moment this is a simple package installation for &lt;code&gt;docker&lt;/code&gt;. After this step, the role will set state &lt;code&gt;started&lt;/code&gt; and &lt;code&gt;enabled&lt;/code&gt; for the services; &lt;code&gt;docker&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/gbraad/ansible-role-docker"&gt;Source&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;Role: &lt;code&gt;gbraad.kubernetes-master&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;As part of the playbook, first we will configure the master node. For this, the role &lt;code&gt;gbraad.kubernetes-master&lt;/code&gt; is used. Just like in the previous role, file &lt;code&gt;tasks/main.yml&lt;/code&gt; will perform a simple check to determine if an Atomic Host is used or not. If not, some packages will be installed:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;kubernetes-master&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;flannel&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;etcd&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://github.com/gbraad/ansible-role-kubernetes-master"&gt;Source&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Configure Kubernetes&lt;/h4&gt;
&lt;p&gt;After this step Kubernetes will be configured on this hosts. Tasks are described in the file &lt;code&gt;tasks/configure_k8s.yml&lt;/code&gt;, &lt;a href="https://github.com/gbraad/ansible-role-kubernetes-master/blob/master/tasks/configure_k8s.yml"&gt;source&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://galaxy.ansible.com/gbraad/kubernetes-master"&gt;Role&lt;/a&gt;&lt;/p&gt;
&lt;h5&gt;Congfigure Kubernetes: etcd&lt;/h5&gt;
&lt;p&gt;This role will create a single 'etcd' server on the master. For simplicty all IP address will be allowed by using &lt;code&gt;0.0.0.0&lt;/code&gt; as the endpoint. The port used for etcd clients is 2379, but since 4001 is also widely used we will also configure to use this.&lt;/p&gt;
&lt;p&gt;Tasks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Configure etcd LISTEN CLIENTS&lt;/li&gt;
&lt;li&gt;Configure etcd ADVERTISE CLIENTS&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Configure Kubernetes: common services&lt;/h5&gt;
&lt;p&gt;After this the role will set an entry in the file &lt;code&gt;/etc/kubernetes/config&lt;/code&gt;. This is a general configuration file used by all the services. It sets the local IP address, identified as &lt;code&gt;default_ipv4_address&lt;/code&gt; as etcd server and the kubernetes master nodes.&lt;/p&gt;
&lt;p&gt;Tasks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Configure k8s common services&lt;/li&gt;
&lt;/ul&gt;
&lt;h5&gt;Configure Kubernetes: apiserver&lt;/h5&gt;
&lt;p&gt;For the apiserer the file &lt;code&gt;/etc/kubernetes/apiserver&lt;/code&gt; is used. We will configure it to listen on all IP address. An admission control plug-in is a piece of code that intercepts requests to the Kubernetes API server prior to persistence of the object. For this role we removed &lt;code&gt;ServiceAccount&lt;/code&gt; which is normally used to limit the creation requests of Pods based on the service account.&lt;/p&gt;
&lt;h5&gt;Restart services&lt;/h5&gt;
&lt;p&gt;After this the services of the master node are &lt;code&gt;started&lt;/code&gt; and &lt;code&gt;enabled&lt;/code&gt;. These are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;etcd&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kube-apiserver&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kube-controller-manager&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;kube-scheduler&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;Configure flannel&lt;/h4&gt;
&lt;p&gt;For this environment we will use flannel to provide an overlay network. An overlay network exists on top of another network to provide a virtual path between nodes who use this overlay network. The steps for this are specified in &lt;code&gt;tasks/configure_flannel.yml&lt;/code&gt; &lt;a href="https://github.com/gbraad/ansible-role-kubernetes-master/blob/master/tasks/configure_flannel.yml"&gt;source&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The configuration of flannel is controller by etcd. We will copy a file to the master node containing:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;{
  &amp;quot;Network&amp;quot;: &amp;quot;172.16.0.0/12&amp;quot;,
  &amp;quot;SubnetLen&amp;quot;: 24,
  &amp;quot;Backend&amp;quot;: {
    &amp;quot;Type&amp;quot;: &amp;quot;vxlan&amp;quot;
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This file is located in the role as &lt;code&gt;files/flanneld-conf.json&lt;/code&gt;. Using &lt;code&gt;curl&lt;/code&gt; we will post this file to etcd on the master.&lt;/p&gt;
&lt;p&gt;Tasks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Copy json with network config&lt;/li&gt;
&lt;li&gt;Configure subnet&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After these steps the Kubernetes master is configured.&lt;/p&gt;
&lt;h3&gt;Role: &lt;code&gt;gbraad.kubernetes-node&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;For the configuration of a Kubernetes node we use the role &lt;code&gt;gbraad.kubernetes-node&lt;/code&gt;. Just like in the previous roles we determine in &lt;code&gt;tasks/main.yml&lt;/code&gt; to install packages or not. For all the nodes we will configure:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;SELinux&lt;/li&gt;
&lt;li&gt;flannel&lt;/li&gt;
&lt;li&gt;kubernetes specific settings&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href="https://github.com/gbraad/ansible-role-kubernetes-node"&gt;Source&lt;/a&gt;, &lt;a href="https://galaxy.ansible.com/gbraad/kubernetes-node/"&gt;Role&lt;/a&gt;&lt;/p&gt;
&lt;h4&gt;Configure SELinux&lt;/h4&gt;
&lt;p&gt;Because I use persistent storage using NFS with Docker, I configure SELinux to set the boolean &lt;code&gt;virt_use_nfs&lt;/code&gt;.&lt;/p&gt;
&lt;h4&gt;Configure flannel&lt;/h4&gt;
&lt;p&gt;In the tasks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Overlay | configure etcd url&lt;/li&gt;
&lt;li&gt;Overlay | configure etcd config key&lt;/li&gt;
&lt;li&gt;Flannel systemd | create service.d&lt;/li&gt;
&lt;li&gt;Flannel systemd | deploy unit file&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We configure all the nodes to use the etcd instance on &lt;code&gt;k8s-master&lt;/code&gt; as the endpoint for flannel configuration. These tasks configure the networking to use the flanneld provided bridge IP and MTU settings. Using the last two tasks we configure systemd to start the service.&lt;/p&gt;
&lt;p&gt;After this change we will restart the &lt;code&gt;flanneld&lt;/code&gt; service.&lt;/p&gt;
&lt;h4&gt;Configure Kubernetes&lt;/h4&gt;
&lt;p&gt;In the file &lt;code&gt;tasks/configure_k8s.yml&lt;/code&gt; we do final configuration of the Kubernetes node to point it to the master node.&lt;/p&gt;
&lt;p&gt;In the tasks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;k8s client configuration&lt;/li&gt;
&lt;li&gt;k8s client configuration | KUBELET_HOSTNAME&lt;/li&gt;
&lt;li&gt;k8s client configuration | KUBELET_ARGS&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;we configure how the node is identified.&lt;/p&gt;
&lt;p&gt;In the tasks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;k8s client configuration | KUBELET_API_SERVER&lt;/li&gt;
&lt;li&gt;Configure k8s master on client | KUBE_MASTER&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;we set the location of the API server and the master node. Both of these will point to the IP address of the &lt;code&gt;k8s-master&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;After this change we will restart the &lt;code&gt;kubelet&lt;/code&gt; and &lt;code&gt;kube-proxy&lt;/code&gt; service.&lt;/p&gt;
&lt;h3&gt;After deployment&lt;/h3&gt;
&lt;p&gt;If all these tasks succeeded, you should have a working Kubernetes deployment. In the next steps we will perform some simple commands to verify if the environment works.&lt;/p&gt;
&lt;h2&gt;Deploy client and verify environment&lt;/h2&gt;
&lt;p&gt;As you have noticed from the &lt;code&gt;hosts&lt;/code&gt; inventory file, there is a possibility to specify a client host:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;[k8s-client]&lt;/span&gt;
&lt;span class="na"&gt;controller ansible_ssh_host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10.5.0.3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You do not have to deploy a kubernetes client using this playbook. It will install a single package, but you could also just use the statically compiled Go binary that is provided from the Kubernetes releases:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;http://storage.googleapis.com/kubernetes-release/release/v1.3.4/bin/linux/amd64/kubectl
$&lt;span class="w"&gt; &lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;+x&lt;span class="w"&gt; &lt;/span&gt;kubectl
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Verify nodes&lt;/h3&gt;
&lt;p&gt;Oncae all the nodes have been deployed using the playbook, you canb verify communication. From a client node you can perform the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;--server&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.5.0.11:8080&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;node&lt;span class="sb"&gt;`&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;NAME             LABELS    STATUS
10.5.0.12        &amp;lt;none&amp;gt;    Ready
10.5.0.13        &amp;lt;none&amp;gt;    Ready
10.5.0.14        &amp;lt;none&amp;gt;    Ready
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Schedule workload&lt;/h3&gt;
&lt;p&gt;If all looks good, you can schedule a workload on the environment. The following commands will create a simple &lt;code&gt;nginx&lt;/code&gt; instance.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;vi&lt;span class="w"&gt; &lt;/span&gt;kube-nginx.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;apiVersion&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;
&lt;span class="n"&gt;kind&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Pod&lt;/span&gt;
&lt;span class="n"&gt;metadata&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;www&lt;/span&gt;
&lt;span class="n"&gt;spec&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;containers&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;name&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nginx&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nginx&lt;/span&gt;
&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="n"&gt;ports&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;containerPort&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;&lt;span class="n"&gt;hostPort&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This file described a Pod with a container called &lt;code&gt;nginx&lt;/code&gt; using the 'nginx' image. To schedule it, do:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;--server&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.5.0.11:8080&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;-f&lt;span class="w"&gt; &lt;/span&gt;kube-nginx.yml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;pods/www
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Using the following command you can check the status:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;kubectl&lt;span class="w"&gt; &lt;/span&gt;--server&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;192&lt;/span&gt;.168.124.40:8080&lt;span class="w"&gt; &lt;/span&gt;get&lt;span class="w"&gt; &lt;/span&gt;pods
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;POD       IP            CONTAINER(S)   IMAGE(S)   HOST                            LABELS    STATUS    CREATED      MESSAGE
www       172.16.59.2                             10.5.0.12/10.5.0.12             &amp;lt;none&amp;gt;    Running   52 seconds
                        nginx          nginx                                                Running   24 seconds
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you now open a browser pointing to the node Kubernetes used to create it (&lt;a href="http://10.5.0.12:8080/"&gt;http://10.5.0.12:8080/&lt;/a&gt;), you will see an nginx welcome page.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Setting up Kubernetes can be a daunting task as there are many different components involved. Kelsey Hightower has a very good guide, called &lt;a href="https://github.com/kelseyhightower/kubernetes-the-hard-way"&gt;Kubernetes The Hard Way&lt;/a&gt; that will teach you how to deploy kubernetes manually on different cloud providers, such as AWS and the Google Compute Engine. After gaining some experience, it is advised to look at automation to deploy an environment, such as the the Ansible scripts that can be found in the &lt;a href="https://github.com/kubernetes/contrib"&gt;contrib&lt;/a&gt; repository of Kubernetes. this allows you to stand up an environment with High Availability. The scripts described in this article should only serve as an introduction to gain understanding what is needed for a Kubernetes environment.&lt;/p&gt;
&lt;p&gt;If you want a production-ready environment, please have a look at OpenShift. OpenShift deals with setting up a cluster of kubernetes nodes, scheduling workload and most important, how to set up images for deployment. This is done using what is called 'source to image'. This and OpenShift itself will be the topic of future articles.&lt;/p&gt;
&lt;h2&gt;More information&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Knowledge-base article about &lt;a href="https://gitlab.com/gbraad/knowledge-base/blob/master/technology/atomic.md#kubernetes-on-atomic"&gt;Kubernetes on Atomic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Knowledge-base article about &lt;a href="https://gitlab.com/gbraad/knowledge-base/tree/master/technology/kubernetes"&gt;Kubernestes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Hands-on-Lab: &lt;a href="http://gbraad.gitlab.io/kubernetes-handsonlabs/deploying-Kubernetes-on-OpenStack.html"&gt;Kubernetes on OpenStack&lt;/a&gt; (Not all material published yet)&lt;/li&gt;
&lt;li&gt;Deploying Kubernetes &lt;a href="https://blog.vanderkussen.org/deploy-kubernetes-with-ansible-on-atomic.html"&gt;on Atomic hosts&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Containers"/><category term="kubernetes"/><category term="atomic"/><category term="ansible"/><category term="docker"/><category term="centos"/><category term="containers"/></entry><entry><title>Mentors and recommended books</title><link href="https://blog.gbraad.nl/mentors-and-recommended-books.html" rel="alternate"/><published>2016-09-23T00:00:00+08:00</published><updated>2016-09-23T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-09-23:/mentors-and-recommended-books.html</id><summary type="html">&lt;p&gt;As a consultant, an engineer, or just any employee, you are responsible to provide solutions to challenges and issues you face on the workfloor. No no, let me say it this way, you are responsible to come up with ideas to improve a situation, make it more efficient. Or, in …&lt;/p&gt;</summary><content type="html">&lt;p&gt;As a consultant, an engineer, or just any employee, you are responsible to provide solutions to challenges and issues you face on the workfloor. No no, let me say it this way, you are responsible to come up with ideas to improve a situation, make it more efficient. Or, in other words, you have to have a lot of knowledge and a certain way of thinking, being analytical. Simple. But knowledge is something you can develop. And one thing you always have to have on mind. You are responsible for your own personal development...&lt;/p&gt;
&lt;p&gt;I have been employed by two companies that were very strong on this; &lt;a href="http://sogyo.nl"&gt;Sogyo&lt;/a&gt; and &lt;a href="http://thoughtworks.com"&gt;ThoughtWorks&lt;/a&gt;. Both are solution providers, mostly focussed on the software. They both used agile methodologies, development practices, like pair programming, cod reviews, etc. All to ensure the delivery of excellence. Especially this, the delivery of quality and outstanding results, expected that engineers keep themselves up-to-date. They reserved time for this and organized meetups, for personnel and the software development community. I have learned a lot from this, but one thing that both of them did was allowing you a mentor (or sponsor). &lt;/p&gt;
&lt;p&gt;This is not a coach that helps you to find your way around the company in the first few weeks or months, but a person that helps you with career development. It is not that he or she defines targets, but sits down with you and discuss about issues you face, knowledge gaps you might have, etc. My mentor at Sogyo, &lt;a href="https://www.linkedin.com/in/edwinvandillen"&gt;Edwin van Dillen&lt;/a&gt;, has been very inspirational. It made me want to mentor other people... and this what I do now for new contributors to Open Source, and software communities in general. Always, when you can, look for a mentor. Someone who can help you along the way to improve yourself. But improvement is also something you can do yourself. Never stop learning. We call this Continuous Improvement.&lt;/p&gt;
&lt;p&gt;So, one of the things I often get is the question of 'what should I read'? I generally do not promote books that much, as a lot of technology books are dated by the time they are printed. I'd rather refer to a good blog post or living content that gets updated regularly. However, there is always this list of books that are timeless. They have been inspirational or defining in the knowledgd they provide. And this is something I want to start adding to my blog, a review or discussion of a book that helped me in my career. Books that I even bought again either as ePub or PDF after I moved to the other side of the world. I started to compile a list on my &lt;a href="https://gitlab.com/gbraad/knowledge-base/tree/master/books"&gt;Knowledge Base&lt;/a&gt;&lt;a href="https://github.com/gbraad/knowledge-base/tree/master/books"&gt;*&lt;/a&gt; repository as a reference to others, but thought I would be a better idea to post them here with a short intro. So, look for the next post in the category 'Books'.&lt;/p&gt;</content><category term="Misc"/><category term="books"/><category term="programmer"/><category term="developer"/><category term="career development"/><category term="personal development"/><category term="continuous improvement"/><category term="mentor"/></entry><entry><title>Object Design</title><link href="https://blog.gbraad.nl/object-design.html" rel="alternate"/><published>2016-09-23T00:00:00+08:00</published><updated>2016-09-23T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-09-23:/object-design.html</id><summary type="html">&lt;p&gt;One of the books I got recommended early in my career was &lt;a href="https://gitlab.com/gbraad/knowledge-base/blob/master/books/object-design.md" title="Object Design"&gt;Object Design&lt;/a&gt;: Roles, Responsibilities, and Collaborations by Rebecca Wirfs-Brock and Alan McKean. The topic of this book is OOD (Object-Oriented Design). It is a wordy book, which could certainly could have been shorter, but the content makes certainly …&lt;/p&gt;</summary><content type="html">&lt;p&gt;One of the books I got recommended early in my career was &lt;a href="https://gitlab.com/gbraad/knowledge-base/blob/master/books/object-design.md" title="Object Design"&gt;Object Design&lt;/a&gt;: Roles, Responsibilities, and Collaborations by Rebecca Wirfs-Brock and Alan McKean. The topic of this book is OOD (Object-Oriented Design). It is a wordy book, which could certainly could have been shorter, but the content makes certainly up for this issue. This write-up is based on reading this book many years ago, so bear with me if things are not completely in line with the book. Although, the knowledge in this book certainly has contributed to this point-of-view. I currently own a copy of this book as reference in a digital format. &lt;/p&gt;
&lt;p&gt;&lt;img alt="Object Design" src="https://d2arxad8u2l0g7.cloudfront.net/books/1372040740l/179204.jpg"&gt;&lt;/p&gt;
&lt;p&gt;The author, Rebecca Wirfs-Brock, is a software engineer and consultant in Object-Oriented Design, and as the title suggests the book details about the design of your object model and how it interacts with other objects. &lt;/p&gt;
&lt;p&gt;One of the things you will learn when creating software, is that design of the  interactions and relations between objects and classes probably is one of the most important and hardest things. Luckily, software design and development is an evolutionary process. You will not get it right he first time and you also shouldn't aim for this. What can be modeled today as a variable on an object today, might become a class itself in the future. If you would design this from day one, you probably over-design the software and implement functionality that might never be needed.&lt;/p&gt;
&lt;p&gt;What I learned from this book is how this interaction and collaboration between objects happen. Where do I keep the state? who can make a change? If the object can encapsulate it, this is probably where it should live. Ask yourself, why would another object need to know about the information, and whose responsibility is it? The book details as far as I remember CRC-cards (Class Reponsibility Rollaboration) and shows a method to get this clear. In my work I have never created the actual cards, but the concept behind it is very valuable. Get this book and browse through it, keep a copy as a reference. It is well worth it.&lt;/p&gt;
&lt;p&gt;More information about this book can be found in my Knowledge Base &lt;a href="https://gitlab.com/gbraad/knowledge-base/blob/master/books/object-design.md" title="Object Design"&gt;entry&lt;/a&gt;.&lt;/p&gt;</content><category term="Books"/><category term="review"/><category term="summary"/><category term="books"/><category term="recommended"/></entry><entry><title>Document generation using Markdown and Pandoc</title><link href="https://blog.gbraad.nl/document-generation-using-markdown-and-pandoc.html" rel="alternate"/><published>2016-09-13T00:00:00+08:00</published><updated>2016-09-13T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-09-13:/document-generation-using-markdown-and-pandoc.html</id><summary type="html">&lt;p&gt;Maintaining documentation can be an involved process,  especially when different versions and output formats are needed. One of the documents I, and probably you also, have to maintain is your work history or resume/CV. Some while back I changed this document from an OpenOffice document to plain text and …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Maintaining documentation can be an involved process,  especially when different versions and output formats are needed. One of the documents I, and probably you also, have to maintain is your work history or resume/CV. Some while back I changed this document from an OpenOffice document to plain text and ever since, this workflow has influenced how I deal with other documentation.&lt;/p&gt;
&lt;h2&gt;Requirement and timeline&lt;/h2&gt;
&lt;p&gt;If I remember correctly the original version of my resume was written in Microsoft Word. As you can imagine, this limits the usage to Windows as the platform. Small corrections became unnecessarily difficult and painful. Of course I could use CrossOver Office or Wine and install Office 2003. But, this is never a long-term solution. So, I moved to OpenOffice as the &lt;code&gt;.odt&lt;/code&gt; format looked promising. It was easy to use to generate the needed PDF output, but still... the workflow was far from ideal.&lt;/p&gt;
&lt;p&gt;I wanted a workflow in which I can use just plaintext, which could be converted into the final format. Text is easy to index and to story under version management. This lead me to using XML directly and the use of FO (Formatting Objects), and Apache FOP. This was painful, but the results were decent to even very acceptable. It allowed me to describe elements with metadata, such as 'suffix', 'employment-type', etc. And all could be validated and transformed using XSLT. Although the conclusion was that the workflow was slow as there was no preview and transforming just took long. Also, describing elements was not useful as no-one would use the source material directly. Most recruiter use analysis tools that rely on extracting keywords and generate  a profile based on this information. This can lead to incorrect results, but since they analyse hundreds of resumes this seems one of the best methods, besides being introduced by a reference.&lt;/p&gt;
&lt;p&gt;I moved to a simpler approach which allows me to change the document and have a partial, and acceptable  preview. By this time Markdown got more popular and I tried to convert my resume and it seemed like an acceptable approach. Using a standard parser the documents looked OK, but it missed the oomph. Then &lt;code&gt;pandoc&lt;/code&gt; arrived and it changed everything.&lt;/p&gt;
&lt;h2&gt;Markdown&lt;/h2&gt;
&lt;p&gt;Using Markdown I would be able to write the following&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;# _**Gerard Braad**_&lt;/span&gt;


&lt;span class="cp"&gt;## Personal information&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;Chinese&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&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;吉拉德&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;Date&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Birth&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="mi"&gt;22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;February&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1981&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;Nationality&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;Dutch&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;Email&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="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;me&lt;/span&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="n"&gt;gbraad&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nl&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;personal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;email&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;It will get rendered as follows:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="//cdn.gbraad.nl/images/blog/docugen-resume-basic.png"&gt;&lt;/p&gt;
&lt;p&gt;This source is humanly readable, and can be parsed by something like the Webinterface of GitHub into a &lt;a href="https://github.com/gbraad/resume/blob/master/resume.md"&gt;decent representation&lt;/a&gt;. And when using &lt;a href="https://github.com/revolunet/sublimetext-markdown-preview"&gt;Markdown Preview&lt;/a&gt; for Sublime Text, even editing this became a pleasure.&lt;/p&gt;
&lt;h2&gt;Pandoc&lt;/h2&gt;
&lt;p&gt;Now for introducing &lt;a href="http://pandoc.org/"&gt;Pandoc&lt;/a&gt;. This tool is like a Swiss knife for handling documents. It can convert between different formats and allows you to specify a template for specific formats, such as HTML. This tool allows me to use:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;pandoc&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;resume.html&lt;span class="w"&gt; &lt;/span&gt;resume.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will generate a standard HTML output from &lt;code&gt;resume.md&lt;/code&gt; as input. Headings are converted to &lt;code&gt;h6&lt;/code&gt;, &lt;code&gt;h5&lt;/code&gt;, etc. and links become &lt;code&gt;a&lt;/code&gt;, etc.&lt;/p&gt;
&lt;h2&gt;Styling and layout&lt;/h2&gt;
&lt;p&gt;But the beauty shows when a template is used:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;pandoc&lt;span class="w"&gt; &lt;/span&gt;--template&lt;span class="w"&gt; &lt;/span&gt;resume-template.html&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;resume.html&lt;span class="w"&gt; &lt;/span&gt;resume.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will generate a similar output, however the template refers to a stylesheet to style the look of the output. Using a template and stylesheet I am able to format the document to my liking. And since the output of markdown auto-generates names for elements in a consistent way, it is easy to style and format the document.&lt;/p&gt;
&lt;p&gt;Take for instance the photo. Although I personally do not like photos on a resume, it is often requested. Placing it inline with the text does not look very nice.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="//cdn.gbraad.nl/images/blog/docugen-photo-inline.png"&gt;&lt;/p&gt;
&lt;p&gt;Using CSS it is possible to convert the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;# _**Gerard Braad**_&lt;/span&gt;


&lt;span class="cp"&gt;## Personal information&lt;/span&gt;

&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Photo&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="n"&gt;personal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;photo&lt;/span&gt;&lt;span class="p"&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;Chinese&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;name&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;吉拉德&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;With the styling:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;figure&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;float&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;right&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="kt"&gt;px&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;border&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="kt"&gt;px&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;solid&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mh"&gt;#eee&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The output of this will look as follows:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="//cdn.gbraad.nl/images/blog/docugen-photo-float.png"&gt;&lt;/p&gt;
&lt;h2&gt;Containerizing pandoc (software distribution)&lt;/h2&gt;
&lt;p&gt;Pandoc itself is written in Haskell. Although a nice language, it has a different style of programming. This means that few people can contribute, and a distribution like Fedora or Ubuntu can not always provide the latest version. This can be due to possible dependency issues, but also the effort a packager has to put into it. The developer of this tool only provides a .deb package. Since I mostly work on Fedora and CentOS, I had to find an alternative solution to install this tool.&lt;/p&gt;
&lt;p&gt;This is a great use-case for a container, as it consolidates the dependencies of the tool, and will allow me to use the tool as packaged by the developer, on a distribution that would else not be supported. Because I use the provided package I can also file issues against a known version, which can aid in reproducibility.&lt;/p&gt;
&lt;p&gt;This lead to me creating a container called &lt;code&gt;docugen&lt;/code&gt;. It uses &lt;code&gt;pandoc&lt;/code&gt;, &lt;code&gt;jekyll&lt;/code&gt; and &lt;code&gt;pandoc-ruby&lt;/code&gt; to integrate &lt;a href="http://jekyllrb.com/"&gt;Jekyll&lt;/a&gt; with pandoc.&lt;/p&gt;
&lt;p&gt;By setting an alias I can call &lt;code&gt;pandoc&lt;/code&gt; as it is a local command, which actually calls the container:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;pandoc&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;docker run -it --rm -v $PWD:/workspace gbraad/docugen pandoc&amp;#39;&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;pandoc&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;resume.html&lt;span class="w"&gt; &lt;/span&gt;resume.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can find more information about it &lt;a href="https://hub.docker.com/r/gbraad/docugen/"&gt;here&lt;/a&gt;. &lt;/p&gt;
&lt;h2&gt;Automated generation&lt;/h2&gt;
&lt;p&gt;Since creating the containerized version of Pandoc, it was easy to setup an automated process for generation of the resume output. Because I use GitLab for almost all of my projects I only needed to add a CI runner definition to my repository. Below is a snippet of the generation, which publishes to GitLab pages.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.gitlab-ci.yml&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;pages&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;image&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gbraad&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docugen&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;latest&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;script&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;mkdir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&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;pandoc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;html5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;o&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;public&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;html&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;resume&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;md&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="n"&gt;artifacts&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;paths&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="kd"&gt;public&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The result of my resume gets published on GitLab at &lt;a href="http://gbraad.gitlab.io/resume/"&gt;http://gbraad.gitlab.io/resume/&lt;/a&gt; and syncs to GitHub, which hosts it at &lt;a href="https://gbraad.nl/resume"&gt;https://gbraad.nl/resume&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;PDF generation using Pandoc -&amp;gt; LaTeX&lt;/h2&gt;
&lt;p&gt;Pandoc can create nice looking PDF documents by using LaTeX. The handout of my &lt;a href="http://gbraad.gitlab.io/openstack-handsonlabs/"&gt;OpenStack Hands-on-Lab&lt;/a&gt; was produced with this.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;pandoc&lt;span class="w"&gt; &lt;/span&gt;-V&lt;span class="w"&gt; &lt;/span&gt;geometry:margin&lt;span class="o"&gt;=&lt;/span&gt;1in&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;deploying-OpenStack.pdf&lt;span class="w"&gt; &lt;/span&gt;deploying-openstack.md
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Although the results look really good, I had several issues with it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;increased the size of the docugen container by more than a gigabyte.&lt;/li&gt;
&lt;li&gt;issues with properly rendering Chinese&lt;ul&gt;
&lt;li&gt;needed additional installation of modules and fonts&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;would not respect width and margins for pre-formatted blocks&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Likely, all of them could be solved with some smart hacks, but I didn't have the time and interest to learn LaTeX. This felt to me like learning how to use XSLT to transform XML into something meaningful. I still have the packages installed in the container as some documents still use &lt;code&gt;xelatex&lt;/code&gt; for the PDF generation.&lt;/p&gt;
&lt;h2&gt;PDF generation using PhantomJS&lt;/h2&gt;
&lt;p&gt;To solve the issues mentioned above, I now use &lt;code&gt;phantomjs&lt;/code&gt;. &lt;a href="http://phantomjs.org/"&gt;PhantomJS&lt;/a&gt; is a headless browser based on the WebKit rendering engine, and is scriptable with JavaScript. By using this approach I am able to use a single stylesheet to produce the same output on screen as on paper.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;page&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;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;webpage&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;system&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;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;system&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;address&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;system&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;output&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;system&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;viewportSize&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;600&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;paperSize&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;format&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;A4&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;orientation&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;portrait&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;margin&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;1cm&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;system&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;length&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;zoomFactor&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;system&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;page&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;phantom&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To generate a PDF, I call:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;phantomjs&lt;span class="w"&gt; &lt;/span&gt;topdf.js&lt;span class="w"&gt; &lt;/span&gt;resume.html&lt;span class="w"&gt; &lt;/span&gt;resume.pdf
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Page breaks&lt;/h2&gt;
&lt;p&gt;To produce a nicer result, I have also added the following to my stylesheet:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nt"&gt;h1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;page-break-before&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="p"&gt;#&lt;/span&gt;&lt;span class="nn"&gt;gerard-braad&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;text-align&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;center&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="k"&gt;page-break-before&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;avoid&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When printed this inserts a page break before the header starts. So when a new topic starts, but avoids it for the start of the document.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Generating a document from plaintext using Markdown can be beneficial. The source will never suffer from issues with 'being unreadable' or 'deprecated software', and it can easily be indexed. Tracking changes and even publishing a change is not as easy as opening the file on my mobile phone, and commiting it using git. Automatically the result will be published.&lt;/p&gt;
&lt;p&gt;I have moved all my documentation over to plaintext, from the handsonlabs, training and teaching material, schedules, etc. I am still tweaking some of the processes, but the convenience is that a single source material can be used for different outputs. For instance, I publish my articles of this &lt;a href="//gbraad.nl/blog/"&gt;blog&lt;/a&gt; in &lt;a href="https://gitlab.com/gbraad/blog-content/blob/master/SUMMARY.md"&gt;Markdown&lt;/a&gt;, as generated &lt;a href="http://gbraad.gitlab.io/blog-content/"&gt;documents&lt;/a&gt;, and as a &lt;a href="https://gbraad.gitbooks.io/blog-articles/content/"&gt;GitBook&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Do not settle for a solution forever. Over time requirements can change and new insights can be utilized to produce a better solution.&lt;/p&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Source of my resume: &lt;a href="https://gitlab.com/gbraad/resume/"&gt;GitLab&lt;/a&gt;, &lt;a href="https://github.com/gbraad/resume/"&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gbraad.nl/resume/"&gt;Published&lt;/a&gt; version&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Endnotes&lt;/h2&gt;
&lt;p&gt;I looked for some of the older formats and output, but was unable to track them down. I do remember my businesscard was used as a reference for '&lt;a href="http://microformats.org/wiki/selected-test-cases-from-the-web"&gt;microformats&lt;/a&gt;'. And someone tried to introduce an XML standard for resume, called xmlresume if I recall correctly. From experience I could conclude this would not work; no applicant will provide XML and converting it in a tool seems pointless.&lt;/p&gt;
&lt;p&gt;At the moment I am still looking for a nice tool on Android to edit the documents. I use &lt;a href="https://github.com/sheimi/SGit"&gt;SGit&lt;/a&gt; with &lt;a href="http://writeily.me/"&gt;Writeily Pro&lt;/a&gt;, but I am a little disappointed in both tools. Opening a file for viewing in sgit will modify the file, and it does not deal well with resetting this. And Writeily Pro becomes slow over time when editing a file. Closing it and re-opening solves this, but it breaks the writing streak. Sometimes I rather use &lt;a href="http://www.droidedit.com/"&gt;DroidEdit&lt;/a&gt;, as it is just a text editor and does not suffer from this issue. Tools on the iPad, like &lt;a href="http://daedalusapp.com/"&gt;Daedalus Touch&lt;/a&gt; and &lt;a href="https://textasticapp.com/"&gt;Textastic&lt;/a&gt; feel more productive. Suggestions are welcome...&lt;/p&gt;</content><category term="CI / CD"/><category term="markdown"/><category term="documentation"/><category term="pandoc"/><category term="docker"/></entry><entry><title>Highly Available storage using GlusterFS</title><link href="https://blog.gbraad.nl/highly-available-storage-using-glusterfs.html" rel="alternate"/><published>2016-09-12T00:00:00+08:00</published><updated>2016-09-12T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-09-12:/highly-available-storage-using-glusterfs.html</id><summary type="html">&lt;p&gt;In this article I will describe how you can setup a webserver environment with
Highly Available (HA) storage, provided by GlusterFS. We will be setting up a
simple environment in which storage between two webservers needs to be replicated.&lt;/p&gt;
&lt;p&gt;GlusterFS is a scalable network filesystem suitable for data-intensive tasks. It …&lt;/p&gt;</summary><content type="html">&lt;p&gt;In this article I will describe how you can setup a webserver environment with
Highly Available (HA) storage, provided by GlusterFS. We will be setting up a
simple environment in which storage between two webservers needs to be replicated.&lt;/p&gt;
&lt;p&gt;GlusterFS is a scalable network filesystem suitable for data-intensive tasks. It
is free and open source software and can utilize common off-the-shelf hardware.
To learn more, please see the Gluster project &lt;a href="http://www.gluster.org/"&gt;home page&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;You will need two servers available, each with a dedicated disk for storage,
such as &lt;code&gt;/dev/vdb&lt;/code&gt; or &lt;code&gt;/dev/sdb&lt;/code&gt;. I will be using Fedora 24, which of writing
is the latest version.&lt;/p&gt;
&lt;p&gt;The following needs to be installed on both servers:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;dnf&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;glusterfs-server&lt;span class="w"&gt; &lt;/span&gt;xfsprogs
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This includes the server component for the distributed filesystem, and the tools
needed to format the disk we will use to store the files. Gluster recommends to
use XFS as the filesystem.&lt;/p&gt;
&lt;p&gt;We will assume for this article, that the machines will be running Apache. If
this is not installed already, you can do the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;dnf&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;httpd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Hostnames&lt;/h2&gt;
&lt;p&gt;Make sure the hostnames and IP addresses of the servers are known to each other.
For this, check the content of &lt;code&gt;/etc/hosts&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;code&gt;/etc/hosts&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="mf"&gt;37.153.173.244&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;server01&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;public&lt;/span&gt;
&lt;span class="mf"&gt;37.153.173.245&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;server01&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;public&lt;/span&gt;
&lt;span class="mf"&gt;10.3.0.44&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;server01&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt;
&lt;span class="mf"&gt;10.3.0.45&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;server02&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;private&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note: these servers have two interfaces, Although this is not necessary, it is
strongly recommended to separate the traffic from the web and what you use for
the storage network. In our case, the web-facing IP addresses have not been
load-balanced yet. This is a topic for future articles.&lt;/p&gt;
&lt;h2&gt;Prepare disks&lt;/h2&gt;
&lt;p&gt;Since Gluster relies on extended file attributes (xattr), we will need to increase
the inode size when formatting the disks.&lt;/p&gt;
&lt;p&gt;Perform on the following on both the servers&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;mkfs.xfs&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;size&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="m"&gt;512&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/dev/vdb
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;dev&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;vdb&lt;/span&gt;&lt;span class="w"&gt;               &lt;/span&gt;&lt;span class="nx"&gt;isize&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;agcount&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;agsize&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;3276800&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;blks&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="nx"&gt;sectsz&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nx"&gt;attr&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;projid32bit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="nx"&gt;crc&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;finobt&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;sparse&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="nx"&gt;bsize&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nx"&gt;blocks&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;13107200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;imaxpct&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="nx"&gt;sunit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="nx"&gt;swidth&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;blks&lt;/span&gt;
&lt;span class="nx"&gt;naming&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="nx"&gt;bsize&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nx"&gt;ascii&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;ci&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ftype&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;internal&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="nx"&gt;bsize&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nx"&gt;blocks&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;6400&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="w"&gt;         &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt;                       &lt;/span&gt;&lt;span class="nx"&gt;sectsz&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;512&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nx"&gt;sunit&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;blks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;lazy&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;count&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="nx"&gt;realtime&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="nx"&gt;none&lt;/span&gt;&lt;span class="w"&gt;                   &lt;/span&gt;&lt;span class="nx"&gt;extsz&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="nx"&gt;blocks&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;rtextents&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we need to create a mountpoint for the filesystem. We will use
&lt;code&gt;/data/var-www/brick01&lt;/code&gt; on &lt;code&gt;server01&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/data/var-www/brick01
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/dev/vdb /data/var-www/brick01 xfs defaults 1 2&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/fstab
$&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;and &lt;code&gt;/data/var-www/brick02&lt;/code&gt; on &lt;code&gt;server02&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/data/var-www/brick02
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;/dev/vdb /data/var-www/brick02 xfs defaults 1 2&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/fstab
$&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Setup Gluster&lt;/h2&gt;
&lt;p&gt;You will now create a cluster of Gluster servers, which means that we will create
a trust between the two nodes. But before we can do this, we need to make sure
the Gluster daemon is running on the nodes. Perform the following commands on
both of the nodes:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;glusterd
$&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;glusterd
$&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;status&lt;span class="w"&gt; &lt;/span&gt;glusterd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we need to create the trusted connection. The following commands will only
need to be used on one of the nodes. In my case, this will be &lt;code&gt;server01&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;gluster&lt;span class="w"&gt; &lt;/span&gt;peer&lt;span class="w"&gt; &lt;/span&gt;probe&lt;span class="w"&gt; &lt;/span&gt;server02-private
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;peer probe: success.
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note: the hostname here refers to the private IP address. This is not the same
range as the public network. For security purposes you will likely separate the
traffic.&lt;/p&gt;
&lt;p&gt;You can verify is the trust exists by running:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;gluster&lt;span class="w"&gt; &lt;/span&gt;peer&lt;span class="w"&gt; &lt;/span&gt;status
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Number of Peers: 1

Hostname: server02-private
Uuid: af523e9b-4257-485d-aa45-ebd24f115c42
State: Peer in Cluster (Connected)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you would run this command also on &lt;code&gt;server02&lt;/code&gt;, you would get a similar result:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Number of Peers: 1

Hostname: server01-private
Uuid: 74c77082-b62c-4cc4-b33f-02de36083990
State: Peer in Cluster (Connected)
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Create Gluster volume&lt;/h2&gt;
&lt;p&gt;In case of a failure, we do not want our data to be unavailable. Therefore we
need to have two copies of our data, and we do this by creating a replicated
volume.&lt;/p&gt;
&lt;p&gt;This command will only need to be run on one node, as Gluster will take care of
the related nodes.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;gluster&lt;span class="w"&gt; &lt;/span&gt;volume&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;var-www&lt;span class="w"&gt; &lt;/span&gt;replica&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;server01-private:/data/var-www/brick01/volume&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;          &lt;/span&gt;server02-private:/data/var-www/brick02/volume
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;volume&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;create&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;www&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;success&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;please&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;volume&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;access&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;gluster&lt;span class="w"&gt; &lt;/span&gt;volume&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;var-www
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;volume&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;start&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;www&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;success&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;gluster&lt;span class="w"&gt; &lt;/span&gt;volume&lt;span class="w"&gt; &lt;/span&gt;info
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;Volume&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;www&lt;/span&gt;
&lt;span class="nx"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Replicate&lt;/span&gt;
&lt;span class="nx"&gt;Volume&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e91014ca&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;f98c&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="nx"&gt;e5&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="nx"&gt;e75&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;de4d2e65f569&lt;/span&gt;
&lt;span class="nx"&gt;Status&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Started&lt;/span&gt;
&lt;span class="nx"&gt;Number&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Bricks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;
&lt;span class="nx"&gt;Transport&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tcp&lt;/span&gt;
&lt;span class="nx"&gt;Bricks&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="nx"&gt;Brick1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;server01&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;www&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;brick01&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;volume&lt;/span&gt;
&lt;span class="nx"&gt;Brick2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;server02&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;private&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;www&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;brick02&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;volume&lt;/span&gt;
&lt;span class="nx"&gt;Options&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Reconfigured&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="nx"&gt;transport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;address&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;family&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;inet&lt;/span&gt;
&lt;span class="nx"&gt;performance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;readdir&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;ahead&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;
&lt;span class="nx"&gt;nfs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;disable&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;on&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Mount Gluster volume&lt;/h2&gt;
&lt;p&gt;Before you can mount the volume on &lt;code&gt;/var/www&lt;/code&gt; to share the webpages, we need to
move the original &lt;code&gt;/var/www&lt;/code&gt; out of the way and create a new directory to mount.
Perform the following commands on both the servers:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;stop&lt;span class="w"&gt; &lt;/span&gt;httpd
$&lt;span class="w"&gt; &lt;/span&gt;mv&lt;span class="w"&gt; &lt;/span&gt;/var/www&lt;span class="o"&gt;{&lt;/span&gt;,.orig&lt;span class="o"&gt;}&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;/var/www
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now that we have the mountpoint, we can add an entry to &lt;code&gt;fstab&lt;/code&gt; to deal with
mounting of our volume. On &lt;code&gt;server01&lt;/code&gt; you need to do the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;server01-private:/var-www /var/www glusterfs defaults,_netdev,fetch-attempts=3 0 0&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/fstab
$&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;-a
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And on &lt;code&gt;server02&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;server02-private:/var-www /var/www glusterfs defaults,_netdev,fetch-attempts=3 0 0&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/fstab
$&lt;span class="w"&gt; &lt;/span&gt;mount&lt;span class="w"&gt; &lt;/span&gt;-a
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now the volume has been mounted and replication is available. We use &lt;code&gt;_netdev&lt;/code&gt;
because network needs to be up before we can use this filesystem, and &lt;code&gt;fetch_attempts&lt;/code&gt;
will deal with the volume information in case of a failure. Since we have multiple
IP address, this is a suggested setting.&lt;/p&gt;
&lt;h2&gt;Test replication&lt;/h2&gt;
&lt;p&gt;On &lt;code&gt;server01&lt;/code&gt; you can do the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/var/www/html
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Hello, World!&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;/var/www/html/index.html
$&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;httpd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If you would now open the web facing IP address, you should see the message:
&lt;code&gt;Hello, World!&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note: if you have issues opening the page, or the default Fedora test page gets
returned, you might have SELinux enabled. In this case, you need to turn on the
following boolean:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;setsebool&lt;span class="w"&gt; &lt;/span&gt;-P&lt;span class="w"&gt; &lt;/span&gt;httpd_use_fusefs&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;which will allow Apache to use the FUSE filesystem mount as used by GlusterFS.&lt;/p&gt;
&lt;p&gt;Now, on &lt;code&gt;server02&lt;/code&gt; you can check the content of the folder:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ls&lt;span class="w"&gt; &lt;/span&gt;/var/www/html
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;and you would see an &lt;code&gt;index.html&lt;/code&gt; file. Now start Apache and you will see that
the content is also served from this server.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;httpd
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Using GlusterFS it is easy to setup an environment that can handle issues with
storage availability. You now have a replicate volume that is available on two
servers. Actions we take on each of these servers, will be replicated to the
other server.&lt;/p&gt;
&lt;p&gt;In this case we have setup the servers to handle both the storage and act as a
client to read these files. More advanced are available and are described in the
&lt;a href="http://gluster.readthedocs.io/en/latest/"&gt;documentation&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Next step&lt;/h2&gt;
&lt;p&gt;Now that we have implemented replicated storage for our webservers, we need to
provide a HA solution to deal with the traffic on the webfacing IP addresses.
In an OpenStack environment you could use Neutron to setup a loadbalancer and 
health monitor for the two servers. How to set this up in described in the
&lt;a href="./building-a-multi-tier-application-using-openstack-packstack.html"&gt;following article&lt;/a&gt;.
However, you can also do so with HAProxy and a failover mechanism, which will be
the topic of a future article.&lt;/p&gt;
&lt;p&gt;If you have questions please let me know on Twitter at &lt;a href="http://twitter.com/gbraad"&gt;@gbraad&lt;/a&gt; or by email.&lt;/p&gt;</content><category term="High Availability"/><category term="gluster"/><category term="high availability"/><category term="web"/><category term="storage"/></entry><entry><title>Highlighting of Code and Text</title><link href="https://blog.gbraad.nl/highlighting-of-code-and-text.html" rel="alternate"/><published>2016-09-09T00:00:00+08:00</published><updated>2016-09-09T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-09-09:/highlighting-of-code-and-text.html</id><summary type="html">&lt;p&gt;Code is read more often than it is written. Nothing is truer than this statement. This means that when writing code it is important to have a good idea of what you are doing. Write clean code, which is simple or easy to reason about. Since if you can't explain …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Code is read more often than it is written. Nothing is truer than this statement. This means that when writing code it is important to have a good idea of what you are doing. Write clean code, which is simple or easy to reason about. Since if you can't explain it, how could others even understand it well. Syntax highlighting of code can help. With this, certain keywords or structure get emphasized by using a color. I do not think it is an ideal solution, but subconsciously it seems I focus more on the code. Likely, the colors themselves are pleasing to look at.&lt;/p&gt;
&lt;h2&gt;Pleasant to the eyes&lt;/h2&gt;
&lt;p&gt;Perhaps because of this last, I tend to always implement or set the &lt;a href="https://github.com/chriskempson/tomorrow-theme"&gt;Tomorrow Theme&lt;/a&gt; for my color scheme, and specifically the &lt;a href="https://github.com/chriskempson/tomorrow-theme#tomorrow-night-bright"&gt;Night Bright&lt;/a&gt; variant. Below you can find an example, as I also enabled it on my blog by implementing a Pygments style.&lt;/p&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;server.js&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="s1"&gt;&amp;#39;use strict&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="c1"&gt;// get port from environment settings for deployment on Heroku&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;EXPRESS_PORT&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="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OPENSHIFT_NODEJS_PORT&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="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;PORT&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="mf"&gt;4000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;EXPRESS_IPADDR&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="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;OPENSHIFT_NODEJS_IP&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="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;IPADDR&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;&amp;#39;127.0.0.1&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;EXPRESS_ROOT&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="nx"&gt;__dirname&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;startExpress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ipaddr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;express&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="nx"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;express&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;app&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="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;use&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;root&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;listen&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ipaddr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;Listening on %s:%d&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="nx"&gt;ipaddr&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;port&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;startExpress&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;EXPRESS_ROOT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;EXPRESS_PORT&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;EXPRESS_IPADDR&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="" src="http://cdn.gbraad.nl/images/blog/javascript-syntax-highlighting.png"&gt;&lt;/p&gt;
&lt;h2&gt;Implementations&lt;/h2&gt;
&lt;p&gt;Chris Kempson now has a new color scheme called 'base16`and it has a '&lt;a href="https://chriskempson.github.io/base16/#tomorrow"&gt;Tomorrow&lt;/a&gt;' variant. It must be the name as I always install 'Tomorrow' first. Here are some of the Night Bright variants I have made over the years:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/gbraad/pygments-style-tomorrownightbright"&gt;Pygments&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/gbraad/chrome-devtools-tomorrow-night-bright-theme"&gt;Chrome DevTools&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/gbraad/brackets-themes-TomorrowNightBright"&gt;Brackets&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/codemirror/CodeMirror/blob/master/theme/tomorrow-night-bright.css"&gt;CodeMirror&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;...&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;How about language&lt;/h2&gt;
&lt;p&gt;Since my wife and I are very involved in teaching, I have also experimented with the idea of using word or word-class highlighting for English. The results are that it can actually help. Words that need to be stressed, or emphasized, can be highlighted in a different color. Think of words like 'very', 'never', etc. Some of this can be automated, as can be seen in the following examples:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://nlp-compromise.github.io/website/"&gt;NLP-compromise&lt;/a&gt;, Text Parsing&lt;/li&gt;
&lt;li&gt;&lt;a href="http://evanhahn.github.io/English-text-highlighting/"&gt;English-text-highlighting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://english.edward.io/"&gt;English syntax highlighter&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/loadfive/Knwl.js"&gt;Knwl.js&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These implementations range from simple hard-coded word matching, to actual Natural Language Processing.&lt;/p&gt;
&lt;h2&gt;Example&lt;/h2&gt;
&lt;p&gt;Take for instance the following example of &lt;code&gt;Alice In Wonderland - Down the Rabbit Hole&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;"&lt;/strong&gt;There was nothing so very remarkable in that; nor did Alice think it so very much out of the way to hear the Rabbit say to itself, &lt;em&gt;'Oh dear! Oh dear! I shall be late!'&lt;/em&gt; (when she thought it over afterwards, it occurred to her that she ought to have wondered at this, but at the time it all seemed quite natural); but when the Rabbit actually took a watch out of its waistcoat-pocket, and looked at it, and then hurried on, Alice started to her feet, for it flashed across her mind that she had never before seen a rabbit with either a waistcoat-pocket, or a watch to take out of it, and burning with curiosity, she ran across the field after it, and fortunately was just in time to see it pop down a large rabbit-hole under the hedge.&lt;strong&gt;"&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;When &lt;code&gt;adverb&lt;/code&gt;, &lt;code&gt;verb&lt;/code&gt;, &lt;code&gt;conjunction&lt;/code&gt;, etc. are highlighted, the text will look as follows:&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="http://cdn.gbraad.nl/images/blog/english-text-highlighting.png"&gt;&lt;/p&gt;
&lt;p&gt;Note: this is taken from &lt;a href="https://english.edward.io/"&gt;English syntax highlighter&lt;/a&gt;. Try and see for yourself if it can help.&lt;/p&gt;
&lt;h2&gt;Chinese&lt;/h2&gt;
&lt;p&gt;Highlighting does not only work well for English. Chinese for instance is a tonal language. Which means that a pronounciation of a character can have a different tone for a different meaning. When not proprerly mastered, this can lead to a lot of confusion or embarrassment. For learner's of Chinese it is actually common to highlight the tones. An example of this is shown here:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;welcome

v.t.
欢迎 huānyíng;  迎接 yíngjiē

Welcome home again!

欢迎你又回家了!

Huānyíng nǐ yòu huíjiā le!
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;img alt="" src="http://cdn.gbraad.nl/images/blog/chinese-tone-highlighting.png"&gt;&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Highlighting can serve different purposes. I can not recall that highlighting actually helped me to write clean or correct code, or that it even prevented me from making a mistake or typo. However, it can certainly provide a plesant feeling, in which you can 'feel good' about your code in another way. For languages, such as English and Chinese, it can assist with the learning process.&lt;/p&gt;</content><category term="Misc"/><category term="highlighting"/><category term="code"/><category term="language"/></entry><entry><title>non-root user inside a Docker container</title><link href="https://blog.gbraad.nl/non-root-user-inside-a-docker-container.html" rel="alternate"/><published>2016-09-08T00:00:00+08:00</published><updated>2016-09-08T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-09-08:/non-root-user-inside-a-docker-container.html</id><summary type="html">&lt;p&gt;One of the things that you notice when using Docker, is that all commands you run from the &lt;code&gt;Dockerfile&lt;/code&gt; with &lt;code&gt;RUN&lt;/code&gt; or &lt;code&gt;CMD&lt;/code&gt; are performed as the &lt;code&gt;root&lt;/code&gt; user. This is not only a bad security practice for running internet facing services, it might even prevent certain applications from working …&lt;/p&gt;</summary><content type="html">&lt;p&gt;One of the things that you notice when using Docker, is that all commands you run from the &lt;code&gt;Dockerfile&lt;/code&gt; with &lt;code&gt;RUN&lt;/code&gt; or &lt;code&gt;CMD&lt;/code&gt; are performed as the &lt;code&gt;root&lt;/code&gt; user. This is not only a bad security practice for running internet facing services, it might even prevent certain applications from working properly. So, how do you run commands as a non-root user? For people using Red Hat-based systems, such as Fedora or CentOS I will explain how you can do this.&lt;/p&gt;
&lt;h2&gt;Let's begin&lt;/h2&gt;
&lt;p&gt;Let's say you have a &lt;code&gt;Dockerfile&lt;/code&gt; using Fedora as a base:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;FROM fedora:24
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Create user&lt;/h2&gt;
&lt;p&gt;Before we can use a different user, we need to create one:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;RUN adduser user
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Run as user&lt;/h2&gt;
&lt;p&gt;Now you can run commands as this user by doing:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;RUN su - user -c &amp;quot;touch me&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The container start process can be changed to:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;CMD [&amp;quot;su&amp;quot;, &amp;quot;-&amp;quot;, &amp;quot;user&amp;quot;, &amp;quot;-c&amp;quot;, &amp;quot;/bin/bash&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This way, a &lt;code&gt;bash&lt;/code&gt; shell will open as the user.&lt;/p&gt;
&lt;h2&gt;Allow &lt;code&gt;sudo&lt;/code&gt; usage&lt;/h2&gt;
&lt;p&gt;Since you are running a normal user, it might be handy to install the following package inside the container:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;RUN dnf install -y sudo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will allow you to use &lt;code&gt;sudo&lt;/code&gt; to perform actions as the root user:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;RUN echo &amp;quot;user ALL=(root) NOPASSWD:ALL&amp;quot; &amp;gt; /etc/sudoers.d/user &amp;amp;&amp;amp; \
    chmod 0440 /etc/sudoers.d/user
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Final &lt;code&gt;Dockerfile&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;To combine all of this, your &lt;code&gt;Dockerfile&lt;/code&gt; would look as follows:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;Dockerfile&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;FROM fedora:24

RUN dnf install -y sudo &amp;amp;&amp;amp; \
    adduser user &amp;amp;&amp;amp; \
    echo &amp;quot;user ALL=(root) NOPASSWD:ALL&amp;quot; &amp;gt; /etc/sudoers.d/user &amp;amp;&amp;amp; \
    chmod 0440 /etc/sudoers.d/user

RUN su - user -c &amp;quot;touch mine&amp;quot;

CMD [&amp;quot;su&amp;quot;, &amp;quot;-&amp;quot;, &amp;quot;user&amp;quot;, &amp;quot;-c&amp;quot;, &amp;quot;/bin/bash&amp;quot;]
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Result&lt;/h2&gt;
&lt;p&gt;Building this container is simple:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;build&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;Step&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&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;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fedora&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;f9873d530588&lt;/span&gt;
&lt;span class="n"&gt;Step&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&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;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dnf&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;adduser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;user ALL=(root) NOPASSWD:ALL&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sudoers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="n"&gt;chmod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mo"&gt;0440&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sudoers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Using&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cache&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mo"&gt;05&lt;/span&gt;&lt;span class="n"&gt;c3f3c7e9fc&lt;/span&gt;
&lt;span class="n"&gt;Step&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&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;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;su&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;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;touch me&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Running&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;584&lt;/span&gt;&lt;span class="n"&gt;ab0ad025b&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;66&lt;/span&gt;&lt;span class="n"&gt;ea558b9855&lt;/span&gt;
&lt;span class="n"&gt;Removing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;intermediate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;584&lt;/span&gt;&lt;span class="n"&gt;ab0ad025b&lt;/span&gt;
&lt;span class="n"&gt;Step&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&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;CMD&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;su&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;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bash&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Running&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;780e0&lt;/span&gt;&lt;span class="n"&gt;ccd5f61&lt;/span&gt;
&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;---&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b19a10012b28&lt;/span&gt;
&lt;span class="n"&gt;Removing&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;intermediate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;container&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;780e0&lt;/span&gt;&lt;span class="n"&gt;ccd5f61&lt;/span&gt;
&lt;span class="n"&gt;Successfully&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;built&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;b19a10012b28&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Running it will produce the following result:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;rm&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="mi"&gt;@48&lt;/span&gt;&lt;span class="n"&gt;add6313ab6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ls&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;al&lt;/span&gt;
&lt;span class="n"&gt;total&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;
&lt;span class="n"&gt;drwx&lt;/span&gt;&lt;span class="o"&gt;------&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Sep&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;08&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;drwxr&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;xr&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4096&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Sep&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;08&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;46&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;..&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rw&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;May&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bash_logout&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rw&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;193&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;May&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bash_profile&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rw&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;231&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;May&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;17&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bashrc&lt;/span&gt;
&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rw&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;rw&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Sep&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;08&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;me&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="mi"&gt;@48&lt;/span&gt;&lt;span class="n"&gt;add6313ab6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;pwd&lt;/span&gt;
&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;home&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="mi"&gt;@48&lt;/span&gt;&lt;span class="n"&gt;add6313ab6&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Base images&lt;/h2&gt;
&lt;p&gt;If you are setting up base images for re-use, it can be handy to use the &lt;code&gt;USER&lt;/code&gt; keyword. This will run all the following commqnds as a particalur. Lets say, you want to use a service, which is Node.JS based, you can create the following &lt;code&gt;Dockerfile&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;centos&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;
&lt;span class="n"&gt;MAINTAINER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Gerard&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Braad&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;me&lt;/span&gt;&lt;span class="nv"&gt;@gbraad&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nl&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;update&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;and&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dependencies&lt;/span&gt;
&lt;span class="n"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;update&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;yum&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nodejs&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;npm&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Add&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;UID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;GID&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;home&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;
&lt;span class="n"&gt;RUN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;groupadd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;useradd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1000&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;sbin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nologin&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;&amp;quot;App user&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;chmod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;755&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;Set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;working&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;directory&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;home&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;directory&lt;/span&gt;
&lt;span class="n"&gt;WORKDIR&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;

&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Specify&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;user&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;execute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;all&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;commands&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;below&lt;/span&gt;
&lt;span class="k"&gt;USER&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can then use this container as a base for NodeJS based applications. You copy the application to &lt;code&gt;/app&lt;/code&gt; and when commands are run, they will use the user named &lt;code&gt;user&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I hope this has been of some help to you. You can &lt;a href="https://twitter.com/gbraad"&gt;follow me&lt;/a&gt; on Twitter or leave a comment below.&lt;/p&gt;</content><category term="Containers"/><category term="docker"/><category term="fedora"/></entry><entry><title>Deployment of Ceph using custom Atomic images</title><link href="https://blog.gbraad.nl/deployment-of-ceph-using-custom-atomic-images.html" rel="alternate"/><published>2016-09-07T00:00:00+08:00</published><updated>2016-09-07T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-09-07:/deployment-of-ceph-using-custom-atomic-images.html</id><summary type="html">&lt;p&gt;As part of providing a scalable infrastructure, many components in the datacenter are now moving towards software-based solutions, such as SDN (for networking) and SDS (for storage). Ceph one of these projects to provide a scalable, software-based software solution. It is often used in conjuction with OpenStack for storing disk …&lt;/p&gt;</summary><content type="html">&lt;p&gt;As part of providing a scalable infrastructure, many components in the datacenter are now moving towards software-based solutions, such as SDN (for networking) and SDS (for storage). Ceph one of these projects to provide a scalable, software-based software solution. It is often used in conjuction with OpenStack for storing disk images and block access for volumes. Setting up an environment usually involves installing a base operating system and configuring the machine to join a storage cluster. In this article I will setup a Atomic based image that allows for fast deployment of Ceph cluster. This is not a recommended solution, but an exercise that shows how to cutomize Atomic Host and using Ansible to standup a Ceph cluster.&lt;/p&gt;
&lt;h2&gt;Components&lt;/h2&gt;
&lt;p&gt;&lt;a href="http://www.projectatomic.io/"&gt;Atomic&lt;/a&gt;&lt;a href="https://gitlab.com/gbraad/knowledge-base/blob/master/technology/atomic.md"&gt;*&lt;/a&gt; Host is a new generation of Operating Systems that used to create an immutable infrastructure to deploy and scale containerized applications. For this, it uses a technology called &lt;a href="https://ostree.readthedocs.io/en/latest/"&gt;OSTree&lt;/a&gt;&lt;a href="https://gitlab.com/gbraad/knowledge-base/blob/master/technology/ostree.md"&gt;*&lt;/a&gt; which is a git-like model for dealing with filesystem trees. It allows different filesystems to exist alongside of each other. If a filesystem is not booting properly, it is possible to move back to the previous state.&lt;/p&gt;
&lt;p&gt;&lt;a href="http://ceph.com/"&gt;Ceph&lt;/a&gt;&lt;a href="https://gitlab.com/gbraad/knowledge-base/blob/master/technology/ceph.md"&gt;*&lt;/a&gt; is a distributed storage solution which provides Object Storage, Block Storage and FIlesystem access. Ceph comes with several software components which provides a role in the cluster, such as a monitor or storage daemon.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.ansible.com/"&gt;Ansible&lt;/a&gt;&lt;a href="https://gitlab.com/gbraad/knowledge-base/blob/master/technology/ansible.md"&gt;*&lt;/a&gt; is a configuration and system management tool which for example can do multi-node deployment of software or execution of commands&lt;/p&gt;
&lt;p&gt;Although Atomic Hosts are primarily used to deploy Docker and Kubernetes environments, or even containerized versions of the Ceph daemons, I will show how it is possible to use ostree to deploy the Ceph software on nodes, with minimal effort. Ansible is used to send commands to these nodes and finalize the configuration.&lt;/p&gt;
&lt;h2&gt;Preparation&lt;/h2&gt;
&lt;p&gt;For this setup we will use about 7 machines. To simplify testing, I have performed these actions on an OpenStack environment, such as &lt;a href="https://www.dreamhost.com/cloud/computing/"&gt;DreamCompute&lt;/a&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;1 controller and compose node, running Fedora 24 with IP address 10.3.0.2&lt;/li&gt;
&lt;li&gt;3 Ceph monitors, running CentOS Atomic with IP addresses 10.3.0.3-5&lt;/li&gt;
&lt;li&gt;3 Ceph storage nodes, running CentOS Atomic with IP addresses 10.3.0.6-8 and attached storage volume at &lt;code&gt;/dev/vdb&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;To deploy you can start with setting up the Fedora node.&lt;/p&gt;
&lt;h3&gt;Install controller&lt;/h3&gt;
&lt;p&gt;To deploy our environment we setup a controller node which can access the other nodes in the network using SSH. In our case we will use Fedora 24.  After installing the operating system, perform the following commands:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;dnf&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;-y
$&lt;span class="w"&gt; &lt;/span&gt;dnf&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt;  &lt;/span&gt;ansible&lt;span class="w"&gt; &lt;/span&gt;rpm-ostree&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;python
$&lt;span class="w"&gt; &lt;/span&gt;ssh-keygen
$&lt;span class="w"&gt; &lt;/span&gt;cat&lt;span class="w"&gt; &lt;/span&gt;~/.ssh/id_rsa.pub
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The last two commands generate an SSH authentication key and will show the result on the command line.&lt;/p&gt;
&lt;h3&gt;Atomic nodes&lt;/h3&gt;
&lt;p&gt;The installation media for Atomic can be found at the main project page. It comes in two different distribution types, CentOS or Fedora. For this article I used CentOS, and downloaded it from the following location:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;http://http://cloud.centos.org/centos/7/atomic/images/CentOS-Atomic-Host-7-GenericCloud.qcow2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;and uploaded it to my OpenStack environment with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;image&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;CentOS7 Atomic&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--progress&lt;span class="w"&gt; &lt;/span&gt;--file&lt;span class="w"&gt; &lt;/span&gt;CentOS-Atomic-Host-7-GenericCloud.qcow2&lt;span class="w"&gt; &lt;/span&gt;--disk-format&lt;span class="w"&gt; &lt;/span&gt;qcow2&lt;span class="w"&gt; &lt;/span&gt;--container-format&lt;span class="w"&gt; &lt;/span&gt;bare&lt;span class="w"&gt; &lt;/span&gt;--property&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;os_distro&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;centos
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After this, I created six identical machines, with provisioning a predefined SSH key with cloud-init which we made on the controller node. If you are not using OpenStack, you have to use a cloud-init configdrive to configure the node with the SSH key. This process is described &lt;a href="http://www.projectatomic.io/docs/quickstart/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The storage nodes need to have to configured with a dedicated volume for use with the &lt;code&gt;osd&lt;/code&gt; storage daemon of Ceph. By creating a volume and attaching them to the node, these will be identified as &lt;code&gt;/dev/vdb&lt;/code&gt;. There is no need to prepapre a filesystem on them. This will be handles by the deployment scripts.&lt;/p&gt;
&lt;p&gt;Note: if you want to upload disk images to DreamCompute or other Ceph-backed OpenStack image services, you have to convert the disk image to raw format first. An example of this can be found in &lt;a href="https://gitlab.com/gbraad/knowledge-base/blob/master/technology/openstack/client.md#examples"&gt;an example&lt;/a&gt; for use of the OpenStack client.&lt;/p&gt;
&lt;h2&gt;Compose tree&lt;/h2&gt;
&lt;p&gt;On the controller node we will create an ostree that will be used to setup the Ceph software on the Atomic host nodes. This process involves creating a definition for a filesystem tree that uses the base defintion of CentOS Atomic with the additional packages from the CentOS-specific Ceph packages.&lt;/p&gt;
&lt;h3&gt;Atomic definition&lt;/h3&gt;
&lt;p&gt;We will clone the git repositiory containing the base definition:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/workspace
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/workspace
$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;https://github.com/CentOS/sig-atomic-buildscripts.git&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;-b&lt;span class="w"&gt; &lt;/span&gt;downstream&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;--depth&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;ceph-atomic
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Inside this folder you can add a RPM repository file where the Ceph packages are located:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ceph-atomic/centos-ceph-jewel.repo&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;[centos-ceph-jewel]&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;CentOS-7 - Ceph Jewel&lt;/span&gt;
&lt;span class="na"&gt;baseurl&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;http://buildlogs.centos.org/centos/7/storage/x86_64/ceph-jewel/&lt;/span&gt;
&lt;span class="na"&gt;gpgcheck&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;0&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And then we will define an Atomic host for Ceph-Jewel and specify which additional repositories and packages are used:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;ceph-atomic/ceph-atomic-host.json&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;include&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;centos-atomic-host.json&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ref&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;centos-atomic-host/7/x86_64/ceph-jewel&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;automatic_version_prefix&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;2016.0&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;repos&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;centos-ceph-jewel&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;epel&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;packages&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ceph&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ntp&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ntpdate&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;hdparm&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;autogen-libopts&amp;quot;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note: with &lt;code&gt;include&lt;/code&gt; we base our image off an existing definition. In our case this will simplify the process, but it also means we will end up with an image with unneeded components. For our test this is not an issue.&lt;/p&gt;
&lt;p&gt;After this, the defintion for the Ceph-specific Atomic host is finished. Before we can compose the ostree, we have to create and initialize the repository directory:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;/srv/repo
$&lt;span class="w"&gt; &lt;/span&gt;ostree&lt;span class="w"&gt; &lt;/span&gt;--repo&lt;span class="o"&gt;=&lt;/span&gt;/srv/repo&lt;span class="w"&gt; &lt;/span&gt;init&lt;span class="w"&gt; &lt;/span&gt;--mode&lt;span class="o"&gt;=&lt;/span&gt;archive-z2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;When you perform the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;rpm-ostree&lt;span class="w"&gt; &lt;/span&gt;compose&lt;span class="w"&gt; &lt;/span&gt;tree&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;--repo&lt;span class="o"&gt;=&lt;/span&gt;/srv/repo&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;./ceph-atomic/ceph-atomic-host.json
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;packages will be fetched and committed to an ostree in &lt;code&gt;/srv/repo&lt;/code&gt;. After this, you will have a filesystem tree which can be served from a webserver, to be used by Atomic hosts.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/srv/repo
$&lt;span class="w"&gt; &lt;/span&gt;python&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;SimpleHTTPServer
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will serve the content from &lt;code&gt;/srv/repo&lt;/code&gt; on the endpoint &lt;code&gt;http://10.3.0.2:8000/&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Deployment&lt;/h2&gt;
&lt;p&gt;To get the Atomic hosts to use the tree, the following commands will have to be used to provision the Ceph-based filesystem tree:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;su&lt;span class="w"&gt; &lt;/span&gt;-
$&lt;span class="w"&gt; &lt;/span&gt;setenforce&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;ostree&lt;span class="w"&gt; &lt;/span&gt;remote&lt;span class="w"&gt; &lt;/span&gt;add&lt;span class="w"&gt; &lt;/span&gt;--set&lt;span class="o"&gt;=&lt;/span&gt;gpg-verify&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;atomic-ceph&lt;span class="w"&gt; &lt;/span&gt;http://10.3.0.2:8000/
$&lt;span class="w"&gt; &lt;/span&gt;rpm-ostree&lt;span class="w"&gt; &lt;/span&gt;rebase&lt;span class="w"&gt; &lt;/span&gt;atomic-ceph:centos-atomic-host/7/x86_64/ceph-jewel
$&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;reboot
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This is however very cumbersome as we have to do this on six nodes. To optimize this process, we will use Ansible.&lt;/p&gt;
&lt;p&gt;Note: &lt;code&gt;setenforce 0&lt;/code&gt; is used to prevent issue with SELinux label during the rebase action.&lt;/p&gt;
&lt;h3&gt;OSTree provisioning using Ansible&lt;/h3&gt;
&lt;p&gt;Create a file called &lt;code&gt;hosts&lt;/code&gt; in your home directory with the following content:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;~/hosts&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="k"&gt;[mons]&lt;/span&gt;
&lt;span class="na"&gt;atomic-01 ansible_ssh_host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10.3.0.3&lt;/span&gt;
&lt;span class="na"&gt;atomic-02 ansible_ssh_host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10.3.0.4&lt;/span&gt;
&lt;span class="na"&gt;atomic-03 ansible_ssh_host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10.3.0.5&lt;/span&gt;

&lt;span class="k"&gt;[osds]&lt;/span&gt;
&lt;span class="na"&gt;atomic-04 ansible_ssh_host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10.3.0.6&lt;/span&gt;
&lt;span class="na"&gt;atomic-05 ansible_ssh_host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10.3.0.7&lt;/span&gt;
&lt;span class="na"&gt;atomic-06 ansible_ssh_host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s"&gt;10.3.0.8&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To test if the nodes are reachable, use the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ansible&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;hosts&lt;span class="w"&gt; &lt;/span&gt;all&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;centos&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;ping
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;If no error occurs, you are all set.&lt;/p&gt;
&lt;p&gt;Using Ansible and the hosts file we can perform these commands on all the nodes.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ansible&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;hosts&lt;span class="w"&gt; &lt;/span&gt;all&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;centos&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;setenforce 0&amp;quot;&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;ansible&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;hosts&lt;span class="w"&gt; &lt;/span&gt;all&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;centos&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;ostree remote add --set=gpg-verify=false atomic-ceph http://10.3.0.2:8000/&amp;quot;&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;ansible&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;hosts&lt;span class="w"&gt; &lt;/span&gt;all&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;centos&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;rpm-ostree rebase atomic-ceph:centos-atomic-host/7/x86_64/ceph-jewel&amp;quot;&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;ansible&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;hosts&lt;span class="w"&gt; &lt;/span&gt;all&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;centos&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;systemctl disable docker&amp;quot;&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;ansible&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;hosts&lt;span class="w"&gt; &lt;/span&gt;all&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;centos&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;-m&lt;span class="w"&gt; &lt;/span&gt;shell&lt;span class="w"&gt; &lt;/span&gt;-a&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;systemctl reboot&amp;quot;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The last command will throw errors, but this is expected as the connection to the node is dropped. To check if the nodes are up again, you can perform the previous ping test again.&lt;/p&gt;
&lt;p&gt;Note: since we based on the original CentOS Atomic host image, it will have Docker installed. For this article we do not use it, so it is best to disable it.&lt;/p&gt;
&lt;h2&gt;Deployment using &lt;code&gt;ceph-ansible&lt;/code&gt;&lt;/h2&gt;
&lt;p&gt;If the previous step succeeded you would have six atomic hosts that are ready to be configured to form a small Ceph cluster; 3 nodes will serve the role of monitor, while the other nodes will be storage nodes with an attached volume at &lt;code&gt;/dev/vdb&lt;/code&gt;. For the deployment we will use &lt;code&gt;ceph-ansible&lt;/code&gt;. This is a collection of playbooks to help with common scenarios for a Ceph storage cluster.&lt;/p&gt;
&lt;p&gt;From your home folder perform the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;https://github.com/ceph/ceph-ansible.git&lt;span class="w"&gt; &lt;/span&gt;--depth&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will clone the latest version of the playbooks. But before we can use them, we will need to configure it for our setup. But before we do, we initialize it with the base configuration. Take note that we will re-use our previosuly used &lt;code&gt;~/hosts&lt;/code&gt; file for Ansible.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ceph-ansible
$&lt;span class="w"&gt; &lt;/span&gt;cp&lt;span class="w"&gt; &lt;/span&gt;site.yml.sample&lt;span class="w"&gt; &lt;/span&gt;site.yml
$&lt;span class="w"&gt; &lt;/span&gt;cp&lt;span class="w"&gt; &lt;/span&gt;group_vars/all.sample&lt;span class="w"&gt; &lt;/span&gt;group_vars/all
$&lt;span class="w"&gt; &lt;/span&gt;cp&lt;span class="w"&gt; &lt;/span&gt;group_vars/mons.sample&lt;span class="w"&gt; &lt;/span&gt;group_vars/mons
$&lt;span class="w"&gt; &lt;/span&gt;cp&lt;span class="w"&gt; &lt;/span&gt;group_vars/osds.sample&lt;span class="w"&gt; &lt;/span&gt;group_vars/osds
$&lt;span class="w"&gt; &lt;/span&gt;ln&lt;span class="w"&gt; &lt;/span&gt;-s&lt;span class="w"&gt; &lt;/span&gt;~/hosts&lt;span class="w"&gt; &lt;/span&gt;hosts
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;We will now customize the configuration by changing the following files and add the shows content to the top of the file:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;group_vars/all&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;cluster_network&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;10.3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;
&lt;span class="n"&gt;generate_fsid&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;true&amp;#39;&lt;/span&gt;
&lt;span class="n"&gt;ceph_origin&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;distro&lt;/span&gt;
&lt;span class="n"&gt;monitor_interface&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;eth0&lt;/span&gt;
&lt;span class="n"&gt;public_network&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mf"&gt;10.3&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="mf"&gt;0.0&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;24&lt;/span&gt;
&lt;span class="n"&gt;journal_size&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5120&lt;/span&gt;
&lt;span class="n"&gt;group_vars&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;mons&lt;/span&gt;
&lt;span class="n"&gt;cephx&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;group_vars/mons&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;cephx&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;&lt;code&gt;group_vars/osds&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;journal_collocation&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="n"&gt;cephx&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;
&lt;span class="n"&gt;devices&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="sr"&gt;/dev/&lt;/span&gt;&lt;span class="n"&gt;vdb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After these changes are made, you have setup to use Ceph packages as provided by the distribution, and to deploy as a storage cluster on 10.3.0.0/24.&lt;/p&gt;
&lt;p&gt;To deploy the storage cluster, all we need to do now is to run the playbook named &lt;code&gt;site.yml&lt;/code&gt; and skipping the tags named &lt;code&gt;with_pkg&lt;/code&gt; and &lt;code&gt;package-install&lt;/code&gt;.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ansible-playbook&lt;span class="w"&gt; &lt;/span&gt;-i&lt;span class="w"&gt; &lt;/span&gt;hosts&lt;span class="w"&gt; &lt;/span&gt;site.yml&lt;span class="w"&gt; &lt;/span&gt;--skip-tags&lt;span class="w"&gt; &lt;/span&gt;with_pkg,package-install
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After this finishes a storage cluster should be available.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This article showed how it is possible to customize an Atomic host image for a specific use-case and use this for deployment of a simple Ceph cluster. Using ostree it is possible to move between different trees, allowing a collection of packages to be upgraded in an atomic fashion. And when there is a failure for some reason, it is possible to rollback to the previous tree and allow the node to function in the former state.&lt;/p&gt;
&lt;p&gt;This is part of the setup I usefor automated builds of Ceph packages and deployment tests. If you have questions about specific parts, please let me know on Twitter at &lt;a href="https://twitter.com/gbraad"&gt;@gbraad&lt;/a&gt; or by email. Input is appreciated as this can help with writing of future articles.&lt;/p&gt;
&lt;h2&gt;Links&lt;/h2&gt;
&lt;p&gt;Some information that can help with customizing your own images:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/jasonbrooks/byo-atomic"&gt;Build your own Atomic&lt;/a&gt;, and my &lt;a href="http://gitlab.com/gbraad/byo-atomic"&gt;automated build&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gitlab.com/gbraad/ceph-atomic/"&gt;Tree definition&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gbraad.gitlab.io/byo-atomic-ceph/"&gt;Remote location&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://gitlab.com/gbraad/byo-atomic-ceph/builds"&gt;Automated build&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="Containers"/><category term="centos"/><category term="ceph"/><category term="atomic"/><category term="ansible"/><category term="ostree"/><category term="storage"/></entry><entry><title>Setting up a powerful self-hosted IDE in the cloud</title><link href="https://blog.gbraad.nl/setting-up-a-powerful-self-hosted-ide-in-the-cloud.html" rel="alternate"/><published>2016-09-06T00:00:00+08:00</published><updated>2016-09-06T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-09-06:/setting-up-a-powerful-self-hosted-ide-in-the-cloud.html</id><summary type="html">&lt;p&gt;Setting up infrastructure should be as simple as playing with LEGO. With the advent of Docker, IT has underwent a dramatic change. For instance, it became easy to setup throw-away development environments. These could then be used to create clean environments to perform builds in. And eventually, containers are starting …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Setting up infrastructure should be as simple as playing with LEGO. With the advent of Docker, IT has underwent a dramatic change. For instance, it became easy to setup throw-away development environments. These could then be used to create clean environments to perform builds in. And eventually, containers are starting to move into the general infrastructure . This is a transaction that is currently still happening, helped by tools as Docker Swarm and Kubernetes. In this short article I will show how these ideas can help in setting up a composable infrastructure, providing you with a powerful IDE in the cloud, full with Let's Encrypt certificate generation.&lt;/p&gt;
&lt;h2&gt;Cloud9&lt;/h2&gt;
&lt;p&gt;We will be deploying C9, or Cloud9 IDE, is a full IDE which can be accessed from your browser. For convenience of use, I created a containerized version of this some while back and have ever since been using it. Although,, C9 also has a hosted environment, I grew worried after Amazon acquired the company. Support has since been slower to respond and this made me look into other ways to provide an alternative approach. After some testing with Docker Cloud it seemed like a good idea to deploy a self-hosted alternative.&lt;/p&gt;
&lt;p&gt;But first about one of the main components. The &lt;a href="https://hub.docker.com/r/gbraad/c9ide/"&gt;container&lt;/a&gt; I created exposes port 8181, which is an unsecured endpoint. It allows you to simply setup a local instance with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;alias&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;c9ide&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;docker run -it --rm -v $PWD:/workspace gbraad/c9ide:u1604&amp;#39;&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/Projects/gauth
$&lt;span class="w"&gt; &lt;/span&gt;c9ide
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This would however work for a local environment and does not provide a secure solution. More was needed... such as secure solution and preferably automated. For this Nginx and Let's Encrypt is used.  More information about Cloud9 can be found in my Knowledge Base &lt;a href="https://github.com/gbraad/knowledge-base/blob/master/technology/c9ide.md"&gt;article&lt;/a&gt;&lt;a href="https://gitlab.com/gbraad/knowledge-base/blob/master/technology/c9ide.md"&gt;*&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;Preparation&lt;/h2&gt;
&lt;p&gt;To deploy the environment I used &lt;a href="http://fedoraproject.org"&gt;Fedora&lt;/a&gt; 24. Most cloud providers provide this as an image. In my case, &lt;a href="https://www.citycloud.com"&gt;CityCloud&lt;/a&gt; provided the latest version after placing a simple request. You can consider any size, but the more storage and memory, the better the performance will be. I set up a 4G and 2 cores instance, with 50G of storage. After logging in, perform the following commands&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;su&lt;span class="w"&gt; &lt;/span&gt;-
$&lt;span class="w"&gt; &lt;/span&gt;dnf&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;-y
$&lt;span class="w"&gt; &lt;/span&gt;dnf&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;docker
$&lt;span class="w"&gt; &lt;/span&gt;setenforce&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;0&lt;/span&gt;
$&lt;span class="w"&gt; &lt;/span&gt;sed&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;s/SELINUX=targeted/SELINUX=permisssive/g&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;/etc/selinux/config
$&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;docker
$&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;docker
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note: SELinux is disabled because we will have a volume attached to the IDE container where the workspace will be located. We can however fix this, but this is something for a future blog post.&lt;/p&gt;
&lt;h3&gt;Setup DNS&lt;/h3&gt;
&lt;p&gt;After this, you host machine should be ready to host containers to will make up our environment. before we continue, we need to be sure we have DNS configured that can point to the running containers that host the C9 IDE. I used &lt;a href="https://www.cloudflare.com"&gt;CloudFlare&lt;/a&gt; and setup the following wildcard for my environment. &lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://cdn.gbraad.nl/images/blog/c9ide-dns.png"&gt;&lt;/p&gt;
&lt;p&gt;With this each hostname, such as &lt;code&gt;ubuntu.c9ide.spotsnel.net&lt;/code&gt; would point to the same machine that hosts our development containers.&lt;/p&gt;
&lt;h3&gt;Deploy Nginx&lt;/h3&gt;
&lt;p&gt;To allow a hostname to be resolved to a 'local' end-point a reverse proxy is needed. Jason Wilder created a container for this purpose called &lt;code&gt;nginx-proxy&lt;/code&gt;. It needs access to the &lt;code&gt;docker.sock&lt;/code&gt; to be notified of changes and it will accordingly create an endpoint in the hosted Nginx. For more information about this, please read &lt;a href="https://hub.docker.com/r/jwilder/nginx-proxy/"&gt;nginx-proxy&lt;/a&gt;'s description on Docker hub.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker run -d -p 80:80 -p 443:443 \&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;\
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;certs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;certs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ro&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;\
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;vhost&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;\
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;share&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;\
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ro&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;\
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;jwilder&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;proxy&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Opening any address pointing to this host would know result in a 503 error. This means that Nginx is listening and can not forward the request. We will deal with this later.&lt;/p&gt;
&lt;h2&gt;Deploy Let's Encrypt companion&lt;/h2&gt;
&lt;p&gt;Setting up a secure connection involves certificates which can be quite a hassle to obtain, and if trust of security is concerned, even very expensive. Luckily, initiatives exist that believe security should be available to all and &lt;a href="https://letsencrypt.org"&gt;Let's Encrypt&lt;/a&gt; provides a fully automated solution. Using the &lt;code&gt;letsencrypt-nginx-proxy-companion&lt;/code&gt; container created by Yves Blusseau, it is possible allow the proxy container to be provisioned with the needed certificates. More information about &lt;a href="https://hub.docker.com/r/jrcs/letsencrypt-nginx-proxy-companion/"&gt;this container&lt;/a&gt; can be found at Docker hub.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# docker run -d \&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;letsencrypt&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;\
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;certs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;certs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;rw&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;\
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;volumes&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;\
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;var&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;docker&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ro&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;\
&lt;span class="w"&gt;   &lt;/span&gt;&lt;span class="n"&gt;jrcs&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;letsencrypt&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;nginx&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;proxy&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;companion&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Unfortunately we do not have a way to really test this. But if the container starts correctly and does not terminate, it is likely working correctly, waiting for notifications of newly created containers.&lt;/p&gt;
&lt;h2&gt;Explanation&lt;/h2&gt;
&lt;p&gt;Containers that provide metadata in the form of environment variables, indicate to these service containers what the endpoint will be.&lt;/p&gt;
&lt;p&gt;The &lt;code&gt;nginx-proxy&lt;/code&gt; service uses &lt;code&gt;VIRTUAL_HOST&lt;/code&gt; to know what the hostname endpoint will be. While the Let's Encrypt companion service uses &lt;code&gt;LETSENCRYPT_HOST&lt;/code&gt; for this. In the rest of this article the endpoints will be the same. With &lt;code&gt;LETSENCRYPT_EMAIL&lt;/code&gt; we indicate to who the certificate will be addressed.&lt;/p&gt;
&lt;h2&gt;C9 IDE&lt;/h2&gt;
&lt;p&gt;The container hosting C9 is available in different flavors. I have created them based on CentOS 7, Fedora 24 and Ubuntu Xenail (16.04). To prepare, it is a good idea to pull the images locally:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;# docker pull gbraad/c9ide:c7
# docker pull gbraad/c9ide:f24
# docker pull gbraad/c9ide:u1604
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To setup the containers as endpoints, I created the following helper script. It will deal with setting up the host and email for login to the container.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;./create.sh [name] [host] [email] [password] [flavor] [volume]&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="ch"&gt;#!/bin/sh -x&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;-e

&lt;span class="nv"&gt;NAME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;1&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;test&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;HOST&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;2&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;.local&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;USER&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;3&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;nobody@local&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;PASS&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;4&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;secrete&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;span class="nv"&gt;FLAVOR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;5&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;u1604&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="c1"&gt;# c7, f24, u1604&lt;/span&gt;
&lt;span class="nv"&gt;VOLUME&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;6&lt;/span&gt;&lt;span class="k"&gt;:-&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;/workspaces/c9ide-&amp;quot;&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAME&lt;/span&gt;&lt;span class="si"&gt;}}&lt;/span&gt;

mkdir&lt;span class="w"&gt; &lt;/span&gt;-p&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VOLUME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
docker&lt;span class="w"&gt; &lt;/span&gt;run&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;NAME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;-v&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;VOLUME&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;:/workspace:rw&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;VIRTUAL_HOST=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOST&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;LETSENCRYPT_HOST=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;HOST&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;LETSENCRYPT_EMAIL=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;USER&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;USERNAME=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;USER&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;PASSWORD=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;PASS&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&lt;span class="w"&gt;   &lt;/span&gt;gbraad/c9ide:&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;FLAVOR&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code&gt;USERNAME&lt;/code&gt; and &lt;code&gt;PASSWORD&lt;/code&gt; are used to perform basic authentication.  As you can see, the email address used for the certificates is also used for the username for login. This can of course customized.
 After this, &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;chmod&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;create&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mkdir&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;workspaces&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;create&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ubuntu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ubuntu&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c9ide&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spotsnel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;me&lt;/span&gt;&lt;span class="nv"&gt;@gbraad&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;verysecrete&lt;/span&gt;
&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;create&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;centos&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;quentin&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;c9ide&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;spotsnel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;net&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;me&lt;/span&gt;&lt;span class="nv"&gt;@quentinyong&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;verysecrete&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;c7&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;will create two containers, hosted at &lt;code&gt;ubuntu.c9ide.spotsnel.net&lt;/code&gt; and &lt;code&gt;quentin.c9ide.spotsnel.net&lt;/code&gt;. Notice that I used &lt;code&gt;/workspaces&lt;/code&gt; to provide the storage location for all the host containers. Make sure this is hosted on a separate mountpoint for instance. &lt;/p&gt;
&lt;p&gt;Now open your IDE by opening &lt;a href="https://ubuntu.c9ide.spotsnel.net"&gt;https://ubuntu.c9ide.spotsnel.net&lt;/a&gt; in your browser. If all goes well, you will be created by a login prompt. The username is &lt;code&gt;me@gbraad.nl&lt;/code&gt; and the password &lt;code&gt;verysecrete&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="" src="https://cdn.gbraad.nl/images/blog/c9ide-final.png"&gt;&lt;/p&gt;
&lt;p&gt;In future articles I will detail more about the composability of infrastructure. if you enjoyed this article, consider tweeting about it. If you have comments, please find me online at &lt;a href="http://twitter.com/gbraad"&gt;@gbraad&lt;/a&gt;.&lt;/p&gt;</content><category term="Containers"/><category term="docker"/><category term="c9ide"/><category term="fedora"/></entry><entry><title>Hello, Internet!</title><link href="https://blog.gbraad.nl/hello-internet.html" rel="alternate"/><published>2016-08-08T00:00:00+08:00</published><updated>2016-08-08T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-08-08:/hello-internet.html</id><summary type="html">&lt;p&gt;Today I decided to pick up blogging again and asked the question; what to use? I had a simple requirement; 'it has to support Markdown-formatted documents'. The reasoning behind this is simple; I want to be able to use &lt;code&gt;Pandoc&lt;/code&gt; to generate other kinds of output if needed. Plus GitBook …&lt;/p&gt;</summary><content type="html">&lt;p&gt;Today I decided to pick up blogging again and asked the question; what to use? I had a simple requirement; 'it has to support Markdown-formatted documents'. The reasoning behind this is simple; I want to be able to use &lt;code&gt;Pandoc&lt;/code&gt; to generate other kinds of output if needed. Plus GitBook has an online editor which allows me to write the articles as if they are chapters in a book.&lt;/p&gt;
&lt;p&gt;Chris Smart, who is the creator of the Korora project, suggested me to have a look at Pelican. So I did, and this resulted in the blog you are reading at the moment.&lt;/p&gt;
&lt;p&gt;Publication is all automated using GitLab CI runners. The project for this is available at &lt;a href="https://gitlab.com/gbraad/blog"&gt;blog&lt;/a&gt;. For the moment it is still a test and I will try to theme it over the coming days. Anyways, progress can be tracked here...&lt;/p&gt;</content><category term="Misc"/><category term="blog"/><category term="pelican"/><category term="markdown"/></entry><entry><title>Software Distribution for a new era</title><link href="https://blog.gbraad.nl/software-distribution-for-a-new-era.html" rel="alternate"/><published>2016-07-30T00:00:00+08:00</published><updated>2016-09-10T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-07-30:/software-distribution-for-a-new-era.html</id><summary type="html">&lt;p&gt;In this presentation I will introduce Software Distribution for a new era. In
short it will explain the negatives of using packages, how 'containers' improved
on this, but now how to make this available for use on servers and desktops. &lt;/p&gt;
&lt;p&gt;In short it will talk about the following topics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;container …&lt;/li&gt;&lt;/ul&gt;</summary><content type="html">&lt;p&gt;In this presentation I will introduce Software Distribution for a new era. In
short it will explain the negatives of using packages, how 'containers' improved
on this, but now how to make this available for use on servers and desktops. &lt;/p&gt;
&lt;p&gt;In short it will talk about the following topics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;container and Docker&lt;/li&gt;
&lt;li&gt;FlatPak&lt;/li&gt;
&lt;li&gt;OSTree&lt;/li&gt;
&lt;li&gt;Project Atomic (Fedora, CentOS)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Presentation&lt;/h2&gt;
&lt;iframe src="http://gbraad.gitlab.io/software-distribution-for-a-new-era/slides.html" width="1024" height="768"&gt;
  &lt;p&gt;Your browser does not support iframes.&lt;/p&gt;
&lt;/iframe&gt;

&lt;h2&gt;Feedback&lt;/h2&gt;
&lt;p&gt;If you have any suggestion, please discuss below or send me an email.&lt;/p&gt;
&lt;p&gt;Note: the original presentation can be found at: &lt;a href="https://gitlab.com/gbraad/software-distribution-for-a-new-era"&gt;Software Distribution for a new era&lt;/a&gt;&lt;/p&gt;</content><category term="Containers"/><category term="flatpak"/><category term="docker"/><category term="ostree"/><category term="atomic"/><category term="fedora"/><category term="centos"/></entry><entry><title>Deploying OpenStack using TripleO</title><link href="https://blog.gbraad.nl/deploying-openstack-using-tripleo.html" rel="alternate"/><published>2016-05-18T00:00:00+08:00</published><updated>2016-09-10T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2016-05-18:/deploying-openstack-using-tripleo.html</id><summary type="html">&lt;p&gt;In this article we will deploy an OpenStack environment using TripleO using
the &lt;code&gt;tripleo-quickstart&lt;/code&gt; scripts. It will create a virtualized environment
which consists of 1 Undercloud node and in total 9 nodes in the Overcloud;
3 controller nodes (High Availability), 3 compute nodes and 3 Ceph storage
nodes.&lt;/p&gt;
&lt;h2&gt;What is …&lt;/h2&gt;</summary><content type="html">&lt;p&gt;In this article we will deploy an OpenStack environment using TripleO using
the &lt;code&gt;tripleo-quickstart&lt;/code&gt; scripts. It will create a virtualized environment
which consists of 1 Undercloud node and in total 9 nodes in the Overcloud;
3 controller nodes (High Availability), 3 compute nodes and 3 Ceph storage
nodes.&lt;/p&gt;
&lt;h2&gt;What is TripleO, &lt;em&gt;undercloud&lt;/em&gt; and &lt;em&gt;overcloud&lt;/em&gt;?&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://wiki.openstack.org/wiki/TripleO"&gt;TripleO&lt;/a&gt; is a deployment method in
which a dedicated OpenStack management environment is used to deploy another
OpenStack environment which is used for the workload. The management environment
is contained in a single machine, called the &lt;em&gt;undercloud&lt;/em&gt;. This OpenStack
environment takes care of the monitoring and management of what is known as the
&lt;em&gt;overcloud&lt;/em&gt;. The &lt;em&gt;overcloud&lt;/em&gt; is the actual OpenStack environment that will run
the workload.&lt;/p&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;It is preferred to use a dedicated server for the following instructions.
Consider using 32G of memory and have enough diskspace available in &lt;code&gt;/home&lt;/code&gt;.
This target node has to be using CentOS 7 (or RHEL7).&lt;/p&gt;
&lt;h2&gt;Prepare for deployment&lt;/h2&gt;
&lt;p&gt;The deployment can be done from a workstation targeting a server, or from the
server itself. Whatever your preferred method is, you will need the 
&lt;a href="https://github.com/openstack/tripleo-quickstart"&gt;tripleo-quickstart&lt;/a&gt; scripts.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-O&lt;span class="w"&gt; &lt;/span&gt;https://raw.githubusercontent.com/openstack/tripleo-quickstart/master/quickstart.sh
$&lt;span class="w"&gt; &lt;/span&gt;chmod&lt;span class="w"&gt; &lt;/span&gt;u+x&lt;span class="w"&gt; &lt;/span&gt;quickstart.sh
$&lt;span class="w"&gt; &lt;/span&gt;./quickstart.sh&lt;span class="w"&gt; &lt;/span&gt;--install-deps
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will install the dependencies used by the &lt;code&gt;quickstart.sh&lt;/code&gt; script. Now you
need to prepare the target node. Make sure you can login to this server without
a password.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;export&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;VIRTHOST&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;&lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ssh&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;copy&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="err"&gt;@$&lt;/span&gt;&lt;span class="n"&gt;VIRTHOST&lt;/span&gt;
&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ssh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;root&lt;/span&gt;&lt;span class="err"&gt;@$&lt;/span&gt;&lt;span class="n"&gt;VIRTHOST&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;uname&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This article witll not describe the setup of passwordless or key-based
authentication with SSH. If issues occur, please verify you have a generated
keyset. If not, generate one with &lt;code&gt;ssh-keygen&lt;/code&gt;. For further information please
consult the &lt;code&gt;man&lt;/code&gt; page or verify online.&lt;/p&gt;
&lt;h2&gt;Cache deployment images locally&lt;/h2&gt;
&lt;p&gt;Although this step is not necessary, you can pre-download the images and cache
them locally. This can be helpful if you want to perform the deployment using
different images and/or suffer from bad connectivity.&lt;/p&gt;
&lt;p&gt;The location if the images is currently at &lt;code&gt;http://artifacts.ci.centos.org/rdo/images/{{release}}/delorean/stable/undercloud.qcow2&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To download the &lt;em&gt;mitaka&lt;/em&gt; image, you can do this with&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;mkdir&lt;span class="w"&gt; &lt;/span&gt;/var/lib/oooq-images
$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;http://artifacts.ci.centos.org/rdo/images/mitaka/delorean/stable/undercloud.qcow2&lt;span class="w"&gt; &lt;/span&gt;-o&lt;span class="w"&gt; &lt;/span&gt;/var/lib/oooq-images/undercloud-mitaka.qcow2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Deployment configuration file&lt;/h2&gt;
&lt;p&gt;We will create a virtual environment for out TripleO deployment. This will
provide you with the knowledge you need to perform a bare-metal installation.&lt;/p&gt;
&lt;p&gt;You can define the node deployment inside a configuration file, eg. called 
&lt;code&gt;deploy-config.yml&lt;/code&gt;. This will contain the following:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;overcloud_nodes:
  &lt;span class="k"&gt;-&lt;/span&gt; name: control_0
    flavor: control
  &lt;span class="k"&gt;-&lt;/span&gt; name: control_1
    flavor: control
  &lt;span class="k"&gt;-&lt;/span&gt; name: control_2
    flavor: control

  &lt;span class="k"&gt;-&lt;/span&gt; name: compute_0
    flavor: compute
  &lt;span class="k"&gt;-&lt;/span&gt; name: compute_1
    flavor: compute
  &lt;span class="k"&gt;-&lt;/span&gt; name: compute_2
    flavor: compute

  &lt;span class="k"&gt;-&lt;/span&gt; name: storage_0
    flavor: ceph
  &lt;span class="k"&gt;-&lt;/span&gt; name: storage_1
    flavor: ceph
  &lt;span class="k"&gt;-&lt;/span&gt; name: storage_2
    flavor: ceph

extra_args: &amp;quot;--control-scale 3 --ceph-storage-scale 3 -e /usr/share/openstack-tripleo-heat-templates/environments/puppet-pacemaker.yaml --ntp-server pool.ntp.org&amp;quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Nodes can be assigned a role by setting the flavor:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;control&lt;/code&gt; sets up a controller node, which also handles the network.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;compute&lt;/code&gt; sets up a Nova compute node.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ceph&lt;/code&gt; sets up a node for Ceph storage.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The extra arguments allow you to modify the deployment that is performed.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;--control-scale 3&lt;/code&gt; instructs the deployment to assign 3 nodes with the
      controller role.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--ceph-storage-scale 3&lt;/code&gt; instructs the deployment to assign 3 nodes to
      be used for the Ceph storage backend.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;-e puppet-pacemaker.yaml&lt;/code&gt; will setup pacemaker HA for the controller
      nodes&lt;/li&gt;
&lt;li&gt;&lt;code&gt;--ntp-server pool.ntp.org&lt;/code&gt; will sync time on the nodes using NTP.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Note: if you want to use all compute nodes at once, include &lt;code&gt;--compute-scale 3&lt;/code&gt;. But in this article I am using these additional nodes for scale out.&lt;/p&gt;
&lt;h2&gt;Perform deployment&lt;/h2&gt;
&lt;p&gt;Now you can perform the &lt;em&gt;undercloud&lt;/em&gt; deployment using:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;./quickstart.sh&lt;span class="w"&gt; &lt;/span&gt;--config&lt;span class="w"&gt; &lt;/span&gt;deploy-config.yml&lt;span class="w"&gt; &lt;/span&gt;--undercloud-image-url&lt;span class="w"&gt; &lt;/span&gt;file:///var/lib/oooq-images/undercloud-mitaka.qcow2&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$VIRTHOST&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;But before you do, please continue reading about the &lt;code&gt;Deployment scripts&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The previous command will target the node as specified with the &lt;code&gt;$VIRTHOST&lt;/code&gt; 
environment variable, and according to the &lt;code&gt;deploy-config.yml&lt;/code&gt; which we defined
earlier.&lt;/p&gt;
&lt;p&gt;It will login to this node and create a &lt;code&gt;stack&lt;/code&gt; user which will be running the
virtual machines. Later we will inspect this. After creating the virtual
machines it will prepare the &lt;code&gt;undercloud&lt;/code&gt; machine. After this, you still need to
start the actual deployment. &lt;/p&gt;
&lt;h2&gt;Deployment scripts&lt;/h2&gt;
&lt;p&gt;To login to the undercloud:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;-F&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$OPT_WORKDIR&lt;/span&gt;/ssh.config.ansible&lt;span class="w"&gt; &lt;/span&gt;undercloud
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The undercloud is not fully prepared, you would have to do so with the following
scripts.&lt;/p&gt;
&lt;p&gt;Undercloud (management)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;undercloud-install.sh&lt;/code&gt; will run the undercloud install and execute
    diskimage elements.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;undercloud-post-install.sh&lt;/code&gt; will perform all pre-deploy steps, such as
    uploading the images to &lt;em&gt;glance&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Overcloud (workload)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;overcloud-deploy.sh&lt;/code&gt; will deploy the overcloud, creating a &lt;em&gt;heat&lt;/em&gt; stack
    and will use the nodes as defined in &lt;code&gt;instack-env.json&lt;/code&gt; and the extra
    arguments given in the deployment configuration.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;overcloud-deploy-post.sh&lt;/code&gt; will do any post-deploy configuration
    such as writing a local &lt;code&gt;/etc/hosts&lt;/code&gt; file.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;overcloud-validate.sh&lt;/code&gt; will run post-deploy validation, like a
    &lt;em&gt;pingtest&lt;/em&gt; and possible &lt;em&gt;tempest&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You can run these scripts one by one... or install the whole &lt;em&gt;undercloud&lt;/em&gt; and
&lt;em&gt;overcloud&lt;/em&gt; using the command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;./quickstart.sh&lt;span class="w"&gt; &lt;/span&gt;--tags&lt;span class="w"&gt; &lt;/span&gt;all&lt;span class="w"&gt; &lt;/span&gt;--config&lt;span class="w"&gt; &lt;/span&gt;deploy-config.yml&lt;span class="w"&gt; &lt;/span&gt;--undercloud-image-url&lt;span class="w"&gt; &lt;/span&gt;file:///var/lib/oooq-images/undercloud-mitaka.qcow2&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$VIRTHOST&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Using &lt;code&gt;--tags all&lt;/code&gt; will instruct ansible to perform all the steps and scripts
as previously described. I suggest you to run the steps first each one by one
and look into the scripts itself to understand how they interact with
&lt;code&gt;python-tripleoclient&lt;/code&gt; (eg. &lt;code&gt;openstack undercloud&lt;/code&gt; and &lt;code&gt;openstack overcloud&lt;/code&gt;).&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack@undercloud ~&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;undercloud&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack@undercloud ~&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;undercloud&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;install&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack@undercloud ~&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;overcloud&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;deploy&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack@undercloud ~&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;overcloud&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;deploy&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack@undercloud ~&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;overcloud&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;validate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Undercloud node&lt;/h2&gt;
&lt;p&gt;After running these commands, you will have a fully deployed environment.
You can verify this from the &lt;em&gt;undercloud&lt;/em&gt; node.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack@undercloud ~&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;stackrc&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack@undercloud ~&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ironic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;+--------------------------------------+-----------+--------------------------------------+-------------+--------------------+-------------+&lt;/span&gt;
&lt;span class="c"&gt;| UUID                                 | Name      | Instance UUID                        | Power State | Provisioning State | Maintenance |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+-----------+--------------------------------------+-------------+--------------------+-------------+&lt;/span&gt;
&lt;span class="c"&gt;| 5c4f1ad5&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;3cea&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;41c2&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8fa8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;f3468e660447 | control&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;0 | aea0add0&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;f638&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4a41&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;97ca&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;a2a64ac083a5 | None        | active             | True        |&lt;/span&gt;
&lt;span class="c"&gt;| 0a0bf5e8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;e903&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4f77&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;be35&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;0a49f4da5109 | control&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;1 | 75778a5e&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;5e65&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;48bc&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;9934&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;d4cb203fad86 | None        | active             | True        |&lt;/span&gt;
&lt;span class="c"&gt;| 12aa12d2&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;0023&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;48ac&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;89d2&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4e138f6eef08 | control&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;2 | f74b2b00&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;0c01&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;44a5&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;917e&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;45fff058f2fa | None        | active             | True        |&lt;/span&gt;
&lt;span class="c"&gt;| 6a0533a2&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;d91f&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4f45&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;acbb&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;5f5f231c8986 | compute&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;0 | None                                 | None        | available          | True        |&lt;/span&gt;
&lt;span class="c"&gt;| e8663954&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4da8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4027&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;9226&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;f9f053f269d9 | compute&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;1 | 113afdbd&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;0afa&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;481c&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;a744&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;90276907b8e2 | None        | active             | True        |&lt;/span&gt;
&lt;span class="c"&gt;| 06679c73&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;97a2&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4de0&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;b676&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;193a3e182fcf | compute&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;2 | None                                 | None        | available          | True        |&lt;/span&gt;
&lt;span class="c"&gt;| a6ef4bce&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;941c&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;407d&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;966e&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;85df2af3f6e1 | storage&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;0 | bbba571f&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;f2a9&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;46f3&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;a270&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;f154e045c5a8 | None        | active             | True        |&lt;/span&gt;
&lt;span class="c"&gt;| 6174dbb7&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;28e7&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;425e&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;b675&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;f1653f0b731c | storage&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;1 | d3afc0e8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;70a0&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;43c4&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;b35a&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;693a7e4e5fa5 | None        | active             | True        |&lt;/span&gt;
&lt;span class="c"&gt;| 32e8122b&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;3a5f&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;45fb&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8a5a&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;60dc4f82325f | storage&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;2 | 53ea0799&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;1bcd&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4f55&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8671&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;e6a7f7f46054 | None        | active             | True        |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+-----------+--------------------------------------+-------------+--------------------+-------------+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will show a list of nodes that are available in the environment. This information &lt;/p&gt;
&lt;h2&gt;Login to the overcloud&lt;/h2&gt;
&lt;p&gt;From the undercloud node you can source the stack resource file and use the
&lt;em&gt;openstack clients&lt;/em&gt; as usual.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack@undercloud ~&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;overcloudrc&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack@undercloud ~&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;overcloudrc&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack@undercloud ~&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nova&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;In the previous output you also see the &lt;code&gt;OS_AUTH_URL&lt;/code&gt; and the credentials
needed to login from the Horizon dashboard.&lt;/p&gt;
&lt;p&gt;Either using ssh portforwaring, or the dynamic proxy option, you can open the
dashboard.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;-F&lt;span class="w"&gt; &lt;/span&gt;~/.quickstart/ssh.config.ansible&lt;span class="w"&gt; &lt;/span&gt;undercloud&lt;span class="w"&gt; &lt;/span&gt;-D&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;8080&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Either using Firefox (with the FoxyProxy extension) or Chrome/Vivaldi (with the
SwitchySharp extension) you can set a SOCKS proxy at &lt;code&gt;127.0.0.1&lt;/code&gt; and port
&lt;code&gt;8080&lt;/code&gt;.&lt;/p&gt;
&lt;h2&gt;Login to overcloud nodes&lt;/h2&gt;
&lt;p&gt;If you need to inspect a node in the overcloud (workload), you can login to these nodes from the undercloud using the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack@undercloud ~&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ssh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;hostname/nodeip&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note: you can find the hostnames and IP addresses on the &lt;em&gt;undercloud&lt;/em&gt; in the
&lt;code&gt;/etc/hosts&lt;/code&gt; file. It will use 'heat-admin' as user to login.&lt;/p&gt;
&lt;h2&gt;Scale out&lt;/h2&gt;
&lt;p&gt;After deployment, you might have noticed that &lt;code&gt;ironic node-list&lt;/code&gt; returned a
list of baremetal nodes that are in &lt;em&gt;Provisioning state&lt;/em&gt; 'available' and do not
have an &lt;em&gt;Instance UUID&lt;/em&gt;. These nodes have not been deployed to, as
&lt;code&gt;--compute-scale&lt;/code&gt; had not been set.&lt;/p&gt;
&lt;p&gt;To scale out to these nodes, you first need to change the &lt;code&gt;Maintenance&lt;/code&gt; status
to false. You can do this for all available at once with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack@undercloud ~&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&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;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ow"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ironic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;list&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;grep&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;available&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;grep&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;v&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;UUID&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;awk&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39; { print $2 } &amp;#39;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;do&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ironic&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;node&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;set&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;maintenance&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can verify the status with &lt;code&gt;ironic node-list&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;After this you can scale out using&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;stack&lt;/span&gt;&lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="nx"&gt;undercloud&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;~&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;openstack&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;overcloud&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;deploy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;templates&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;libvirt&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;qemu&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;control&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;flavor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;oooq_control&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;flavor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;oooq_compute&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;ceph&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;storage&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;flavor&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;oooq_ceph&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;timeout&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;ntp&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;server&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ntp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;org&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;compute&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;scale&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This will change the current &lt;em&gt;overcloud&lt;/em&gt; heat deployment and provision the
remaining nodes.&lt;/p&gt;
&lt;p&gt;Eventually the command will return with:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;...
Stack overcloud UPDATE_COMPLETE
Overcloud Endpoint: http://192.0.2.6:5000/v2.0
Overcloud Deployed
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;after which the new nodes have been added to the &lt;em&gt;overcloud&lt;/em&gt;. To update the
hosts entries in &lt;code&gt;/etc/hosts&lt;/code&gt; you can rerun:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;stack@undercloud ~&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;overcloud&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;deploy&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sh&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Diskimage building&lt;/h2&gt;
&lt;p&gt;The &lt;em&gt;undercloud&lt;/em&gt; images can be created using &lt;a href="https://github.com/redhat-openstack/ansible-role-tripleo-image-build"&gt;ansible-role-tripleo-image-build&lt;/a&gt;.
Using the following commands it will generate the images:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;git&lt;span class="w"&gt; &lt;/span&gt;clone&lt;span class="w"&gt; &lt;/span&gt;https://github.com/redhat-openstack/ansible-role-tripleo-image-build.git
$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;cd&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ansible-role-tripleo-image-build/tests/pip
$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;./build.sh&lt;span class="w"&gt; &lt;/span&gt;-i
$&lt;span class="w"&gt; &lt;/span&gt;./build.sh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$VIRTHOST&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After the command finishes succesfully, the images can be found in
&lt;code&gt;/var/lib/oooq-images&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Note: The content of &lt;code&gt;/var/lib/oooq-images&lt;/code&gt; will be cleaned on run. After this
it will download a base image from
&lt;code&gt;http://cloud.centos.org/centos/7/images/CentOS-7-x86_64-GenericCloud.qcow2&lt;/code&gt; of
about 800M. You can download this image and specify the location in a
configuration file to prevent it from having to be downloaded each time.&lt;/p&gt;
&lt;p&gt;A create a file called: &lt;code&gt;override.yml&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;artib_minimal_base_image_url&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;:///&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="sr"&gt;/lib/oooq-base-images/&lt;/span&gt;&lt;span class="n"&gt;CentOS&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;x86_64&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;GenericCloud&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;qcow2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;And pass this to the build command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;./build.sh&lt;span class="w"&gt; &lt;/span&gt;-e&lt;span class="w"&gt; &lt;/span&gt;override.yml&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$VIRTHOST&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;Since the introduction of TripleO Quickstart, standing up a multi-node OpenStack
environment is very easy. In my knowledge-base article I describe also how you
can do a baremetal deployment using the Quickstart.&lt;/p&gt;
&lt;p&gt;If you have any suggestion, please discuss below or send me an email.&lt;/p&gt;
&lt;p&gt;Note: the original publication can be found at: &lt;a href="https://gitlab.com/gbraad/openstack-handsonlabs"&gt;OpenStack hands-on-labs&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;More information&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Deployment &lt;a href="https://github.com/openstack/tripleo-quickstart/blob/master/docs/configuring.md"&gt;configuration options&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Knowledge-Base for &lt;a href="https://gitlab.com/gbraad/knowledge-base/blob/master/technology/openstack/tripleo.md"&gt;development/architecture notes&lt;/a&gt; on TripleO  &lt;/li&gt;
&lt;li&gt;Openstack deployment &lt;a href="https://remote-lab.net/rdo-manager-ha-openstack-deployment"&gt;using RDO-Manager&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="OpenStack"/><category term="openstack"/><category term="tripleo"/><category term="rdo"/></entry><entry><title>Building a multi-tier application using OpenStack (PackStack)</title><link href="https://blog.gbraad.nl/building-a-multi-tier-application-using-openstack-packstack.html" rel="alternate"/><published>2016-03-05T00:00:00+08:00</published><updated>2016-09-10T00:00:00+08:00</updated><author><name>Gerard Braad</name></author><id>tag:blog.gbraad.nl,2016-03-05:/building-a-multi-tier-application-using-openstack-packstack.html</id><summary type="html">&lt;p&gt;This is a publication of an article/training class I gave related to setting up
an environment using OpenStack, to host a multi-tier applicatiom.&lt;/p&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In this hands-on-labs you will learn how to set-up an OpenStack environment to
host a multi-tier application; front-end, back-end and the related network
settings to …&lt;/p&gt;</summary><content type="html">&lt;p&gt;This is a publication of an article/training class I gave related to setting up
an environment using OpenStack, to host a multi-tier applicatiom.&lt;/p&gt;
&lt;h2&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In this hands-on-labs you will learn how to set-up an OpenStack environment to
host a multi-tier application; front-end, back-end and the related network
settings to prevent access to back-end servers, etc.&lt;/p&gt;
&lt;p&gt;To setup the environment quickly, we will be using PackStack. PackStack is an
installation utility to quickly deploy an OpenStack cloud. In our case we will
use the all-in-one solutiion which allows a single node environment to
test deploying our multi-tier application.&lt;/p&gt;
&lt;h2&gt;Setup packstack environment&lt;/h2&gt;
&lt;p&gt;Use a RHEL or CentOS 7 installation.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;disable&lt;span class="w"&gt; &lt;/span&gt;NetworkManager
$&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;network
$&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;stop&lt;span class="w"&gt; &lt;/span&gt;NetworkManager.service
$&lt;span class="w"&gt; &lt;/span&gt;systemctl&lt;span class="w"&gt; &lt;/span&gt;start&lt;span class="w"&gt; &lt;/span&gt;network.service
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;yum&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;https://www.rdoproject.org/repos/rdo-release.rpm
$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;yum&lt;span class="w"&gt; &lt;/span&gt;update&lt;span class="w"&gt; &lt;/span&gt;-y
$&lt;span class="w"&gt; &lt;/span&gt;sudo&lt;span class="w"&gt; &lt;/span&gt;yum&lt;span class="w"&gt; &lt;/span&gt;install&lt;span class="w"&gt; &lt;/span&gt;-y&lt;span class="w"&gt; &lt;/span&gt;openstack-packstack
$&lt;span class="w"&gt; &lt;/span&gt;packstack&lt;span class="w"&gt; &lt;/span&gt;--allinone&lt;span class="w"&gt; &lt;/span&gt;--os-neutron-lbaas-install&lt;span class="o"&gt;=&lt;/span&gt;y
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Check environment&lt;/h2&gt;
&lt;p&gt;In order to start using &lt;em&gt;OpenStack&lt;/em&gt;, you’ll need to authenticate as a tenant. To
do this, run the following command in order to put the demo user’s credentials
in your environment.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nb"&gt;source&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;~/keystonerc_admin
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;The installation automatically creates two networks for you &lt;em&gt;‘private’&lt;/em&gt; and
&lt;em&gt;‘public’&lt;/em&gt;. The &lt;em&gt;‘public’&lt;/em&gt; network we’ll use to allocate floating ips out of
later. Running &lt;code&gt;openstack network list&lt;/code&gt; will show this.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;network&lt;span class="w"&gt; &lt;/span&gt;list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;+--------------------------------------+---------+--------------------------------------+&lt;/span&gt;
&lt;span class="c"&gt;| ID                                   | Name    | Subnets                              |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+---------+--------------------------------------+&lt;/span&gt;
&lt;span class="c"&gt;| 84aff6b0&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;2291&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;41b5&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;9871&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;d3d24906e358 | private | 92432fb8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8c29&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4abe&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;98d8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;de8bf161a18b |&lt;/span&gt;
&lt;span class="c"&gt;| 427becab&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;54af&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4b43&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;a5d2&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;e292b13b6a86 | public  | 78eff45a&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;25f2&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4904&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;bab8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;a8795d9a7f9b |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+---------+--------------------------------------+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Setup security groups&lt;/h2&gt;
&lt;p&gt;First we’ll create the three security groups we’ll need to contain the members:
web, database and ssh.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;security&lt;span class="w"&gt; &lt;/span&gt;group&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;web
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;+-------------+--------------------------------------+&lt;/span&gt;
&lt;span class="c"&gt;| Field       | Value                                |&lt;/span&gt;
&lt;span class="nb"&gt;+-------------+--------------------------------------+&lt;/span&gt;
&lt;span class="c"&gt;| description | web                                  |&lt;/span&gt;
&lt;span class="c"&gt;| id          | a98fcd2f&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;a828&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4a88&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;92aa&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;36e3c1223a92 |&lt;/span&gt;
&lt;span class="c"&gt;| name        | web                                  |&lt;/span&gt;
&lt;span class="c"&gt;| rules       | &lt;/span&gt;&lt;span class="k"&gt;[]&lt;/span&gt;&lt;span class="c"&gt;                                   |&lt;/span&gt;
&lt;span class="c"&gt;| tenant_id   | 3d44af649a1c42fcaa102ed11e3f010f     |&lt;/span&gt;
&lt;span class="nb"&gt;+-------------+--------------------------------------+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;security&lt;span class="w"&gt; &lt;/span&gt;group&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;database
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;+-------------+--------------------------------------+&lt;/span&gt;
&lt;span class="c"&gt;| Field       | Value                                |&lt;/span&gt;
&lt;span class="nb"&gt;+-------------+--------------------------------------+&lt;/span&gt;
&lt;span class="c"&gt;| description | database                             |&lt;/span&gt;
&lt;span class="c"&gt;| id          | cf6c0380&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;e255&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4ba8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;9258&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;bb8e9c062fa7 |&lt;/span&gt;
&lt;span class="c"&gt;| name        | database                             |&lt;/span&gt;
&lt;span class="c"&gt;| rules       | &lt;/span&gt;&lt;span class="k"&gt;[]&lt;/span&gt;&lt;span class="c"&gt;                                   |&lt;/span&gt;
&lt;span class="c"&gt;| tenant_id   | 3d44af649a1c42fcaa102ed11e3f010f     |&lt;/span&gt;
&lt;span class="nb"&gt;+-------------+--------------------------------------+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;security&lt;span class="w"&gt; &lt;/span&gt;group&lt;span class="w"&gt; &lt;/span&gt;create&lt;span class="w"&gt; &lt;/span&gt;ssh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;+-------------+--------------------------------------+&lt;/span&gt;
&lt;span class="c"&gt;| Field       | Value                                |&lt;/span&gt;
&lt;span class="nb"&gt;+-------------+--------------------------------------+&lt;/span&gt;
&lt;span class="c"&gt;| description | ssh                                  |&lt;/span&gt;
&lt;span class="c"&gt;| id          | 141ed0d0&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;c004&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;457d&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8efa&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;45e0fd2dc986 |&lt;/span&gt;
&lt;span class="c"&gt;| name        | ssh                                  |&lt;/span&gt;
&lt;span class="c"&gt;| rules       | &lt;/span&gt;&lt;span class="k"&gt;[]&lt;/span&gt;&lt;span class="c"&gt;                                   |&lt;/span&gt;
&lt;span class="c"&gt;| tenant_id   | 3d44af649a1c42fcaa102ed11e3f010f     |&lt;/span&gt;
&lt;span class="nb"&gt;+-------------+--------------------------------------+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;security&lt;span class="w"&gt; &lt;/span&gt;group&lt;span class="w"&gt; &lt;/span&gt;list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;+--------------------------------------+----------+------------------------+&lt;/span&gt;
&lt;span class="c"&gt;| ID                                   | Name     | Description            |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+----------+------------------------+&lt;/span&gt;
&lt;span class="c"&gt;| cf6c0380&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;e255&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4ba8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;9258&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;bb8e9c062fa7 | database | database               |&lt;/span&gt;
&lt;span class="c"&gt;| 379b58b2&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;7ca3&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;431e&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;ae1f&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;cd6a627a9b30 | default  | Default security group |&lt;/span&gt;
&lt;span class="c"&gt;| 141ed0d0&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;c004&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;457d&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8efa&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;45e0fd2dc986 | ssh      | ssh                    |&lt;/span&gt;
&lt;span class="c"&gt;| a98fcd2f&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;a828&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4a88&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;92aa&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;36e3c1223a92 | web      | web                    |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+----------+------------------------+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we’ll add rules into these security groups for their desired functionality.&lt;/p&gt;
&lt;p&gt;Allow all HTTP traffic on port 80 to the &lt;code&gt;web&lt;/code&gt; security group:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;security-group-rule-create&lt;span class="w"&gt; &lt;/span&gt;--direction&lt;span class="w"&gt; &lt;/span&gt;ingress&lt;span class="w"&gt; &lt;/span&gt;--protocol&lt;span class="w"&gt; &lt;/span&gt;TCP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\ &lt;/span&gt;
&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;--port-range-min&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--port-range-max&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;web
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;Created&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;security_group_rule&lt;/span&gt;&lt;span class="p"&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="nx"&gt;Field&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="nx"&gt;Value&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="nx"&gt;direction&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="nx"&gt;ingress&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ethertype&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="nx"&gt;IPv4&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;id&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="nx"&gt;b293d93a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="nx"&gt;c2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4854&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;a890&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nx"&gt;ce65639f870&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;port_range_max&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="mi"&gt;80&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;port_range_min&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="mi"&gt;80&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;protocol&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="nx"&gt;tcp&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;remote_group_id&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;remote_ip_prefix&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;security_group_id&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="nx"&gt;a98fcd2f&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;a828&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;a88&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;92&lt;/span&gt;&lt;span class="nx"&gt;aa&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="nx"&gt;e3c1223a92&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tenant_id&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="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;d44af649a1c42fcaa102ed11e3f010f&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Allow database servers to be accessed from the web servers:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;security-group-rule-create&lt;span class="w"&gt; &lt;/span&gt;--direction&lt;span class="w"&gt; &lt;/span&gt;ingress&lt;span class="w"&gt; &lt;/span&gt;--protocol&lt;span class="w"&gt; &lt;/span&gt;TCP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;--port-range-min&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3306&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--port-range-max&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3306&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--remote-group-id&lt;span class="w"&gt; &lt;/span&gt;web&lt;span class="w"&gt; &lt;/span&gt;database
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;Created&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;security_group_rule&lt;/span&gt;&lt;span class="p"&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="nx"&gt;Field&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="nx"&gt;Value&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="nx"&gt;direction&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="nx"&gt;ingress&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ethertype&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="nx"&gt;IPv4&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;id&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="nx"&gt;dfc77fb6&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="nx"&gt;a0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="nx"&gt;ca&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9230&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="nx"&gt;c2cda27c63&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;port_range_max&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="mi"&gt;3306&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;port_range_min&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="mi"&gt;3306&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;protocol&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="nx"&gt;tcp&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;remote_group_id&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="nx"&gt;a98fcd2f&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;a828&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;a88&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;92&lt;/span&gt;&lt;span class="nx"&gt;aa&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="nx"&gt;e3c1223a92&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;remote_ip_prefix&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;security_group_id&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="nx"&gt;cf6c0380&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;e255&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;ba8&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9258&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;bb8e9c062fa7&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tenant_id&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="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;d44af649a1c42fcaa102ed11e3f010f&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Allow the jump host to &lt;code&gt;ssh&lt;/code&gt; into both the database servers and webservers&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;security-group-rule-create&lt;span class="w"&gt; &lt;/span&gt;--direction&lt;span class="w"&gt; &lt;/span&gt;ingress&lt;span class="w"&gt; &lt;/span&gt;--protocol&lt;span class="w"&gt; &lt;/span&gt;TCP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\ &lt;/span&gt;
&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;--port-range-min&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--port-range-max&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--remote-group-id&lt;span class="w"&gt; &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;database
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;Created&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;security_group_rule&lt;/span&gt;&lt;span class="p"&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="nx"&gt;Field&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="nx"&gt;Value&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="nx"&gt;direction&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="nx"&gt;ingress&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ethertype&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="nx"&gt;IPv4&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;id&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="mi"&gt;0&lt;/span&gt;&lt;span class="nx"&gt;c686a2c&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;304&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="nx"&gt;be&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9936&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;cdce46963d46&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;port_range_max&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="mi"&gt;22&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;port_range_min&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="mi"&gt;22&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;protocol&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="nx"&gt;tcp&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;remote_group_id&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="mi"&gt;141&lt;/span&gt;&lt;span class="nx"&gt;ed0d0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;c004&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;457&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="nx"&gt;efa&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="nx"&gt;e0fd2dc986&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;remote_ip_prefix&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;security_group_id&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="nx"&gt;cf6c0380&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;e255&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;ba8&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9258&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;bb8e9c062fa7&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tenant_id&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="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;d44af649a1c42fcaa102ed11e3f010f&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;security-group-rule-create&lt;span class="w"&gt; &lt;/span&gt;--direction&lt;span class="w"&gt; &lt;/span&gt;ingress&lt;span class="w"&gt; &lt;/span&gt;--protocol&lt;span class="w"&gt; &lt;/span&gt;TCP&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;--port-range-min&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--port-range-max&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--remote-group-id&lt;span class="w"&gt; &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;web
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;Created&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;security_group_rule&lt;/span&gt;&lt;span class="p"&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="nx"&gt;Field&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="nx"&gt;Value&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="nx"&gt;direction&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="nx"&gt;ingress&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ethertype&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="nx"&gt;IPv4&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;id&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="mi"&gt;919&lt;/span&gt;&lt;span class="nx"&gt;a6ede&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="nx"&gt;dfd&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4184&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;bf2a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;f07c0527d5bf&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;port_range_max&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="mi"&gt;22&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;port_range_min&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="mi"&gt;22&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;protocol&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="nx"&gt;tcp&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;remote_group_id&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="mi"&gt;141&lt;/span&gt;&lt;span class="nx"&gt;ed0d0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;c004&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;457&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="nx"&gt;efa&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="nx"&gt;e0fd2dc986&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;remote_ip_prefix&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;security_group_id&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="nx"&gt;a98fcd2f&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;a828&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;a88&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;92&lt;/span&gt;&lt;span class="nx"&gt;aa&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="nx"&gt;e3c1223a92&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tenant_id&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="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;d44af649a1c42fcaa102ed11e3f010f&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Allow the outside world to be able to &lt;code&gt;ssh&lt;/code&gt; into the jump host on port 22:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;security-group-rule-create&lt;span class="w"&gt; &lt;/span&gt;--direction&lt;span class="w"&gt; &lt;/span&gt;ingress&lt;span class="w"&gt; &lt;/span&gt;--protocol&lt;span class="w"&gt; &lt;/span&gt;tcp&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;--port-range-min&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--port-range-max&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;22&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;ssh
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;Created&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;security_group_rule&lt;/span&gt;&lt;span class="p"&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="nx"&gt;Field&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="nx"&gt;Value&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="nx"&gt;direction&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="nx"&gt;ingress&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ethertype&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="nx"&gt;IPv4&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;id&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="nx"&gt;fb8dcbe6&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;e553&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;a92&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;aed4&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;aca7f086dca4&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;port_range_max&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="mi"&gt;22&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;port_range_min&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="mi"&gt;22&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;protocol&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="nx"&gt;tcp&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;remote_group_id&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;remote_ip_prefix&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;security_group_id&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="mi"&gt;141&lt;/span&gt;&lt;span class="nx"&gt;ed0d0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;c004&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;457&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="nx"&gt;efa&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;45&lt;/span&gt;&lt;span class="nx"&gt;e0fd2dc986&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tenant_id&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="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;d44af649a1c42fcaa102ed11e3f010f&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h2&gt;Setup virtual machines&lt;/h2&gt;
&lt;p&gt;Now we can boot some virtual machines that will make use of these security
groups. Run &lt;code&gt;openstack net work list&lt;/code&gt; to obtain the private network &lt;code&gt;uuid&lt;/code&gt; that
we are going to be using:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;network&lt;span class="w"&gt; &lt;/span&gt;list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;+--------------------------------------+---------+--------------------------------------+&lt;/span&gt;
&lt;span class="c"&gt;| ID                                   | Name    | Subnets                              |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+---------+--------------------------------------+&lt;/span&gt;
&lt;span class="c"&gt;| 427becab&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;54af&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4b43&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;a5d2&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;e292b13b6a86 | public  | 78eff45a&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;25f2&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4904&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;bab8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;a8795d9a7f9b |&lt;/span&gt;
&lt;span class="c"&gt;| 84aff6b0&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;2291&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;41b5&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;9871&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;d3d24906e358 | private | 92432fb8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8c29&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4abe&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;98d8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;de8bf161a18b |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+---------+--------------------------------------+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Then, we’ll run &lt;code&gt;openstack image list&lt;/code&gt; to determine the images available to boot
our instances with. Since we’re using &lt;em&gt;packstack&lt;/em&gt;, the script automatically
uploaded an image to &lt;em&gt;glance&lt;/em&gt; for us to use.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;image&lt;span class="w"&gt; &lt;/span&gt;list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;+--------------------------------------+--------+&lt;/span&gt;
&lt;span class="c"&gt;| ID                                   | Name   |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+--------+&lt;/span&gt;
&lt;span class="c"&gt;| eea0e326&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8e2e&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;41db&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;80a0&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;1138a4bdd5a6 | cirros |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+--------+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h4&gt;Overview&lt;/h4&gt;
&lt;p&gt;In the next steps we will boot four instances:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;2 web servers&lt;/li&gt;
&lt;li&gt;1 database server&lt;/li&gt;
&lt;li&gt;1 ssh jump host&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We will be creating instances using the smallest flavor available.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;flavor&lt;span class="w"&gt; &lt;/span&gt;list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;+----+-----------+-------+------+-----------+-------+-----------+&lt;/span&gt;
&lt;span class="c"&gt;| ID | Name      |   RAM | Disk | Ephemeral | VCPUs | Is Public |&lt;/span&gt;
&lt;span class="nb"&gt;+----+-----------+-------+------+-----------+-------+-----------+&lt;/span&gt;
&lt;span class="c"&gt;| 1  | m1&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;tiny   |   512 |    1 |         0 |     1 | True      |&lt;/span&gt;
&lt;span class="c"&gt;| 2  | m1&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;small  |  2048 |   20 |         0 |     1 | True      |&lt;/span&gt;
&lt;span class="c"&gt;| 3  | m1&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;medium |  4096 |   40 |         0 |     2 | True      |&lt;/span&gt;
&lt;span class="c"&gt;| 4  | m1&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;large  |  8192 |   80 |         0 |     4 | True      |&lt;/span&gt;
&lt;span class="c"&gt;| 5  | m1&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;xlarge | 16384 |  160 |         0 |     8 | True      |&lt;/span&gt;
&lt;span class="nb"&gt;+----+-----------+-------+------+-----------+-------+-----------+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;So we will be using flavor 1, which means instances are created with 512MB of
memory and a disk of 1G.&lt;/p&gt;
&lt;p&gt;Note:&lt;br&gt;
We also have to make sure that each instances has an IP address on the private
network. For this we are including the &lt;code&gt;--nic net-id=&lt;/code&gt; option specifying the
network ID of the private network.&lt;/p&gt;
&lt;h3&gt;Setup web servers&lt;/h3&gt;
&lt;p&gt;Boot two instances named &lt;code&gt;web_server1&lt;/code&gt; and &lt;code&gt;web_server2&lt;/code&gt; on the private network
using the &lt;code&gt;cirros&lt;/code&gt; image and part of the web security group:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;nova&lt;span class="w"&gt; &lt;/span&gt;boot&lt;span class="w"&gt; &lt;/span&gt;--image&lt;span class="w"&gt; &lt;/span&gt;cirros&lt;span class="w"&gt; &lt;/span&gt;--nic&lt;span class="w"&gt; &lt;/span&gt;net-id&lt;span class="o"&gt;=&lt;/span&gt;84aff6b0-2291-41b5-9871-d3d24906e358&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;--security_groups&lt;span class="w"&gt; &lt;/span&gt;web&lt;span class="w"&gt; &lt;/span&gt;--flavor&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;web_server1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;+--------------------------------------+-----------------------------------------------+
| Property                             | Value                                         |
+--------------------------------------+-----------------------------------------------+
| OS-DCF:diskConfig                    | MANUAL                                        |
| OS-EXT-AZ:availability_zone          |                                               |
| OS-EXT-SRV-ATTR:host                 | -                                             |
| OS-EXT-SRV-ATTR:hypervisor_hostname  | -                                             |
| OS-EXT-SRV-ATTR:instance_name        | instance-00000001                             |
| OS-EXT-STS:power_state               | 0                                             |
| OS-EXT-STS:task_state                | scheduling                                    |
| OS-EXT-STS:vm_state                  | building                                      |
| OS-SRV-USG:launched_at               | -                                             |
| OS-SRV-USG:terminated_at             | -                                             |
| accessIPv4                           |                                               |
| accessIPv6                           |                                               |
| adminPass                            | rijM8RvVKXhd                                  |
| config_drive                         |                                               |
| created                              | 2016-02-25T08:21:23Z                          |
| flavor                               | m1.tiny (1)                                   |
| hostId                               |                                               |
| id                                   | be6ec624-07cd-45c1-8260-211f1f2fd786          |
| image                                | cirros (eea0e326-8e2e-41db-80a0-1138a4bdd5a6) |
| key_name                             | -                                             |
| metadata                             | {}                                            |
| name                                 | web_server1                                   |
| os-extended-volumes:volumes_attached | []                                            |
| progress                             | 0                                             |
| security_groups                      | web                                           |
| status                               | BUILD                                         |
| tenant_id                            | 3d44af649a1c42fcaa102ed11e3f010f              |
| updated                              | 2016-02-25T08:21:24Z                          |
| user_id                              | a72ce317d35c47e8b8274995d0a2af92              |
+--------------------------------------+-----------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;nova&lt;span class="w"&gt; &lt;/span&gt;boot&lt;span class="w"&gt; &lt;/span&gt;--image&lt;span class="w"&gt; &lt;/span&gt;cirros&lt;span class="w"&gt; &lt;/span&gt;--nic&lt;span class="w"&gt; &lt;/span&gt;net-id&lt;span class="o"&gt;=&lt;/span&gt;84aff6b0-2291-41b5-9871-d3d24906e358&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\ &lt;/span&gt;
&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;--security_groups&lt;span class="w"&gt; &lt;/span&gt;web&lt;span class="w"&gt; &lt;/span&gt;--flavor&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;web_server2
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;+--------------------------------------+-----------------------------------------------+
| Property                             | Value                                         |
+--------------------------------------+-----------------------------------------------+
| OS-DCF:diskConfig                    | MANUAL                                        |
| OS-EXT-AZ:availability_zone          |                                               |
| OS-EXT-SRV-ATTR:host                 | -                                             |
| OS-EXT-SRV-ATTR:hypervisor_hostname  | -                                             |
| OS-EXT-SRV-ATTR:instance_name        | instance-00000002                             |
| OS-EXT-STS:power_state               | 0                                             |
| OS-EXT-STS:task_state                | scheduling                                    |
| OS-EXT-STS:vm_state                  | building                                      |
| OS-SRV-USG:launched_at               | -                                             |
| OS-SRV-USG:terminated_at             | -                                             |
| accessIPv4                           |                                               |
| accessIPv6                           |                                               |
| adminPass                            | vyT4575gsqth                                  |
| config_drive                         |                                               |
| created                              | 2016-02-25T08:22:53Z                          |
| flavor                               | m1.tiny (1)                                   |
| hostId                               |                                               |
| id                                   | 146056ad-e8dc-4ad3-8765-97b753f3d040          |
| image                                | cirros (eea0e326-8e2e-41db-80a0-1138a4bdd5a6) |
| key_name                             | -                                             |
| metadata                             | {}                                            |
| name                                 | web_server2                                   |
| os-extended-volumes:volumes_attached | []                                            |
| progress                             | 0                                             |
| security_groups                      | web                                           |
| status                               | BUILD                                         |
| tenant_id                            | 3d44af649a1c42fcaa102ed11e3f010f              |
| updated                              | 2016-02-25T08:22:53Z                          |
| user_id                              | a72ce317d35c47e8b8274995d0a2af92              |
+--------------------------------------+-----------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Setup database server&lt;/h3&gt;
&lt;p&gt;Boot database server&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;nova&lt;span class="w"&gt; &lt;/span&gt;boot&lt;span class="w"&gt; &lt;/span&gt;--image&lt;span class="w"&gt; &lt;/span&gt;cirros&lt;span class="w"&gt; &lt;/span&gt;--nic&lt;span class="w"&gt; &lt;/span&gt;net-id&lt;span class="o"&gt;=&lt;/span&gt;84aff6b0-2291-41b5-9871-d3d24906e358&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;--security_groups&lt;span class="w"&gt; &lt;/span&gt;database&lt;span class="w"&gt; &lt;/span&gt;--flavor&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;database_server
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;+--------------------------------------+-----------------------------------------------+
| Property                             | Value                                         |
+--------------------------------------+-----------------------------------------------+
| OS-DCF:diskConfig                    | MANUAL                                        |
| OS-EXT-AZ:availability_zone          |                                               |
| OS-EXT-SRV-ATTR:host                 | -                                             |
| OS-EXT-SRV-ATTR:hypervisor_hostname  | -                                             |
| OS-EXT-SRV-ATTR:instance_name        | instance-00000003                             |
| OS-EXT-STS:power_state               | 0                                             |
| OS-EXT-STS:task_state                | scheduling                                    |
| OS-EXT-STS:vm_state                  | building                                      |
| OS-SRV-USG:launched_at               | -                                             |
| OS-SRV-USG:terminated_at             | -                                             |
| accessIPv4                           |                                               |
| accessIPv6                           |                                               |
| adminPass                            | 9GJgxdvz3eFQ                                  |
| config_drive                         |                                               |
| created                              | 2016-02-25T08:23:22Z                          |
| flavor                               | m1.tiny (1)                                   |
| hostId                               |                                               |
| id                                   | d66ced0e-3aaf-4c14-8921-229ac6307ecd          |
| image                                | cirros (eea0e326-8e2e-41db-80a0-1138a4bdd5a6) |
| key_name                             | -                                             |
| metadata                             | {}                                            |
| name                                 | database_server                               |
| os-extended-volumes:volumes_attached | []                                            |
| progress                             | 0                                             |
| security_groups                      | database                                      |
| status                               | BUILD                                         |
| tenant_id                            | 3d44af649a1c42fcaa102ed11e3f010f              |
| updated                              | 2016-02-25T08:23:22Z                          |
| user_id                              | a72ce317d35c47e8b8274995d0a2af92              |
+--------------------------------------+-----------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Setup jumphost server&lt;/h3&gt;
&lt;p&gt;Boot ssh jump host&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;nova&lt;span class="w"&gt; &lt;/span&gt;boot&lt;span class="w"&gt; &lt;/span&gt;--image&lt;span class="w"&gt; &lt;/span&gt;cirros&lt;span class="w"&gt; &lt;/span&gt;--nic&lt;span class="w"&gt; &lt;/span&gt;net-id&lt;span class="o"&gt;=&lt;/span&gt;84aff6b0-2291-41b5-9871-d3d24906e358&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;--security_groups&lt;span class="w"&gt; &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;--flavor&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;jumphost
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;+--------------------------------------+-----------------------------------------------+
| Property                             | Value                                         |
+--------------------------------------+-----------------------------------------------+
| OS-DCF:diskConfig                    | MANUAL                                        |
| OS-EXT-AZ:availability_zone          |                                               |
| OS-EXT-SRV-ATTR:host                 | -                                             |
| OS-EXT-SRV-ATTR:hypervisor_hostname  | -                                             |
| OS-EXT-SRV-ATTR:instance_name        | instance-00000004                             |
| OS-EXT-STS:power_state               | 0                                             |
| OS-EXT-STS:task_state                | scheduling                                    |
| OS-EXT-STS:vm_state                  | building                                      |
| OS-SRV-USG:launched_at               | -                                             |
| OS-SRV-USG:terminated_at             | -                                             |
| accessIPv4                           |                                               |
| accessIPv6                           |                                               |
| adminPass                            | jwbUXkmfEK7Y                                  |
| config_drive                         |                                               |
| created                              | 2016-02-25T08:23:54Z                          |
| flavor                               | m1.tiny (1)                                   |
| hostId                               |                                               |
| id                                   | e540896e-e148-414a-9588-3b83d3f2b059          |
| image                                | cirros (eea0e326-8e2e-41db-80a0-1138a4bdd5a6) |
| key_name                             | -                                             |
| metadata                             | {}                                            |
| name                                 | jumphost                                      |
| os-extended-volumes:volumes_attached | []                                            |
| progress                             | 0                                             |
| security_groups                      | ssh                                           |
| status                               | BUILD                                         |
| tenant_id                            | 3d44af649a1c42fcaa102ed11e3f010f              |
| updated                              | 2016-02-25T08:23:54Z                          |
| user_id                              | a72ce317d35c47e8b8274995d0a2af92              |
+--------------------------------------+-----------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Client&lt;/h3&gt;
&lt;p&gt;We will also create a client instance that we will use to access the web servers
from.&lt;/p&gt;
&lt;p&gt;Note: Since we did not specify a security group this instance will be part of a
&lt;code&gt;default&lt;/code&gt; security group which allows the instance to make outgoing connections
to anyone but only accept incoming connections from members of this same
security group.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;nova&lt;span class="w"&gt; &lt;/span&gt;boot&lt;span class="w"&gt; &lt;/span&gt;--image&lt;span class="w"&gt; &lt;/span&gt;cirros&lt;span class="w"&gt; &lt;/span&gt;--nic&lt;span class="w"&gt; &lt;/span&gt;net-id&lt;span class="o"&gt;=&lt;/span&gt;84aff6b0-2291-41b5-9871-d3d24906e358&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;--flavor&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;client
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;+--------------------------------------+-----------------------------------------------+
| Property                             | Value                                         |
+--------------------------------------+-----------------------------------------------+
| OS-DCF:diskConfig                    | MANUAL                                        |
| OS-EXT-AZ:availability_zone          |                                               |
| OS-EXT-SRV-ATTR:host                 | -                                             |
| OS-EXT-SRV-ATTR:hypervisor_hostname  | -                                             |
| OS-EXT-SRV-ATTR:instance_name        | instance-00000005                             |
| OS-EXT-STS:power_state               | 0                                             |
| OS-EXT-STS:task_state                | scheduling                                    |
| OS-EXT-STS:vm_state                  | building                                      |
| OS-SRV-USG:launched_at               | -                                             |
| OS-SRV-USG:terminated_at             | -                                             |
| accessIPv4                           |                                               |
| accessIPv6                           |                                               |
| adminPass                            | c63QG7iE3PrY                                  |
| config_drive                         |                                               |
| created                              | 2016-02-25T08:24:27Z                          |
| flavor                               | m1.tiny (1)                                   |
| hostId                               |                                               |
| id                                   | 8e0179a3-6bf8-4c07-8035-f8916ca3183d          |
| image                                | cirros (eea0e326-8e2e-41db-80a0-1138a4bdd5a6) |
| key_name                             | -                                             |
| metadata                             | {}                                            |
| name                                 | client                                        |
| os-extended-volumes:volumes_attached | []                                            |
| progress                             | 0                                             |
| security_groups                      | default                                       |
| status                               | BUILD                                         |
| tenant_id                            | 3d44af649a1c42fcaa102ed11e3f010f              |
| updated                              | 2016-02-25T08:24:27Z                          |
| user_id                              | a72ce317d35c47e8b8274995d0a2af92              |
+--------------------------------------+-----------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Check virtual machines&lt;/h3&gt;
&lt;p&gt;Running &lt;code&gt;openstack server list&lt;/code&gt; will display the status of the instances. After
a few seconds all of the instances should go to an ACTIVE status.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;server&lt;span class="w"&gt; &lt;/span&gt;list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;+--------------------------------------+-----------------+--------+------------------+&lt;/span&gt;
&lt;span class="c"&gt;| ID                                   | Name            | Status | Networks         |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+-----------------+--------+------------------+&lt;/span&gt;
&lt;span class="c"&gt;| 8e0179a3&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;6bf8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4c07&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8035&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;f8916ca3183d | client          | ACTIVE | private=10&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;7 |&lt;/span&gt;
&lt;span class="c"&gt;| e540896e&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;e148&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;414a&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;9588&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;3b83d3f2b059 | jumphost        | ACTIVE | private=10&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;6 |&lt;/span&gt;
&lt;span class="c"&gt;| d66ced0e&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;3aaf&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4c14&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8921&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;229ac6307ecd | database_server | ACTIVE | private=10&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;5 |&lt;/span&gt;
&lt;span class="c"&gt;| 146056ad&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;e8dc&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4ad3&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8765&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;97b753f3d040 | web_server2     | ACTIVE | private=10&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;4 |&lt;/span&gt;
&lt;span class="c"&gt;| be6ec624&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;07cd&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;45c1&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8260&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;211f1f2fd786 | web_server1     | ACTIVE | private=10&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;3 |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+-----------------+--------+------------------+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Setup public IP address for SSH&lt;/h3&gt;
&lt;p&gt;To make the jumphost publicly accessible on the internet we’ll need to assign a
floating IP to it. To do this first create a floating IP via:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;floatingip-create&lt;span class="w"&gt; &lt;/span&gt;public
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;Created&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;floatingip&lt;/span&gt;&lt;span class="p"&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="nx"&gt;Field&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="nx"&gt;Value&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="nx"&gt;fixed_ip_address&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;floating_ip_address&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="m m-Double"&gt;172.24.4.228&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;floating_network_id&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="mi"&gt;427&lt;/span&gt;&lt;span class="nx"&gt;becab&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;54&lt;/span&gt;&lt;span class="nx"&gt;af&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;b43&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;a5d2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;e292b13b6a86&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;id&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="nx"&gt;ce6efd31&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;97&lt;/span&gt;&lt;span class="nx"&gt;e9&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;428&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;a3ac&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;b5a14e77a305&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;port_id&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;router_id&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;status&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="nx"&gt;DOWN&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tenant_id&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="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;d44af649a1c42fcaa102ed11e3f010f&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Next, we need to determine the port id of the jumpbox:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;port-list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;+--------------------------------------+------+-------------------+-------------------------------------------------------------------------------------+&lt;/span&gt;
&lt;span class="c"&gt;| id                                   | name | mac_address       | fixed_ips                                                                           |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+------+-------------------+-------------------------------------------------------------------------------------+&lt;/span&gt;
&lt;span class="c"&gt;| 551cf7bc&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;802f&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4b02&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;bd3e&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;c44473ffb1ff |      | fa:16:3e:48:a4:d1 | {&amp;quot;subnet_id&amp;quot;: &amp;quot;78eff45a&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;25f2&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4904&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;bab8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;a8795d9a7f9b&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt; &amp;quot;ip_address&amp;quot;: &amp;quot;172&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;24&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;4&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;226&amp;quot;} |&lt;/span&gt;
&lt;span class="c"&gt;| 5d98aa79&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8bc0&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4512&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;a128&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;078281aae2bc |      | fa:16:3e:0d:4b:55 | {&amp;quot;subnet_id&amp;quot;: &amp;quot;92432fb8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8c29&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4abe&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;98d8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;de8bf161a18b&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt; &amp;quot;ip_address&amp;quot;: &amp;quot;10&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;6&amp;quot;}     |&lt;/span&gt;
&lt;span class="c"&gt;| 6aab05f6&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;9176&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;48b4&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;9b0f&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;113593945593 |      | fa:16:3e:2d:b6:a4 | {&amp;quot;subnet_id&amp;quot;: &amp;quot;92432fb8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8c29&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4abe&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;98d8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;de8bf161a18b&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt; &amp;quot;ip_address&amp;quot;: &amp;quot;10&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;1&amp;quot;}     |&lt;/span&gt;
&lt;span class="c"&gt;| 8941a204&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;08e7&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4547&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;b720&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;f9840358929b |      | fa:16:3e:5b:a3:c7 | {&amp;quot;subnet_id&amp;quot;: &amp;quot;78eff45a&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;25f2&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4904&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;bab8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;a8795d9a7f9b&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt; &amp;quot;ip_address&amp;quot;: &amp;quot;172&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;24&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;4&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;228&amp;quot;} |&lt;/span&gt;
&lt;span class="c"&gt;| 9bd695dc&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4e6c&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;40c5&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;952d&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;44269711bd6c |      | fa:16:3e:9e:36:8f | {&amp;quot;subnet_id&amp;quot;: &amp;quot;92432fb8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8c29&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4abe&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;98d8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;de8bf161a18b&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt; &amp;quot;ip_address&amp;quot;: &amp;quot;10&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;3&amp;quot;}     |&lt;/span&gt;
&lt;span class="c"&gt;| afd18b4f&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;c19f&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4c03&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;a049&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;fe8aeae7da49 |      | fa:16:3e:ac:94:5e | {&amp;quot;subnet_id&amp;quot;: &amp;quot;92432fb8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8c29&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4abe&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;98d8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;de8bf161a18b&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt; &amp;quot;ip_address&amp;quot;: &amp;quot;10&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;5&amp;quot;}     |&lt;/span&gt;
&lt;span class="c"&gt;| e63d8edb&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;f10c&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4776&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;a10e&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;cba9ec3f3d56 |      | fa:16:3e:d4:9c:57 | {&amp;quot;subnet_id&amp;quot;: &amp;quot;92432fb8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8c29&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4abe&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;98d8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;de8bf161a18b&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt; &amp;quot;ip_address&amp;quot;: &amp;quot;10&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;4&amp;quot;}     |&lt;/span&gt;
&lt;span class="c"&gt;| f0d35941&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;989c&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4f2b&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;b187&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;872445b0b653 |      | fa:16:3e:0c:7f:d5 | {&amp;quot;subnet_id&amp;quot;: &amp;quot;92432fb8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8c29&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4abe&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;98d8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;de8bf161a18b&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt; &amp;quot;ip_address&amp;quot;: &amp;quot;10&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;7&amp;quot;}     |&lt;/span&gt;
&lt;span class="c"&gt;| f9e097b4&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4227&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;49ee&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;9442&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;643c4186e587 |      | fa:16:3e:a5:36:2c | {&amp;quot;subnet_id&amp;quot;: &amp;quot;92432fb8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8c29&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4abe&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;98d8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;de8bf161a18b&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt; &amp;quot;ip_address&amp;quot;: &amp;quot;10&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;2&amp;quot;}     |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+------+-------------------+-------------------------------------------------------------------------------------+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;and find the &lt;em&gt;id&lt;/em&gt; that matches the IP address of the jumphost (10.0.0.6) and
associate it via:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="cp"&gt;# neutron floatingip-associate [floating_ip id] [port-list id]&lt;/span&gt;
&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;neutron&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;floatingip&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;associate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ce6efd31&lt;/span&gt;&lt;span class="mf"&gt;-97e9&lt;/span&gt;&lt;span class="mi"&gt;-428&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;a3ac&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;b5a14e77a305&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;\
&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="n"&gt;d98aa79&lt;/span&gt;&lt;span class="mi"&gt;-8&lt;/span&gt;&lt;span class="n"&gt;bc0&lt;/span&gt;&lt;span class="mi"&gt;-4512&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;a128&lt;/span&gt;&lt;span class="mo"&gt;-07&lt;/span&gt;&lt;span class="mi"&gt;8281&lt;/span&gt;&lt;span class="n"&gt;aae2bc&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Associated floating IP ce6efd31-97e9-428b-a3ac-b5a14e77a305
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;floatingip-list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;+--------------------------------------+------------------+---------------------+--------------------------------------+&lt;/span&gt;
&lt;span class="c"&gt;| id                                   | fixed_ip_address | floating_ip_address | port_id                              |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+------------------+---------------------+--------------------------------------+&lt;/span&gt;
&lt;span class="c"&gt;| ce6efd31&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;97e9&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;428b&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;a3ac&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;b5a14e77a305 | 10&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;6         | 172&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;24&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;4&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;228        | 5d98aa79&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8bc0&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4512&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;a128&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;078281aae2bc |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+------------------+---------------------+--------------------------------------+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Verify SSH connectivity&lt;/h3&gt;
&lt;p&gt;Now you should be able to ssh to the jumbox via with password &lt;code&gt;cubswin:)&lt;/code&gt; :&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;ssh&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;cirros&lt;/span&gt;&lt;span class="mf"&gt;@172.24.4.228&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;The&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;authenticity&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="mf"&gt;172.24.4.3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;172.24.4.3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;can&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;be&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;established&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;RSA&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;fingerprint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;90&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ae&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;eb&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;be&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;83&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;ae&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;33&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;fe&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;84&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;88&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;d1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;Are&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;sure&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;want&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;connecting&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;yes&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;no&lt;/span&gt;&lt;span class="p"&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;yes&lt;/span&gt;
&lt;span class="nl"&gt;Warning&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Permanently&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;added&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="mf"&gt;172.24.4.3&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RSA&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;list&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;known&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hosts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="n"&gt;cirros&lt;/span&gt;&lt;span class="mf"&gt;@172.24.4.3&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;$&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After logging into the jumpbox you’ll be able to ssh into your &lt;em&gt;webserver1&lt;/em&gt;,
&lt;em&gt;webserver2&lt;/em&gt;, and &lt;em&gt;database server&lt;/em&gt; via:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.0.0.3
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="mf"&gt;10.0.0.3&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;is&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;not&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;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;trusted&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;hosts&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fingerprint&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;md5&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;e7&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;c3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;d2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;93&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;eb&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;65&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="n"&gt;d&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;e6&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;01&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;b3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;e6&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;72&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;fd&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;c0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;Do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;you&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;want&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;continue&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;connecting&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;
&lt;span class="n"&gt;cirros&lt;/span&gt;&lt;span class="mf"&gt;@10.0.0.3&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.0.0.4
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;ssh&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.0.0.5
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;...
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;None of those instances will be able to ssh to each other. The point of this
instance is so that you do not need to have all of your other instances publicly
addressable and directly accessible via the internet.&lt;/p&gt;
&lt;h3&gt;Simulate web server&lt;/h3&gt;
&lt;p&gt;Now let’s log in to &lt;code&gt;web_server1&lt;/code&gt; and &lt;code&gt;web_server2&lt;/code&gt; (via ssh or via horizon) and
setup a simple web server to handle requests and reply with who they are:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# On web_server 1 (10.0.0.3)&lt;/span&gt;
&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;HTTP/1.0 200 OK&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n n-Quoted"&gt;`hostname`&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;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;done&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;
&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# on web_server 2 (10.0.0.4)&lt;/span&gt;
&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;HTTP/1.0 200 OK&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n n-Quoted"&gt;`hostname`&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;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;done&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;
&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;exit&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Simulate HTTP request&lt;/h3&gt;
&lt;p&gt;Now, log in to your &lt;em&gt;client&lt;/em&gt; virtual machine (from the web console). From there
if you run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;-O&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;http://10.0.0.3/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Connecting to 10.0.0.3 (10.0.0.3:80)
web-server1
               100% |************************************| 12 0:00:00 ETA
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;-O&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;http://10.0.0.4/
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Connecting to 10.0.0.4 (10.0.0.4:80)
web-server2
               100% |************************************| 12 0:00:00 ETA
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;This demonstrates that our simple web server is working on our two web server
instances.&lt;/p&gt;
&lt;h3&gt;Optional check&lt;/h3&gt;
&lt;p&gt;We can demonstrate that the web security group is working correctly by killing
our simple web server and changing the port number. (Note: to kill the web
server you may need to hold control + c for a second in order for it to break
out of the while loop before another instance of nc is created.)&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="c1"&gt;# On web_server 1 &lt;/span&gt;
&lt;span class="n"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;echo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;HTTP/1.0 200 OK&lt;/span&gt;&lt;span class="se"&gt;\r\n\r\n&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;&lt;/span&gt;&lt;span class="n n-Quoted"&gt;`hostname`&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;sudo&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;nc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;p&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;81&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;done&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now on the client run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;-O&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;http://10.0.0.3:81
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nv"&gt;Connecting&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt;.&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="ss"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt;.&lt;span class="mi"&gt;0&lt;/span&gt;.&lt;span class="mi"&gt;3&lt;/span&gt;:&lt;span class="mi"&gt;81&lt;/span&gt;&lt;span class="ss"&gt;)&lt;/span&gt;
&lt;span class="nv"&gt;wget&lt;/span&gt;:&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;can&lt;/span&gt;&lt;span class="err"&gt;&amp;#39;t connect to remote host (10.0.0.3): Connection timed out&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;As you can see the request is never answered as expected because our web
security group does not allow port 81 ingress. Now let’s set the web server to
run on port 80 again.&lt;/p&gt;
&lt;h3&gt;Provision loadbalancer&lt;/h3&gt;
&lt;p&gt;At this point were going to provision loadbalancer via neutron in order to load
balance requests between our two web server instances.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;subnet-list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;+--------------------------------------+----------------+-----------------+--------------------------------------------------+&lt;/span&gt;
&lt;span class="c"&gt;| id                                   | name           | cidr            | allocation_pools                                 |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+----------------+-----------------+--------------------------------------------------+&lt;/span&gt;
&lt;span class="c"&gt;| 78eff45a&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;25f2&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4904&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;bab8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;a8795d9a7f9b | public_subnet  | 172&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;24&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;4&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;224/28 | {&amp;quot;start&amp;quot;: &amp;quot;172&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;24&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;4&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;226&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt; &amp;quot;end&amp;quot;: &amp;quot;172&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;24&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;4&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;238&amp;quot;} |&lt;/span&gt;
&lt;span class="c"&gt;| 92432fb8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8c29&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4abe&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;98d8&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;de8bf161a18b | private_subnet | 10&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0/24     | {&amp;quot;start&amp;quot;: &amp;quot;10&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;2&amp;quot;&lt;/span&gt;&lt;span class="nt"&gt;,&lt;/span&gt;&lt;span class="c"&gt; &amp;quot;end&amp;quot;: &amp;quot;10&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;254&amp;quot;}       |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+----------------+-----------------+--------------------------------------------------+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Create a loadbalancer pool:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;lb-pool-create&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;http-pool&lt;span class="w"&gt; &lt;/span&gt;--lb-method&lt;span class="w"&gt; &lt;/span&gt;ROUND_ROBIN&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;--protocol&lt;span class="w"&gt; &lt;/span&gt;HTTP&lt;span class="w"&gt; &lt;/span&gt;--subnet-id&lt;span class="w"&gt; &lt;/span&gt;92432fb8-8c29-4abe-98d8-de8bf161a18b
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="n"&gt;Created&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;pool&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="o"&gt;+------------------------+--------------------------------------+&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Field&lt;/span&gt;                  &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;Value&lt;/span&gt;                                &lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+------------------------+--------------------------------------+&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;admin_state_up&lt;/span&gt;         &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;True&lt;/span&gt;                                 &lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;description&lt;/span&gt;            &lt;span class="p"&gt;|&lt;/span&gt;                                      &lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;health_monitors&lt;/span&gt;        &lt;span class="p"&gt;|&lt;/span&gt;                                      &lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;health_monitors_status&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;                                      &lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;                     &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;51&lt;/span&gt;&lt;span class="n"&gt;ca1962&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;a24a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;f43&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;920&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;162&lt;/span&gt;&lt;span class="n"&gt;a03a45c51&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;lb_method&lt;/span&gt;              &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;ROUND_ROBIN&lt;/span&gt;                          &lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;members&lt;/span&gt;                &lt;span class="p"&gt;|&lt;/span&gt;                                      &lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;                   &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;pool&lt;/span&gt;                            &lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;protocol&lt;/span&gt;               &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;HTTP&lt;/span&gt;                                 &lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;provider&lt;/span&gt;               &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;haproxy&lt;/span&gt;                              &lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;                 &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;PENDING_CREATE&lt;/span&gt;                       &lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;status_description&lt;/span&gt;     &lt;span class="p"&gt;|&lt;/span&gt;                                      &lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;subnet_id&lt;/span&gt;              &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;92432&lt;/span&gt;&lt;span class="n"&gt;fb8&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="n"&gt;c29&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="n"&gt;abe&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;98&lt;/span&gt;&lt;span class="n"&gt;d8&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;de8bf161a18b&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;tenant_id&lt;/span&gt;              &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="n"&gt;d44af649a1c42fcaa102ed11e3f010f&lt;/span&gt;     &lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;vip_id&lt;/span&gt;                 &lt;span class="p"&gt;|&lt;/span&gt;                                      &lt;span class="p"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+------------------------+--------------------------------------+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;You can verify the creation of the &lt;em&gt;http-pool&lt;/em&gt; with the &lt;code&gt;neutron lb-pool-list&lt;/code&gt;
and &lt;code&gt;neutron lb-pool-show http-pool&lt;/code&gt; command.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;lb-pool-list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;+--------------------------------------+-----------+----------+-------------+----------+----------------+--------+&lt;/span&gt;
&lt;span class="c"&gt;| id                                   | name      | provider | lb_method   | protocol | admin_state_up | status |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+-----------+----------+-------------+----------+----------------+--------+&lt;/span&gt;
&lt;span class="c"&gt;| 51ca1962&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;a24a&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;4f43&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;920f&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;162a03a45c51 | http&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;pool | haproxy  | ROUND_ROBIN | HTTP     | True           | ACTIVE |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+-----------+----------+-------------+----------+----------------+--------+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;lb-pool-show&lt;span class="w"&gt; &lt;/span&gt;http-pool
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;+------------------------+--------------------------------------+
| Field                  | Value                                |
+------------------------+--------------------------------------+
| admin_state_up         | True                                 |
| description            |                                      |
| health_monitors        |                                      |
| health_monitors_status |                                      |
| id                     | 51ca1962-a24a-4f43-920f-162a03a45c51 |
| lb_method              | ROUND_ROBIN                          |
| members                |                                      |
| name                   | http-pool                            |
| protocol               | HTTP                                 |
| provider               | haproxy                              |
| status                 | ACTIVE                               |
| status_description     |                                      |
| subnet_id              | 92432fb8-8c29-4abe-98d8-de8bf161a18b |
| tenant_id              | 3d44af649a1c42fcaa102ed11e3f010f     |
| vip_id                 |                                      |
+------------------------+--------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now, let’s create a health monitor, which checks to make sure our instances are
still running and associate that with the pool:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;lbaas-healthmonitor-create&lt;span class="w"&gt; &lt;/span&gt;--delay&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--type&lt;span class="w"&gt; &lt;/span&gt;HTTP&lt;span class="w"&gt; &lt;/span&gt;--max-retries&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;--timeout&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--pool&lt;span class="w"&gt; &lt;/span&gt;webserver-pool
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Adding loadbalancer members&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;lb-member-create&lt;span class="w"&gt; &lt;/span&gt;--address&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.0.0.3&lt;span class="w"&gt; &lt;/span&gt;--protocol-port&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;http-pool
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;Created&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;member&lt;/span&gt;&lt;span class="p"&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="nx"&gt;Field&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="nx"&gt;Value&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="nx"&gt;address&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="m m-Double"&gt;10.0.0.3&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;admin_state_up&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="nx"&gt;True&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;id&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="mi"&gt;36&lt;/span&gt;&lt;span class="nx"&gt;b01f84&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;a273&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;417&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9588&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="nx"&gt;cceea18868&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pool_id&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="mi"&gt;51&lt;/span&gt;&lt;span class="nx"&gt;ca1962&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;a24a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;f43&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;920&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;162&lt;/span&gt;&lt;span class="nx"&gt;a03a45c51&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;protocol_port&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="mi"&gt;80&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;status&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="nx"&gt;PENDING_CREATE&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;status_description&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tenant_id&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="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;d44af649a1c42fcaa102ed11e3f010f&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;weight&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="mi"&gt;1&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;lb-member-create&lt;span class="w"&gt; &lt;/span&gt;--address&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;.0.0.4&lt;span class="w"&gt; &lt;/span&gt;--protocol-port&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;http-pool
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;Created&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;member&lt;/span&gt;&lt;span class="p"&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="nx"&gt;Field&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="nx"&gt;Value&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="nx"&gt;address&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="m m-Double"&gt;10.0.0.4&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;admin_state_up&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="nx"&gt;True&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;id&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="mi"&gt;5&lt;/span&gt;&lt;span class="nx"&gt;d68b992&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;d09f&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;408&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8049&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;353&lt;/span&gt;&lt;span class="nx"&gt;e702cc990&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pool_id&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="mi"&gt;51&lt;/span&gt;&lt;span class="nx"&gt;ca1962&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;a24a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;f43&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;920&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;162&lt;/span&gt;&lt;span class="nx"&gt;a03a45c51&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;protocol_port&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="mi"&gt;80&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;status&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="nx"&gt;PENDING_CREATE&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;status_description&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tenant_id&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="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;d44af649a1c42fcaa102ed11e3f010f&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;weight&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="mi"&gt;1&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After this you can verify the nodes have been added to the loadbalancer pool.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;lb-member-list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nb"&gt;+--------------------------------------+----------+---------------+--------+----------------+--------+&lt;/span&gt;
&lt;span class="c"&gt;| id                                   | address  | protocol_port | weight | admin_state_up | status |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+----------+---------------+--------+----------------+--------+&lt;/span&gt;
&lt;span class="c"&gt;| 36b01f84&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;a273&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;417f&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;9588&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;15cceea18868 | 10&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;3 |            80 |      1 | True           | ACTIVE |&lt;/span&gt;
&lt;span class="c"&gt;| 5d68b992&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;d09f&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;408b&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;8049&lt;/span&gt;&lt;span class="nb"&gt;-&lt;/span&gt;&lt;span class="c"&gt;353e702cc990 | 10&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;0&lt;/span&gt;&lt;span class="nt"&gt;.&lt;/span&gt;&lt;span class="c"&gt;4 |            80 |      1 | True           | ACTIVE |&lt;/span&gt;
&lt;span class="nb"&gt;+--------------------------------------+----------+---------------+--------+----------------+--------+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Add healthmonitor&lt;/h3&gt;
&lt;p&gt;We need to create a health monitor, which will check our instances to make sure they are still running&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;lb-healthmonitor-create&lt;span class="w"&gt; &lt;/span&gt;--delay&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;--type&lt;span class="w"&gt; &lt;/span&gt;HTTP&lt;span class="w"&gt; &lt;/span&gt;--max-retries&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;--timeout&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;Created&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;health_monitor&lt;/span&gt;&lt;span class="p"&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="nx"&gt;Field&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="nx"&gt;Value&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="nx"&gt;admin_state_up&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="nx"&gt;True&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;delay&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="mi"&gt;3&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;expected_codes&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="mi"&gt;200&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;http_method&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="nx"&gt;GET&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;id&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="mi"&gt;05&lt;/span&gt;&lt;span class="nx"&gt;cbf7f9&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;d01b&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;483&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;934&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8955&lt;/span&gt;&lt;span class="nx"&gt;b14a1653&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;max_retries&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="mi"&gt;3&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pools&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tenant_id&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="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;d44af649a1c42fcaa102ed11e3f010f&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;timeout&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="mi"&gt;3&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="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;type&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="nx"&gt;HTTP&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;url_path&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="o"&gt;|&lt;/span&gt;
&lt;span class="o"&gt;+----------------+--------------------------------------+&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Now we have to associate the health monitor to the previously created
loadbalancer pool.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;lb-healthmonitor-associate&lt;span class="w"&gt; &lt;/span&gt;05cbf7f9-d01b-483b-934e-8955b14a1653&lt;span class="w"&gt; &lt;/span&gt;http-pool
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Associated health monitor 05cbf7f9-d01b-483b-934e-8955b14a1653
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To make the loadbalancer and associated health monitor available, we need to
assign it a Virual IP. The address will be allocated from the private subnet.
This address will redirect the request to either instance within the pool to
handle the request.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;lb-vip-create&lt;span class="w"&gt; &lt;/span&gt;--name&lt;span class="w"&gt; &lt;/span&gt;webserver-vip&lt;span class="w"&gt; &lt;/span&gt;--protocol-port&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;80&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;--protocol&lt;span class="w"&gt; &lt;/span&gt;HTTP&lt;span class="w"&gt; &lt;/span&gt;--subnet-id&lt;span class="w"&gt; &lt;/span&gt;92432fb8-8c29-4abe-98d8-de8bf161a18b&lt;span class="w"&gt; &lt;/span&gt;http-pool
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;Created&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;vip&lt;/span&gt;&lt;span class="p"&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="nx"&gt;Field&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="nx"&gt;Value&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="nx"&gt;address&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="m m-Double"&gt;10.0.0.8&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;admin_state_up&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="nx"&gt;True&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;connection_limit&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="mi"&gt;1&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;description&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;id&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="nx"&gt;b9ca33b0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;b09c&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;e7d&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="nx"&gt;ab7&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;77&lt;/span&gt;&lt;span class="nx"&gt;fe5207add6&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;name&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="nx"&gt;webserver&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;vip&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;pool_id&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="mi"&gt;51&lt;/span&gt;&lt;span class="nx"&gt;ca1962&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;a24a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;f43&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;920&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;162&lt;/span&gt;&lt;span class="nx"&gt;a03a45c51&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;port_id&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="nx"&gt;ecbadc53&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5266&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4146&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;bbb3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;d1b6d383be10&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;protocol&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="nx"&gt;HTTP&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;protocol_port&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="mi"&gt;80&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;session_persistence&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;status&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="nx"&gt;PENDING_CREATE&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;status_description&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;subnet_id&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="mi"&gt;92432&lt;/span&gt;&lt;span class="nx"&gt;fb8&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="nx"&gt;c29&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;abe&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;98&lt;/span&gt;&lt;span class="nx"&gt;d8&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;de8bf161a18b&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tenant_id&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="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;d44af649a1c42fcaa102ed11e3f010f&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Verify loadbalancer&lt;/h3&gt;
&lt;p&gt;Finally, let’s test out the loadbalancer. From the client instance we should be
able to run wget at 10.0.0.8 and see that it loadbalancers our requests.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&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;i&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="k"&gt;$(&lt;/span&gt;seq&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;-O&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;http://10.0.0.8/&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Connecting to 10.0.0.8 (10.0.0.8:80)
web-server1
&lt;span class="k"&gt;-&lt;/span&gt;                    100% |************************************| 12 0:00:00 ETA
Connecting to 10.0.0.8 (10.0.0.8:80)
web-server2
&lt;span class="k"&gt;-&lt;/span&gt;                    100% |************************************| 12 0:00:00 ETA
Connecting to 10.0.0.8 (10.0.0.8:80)
web-server1
&lt;span class="k"&gt;-&lt;/span&gt;                    100% |************************************| 12 0:00:00 ETA
Connecting to 10.0.0.8 (10.0.0.8:80)
web-server2
&lt;span class="k"&gt;-&lt;/span&gt;                    100% |************************************| 12 0:00:00 ETA
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;From the output above you can see that the the requests are being handled by
&lt;code&gt;web_server1&lt;/code&gt; then &lt;code&gt;web_server2&lt;/code&gt; in an alternating fashion according to the
round robin method.&lt;/p&gt;
&lt;h3&gt;Setup public IP address for web traffic&lt;/h3&gt;
&lt;p&gt;Now to make our VIP publicly accessible via the internet we need to create
another floating IP:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;floatingip-create&lt;span class="w"&gt; &lt;/span&gt;public
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="nx"&gt;Created&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;new&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;floatingip&lt;/span&gt;&lt;span class="p"&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="nx"&gt;Field&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="nx"&gt;Value&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="nx"&gt;fixed_ip_address&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;floating_ip_address&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="m m-Double"&gt;172.24.4.229&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;floating_network_id&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="mi"&gt;427&lt;/span&gt;&lt;span class="nx"&gt;becab&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;54&lt;/span&gt;&lt;span class="nx"&gt;af&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;b43&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;a5d2&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;e292b13b6a86&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;id&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="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;c15f8a4&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;bdc6&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4154&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="nx"&gt;bfa&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;e8b0674079ca&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;port_id&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;router_id&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;status&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="nx"&gt;DOWN&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;tenant_id&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="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;d44af649a1c42fcaa102ed11e3f010f&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Determine the port_id for the Virtual IP we created earlier:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;port-list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&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="nx"&gt;id&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="nx"&gt;name&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="nx"&gt;mac_address&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="nx"&gt;fixed_ips&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="mi"&gt;54&lt;/span&gt;&lt;span class="nx"&gt;b17392&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;dce7&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;d6a&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="nx"&gt;cce&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;153&lt;/span&gt;&lt;span class="nx"&gt;fccb5d441&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="nx"&gt;fa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;f0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;c7&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;cf&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="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;subnet_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;78eff45a-25f2-4904-bab8-a8795d9a7f9b&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ip_address&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;172.24.4.229&amp;quot;&lt;/span&gt;&lt;span class="p"&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="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;551&lt;/span&gt;&lt;span class="nx"&gt;cf7bc&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;802&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;b02&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;bd3e&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;c44473ffb1ff&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="nx"&gt;fa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;a4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;d1&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="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;subnet_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;78eff45a-25f2-4904-bab8-a8795d9a7f9b&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ip_address&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;172.24.4.226&amp;quot;&lt;/span&gt;&lt;span class="p"&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="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nx"&gt;d98aa79&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="nx"&gt;bc0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4512&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;a128&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;078281&lt;/span&gt;&lt;span class="nx"&gt;aae2bc&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="nx"&gt;fa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;55&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="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;subnet_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;92432fb8-8c29-4abe-98d8-de8bf161a18b&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ip_address&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10.0.0.6&amp;quot;&lt;/span&gt;&lt;span class="p"&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="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="nx"&gt;aab05f6&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9176&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;48&lt;/span&gt;&lt;span class="nx"&gt;b4&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="nx"&gt;b0f&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;113593945593&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="nx"&gt;fa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;b6&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;a4&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="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;subnet_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;92432fb8-8c29-4abe-98d8-de8bf161a18b&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ip_address&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10.0.0.1&amp;quot;&lt;/span&gt;&lt;span class="p"&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="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8941&lt;/span&gt;&lt;span class="nx"&gt;a204&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;08&lt;/span&gt;&lt;span class="nx"&gt;e7&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4547&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;b720&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;f9840358929b&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="nx"&gt;fa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;a3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;c7&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="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;subnet_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;78eff45a-25f2-4904-bab8-a8795d9a7f9b&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ip_address&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;172.24.4.228&amp;quot;&lt;/span&gt;&lt;span class="p"&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="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="nx"&gt;bd695dc&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;e6c&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="nx"&gt;c5&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;952&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;44269711&lt;/span&gt;&lt;span class="nx"&gt;bd6c&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="nx"&gt;fa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="nx"&gt;f&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="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;subnet_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;92432fb8-8c29-4abe-98d8-de8bf161a18b&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ip_address&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10.0.0.3&amp;quot;&lt;/span&gt;&lt;span class="p"&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;afd18b4f&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;c19f&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;c03&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;a049&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;fe8aeae7da49&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="nx"&gt;fa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;ac&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;94&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="nx"&gt;e&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="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;subnet_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;92432fb8-8c29-4abe-98d8-de8bf161a18b&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ip_address&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10.0.0.5&amp;quot;&lt;/span&gt;&lt;span class="p"&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;e63d8edb&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;f10c&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4776&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;a10e&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;cba9ec3f3d56&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="nx"&gt;fa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;d4&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;57&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="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;subnet_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;92432fb8-8c29-4abe-98d8-de8bf161a18b&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ip_address&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10.0.0.4&amp;quot;&lt;/span&gt;&lt;span class="p"&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ecbadc53&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;5266&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4146&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;bbb3&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;d1b6d383be10&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="nx"&gt;vip&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;b9ca33b0&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;b09c&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;e7d&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="nx"&gt;ab7&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;77&lt;/span&gt;&lt;span class="nx"&gt;fe5207add6&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="nx"&gt;fa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;41&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;eb&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="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;subnet_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;92432fb8-8c29-4abe-98d8-de8bf161a18b&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ip_address&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10.0.0.8&amp;quot;&lt;/span&gt;&lt;span class="p"&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;f0d35941&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;989&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="nx"&gt;f2b&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;b187&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;872445&lt;/span&gt;&lt;span class="nx"&gt;b0b653&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="nx"&gt;fa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;d5&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="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;subnet_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;92432fb8-8c29-4abe-98d8-de8bf161a18b&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ip_address&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10.0.0.7&amp;quot;&lt;/span&gt;&lt;span class="p"&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="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;f9e097b4&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4227&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;49&lt;/span&gt;&lt;span class="nx"&gt;ee&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;9442&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;643&lt;/span&gt;&lt;span class="nx"&gt;c4186e587&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="nx"&gt;fa&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;a5&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;36&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="nx"&gt;c&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="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;subnet_id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;92432fb8-8c29-4abe-98d8-de8bf161a18b&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;ip_address&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;&amp;quot;10.0.0.2&amp;quot;&lt;/span&gt;&lt;span class="p"&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;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Associate VIP port with floating IP:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;floatingip-associate&lt;span class="w"&gt; &lt;/span&gt;3c15f8a4-bdc6-4154-8bfa-e8b0674079ca&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;ecbadc53-5266-4146-bbb3-d1b6d383be10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Associated floating IP 3c15f8a4-bdc6-4154-8bfa-e8b0674079ca
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;At this point the Virtual IP is a member of the &lt;em&gt;default&lt;/em&gt; security group which
does not allow ingress traffic unless you are also part of a security group
which allows incoming traffic. We need to update the VIP to be a member of the
&lt;em&gt;web&lt;/em&gt; security group so that requests from the internet are allowed to pass
(not just from our client instance).&lt;/p&gt;
&lt;p&gt;Get the web security group uuid:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;security-group-list
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;+--------------------------------------+----------+--------------------------------------------------------------------------------+
| id                                   | name     | security_group_rules                                                           |
+--------------------------------------+----------+--------------------------------------------------------------------------------+
| 141ed0d0-c004-457d-8efa-45e0fd2dc986 | ssh      | egress, IPv4                                                                   |
|                                      |          | egress, IPv6                                                                   |
|                                      |          | ingress, IPv4, 22/tcp                                                          |
| 379b58b2-7ca3-431e-ae1f-cd6a627a9b30 | default  | egress, IPv4                                                                   |
|                                      |          | egress, IPv6                                                                   |
|                                      |          | ingress, IPv4, remote_group_id: 379b58b2-7ca3-431e-ae1f-cd6a627a9b30           |
|                                      |          | ingress, IPv6, remote_group_id: 379b58b2-7ca3-431e-ae1f-cd6a627a9b30           |
| 5e0d0d57-2df6-4fbc-ad18-5908aacdf799 | default  | egress, IPv4                                                                   |
|                                      |          | egress, IPv6                                                                   |
|                                      |          | ingress, IPv4, remote_group_id: 5e0d0d57-2df6-4fbc-ad18-5908aacdf799           |
|                                      |          | ingress, IPv6, remote_group_id: 5e0d0d57-2df6-4fbc-ad18-5908aacdf799           |
| a98fcd2f-a828-4a88-92aa-36e3c1223a92 | web      | egress, IPv4                                                                   |
|                                      |          | egress, IPv6                                                                   |
|                                      |          | ingress, IPv4, 22/tcp, remote_group_id: 141ed0d0-c004-457d-8efa-45e0fd2dc986   |
|                                      |          | ingress, IPv4, 80/tcp                                                          |
| b2c914cb-3bc1-4ee6-9f30-66c459af5f4c | default  | egress, IPv4                                                                   |
|                                      |          | egress, IPv6                                                                   |
|                                      |          | ingress, IPv4, remote_group_id: b2c914cb-3bc1-4ee6-9f30-66c459af5f4c           |
|                                      |          | ingress, IPv6, remote_group_id: b2c914cb-3bc1-4ee6-9f30-66c459af5f4c           |
| cf6c0380-e255-4ba8-9258-bb8e9c062fa7 | database | egress, IPv4                                                                   |
|                                      |          | egress, IPv6                                                                   |
|                                      |          | ingress, IPv4, 22/tcp, remote_group_id: 141ed0d0-c004-457d-8efa-45e0fd2dc986   |
|                                      |          | ingress, IPv4, 3306/tcp, remote_group_id: a98fcd2f-a828-4a88-92aa-36e3c1223a92 |
+--------------------------------------+----------+--------------------------------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Update VIP port to be a member of the &lt;em&gt;web&lt;/em&gt; security group:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;neutron&lt;span class="w"&gt; &lt;/span&gt;port-update&lt;span class="w"&gt; &lt;/span&gt;ecbadc53-5266-4146-bbb3-d1b6d383be10&lt;span class="w"&gt; &lt;/span&gt;--security_groups&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;\&lt;/span&gt;
&amp;gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;list&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;a98fcd2f-a828-4a88-92aa-36e3c1223a92
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Updated port: ecbadc53-5266-4146-bbb3-d1b6d383be10
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;h3&gt;Verify loadbalancer&lt;/h3&gt;
&lt;p&gt;At this point your VIP is publicly addressable:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&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;i&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="k"&gt;$(&lt;/span&gt;seq&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;-O&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;http://172.24.4.229/&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Connecting to 172.24.4.229 (172.24.4.229:80)
web-server1
&lt;span class="k"&gt;-&lt;/span&gt;                    100% |************************************| 12 0:00:00 ETA
Connecting to 172.24.4.229 (172.24.4.229:80)
web-server2
&lt;span class="k"&gt;-&lt;/span&gt;                    100% |************************************| 12 0:00:00 ETA
Connecting to 172.24.4.229 (172.24.4.229:80)
web-server1
&lt;span class="k"&gt;-&lt;/span&gt;                    100% |************************************| 12 0:00:00 ETA
Connecting to 172.24.4.229 (172.24.4.229:80)
web-server2
&lt;span class="k"&gt;-&lt;/span&gt;                    100% |************************************| 12 0:00:00 ETA
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;To demonstration high availability, we’ll go and delete our &lt;code&gt;web_server1&lt;/code&gt;
instance to simulate a failure.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;openstack&lt;span class="w"&gt; &lt;/span&gt;server&lt;span class="w"&gt; &lt;/span&gt;delete&lt;span class="w"&gt; &lt;/span&gt;web_server1
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After the health monitor detects the host is not responding it will stop sending
requests to &lt;code&gt;web_server1&lt;/code&gt;. Now &lt;code&gt;web_server2&lt;/code&gt; is handling all the requests.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&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;i&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="k"&gt;$(&lt;/span&gt;seq&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;do&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;wget&lt;span class="w"&gt; &lt;/span&gt;-O&lt;span class="w"&gt; &lt;/span&gt;-&lt;span class="w"&gt; &lt;/span&gt;http://172.24.4.229/&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;Connecting to 172.24.4.229 (172.24.4.229:80)
web-server2
&lt;span class="k"&gt;-&lt;/span&gt;                    100% |************************************| 12 0:00:00 ETA
Connecting to 172.24.4.229 (172.24.4.229:80)
web-server2
&lt;span class="k"&gt;-&lt;/span&gt;                    100% |************************************| 12 0:00:00 ETA
Connecting to 172.24.4.229 (172.24.4.229:80)
web-server2
&lt;span class="k"&gt;-&lt;/span&gt;                    100% |************************************| 12 0:00:00 ETA
Connecting to 172.24.4.229 (172.24.4.229:80)
web-server2
&lt;span class="k"&gt;-&lt;/span&gt;                    100% |************************************| 12 0:00:00 ETA
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Note: the first request might take longer to handle. This is because of the
timeout before it notices the host is not responding.&lt;/p&gt;
&lt;h2&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;As described in this article, it is easy to set up an environment with OpenStack
in which you can securely host website, and deny access to your database servers.&lt;/p&gt;
&lt;p&gt;In future articles I will talk about High Availability and automation of setting
up an environment; for instance with HAProxy, GlusterFS and OpenStack Heat.&lt;/p&gt;
&lt;p&gt;If you have any suggestion, please discuss below or send me an email.&lt;/p&gt;
&lt;p&gt;Note: the original publication can be found at: &lt;a href="https://gitlab.com/gbraad/openstack-handsonlabs"&gt;OpenStack hands-on-labs&lt;/a&gt;&lt;/p&gt;</content><category term="OpenStack"/><category term="openstack"/><category term="packstack"/><category term="neutron"/><category term="rdo"/><category term="high availability"/><category term="web"/></entry><entry><title>JavaScript Loaders</title><link href="https://blog.gbraad.nl/javascript-loaders.html" rel="alternate"/><published>2014-11-04T00:00:00+08:00</published><updated>2014-11-04T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2014-11-04:/javascript-loaders.html</id><content type="html">&lt;p&gt;Overview of JavaScript loaders&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="http://requirejs.org/docs/commonjs.html#autoconversion"&gt;http://requirejs.org/docs/commonjs.html#autoconversion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://blog.millermedeiros.com/amd-is-better-for-the-web-than-commonjs-modules/"&gt;http://blog.millermedeiros.com/amd-is-better-for-the-web-than-commonjs-modules/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://addyosmani.com/writing-modular-js/"&gt;http://addyosmani.com/writing-modular-js/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/magazine/hh227261.aspx"&gt;http://msdn.microsoft.com/en-us/magazine/hh227261.aspx&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><category term="JavaScript"/><category term="javascript"/></entry><entry><title>Trigger PhoneGap Build from GitHub</title><link href="https://blog.gbraad.nl/trigger-phonegap-build-from-github.html" rel="alternate"/><published>2014-11-04T00:00:00+08:00</published><updated>2014-11-04T00:00:00+08:00</updated><author><name>Gerard Braad &lt;me@gbraad.nl&gt;</name></author><id>tag:blog.gbraad.nl,2014-11-04:/trigger-phonegap-build-from-github.html</id><summary type="html">&lt;p&gt;You can remotely trigger a build by using the &lt;a href="https://build.phonegap.com/docs/api"&gt;API&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;First you need to get your auth token:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;me@gbraad.nl-X&lt;span class="w"&gt; &lt;/span&gt;POST&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;https://build.phonegap.com/token
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Test it and retrieve your appid using the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;curl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;phonegap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;me&lt;/span&gt;&lt;span class="vm"&gt;?&lt;/span&gt;&lt;span class="n"&gt;auth_token&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;&lt;span class="n"&gt;token …&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</summary><content type="html">&lt;p&gt;You can remotely trigger a build by using the &lt;a href="https://build.phonegap.com/docs/api"&gt;API&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;First you need to get your auth token:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;$&lt;span class="w"&gt; &lt;/span&gt;curl&lt;span class="w"&gt; &lt;/span&gt;-u&lt;span class="w"&gt; &lt;/span&gt;me@gbraad.nl-X&lt;span class="w"&gt; &lt;/span&gt;POST&lt;span class="w"&gt; &lt;/span&gt;-d&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;https://build.phonegap.com/token
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;Test it and retrieve your appid using the following command:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;curl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;https&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;//&lt;/span&gt;&lt;span class="n"&gt;build&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;phonegap&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;com&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;api&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;v1&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;me&lt;/span&gt;&lt;span class="vm"&gt;?&lt;/span&gt;&lt;span class="n"&gt;auth_token&lt;/span&gt;&lt;span class="o"&gt;=[&lt;/span&gt;&lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;

&lt;p&gt;After this go to your Github repo, open the admin and go to 'Service hooks'. Add a new WebHook URL (first option) and add yours 
&lt;code&gt;https://build.phonegap.com/apps/[appid]/build/?auth_token=[token]&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Save this and trigger it with 'Test hook'. When you would open: &lt;code&gt;https://build.phonegap.com/apps/[appid]/builds&lt;/code&gt; you will probably see a new build.&lt;/p&gt;</content><category term="Misc"/><category term="phonegap"/></entry></feed>