Update GettingStartedTutorial.adoc

Update GettingStartedTutorial.adoc

Getting Started Tutorial
========================
Madars Vitolins
v1.0, 2015-11:
	Initial draft
:doctype: book

About the guide
---------------
Getting started tutorial covers Enduro/X installation from binary package,
environment setup, creating a sample Enduro/X server and creating sample client.
This include creating a neccessary configuration files. Finally the applicatioin is booted,
and client process calls the sample server process.

== Configuring Linux Kernel parameters

Kernel parameter configuration is needed for Enduro/X runtime. It includes changing
the security and Posix queue settings.

=== Security Configuration
---------------------------------------------------------------------
$ su - root
# cat << EOF >> /etc/security/limits.conf

# Do not limit message Q Count.
# Some Linux 3.x series kernels have a bug, that limits 1024
# queues for one system user.
# In 2.6.x and 4.x this is fixed, to have
# unlimited count of queues (memory limit).
# ealrier and later Linuxes have fixed this issue.
*               soft    msgqueue        -1
*               hard    msgqueue        -1

# Increase the number of open files
*               soft    nofile  1024
*               hard    nofile  65536

EOF
---------------------------------------------------------------------

=== Message Queue Configuration
At the startup of the system needs to mount a Posix Queues folder, and needs to
set a appropriate limits. To do this automatically at system startup,
Linuxes which supports '/etc/rc.local', must add following lines before "exit 0":

---------------------------------------------------------------------
# Mount the /dev/mqueue
mkdir /dev/mqueue
mount -t mqueue none /dev/mqueue

# Max Messages in Queue
echo 10000 > /proc/sys/fs/mqueue/msg_max

# Max message size (Currently Enduro/X supports only 32K as max)
echo 32000 > /proc/sys/fs/mqueue/msgsize_max

# Max number of queues for user
echo 10000 > /proc/sys/fs/mqueue/queues_max
---------------------------------------------------------------------

== Installing binary package (RPM for Centos 6.x)
---------------------------------------------------------------------
# wget http://www.endurox.org/attachments/download/6/endurox-2.3.2-1.centos6.x86_64.rpm
# rpm -i endurox-2.3.2-1.centos6.x86_64.rpm
---------------------------------------------------------------------

== Configuring the application environment
We will run our app "app1" from new user "user1". Application domain will be located in /opt/app1 folder. With follwing direcotry structure:
[options="compact"]
- /opt/app1/conf - will contain configuration files.
- /opt/app1/src/eclient - Enduro/X sample client sources.
- /opt/app1/src/eserver - Enduro/X sample server process sources.
- /opt/app1/bin - for executables.
- /opt/app1/ubftab - for tables for field defintions.

Create the user & directories:
---------------------------------------------------------------------
# useradd -m user1
# mkdir -p /opt/app1/conf
# mkdir -p /opt/app1/src/eclient
# mkdir -p /opt/app1/src/eserver
# mkdir -p /opt/app1/bin
# mkdir -p /opt/app1/ubftab
# mkdir -p /opt/app1/tmp
# mkdir -p /opt/app1/log
# chown -R user1 /opt/app1
---------------------------------------------------------------------
Next we will configure environment files, file /opt/app1/conf/setndrx - this will contain neccessary configuration for Enduro/X.

