My Openshift

Aloha, I propose you a general presentation of Openshift with a Symfony 4 application as a use case.

First, we start with presentations

I'm an open source container application platform based on Kubernetes container orchestrator for enterprise application development and deployment ¹


What can I say in a few words about Openshift

  • It's a PaaS : Plateform-as-a-service
  • Three offers availables : Online (used in this Post), Online Dedicated and private (not hosted at RedHat)
  • It allows build, deploy and run applications in containers
  • His configuration is based on a Docker container engine with Kubernetes Orchestrator
  • It offers a microservices oriented architecture.


Among the services of Openshift platform

  • Containerization (Source to images ², Docker Repository, Image Stream)
  • Route & LoaderBalancer
  • Shared Storage
  • Resource Management (Quota, Membership, ConfigMap, Secret,...)
  • Monitoring (Elasticsearch, Fluentd, Kibana) & Readiness / Liveness


Real life
This is a simple example of a web application deployed in Openshift cluster.

Reminder : An Openshift Cluster is a set of virtual or physical machines, containing nodes (at least a master), they contain Pods that are the result of the Run of a docker image.

The client (which may be a web browser) requests an URL (an external route to the cluster) of the Web application, the platform Router will dispatch this request to the concerned service (this may be an opening of port 80 of the frontal Pod).

The frontal Pod can then be considered as the FontEnd controller of our application, and which will use the business application also deployed in a Pod in Backend and in communication with the Pod of database (on a TCP service on 3306 for example with MySQL database).

Finally, all Pods use the distributed storage system managed by the platform on virtual file system mounts.

Typically, when you have multiple clusters, you define a front cluster (perhaps behind a proxy) to expose your services to outside of the cluster and another back cluster that will embed a business applications as well as access to the data. Both of these clusters will have different security configurations and requirements, which will allow us to isolate and protect business data.



Use case with a Symfony application
It's a standard Symfony 4 demonstration application with a few modifications to add Memcached support for example and using of MySQL database instead of SQLLite. Source is  available here (branch "openshift").


Let's start !
To begin, we need an OpenShift instance, so there simple registration to demo program (Starter Pack), gives us right to 2GB of memory, 2GB of disk and 4 CPU core free for 60 days.

After login to Web console, we have a view of catalog of images and services supported by the platform:

Catalog view with our project "MedInvention project"

