diff --git a/javaweb-tomcat-sidecar/README.md b/javaweb-tomcat-sidecar/README.md new file mode 100644 index 00000000..bb234766 --- /dev/null +++ b/javaweb-tomcat-sidecar/README.md @@ -0,0 +1,216 @@ + + + + +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](http://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: + +![](workflow.png?raw=true "Workflow") + +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 /bin/bash +# do your change, and then commit it to a new image +docker commit 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_](../../docs/user-guide/pods.md) 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](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: + +```sh +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](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: + +```sh +kubectl create -f examples/javaweb-tomcat-sidecar/javaweb-2.yaml +``` + +Check status of the pod: + +```sh +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: + +```sh +kubectl delete -f examples/javaweb-tomcat-sidecar/javaweb-2.yaml +``` + + + + + +[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/examples/javaweb-tomcat-sidecar/README.md?pixel)]() + diff --git a/javaweb-tomcat-sidecar/javaweb-2.yaml b/javaweb-tomcat-sidecar/javaweb-2.yaml new file mode 100644 index 00000000..74908189 --- /dev/null +++ b/javaweb-tomcat-sidecar/javaweb-2.yaml @@ -0,0 +1,29 @@ +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 \ No newline at end of file diff --git a/javaweb-tomcat-sidecar/javaweb.yaml b/javaweb-tomcat-sidecar/javaweb.yaml new file mode 100644 index 00000000..c29bcd7c --- /dev/null +++ b/javaweb-tomcat-sidecar/javaweb.yaml @@ -0,0 +1,22 @@ +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 \ No newline at end of file diff --git a/javaweb-tomcat-sidecar/workflow.png b/javaweb-tomcat-sidecar/workflow.png new file mode 100644 index 00000000..7be56d08 Binary files /dev/null and b/javaweb-tomcat-sidecar/workflow.png differ