Copy following text to /opt/app1/conf/setndrx
---------------------------------------------------------------------
#!/bin/bash
export NDRX_NODEID=1
# If 1 - then yes, if 0 - then not clusterised.
export NDRX_CLUSTERISED=0
# Load balance, 0 = process all locally, 100 = process all on remote servers
export NDRX_LDBAL=0
# tpcall() timeout:
export NDRX_TOUT=60
# where to write ulog
export NDRX_ULOG=/opt/app1/log
export NDRX_QPREFIX=/app1
export NDRX_SVCMAX=20000
export NDRX_SRVMAX=10000
export NDRX_QPATH=/dev/mqueue
export NDRX_SHMPATH=/dev/shm
# Milli seconds to wait for command
export NDRX_CMDWAIT=1
export NDRX_DPID=/opt/app1/tmp/ndrxd.pid
# Random key to indentify the processes beloning to this session (i.e. used in ps ef)
export NDRX_RNDK="0myWI5nu"
# System V Semaphores...
export NDRX_IPCKEY=44000
# Posix queue config (attribs..)
# Max number of messages that can be put in one queue
export NDRX_MSGMAX=1000
# Daemon Q size...
export NDRX_DQMAX=100
# Max message size (in bytes), max 64K
export NDRX_MSGSIZEMAX=10000
# Where app domain lives
export NDRX_APPHOME=/opt/app1
# Where NDRX runtime lives
export NDRX_HOME=/usr
# Debug config too
export NDRX_DEBUG_CONF=/opt/app1/conf/debug.conf
# NDRX config too.
export NDRX_CONFIG=/opt/app1/conf/ndrxconfig.xml
export PATH=$PATH:/opt/app1/bin
export export FLDTBLDIR=/opt/app1/ubftab
# Max fields for hashing UBF
export NDRX_UBFMAXFLDS=16000

# Log & levels (basic for scripting..)
export NDRX_DMNLOG=/opt/app1/log/ndrxd.log
export NDRX_DMNLEV=5

export NDRX_LOG=/opt/app1/log/ndrx.log
export NDRX_LEV=5

# Correct the path so that ndrx can find ndrxd
export PATH=$PATH:$NDRX_HOME/bin

# UBFTAB Exfields - Enduro/X specifc, test.fd - our apps' UBF fields
export FIELDTBLS=Exfields,test.fd
---------------------------------------------------------------------

Debug config
---------------------------------------------------------------------
..
---------------------------------------------------------------------

== Creating the server process

=== Defining the UBF fields

=== Server source code

=== Booting the server process

=== Testing the service with "ud" command

== Creating the client application

=== Client binary source code

=== Running the client process

== Conclusions

:numbered!:

[bibliography]
Additional documentation
------------------------
This section lists additional related documents.

[bibliography]
.Internet resources
- [[[ATMI-API]]] http://docs.oracle.com/cd/E13203_01/tuxedo/tux71/html/pgint6.htm
- [[[FML-API]]] http://docs.oracle.com/cd/E13203_01/tuxedo/tux91/fml/index.htm
- [[[EX_OVERVIEW]]] ex_overview.pdf
- [[[MQ_OVERVIEW]]] 'man 7 mq_overview'
- [[[EX_ENV]]] 'man 5 ex_env' or 'ex_env.pdf'
- [[[NDRXCONFIG]]] 'man 5 ndrxconfig.xml'  or 'ndrxconfig.xml.pdf'
- [[[DEBUGCONF]]] 'man 5 ndrxdebug.conf'  or 'ndrxdebug.conf.pdf'
- [[[XADMIN]]] 'man 8 xadmin' or 'xadmin.pdf'

[glossary]
Glossary
--------
This section lists

[glossary]
ATMI::
  Application Transaction Monitor Interface

UBF::
  Unified Buffer Format it is similar API as Tuxedo's FML

////////////////////////////////////////////////////////////////
The index is normally left completely empty, it's contents being
generated automatically by the DocBook toolchain.
////////////////////////////////////////////////////////////////

Getting Started Tutorial
========================
Madars Vitolins
v1.0, 2015-11:
	Initial draft
:doctype: book

About the guide
---------------
Getting started tutorial covers Enduro/X installation from binary package,
environment setup, creating a sample Enduro/X server and creating sample client.
This include creating a neccessary configuration files. Finally the applicatioin is booted,
and client process calls the sample server process.

== Configuring Linux Kernel parameters

Kernel parameter configuration is needed for Enduro/X runtime. It includes changing
the security and Posix queue settings.

=== Security Configuration
---------------------------------------------------------------------
$ su - root
# cat << EOF >> /etc/security/limits.conf

