Kubernetes

kpack - A guide to build optimized app-image

2021-05-0122 min read

kpack - A guide to build optimized app-image

kpack extends Kubernetes and utilizes kubernetes capabilities to provide builds of OCI images as a platform implementation of Cloud Native Buildpacks (CNB). It provides a declarative image type that builds an image ( with app source and configurations) and then schedules image rebuilds for any source or underlying buildpack changes.

Some history about kpack

Buildpacks were first conceived by Heroku in 2011. Later, Pivotal and Heroku teamed up to create Cloud Native Buildpacks for Kubernetes. Then, Pivotal open-sourced kpack, which started as an experimental build service Kubernetes resource controllers but soon going to be the key to app build and modernisation process.

Prerequisites for image build

  • A Kubernetes cluster version 1.15 or later
  • kubectl CLI
  • User with cluster-admin permission
  • Accessible Docker V2 Registry

Configure kpack

kpack services provide a kubernetes build type to execute a single Cloud Native Buildpack image build. The process generates an image resource which actively keeps watch on any buildpack or source change for rebuild. For supporting the App image creation process, there would be a cache maintained as persistent-storage for each image resource with all the underlying app dependencies & supporting resources during image build process.

Install kpack

We can download the resources for kpack from here We can apply resources to install kpack to a kubernetes cluster.

kubectl apply -f release-0.0.9.yaml

Result shows various resource created in k8s cluster.

 
$ kubectl apply -f release-0.2.2.yaml
 
namespace/kpack created
customresourcedefinition.apiextensions.k8s.io/builds.kpack.io created
customresourcedefinition.apiextensions.k8s.io/builders.kpack.io created
customresourcedefinition.apiextensions.k8s.io/clusterbuilders.kpack.io created
customresourcedefinition.apiextensions.k8s.io/clusterstores.kpack.io created
configmap/build-init-image created
configmap/build-init-windows-image created
configmap/rebase-image created
configmap/lifecycle-image created
configmap/completion-image created
configmap/completion-windows-image created
deployment.apps/kpack-controller created
serviceaccount/controller created
clusterrole.rbac.authorization.k8s.io/kpack-controller-admin created
clusterrolebinding.rbac.authorization.k8s.io/kpack-controller-admin-binding created
role.rbac.authorization.k8s.io/kpack-controller-local-config created
rolebinding.rbac.authorization.k8s.io/kpack-controller-local-config-binding created
customresourcedefinition.apiextensions.k8s.io/images.kpack.io created
service/kpack-webhook created
customresourcedefinition.apiextensions.k8s.io/sourceresolvers.kpack.io created
customresourcedefinition.apiextensions.k8s.io/clusterstacks.kpack.io created
Warning: admissionregistration.k8s.io/v1beta1 MutatingWebhookConfiguration is deprecated in v1.16+, unavailable in v1.22+; use admissionregistration.k8s.io/v1 MutatingWebhookConfiguration
mutatingwebhookconfiguration.admissionregistration.k8s.io/defaults.webhook.kpack.io created
Warning: admissionregistration.k8s.io/v1beta1 ValidatingWebhookConfiguration is deprecated in v1.16+, unavailable in v1.22+; use admissionregistration.k8s.io/v1 ValidatingWebhookConfiguration
validatingwebhookconfiguration.admissionregistration.k8s.io/validation.webhook.kpack.io created
secret/webhook-certs created
deployment.apps/kpack-webhook created
serviceaccount/webhook created
role.rbac.authorization.k8s.io/kpack-webhook-certs-admin created
rolebinding.rbac.authorization.k8s.io/kpack-webhook-certs-admin-binding created
clusterrole.rbac.authorization.k8s.io/kpack-webhook-mutatingwebhookconfiguration-admin created
clusterrolebinding.rbac.authorization.k8s.io/kpack-webhook-certs-mutatingwebhookconfiguration-admin-binding created

We can observe the controller and webhook resources created for kpack.

 
$ kubectl get all -n kpack
NAME                                    READY   STATUS    RESTARTS   AGE
pod/kpack-controller-6d7b8f49ff-fcc8d   1/1     Running   0          17s
pod/kpack-webhook-597484b97-pzbtp       1/1     Running   0          17s
 
NAME                    TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
service/kpack-webhook   ClusterIP   100.71.36.244   <none>        443/TCP   18s
 
NAME                               READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/kpack-controller   1/1     1            1           18s
deployment.apps/kpack-webhook      1/1     1            1           18s
 
NAME                                          DESIRED   CURRENT   READY   AGE
replicaset.apps/kpack-controller-6d7b8f49ff   1         1         1       18s
replicaset.apps/kpack-webhook-597484b97       1         1         1       18s

