We already saw how we can build and push our docker images using Jenkins in this post. Now we want to deploy this image to our local Kubernetes cluster so we have a running application. Here we go!
Setup Jenkins
If you want to follow along please take the steps in my post on docker on jenkins. Then checkout the following branch from github and install these values using helm:
helm upgrade jenkins stable/jenkins -f helm/jenkins-values.yaml --namespace sybrenbolandit --version 0.22.0
This upgrade gives Jenkins a bit more memory to use and installs the workspace cleanup plugin that we will use in our build.
One more thing we need is a Jenkins role on our Kubernetes cluster that authorizes Jenkins to do deployments. It is defined in the following way:
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
name: jenkins-role
subjects:
- kind: ServiceAccount
name: default
namespace: sybrenbolandit
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
And we can create this role by stating:
kubectl create -f jenkins-role.yaml
Kubernetes deploy
To get our app running on kubernetes we need a deployment definition. Check out this branch of our test application and check deployment/deployment.yaml:
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: java-spring-api
spec:
template:
spec:
containers:
- name: spring-api
image: sybrenbolandit/java-spring-api
imagePullPolicy: Always
ports:
- containerPort: 8080
resources:
requests:
memory: "256Mi"
cpu: "200m"
limits:
memory: "512Mi"
cpu: "200m"
Important things to note are the docker settings like the image and the port. Moreover we set requested and limit on the resources of the Kubernetes cluster. Applying this to our cluster creates a deployment object, a pod and a replica set. If you are new to these concepts please read the Kubernetes documentation.
To make our service available outside the cluster we need to define a Kubernetes service. In our application project we define this as follows:
apiVersion: v1
kind: Service
metadata:
name: java-spring-api
spec:
type: NodePort
ports:
- nodePort: 31311
port: 8080
protocol: TCP
targetPort: 8080
selector:
app: java-spring-api
Note that the nodePort is the port on which our application becomes available.
We could deploy these definitions ourselves using kubectl but we are going to automate this using Jenkins.
Kustomize
To get different configuration with different deployments (say to different environments) we use Kustomize. We define a base kustomization.yaml
namespace: sybrenbolandit
commonLabels:
app: java-spring-api
resources:
- deployment.yaml
- service.yaml
Where we see our Kubernetes definition files from earlier included. Now we define overlays of this base file for environment specific configuration. In our test project we have only one environment: test.
namespace: sybrenbolandit
commonLabels:
env: test
bases:
- ../..
configMapGenerator:
- files:
- application.properties
name: application-config
And we include the application.properties specific for the test environment included in the deployment/overlays/test directory.
The deploy stage
Now change which branch Jenkins builds of our test project to */blog/jenkins-deploy-to-kubernetes in the configuration of the build:

On this branch we updated the Jenkinsfile with a new stage Deploy:
stage ("Deploy") {
container ('kubectl') {
dir ("deployment") {
sh """
kustomize edit set imagetag $repository:$commitId;
kustomize build overlays/test | kubectl apply --record -f -
"""
}
}
}
We see that we use Kustomize to set our newly build image, get the configuration of the test environment and use kubectl to deploy this in our cluster. Note that we run this in the kubectl container which is defined as follows containing kubectl and Kustomize:
containerTemplate(name: 'kubectl', image: 'traherom/kustomize-docker:1.0.5', ttyEnabled: true, command: 'cat')
Hit build now! And wait for the build to complete…

Now let’s see our running app here!

Hopefully you can now Jenkins deploy to Kubernetes. Happy deploying!