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/jenins-deploy-to-kubernetes in the configuration of the build:

jenkins pipeline configuration

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…

jenkins pipeline overview

Now let’s see our running app here!

browser test output

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