Once we install kpack, the following kubernetes custom resources get installed in to the cluster.

 
$ kubectl api-resources | grep kpack -i
builders                          bldr,bldrs                    kpack.io/v1alpha1                                    true         Builder
builds                            cnbbuild,cnbbuilds,bld,blds   kpack.io/v1alpha1                                    true         Build
clusterbuilders                   clstbldr,clstbldrs            kpack.io/v1alpha1                                    false        ClusterBuilder
clusterstacks                                                   kpack.io/v1alpha1                                    false        ClusterStack
clusterstores                                                   kpack.io/v1alpha1                                    false        ClusterStore
images                            cnbimage,cnbimages,img,imgs   kpack.io/v1alpha1                                    true         Image
sourceresolvers                                                 kpack.io/v1alpha1                                    true         SourceResolver

Add custom certs to kpack

In case we are using a registry that has a self-signed certificate, need to update kpack controller to trust that certificate. It can be done by using SSL_CERT_FILE and SSL_CERT_DIR environment variables, so registry can be trusted by mounting the certificates into the controller’s deployment and setting the environment variable.

To perform, we need to create a kubernetes secret of tls type with the cert and key for the registry’s CA. Then, mount the secret into kpack controller and pass the path as an environment variable.

 
$ kubectl create secret tls  custom-ca --cert=ca.crt --key=ca.key -n kpack
secret/custom-ca created
 
$ kubectl edit deploy kpack-controller -n kpack
apiVersion: apps/v1
kind: Deployment
metadata:
  name: kpack-controller
  namespace: kpack
spec:
  replicas: 1
  selector:
    matchLabels:
      app: kpack-controller
  template:
    metadata:
      labels:
        app: kpack-controller
        version: 0.2.2-rc.1
    spec:
      serviceAccountName: controller
      nodeSelector:
        kubernetes.io/os: linux
      volumes:
        - name: custom-certs
          secret:
            secretName: custom-ca
      containers:
        - name: controller
          image: gcr.io/cf-build-service-public/kpack/controller@sha256:ec256da7e29eeecdd0821f499e754080672db8f0bc521b2fa1f13f6a75a04835
          volumeMounts:
            - name: custom-certs
              mountPath: /certs
          env:
            - name: SSL_CERT_DIR
              value: /certs

Install logs utility

We would also install the kpack log utility. It would be used later to access and monitor build logs for image creation process. The utility resource to install can be found here.

 
$ logs -h
Usage of logs:
  -build string
    	The build number to tail logs
  -image string
    	The image name to tail logs
  -kubeconfig string
    	Path to a kubeconfig.
  -master string
    	The address of the Kubernetes API server. Overrides any value in kubeconfig.
  -namespace string
    	The namespace of the image (default "default")

Prepare cluster for image builds

The entire cloud native buildpack stack consists of some key components. We would prepare the cluster with those components.

Configure ClusterStack

A ClusterStore resource is a repository of buildpacks packaged in buildpackages that can be used by kpack to build images.

 
apiVersion: kpack.io/v1alpha1
kind: ClusterStore
metadata:
  name: default
spec:
  sources:
  - image: gcr.io/paketo-buildpacks/java
  - image: gcr.io/paketo-buildpacks/nodejs

Configure ClusterStore

A ClusterStack resource is the specification for a cloud native buildpacks stack used during build and in the resulting app image. A stack is composed of two images that are intended to work together:

  • The build image of a stack provides the base image from which the build environment is constructed. The build environment is the containerized environment in which the lifecycle (and thereby buildpacks) are executed.
  • The run image of a stack provides the base image from which application images are built.
 
apiVersion: kpack.io/v1alpha1
kind: ClusterStack
metadata:
  name: base
spec:
  id: "io.buildpacks.stacks.bionic"
  buildImage:
    image: "paketobuildpacks/build:base-cnb"
  runImage:
    image: "paketobuildpacks/run:base-cnb"

Configure ClusterBuilder

A Builder is the kpack configuration for a builder image that includes the stack and buildpacks needed to build an image from your app source code. This builder object uses a ClusterStore, a ClusterStack, and an order definition to construct a builder image.

clusterbuilder.yml

 
$ cat clusterbuilder.yml
apiVersion: kpack.io/v1alpha1
kind: ClusterBuilder
metadata:
  name: default
spec:
  tag: pvtregistry.txvlab.com/kpack/builder
  stack:
    name: base
    kind: ClusterStack
  store:
    name: default
    kind: ClusterStore
  serviceAccountRef:
    name: build-sa
    namespace: kpack
  order:
  - group:
    - id: paketo-buildpacks/java
  - group:
    - id: paketo-buildpacks/nodejs

I have also created a kubernetes secret of registry type to pass the credentials for the private registry. We assign the secret to act as the imagePullSecret during builder creation, by assigning secret to service account “build-sa”

 
$ cat build-sa.yml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: build-sa
secrets:
  - name: regcredhbr
imagePullSecrets:
  - name: regcredhbr

Install clusterBuilder :

$ kubectl apply -f clusterbuilder.yml
clusterbuilder.kpack.io/default created

Result:

 
$ kubectl get clusterbuilders.kpack.io default
NAME      LATESTIMAGE                                                                                                    READY
default   pvtregistry.txvlab.com/kpack/builder@sha256:f819bc21837c2faf9858934c810bfc3ee9739455a18aa835a578bbcc0bf0866e   True

Details about the supported buildpacks in the builder can be found with kubectl describe command.

 
Builder Metadata:
    Homepage:  https://github.com/paketo-buildpacks/bellsoft-liberica
    Id:        paketo-buildpacks/bellsoft-liberica
    Version:   8.0.0
    Homepage:  https://github.com/paketo-buildpacks/spring-boot
    Id:        paketo-buildpacks/spring-boot
    Version:   4.2.0
    Homepage:  https://github.com/paketo-buildpacks/google-stackdriver
    Id:        paketo-buildpacks/google-stackdriver
    Version:   3.10.0
    Homepage:  https://github.com/paketo-buildpacks/apache-tomcat
    Id:        paketo-buildpacks/apache-tomcat
    Version:   5.3.0
    Homepage:  https://github.com/paketo-buildpacks/azure-application-insights
    Id:        paketo-buildpacks/azure-application-insights
    Version:   4.3.0
    Homepage:  https://github.com/paketo-buildpacks/ca-certificates
    Id:        paketo-buildpacks/ca-certificates
    Version:   2.2.0
    Homepage:  https://github.com/paketo-buildpacks/ca-certificates
    Id:        paketo-buildpacks/ca-certificates
    Version:   2.1.0
    Homepage:  https://github.com/paketo-buildpacks/procfile
    Id:        paketo-buildpacks/procfile
    Version:   4.1.0
    Homepage:  https://github.com/paketo-buildpacks/node-engine
    Id:        paketo-buildpacks/node-engine
    Version:   0.3.0
    Homepage:  https://github.com/paketo-buildpacks/yarn-install
    Id:        paketo-buildpacks/yarn-install
    Version:   0.3.0
    Homepage:  https://github.com/paketo-buildpacks/yarn
    Id:        paketo-buildpacks/yarn
    Version:   0.2.0
    Homepage:  https://github.com/paketo-buildpacks/encrypt-at-rest
    Id:        paketo-buildpacks/encrypt-at-rest
    Version:   3.0.0
    Homepage:  https://github.com/paketo-buildpacks/debug
    Id:        paketo-buildpacks/debug
    Version:   3.0.0
    Homepage:  https://github.com/paketo-buildpacks/maven
    Id:        paketo-buildpacks/maven
    Version:   5.1.0
    Homepage:  https://github.com/paketo-buildpacks/sbt
    Id:        paketo-buildpacks/sbt
    Version:   5.2.0
    Homepage:  https://github.com/paketo-buildpacks/gradle
    Id:        paketo-buildpacks/gradle
    Version:   5.2.0
    Homepage:  https://github.com/paketo-buildpacks/leiningen
    Id:        paketo-buildpacks/leiningen
    Version:   3.1.0
    Homepage:  https://github.com/paketo-buildpacks/jmx
    Id:        paketo-buildpacks/jmx
    Version:   3.0.0
    Homepage:  https://github.com/paketo-buildpacks/npm-install
    Id:        paketo-buildpacks/npm-install
    Version:   0.3.0
    Homepage:  https://github.com/paketo-buildpacks/npm-start
    Id:        paketo-buildpacks/npm-start
    Version:   0.2.0
    Homepage:  https://github.com/paketo-buildpacks/yarn-start
    Id:        paketo-buildpacks/yarn-start
    Version:   0.1.0
    Homepage:  https://github.com/paketo-buildpacks/node-start
    Id:        paketo-buildpacks/node-start
    Version:   0.2.0
    Homepage:  https://github.com/paketo-buildpacks/executable-jar
    Id:        paketo-buildpacks/executable-jar
    Version:   5.0.0
    Homepage:  https://github.com/paketo-buildpacks/environment-variables
    Id:        paketo-buildpacks/environment-variables
    Version:   3.0.0
    Homepage:  https://github.com/paketo-buildpacks/image-labels
    Id:        paketo-buildpacks/image-labels
    Version:   3.0.0
    Homepage:  https://github.com/paketo-buildpacks/dist-zip
    Id:        paketo-buildpacks/dist-zip
    Version:   4.0.0
    Homepage:  https://github.com/paketo-buildpacks/java
    Id:        paketo-buildpacks/java
    Version:   5.7.0
    Homepage:  https://github.com/paketo-buildpacks/nodejs
    Id:        paketo-buildpacks/nodejs
    Version:   0.3.0

Image Build Process

Lets create a namespace to use for the app image build process

$ kubectl create ns helloapp-project
namespace/helloapp-project created

As part of preparation to build app image, need to configure the kubernetes secret of registry type for the private registry and any other registry to be used for storing app images (i.e docker registry in current case).

Also need to configure secret for git repo credentials. We assume the source code is maintained in a github repo.

 
kubectl create secret docker-registry regcreddoc \
    --docker-username=USERNAME \
    --docker-password=PASSWORD \
    --docker-server=https://index.docker.io/v1/ \
    --namespace helloapp-project
 
kubectl create secret docker-registry regcredhbr \
    --docker-username=USERNAME \
    --docker-password=PASSWORD \
    --docker-server=https://pvtregistry.txvlab.com \
    --namespace helloapp-project
 
$ cat git-cred.yml
apiVersion: v1
kind: Secret
metadata:
  name: git-cred
  annotations:
    build.pivotal.io/git: https://github.com
type: kubernetes.io/basic-auth
stringData:
  username: <username>
  password: <password>
 
$ cat app-sa.yml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: app-sa
secrets:
  - name: regcreddoc
  - name: regcredhbr
  - name: git-cred
imagePullSecrets:
  - name: regcreddoc
  - name: regcredhbr

Apply the kubernetes resource to create docker-registry and git-cred secret and the “app-sa” service account. Let’s prepare the app image resource specifying the configured ClusterBuilder, service-account and source path.

appimage.yml

 
$ cat appimage.yml
apiVersion: kpack.io/v1alpha1
kind: Image
metadata:
  name: helloapp
  namespace: helloapp-project
spec:
  tag: txconsole/helloapp
  serviceAccount: app-sa
  builder:
    name: default
    kind: ClusterBuilder
  source:
    git:
      url: https://github.com/txconsole/helloapp.git
      revision: master

Now, apply the image resource to the kubernetes cluster.

Once the image resources is applied, it would create resources for image, build and a pod to perform the build action.

 
$ kubectl get pod,builds,image -n helloapp-project
NAME                                   READY   STATUS     RESTARTS   AGE
pod/helloapp-build-1-jtsdc-build-pod   0/1     Init:0/6   0          6s
 
NAME                                    IMAGE   SUCCEEDED
build.kpack.io/helloapp-build-1-jtsdc           Unknown
 
NAME                      LATESTIMAGE   READY
image.kpack.io/helloapp                 Unknown

We can use the logs executable(installed in local-workstation) to monitor the image build logs and status.

logs utility tool uses the kubernetes context from configured kubeconfig in local-workspation to detect & connect to the current “in-use” kubernetes cluster context.

The builder image represented by the ClusterBuilder resources provisions the lifecycle scripts which would facilitate the image build.

During the build process, the lifecycle orchestrates the buildpack execution, then assembles resulting artifacts into final app image. At high level, lifecycle stages can be defined as below :

  • Detection – Finds an ordered group of buildpacks to use during the build phase.
  • Analysis – Restores files that buildpacks may use to optimize the build and export phases.
  • Build – Transforms app source code into runnable artifacts to be packaged as a container.
  • Export – Creates the final OCI image.
 
$ logs -image helloapp -namespace helloapp-project
 
===> PREPARE
Build reason(s): CONFIG
CONFIG:
	resources: {}
	- source: {}
	+ source:
	+   git:
	+     revision: 76e91560cce2abe386af0d133d3ede96599277e2
	+     url: https://github.com/txconsole/helloapp.git
Loading secret for "https://index.docker.io/v1/" from secret "regcreddoc" at location "/var/build-secrets/regcreddoc"
Loading secret for "https://pvtregistry.txvlab.com" from secret "regcredhbr" at location "/var/build-secrets/regcredhbr"
Cloning "https://github.com/txconsole/helloapp.git" @ "76e91560cce2abe386af0d133d3ede96599277e2"...
Successfully cloned "https://github.com/txconsole/helloapp.git" @ "76e91560cce2abe386af0d133d3ede96599277e2" in path "/workspace"
===> DETECT
7 of 18 buildpacks participating
paketo-buildpacks/ca-certificates   2.2.0
paketo-buildpacks/bellsoft-liberica 8.0.0
paketo-buildpacks/maven             5.1.0
paketo-buildpacks/executable-jar    5.0.0
paketo-buildpacks/apache-tomcat     5.3.0
paketo-buildpacks/dist-zip          4.0.0
paketo-buildpacks/spring-boot       4.2.0
===> ANALYZE
Previous image with name "txconsole/helloapp" not found
===> RESTORE
===> BUILD
 
Paketo CA Certificates Buildpack 2.2.0
  https://github.com/paketo-buildpacks/ca-certificates
  Launch Helper: Contributing to layer
    Creating /layers/paketo-buildpacks_ca-certificates/helper/exec.d/ca-certificates-helper
 
Paketo BellSoft Liberica Buildpack 8.0.0
  https://github.com/paketo-buildpacks/bellsoft-liberica
  Build Configuration:
    $BP_JVM_VERSION              11              the Java version
  Launch Configuration:
    $BPL_JVM_HEAD_ROOM           0               the headroom in memory calculation
    $BPL_JVM_LOADED_CLASS_COUNT  35% of classes  the number of loaded classes in memory calculation
    $BPL_JVM_THREAD_COUNT        250             the number of threads in memory calculation
    $JAVA_TOOL_OPTIONS                           the JVM launch flags
  BellSoft Liberica JDK 11.0.11: Contributing to layer
    Downloading from https://github.com/bell-sw/Liberica/releases/download/11.0.11+9/bellsoft-jdk11.0.11+9-linux-amd64.tar.gz
    Verifying checksum
    Expanding to /layers/paketo-buildpacks_bellsoft-liberica/jdk
    Adding 129 container CA certificates to JVM truststore
    Writing env.build/JAVA_HOME.override
    Writing env.build/JDK_HOME.override
  BellSoft Liberica JRE 11.0.11: Contributing to layer
    Downloading from https://github.com/bell-sw/Liberica/releases/download/11.0.11+9/bellsoft-jre11.0.11+9-linux-amd64.tar.gz
    Verifying checksum
    Expanding to /layers/paketo-buildpacks_bellsoft-liberica/jre
    Adding 129 container CA certificates to JVM truststore
    Writing env.launch/BPI_APPLICATION_PATH.default
    Writing env.launch/BPI_JVM_CACERTS.default
    Writing env.launch/BPI_JVM_CLASS_COUNT.default
    Writing env.launch/BPI_JVM_SECURITY_PROVIDERS.default
    Writing env.launch/JAVA_HOME.default
    Writing env.launch/MALLOC_ARENA_MAX.default
  Launch Helper: Contributing to layer
    Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/active-processor-count
    Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/java-opts
    Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/link-local-dns
    Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/memory-calculator
    Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/openssl-certificate-loader
    Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/security-providers-configurer
    Creating /layers/paketo-buildpacks_bellsoft-liberica/helper/exec.d/security-providers-classpath-9
  JVMKill Agent 1.16.0: Contributing to layer
    Downloading from https://github.com/cloudfoundry/jvmkill/releases/download/v1.16.0.RELEASE/jvmkill-1.16.0-RELEASE.so
    Verifying checksum
    Copying to /layers/paketo-buildpacks_bellsoft-liberica/jvmkill
    Writing env.launch/JAVA_TOOL_OPTIONS.append
    Writing env.launch/JAVA_TOOL_OPTIONS.delim
  Java Security Properties: Contributing to layer
    Writing env.launch/JAVA_SECURITY_PROPERTIES.default
    Writing env.launch/JAVA_TOOL_OPTIONS.append
    Writing env.launch/JAVA_TOOL_OPTIONS.delim
 