# Do not limit message Q Count.
# Some Linux 3.x series kernels have a bug, that limits 1024
# queues for one system user.
# In 2.6.x and 4.x this is fixed, to have
# unlimited count of queues (memory limit).
# ealrier and later Linuxes have fixed this issue.
*               soft    msgqueue        -1
*               hard    msgqueue        -1

# Increase the number of open files
*               soft    nofile  1024
*               hard    nofile  65536

EOF
---------------------------------------------------------------------

=== Message Queue Configuration
At the startup of the system needs to mount a Posix Queues folder, and needs to
set a appropriate limits. To do this automatically at system startup,
Linuxes which supports '/etc/rc.local', must add following lines before "exit 0":

---------------------------------------------------------------------
# Mount the /dev/mqueue
mkdir /dev/mqueue
mount -t mqueue none /dev/mqueue

# Max Messages in Queue
echo 10000 > /proc/sys/fs/mqueue/msg_max

# Max message size (Currently Enduro/X supports only 32K as max)
echo 32000 > /proc/sys/fs/mqueue/msgsize_max

# Max number of queues for user
echo 10000 > /proc/sys/fs/mqueue/queues_max
---------------------------------------------------------------------

== Installing binary package (RPM for Centos 6.x)
---------------------------------------------------------------------
# wget http://www.endurox.org/attachments/download/6/endurox-2.3.2-1.centos6.x86_64.rpm
# rpm -i endurox-2.3.2-1.centos6.x86_64.rpm
---------------------------------------------------------------------

== Configuring the application environment
We will run our app "app1" from new user "user1". Application domain will be located in /opt/app1 folder. With follwing direcotry structure:
[options="compact"]
- /opt/app1/conf - will contain configuration files.
- /opt/app1/src/eclient - Enduro/X sample client sources.
- /opt/app1/src/eserver - Enduro/X sample server process sources.
- /opt/app1/bin - for executables.
- /opt/app1/ubftab - for tables for field defintions.

Create the user & directories:
---------------------------------------------------------------------
# useradd -m user1
# mkdir -p /opt/app1/conf
# mkdir -p /opt/app1/src/eclient
# mkdir -p /opt/app1/src/eserver
# mkdir -p /opt/app1/bin
# mkdir -p /opt/app1/ubftab
# mkdir -p /opt/app1/tmp
# mkdir -p /opt/app1/log
# chown -R user1 /opt/app1
---------------------------------------------------------------------
Next we will configure environment files, file /opt/app1/conf/setndrx - this will contain neccessary configuration for Enduro/X.

Copy following text to /opt/app1/conf/setndrx
---------------------------------------------------------------------
#!/bin/bash
export NDRX_NODEID=1
# If 1 - then yes, if 0 - then not clusterised.
export NDRX_CLUSTERISED=0
# Load balance, 0 = process all locally, 100 = process all on remote servers
export NDRX_LDBAL=0
# tpcall() timeout:
export NDRX_TOUT=60
# where to write ulog
export NDRX_ULOG=/opt/app1/log
export NDRX_QPREFIX=/app1
export NDRX_SVCMAX=20000
export NDRX_SRVMAX=10000
export NDRX_QPATH=/dev/mqueue
export NDRX_SHMPATH=/dev/shm
# Milli seconds to wait for command
export NDRX_CMDWAIT=1
export NDRX_DPID=/opt/app1/tmp/ndrxd.pid
# Random key to indentify the processes beloning to this session (i.e. used in ps ef)
export NDRX_RNDK="0myWI5nu"
# System V Semaphores...
export NDRX_IPCKEY=44000
# Posix queue config (attribs..)
# Max number of messages that can be put in one queue
export NDRX_MSGMAX=1000
# Daemon Q size...
export NDRX_DQMAX=100
# Max message size (in bytes), max 64K
export NDRX_MSGSIZEMAX=10000
# Where app domain lives
export NDRX_APPHOME=/opt/app1
# Where NDRX runtime lives
export NDRX_HOME=/usr
# Debug config too
export NDRX_DEBUG_CONF=/opt/app1/conf/debug.conf
# NDRX config too.
export NDRX_CONFIG=/opt/app1/conf/ndrxconfig.xml
export PATH=$PATH:/opt/app1/bin
export export FLDTBLDIR=/opt/app1/ubftab
# Max fields for hashing UBF
export NDRX_UBFMAXFLDS=16000

# Log & levels (basic for scripting..)
export NDRX_DMNLOG=/opt/app1/log/ndrxd.log
export NDRX_DMNLEV=5

export NDRX_LOG=/opt/app1/log/ndrx.log
export NDRX_LEV=5

# Correct the path so that ndrx can find ndrxd
export PATH=$PATH:$NDRX_HOME/bin

# UBFTAB Exfields - Enduro/X specifc, test.fd - our apps' UBF fields
export FIELDTBLS=Exfields,test.fd
---------------------------------------------------------------------

Basic application server configuration (/opt/app1/conf/ndrxconfig.xml)
---------------------------------------------------------------------
<?xml version="1.0" ?>
<endurox>
    <appconfig>
         <!-- ALL BELLOW ONES USES <sanity> periodical timer  -->
         <!-- Sanity check time, sec -->
         <sanity>5</sanity>
         <!--
             Seconds in which we should send service refresh to other node.
         -->
         <brrefresh>6</brrefresh>

         <!--  <sanity> timer, end -->

         <!-- ALL BELLOW ONES USES <respawn> periodical timer  -->
         <!-- Do dead process restart every X seconds
         NOT USED ANYMORE, REPLACED WITH SANITY!
         <respawncheck>10</respawncheck>
         -->
         <!-- Do process reset after 1 sec -->
         <restart_min>1</restart_min>
         <!-- If restart fails, then boot after +5 sec of previous wait time -->
         <restart_step>1</restart_step>
         <!-- If still not started, then max boot time is a 30 sec. -->
         <restart_max>5</restart_max>
         <!--  <sanity> timer, end -->

         <!-- Time after attach when program will start do sanity & respawn checks,
              starts counting after configuration load -->
         <restart_to_check>20</restart_to_check>

         <!-- Setting for pq command, should ndrxd collect service
              queue stats automatically
         If set to Y or y, then queue stats are on.
         Default is off.
         -->
         <gather_pq_stats>Y</gather_pq_stats>

	</appconfig>
    <defaults>
        <min>1</min>
        <max>2</max>
        <!-- Kill the process which have not started in <start_max> time -->
        <autokill>1</autokill>
        <!--
        <respawn>1<respawn>
        -->
        <!--
            <env></env> works here too!
        -->
         <!-- The maximum time while process can hang in 'starting' state i.e.
            have not completed initialization, sec
            X <= 0 = disabled
        -->
         <start_max>2</start_max>
         <!--
            Ping server in every X seconds (step is <sanity>).
         -->
         <pingtime>1</pingtime>
         <!--
            Max time in seconds in which server must respond.
            The granularity is sanity time.
            X <= 0 = disabled
         -->
         <ping_max>4</ping_max>
         <!--
            Max time to wait until process should exit on shutdown
            X <= 0 = disabled
         -->
         <end_max>30</end_max>
         <!-- Interval, in seconds, by which signal sequence -2, -15, -9, -9.... will be sent
         to process until it have been terminated. -->
         <killtime>1</killtime>
         <!-- List of services (comma separated) for ndrxd to export services over bridges -->
    <!--     <exportsvcs>FOREX</exportsvcs> -->
	</defaults>
	<servers>
		<!-- This is binary we are about to build -->
		<server name="eserver">
			<srvid>1</srvid>
			<min>2</min>
			<max>2</max>
			<sysopt>-e /opt/app1/log/ESERVER -r</sysopt>
		</server>
	</servers>
</endurox>

---------------------------------------------------------------------

Debug config
---------------------------------------------------------------------

---------------------------------------------------------------------

== Creating the server process

=== Defining the UBF fields

=== Server source code

=== Booting the server process

=== Testing the service with "ud" command

== Creating the client application

=== Client binary source code

=== Running the client process

== Conclusions

:numbered!:

[bibliography]
Additional documentation
------------------------
This section lists additional related documents.

[bibliography]
.Internet resources
- [[[ATMI-API]]] http://docs.oracle.com/cd/E13203_01/tuxedo/tux71/html/pgint6.htm
- [[[FML-API]]] http://docs.oracle.com/cd/E13203_01/tuxedo/tux91/fml/index.htm
- [[[EX_OVERVIEW]]] ex_overview.pdf
- [[[MQ_OVERVIEW]]] 'man 7 mq_overview'
- [[[EX_ENV]]] 'man 5 ex_env' or 'ex_env.pdf'
- [[[NDRXCONFIG]]] 'man 5 ndrxconfig.xml'  or 'ndrxconfig.xml.pdf'
- [[[DEBUGCONF]]] 'man 5 ndrxdebug.conf'  or 'ndrxdebug.conf.pdf'
- [[[XADMIN]]] 'man 8 xadmin' or 'xadmin.pdf'

[glossary]
Glossary
--------
This section lists

[glossary]
ATMI::
  Application Transaction Monitor Interface

UBF::
  Unified Buffer Format it is similar API as Tuxedo's FML

////////////////////////////////////////////////////////////////
The index is normally left completely empty, it's contents being
generated automatically by the DocBook toolchain.
////////////////////////////////////////////////////////////////


Minor changes based on review

Minor changes based on review

## First step with Kubernetes

Following a microservice approach will help you increase your _agility_. However, it does not come for free and
requires a lot of discipline. It also stresses your deployment facilities. When the number of microservices grows, it
very quickly becomes an issue to keep your system on track.

To help us with this, containers are a great packaging and runtime technology. Your application runs in an
_isolated_ container, avoiding resource conflicts. But to deploy a set of containers and keep them coordinated, you
need a container platform. That's what Kubernetes is. Kubernetes defines a set of building blocks ("primitives") which
collectively provide mechanisms for deploying, maintaining, and scaling applications packaged inside containers. OpenShift
 _extends_ Kubernetes with build automation and a routing system, while inheriting all the primitives from Kubernetes.

image::openshift-architecture.png[OpenShift Architecture, 800]

### Primitives

#### Pod

The basic scheduling unit in Kubernetes is called a _pod_. It adds a higher level of abstraction to containerized components.
A pod consists of one or more containers that are guaranteed to be co-located on the host machine and can share resources.
Each pod in Kubernetes is assigned a unique (within the cluster) IP address, which allows applications to use ports without
 the risk of conflict. A pod can define a _volume_, such as a local disk directory or a network disk, and expose it to
 the containers in the pod. Pods can be manually managed through the Kubernetes API, or their management can be
 delegated to a controller.

#### Labels and Selectors

Kubernetes enables clients (users or internal components) to attach key-value pairs called _labels_ to any API object
 in the system, such as pods. Correspondingly, _label selectors_ are queries against labels that resolve to matching
 objects. Labels and selectors are the primary grouping mechanism in Kubernetes and are used to determine the components
 to which an operation applies. Labels and selectors are used to group entities together.

#### Replication Controller and Deployment

Controllers are entities managing other entities in order to keep them in a specific state. For instance, a
replication controller has the responsibility to keep alive _x_ replicas of a pod. When one of these replicas dies or
 becomes unresponsive, the controller kills it and restarts one. Likewise, if there are more replicas running than desired,
  it deletes as many as necessary to match the number.

The definition of a replication controller consists mainly of:

1. The number of replicas desired (which can be adjusted at runtime).
2. A pod definition for creating a replicated pod.
3. A selector for identifying managed pods (using labels)

Building on replication controllers, OpenShift expands support for the deployment lifecycle with the concept of _deployments_.
 In the simplest case, a deployment just creates a new replication controller and lets it start up pods. However, OpenShift
  deployments also provide the ability to transition from an existing deployment (_v1_ for instance) of an image to a new
  one (_v2_ for instance) and also define hooks to be run before or after creating the replication controller.

Openshift deployments propose a set of strategies. The default is _rolling_ which implements (as the name implies) rolling
updates and ensures that you don't disrupt your service. Before stopping the pod, it ensures that the new _version_ is alive and
ready. Then, it routes requests to this new pod and dispose the old one.  Other strategies provided include _recreate_,
_blue-green_, _A/B_, and the ability to create a custom strategy.

#### Build and Image

As stated in the previous section, `deployments` are responsible for keeping the application running. But we need to
provide the application first. The application is pushed to OpenShift as an (container) _image_. This image is
created by a _build_ and instantiated by the _deployment_.

A build is the process of transforming your code into an image. The process is described in a `BuildConfig` object. Build
objects share common characteristics: inputs for a build (source code, artifacts), the need to complete a build process,
logging the build process, publishing resources from successful builds, and publishing the final status of the build.

There are different types of builds. You can create a `Docker` build taking a `Dockerfile` as parameter. The
resulting image is generated by _building_ the `Dockerfile`. OpenShift also provides the concept of S2I (Source to
Image) as a tool to provide reproducible images. In this lab, we are going to use S2I with binary content. We are
going to build the application on our machine and push the resulting artifact (a _fat jar_) as input to an S2I build.
This build creates an image for starting the application.

image::openshift-build-process.png[OpenShift Build Process, 800]

#### Services

Ok, so we know how our application is going to be _built_ and instantiated on OpenShift. But how are we going to use
it? For this we need _services_. A _service_ identifies a set of pods (using labels) in order to proxy the connections
it receives to them. Backing pods can be added to or removed from a service arbitrarily while the service remains
consistently available enabling anything that depends on the service to refer to it at a consistent internal address.

Services are assigned an IP address and port pair that, when accessed, proxy to an appropriate backing pod. A service
uses a label selector to find all the containers running that provide a certain network service on a certain port.

image::openshift-service.png[OpenShift Services, 400]

#### Routes

_Routes_ are the last concept to understand before starting to use OpenShift. Services provides an internal IP.
Routes exposes a service outside of OpenShift. A route allows you to associate a service with an externally-reachable
 host name.

image::openshift-entities.png[OpenShift Entities, 800]

### Installing and Starting OpenShift

