Demo a sidecar mode within pod for java users

This commit is contained in:
harry 2015-09-15 17:44:00 +08:00 committed by Harry Zhang
parent 7e72f549df
commit 20f6894667
4 changed files with 267 additions and 0 deletions

View File

@ -0,0 +1,216 @@
<!-- BEGIN MUNGE: UNVERSIONED_WARNING -->
<!-- BEGIN STRIP_FOR_RELEASE -->
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<img src="http://kubernetes.io/img/warning.png" alt="WARNING"
width="25" height="25">
<h2>PLEASE NOTE: This document applies to the HEAD of the source tree</h2>
If you are using a released version of Kubernetes, you should
refer to the docs that go with that version.
<strong>
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).
</strong>
--
<!-- END STRIP_FOR_RELEASE -->
<!-- END MUNGE: UNVERSIONED_WARNING -->
## 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 <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_](../../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".
<!-- BEGIN MUNGE: javaweb.yaml -->
```
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
```
<!-- END MUNGE: EXAMPLE -->
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):
<!-- BEGIN MUNGE: 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
```
<!-- END MUNGE: EXAMPLE -->
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
```
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/examples/javaweb-tomcat-sidecar/README.md?pixel)]()
<!-- END MUNGE: GENERATED_ANALYTICS -->

View File

@ -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

View File

@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB