Sunday, 9 June 2019

Building PivotalMySQLWeb using Cloud Native Buildpacks (CNB)

Not heard of Cloud Native Buildpacks? If not this post will show why you might want to. If you want to make your developers more productive with Kubernetes, you’re going to want to look at Cloud Native Buildpacks.

https://buildpacks.io/

Until cloud platforms such as Heroku and Pivotal Cloud Foundry incorporate the Buildpack v3 Lifecycle, the fastest way to try Cloud Native Buildpacks is via the pack CLI, which integrates with your local Docker daemon. Here is an example below taking Pivotal MySQLWeb application and creating an OCI compliant image from that

Pre Steps:

1. Install pack using this link

  https://buildpacks.io/docs/install-pack/

2. Ensure you have Docker CE installed if not use this link

  https://hub.docker.com/search/?type=edition&offering=community

Steps:

1. I am using Pivotal MySQLWeb which i have packaged using maven and then taken the JAR and exploded it onto the file system to avoid compilation. You can still just use source code and the Cloud Native Buildpack's will still work but in this example I avoid the maven compilation step by using an exploded JAR file already compiled which is what a Build Service on a cloud platform would do in any case

Let's start by using "pack" to create our image as per below

papicella@papicella:~/pivotal/PCF/APJ/PPTX/CNCF/buildpacks.io/demos$ pack build pivotal-mysql-web --path ./PivotalMySQLWeb

Using default builder image cloudfoundry/cnb:cflinuxfs3
Pulling image index.docker.io/cloudfoundry/cnb:cflinuxfs3
cflinuxfs3: Pulling from cloudfoundry/cnb
18d7ea8d445c: Pull complete
18d0be9dc457: Pull complete
f5407c34df38: Pull complete
35c61e03e6bf: Pull complete
40d144c93ada: Pull complete
4f4fb700ef54: Pull complete
0432ec3bb9f8: Pull complete
3731e128636c: Pull complete
1bab066bbafe: Pull complete
4cc53e89f635: Pull complete
4fd62e90f994: Pull complete
dc9fa77b2cd2: Pull complete
3cd4ed6e9bbf: Pull complete
a525f8221dc8: Pull complete
f01bc40f59c5: Pull complete
1f9842b1696d: Pull complete
3e15eeb884d5: Pull complete
3c0f59c7956f: Pull complete
c3e6214340d9: Pull complete
6955f2c8bfad: Pull complete
5112994886a0: Pull complete
e19195f86112: Pull complete
07fb5cd454f2: Pull complete
Digest: sha256:197439e9ccc699daa6431bd7154c80b3b0ce75b072792a0e93edd6779756f3bc
Status: Downloaded newer image for cloudfoundry/cnb:cflinuxfs3
Selected run image cloudfoundry/cnb-run:cflinuxfs3 from builder
Pulling image cloudfoundry/cnb-run:cflinuxfs3
cflinuxfs3: Pulling from cloudfoundry/cnb-run
0a25bf28c5eb: Pull complete
7216becd0525: Pull complete
Digest: sha256:f9605c5af04b2ba04918879f2bf9d37c55620ae28e73b94e9926cd97bbf8fe96
Status: Downloaded newer image for cloudfoundry/cnb-run:cflinuxfs3
Using build cache volume pack-cache-1f2556cf858e.build
Executing lifecycle version 0.2.1
===> DETECTING
[detector] Trying group 1 out of 4 with 8 buildpacks...
[detector] ======== Results ========
[detector] pass: Cloud Foundry OpenJDK Buildpack
[detector] skip: Cloud Foundry Build System Buildpack
[detector] pass: Cloud Foundry JVM Application Buildpack
[detector] skip: Cloud Foundry Azure Application Insights Buildpack
[detector] skip: Cloud Foundry Debug Buildpack
[detector] skip: Cloud Foundry Google Stackdriver Buildpack
[detector] skip: Cloud Foundry JMX Buildpack
[detector] skip: Cloud Foundry Procfile Buildpack
===> RESTORING
[restorer] cache '/cache': metadata not found, nothing to restore
===> ANALYZING
===> BUILDING
[builder] -----> Cloud Foundry OpenJDK Buildpack 1.0.0-M8
[builder] -----> OpenJDK JRE 11.0.3: Contributing to layer
[builder]        Downloading from https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.3%2B7/OpenJDK11U-jre_x64_linux_hotspot_11.0.3_7.tar.gz
[builder]        Verifying checksum
[builder]        Expanding to /layers/org.cloudfoundry.openjdk/openjdk-jre
[builder]        Writing JAVA_HOME to shared
[builder]
[builder] -----> Cloud Foundry JVM Application Buildpack 1.0.0-M8
[builder] -----> Main-Class Classpath: Contributing to layer
[builder]        Writing CLASSPATH to launch
[builder] -----> Process types:
[builder]        task: java -cp $CLASSPATH $JAVA_OPTS org.springframework.boot.loader.JarLauncher
[builder]        web:  java -cp $CLASSPATH $JAVA_OPTS org.springframework.boot.loader.JarLauncher
[builder]
===> EXPORTING
[exporter] Exporting layer 'app' with SHA sha256:b32618ed6b86fb496a4ce33db9df49fdd4ef16c5646b174b5643c8befcb7408a
[exporter] Exporting layer 'config' with SHA sha256:9538e967fa10f23b3415c382a3754ebf4c2645c20b6d76af519236c1181e7639
[exporter] Exporting layer 'launcher' with SHA sha256:04ca7957074763290a9abe6a067ce8c902a2ab51ed6c55102964e3f3294cdebd
[exporter] Exporting layer 'org.cloudfoundry.openjdk:openjdk-jre' with SHA sha256:e540f1464509ac673a25bd2f24c7dd6875f805c0dd35e9af84dd4669e2fd0c93
[exporter] Exporting layer 'org.cloudfoundry.jvmapplication:main-class' with SHA sha256:8537197b3f57d86a59397b89b4fbdd14900a602cc12961eae338b9ef2513cdc0
[exporter]
[exporter] *** Image: index.docker.io/library/pivotal-mysql-web:latest@8957afa91f464e2c0adc24968c31613148b9905ff1fb90ec59ff84e165d939ac
===> CACHING
[cacher] Caching layer 'org.cloudfoundry.openjdk:d2df8bc799b09c8375f79bf646747afac3d933bb1f65de71d6c78e7466ff8fe4' with SHA sha256:11439713b023be71211cb83ecd56a1be63e0c0be3e4814a18cc4c71d2264dea5
Successfully built image pivotal-mysql-web

