So with that in mind lets go and deploy kpack on GKE cluster and build our first image...
Steps
1. Install v0.0.3 of kpack into your Kube cluster
$ kubectl apply -f <(curl -L https://github.com/pivotal/kpack/releases/download/v0.0.3/release.yaml)
...
namespace/kpack created
customresourcedefinition.apiextensions.k8s.io/builds.build.pivotal.io created
customresourcedefinition.apiextensions.k8s.io/builders.build.pivotal.io created
clusterrole.rbac.authorization.k8s.io/kpack-admin created
clusterrolebinding.rbac.authorization.k8s.io/kpack-controller-admin created
deployment.apps/kpack-controller created
customresourcedefinition.apiextensions.k8s.io/images.build.pivotal.io created
serviceaccount/controller created
customresourcedefinition.apiextensions.k8s.io/sourceresolvers.build.pivotal.io created
2. Lets just verify what Custom resources definition (CRD's) have been installed
$ kubectl api-resources --api-group build.pivotal.io
NAME SHORTNAMES APIGROUP NAMESPACED KIND
builders cnbbuilder,cnbbuilders,bldr build.pivotal.io true Builder
builds cnbbuild,cnbbuilds,bld build.pivotal.io true Build
images cnbimage,cnbimages build.pivotal.io true Image
sourceresolvers build.pivotal.io true SourceResolver
3. Create a builder resource as follows
builder-resource.yaml
apiVersion: build.pivotal.io/v1alpha1
kind: Builder
metadata:
name: sample-builder
spec:
image: cloudfoundry/cnb:bionic
updatePolicy: polling
$ kubectl create -f builder-resource.yaml
builder.build.pivotal.io/sample-builder created
$ kubectl get builds,images,builders,sourceresolvers
NAME AGE
builder.build.pivotal.io/sample-builder 42s
4. Create a secret for push access to the desired docker registry
docker-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: basic-docker-user-pass
annotations:
build.pivotal.io/docker: index.docker.io
type: kubernetes.io/basic-auth
stringData:
username: papicella
password:
$ kubectl create -f docker-secret.yaml
secret/basic-docker-user-pass created
5. Create a secret for pull access from the desired git repository. The example below is for a github repository
git-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: basic-git-user-pass
annotations:
build.pivotal.io/git: https://github.com
type: kubernetes.io/basic-auth
stringData:
username: papicella
password:
$ kubectl create -f git-secret.yaml
secret/basic-git-user-pass created
6. Create a service account that uses the docker registry secret and the git repository secret.
service-account.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: service-account
secrets:
- name: basic-docker-user-pass
- name: basic-git-user-pass
$ kubectl create -f service-account.yaml
serviceaccount/service-account created
7. Install logs utility. In order to view the build logs for each image as it's created right now you have to use a utility that you build from the kpack github repo source fils itself. Follow the steps below to get it built
$ export GOPATH=`pwd`
$ git clone https://github.com/pivotal/kpack $GOPATH/src/github.com/pivotal/kpack
$ cd $GOPATH/src/github.com/pivotal/kpack
$ dep ensure -v
$ go build ./cmd/logs
You will have "logs" executable created in current directory which we will use it shortly
8. Create an image as follows. The GitHub repo I have here is public so will work no problem at all
pbs-demo-sample-image.yaml
apiVersion: build.pivotal.io/v1alpha1
kind: Image
metadata:
name: pbs-demo-image
spec:
tag: pasapples/pbs-demo-image
serviceAccount: service-account
builderRef: sample-builder
cacheSize: "1.5Gi" # Optional, if not set then the caching feature is disabled
failedBuildHistoryLimit: 5 # Optional, if not present defaults to 10
successBuildHistoryLimit: 5 # Optional, if not present defaults to 10
source:
git:
url: https://github.com/papicella/pbs-demo
revision: master
build: # Optional
env:
- name: BP_JAVA_VERSION
value: 11.*
resources:
limits:
cpu: 100m
memory: 1G
requests:
cpu: 50m
memory: 512M
$ kubectl create -f pbs-demo-sample-image.yaml
image.build.pivotal.io/sample-image created
9. Now at this point we can view the created image and current Cloud native Buildpack builds being run using two commands as follows.
$ kubectl get images
NAME LATESTIMAGE READY
pbs-demo-image Unknown
$ kubectl get cnbbuilds
NAME IMAGE SUCCEEDED
pbs-demo-image-build-1-pvh6k Unknown
Note: Unknown is normal as it has not yet completed
10. Now using our created "logs" utility lets view the current build logs
$ ./logs -image pbs-demo-image
{"level":"info","ts":1568175056.446671,"logger":"fallback-logger","caller":"creds-init/main.go:40","msg":"Credentials initialized.","commit":"002a41a"}
source-init:main.go:277: Successfully cloned "https://github.com/papicella/pbs-demo" @ "cee67e26d55b6d2735afd7fa3e0b81e251e0d5ce" in path "/workspace"
2019/09/11 04:11:23 Unable to read "/root/.docker/config.json": open /root/.docker/config.json: no such file or directory
======== Results ========
skip: org.cloudfoundry.archiveexpanding@1.0.0-RC03
pass: org.cloudfoundry.openjdk@1.0.0-RC03
pass: org.cloudfoundry.buildsystem@1.0.0-RC03
pass: org.cloudfoundry.jvmapplication@1.0.0-RC03
pass: org.cloudfoundry.tomcat@1.0.0-RC03
pass: org.cloudfoundry.springboot@1.0.0-RC03
pass: org.cloudfoundry.distzip@1.0.0-RC03
skip: org.cloudfoundry.procfile@1.0.0-RC03
skip: org.cloudfoundry.azureapplicationinsights@1.0.0-RC03
skip: org.cloudfoundry.debug@1.0.0-RC03
skip: org.cloudfoundry.googlestackdriver@1.0.0-RC03
skip: org.cloudfoundry.jdbc@1.0.0-RC03
skip: org.cloudfoundry.jmx@1.0.0-RC03
pass: org.cloudfoundry.springautoreconfiguration@1.0.0-RC03
Resolving plan... (try #1)
Success! (7)
Cache '/cache': metadata not found, nothing to restore
Analyzing image 'index.docker.io/pasapples/pbs-demo-image@sha256:40fe8aa932037faad697c3934667241eef620aac1d09fc7bb5ec5a75d5921e3e'
Writing metadata for uncached layer 'org.cloudfoundry.openjdk:openjdk-jre'
......
11. Now this will take some time to do our first build given it will hagve to download all the maven dependancies but you may be wondering how do we determine how many builds have been run so we can actually view the logs of any builds across our image we just created. To do that run a command as follows
$ kubectl get pods --show-labels | grep pbs-demo-image
pbs-demo-image-build-1-pvh6k-build-pod 0/1 Init:6/9 0 6m29s image.build.pivotal.io/buildNumber=1,image.build.pivotal.io/image=pbs-demo-image
12. So from the output above you can clearly see we just have the one single build so to view logs of just a particular build we use it's ID as shown above as follows
$ ./logs -image pbs-demo-image -build {ID}
...
13. Now if we wait at least 5 minutes as the first build will always take time just to the dependancies required to be downloaded it will eventually complete and show it's complete using the following commands
$ kubectl get images
NAME LATESTIMAGE READY
pbs-demo-image index.docker.io/pasapples/pbs-demo-image@sha256:a2d4082004d686bb2c76222a631b8a9b3866bef54c1fae03261986a528b556fe True
$ kubectl get cnbbuilds
NAME IMAGE SUCCEEDED
pbs-demo-image-build-1-pvh6k index.docker.io/pasapples/pbs-demo-image@sha256:a2d4082004d686bb2c76222a631b8a9b3866bef54c1fae03261986a528b556fe True
14. Now let's actually make a code change to our source code and issue a git commit. In this example below I am using IntelliJ IDEA for my code change/commit
15. Now let's see if a new build is kicked off it should be. Run the following command
$ kubectl get cnbbuilds
NAME IMAGE SUCCEEDED
pbs-demo-image-build-1-pvh6k index.docker.io/pasapples/pbs-demo-image@sha256:a2d4082004d686bb2c76222a631b8a9b3866bef54c1fae03261986a528b556fe True
pbs-demo-image-build-2-stl8w Unknown
16. Now lets see that in fact this new build is build ID 2 using a command as follows
$ kubectl get pods --show-labels | grep pbs-demo-image
pbs-demo-image-build-1-pvh6k-build-pod 0/1 Completed 0 21m image.build.pivotal.io/buildNumber=1,image.build.pivotal.io/image=pbs-demo-image
pbs-demo-image-build-2-stl8w-build-pod 0/1 Init:6/9 0 2m15s image.build.pivotal.io/buildNumber=2,image.build.pivotal.io/image=pbs-demo-image
17. Lets view the logs for BUILD 2 as follows
$ ./logs -image pbs-demo-image -build 2
{"level":"info","ts":1568176191.088838,"logger":"fallback-logger","caller":"creds-init/main.go:40","msg":"Credentials initialized.","commit":"002a41a"}
source-init:main.go:277: Successfully cloned "https://github.com/papicella/pbs-demo" @ "e2830bbcfb32bfdd72bf5d4b17428c405f46f3c1" in path "/workspace"
2019/09/11 04:29:55 Unable to read "/root/.docker/config.json": open /root/.docker/config.json: no such file or directory
======== Results ========
skip: org.cloudfoundry.archiveexpanding@1.0.0-RC03
pass: org.cloudfoundry.openjdk@1.0.0-RC03
pass: org.cloudfoundry.buildsystem@1.0.0-RC03
pass: org.cloudfoundry.jvmapplication@1.0.0-RC03
pass: org.cloudfoundry.tomcat@1.0.0-RC03
pass: org.cloudfoundry.springboot@1.0.0-RC03
pass: org.cloudfoundry.distzip@1.0.0-RC03
skip: org.cloudfoundry.procfile@1.0.0-RC03
skip: org.cloudfoundry.azureapplicationinsights@1.0.0-RC03
skip: org.cloudfoundry.debug@1.0.0-RC03
skip: org.cloudfoundry.googlestackdriver@1.0.0-RC03
skip: org.cloudfoundry.jdbc@1.0.0-RC03
skip: org.cloudfoundry.jmx@1.0.0-RC03
pass: org.cloudfoundry.springautoreconfiguration@1.0.0-RC03
Resolving plan... (try #1)
Success! (7)
Restoring cached layer 'org.cloudfoundry.openjdk:openjdk-jdk'
Restoring cached layer 'org.cloudfoundry.openjdk:90c33cf3f2ed0bd773f648815de7347e69cfbb3416ef3bf41616ab1c4aa0f5a8'
Restoring cached layer 'org.cloudfoundry.buildsystem:build-system-cache'
Restoring cached layer 'org.cloudfoundry.jvmapplication:executable-jar'
Restoring cached layer 'org.cloudfoundry.springboot:spring-boot'
Analyzing image 'index.docker.io/pasapples/pbs-demo-image@sha256:a2d4082004d686bb2c76222a631b8a9b3866bef54c1fae03261986a528b556fe'
Using cached layer 'org.cloudfoundry.openjdk:90c33cf3f2ed0bd773f648815de7347e69cfbb3416ef3bf41616ab1c4aa0f5a8'
Using cached layer 'org.cloudfoundry.openjdk:openjdk-jdk'
Writing metadata for uncached layer 'org.cloudfoundry.openjdk:openjdk-jre'
Using cached layer 'org.cloudfoundry.buildsystem:build-system-cache'
Using cached launch layer 'org.cloudfoundry.jvmapplication:executable-jar'
Rewriting metadata for layer 'org.cloudfoundry.jvmapplication:executable-jar'
Using cached launch layer 'org.cloudfoundry.springboot:spring-boot'
Rewriting metadata for layer 'org.cloudfoundry.springboot:spring-boot'
Writing metadata for uncached layer 'org.cloudfoundry.springautoreconfiguration:auto-reconfiguration'
Cloud Foundry OpenJDK Buildpack 1.0.0-RC03
OpenJDK JDK 11.0.4: Reusing cached layer
OpenJDK JRE 11.0.4: Reusing cached layer
Cloud Foundry Build System Buildpack 1.0.0-RC03
Using wrapper
Linking Cache to /home/cnb/.m2
Compiled Application: Contributing to layer
Executing /workspace/mvnw -Dmaven.test.skip=true package
[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------< com.example:pbs-demo >------------------------
[INFO] Building pbs-demo 0.0.1-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.1.0:resources (default-resources) @ pbs-demo ---
...
18. Now this build won't take as long as the first build as this time we don't have to pull down the maven dependancies plus avoid creating layers that have not changes in the first OCI complaint image which is something cloud native buildpacks does for us nicely. Once complete you now have two builds as follows
$ kubectl get cnbbuilds
NAME IMAGE SUCCEEDED
pbs-demo-image-build-1-pvh6k index.docker.io/pasapples/pbs-demo-image@sha256:a2d4082004d686bb2c76222a631b8a9b3866bef54c1fae03261986a528b556fe True
pbs-demo-image-build-2-stl8w index.docker.io/pasapples/pbs-demo-image@sha256:a22c64754cb7addc3f7e9a9335b094adf466b5f8035227691e81403d0c9c177f True
19. Now let's run this locally as follows given I have docker desktop running. First we pull down the created image which in this case is the LATEST build build 2 here
$ docker pull pasapples/pbs-demo-image
Using default tag: latest
latest: Pulling from pasapples/pbs-demo-image
35c102085707: Already exists
251f5509d51d: Already exists
8e829fe70a46: Already exists
6001e1789921: Already exists
76a30c9e6d47: Pull complete
8538f1fe6188: Pull complete
2a899c7e684d: Pull complete
0ea0c38329cb: Pull complete
bb281735f842: Pull complete
664d87aab7ff: Pull complete
f4b03070a779: Pull complete
682af613b7ca: Pull complete
b893e5904080: Pull complete
Digest: sha256:a22c64754cb7addc3f7e9a9335b094adf466b5f8035227691e81403d0c9c177f
Status: Downloaded newer image for pasapples/pbs-demo-image:latest
20. Now let's run it
$ docker run -p 8080:8080 pasapples/pbs-demo-image
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.6.RELEASE)
2019-09-11 04:40:41.747 WARN 1 --- [ main] pertySourceApplicationContextInitializer : Skipping 'cloud' property source addition because not in a cloud
2019-09-11 04:40:41.751 WARN 1 --- [ main] nfigurationApplicationContextInitializer : Skipping reconfiguration because not in a cloud
2019-09-11 04:40:41.760 INFO 1 --- [ main] com.example.pbsdemo.PbsDemoApplication : Starting PbsDemoApplication on 5975633400c4 with PID 1 (/workspace/BOOT-INF/classes started by cnb in /workspace)
...
2019-09-11 04:40:50.255 INFO 1 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat started on port(s): 8080 (http) with context path ''
2019-09-11 04:40:50.259 INFO 1 --- [ main] com.example.pbsdemo.PbsDemoApplication : Started PbsDemoApplication in 8.93 seconds (JVM running for 9.509)
Hibernate: insert into customer (id, name, status) values (null, ?, ?)
2019-09-11 04:40:50.323 INFO 1 --- [ main] com.example.pbsdemo.LoadDatabase : Preloading Customer(id=1, name=pas, status=active)
Hibernate: insert into customer (id, name, status) values (null, ?, ?)
2019-09-11 04:40:50.326 INFO 1 --- [ main] com.example.pbsdemo.LoadDatabase : Preloading Customer(id=2, name=lucia, status=active)
Hibernate: insert into customer (id, name, status) values (null, ?, ?)
2019-09-11 04:40:50.329 INFO 1 --- [ main] com.example.pbsdemo.LoadDatabase : Preloading Customer(id=3, name=lucas, status=inactive)
Hibernate: insert into customer (id, name, status) values (null, ?, ?)
2019-09-11 04:40:50.331 INFO 1 --- [ main] com.example.pbsdemo.LoadDatabase : Preloading Customer(id=4, name=siena, status=inactive)
21. Invoke it through a browser as follows
http://localhost:8080/swagger-ui.html
22. Finally let's actually run this application on our k8s cluster itself. So start by creating a basic YAML file for deployment as follows
run-pbs-image-k8s-yaml.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: pbs-demo-image
spec:
replicas: 2
template:
metadata:
labels:
app: pbs-demo-image
spec:
containers:
- name: pbs-demo-image
image: pasapples/pbs-demo-image
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: pbs-demo-image-service
labels:
name: pbs-demo-image-service
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
selector:
app: pbs-demo-image
type: LoadBalancer
23. Apply your config
$ kubectl create -f run-pbs-image-k8s-yaml.yaml
deployment.extensions/pbs-demo-image created
service/pbs-demo-image-service created
24. Check we have running pods and LB service created
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/pbs-demo-image-build-1-pvh6k-build-pod 0/1 Completed 0 39m
pod/pbs-demo-image-build-2-stl8w-build-pod 0/1 Completed 0 19m
pod/pbs-demo-image-f5c9d989-l2hg5 1/1 Running 0 48s
pod/pbs-demo-image-f5c9d989-pfxzs 1/1 Running 0 48s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.101.0.1
service/pbs-demo-image-service LoadBalancer 10.101.15.197
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/pbs-demo-image 2/2 2 2 49s
NAME DESIRED CURRENT READY AGE
replicaset.apps/pbs-demo-image-f5c9d989 2 2 2 50s
More Information
Introducing kpack, a Kubernetes Native Container Build Service
https://content.pivotal.io/blog/introducing-kpack-a-kubernetes-native-container-build-service
Cloud Native Buildpacks
https://buildpacks.io/
No comments:
Post a Comment