Files
kubernetes/examples/javaweb-tomcat-sidecar

WARNING WARNING WARNING WARNING WARNING

PLEASE NOTE: This document applies to the HEAD of the source tree

If you are using a released version of Kubernetes, you should refer to the docs that go with that version.

The latest 1.0.x release of this document can be found [here](http://releases.k8s.io/release-1.0/examples/javaweb-tomcat-sidecar/README.md).

Documentation for other releases can be found at releases.k8s.io.

Java Web Application with Tomcat and Sidercar Container

The following document describes the deployment of a Java Web application using Tomcat. Instead of packaging war file inside the Tomcat image or mount the war as a volume, we use a sidecar container as war file provider.

Prerequisites

https://github.com/kubernetes/kubernetes/blob/master/docs/user-guide/prereqs.md

Overview

This sidecar mode brings a new workflow for Java users:

As you can see, user can create a sample:v2 container as sidecar to "provide" war file to Tomcat by copying it to the shared emptyDir volume. And Pod will make sure the two containers compose a "atomic" scheduling unit, which is perfect for this case. Thus, your application version management will be totally seperated from web server management.

For example, if you gonna change the configurations of your Tomcat:

docker exec -it <tomcat_container_id> /bin/bash
# do your change, and then commit it to a new image
docker commit <tomcat_container_id> mytomcat:7.0-dev

Done! The new Tomcat image will not mess up with your sample.war file.

You can also upgrade your app to new version seperately, without creating a new "Tomcat plus app" image (and this image will become huge as unionfs will keep all the old war files in its layers).

Why don't put my sample.war in a host dir and mount it to tomcat container?

You have to manage the volumes in this case, for example, when you restart or scale the Pod on another Node, your contents is not ready on that host.

Generally, we have to set up a distributed file system (NFS at least) volume to solve this (if we do not have GCE PD volume). But seriously, it's a overkill.

How To

In Kubernetes a Pod is the smallest deployable unit that can be created, scheduled, and managed. Its a collocated group of containers that share an IP and storage volume.

Here is the config javaweb.yaml for Java Web pod:

NOTE: you should define war contaienr first as it is the "provider".

apiVersion: v1
kind: Pod
metadata:
  name: javaweb
spec:
  containers:
  - image: resouer/sample:v1
    name: war
    volumeMounts:
    - mountPath: /app
      name: app-volume
  - image: resouer/mytomcat:7.0
    name: tomcat
    command: ["sh","-c","/root/apache-tomcat-7.0.42-v2/bin/start.sh"]
    volumeMounts:
    - mountPath: /root/apache-tomcat-7.0.42-v2/webapps
      name: app-volume
    ports:
    - containerPort: 8080
      hostPort: 8001
  volumes:
  - name: app-volume

The only magic here is the resouer/sample:v1 image:

FROM busybox:latest
ADD sample.war sample.war
CMD "sh" "mv.sh"

And the content inf mv.sh is:

cp /sample.war /app
tail -f /etc/hosts

Explaination

  1. 'war' container only contains the war file of your app
  2. 'war' container's CMD try to copy sample.war to the emptyDir volume path
  3. The last line of tailf -f is just used to hold the container, as RC does not support one-off task
  4. 'tomcat' container will load the sample.war from volume path

What's more, if you don't want to add a build in mv.sh script in the war container, you can use Pod lifecycle handler to do the copy work, here's a example javaweb-2.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: javaweb-2
spec:
  containers:
  - image: resouer/sample:v2
    name: war
    lifecycle:
      postStart:
        exec:
          command:
            - "cp"
            - "/sample.war"
            - "/app"
    volumeMounts:
    - mountPath: /app
      name: app-volume
  - image: resouer/mytomcat:7.0
    name: tomcat
    command: ["sh","-c","/root/apache-tomcat-7.0.42-v2/bin/start.sh"]
    volumeMounts:
    - mountPath: /root/apache-tomcat-7.0.42-v2/webapps
      name: app-volume
    ports:
    - containerPort: 8080
      hostPort: 8001 
  volumes:
  - name: app-volume

And the resouer/sample:v2 Dockerfile is quite simple:

FROM busybox:latest
ADD sample.war sample.war
CMD "tail" "-f" "/etc/hosts"

Explaination

  1. 'war' container only contains the war file of your app
  2. 'war' container's CMD use tail to hold the container, nothing else
  3. The postStart lifecycle handler will do cp after the war container is started
  4. Again 'tomcat' container will load the sample.war from volume path

Done! Now your war container contains nothing except sample.war, clean enough.

Test It Out

Create the Java web pod:

kubectl create -f examples/javaweb-tomcat-sidecar/javaweb-2.yaml

Check status of the pod:

kubectl get -w po
NAME        READY     STATUS    RESTARTS   AGE
javaweb-2   2/2       Running   0         7s

Wait for the status to 2/2 and Running. Then you can visit "Hello, World" on http://localhost:8001/sample/index.html

You can also test javaweb.yaml in the same way.

Delete Resources

All resources created in this application can be deleted:

kubectl delete -f examples/javaweb-tomcat-sidecar/javaweb-2.yaml

Analytics