Skip to content
This repository has been archived by the owner on Jun 19, 2019. It is now read-only.

Cloud Native Developer's experience for Spring Boot around Go CLI to scaffold a project, inner-loop with supervisord

Notifications You must be signed in to change notification settings

snowdrop/snowdrop-cloud-devex

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Cloud Native Developer's experience for Spring Boot

The prototype developed within this project aims to resolve the following user's stories for a Spring Boot developer

"As a developer, I want to install a pod running my runtime Java - Spring Boot application where my endpoint is exposed as a Service accessible via a route, where I can instruct the pod to start or stop a command such as "compile", "run java", ..." within the pod"

"As a developer, I would like to generate/scaffold a Spring Boot application supporting different technologies such as JAX-RS - REST, JPA, ...."

"As a developer, I want to customize the application deployed using a MANIFEST yaml file where I can specify, the name of the application, s2i image to be used, maven tool, port of the service, cpu, memory, ...."

"As a developer, I would like to know according to the OpenShift platform, which version of the template/builder and which resources are processed when it will be installed/deployed"

Table of Contents

Instructions

Prerequisites

Download and validate the Spring boot's go client

  • Execute within a terminal this curl command in order to download our Spring Boot go client

    sudo curl -L https://github.com/snowdrop/spring-boot-cloud-devex/releases/download/v0.15.0/sb-darwin-amd64 -o /usr/local/bin/sd
    or 
    sudo curl -L https://github.com/snowdrop/spring-boot-cloud-devex/releases/download/v0.15.0/sb-linux-amd64 -o /usr/local/bin/sd
    sudo chmod +x /usr/local/bin/sd
  • Test it to check that you can access the commands proposed within your terminal

    $sd -h
    
    snowdrop's client tool to scaffold a spring boot application on kubernetes/openshift
    Usage:
      sd [command]
    
    Examples:
        # Creating and deploying a spring Boot application
        git clone https://github.com/snowdrop/spring-boot-cloud-devex.git && cd spring-boot-cloud-devex/spring-boot
        sd push
        sd compile
        sd run
    
    Available Commands:
      build       Build an image of the application
      clean       Remove development pod for the component
      compile     Compile local project within the development pod
      create      Create a Spring Boot maven project
      debug       Debug your SpringBoot application
      exec        Stop, start or restart your SpringBoot application.
      help        Help about any command
      push        Push local code to the development pod
      version     Show sd  client version
    
    Flags:
      -h, --help                 help for sb
      -k, --kubeconfig string    Path to a kubeconfig ($HOME/.kube/config). Only required if out-of-cluster.
          --masterurl string     The address of the Kubernetes API server. Overrides any value in kubeconfig. Only required if out-of-cluster.
      
    Use "sd [command] --help" for more information about a command.

Create a project

Create top of your OpenShift's cluster (minishift, ocp, ...) a project where you will deploy and run your spring boot application

oc new-project <your-namespace>

WARNING: Check/verify that you have access to an OpenShift cluster before to create your project.

Scaffold a Spring Boot's project

Within your terminal, move to the folder where you would like to create a Spring REST application

$ cd ~/my-spring-boot

Execute the following command to create a Maven project containing the Spring code exposing a REST Endpoint /api/greeting

sd create -t rest -i my-spring-boot

REMARK : The parameter -i will configure the artifactId to use the same name as the folder of your project. The command will populate a project using default values for the GAV, package name, Spring Boot version. That could be of course tailored using the different parameters proposed by the command sd create -h

Development pod

In order to install the application, compile it (optional), debug or start/stop it. This development pod is automatically created on demand the first time you issue an sd command. You can check the logs as follows:

$oc logs $(oc get pod -l app=my-spring-boot -o name)
time="2018-08-24T09:45:02Z" level=info msg="create process:run-java"
time="2018-08-24T09:45:02Z" level=info msg="create process:compile-java"
time="2018-08-24T09:45:02Z" level=info msg="create process:build"

Push the code

As the development's pod has been created and is running the supervisord server, we will now compile the maven project and push the binary code.

mvn clean package

To use the created uberjar file located under /target/<application-name-version>.jar, then run this command :

sd push --mode binary

Start the java application

  • Launch the Spring Boot Application

    sd exec start
    ime="2018-07-13T11:06:26Z" level=debug msg="succeed to find process:run-java"
    time="2018-07-13T11:06:26Z" level=info msg="try to start program" program=run-java
    time="2018-07-13T11:06:26Z" level=info msg="success to start program" program=run-java
    Starting the Java application using /opt/run-java/run-java.sh ...
    exec java -javaagent:/opt/jolokia/jolokia.jar=config=/opt/jolokia/etc/jolokia.properties -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:+UseParallelOldGC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:MaxMetaspaceSize=100m -XX:+ExitOnOutOfMemoryError -cp . -jar /deployments/spring-boot-http-1.0.jar
    time="2018-07-13T11:06:27Z" level=debug msg="wait program exit" program=run-java
    I> No access restrictor found, access to any MBean is allowed
    Jolokia: Agent started with URL https://172.17.0.7:8778/jolokia/
      .   ____          _            __ _ _
     /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
    ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
     \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
      '  |____| .__|_| |_|_| |_\__, | / / / /
     =========|_|==============|___/=/_/_/_/
     :: Spring Boot ::       (v1.5.14.RELEASE)
    ... 
    2018-07-13 11:06:34.293  INFO 222 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup
    2018-07-13 11:06:34.304  INFO 222 --- [           main] o.s.c.support.DefaultLifecycleProcessor  : Starting beans in phase 0
    2018-07-13 11:06:34.427  INFO 222 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http)
    2018-07-13 11:06:34.436  INFO 222 --- [           main] io.openshift.booster.BoosterApplication  : Started BoosterApplication in 6.412 seconds (JVM running for 7.32) 

Test the endpoint of the Spring Boot application

Access the endpoint of the Spring Boot application using curl and the route exposed on the cloud platform

URL="http://$(oc get routes/my-spring-boot -o jsonpath='{.spec.host}')"
curl $URL/api/greeting
{"content":"Hello, World!"}% 

Start, stop, debug or restart the spring boot application

  • The Spring Boot Application can be stopped, started or restarted using respectively these commands:

    sd exec stop
    sd exec start
    sd exec restart
  • You can also debug your application by forwarding the traffic between the pod and your machine using the following command :

    sd exec debug
    INFO[0000] sd exec start command called                        
    INFO[0000] [Step 1] - Parse MANIFEST of the project if it exists 
    INFO[0000] [Step 2] - Get K8s config file               
    INFO[0000] [Step 3] - Create kube Rest config client using config's file of the developer's machine 
    INFO[0000] [Step 4] - Wait till the dev's pod is available 
    INFO[0000] [Step 5] - Restart Java Application          
    run-java: stopped
    run-java: started
    INFO[0003] [Step 6] - Remote Debug the spring Boot Application ... 
    Forwarding from 127.0.0.1:5005 -> 5005

    Remark : You can change the local/remote ports to be used by passing the parameter -p. E.g sd exec debug -p 9009:9009

Compile the maven project within the pod (optional)

if you want or prefer to compile the project using the development's pod which contains the maven tool, then execute this command responsible to copy the following resources within the pod : pom.xml, src/ folder

sd push --mode source

And next execute the compilation using this command

