The exec healthz server is a sidecar container meant to serve as a liveness-exec-over-http bridge. It isolates pods from the idiosyncracies of container runtime exec implemetations.
## Examples:
### Run the healthz server directly on localhost:
```shell
$ make server
$ ./exechealthz -cmd"ls /tmp/test"
$ curl http://localhost:8080/healthz
Healthz probe error: Result of last exec: ls: cannot access /tmp/test: No such file or directory
, at 2015-07-08 17:59:45.698036238 -0700 PDT, error exit status 2
$ touch /tmp/test
$ curl http://localhost:8080/healthz
ok
```
### Run the healthz server in a docker container:
The [docker daemon](https://docs.docker.com/userguide/) needs to be running on your host.
```shell
$ make container PREFIX=mycontainer/test
$ docker run -itP-p 8080:8080 mycontainer/test:0.0 -cmd"ls /tmp/test"
$ curl http://localhost:8080/healthz
Healthz probe error: Result of last exec: ls: cannot access /tmp/test: No such file or directory
, at 2015-07-08 18:00:57.698103532 -0700 PDT, error exit status 2
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8e86f8accfa6 mycontainer/test:0.0 "/exechealthz -cm" 27 seconds ago Up 26 seconds 0.0.0.0:8080->8080/tcp loving_albattani
$ docker exec-it 8e86f8accfa6 touch /tmp/test
$ curl http://localhost:8080/healthz
ok
```
### Run the healthz server in a kubernetes pod:
You need a running [kubernetes cluster](../../docs/getting-started-guides/README.md).
SSH into the node (note that the recommended way to access a server in a container is through a [service](../../docs/services.md), the example that follows is just to illustrate how the kubelet performs an http liveness probe):
```shell
node$ kubectl get pods simple -o json | grep podIP
"podIP": "10.1.0.2",
node$ curl http://10.1.0.2:8080/healthz
ok
```
### Run the healthz server as a sidecar container for liveness probes of another container:
Create a pod.json with 2 containers, one of which is the healthz probe and the other, the container being health checked. The
pod.json example file in this directory does exactly that. If you create the pod the same way you created the pod in the previous
example, the kubelet on the node will periodically perform a health check similar to what you did manually and restart the container
when it fails. Explore [liveness probes](../../examples/liveness/README.md).
## Limitations:
* Doesn't handle sigterm, which means docker stop on this container can take longer than it needs to.
* Doesn't sanity check the probe command. You should set the -period and -latency parameters of exechealthz appropriately.
port=flag.Int("port",8080,"Port number to serve /healthz.")
cmd=flag.String("cmd","echo healthz","Command to run in response to a GET on /healthz. If the given command exits with 0, /healthz will respond with a 200.")
period=flag.Duration("period",2*time.Second,"Period to run the given cmd in an async worker.")
maxLatency=flag.Duration("latency",30*time.Second,"If the async worker hasn't updated the probe command output in this long, return a 503.")
// prober is the async worker running the cmd, the output of which is used to service /healthz.
prober*execWorker
)
// execResult holds the result of the latest exec from the execWorker.
typeexecResultstruct{
output[]byte
errerror
tstime.Time
}
func(rexecResult)String()string{
errMsg:="None"
ifr.err!=nil{
errMsg=fmt.Sprintf("%v",r.err)
}
returnfmt.Sprintf("Result of last exec: %v, at %v, error %v",string(r.output),r.ts,errMsg)
}
// execWorker provides an async interface to exec.
typeexecWorkerstruct{
resultexecResult
mutexsync.Mutex
periodtime.Duration
probeCmdstring
stopChchanstruct{}
}
// getResults returns the results of the latest execWorker run.
// The caller should treat returned results as read-only.
func(h*execWorker)getResults()execResult{
h.mutex.Lock()
deferh.mutex.Unlock()
returnh.result
}
// start attemtps to run the probeCmd every `period` seconds.
// Meant to be called as a goroutine.
func(h*execWorker)start(){
ticker:=time.NewTicker(h.period)
deferticker.Stop()
for{
select{
// If the command takes > period, the command runs continuously.