So we start by creating a project (we're entitled to one at a time). For Openshift, this project is a namespace with own rules of resource management, access and some isolation with other namespaces.
For our Post, we will need an instance of Apache with PHP 7, Opcache and Memcached installed. The PHP image proposed by the platform does not support Memcached, for this reason that we will use a dedicated image available on  DockerHub (Tag "openshift" and source available on GitHub).
However, if we want to use the proposed image, we go through the catalog and we will have this

You can use CakePHP demonstration application available on GitHub or consult details of image (environment variables and characteristics)
You must specify a PHP version and Git Repository of your PHP application

And if we want to use our image, we go through "Add to Project" then "Import YAML / JSON "

Import a BuildConfig for Docker image building

We can copy / paste this content

apiVersion: build.openshift.io/v1
kind: BuildConfig
metadata:
  labels:
    app: webapp
  name: webapp
spec:
  output:
    to:
      kind: ImageStreamTag
      name: 'webapp:latest'
  source:
    git:
      ref: openshift
      uri: 'https://github.com/mmohamed/demo.git'
    type: Git
  strategy:
    sourceStrategy:
      from:
        kind: DockerImage
        name: 'medinvention/s2i-ubuntu-php72-apache24:openshift'
    type: Source

Then we have to define an external route for application

Case where an image of catalog is used, this route will be provisioned automatically. It should point to the webapp service that exposes 8080 port of our frontend Pod

We can also go through " Add to Project " then " Deploy image " (Without Git sources) we will have

We see that we will be entitled to a DeployementConfig of image, that port 8080 will be exposed with service and container will be accessible on hostname s2i-ubuntu-php72-apache

/!\ Tip: You can use the default PHP image to initiate S2I DeploymentConfig with our GitHub Repository, then modify the configuration to use our specific image without having to define a complete BuildConfig.

So, now we have a functional Build and DeploymentConfig, our first Build and our first Deploy are completed successfully. We have a Pod in Run and Ready to process queries.

External route available to access our application Pod


It then remains the deployment of a database image (we will use MySQL from catalog), and a MemCached server image. For Memcached, we will use a YAML Template , because it does not exist in catalog, with the import of object definitions in YAML / JSON functionality to import this template and apply it.


Now, we must have a complete environment

Our environment

We can access to our application with generated public URL

You can browse application to check connection to database and communication with Memcached server

One last tool is missing for continuous deployment; there we can use Jenkins which is proposed by platform in catalog.

Default, Jenkins will have his own public route and a single Job definition.

We just have to update our Jenkins Job to trigger a build, followed by a deployment when it detects a change in our application sources (hosted at GitHub)

A Job to deploy, but several forming a Pipeline with a build stage, Test and Deploy would be better of course

We can see Logs of Job run

Started by an SCM change

No credentials specified
 > git rev-parse --is-inside-work-tree # timeout=10
....
 > git rev-list --no-walk b9feb776306e16bcba20a6d371e9e83a838d1a2b # timeout=10

Starting "Scale OpenShift Deployment" with deployment config "memcached" from the project "demo-medinvention".
 Scaling to "0" replicas and verifying the replica count is reached ...
Operation will timeout after 180000 milliseconds

Exiting "Scale OpenShift Deployment" successfully, where the deployment "memcached-2" reached "0" replica(s).

Starting the "Trigger OpenShift Build" step with build config "webapp" from the project "demo-medinvention".
  Started build "webapp-9" and waiting for build completion ...
Operation will timeout after 900000 milliseconds
Pulling image "medinvention/s2i-ubuntu-php72-apache24:openshift" ...
Using medinvention/s2i-ubuntu-php72-apache24:openshift as the s2i builder image
---> Installing application source...
Loading composer repositories with package information
Installing dependencies (including require-dev) from lock file
....
Generating optimized autoload files
ocramius/package-versions:  Generating version class...
ocramius/package-versions: ...done generating version class
Executing script cache:clear [OK]
Executing script assets:install --symlink --relative public [OK]

Executing script security-checker security:check [OK]
---> Clear cache/logs and fixing permissions...

Pushing image docker-registry.default.svc:5000/demo-medinvention/webapp:latest ...
Pushed 0/17 layers, 0% complete
....
Pushed 17/17 layers, 100% complete
Push successful


Exiting "Trigger OpenShift Build" successfully; build "webapp-9" has completed with status:  [Complete].

Starting "Trigger OpenShift Deployment" with deployment config "webapp" from the project "demo-medinvention".
Operation will timeout after 600000 milliseconds

Exiting "Trigger OpenShift Deployment" successfully; deployment "webapp-13" has completed with status:  [Complete].

Starting "Tag OpenShift Image" with the source [image stream:tag] "webapp:latest" from the project "demo-medinvention" and destination stream(s) "webapp" with tag(s) "prod" from the project "demo-medinvention".

Exiting "Tag OpenShift Image" successfully.

Starting "Verify OpenShift Deployment" with deployment config "webapp" from the project "demo-medinvention".
  Waiting on the latest deployment for "webapp" to complete ...
Operation will timeout after 180000 milliseconds


Exiting "Verify OpenShift Deployment" successfully; deployment "webapp-13" has completed with status:  [Complete].

Starting "Scale OpenShift Deployment" with deployment config "memcached" from the project "demo-medinvention".
 Scaling to "1" replicas and verifying the replica count is reached ...
Operation will timeout after 180000 milliseconds


Exiting "Scale OpenShift Deployment" successfully, where the deployment "memcached-2" reached "1" replica(s).
Finished: SUCCESS

Finally,

Target

Now, we have a complete environment with full integration and deployment.

We can pick out two Pipelines :

  • First is for our Base Docker image (S2I) ; as I have set up an Auto-Build in DockerHub (1) , it's constantly monitors the repository  of the image in GitHub and as soon as there is a change, a Build is launched in DockerHub and result image is pushed to Registry. In this way, with each new Build of our project in Openshit, the new image will be used (2) .
  • The second Pipeline is for our application; it's our Jenkins Job who will be the orchestrator, because as soon as he detects a change in the repository of the sources of our demo application (5) , he will launch a new Build starting with a " Scale down " of the Memcache DeployConfig (because there is a lack of CPU in project resources), followed by a " Build webapp ", then a deployment " Deploy webapp ". Then we Tag the resulting image of the Build (in the Openshift Registry) before checking the deployment. Finally, we finish our Job with a " Scale Up " Memcache DeployConfig .



The functioning of our environment remains simple; when an HTTP request from the client(3) come, it will be dispatched by the Router to webapp service and therefore to application pod on port 8080 (4) . The application will need to communicate with the Memcache server(6) and will have to go through the services, as well as to communicate with Pod of database(7).



Here is an environment that can be used perfectly to develop and experience Openshift freely.
Personally, I fell in love with this solution and this wonderful compilation of tools. I hope you start to love Openshift.


NOTA : This post is the result of my experience with Openshift and my own understanding. If you notice omissions or errors do not hesitate to report it to me with a nice comment.



¹ : RedHat definition - ² :I will do another Post for S2I