Paketo Maven Buildpack 5.1.0
  https://github.com/paketo-buildpacks/maven
  Build Configuration:
    $BP_MAVEN_BUILD_ARGUMENTS  -Dmaven.test.skip=true package  the arguments to pass to Maven
    $BP_MAVEN_BUILT_ARTIFACT   target/*.[jw]ar                 the built application artifact explicitly.  Supersedes $BP_MAVEN_BUILT_MODULE
    $BP_MAVEN_BUILT_MODULE                                     the module to find application artifact in
    Creating cache directory /home/cnb/.m2
  Compiled Application: Contributing to layer
    Executing mvnw --batch-mode -Dmaven.test.skip=true package
[INFO] Scanning for projects...
[INFO] Downloading from central: https://repo.maven.apache.org/maven2/org/springframework/boot/spring-boot-starter-parent/2.2.7.RELEASE/spring-boot-starter-parent-2.2.7.RELEASE.pom
[INFO] -----------------------< com.txconsole:helloapp >-----------------------
[INFO] Building helloapp 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO] Downloading from central: https://repo.maven.apache.org/maven2/org/springframework/boot/spring-boot-maven-plugin/2.2.7.RELEASE/spring-boot-maven-plugin-2.2.7.RELEASE.pom
 
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  02:50 min
[INFO] Finished at: 2021-05-12T16:22:04Z
[INFO] ------------------------------------------------------------------------
  Removing source code
 
Paketo Executable JAR Buildpack 5.0.0
  https://github.com/paketo-buildpacks/executable-jar
  Class Path: Contributing to layer
    Writing env/CLASSPATH.delim
    Writing env/CLASSPATH.prepend
  Process types:
    executable-jar: java org.springframework.boot.loader.JarLauncher (direct)
    task:           java org.springframework.boot.loader.JarLauncher (direct)
    web:            java org.springframework.boot.loader.JarLauncher (direct)
 
Paketo Spring Boot Buildpack 4.2.0
  https://github.com/paketo-buildpacks/spring-boot
  Launch Helper: Contributing to layer
    Creating /layers/paketo-buildpacks_spring-boot/helper/exec.d/spring-cloud-bindings
  Spring Cloud Bindings 1.7.1: Contributing to layer
    Downloading from https://repo.spring.io/release/org/springframework/cloud/spring-cloud-bindings/1.7.1/spring-cloud-bindings-1.7.1.jar
    Verifying checksum
    Copying to /layers/paketo-buildpacks_spring-boot/spring-cloud-bindings
  Web Application Type: Contributing to layer
    Servlet web application detected
    Writing env.launch/BPL_JVM_THREAD_COUNT.default
  Image labels:
    org.opencontainers.image.title
    org.opencontainers.image.version
    org.springframework.boot.spring-configuration-metadata.json
    org.springframework.boot.version
===> EXPORT
Adding layer 'paketo-buildpacks/ca-certificates:helper'
Adding layer 'paketo-buildpacks/bellsoft-liberica:helper'
Adding layer 'paketo-buildpacks/bellsoft-liberica:java-security-properties'
Adding layer 'paketo-buildpacks/bellsoft-liberica:jre'
Adding layer 'paketo-buildpacks/bellsoft-liberica:jvmkill'
Adding layer 'paketo-buildpacks/executable-jar:classpath'
Adding layer 'paketo-buildpacks/spring-boot:helper'
Adding layer 'paketo-buildpacks/spring-boot:spring-cloud-bindings'
Adding layer 'paketo-buildpacks/spring-boot:web-application-type'
Adding 1/1 app layer(s)
Adding layer 'launcher'
Adding layer 'config'
Adding layer 'process-types'
Adding label 'io.buildpacks.lifecycle.metadata'
Adding label 'io.buildpacks.build.metadata'
Adding label 'io.buildpacks.project.metadata'
Adding label 'org.opencontainers.image.title'
Adding label 'org.opencontainers.image.version'
Adding label 'org.springframework.boot.spring-configuration-metadata.json'
Adding label 'org.springframework.boot.version'
Setting default process type 'web'
*** Images (sha256:5cb7b0605f985ebb3261cd5f4f5249e02656f828530b92189822038de8f132fe):
      txconsole/helloapp
      index.docker.io/txconsole/helloapp:b1.20210512.161819
Adding cache layer 'paketo-buildpacks/bellsoft-liberica:jdk'
Adding cache layer 'paketo-buildpacks/maven:application'
Adding cache layer 'paketo-buildpacks/maven:cache'
===> COMPLETION
Build successful

Once the build is successful, then the resultant resource status can be verified in k8s namespace :

 
$ kubectl get pod,builds,image -n helloapp-project
NAME                                   READY   STATUS      RESTARTS   AGE
pod/helloapp-build-1-jtsdc-build-pod   0/1     Completed   0          4m55s
 
NAME                                    IMAGE                                                                                                        SUCCEEDED
build.kpack.io/helloapp-build-1-jtsdc   index.docker.io/txconsole/helloapp@sha256:5cb7b0605f985ebb3261cd5f4f5249e02656f828530b92189822038de8f132fe   True
 
NAME                      LATESTIMAGE                                                                                                  READY
image.kpack.io/helloapp   index.docker.io/txconsole/helloapp@sha256:5cb7b0605f985ebb3261cd5f4f5249e02656f828530b92189822038de8f132fe   True

Thus, the image helloapp:b1.20210512.161819 is built and pushed to the configured docker registry. The build details are configured in the build resource.

 
Spec:
  Builder:
    Image:     pvtregistry.txvlab.com/kpack/builder@sha256:f819bc21837c2faf9858934c810bfc3ee9739455a18aa835a578bbcc0bf0866e
  Cache Name:  helloapp-cache
  Resources:
  Service Account:  app-sa
  Source:
    Git:
      Revision:  76e91560cce2abe386af0d133d3ede96599277e2
      URL:       https://github.com/txconsole/helloapp.git
  Tags:
    txconsole/helloapp
    index.docker.io/txconsole/helloapp:b1.20210512.161819

The build job’s pod has moved to completed state after successful image build.

The image resource specify the latest image detail and status.

 
Spec:
  Builder:
    Kind:                      ClusterBuilder
    Name:                      default
  Cache Size:                  2G
  Failed Build History Limit:  10
  Image Tagging Strategy:      BuildNumber
  Service Account:             app-sa
  Source:
    Git:
      Revision:                 master
      URL:                      https://github.com/txconsole/helloapp.git
  Success Build History Limit:  10
  Tag:                          txconsole/helloapp
Status:
  Build Cache Name:  helloapp-cache
  Build Counter:     1
  Conditions:
    Last Transition Time:         2021-05-12T16:22:52Z
    Status:                       True
    Type:                         Ready
    Last Transition Time:         2021-05-12T16:22:52Z
    Status:                       True
    Type:                         BuilderReady
  Latest Build Image Generation:  1
  Latest Build Reason:            CONFIG
  Latest Build Ref:               helloapp-build-1-jtsdc
  Latest Image:                   index.docker.io/txconsole/helloapp@sha256:5cb7b0605f985ebb3261cd5f4f5249e02656f828530b92189822038de8f132fe
  Latest Stack:                   io.buildpacks.stacks.bionic
  Observed Generation:            1

Perform image rebuild

Time to perform some app source code change to auto-trigger kpack webhook and create another app image version with the new source code revision.

 
$ kubectl get pod,builds,image -n helloapp-project
NAME                                   READY   STATUS      RESTARTS   AGE
pod/helloapp-build-1-jtsdc-build-pod   0/1     Completed   0          23m
pod/helloapp-build-2-zcwd7-build-pod   0/1     Init:0/6    0          5s
 
NAME                                    IMAGE                                                                                                        SUCCEEDED
build.kpack.io/helloapp-build-1-jtsdc   index.docker.io/txconsole/helloapp@sha256:5cb7b0605f985ebb3261cd5f4f5249e02656f828530b92189822038de8f132fe   True
build.kpack.io/helloapp-build-2-zcwd7                                                                                                                Unknown
 
NAME                      LATESTIMAGE                                                                                                  READY
image.kpack.io/helloapp   index.docker.io/txconsole/helloapp@sha256:5cb7b0605f985ebb3261cd5f4f5249e02656f828530b92189822038de8f132fe   Unknown

The above app revision should auto-trigger another app image build. The build logs can be still verified with the logs utility.

 
===> PREPARE
Build reason(s): COMMIT
COMMIT:
	- 76e91560cce2abe386af0d133d3ede96599277e2
	+ 1c3b53849a0b8ebc274a1928a5225581e6b35cd6
Loading secret for "https://index.docker.io/v1/" from secret "regcreddoc" at location "/var/build-secrets/regcreddoc"
Loading secret for "https://pvtregistry.txvlab.com" from secret "regcredhbr" at location "/var/build-secrets/regcredhbr"
Cloning "https://github.com/txconsole/helloapp.git" @ "1c3b53849a0b8ebc274a1928a5225581e6b35cd6"...
Successfully cloned "https://github.com/txconsole/helloapp.git" @ "1c3b53849a0b8ebc274a1928a5225581e6b35cd6" in path "/workspace"
===> DETECT
7 of 18 buildpacks participating
paketo-buildpacks/ca-certificates   2.2.0
paketo-buildpacks/bellsoft-liberica 8.0.0
paketo-buildpacks/maven             5.1.0
paketo-buildpacks/executable-jar    5.0.0
paketo-buildpacks/apache-tomcat     5.3.0
paketo-buildpacks/dist-zip          4.0.0
paketo-buildpacks/spring-boot       4.2.0
===> ANALYZE
Restoring metadata for "paketo-buildpacks/ca-certificates:helper" from app image
Restoring metadata for "paketo-buildpacks/bellsoft-liberica:helper" from app image
Restoring metadata for "paketo-buildpacks/bellsoft-liberica:java-security-properties" from app image
Restoring metadata for "paketo-buildpacks/bellsoft-liberica:jre" from app image
Restoring metadata for "paketo-buildpacks/bellsoft-liberica:jvmkill" from app image
Restoring metadata for "paketo-buildpacks/bellsoft-liberica:jdk" from cache
Restoring metadata for "paketo-buildpacks/maven:application" from cache
Restoring metadata for "paketo-buildpacks/maven:cache" from cache
Restoring metadata for "paketo-buildpacks/spring-boot:helper" from app image
Restoring metadata for "paketo-buildpacks/spring-boot:spring-cloud-bindings" from app image
Restoring metadata for "paketo-buildpacks/spring-boot:web-application-type" from app image
===> RESTORE
Restoring data for "paketo-buildpacks/bellsoft-liberica:jdk" from cache
Restoring data for "paketo-buildpacks/maven:application" from cache
Restoring data for "paketo-buildpacks/maven:cache" from cache
===> BUILD
 
Paketo CA Certificates Buildpack 2.2.0
  https://github.com/paketo-buildpacks/ca-certificates
  Launch Helper: Reusing cached layer
 
Paketo BellSoft Liberica Buildpack 8.0.0
  https://github.com/paketo-buildpacks/bellsoft-liberica
  Build Configuration:
    $BP_JVM_VERSION              11              the Java version
  Launch Configuration:
    $BPL_JVM_HEAD_ROOM           0               the headroom in memory calculation
    $BPL_JVM_LOADED_CLASS_COUNT  35% of classes  the number of loaded classes in memory calculation
    $BPL_JVM_THREAD_COUNT        250             the number of threads in memory calculation
    $JAVA_TOOL_OPTIONS                           the JVM launch flags
  BellSoft Liberica JDK 11.0.11: Reusing cached layer
  BellSoft Liberica JRE 11.0.11: Reusing cached layer
  Launch Helper: Reusing cached layer
  JVMKill Agent 1.16.0: Reusing cached layer
  Java Security Properties: Reusing cached layer
 
Paketo Maven Buildpack 5.1.0
  https://github.com/paketo-buildpacks/maven
  Build Configuration:
    $BP_MAVEN_BUILD_ARGUMENTS  -Dmaven.test.skip=true package  the arguments to pass to Maven
    $BP_MAVEN_BUILT_ARTIFACT   target/*.[jw]ar                 the built application artifact explicitly.  Supersedes $BP_MAVEN_BUILT_MODULE
    $BP_MAVEN_BUILT_MODULE                                     the module to find application artifact in
    Creating cache directory /home/cnb/.m2
  Compiled Application: Contributing to layer
    Executing mvnw --batch-mode -Dmaven.test.skip=true package
[INFO] Scanning for projects...
[INFO]
[INFO] -----------------------< com.txconsole:helloapp >-----------------------
[INFO] Building helloapp 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ helloapp ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] Copying 1 resource
[INFO] Copying 5 resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:compile (default-compile) @ helloapp ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 3 source files to /workspace/target/classes
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:testResources (default-testResources) @ helloapp ---
[INFO] Not copying test resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.1:testCompile (default-testCompile) @ helloapp ---
[INFO] Not compiling test sources
[INFO]
[INFO] --- maven-surefire-plugin:2.22.2:test (default-test) @ helloapp ---
[INFO] Tests are skipped.
[INFO]
[INFO] --- maven-jar-plugin:3.1.2:jar (default-jar) @ helloapp ---
[INFO] Building jar: /workspace/target/helloapp-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:2.2.7.RELEASE:repackage (repackage) @ helloapp ---
[INFO] Replacing main artifact with repackaged archive
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time:  2.880 s
[INFO] Finished at: 2021-05-12T16:42:05Z
[INFO] ------------------------------------------------------------------------
  Removing source code
 
Paketo Executable JAR Buildpack 5.0.0
  https://github.com/paketo-buildpacks/executable-jar
  Class Path: Contributing to layer
    Writing env/CLASSPATH.delim
    Writing env/CLASSPATH.prepend
  Process types:
    executable-jar: java org.springframework.boot.loader.JarLauncher (direct)
    task:           java org.springframework.boot.loader.JarLauncher (direct)
    web:            java org.springframework.boot.loader.JarLauncher (direct)
 
Paketo Spring Boot Buildpack 4.2.0
  https://github.com/paketo-buildpacks/spring-boot
  Launch Helper: Reusing cached layer
  Spring Cloud Bindings 1.7.1: Reusing cached layer
  Web Application Type: Reusing cached layer
  Image labels:
    org.opencontainers.image.title
    org.opencontainers.image.version
    org.springframework.boot.spring-configuration-metadata.json
    org.springframework.boot.version
===> EXPORT
Reusing layers from image 'index.docker.io/txconsole/helloapp@sha256:5cb7b0605f985ebb3261cd5f4f5249e02656f828530b92189822038de8f132fe'
Reusing layer 'paketo-buildpacks/ca-certificates:helper'
Reusing layer 'paketo-buildpacks/bellsoft-liberica:helper'
Reusing layer 'paketo-buildpacks/bellsoft-liberica:java-security-properties'
Reusing layer 'paketo-buildpacks/bellsoft-liberica:jre'
Reusing layer 'paketo-buildpacks/bellsoft-liberica:jvmkill'
Reusing layer 'paketo-buildpacks/executable-jar:classpath'
Reusing layer 'paketo-buildpacks/spring-boot:helper'
Reusing layer 'paketo-buildpacks/spring-boot:spring-cloud-bindings'
Reusing layer 'paketo-buildpacks/spring-boot:web-application-type'
Reusing 1/1 app layer(s)
Reusing layer 'launcher'
Reusing layer 'config'
Reusing layer 'process-types'
Adding label 'io.buildpacks.lifecycle.metadata'
Adding label 'io.buildpacks.build.metadata'
Adding label 'io.buildpacks.project.metadata'
Adding label 'org.opencontainers.image.title'
Adding label 'org.opencontainers.image.version'
Adding label 'org.springframework.boot.spring-configuration-metadata.json'
Adding label 'org.springframework.boot.version'
Setting default process type 'web'
*** Images (sha256:1d9f6c0627cb98721a6ad7c12c67476d55b3fb2fc12c70a478f318c8e2e98fa8):
      txconsole/helloapp
      index.docker.io/txconsole/helloapp:b2.20210512.164127
Reusing cache layer 'paketo-buildpacks/bellsoft-liberica:jdk'
Adding cache layer 'paketo-buildpacks/maven:application'
Reusing cache layer 'paketo-buildpacks/maven:cache'
===> COMPLETION
Build successful

Thus, the image resource is updated with the newly created and pushed image helloapp:b2.20200717.143231. We can observe another entry of build resource showing the specs as configured and used in the 2nd build. It also shows the status “SUCCEEDED” as “true” which proves that all the image build lifecycle stages were performed successfully.

 
$ kubectl get pod,builds,image -n helloapp-project
NAME                                   READY   STATUS      RESTARTS   AGE
pod/helloapp-build-1-jtsdc-build-pod   0/1     Completed   0          24m
pod/helloapp-build-2-zcwd7-build-pod   0/1     Completed   0          97s
 
NAME                                    IMAGE                                                                                                        SUCCEEDED
build.kpack.io/helloapp-build-1-jtsdc   index.docker.io/txconsole/helloapp@sha256:5cb7b0605f985ebb3261cd5f4f5249e02656f828530b92189822038de8f132fe   True
build.kpack.io/helloapp-build-2-zcwd7   index.docker.io/txconsole/helloapp@sha256:1d9f6c0627cb98721a6ad7c12c67476d55b3fb2fc12c70a478f318c8e2e98fa8   True
 
NAME                      LATESTIMAGE                                                                                                  READY
image.kpack.io/helloapp   index.docker.io/txconsole/helloapp@sha256:1d9f6c0627cb98721a6ad7c12c67476d55b3fb2fc12c70a478f318c8e2e98fa8   True

docker-images.jpg

Conclusion

We performed the poc on installing kpack and using it to perform app image build/rebuild which is ready to be consumed for microservice deployment.