2. Inspect the docker image on your laptop as shown below

papicella@papicella:~/pivotal/PCF/APJ/PPTX/CNCF/buildpacks.io/demos$ docker image inspect pivotal-mysql-web

[
    {
        "Id": "sha256:8957afa91f464e2c0adc24968c31613148b9905ff1fb90ec59ff84e165d939ac",
        "RepoTags": [
            "pivotal-mysql-web:latest"
        ],
        "RepoDigests": [],
        "Parent": "",
        "Comment": "",
        "Created": "2019-06-05T05:25:58Z",
        "Container": "",
        "ContainerConfig": {

...

3. Run the docker image as shown below

papicella@papicella:~/pivotal/PCF/APJ/PPTX/CNCF/buildpacks.io/demos$ docker run --rm -p 8080:8080 pivotal-mysql-web

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.0.RELEASE)

2019-06-05 05:30:43.005  INFO 1 --- [           main] c.p.p.m.PivotalMySqlWebApplication       : Starting PivotalMySqlWebApplication on 5d21f8f32ba4 with PID 1 (/workspace/BOOT-INF/classes started by vcap in /workspace)
2019-06-05 05:30:43.009  INFO 1 --- [           main] c.p.p.m.PivotalMySqlWebApplication       : No active profile set, falling back to default profiles: default
2019-06-05 05:30:44.662  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat initialized with port(s): 8080 (http)
2019-06-05 05:30:44.686  INFO 1 --- [           main] o.apache.catalina.core.StandardService   : Starting service [Tomcat]
2019-06-05 05:30:44.687  INFO 1 --- [           main] org.apache.catalina.core.StandardEngine  : Starting Servlet Engine: Apache Tomcat/9.0.12
2019-06-05 05:30:44.698  INFO 1 --- [           main] o.a.catalina.core.AprLifecycleListener   : The APR based Apache Tomcat Native library which allows optimal performance in production environments was not found on the java.library.path: [/layers/org.cloudfoundry.openjdk/openjdk-jre/lib:/usr/java/packages/lib:/usr/lib64:/lib64:/lib:/usr/lib]
2019-06-05 05:30:44.793  INFO 1 --- [           main] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring embedded WebApplicationContext
2019-06-05 05:30:44.794  INFO 1 --- [           main] o.s.web.context.ContextLoader            : Root WebApplicationContext: initialization completed in 1736 ms
2019-06-05 05:30:45.130  INFO 1 --- [           main] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'characterEncodingFilter' to: [/*]
2019-06-05 05:30:45.131  INFO 1 --- [           main] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'webMvcMetricsFilter' to: [/*]
2019-06-05 05:30:45.131  INFO 1 --- [           main] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'hiddenHttpMethodFilter' to: [/*]
2019-06-05 05:30:45.131  INFO 1 --- [           main] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'formContentFilter' to: [/*]
2019-06-05 05:30:45.132  INFO 1 --- [           main] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'requestContextFilter' to: [/*]
2019-06-05 05:30:45.132  INFO 1 --- [           main] .s.DelegatingFilterProxyRegistrationBean : Mapping filter: 'springSecurityFilterChain' to: [/*]
2019-06-05 05:30:45.133  INFO 1 --- [           main] o.s.b.w.servlet.FilterRegistrationBean   : Mapping filter: 'httpTraceFilter' to: [/*]
2019-06-05 05:30:45.134  INFO 1 --- [           main] o.s.b.w.servlet.ServletRegistrationBean  : Servlet dispatcherServlet mapped to [/]
2019-06-05 05:30:45.436  INFO 1 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Initializing ExecutorService 'applicationTaskExecutor'
2019-06-05 05:30:45.851  INFO 1 --- [           main] .s.s.UserDetailsServiceAutoConfiguration :

Using generated security password: 3823aef6-6f72-4f5f-939d-bbd3d57ec2fa

2019-06-05 05:30:45.931  INFO 1 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: Ant [pattern='/**'], []
2019-06-05 05:30:45.967  INFO 1 --- [           main] o.s.s.web.DefaultSecurityFilterChain     : Creating filter chain: any request, [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@2e140e59, org.springframework.security.web.context.SecurityContextPersistenceFilter@26ae880a, org.springframework.security.web.header.HeaderWriterFilter@25a73de1, org.springframework.security.web.csrf.CsrfFilter@652ab8d9, org.springframework.security.web.authentication.logout.LogoutFilter@17814b1c, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@54f66455, org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter@58399d82, org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter@49a71302, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@4c03a37, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@3c017078, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@298d9a05, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@5cd61783, org.springframework.security.web.session.SessionManagementFilter@771db12c, org.springframework.security.web.access.ExceptionTranslationFilter@5f303ecd, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@73ab3aac]
2019-06-05 05:30:46.000  INFO 1 --- [           main] o.s.b.a.e.web.EndpointLinksResolver      : Exposing 9 endpoint(s) beneath base path '/actuator'
2019-06-05 05:30:46.096  INFO 1 --- [           main] o.s.b.w.embedded.tomcat.TomcatWebServer  : Tomcat started on port(s): 8080 (http) with context path ''
2019-06-05 05:30:46.101  INFO 1 --- [           main] c.p.p.m.PivotalMySqlWebApplication       : Started PivotalMySqlWebApplication in 3.654 seconds (JVM running for 4.324)


4. Browse to localhost:8080 to invoke the application just to be sure it worked



5. Publish the OCI compliant image to your registry. In this example I am using Docker Hub as shown below

papicella@papicella:~/pivotal/PCF/APJ/PPTX/CNCF/buildpacks.io/demos$ pack build pasapples/pivotal-mysql-web:latest --publish --path ./PivotalMySQLWeb --no-pull

Using default builder image cloudfoundry/cnb:cflinuxfs3
Selected run image cloudfoundry/cnb-run:cflinuxfs3 from builder
Using build cache volume pack-cache-a4a78257c7be.build
Executing lifecycle version 0.2.1
===> DETECTING
[detector] Trying group 1 out of 4 with 8 buildpacks...
[detector] ======== Results ========
[detector] pass: Cloud Foundry OpenJDK Buildpack
[detector] skip: Cloud Foundry Build System Buildpack
[detector] pass: Cloud Foundry JVM Application Buildpack
[detector] skip: Cloud Foundry Azure Application Insights Buildpack
[detector] skip: Cloud Foundry Debug Buildpack
[detector] skip: Cloud Foundry Google Stackdriver Buildpack
[detector] skip: Cloud Foundry JMX Buildpack
[detector] skip: Cloud Foundry Procfile Buildpack
===> RESTORING
[restorer] cache '/cache': metadata not found, nothing to restore
===> ANALYZING
===> BUILDING
[builder] -----> Cloud Foundry OpenJDK Buildpack 1.0.0-M8
[builder] -----> OpenJDK JRE 11.0.3: Contributing to layer
[builder]        Downloading from https://github.com/AdoptOpenJDK/openjdk11-binaries/releases/download/jdk-11.0.3%2B7/OpenJDK11U-jre_x64_linux_hotspot_11.0.3_7.tar.gz
[builder]        Verifying checksum
[builder]        Expanding to /layers/org.cloudfoundry.openjdk/openjdk-jre
[builder]        Writing JAVA_HOME to shared
[builder]
[builder] -----> Cloud Foundry JVM Application Buildpack 1.0.0-M8
[builder] -----> Main-Class Classpath: Contributing to layer
[builder]        Writing CLASSPATH to launch
[builder] -----> Process types:
[builder]        task: java -cp $CLASSPATH $JAVA_OPTS org.springframework.boot.loader.JarLauncher
[builder]        web:  java -cp $CLASSPATH $JAVA_OPTS org.springframework.boot.loader.JarLauncher
[builder]
===> EXPORTING
[exporter] Exporting layer 'app' with SHA sha256:b32618ed6b86fb496a4ce33db9df49fdd4ef16c5646b174b5643c8befcb7408a
[exporter] Exporting layer 'config' with SHA sha256:9538e967fa10f23b3415c382a3754ebf4c2645c20b6d76af519236c1181e7639
[exporter] Exporting layer 'launcher' with SHA sha256:04ca7957074763290a9abe6a067ce8c902a2ab51ed6c55102964e3f3294cdebd
[exporter] Exporting layer 'org.cloudfoundry.openjdk:openjdk-jre' with SHA sha256:e540f1464509ac673a25bd2f24c7dd6875f805c0dd35e9af84dd4669e2fd0c93
[exporter] Exporting layer 'org.cloudfoundry.jvmapplication:main-class' with SHA sha256:8537197b3f57d86a59397b89b4fbdd14900a602cc12961eae338b9ef2513cdc0
[exporter]
[exporter] *** Image: index.docker.io/pasapples/pivotal-mysql-web:latest@sha256:c862eda516289c2daa29580c95b74b4d72eca9caf941a3a6ac2bf2bd886057e5
===> CACHING
[cacher] Caching layer 'org.cloudfoundry.openjdk:d2df8bc799b09c8375f79bf646747afac3d933bb1f65de71d6c78e7466ff8fe4' with SHA sha256:11439713b023be71211cb83ecd56a1be63e0c0be3e4814a18cc4c71d2264dea5
Successfully built image pasapples/pivotal-mysql-web:latest


At this point you have a OCI compliant image sitting in your registry ready to be consumed for your K8's application needs all from just source code or pre compiled source code in this example a Java Application. Let's not forget this support's a polyglot programming model so supports NodeJS, Python and anything that buildpack's supports.

More Information

1. Cloud Native Buildpacks: an Industry-Standard Build Process for Kubernetes and Beyond.

2. buildspacks.io Home Page

No comments: