Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e64ec0d8cc | |||
| 65f9c5a529 | |||
| 23e85fe4a5 | |||
| 037dbeb678 | |||
| c225d7fd36 | |||
| 65b3621581 | |||
| a2f8953bc4 | |||
| 69304ab37e | |||
| a4d6cf3769 |
+4
-18
@@ -1,6 +1,6 @@
|
||||
language: go
|
||||
go:
|
||||
- 1.7.3
|
||||
- 1.8.1
|
||||
|
||||
# Don't want default ./... here:
|
||||
install:
|
||||
@@ -11,23 +11,9 @@ install:
|
||||
# (1) Fetch dependencies for us to run the tests in test/examples_test.go
|
||||
- go get -t -v k8s.io/kubernetes.github.io/test
|
||||
|
||||
# The dependencies are complicated for test/examples_test.go
|
||||
# k8s.io/kubernetes/pkg is a dependency, which in turn depends on apimachinery
|
||||
# but we also have apimachinery directly as one of our dependencies, which causes a conflict.
|
||||
# Additionally, we get symlinks when we clone the directory. The below steps do the following:
|
||||
|
||||
# (a) Replace the symlink with the actual dependencies from kubernetes/staging/src/
|
||||
# (b) copy all the vendored files to $GOPATH/src
|
||||
- rm $GOPATH/src/k8s.io/kubernetes/vendor/k8s.io/apimachinery
|
||||
- rm $GOPATH/src/k8s.io/kubernetes/vendor/k8s.io/apiserver
|
||||
- rm $GOPATH/src/k8s.io/kubernetes/vendor/k8s.io/client-go
|
||||
- rm $GOPATH/src/k8s.io/kubernetes/vendor/k8s.io/sample-apiserver
|
||||
- rm $GOPATH/src/k8s.io/kubernetes/vendor/k8s.io/kube-aggregator
|
||||
- cp -r $GOPATH/src/k8s.io/kubernetes/vendor/* $GOPATH/src/
|
||||
- rm -rf $GOPATH/src/k8s.io/kubernetes/vendor/*
|
||||
- cp -r $GOPATH/src/k8s.io/kubernetes/staging/src/* $GOPATH/src/
|
||||
- cp -r $GOPATH/src/k8s.io/apimachinery/vendor/* $GOPATH/src/
|
||||
- rm -rf $GOPATH/src/k8s.io/apimachinery/vendor/*
|
||||
# Simplified deduplication of dependencies.
|
||||
- cp -L -R $GOPATH/src/k8s.io/kubernetes/vendor/ $GOPATH/src/
|
||||
- rm -r $GOPATH/src/k8s.io/kubernetes/vendor/
|
||||
|
||||
# (2) Fetch md-check along with all its dependencies.
|
||||
- git clone --depth=50 --branch=master https://github.com/kubernetes/md-check $HOME/gopath/src/k8s.io/md-check
|
||||
|
||||
@@ -36,6 +36,8 @@ gems:
|
||||
- jekyll-seo-tag
|
||||
- jekyll-include-cache
|
||||
|
||||
include: [_headers]
|
||||
|
||||
# SEO
|
||||
logo: /images/favicon.png
|
||||
twitter:
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
---
|
||||
|
||||
# API Reference
|
||||
|
||||
Use the following reference docs to understand the kubernetes REST API for various API group versions:
|
||||
|
||||
* apps/v1alpha1: [operations](/docs/api-reference/apps/v1alpha1/operations.html), [model definitions](/docs/api-reference/apps/v1alpha1/definitions.html)
|
||||
* authentication.k8s.io/v1beta1: [operations](/docs/api-reference/authentication.k8s.io/v1beta1/operations.html), [model definitions](/docs/api-reference/authentication.k8s.io/v1beta1/definitions.html)
|
||||
* authorization.k8s.io/v1beta1: [operations](/docs/api-reference/authorization.k8s.io/v1beta1/operations.html), [model definitions](/docs/api-reference/authorization.k8s.io/v1beta1/definitions.html)
|
||||
* autoscaling/v1: [operations](/docs/api-reference/autoscaling/v1/operations.html), [model definitions](/docs/api-reference/autoscaling/v1/definitions.html)
|
||||
* batch/v1: [operations](/docs/api-reference/batch/v1/operations.html), [model definitions](/docs/api-reference/batch/v1/definitions.html)
|
||||
* certificates.k8s.io/v1alpha1: [operations](/docs/api-reference/certificates.k8s.io/v1alpha1/operations.html), [model definitions](/docs/api-reference/certificates.k8s.io/v1alpha1/definitions.html)
|
||||
* extensions/v1beta1: [operations](/docs/api-reference/extensions/v1beta1/operations.html), [model definitions](/docs/api-reference/extensions/v1beta1/definitions.html)
|
||||
* policy/v1: [operations](/docs/api-reference/policy/v1/operations.html), [model definitions](/docs/api-reference/policy/v1/definitions.html)
|
||||
* rbac.authorization.k8s.io/v1alpha1: [operations](/docs/api-reference/rbac.authorization.k8s.io/v1alpha1/operations.html), [model definitions](/docs/api-reference/rbac.authorization.k8s.io/v1alpha1/definitions.html)
|
||||
* storage.k8s.io/v1beta1: [operations](/docs/api-reference/storage.k8s.io/v1beta1/operations.html), [model definitions](/docs/api-reference/storage.k8s.io/v1beta1/definitions.html)
|
||||
* v1: [operations](/docs/api-reference/v1/operations.html), [model definitions](/docs/api-reference/v1/definitions.html)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
|
||||
[]()
|
||||
<!-- END MUNGE: GENERATED_ANALYTICS -->
|
||||
@@ -0,0 +1,12 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: counter
|
||||
spec:
|
||||
containers:
|
||||
- name: count
|
||||
image: ubuntu:14.04
|
||||
args: [bash, -c,
|
||||
'for ((i = 0; ; i++)); do echo "$i: $(date)"; sleep 1; done']
|
||||
|
||||
|
||||
@@ -2,9 +2,167 @@
|
||||
assignees:
|
||||
- crassirostris
|
||||
- piosz
|
||||
title: Logging with Stackdriver Logging
|
||||
|
||||
---
|
||||
|
||||
{% include user-guide-content-moved.md %}
|
||||
Before reading this page, it's recommended to familiarize yourself with the [overview of logging in Kubernetes](/docs/user-guide/logging/overview).
|
||||
|
||||
[Logging Using Stackdriver](/docs/tasks/debug-application-cluster/logging-stackdriver/)
|
||||
This article assumes that you have created a Kubernetes cluster with cluster-level logging support for sending logs to Stackdriver Logging. You can do this either by selecting "Enable Stackdriver Logging" checkbox in create cluster dialogue in [GKE](https://cloud.google.com/container-engine/) or by setting flag `KUBE_LOGGING_DESTINATION` to `gcp` when manually starting cluster using `kube-up.sh`.
|
||||
|
||||
## Overview
|
||||
|
||||
After creation, your cluster has a collection of system pods running in the `kube-system` namespace that support monitoring, logging, and DNS resolution for Kuberentes service names. You can see these system pods by running the following command:
|
||||
|
||||
```shell
|
||||
$ kubectl get pods --namespace=kube-system
|
||||
NAME READY REASON RESTARTS AGE
|
||||
fluentd-cloud-logging-kubernetes-node-0f64 1/1 Running 0 32m
|
||||
fluentd-cloud-logging-kubernetes-node-27gf 1/1 Running 0 32m
|
||||
fluentd-cloud-logging-kubernetes-node-pk22 1/1 Running 0 31m
|
||||
fluentd-cloud-logging-kubernetes-node-20ej 1/1 Running 0 31m
|
||||
kube-dns-v3-pk22 3/3 Running 0 32m
|
||||
monitoring-heapster-v1-20ej 0/1 Running 9 32m
|
||||
```
|
||||
|
||||
Here is the same information in a picture which shows how the pods might be placed on specific nodes.
|
||||
|
||||

|
||||
|
||||
This diagram shows four nodes created on a Google Compute Engine cluster with the name of each VM node on a purple background. The internal and public IPs of each node are shown on gray boxes and the pods running in each node are shown in green boxes. Each pod box shows the name of the pod and the namespace it runs in, the IP address of the pod and the images which are run as part of the pod's execution. Here we see that every node is running a fluentd-cloud-logging pod which is collecting the log output of the containers running on the same node and sending them to Stackdriver Logging. A pod which provides the
|
||||
[cluster DNS service](/docs/admin/dns) runs on one of the nodes and a pod which provides monitoring support runs on another node.
|
||||
|
||||
To help explain how cluster-level logging works, consider the following synthetic log generator pod specification [counter-pod.yaml](/docs/user-guide/logging/counter-pod.yaml):
|
||||
|
||||
{% include code.html language="yaml" file="counter-pod.yaml" %}
|
||||
|
||||
This pod specification has one container which runs a bash script when the container is born. This script simply writes out the value of a counter and the date once per second and runs indefinitely. Let's create the pod in the default namespace.
|
||||
|
||||
```shell
|
||||
$ kubectl create -f examples/blog-logging/counter-pod.yaml
|
||||
pods/counter
|
||||
```
|
||||
|
||||
We can observe the running pod:
|
||||
|
||||
```shell
|
||||
$ kubectl get pods
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
counter 1/1 Running 0 5m
|
||||
```
|
||||
|
||||
This step may take a few minutes to download the ubuntu:14.04 image during which the pod status will be shown as `Pending`.
|
||||
|
||||
One of the nodes is now running the counter pod:
|
||||
|
||||

|
||||
|
||||
When the pod status changes to `Running` we can use the `kubectl logs` command to view the output of this counter pod.
|
||||
|
||||
```shell
|
||||
$ kubectl logs counter
|
||||
0: Tue Jun 2 21:37:31 UTC 2015
|
||||
1: Tue Jun 2 21:37:32 UTC 2015
|
||||
2: Tue Jun 2 21:37:33 UTC 2015
|
||||
3: Tue Jun 2 21:37:34 UTC 2015
|
||||
4: Tue Jun 2 21:37:35 UTC 2015
|
||||
5: Tue Jun 2 21:37:36 UTC 2015
|
||||
...
|
||||
```
|
||||
|
||||
This command fetches the log text from the Docker log file for the image that is running in this container. We can connect to the running container and observe the running counter bash script.
|
||||
|
||||
```shell
|
||||
$ kubectl exec -i counter bash
|
||||
ps aux
|
||||
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
|
||||
root 1 0.0 0.0 17976 2888 ? Ss 00:02 0:00 bash -c for ((i = 0; ; i++)); do echo "$i: $(date)"; sleep 1; done
|
||||
root 468 0.0 0.0 17968 2904 ? Ss 00:05 0:00 bash
|
||||
root 479 0.0 0.0 4348 812 ? S 00:05 0:00 sleep 1
|
||||
root 480 0.0 0.0 15572 2212 ? R 00:05 0:00 ps aux
|
||||
```
|
||||
|
||||
If, for any reason, the image in this pod is killed off and then restarted by Kubernetes, or the pod was evicted from the node, logs for the container are lost.
|
||||
|
||||
Try deleting the currently running counter container:
|
||||
|
||||
```shell
|
||||
$ kubectl delete pod counter
|
||||
pods/counter
|
||||
```
|
||||
|
||||
Now let's restart the counter.
|
||||
|
||||
```shell
|
||||
$ kubectl create -f examples/blog-logging/counter-pod.yaml
|
||||
pods/counter
|
||||
```
|
||||
|
||||
Let's wait for the container to restart and get the log lines again.
|
||||
|
||||
```shell
|
||||
$ kubectl logs counter
|
||||
0: Tue Jun 2 21:51:40 UTC 2015
|
||||
1: Tue Jun 2 21:51:41 UTC 2015
|
||||
2: Tue Jun 2 21:51:42 UTC 2015
|
||||
3: Tue Jun 2 21:51:43 UTC 2015
|
||||
4: Tue Jun 2 21:51:44 UTC 2015
|
||||
5: Tue Jun 2 21:51:45 UTC 2015
|
||||
6: Tue Jun 2 21:51:46 UTC 2015
|
||||
7: Tue Jun 2 21:51:47 UTC 2015
|
||||
8: Tue Jun 2 21:51:48 UTC 2015
|
||||
```
|
||||
|
||||
As expected, the log lines from the first invocation of the container in this pod have been lost. However, you'll likely want to preserve all the log lines from each invocation of each container in the pod. Furthermore, even if the pod is restarted, you might still want to preserve all the log lines that were ever emitted by the containers in the pod. This is exactly the functionality provided by cluster-level logging in Kubernetes.
|
||||
|
||||
## Viewing logs
|
||||
|
||||
We can click on the Logs item under the Monitoring section of the Google Developer Console and select the logs for the counter container, which will be called kubernetes.counter_default_count. This identifies the name of the pod (counter), the namespace (default) and the name of the container (count) for which the log collection occurred. Using this name we can select just the logs for our counter container from the drop down menu:
|
||||
|
||||

|
||||
|
||||
When we view the logs in the Developer Console we observe the logs for both invocations of the container.
|
||||
|
||||

|
||||
|
||||
Note the first container counted to 108 and then it was terminated. When the next container image restarted the counting process resumed from 0. Similarly if we deleted the pod and restarted it we would capture the logs for all instances of the containers in the pod whenever the pod was running.
|
||||
|
||||
Logs ingested into Stackdriver Logging may be exported to various other destinations including [Google Cloud Storage](https://cloud.google.com/storage/) buckets and [BigQuery](https://cloud.google.com/bigquery/). Use the Exports tab in the Cloud Logging console to specify where logs should be streamed to. You can also follow this link to the
|
||||
[settings tab](https://pantheon.corp.google.com/project/_/logs/settings).
|
||||
|
||||
We could query the ingested logs from BigQuery using the SQL query which reports the counter log lines showing the newest lines first:
|
||||
|
||||
```shell
|
||||
SELECT metadata.timestamp, structPayload.log
|
||||
FROM [mylogs.kubernetes_counter_default_count_20150611]
|
||||
ORDER BY metadata.timestamp DESC
|
||||
```
|
||||
|
||||
Here is some sample output:
|
||||
|
||||

|
||||
|
||||
We could also fetch the logs from Google Cloud Storage buckets to our desktop or laptop and then search them locally. The following command fetches logs for the counter pod running in a cluster which is itself in a Compute Engine project called `myproject`. Only logs for the date 2015-06-11 are fetched.
|
||||
|
||||
|
||||
```shell
|
||||
$ gsutil -m cp -r gs://myproject/kubernetes.counter_default_count/2015/06/11 .
|
||||
```
|
||||
|
||||
Now we can run queries over the ingested logs. The example below uses the [jq](http://stedolan.github.io/jq/) program to extract just the log lines.
|
||||
|
||||
```shell
|
||||
$ cat 21\:00\:00_21\:59\:59_S0.json | jq '.structPayload.log'
|
||||
"0: Thu Jun 11 21:39:38 UTC 2015\n"
|
||||
"1: Thu Jun 11 21:39:39 UTC 2015\n"
|
||||
"2: Thu Jun 11 21:39:40 UTC 2015\n"
|
||||
"3: Thu Jun 11 21:39:41 UTC 2015\n"
|
||||
"4: Thu Jun 11 21:39:42 UTC 2015\n"
|
||||
"5: Thu Jun 11 21:39:43 UTC 2015\n"
|
||||
"6: Thu Jun 11 21:39:44 UTC 2015\n"
|
||||
"7: Thu Jun 11 21:39:45 UTC 2015\n"
|
||||
...
|
||||
```
|
||||
|
||||
This page has touched briefly on the underlying mechanisms that support gathering cluster-level logs on a Kubernetes deployment. The approach here only works for gathering the standard output and standard error output of the processes running in the pod's containers. To gather other logs that are stored in files one can use a sidecar container to gather the required files as described at the page [Collecting log files within containers with Fluentd](https://github.com/kubernetes/contrib/blob/master/logging/fluentd-sidecar-gcp/README.md) and sending them to the Stackdriver Logging service.
|
||||
|
||||
Some of the material in this section also appears in the blog article [Cluster-level Logging with Kubernetes](http://blog.kubernetes.io/2015/06/cluster-level-logging-with-kubernetes.html)
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
---
|
||||
assignees:
|
||||
- bgrant0607
|
||||
- janetkuo
|
||||
- thockin
|
||||
|
||||
---
|
||||
|
||||
You've seen [how to configure and deploy pods and containers](/docs/user-guide/configuring-containers), using some of the most common configuration parameters. This section dives into additional features that are especially useful for running applications in production.
|
||||
|
||||
* TOC
|
||||
{:toc}
|
||||
|
||||
## Using a Volume for storage
|
||||
|
||||
The container file system only lives as long as the container does, so when a container crashes and restarts, changes to the filesystem will be lost and the container will restart from a clean slate. For more consistent storage that lasts for the life of a Pod, you need a [*volume*](/docs/user-guide/volumes). This is especially important to stateful applications, such as key-value stores and databases.
|
||||
|
||||
For example, [Redis](http://redis.io/) is a key-value cache and store, which we use in the [guestbook](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/guestbook/) and other examples. We can add a volume to it to store data as follows:
|
||||
|
||||
{% include code.html language="yaml" file="redis-deployment.yaml" ghlink="/docs/user-guide/redis-deployment.yaml" %}
|
||||
|
||||
`emptyDir` volumes live for the lifespan of the [pod](/docs/user-guide/pods), which is longer than the lifespan of any one container, so if the container fails and is restarted, our storage will live on.
|
||||
|
||||
In addition to the local disk storage provided by `emptyDir`, Kubernetes supports many different network-attached storage solutions, including PD on GCE and EBS on EC2, which are preferred for critical data, and will handle details such as mounting and unmounting the devices on the nodes. See [the volumes doc](/docs/user-guide/volumes) for more details.
|
||||
|
||||
## Distributing credentials
|
||||
|
||||
Many applications need credentials, such as passwords, OAuth tokens, and TLS keys, to authenticate with other applications, databases, and services. Storing these credentials in container images or environment variables is less than ideal, since the credentials can then be copied by anyone with access to the image, pod/container specification, host file system, or host Docker daemon.
|
||||
|
||||
Kubernetes provides a mechanism, called [*secrets*](/docs/user-guide/secrets), that facilitates delivery of sensitive credentials to applications. A `Secret` is a simple resource containing a map of data. For instance, you can create a simple secret with a username and password as follows:
|
||||
|
||||
```shell
|
||||
$ kubectl create secret generic mysecret --from-literal=username="admin",password="1234"
|
||||
secret "mysecret" created
|
||||
```
|
||||
|
||||
This is equivalent to `kubectl create -f`:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: mysecret
|
||||
type: Opaque
|
||||
data:
|
||||
username: YWRtaW4=
|
||||
password: MTIzNA==
|
||||
```
|
||||
|
||||
As with other resources, the created secret can be viewed with `get`:
|
||||
|
||||
```shell
|
||||
$ kubectl get secrets
|
||||
NAME TYPE DATA AGE
|
||||
default-token-zirbw kubernetes.io/service-account-token 3 3h
|
||||
mysecret Opaque 2 2m
|
||||
```
|
||||
|
||||
To use the secret, you need to reference it in a pod or pod template. The `secret` volume source enables you to mount it as an in-memory directory into your containers.
|
||||
|
||||
{% include code.html language="yaml" file="redis-secret-deployment.yaml" ghlink="/docs/user-guide/redis-secret-deployment.yaml" %}
|
||||
|
||||
For more details, see the [secrets document](/docs/user-guide/secrets), [example](/docs/user-guide/secrets/) and [design doc](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/secrets.md).
|
||||
|
||||
## Authenticating with a private image registry
|
||||
|
||||
Secrets can also be used to pass [image registry credentials](/docs/user-guide/images/#using-a-private-registry).
|
||||
|
||||
The easiest way to create a secret for Docker registry is:
|
||||
|
||||
```shell
|
||||
$ kubectl create secret docker-registry myregistrykey --docker-username=janedoe --docker-password=●●●●●●●●●●● --docker-email=jdoe@example.com
|
||||
secret "myregistrykey" created
|
||||
```
|
||||
|
||||
Alternatively, you can do the equivalent with the following steps. First, create a `.docker/config.json`, such as by running `docker login <registry.domain>`.
|
||||
Then put the resulting `.docker/config.json` file into a [secret resource](secrets.md). For example:
|
||||
|
||||
```shell
|
||||
$ docker login
|
||||
Username: janedoe
|
||||
Password: ●●●●●●●●●●●
|
||||
Email: jdoe@example.com
|
||||
WARNING: login credentials saved in /Users/jdoe/.docker/config.json.
|
||||
Login Succeeded
|
||||
|
||||
$ echo $(cat ~/.docker/config.json)
|
||||
{ "https://index.docker.io/v1/": { "auth": "ZmFrZXBhc3N3b3JkMTIK", "email": "jdoe@example.com" } }
|
||||
|
||||
$ cat ~/.docker/config.json | base64
|
||||
eyAiaHR0cHM6Ly9pbmRleC5kb2NrZXIuaW8vdjEvIjogeyAiYXV0aCI6ICJabUZyWlhCaGMzTjNiM0prTVRJSyIsICJlbWFpbCI6ICJqZG9lQGV4YW1wbGUuY29tIiB9IH0K
|
||||
|
||||
$ cat > /tmp/image-pull-secret.yaml <<EOF
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: myregistrykey
|
||||
data:
|
||||
.dockerconfigjson: eyAiaHR0cHM6Ly9pbmRleC5kb2NrZXIuaW8vdjEvIjogeyAiYXV0aCI6ICJabUZyWlhCaGMzTjNiM0prTVRJSyIsICJlbWFpbCI6ICJqZG9lQGV4YW1wbGUuY29tIiB9IH0K
|
||||
type: kubernetes.io/dockerconfigjson
|
||||
EOF
|
||||
|
||||
$ kubectl create -f /tmp/image-pull-secret.yaml
|
||||
secret "myregistrykey" created
|
||||
```
|
||||
|
||||
Now, you can create pods which reference that secret by adding an `imagePullSecrets`
|
||||
section to a pod definition.
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: foo
|
||||
spec:
|
||||
containers:
|
||||
- name: foo
|
||||
image: janedoe/awesomeapp:v1
|
||||
imagePullSecrets:
|
||||
- name: myregistrykey
|
||||
```
|
||||
|
||||
## Helper containers
|
||||
|
||||
[Pods](/docs/user-guide/pods) support running multiple containers co-located together. They can be used to host vertically integrated application stacks, but their primary motivation is to support auxiliary helper programs that assist the primary application. Typical examples are data pullers, data pushers, and proxies.
|
||||
|
||||
Such containers typically need to communicate with one another, often through the file system. This can be achieved by mounting the same volume into both containers. An example of this pattern would be a web server with a [program that polls a git repository](http://releases.k8s.io/{{page.githubbranch}}/contrib/git-sync/) for new updates:
|
||||
|
||||
```yaml
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: my-nginx
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
volumes:
|
||||
- name: www-data
|
||||
emptyDir: {}
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx
|
||||
# This container reads from the www-data volume
|
||||
volumeMounts:
|
||||
- mountPath: /srv/www
|
||||
name: www-data
|
||||
readOnly: true
|
||||
- name: git-monitor
|
||||
image: myrepo/git-monitor
|
||||
env:
|
||||
- name: GIT_REPO
|
||||
value: http://github.com/some/repo.git
|
||||
# This container writes to the www-data volume
|
||||
volumeMounts:
|
||||
- mountPath: /data
|
||||
name: www-data
|
||||
```
|
||||
|
||||
More examples can be found in our [blog article](http://blog.kubernetes.io/2015/06/the-distributed-system-toolkit-patterns.html) and [presentation slides](http://www.slideshare.net/Docker/slideshare-burns).
|
||||
|
||||
## Resource management
|
||||
|
||||
Kubernetes's scheduler will place applications only where they have adequate CPU and memory, but it can only do so if it knows how much [resources they require](/docs/user-guide/compute-resources). The consequence of specifying too little CPU is that the containers could be starved of CPU if too many other containers were scheduled onto the same node. Similarly, containers could die unpredictably due to running out of memory if no memory were requested, which can be especially likely for large-memory applications.
|
||||
|
||||
If no resource requirements are specified, a nominal amount of resources is assumed. (This default is applied via a [LimitRange](/docs/admin/limitrange/) for the default [Namespace](/docs/user-guide/namespaces). It can be viewed with `kubectl describe limitrange limits`.) You may explicitly specify the amount of resources required as follows:
|
||||
|
||||
{% include code.html language="yaml" file="redis-resource-deployment.yaml" ghlink="/docs/user-guide/redis-resource-deployment.yaml" %}
|
||||
|
||||
The container will die due to OOM (out of memory) if it exceeds its specified limit, so specifying a value a little higher than expected generally improves reliability. By specifying request, pod is guaranteed to be able to use that much of resource when needed. See [Resource QoS](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/docs/design/resource-qos.md) for the difference between resource limits and requests.
|
||||
|
||||
If you're not sure how much resources to request, you can first launch the application without specifying resources, and use [resource usage monitoring](/docs/user-guide/monitoring) to determine appropriate values.
|
||||
|
||||
## Liveness and readiness probes (aka health checks)
|
||||
|
||||
Many applications running for long periods of time eventually transition to broken states, and cannot recover except by restarting them. Kubernetes provides [*liveness probes*](/docs/user-guide/pod-states/#container-probes) to detect and remedy such situations.
|
||||
|
||||
A common way to probe an application is using HTTP, which can be specified as follows:
|
||||
|
||||
{% include code.html language="yaml" file="nginx-probe-deployment.yaml" ghlink="/docs/user-guide/nginx-probe-deployment.yaml" %}
|
||||
|
||||
Other times, applications are only temporarily unable to serve, and will recover on their own. Typically in such cases you'd prefer not to kill the application, but don't want to send it requests, either, since the application won't respond correctly or at all. A common such scenario is loading large data or configuration files during application startup. Kubernetes provides *readiness probes* to detect and mitigate such situations. Readiness probes are configured similarly to liveness probes, just using the `readinessProbe` field. A pod with containers reporting that they are not ready will not receive traffic through Kubernetes [services](/docs/user-guide/connecting-applications).
|
||||
|
||||
For more details (e.g., how to specify command-based probes), see the [example in the walkthrough](/docs/user-guide/walkthrough/k8s201/#health-checking), the [standalone example](/docs/user-guide/liveness/), and the [documentation](/docs/user-guide/pod-states/#container-probes).
|
||||
|
||||
## Handling initialization
|
||||
|
||||
Applications often need a set of initialization steps prior to performing their day job. This may include:
|
||||
|
||||
* Waiting for other components (like a database or web service) to be available
|
||||
* Performing configuration templating from environment variables into a config file
|
||||
* Registering the pod into a central database, or fetching remote configuration from that database
|
||||
* Downloading application dependencies, seed data, or preconfiguring disk
|
||||
|
||||
Kubernetes now includes a beta feature known as **init containers**, which are one or more containers in a pod that get a chance to run and initialize shared volumes prior to the other application containers starting. An init container is exactly like a regular container, except that it always runs to completion and each init container must complete successfully before the next one is started. If the init container fails (exits with a non-zero exit code) on a `RestartNever` pod the pod will fail - otherwise it will be restarted until it succeeds or the user deletes the pod.
|
||||
|
||||
Since init containers are a beta feature, they are specified by setting the `pod.beta.kubernetes.io/init-containers` annotation on a pod (or replica set, deployment, daemon set, pet set, or job). The value of the annotation must be a string containing a JSON array of container definitions:
|
||||
|
||||
{% include code.html language="yaml" file="nginx-init-containers.yaml" ghlink="/docs/user-guide/nginx-init-containers.yaml" %}
|
||||
|
||||
The status of the init containers is returned as another annotation - `pod.beta.kubernetes.io/init-container-statuses` -- as an array of the container statuses (similar to the `status.containerStatuses` field).
|
||||
|
||||
Init containers support all of the same features as normal containers, including resource limits, volumes, and security settings. The resource requests and limits for an init container are handled slightly different than normal containers since init containers are run one at a time instead of all at once - any limits or quotas will be applied based on the largest init container resource quantity, rather than as the sum of quantities. Init containers do not support readiness probes since they will run to completion before the pod can be ready.
|
||||
|
||||
[Complete Init Container Documentation](/docs/user-guide/pods/init-container/)
|
||||
|
||||
|
||||
## Lifecycle hooks and termination notice
|
||||
|
||||
Of course, nodes and applications may fail at any time, but many applications benefit from clean shutdown, such as to complete in-flight requests, when the termination of the application is deliberate. To support such cases, Kubernetes supports two kinds of notifications:
|
||||
|
||||
* Kubernetes will send SIGTERM to applications, which can be handled in order to effect graceful termination. SIGKILL is sent a configurable number of seconds later if the application does not terminate sooner (defaults to 30 seconds, controlled by `spec.terminationGracePeriodSeconds`).
|
||||
* Kubernetes supports the (optional) specification of a [*pre-stop lifecycle hook*](/docs/user-guide/container-environment/#container-hooks), which will execute prior to sending SIGTERM.
|
||||
|
||||
The specification of a pre-stop hook is similar to that of probes, but without the timing-related parameters. For example:
|
||||
|
||||
{% include code.html language="yaml" file="nginx-lifecycle-deployment.yaml" ghlink="/docs/user-guide/nginx-lifecycle-deployment.yaml" %}
|
||||
|
||||
## Termination message
|
||||
|
||||
In order to achieve a reasonably high level of availability, especially for actively developed applications, it's important to debug failures quickly. Kubernetes can speed debugging by surfacing causes of fatal errors in a way that can be display using [`kubectl`](/docs/user-guide/kubectl/) or the [UI](/docs/user-guide/ui), in addition to general [log collection](/docs/user-guide/logging/overview). It is possible to specify a `terminationMessagePath` where a container will write its 'death rattle'?, such as assertion failure messages, stack traces, exceptions, and so on. The default path is `/dev/termination-log`.
|
||||
|
||||
Here is a toy example:
|
||||
|
||||
{% include code.html language="yaml" file="pod-w-message.yaml" ghlink="/docs/user-guide/pod-w-message.yaml" %}
|
||||
|
||||
The message is recorded along with the other state of the last (i.e., most recent) termination:
|
||||
|
||||
```shell
|
||||
{% raw %}
|
||||
$ kubectl create -f ./pod-w-message.yaml
|
||||
pod "pod-w-message" created
|
||||
$ sleep 70
|
||||
$ kubectl get pods/pod-w-message -o go-template="{{range .status.containerStatuses}}{{.lastState.terminated.message}}{{end}}"
|
||||
Sleep expired
|
||||
$ kubectl get pods/pod-w-message -o go-template="{{range .status.containerStatuses}}{{.lastState.terminated.exitCode}}{{end}}"
|
||||
0
|
||||
{% endraw %}
|
||||
```
|
||||
|
||||
## What's next?
|
||||
|
||||
[Learn more about managing deployments.](/docs/user-guide/managing-deployments)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 25 KiB |
@@ -9,4 +9,7 @@ docs/api-reference/v1/definitions.md
|
||||
docs/api-reference/v1/operations.md
|
||||
docs/user-guide/pods/_viewing-a-pod.md
|
||||
docs/user-guide/simple-yaml.md
|
||||
docs/concepts/abstractions/pod-termination.md
|
||||
docs/concepts/abstractions/pod-termination.md
|
||||
docs/api-reference/README.md
|
||||
docs/user-guide/logging/stackdriver.md
|
||||
docs/user-guide/production-pods.md
|
||||
|
||||
@@ -16,3 +16,6 @@ docs/user-guide/downward-api/index.md
|
||||
docs/user-guide/downward-api/volume/index.md
|
||||
docs/user-guide/getting-into-containers.md
|
||||
|
||||
docs/api-reference/README.md
|
||||
docs/user-guide/logging/stackdriver.md
|
||||
docs/user-guide/production-pods.md
|
||||
|
||||
Reference in New Issue
Block a user