GithubHelp home page GithubHelp logo

aureamunoz / component-operator-demo Goto Github PK

View Code? Open in Web Editor NEW

This project forked from snowdrop/component-operator-demo

0.0 2.0 0.0 329 KB

Demo project to install Spring Boot (Client, CRUD) applications and Service on k8s using Component CRD processed by an operator on the cloud platform

Java 53.64% HTML 27.37% JavaScript 14.89% Shell 4.11%

component-operator-demo's Introduction

Spring Boot Demo using Component's CRD

Introduction

The purpose of this demo is to showcase how you can use Component CRD and a Kubernetes operator deployed on OpenShift to help you to install your Microservices Spring Boot application, instantiate a database using a Kubernetes Service Catalog and inject the required information to the different Microservices to let a Spring Boot application to access/consume a service (http endpoint, database, ...).

The demo's project consists, as depicted within the following diagram, of two Spring Boot applications and a PostgreSQL Database.

Composition

The application to be deployed can be described using a Fluent DSL syntax as :

(from:componentA).(to:componentB).(to:serviceA)

where the ComponentA and ComponentB correspond respectively to a Spring Boot application fruit-client-sb and fruit-backend-sb.

The relation from -> to indicates that we will reference the ComponentA with the ComponentB using a Link.

The link's purpose is to inject as Env var(s) the information required to by example configure the HTTP client of the ComponentA to access the ComponentB which exposes the logic of the backend's system as CRUD REST operations.

To let the ComponentB to access the database, we will also setup a link in order to pass using the Secret of the service instance created the parameters which are needed to configure a Spring Boot Datasource's bean.

The deployment or installation of the application in a namespace will consist in to create the resources on the platform using some Component yaml resource files defined according to the Component API spec. When they will be created, then the Component operator which is a Kubernetes controller will execute different operations to create :

  • For the component-runtime a development's pod running a supervisord's daemon able to start/stop the application [1] and where we can push the uber jar file compiled locally,
  • A Service using the OpenShift Automation Broker and the Kubernetes Service Catalog [2],
  • EnvVar section for the development's pod [3].

Setup

Hetzner remote's cluster

oc login https://195.201.87.126:8443 --token=TOKEN_PROVIDED_BY_SNOWDROP_TEAM
oc project <user_project>

Local cluster using MiniShift

  • Minishift (>= v1.26.1) with Service Catalog feature enabled
  • Launch Minishift VM
# if you don't have a minishift VM, start as follows
minishift addons enable xpaas
minishift addons enable admin-user
minishift start
minishift openshift component add service-catalog
minishift openshift component add automation-service-broker
  • Login to MiniShift using admin's user
oc login https://$(minishift ip):8443 -u admin -p admin
  • Deploy the resources within the namespace component-operator
oc new-project component-operator
oc create -f resources/sa.yaml
oc create -f resources/cluster-rbac.yaml
oc create -f resources/user-rbac.yaml
oc create -f resources/crd.yaml
oc create -f resources/operator.yaml

Demo's time

Install the project

  • Login to the OpenShift's cluster using your favorite user
oc login https://ip_address_or_hostname_fqdn>:8443 -u <user> -p <password
  • Git clone the project locally to play with a Spring Boot composite application
git clone https://github.com/snowdrop/component-operator-demo.git && cd component-operator-demo
  • Create a new project my-spring-app
oc new-project my-spring-app

Build code

  • Build the Client and the Backend using mvn tool to generate their respective Spring Boot uber jar file
cd fruit-client
mvn package
cd ..
cd fruit-backend-sb
mvn package
cd ..

Install the components

  • Deploy for each microservice, their Component CRs on the cluster and wait till they will be processed by the controller to create the corresponding kubernetes resources such as DeploymentConfig, Pod, Service, Route, ...
oc apply -f fruit-backend-sb/component.yml
oc apply -f fruit-client-sb/component.yml
  • Verify that we have 2 components installed
oc get components
NAME            RUNTIME       VERSION   SERVICE   TYPE      CONSUMED BY   AGE
fruit-backend-sb   spring-boot   1.5.16                                      34s
fruit-client    spring-boot   1.5.16                                      32s

Create the database's service usign the Catalog

  • Create the PostgreSQL database using the db-service.yml Component CR
oc apply -f service/database.yml

WARNING As this process is performed asynchrounously and is managed by the Kubernetes Service Catalog controller in combination with the Service Broker, then this process can take time !

Remark Use the following command to check the status of the instance which, at the end of the installation process, should be equal to ready

oc get serviceinstance/postgresql-db
NAME            CLASS                                   PLAN      STATUS    AGE
postgresql-db   ClusterServiceClass/dh-postgresql-apb   dev       Ready     3m
  • Control as we did before that we have 3 components installed: 2 Spring Boot runtimes and 1 service
oc get components
NAME             RUNTIME       VERSION   SERVICE         TYPE      CONSUMED BY   AGE
fruit-backend-sb    spring-boot   1.5.16                                            2m
fruit-client     spring-boot   1.5.16                                            2m
fruit-database                           postgresql-db                           6s

Link the components

  • Inject as ENV variables the parameters of the database to let Spring Boot to create a Datasource's bean to connect to the database using the secret created
oc apply -f fruit-backend-sb/env-secret-service.yml
  • Inject the endpoint's address of the fruit backend application as an ENV Var. This ENV Var will be used as parameter by the Spring Boot application to configure the HTTP client to access the backend
oc apply -f fruit-client-sb/env-backend-endpoint.yml

Push the code and start the Spring Boot application

  • As we have finished to compose our application from Spring Boot Http Client -> to Spring Boot REST Backend -> to PostgreSQL database, we will now copy the uber jar files, and next start the client, backend Spring Boot applications. Execute the following commands :
./scripts/push_start.sh fruit-client sb
./scripts/push_start.sh fruit-backend sb

Use ap4k and yaml files generated

  • Edit the pom.xml file of the fruit-client-sb and fruit-backend-sb maven modules and add the ap4k gavs (responsible to scan the annotated class and to generate the yaml resource files)
<!-- To generate CRD -->
<dependency>
    <groupId>io.ap4k</groupId>
    <artifactId>ap4k-core</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>io.ap4k</groupId>
    <artifactId>component-annotations</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
<!-- Only needed for the backend component -->
<dependency>
    <groupId>io.ap4k</groupId>
    <artifactId>servicecatalog-annotations</artifactId>
    <version>1.0-SNAPSHOT</version>    
</dependency>
<dependency>
    <groupId>io.ap4k</groupId>
    <artifactId>ap4k-spring-boot</artifactId>
    <version>1.0-SNAPSHOT</version>    
</dependency>
  • Edit the Application class to specify the Component's definition, service or relations (= links).

    The @CompositeApplication is used by the ap4k lib to generate a Component CRD resource, containing the definition of the runtime, the name of the component, if a route is needed.

    A @Link represents additional information or metadata to be injected within the Comnponent (aka DeploymentConfig resource) in order to configure the application to access another component using its service address, a service deployed from the k8s catalog.

    client

    @CompositeApplication(
            name = "fruit-client-sb",
            exposeService = true,
            links = @Link(
                      name = "Env var to be injected within the target component -> fruit-backend",
                      targetcomponentname = "fruit-client-sb",
                      kind = "Env",
                      ref = "",
                      envVars = @Env(
                              name  = "OPENSHIFT_ENDPOINT_BACKEND",
                              value = "http://fruit-backend-sb:8080/api/fruits"
                      )
    ))

    To express the creation of a service on the Cloud platform, we are using the @ServiceCatalog annotation where we define the Service's class, its plan and parameters.

    Like for the Client's component, we will also define a @Link annotation to inject from the secret created during the creation of the service, the parameters that the application will use to configure, in this example, the DataSource's object able to call the PostgreSQL instance.

    Backend

    @CompositeApplication(
            name = "fruit-backend-sb",
            exposeService = true,
            envVars = @Env(
                    name = "SPRING_PROFILES_ACTIVE",
                    value = "openshift-catalog"),
            links = @Link(
                    name = "Secret to be injected as EnvVar using Service's secret",
                    targetcomponentname = "fruit-backend-sb",
                    kind = "Secret",
                    ref = "postgresql-db"))
    @ServiceCatalog(
       instances = @ServiceCatalogInstance(
            name = "postgresql-db",
            serviceClass = "dh-postgresql-apb",
            servicePlan = "dev",
            bindingSecret = "postgresql-db",
            parameters = {
                    @Parameter(key = "postgresql_user", value = "luke"),
                    @Parameter(key = "postgresql_password", value = "secret"),
                    @Parameter(key = "postgresql_database", value = "my_data"),
                    @Parameter(key = "postgresql_version", value = "9.6")
            }
       )
    ) 
  • Compile the modules at the root of the project

mvn clean install
  • Deploy the generated component.yaml resource files
oc apply -f fruit-client-sb/target/classes/META-INF/ap4k/component.yml
oc apply -f fruit-backend-sb/target/classes/META-INF/ap4k/component.yml
  • Push the code and launch the java application
./scripts/push_start.sh fruit-client sb
./scripts/push_start.sh fruit-backend sb