sd compile
INFO[0000] sd Compile command called                    
INFO[0000] [Step 1] - Parse MANIFEST of the project if it exists 
INFO[0000] [Step 2] - Get K8s config file               
INFO[0000] [Step 3] - Create kube Rest config client using config's file of the developer's machine 
INFO[0000] [Step 4] - Wait till the dev's pod is available 
INFO[0000] [Step 5] - Compile ...                       
compile-java: started
time="2018-07-13T10:59:05Z" level=info msg="create process:run-java"
time="2018-07-13T10:59:05Z" level=info msg="create process:compile-java"
time="2018-07-13T10:59:05Z" level=info msg="create process:build"
time="2018-07-13T10:59:05Z" level=info msg="create process:echo"
time="2018-07-13T11:03:39Z" level=debug msg="no auth required"
time="2018-07-13T11:03:39Z" level=debug msg="succeed to find process:compile-java"
time="2018-07-13T11:03:39Z" level=info msg="try to start program" program=compile-java
time="2018-07-13T11:03:39Z" level=info msg="success to start program" program=compile-java
==================================================================
Starting S2I Java Build .....
Maven build detected
Initialising default settings /tmp/artifacts/configuration/settings.xml
Setting MAVEN_OPTS to -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:+UseParallelOldGC -XX:MinHeapFreeRatio=10 -XX:MaxHeapFreeRatio=20 -XX:GCTimeRatio=4 -XX:AdaptiveSizePolicyWeight=90 -XX:MaxMetaspaceSize=100m -XX:+ExitOnOutOfMemoryError
Found pom.xml ... 
Running 'mvn -Dmaven.repo.local=/tmp/artifacts/m2 -s /tmp/artifacts/configuration/settings.xml -e -Popenshift -DskipTests -Dcom.redhat.xpaas.repo.redhatga -Dfabric8.skip=true package --batch-mode -Djava.net.preferIPv4Stack=true '
Apache Maven 3.5.0 (Red Hat 3.5.0-4.3)
Maven home: /opt/rh/rh-maven35/root/usr/share/maven
Java version: 1.8.0_171, vendor: Oracle Corporation
Java home: /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.171-8.b10.el7_5.x86_64/jre
Default locale: en_US, platform encoding: ANSI_X3.4-1968
OS name: "linux", version: "3.10.0-693.21.1.el7.x86_64", arch: "amd64", family: "unix"
time="2018-07-13T11:03:40Z" level=debug msg="wait program exit" program=compile-java
[INFO] Error stacktraces are turned on.
[INFO] Scanning for projects...
[INFO] Downloading: https://repo1.maven.org/maven2/io/openshift/booster-parent/23/booster-parent-23.pom
...
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:07 min
[INFO] Finished at: 2018-07-13T11:04:49Z
[INFO] Final Memory: 26M/40M
[INFO] ------------------------------------------------------------------------
[WARNING] The requested profile "openshift" could not be activated because it does not exist.
Copying Maven artifacts from /tmp/src/target to /deployments ...
Running: cp *.jar /deployments
... done
time="2018-07-13T11:04:49Z" level=info msg="program stopped with status:exit status 0" program=compile-java
time="2018-07-13T11:04:49Z" level=info msg="Don't start the stopped program because its autorestart flag is false" program=compile-java

Remark Before to launch the compilation's command using supervisord, the program will wait till the development's pod is alive !

Trick: When the command finishes, you can verify the existence of the uberjar by executing:

oc rsh $(oc get pod -l app=my-spring-boot -o name) ls -l /deployments

Clean up

sd clean

More examples

Additional use cases are developed under the examples directory

Technical ideas

The technically consideration that we have investigated to implement the user stories are described hereafter :

  • pod of the application designed with a :

    • initContainer : supervisord [1] where different commands are registered from ENV vars. E.g. start/stop the java runtime, debug or compile (= maven), ...
    • container : created using Java S2I image
    • shared volume mounted to by example keep maven .m2 repository
  • commands can be executed remotely to trigger and action within the developer's pod -> supervisord ctl start|stop program1,....,programN

  • OpenShift Template -> converted into individual yaml files (= builder concept) and containing "{{.key}} to be processed by the go template engine

  • Developer's user preferences are stored into a MANIFEST yaml (as Cloudfoundry proposes too) which is parsed at bootstrap to create an "Application" struct object used next to process the template and replace the keys with their values

  • [1] redhat-developer/odo#556

About

Cloud Native Developer's experience for Spring Boot around Go CLI to scaffold a project, inner-loop with supervisord

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published