We are going to use _minishift_ (https://github.com/minishift/minishift) to run OpenShift locally on your machine.

Before starting minishift, you need to install a hypervisor. Check the https://docs.openshift.org/latest/minishift/getting-started/installing.html
to check what are the supported ones for your operating system. When in doubt, use VirtualBox (https://www.virtualbox.org/wiki/Downloads).
Be sure to have a hypervisor before continuing.

If not already done, download the latest release from https://github.com/minishift/minishift/releases (do not
use beta). Download the archive and copy the `minishift` executable in the directory of your choice. Add this
directory to your system `$PATH`.

Then, in a terminal, run:

[source, bash]
----
minishift start
----

When the starting sequence completes, you should get the URL of the OpenShift Web Console such as: `https://192.168
.64.12:8443`. Open this url in a browser and connect using the default `developer/developer` credentials.

Now we have OpenShift running, but we need a way to interact with it. The _OpenShift Client_ (`oc`) is a command line
 tool to interact with OpenShift. Fortunately, this client is shipped with minishift. Use `minishift oc-env` to display
  the command you need to type into your shell in order to add the oc binary to your PATH environment variable. Then,
   run the following `oc` command to connect to your OpenShift instance:

[source, bash]
----
oc login -u developer -p developer
----

TIP: for Unix style shells you can run `eval $(minishift oc-env)` to make `oc` available.

Now, you are ready to deploy your first application.

### Your first project and deployment

We are going to use a specific project to host all the microservices developed in this lab. A `project` is a
namespace making easy to organize your different applications in OpenShift. In a terminal run:

[source, bash]
----
oc new-project vertx-kubernetes-workshop
oc policy add-role-to-user view admin -n vertx-kubernetes-workshop
oc policy add-role-to-user view -n vertx-kubernetes-workshop -z default
oc policy add-role-to-group view system:serviceaccounts -n vertx-kubernetes-workshop
----

The first instruction creates the project. The 3 last instructions grant permissions in order to use all the
OpenShift capabilities.

In the OpenShift Web Console, you should see the newly created project. Click on it. It's empty, so let's deploy our
first application.

In the workshop source code, locate the `currency-3rdparty-service` and navigate to the directory in your terminal.
Now issue the `mvn fabric8:deploy` command:

[source, bash]
----
cd $WORKSHOP_ROOT/currency-3rdparty-service
mvn fabric8:deploy
----

The `fabric8 maven plugin` is a Maven Plugin facilitating the deployment of OpenShift applications. The `:deploy`
mojo packages the application and triggers the S2I build described above.

In your browser, check the content of the project. You should see something like:

image::openshift-first-deployment.png[First deployment, 1024]

Click on the route url and you should see `ok`.  This indicates that your first application was successfully deployed.

## First step with Kubernetes

Following a microservice approach will help you increasing your _agility_. However, it does not come for free and
requires a lot of discipline. It also stresses your deployment facilities. When the number of microservice grows, it
becomes very quickly an issue to maintain your system on track.

To help us with this, containers are a great packaging and runtime technology. Your application runs in an
_isolated_ container, avoiding resource conflicts. But to deploy a set of containers and keep them coordinated, you
need a container platform. That's what Kubernetes is. Kubernetes defines a set of building blocks ("primitives") which
collectively provide mechanisms for deploying, maintaining, and scaling applications packaged inside containers. OpenShift
 _extends_ Kubernetes with build automation and routing system, but inherits from all these Kubernetes
primitives.

image::openshift-architecture.png[OpenShift Architecture, 800]

### Primitives

#### Pod

The basic scheduling unit in Kubernetes is called a _pod_. It adds a higher level of abstraction to containerized components.
A pod consists of one or more containers that are guaranteed to be co-located on the host machine and can share resources.
Each pod in Kubernetes is assigned a unique (within the cluster) IP address, which allows applications to use ports without
 the risk of conflict. A pod can define a _volume_, such as a local disk directory or a network disk, and expose it to
 the containers in the pod. Pods can be manually managed through the Kubernetes API, or their management can be
 delegated to a controller.

#### Labels and Selectors

Kubernetes enables clients (users or internal components) to attach key-value pairs called _labels_ to any API object
 in the system, such as pods. Correspondingly, _label selectors_ are queries against labels that resolve to matching
 objects. Labels and selectors are the primary grouping mechanism in Kubernetes, and are used to determine the components
 to which an operation applies. Labels and selectors are used to group entities together.

#### Replication Controller and Deployment

Controllers are entities managing other entities in order to keep them in a specific state. For instance, a
replication controller has the responsibility to keep alive _x_ replicas of a pod. When one of these replicas dies or
 becomes irresponsive, the controller kills it and restarts one. Likewise, if there are more replicas running than desired,
  it deletes as many as necessary to match the number.

The definition of a replication controller consists mainly of:

1. The number of replicas desired (which can be adjusted at runtime).
2. A pod definition for creating a replicated pod.
3. A selector for identifying managed pods (using labels)

Building on replication controllers, OpenShift expands support for the deployment lifecycle with the concept of _deployments_.
 In the simplest case, a deployment just creates a new replication controller and lets it start up pods. However, OpenShift
  deployments also provide the ability to transition from an existing deployment (_v1_ for instance) of an image to a new
  one (_v2_ for instance) and also define hooks to be run before or after creating the replication controller.

Openshift deployments proposes a set of strategy. One of them named _rolling_ implements a rolling updates and ensure
 that you don't disrupt your service. Before stopping the pod, it ensures that the new _version_ is alive and ready.
 Then it routes requests to this new pod and dispose the old one.

#### Build and Image

As said in the previous section, `deployments` are responsible to keep the application running. But we need to
provide this application first. This application is pushed to OpenShift as an (container) _image_. This image is
created by a _build_ and instantiated by the _deployment_.

A build is the process of transforming your code into an image. The process is described in a `BuildConfig` object. Build
objects share common characteristics: inputs for a build (source code, artifacts), the need to complete a build process,
logging the build process, publishing resources from successful builds, and publishing the final status of the build.

There are different types of builds. You can create a `Docker` build taking a `Dockerfile` as parameter. The
resulting image is generated by _building_ the `Dockerfile`. OpenShift also provides the concept of S2I (Source to
Image) as a tool to provide reproducible image. In this lab, we are going to use S2I with binary content. We are
going to build the application on our machine and push the resulting artifact (_fat jar_) as input of a S2I build.
This build creates an image starting the application.

image::openshift-build-process.png[OpenShift Build Process, 800]

#### Services

Ok, so we know how our application is going to be _built_ and instantiated on OpenShift. But how are we going to use
it? For this we need _services_. A _service_ identifies a set of pods (using labels) in order to proxy the connections
it receives to them. Backing pods can be added to or removed from a service arbitrarily while the service remains
consistently available, enabling anything that depends on the service to refer to it at a consistent internal address.

Services are assigned an IP address and port pair that, when accessed, proxy to an appropriate backing pod. A service
uses a label selector to find all the containers running that provide a certain network service on a certain port.

image::openshift-service.png[OpenShift Services, 400]

#### Routes

_Routes_ are the last concept to understand before starting to use OpenShift. Services provides an internal IP.
Routes exposes a service outside of OpenShift. A route allows you to associate a service with an externally-reachable
 host name.

image::openshift-entities.png[OpenShift Entities, 800]

### Installing and Starting OpenShift

We are going to use _minishift_ (https://github.com/minishift/minishift) to run OpenShift locally on your machine.

Before starting minishift, you need to install a hypervisor. Check the https://docs.openshift.org/latest/minishift/getting-started/installing.html to check what are the supported ones depending on your operating system. In case of doubt, use VirtualBox (https://www.virtualbox.org/wiki/Downloads). Be sure to have a hypervisor before continuing.

If not already done, download the latest releases from https://github.com/minishift/minishift/releases (don't
use beta). Download the archive and copy the `minishift` executable in the directory of your choice. Add this
directory to your system `$PATH`.

Then, in a terminal, run:

[source, bash]
----
minishift start
----

When the starting sequence completes, you should get the URL of the OpenShift Web Console such as: `https://192.168
.64.12:8443`. Open this url in a browser and connect using the `developer/developer` credentials.

Now we have OpenShift running. But we need a way to interact with it. The _OpenShift Client_ (`oc`) is a command line
 tool to interact with OpenShift. Fortunately, this client is shipped with minishift. Use `minishift oc-env` to display
  the command you need to type into your shell in order to add the oc binary to your PATH environment variable. Then,
   run the following `oc` command to connect to your OpenShift instance:

[source, bash]
----
oc login -u developer -p developer
----

Now, you are ready to deploy your first application.

### Your first project and deployment

We are going to use a specific project to host all the microservices developed in this lab. A `project` is a
namespace making easy to organize your different application in OpenShift. In a terminal run:

[source, bash]
----
oc new-project vertx-kubernetes-workshop
oc policy add-role-to-user view admin -n vertx-kubernetes-workshop
oc policy add-role-to-user view -n vertx-kubernetes-workshop -z default
oc policy add-role-to-group view system:serviceaccounts -n vertx-kubernetes-workshop
----

The first instruction creates the project. The 3 last instructions grants permissions in order to use all the
OpenShift capabilities.

In the OpenShift Web Console, you should see the newly created project. Click on it. It's empty, let's deploy our
first application.

In the workshop source code, locate the `currency-3rdparty-service`, and navigate in the directory in your terminal.
Then issue the `mvn fabric8:deploy` command:

[source, bash]
----
cd $WORKSHOP_ROOT/currency-3rdparty-service
mvn fabric8:deploy
----

The `fabric8 maven plugin` is a Maven Plugin facilitating the deployment of OpenShift applications. The `:deploy`
mojo packages the application and triggers the S2I build are described above.

In your browser, check the content of the project. You should see something like:

image::openshift-first-deployment.png[First deployment, 1024]

Click on the route url, you should see `ok`.