Check if the Component Client is replying

  • Call the HTTP Endpoint exposed by the Spring Boot Fruit Client in order to fetch data from the database
route_address=$(oc get route/fruit-client-sb -o jsonpath='{.spec.host}')
curl http://$route_address/api/client
or 

using httpie client
http -s solarized http://$route_address/api/client
http -s solarized http://$route_address/api/client/1
http -s solarized http://$route_address/api/client/2
http -s solarized http://$route_address/api/client/3

Switch fromm inner to outer loop

  • Decorate the Component with the following values in order to specify the git info needed to perform a Build, like the name of the component to be selected to switch from the dev loop to the publish loop

     annotations:
       app.openshift.io/git-uri: https://github.com/snowdrop/component-operator-demo.git
       app.openshift.io/git-ref: master
       app.openshift.io/git-dir: fruit-backend-sb
       app.openshift.io/artifact-copy-args: "*.jar"
       app.openshift.io/runtime-image: "fruit-backend-sb"
       app.openshift.io/component-name: "fruit-backend-sb"
       app.openshift.io/java-app-jar: "fruit-backend-sb-0.0.1-SNAPSHOT.jar"

    Remark : When the maven project does not contain multi modules, then replace the name of the folder / module with . using the annotation app.openshift.io/git-dir

  • Patch the component when it has been deployed to switch fromm inner to outer

    oc patch cp fruit-backend-sb -p '{"spec":{"deploymentMode":"outerloop"}}' --type=merge

Nodejs deployment

  • Build node project locally
cd fruit-client-nodejs
nvm use v10.1.0
npm audit fix
npm install -s --only=production
  • Run locally
export OPENSHIFT_ENDPOINT_BACKEND=http://fruit-backend-sb.my-spring-app.195.201.87.126.nip.io/api/fruits
npm run -d start      
  • Deploy the node's component and link it to the Spring Boot fruit backend
oc apply -f fruit-client-nodejs/component.yml
oc apply -f fruit-client-nodejs/env-backend-endpoint.yml
  • Push the code and start the nodejs application
./scripts/push_start.sh fruit-client nodejs
  • Test it locally or remotely
# locally
http :8080/api/client
http :8080/api/client/1 

#Remotely
route_address=$(oc get route/fruit-client-nodejs -o jsonpath='{.spec.host}')
curl http://$route_address/api/client
or 

using httpie client
http http://$route_address/api/client
http http://$route_address/api/client/1
http http://$route_address/api/client/2
http http://$route_address/api/client/3

Scaffold a project

git clone [email protected]:snowdrop/scaffold-command.git && cd scaffold-command
go build -o scaffold cmd/scaffold.go
export PATH=$PATH:/Users/dabou/Code/snowdrop/scaffold-command

 scaffold   
? Create from template Yes
? Available templates rest
? Group Id me.snowdrop
? Artifact Id myproject
? Version 1.0.0-SNAPSHOT
? Package name me.snowdrop.myproject
? Spring Boot version 2.1.2.RELEASE
? Use supported version No
? Where should we create your new project ./fruit-demo

cd demo

add to the pom.xml file

<properties>
  ...
  <ap4k.version>0.3.2</ap4k.version>
</properties>
  
and 

<dependencies>
  <dependency>
    <groupId>io.ap4k</groupId>
    <artifactId>component-annotations</artifactId>
    <version>${ap4k.version}</version>
  </dependency>
  <dependency>
    <groupId>io.ap4k</groupId>
    <artifactId>kubernetes-annotations</artifactId>
    <version>${ap4k.version}</version>
  </dependency>
  <dependency>
    <groupId>io.ap4k</groupId>
    <artifactId>ap4k-spring-boot</artifactId>
    <version>${ap4k.version}</version>
  </dependency>
  <!-- spring Boot -->
  

Cleanup

Demo components

oc delete cp/fruit-backend-sb
oc delete cp/fruit-database
oc delete cp/fruit-database-config

oc delete cp/fruit-client
oc delete cp/fruit-endpoint

Operator and CRD resources

oc delete -f resources/sa.yaml -n component-operator
oc delete -f resources/cluster-rbac.yaml
oc delete -f resources/crd.yaml 
oc delete -f resources/operator.yaml -n component-operator

Start locally Postgresql

brew install [email protected]
echo 'export PATH="/usr/local/opt/[email protected]/bin:$PATH"' >> ~/.zshrc
pg_ctl -D /usr/local/var/[email protected] start
createuser -s postgres
psql -U postgres -h localhost
createdb -h localhost -p 5432 -U postgres springbootdb

component-operator-demo's People

Contributors

cmoulliard avatar metacosm avatar

Watchers

James Cloos avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.