From 8a484aff51fd0333dfe84a572901914d904eec6a Mon Sep 17 00:00:00 2001 From: gavinB-orange Date: Tue, 4 Oct 2016 19:08:22 +0200 Subject: [PATCH 001/247] Update minikube.md to cover use behind a web proxy In a corporate environment you need to pass proxy information, and just setting the appropriate environment variables does not work. The code snippet here works for me --- docs/getting-started-guides/minikube.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docs/getting-started-guides/minikube.md b/docs/getting-started-guides/minikube.md index 020fc5e257..1ad16b6d28 100644 --- a/docs/getting-started-guides/minikube.md +++ b/docs/getting-started-guides/minikube.md @@ -99,6 +99,14 @@ Kubectl is now configured to use the cluster. This will build and start a lightweight local cluster, consisting of a master, etcd, Docker and a single node. +If you are behind a web proxy, you will need to pass this information in e.g. via + +``` + +https_proxy= minikube start --docker-env HTTP_PROXY= --docker-env HTTPS_PROXY= --docker-env NO_PROXY=192.168.99.0/24 + +Unfortunately just setting the environment variables will not work. +``` Minikube will also create a "minikube" context, and set it to default in kubectl. To switch back to this context later, run this command: `kubectl config use-context minikube`. From 199101048df6f84a80349464f3fb77a17fd799eb Mon Sep 17 00:00:00 2001 From: Devin Donnelly Date: Wed, 2 Nov 2016 16:27:27 -0700 Subject: [PATCH 002/247] Adds Concepts root page and starts to fill out the underlying section. --- docs/concepts/abstractions/pod.md | 3 ++ docs/concepts/index.md | 46 ++++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 docs/concepts/abstractions/pod.md diff --git a/docs/concepts/abstractions/pod.md b/docs/concepts/abstractions/pod.md new file mode 100644 index 0000000000..ec380ec43f --- /dev/null +++ b/docs/concepts/abstractions/pod.md @@ -0,0 +1,3 @@ +--- +--- + diff --git a/docs/concepts/index.md b/docs/concepts/index.md index db56a3d05b..3511f2354d 100644 --- a/docs/concepts/index.md +++ b/docs/concepts/index.md @@ -1,7 +1,51 @@ --- --- -The Concepts section of the Kubernetes documentation is a work in progress. +The Concepts section helps you learn about the parts of the Kubernetes system and the abstractions Kubernetes uses to represent your cluster, and helps you obtain a deeper understanding of how Kubernetes works. + +## Overview + +To work with Kubernetes, you use the **Kubernetes API abstractions** to describe your cluster's **desired state**: what applications or other workloads you want to run, what container images they use, the number of replicas, what network and disk resources you want to make available, and more. You set your desired state by using the Kubernetes API, typically via the command-line interface, `kubectl`. You can also use the Kubernetes API directly to interact with the cluster and set or modify your desired state. + +Once you've set your desired state, the **Kubernetes Control Plane** works to make the cluster's current state match the desired state. To do so, Kuberentes performs a variety of tasks automatically--such as starting or restarting containers, scaling the number of replicas of a given application, and more. The Kubernetes Control Plane consists of processes running on your cluster: the Kubernetes Master, and kubelet and kube-proxy processes running on your cluster's individual nodes. + +## Kubernetes Abstractions + +Kubernetes contains a number of abstractions that represent your deployed containerized applications and workloads, along with their associated network and disk resources. These abstractions are made manifest as objects in the Kubernetes API. The basic Kubernetes abstractions include: + +* Pod +* Service +* Volume +* Namespace + +In addition, Kubernetes contains a number of higher-level abstractions that build upon the basic abstractions, and provide additional functionality and convenience features. They include: + +* ReplicaSet +* Deployment +* StatefulSet +* DaemonSet +* Job + +## Kubernetes Control Plane + +The various parts of the Kubernetes Control Plane, such as the Kubernetes Master and kubelet processes, govern how Kubernetes communicates with your cluster. When you use the Kubernetes API to create deployments, for example, the Kubernetes Control Plane carries out your instructions. + +### Kubernetes Master + +The Kubernetes master is responsible for maintaining the desired state for your cluster. The Kubernetes master(s) runs the following processes: + +* API Server +* Scheduler +* Etcd +* Controller Manager + +### Kubernetes Nodes + +The nodes in a cluster are the machines (VMs, physical servers, etc) that run your applications and cloud workflows. These nodes are controlled by the Kubernetes master. The following processes run on each node in a Kubernetes cluster: + +* Kubelet +* Docker-daemon +* kube-proxy #### Object Metadata From 6eea38eddb71bbab2dc9ffc121f0cd5e25575fc5 Mon Sep 17 00:00:00 2001 From: Devin Donnelly Date: Thu, 17 Nov 2016 16:10:17 -0800 Subject: [PATCH 003/247] First draft of Concepts landing page. Adds Kubernetes Objects overview. Adds first draft of Pod. --- docs/concepts/abstractions/overview.md | 58 +++++++++++++++++++++ docs/concepts/abstractions/pod.md | 71 ++++++++++++++++++++++++++ docs/concepts/index.md | 16 +++--- 3 files changed, 138 insertions(+), 7 deletions(-) create mode 100644 docs/concepts/abstractions/overview.md diff --git a/docs/concepts/abstractions/overview.md b/docs/concepts/abstractions/overview.md new file mode 100644 index 0000000000..9b561d1b3e --- /dev/null +++ b/docs/concepts/abstractions/overview.md @@ -0,0 +1,58 @@ +--- +--- + +{% capture overview %} +This page explains how Kubernetes objects are represented in the Kubernetes API, and how you can express them in `.yaml` format. +{% endcapture %} + +{% capture body %} +### Understanding Kubernetes Objects + +*Kubernetes Objects* are persistent entities in the Kubernetes system. Kubenetes uses these entities to represent the state of your cluster. Specifically, they can describe: + +* What containerized applications are running (and on which nodes) +* The resources available to those applications +* The policies around how those applications behave, such as restart policies, upgrades, and fault-tolerance + +When you create a Kubernetes object, you create a "record of intent"--once you create the object, the Kubernetes system will constantly work to ensure that the entity exists. By creating an object, you're effectively telling the Kubernetes system what you want your cluster to be doing; this is your cluster's **desired state**. + +To work with Kubernetes objects--whether to create, modify, or delete them--you'll need to use the [Kubernetes API](https://github.com/kubernetes/kubernetes/blob/master/docs/devel/api-conventions.md). When you use the `kubectl` comamnd-line interface, for example, the CLI makes the necessary Kubernetes API calls for you; you can also use the Kubernetes API directly in your own programs. + +#### Object Spec and Status + +Every Kubernetes object has two major nested object fields: the object *spec* and the object *status*. The *spec*, which you must provide, describes your *desired state* for the object--the characteristics that you want the object to have. The *status* describes the *actual state* for the object, and is supplied by the Kubernetes system. At any given time, the [Kubernetes Control Plane](/docs/concepts/control-plane/overview/) actively maintains an object's actual state to match the desired state you supplied. + +For more information on the object spec and status, see the [Kubernetes API Conventions](https://github.com/kubernetes/kubernetes/blob/master/docs/devel/api-conventions.md#spec-and-status). + +#### Describing a Kubernetes Object + +When you create an object in Kubernetes, you need to describe it. Your description must provide some basic information about the object along with the object spec that represents your desired state. The Kubernetes API communicates this information by passing JSON; when you make Kubernetes API calls or use the `kubectl` command-line interface, **you can express that JSON using a `.yaml` file.** + +Here's an example `.yaml` file that shows an example of the required fields and object spec for a Kubernetes [Deployment](/docs/concepts/abstractions/deployment/): + +{% include code.html language="yaml" file="nginx-deployment.yaml" ghlink="/docs/user-guide/nginx-deployment.yaml" %} + +One way to create a Deployment using a `.yaml` file like the one above is to use the []`kubectl create`]() command in the `kubectl` command-line interface, passing the `.yaml` file as an argument. Here's an example: + +```shell +$ kubectl create -f docs/user-guide/nginx-deployment.yaml --record +deployment "nginx-deployment" created +``` + +#### Required Fields + +In the `.yaml` file for the Kubernetes object you want to create, you'll need to set values for the following fields: + +* `apiVersion` - Which version of the Kubernetes API you're using to create this object +* `kind` - What kind of object you want to create +* `metadata` - Data that helps uniquely identify the object, including a `name` string, UID, and optional `namespace` + +You'll also need to provide the object `spec` field. The precise format of the object `spec` is different for every Kubernetes object, and contains nested fields specific to that object. The [Kubernetes API reference](/docs/api/) can help you find the spec format for all of the objects you can create using Kubernetes. + +{% endcapture %} + +{% capture whatsnext %} +* Learn about the most important basic Kubernetes objects, such as [Pod](/docs/concepts/abstractions/pod/). +{% endcapture %} + +{% include templates/concept.md %} \ No newline at end of file diff --git a/docs/concepts/abstractions/pod.md b/docs/concepts/abstractions/pod.md index ec380ec43f..4fd21471e9 100644 --- a/docs/concepts/abstractions/pod.md +++ b/docs/concepts/abstractions/pod.md @@ -1,3 +1,74 @@ --- --- +{% capture overview %} +This page provides an overview of `Pod`, the smallest deployable object in the Kubernetes object model. +{% endcapture %} + +* TOC +{:toc} + +{% capture body %} +### Understanding Pods + +A *Pod* is the basic building block of Kubernetes--the smallest and simplest unit in the Kubernetes object model that you create or deploy. A Pod represents a running process on your cluster. + +A Pod encapsulates an application container (or, in some cases, multiple containers), storage resources, and options that govern how the container(s) should run. A Pod represents a unit of deployment: *a single workload in Kubernetes*, which might consist of either a single application or a small number of applications that are tightly coupled and that share resources. + +> [Docker](https://www.docker.com) is the most common container runtime used in a Kubernetes Pod, but Pods support other container runtimes as well. + +Pods are employed a number of ways in a Kubernetes cluster, including: + +* **Pods that run a single application container**. The "one-application per Pod" model is the most common Kubernetes use case; in this case, you can think of a Pod as a wrapper around a single application, and Kubernetes manages the Pods rather than the containers directly. +* **Pods that run multiple application containers that need to work together**. Pods can support multiple application containers that are tightly coupled and need to share resources. You can think of these applications as forming a *single cohesive unit of service*. The Pod wraps them together with shared resources as a single managable entity. + +Pods typically *do not* model multiple instances of the same application container. Instead, you can have Kubernetes maintain separate Pods for each instance you want to run, usually managed by a Controller. See [Pods and Controllers](#pods-and-controllers) for more information. + +#### How Pods Manage Containers + +Pods are designed to support multiple cooperating processes (as application containers) that form a cohesive unit of service. The containers in a Pod are automatically co-located and co-scheduled on the same phyiscal or virtual machine in the cluster. The containers can share resources and dependencies, communicate with one another, and coordinate when and how they are terminated. + +Pods provide two kinds of shared resources for their constituent containers: *networking* and *storage*. + +##### Networking + +Each Pod is assigned a unique IP address. Every the container in a pod shares the network namespace, including the IP address and network ports. Containers *inside a Pod* can communicate with one another using `localhost`. When containers in a Pod communicate with entities *outside the Pod*, they must coordinate how they use the shared network resources (such as ports). + +##### Storage + +A Pod can specify a set of shared storage *volumes*. All containers in the pod can access the shared volumes, allowing those containers to share data. Volumes also allow persistent data in a pod to survive in case one of the containers within needs to be restarted. See [Volumes]() for more information on how Kubernetes implements shared storage in a Pod. + +### Working with Pods + +When a Pod gets created (directly or indirectly), it is scheduled to run on a [node]() in your cluster, and remains on that node until terminated or deleted. Should a node in the cluster fail, the Pods scheduled on that node are deleted after a timeout period. See [Termination](#pod-termination) for more details on how Pods terminate in Kubernetes. + +You'll rarely create or interact directly with individual Pods in Kubernetes--even singleton Pods. This is because Pods are designed as relatively ephemeral entities (as opposed to a durable one). A Pod won't survive a scheduling failure, a node failure, or an eviction due to a lack of resources or node maintenance. Thus, while it is possible to use Pod directly, it's far more common in Kubernetes to manage your pods using a higher-level abstraction called a *Controller*. + +#### Pods and Controllers + +A Controller can create and manage multiple Pods for you, handling replication and rollout and providing self-healing capabilities at cluster scope (for example, if a node fails, a Controller might schedule an identical replacement Pod on a different node). + +Some examples of Controllers that contain one or more pods include: + +* [Deployment]() +* [StatefulSet]() +* [DaemonSet]() + +In general, Controllers use a [Pod Template]() that you provide to create the Pods for which it is responsible. + +#### Pod Termination + +Since Pods represent processes running on your cluster, Kubernetes provides for *graceful termination* when Pods are no longer needed. Kubernetes implements graceful termination by applying a default *grace period* of 30 seconds from the time that you issue a termination request. After the grace period expires, Kubernetes issues a `KILL` signal to the relevant processes and the Pod is deleted from the Kubernetes Master. + +> **Note:** The grace period is configurable; you can set your own grace period when interacting with the cluster to request termination, such as using the `kubectl delete` command. See the [Terminating a Pod]() tutorial for more information. + +{% endcapture %} + + +{% if whatsnext %} + +### What's next + +{{ whatsnext }} + +{% endif %} \ No newline at end of file diff --git a/docs/concepts/index.md b/docs/concepts/index.md index 3511f2354d..a6b35bdfde 100644 --- a/docs/concepts/index.md +++ b/docs/concepts/index.md @@ -5,20 +5,22 @@ The Concepts section helps you learn about the parts of the Kubernetes system an ## Overview -To work with Kubernetes, you use the **Kubernetes API abstractions** to describe your cluster's **desired state**: what applications or other workloads you want to run, what container images they use, the number of replicas, what network and disk resources you want to make available, and more. You set your desired state by using the Kubernetes API, typically via the command-line interface, `kubectl`. You can also use the Kubernetes API directly to interact with the cluster and set or modify your desired state. +To work with Kubernetes, you use *Kubernetes API objects* to describe your cluster's *desired state*: what applications or other workloads you want to run, what container images they use, the number of replicas, what network and disk resources you want to make available, and more. You set your desired state by creating objects using the Kubernetes API, typically via the command-line interface, `kubectl`. You can also use the Kubernetes API directly to interact with the cluster and set or modify your desired state. -Once you've set your desired state, the **Kubernetes Control Plane** works to make the cluster's current state match the desired state. To do so, Kuberentes performs a variety of tasks automatically--such as starting or restarting containers, scaling the number of replicas of a given application, and more. The Kubernetes Control Plane consists of processes running on your cluster: the Kubernetes Master, and kubelet and kube-proxy processes running on your cluster's individual nodes. +Once you've set your desired state, the *Kubernetes Control Plane* works to make the cluster's current state match the desired state. To do so, Kuberentes performs a variety of tasks automatically--such as starting or restarting containers, scaling the number of replicas of a given application, and more. The Kubernetes Control Plane consists of processes running on your cluster: the Kubernetes Master, and kubelet and kube-proxy processes running on your cluster's individual nodes. -## Kubernetes Abstractions +## Kubernetes Objects -Kubernetes contains a number of abstractions that represent your deployed containerized applications and workloads, along with their associated network and disk resources. These abstractions are made manifest as objects in the Kubernetes API. The basic Kubernetes abstractions include: +Kubernetes contains a number of abstractions that represent your the state of your system: deployed containerized applications and workloads, their associated network and disk resources, and other information about what your cluster is doing. These abstractions are represented by objects in the Kubernetes API; see the [Kubernetes Objects overview](/docs/concepts/abstractions/overview/) for more details. -* Pod +The basic Kubernetes objects include: + +* [Pod](/docs/concepts/abstractions/pod/) * Service * Volume * Namespace -In addition, Kubernetes contains a number of higher-level abstractions that build upon the basic abstractions, and provide additional functionality and convenience features. They include: +In addition, Kubernetes contains a number of higher-level abstractions that build upon the basic objects, and provide additional functionality and convenience features. They include: * ReplicaSet * Deployment @@ -28,7 +30,7 @@ In addition, Kubernetes contains a number of higher-level abstractions that buil ## Kubernetes Control Plane -The various parts of the Kubernetes Control Plane, such as the Kubernetes Master and kubelet processes, govern how Kubernetes communicates with your cluster. When you use the Kubernetes API to create deployments, for example, the Kubernetes Control Plane carries out your instructions. +The various parts of the Kubernetes Control Plane, such as the Kubernetes Master and kubelet processes, govern how Kubernetes communicates with your cluster. When you use the Kubernetes API to create a Deployment object, for example, the Kubernetes Control Plane carries out your instructions. ### Kubernetes Master From a21c80911e6a50e33f1add5fc1b7c832d4cb1ee5 Mon Sep 17 00:00:00 2001 From: Devin Donnelly Date: Thu, 17 Nov 2016 16:22:46 -0800 Subject: [PATCH 004/247] Attempted include file fix for sample Deployment .yaml file. --- docs/concepts/abstractions/overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/concepts/abstractions/overview.md b/docs/concepts/abstractions/overview.md index 9b561d1b3e..c4899afa44 100644 --- a/docs/concepts/abstractions/overview.md +++ b/docs/concepts/abstractions/overview.md @@ -30,7 +30,7 @@ When you create an object in Kubernetes, you need to describe it. Your descripti Here's an example `.yaml` file that shows an example of the required fields and object spec for a Kubernetes [Deployment](/docs/concepts/abstractions/deployment/): -{% include code.html language="yaml" file="nginx-deployment.yaml" ghlink="/docs/user-guide/nginx-deployment.yaml" %} +{% include code.html language="yaml" file="/docs/user-guide/nginx-deployment.yaml" ghlink="/docs/user-guide/nginx-deployment.yaml" %} One way to create a Deployment using a `.yaml` file like the one above is to use the []`kubectl create`]() command in the `kubectl` command-line interface, passing the `.yaml` file as an argument. Here's an example: From 30be38b63f5a249d654e8b132c8987bd4f4c6021 Mon Sep 17 00:00:00 2001 From: Devin Donnelly Date: Fri, 18 Nov 2016 16:37:23 -0800 Subject: [PATCH 005/247] Edited Concepts landing page, Objects overview, and Pod concept documentation to address feedback from pwittroc. --- docs/concepts/abstractions/overview.md | 17 ++++++++---- docs/concepts/abstractions/pod.md | 38 +++++++++++++++++++------- docs/concepts/index.md | 11 ++++++-- 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/docs/concepts/abstractions/overview.md b/docs/concepts/abstractions/overview.md index c4899afa44..8407eecf43 100644 --- a/docs/concepts/abstractions/overview.md +++ b/docs/concepts/abstractions/overview.md @@ -14,19 +14,21 @@ This page explains how Kubernetes objects are represented in the Kubernetes API, * The resources available to those applications * The policies around how those applications behave, such as restart policies, upgrades, and fault-tolerance -When you create a Kubernetes object, you create a "record of intent"--once you create the object, the Kubernetes system will constantly work to ensure that the entity exists. By creating an object, you're effectively telling the Kubernetes system what you want your cluster to be doing; this is your cluster's **desired state**. +When you create a Kubernetes object, you create a "record of intent"--once you create the object, the Kubernetes system will constantly work to ensure that that object exists. By creating an object, you're effectively telling the Kubernetes system what you want your cluster's workload to look like; this is your cluster's **desired state**. -To work with Kubernetes objects--whether to create, modify, or delete them--you'll need to use the [Kubernetes API](https://github.com/kubernetes/kubernetes/blob/master/docs/devel/api-conventions.md). When you use the `kubectl` comamnd-line interface, for example, the CLI makes the necessary Kubernetes API calls for you; you can also use the Kubernetes API directly in your own programs. +To work with Kubernetes objects--whether to create, modify, or delete them--you'll need to use the [Kubernetes API](https://github.com/kubernetes/kubernetes/blob/master/docs/devel/api-conventions.md). When you use the `kubectl` comamnd-line interface, for example, the CLI makes the necessary Kubernetes API calls for you; you can also use the Kubernetes API directly in your own programs. Kubernetes currently provides a `golang` client library for this purpose, and other language libraries are being developed. #### Object Spec and Status -Every Kubernetes object has two major nested object fields: the object *spec* and the object *status*. The *spec*, which you must provide, describes your *desired state* for the object--the characteristics that you want the object to have. The *status* describes the *actual state* for the object, and is supplied by the Kubernetes system. At any given time, the [Kubernetes Control Plane](/docs/concepts/control-plane/overview/) actively maintains an object's actual state to match the desired state you supplied. +Every Kubernetes object includes two nested object fields that govern the object's configuration: the object *spec* and the object *status*. The *spec*, which you must provide, describes your *desired state* for the object--the characteristics that you want the object to have. The *status* describes the *actual state* for the object, and is supplied and updated by the Kubernetes system. At any given time, the [Kubernetes Control Plane](/docs/concepts/control-plane/overview/) actively manages an object's actual state to match the desired state you supplied. -For more information on the object spec and status, see the [Kubernetes API Conventions](https://github.com/kubernetes/kubernetes/blob/master/docs/devel/api-conventions.md#spec-and-status). +For example, a Kubernetes [Deployment]() is an object that can represent an application running on your cluster. When you create the Deployment, you might set the Deployment spec to specify that you want three replicas of the application to be running. The Kubernetes system reads the Deployment spec and starts three instances of your desired application--updating the status to match your spec. If any of those instances should fail (a status change), the Kubernetes system reacts to the difference between spec and status by making a correction--in this case, starting a replacement instance. + +For more information on the object spec, status, and metadata, see the [Kubernetes API Conventions](https://github.com/kubernetes/kubernetes/blob/master/docs/devel/api-conventions.md#spec-and-status). #### Describing a Kubernetes Object -When you create an object in Kubernetes, you need to describe it. Your description must provide some basic information about the object along with the object spec that represents your desired state. The Kubernetes API communicates this information by passing JSON; when you make Kubernetes API calls or use the `kubectl` command-line interface, **you can express that JSON using a `.yaml` file.** +When you create an object in Kubernetes, you must provide the object spec that describes your desired state for it, as well as some basic information about the object (such as a name). When you use the Kubernetes API to create the object (either directly or via `kubectl`), that API call sends the information to the Kubernetes Master as JSON. **You can express that JSON using a `.yaml` file.** Here's an example `.yaml` file that shows an example of the required fields and object spec for a Kubernetes [Deployment](/docs/concepts/abstractions/deployment/): @@ -36,6 +38,11 @@ One way to create a Deployment using a `.yaml` file like the one above is to use ```shell $ kubectl create -f docs/user-guide/nginx-deployment.yaml --record +``` + +The output is similar to this: + +```shell deployment "nginx-deployment" created ``` diff --git a/docs/concepts/abstractions/pod.md b/docs/concepts/abstractions/pod.md index 4fd21471e9..fb65c8b33c 100644 --- a/docs/concepts/abstractions/pod.md +++ b/docs/concepts/abstractions/pod.md @@ -13,20 +13,29 @@ This page provides an overview of `Pod`, the smallest deployable object in the K A *Pod* is the basic building block of Kubernetes--the smallest and simplest unit in the Kubernetes object model that you create or deploy. A Pod represents a running process on your cluster. -A Pod encapsulates an application container (or, in some cases, multiple containers), storage resources, and options that govern how the container(s) should run. A Pod represents a unit of deployment: *a single workload in Kubernetes*, which might consist of either a single application or a small number of applications that are tightly coupled and that share resources. +A Pod encapsulates an application container (or, in some cases, multiple containers), storage resources, a unique network IP, and options that govern how the container(s) should run. A Pod represents a unit of deployment: *a single instance of an application in Kubernetes*, which might consist of either a single container or a small number of containers that are tightly coupled and that share resources. > [Docker](https://www.docker.com) is the most common container runtime used in a Kubernetes Pod, but Pods support other container runtimes as well. Pods are employed a number of ways in a Kubernetes cluster, including: -* **Pods that run a single application container**. The "one-application per Pod" model is the most common Kubernetes use case; in this case, you can think of a Pod as a wrapper around a single application, and Kubernetes manages the Pods rather than the containers directly. -* **Pods that run multiple application containers that need to work together**. Pods can support multiple application containers that are tightly coupled and need to share resources. You can think of these applications as forming a *single cohesive unit of service*. The Pod wraps them together with shared resources as a single managable entity. +* **Pods that run a single container**. The "one-container-per-Pod" model is the most common Kubernetes use case; in this case, you can think of a Pod as a wrapper around a single container, and Kubernetes manages the Pods rather than the containers directly. +* **Pods that run multiple containers that need to work together**. A Pod might encapsulate an application that relies on multiple co-located containers that are tightly coupled and need to share resources. These co-located containers might form a single cohesive unit of service--one container serving files from a shared volume to the public, while a separate "sidecar" container refreshes or updates those files. The Pod wraps these containers and storage resources together as a single managable entity. -Pods typically *do not* model multiple instances of the same application container. Instead, you can have Kubernetes maintain separate Pods for each instance you want to run, usually managed by a Controller. See [Pods and Controllers](#pods-and-controllers) for more information. +The [Kubernetes Blog](http://blog.kubernetes.io) has some additional information on Pod use cases. For more information, see: -#### How Pods Manage Containers +* [The Distributed System Toolkit: Patterns for Composite Containers](http://blog.kubernetes.io/2015/06/the-distributed-system-toolkit-patterns.html) +* [Container Design Patterns](http://blog.kubernetes.io/2016/06/container-design-patterns.html) -Pods are designed to support multiple cooperating processes (as application containers) that form a cohesive unit of service. The containers in a Pod are automatically co-located and co-scheduled on the same phyiscal or virtual machine in the cluster. The containers can share resources and dependencies, communicate with one another, and coordinate when and how they are terminated. +Note that each Pod is meant to run a single instance of a given application. If you want to scale your application horizontally (e.g., run muliple instances), you should use multiple Pods, one for each instance. In Kubernetes, such Pods are usually managed by a Controller. See [Pods and Controllers](#pods-and-controllers) for more information. + +#### How Pods Manage Multiple Containers + +Pods are designed to support multiple cooperating processes (as containers) that form a cohesive unit of service. The containers in a Pod are automatically co-located and co-scheduled on the same phyiscal or virtual machine in the cluster. The containers can share resources and dependencies, communicate with one another, and coordinate when and how they are terminated. + +Note that grouping multiple co-located and co-managed containers in a single Pod is a relatively advanced use case. You should use this pattern only in specific instances in which your containers are tightly coupled. For example, you might have a container that acts as a web server for files in a shared volume, and a separate "sidecar" container that updates those files from a remote source, as in the following diagram: + +![pod diagram](/images/docs/pod.svg){: style="max-width: 50%" } Pods provide two kinds of shared resources for their constituent containers: *networking* and *storage*. @@ -40,13 +49,15 @@ A Pod can specify a set of shared storage *volumes*. All containers in the pod c ### Working with Pods -When a Pod gets created (directly or indirectly), it is scheduled to run on a [node]() in your cluster, and remains on that node until terminated or deleted. Should a node in the cluster fail, the Pods scheduled on that node are deleted after a timeout period. See [Termination](#pod-termination) for more details on how Pods terminate in Kubernetes. +You'll rarely create individual Pods directly in Kubernetes--even singleton Pods. This is because Pods are designed as relatively ephemeral, disposable entities. When a Pod gets created (directly by you, or indirectly by a Controller), it is scheduled to run on a [node]() in your cluster. The Pod remains on that node until the process is terminated, the pod object is deleted, or the pod is *evicted* for lack of resources. -You'll rarely create or interact directly with individual Pods in Kubernetes--even singleton Pods. This is because Pods are designed as relatively ephemeral entities (as opposed to a durable one). A Pod won't survive a scheduling failure, a node failure, or an eviction due to a lack of resources or node maintenance. Thus, while it is possible to use Pod directly, it's far more common in Kubernetes to manage your pods using a higher-level abstraction called a *Controller*. +> Note: Restarting a container in a Pod should not be confused with restarting the Pod. The Pod itself does not run, but is an environment the containers run in and persists until it is deleted. + +Pods do not, by themselves, self-heal. If a Pod is scheduled to a node that fails, or if the scheduling operation itself fails, the Pod is deleted; likewise, a Pod won't survive an eviction due to a lack of resources or node maintenance. Kubernetes uses a higher-level abstraction, called a *Controller*, that handles the work of managing the relatively disposable Pod instances. Thus, while it is possible to use Pod directly, it's far more common in Kubernetes to manage your pods using a Controller. See [Pods and Controllers](#pods-and-controllers) for more information on how Kubernetes uses Controllers to implement Pod scaling and healing. #### Pods and Controllers -A Controller can create and manage multiple Pods for you, handling replication and rollout and providing self-healing capabilities at cluster scope (for example, if a node fails, a Controller might schedule an identical replacement Pod on a different node). +A Controller can create and manage multiple Pods for you, handling replication and rollout and providing self-healing capabilities at cluster scope. For example, if a node fails, the Controller might automatically replace the Pod by scheduling an identical replacement on a different node). Some examples of Controllers that contain one or more pods include: @@ -58,7 +69,14 @@ In general, Controllers use a [Pod Template]() that you provide to create the Po #### Pod Termination -Since Pods represent processes running on your cluster, Kubernetes provides for *graceful termination* when Pods are no longer needed. Kubernetes implements graceful termination by applying a default *grace period* of 30 seconds from the time that you issue a termination request. After the grace period expires, Kubernetes issues a `KILL` signal to the relevant processes and the Pod is deleted from the Kubernetes Master. +Since Pods represent processes running on your cluster, Kubernetes provides for *graceful termination* when Pods are no longer needed. Kubernetes implements graceful termination by applying a default *grace period* of 30 seconds from the time that you issue a termination request. A typical Pod termination in Kubernetes involves the following steps: + +1. You send a command or API call to terminate the Pod. +1. Kubernetes updates the Pod status to reflect the time after which the Pod is to be considered "dead" (the time of the termination request plus the grace period). +1. Kubernetes marks the Pod state as "Terminating" and stops sending traffic to the Pod. +1. Kubernetes send a `TERM` signal to the Pod, indicating that the Pod should shut down. +1. When the grace period expires, Kubernetes issues a `SIGKILL` to any processes still running in the Pod. +1. Kubernetes removes the Pod from the API server on the Kubernetes Master. > **Note:** The grace period is configurable; you can set your own grace period when interacting with the cluster to request termination, such as using the `kubectl delete` command. See the [Terminating a Pod]() tutorial for more information. diff --git a/docs/concepts/index.md b/docs/concepts/index.md index a6b35bdfde..ab5bd548a5 100644 --- a/docs/concepts/index.md +++ b/docs/concepts/index.md @@ -7,7 +7,12 @@ The Concepts section helps you learn about the parts of the Kubernetes system an To work with Kubernetes, you use *Kubernetes API objects* to describe your cluster's *desired state*: what applications or other workloads you want to run, what container images they use, the number of replicas, what network and disk resources you want to make available, and more. You set your desired state by creating objects using the Kubernetes API, typically via the command-line interface, `kubectl`. You can also use the Kubernetes API directly to interact with the cluster and set or modify your desired state. -Once you've set your desired state, the *Kubernetes Control Plane* works to make the cluster's current state match the desired state. To do so, Kuberentes performs a variety of tasks automatically--such as starting or restarting containers, scaling the number of replicas of a given application, and more. The Kubernetes Control Plane consists of processes running on your cluster: the Kubernetes Master, and kubelet and kube-proxy processes running on your cluster's individual nodes. +Once you've set your desired state, the *Kubernetes Control Plane* works to make the cluster's current state match the desired state. To do so, Kuberentes performs a variety of tasks automatically--such as starting or restarting containers, scaling the number of replicas of a given application, and more. The Kubernetes Control Plane consists of a collection processes running on your cluster: + +* The **Kubernetes Master** is a collection of four processes that run on a single node in your cluster, which is designated as the master node. +* Each individual non-master node in your cluster runs two processes: + * **kubelet**, which communicates with the Kubernetes Master. + * **kube-proxy**, a network proxy which reflects Kubernetes networking services on each node. ## Kubernetes Objects @@ -30,7 +35,9 @@ In addition, Kubernetes contains a number of higher-level abstractions that buil ## Kubernetes Control Plane -The various parts of the Kubernetes Control Plane, such as the Kubernetes Master and kubelet processes, govern how Kubernetes communicates with your cluster. When you use the Kubernetes API to create a Deployment object, for example, the Kubernetes Control Plane carries out your instructions. +The various parts of the Kubernetes Control Plane, such as the Kubernetes Master and kubelet processes, govern how Kubernetes communicates with your cluster. The Control Plane maintains a record of all of the Kubernetes Objects in the system, and runs continuous control loops to manage those objects' state. At any given time, the Control Plane's control loops will attempt to match the actual state of all the objects in the system to the desired state that you provided when you created those objects. + +For example, When you use the Kubernetes API to create a Deployment object, for example, you provide a new desired state for the system. The Kubernetes Control Plane records that object creation, and carries out your instructions by starting the required applications and scheduling them to cluster nodes--thus making the cluster's actual state match the desired state. ### Kubernetes Master From 537893253f98d719185439899af05e032f82dda3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolai=20von=C2=A0Neudeck?= Date: Tue, 29 Nov 2016 00:11:40 +0100 Subject: [PATCH 006/247] Added info about where to add/drop capabilities The user-guide did not mention where to drop/add capabilities in Kubernetes. Added a link to the not yet complete API documentation and an example. --- docs/user-guide/containers.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/docs/user-guide/containers.md b/docs/user-guide/containers.md index cf05278801..26eceebbce 100644 --- a/docs/user-guide/containers.md +++ b/docs/user-guide/containers.md @@ -94,3 +94,24 @@ The relationship between Docker's capabilities and [Linux capabilities](http://m | SETFCAP | CAP_SETFCAP | | WAKE_ALARM | CAP_WAKE_ALARM | | BLOCK_SUSPEND | CAP_BLOCK_SUSPEND | + +Capabilities are added/dropped in the [`SecurityContext`](http://kubernetes.io/docs/api-reference/v1/definitions/#_v1_securitycontext), e.g.: + +``` +apiVersion: v1 +kind: Pod +metadata: + name: hello-world +spec: + containers: + - name: friendly-container + image: "alpine:3.4" + command: + - echo "hello" + securityContext: + capabilities: + add: + - SYS_NICE + drop: + - KILL +``` From c61aee3c5407da65c1902f9060c9654c1a5f5c17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolai=20von=C2=A0Neudeck?= Date: Tue, 29 Nov 2016 00:34:29 +0100 Subject: [PATCH 007/247] forgot yaml format --- docs/user-guide/containers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user-guide/containers.md b/docs/user-guide/containers.md index 26eceebbce..c985c94f02 100644 --- a/docs/user-guide/containers.md +++ b/docs/user-guide/containers.md @@ -97,7 +97,7 @@ The relationship between Docker's capabilities and [Linux capabilities](http://m Capabilities are added/dropped in the [`SecurityContext`](http://kubernetes.io/docs/api-reference/v1/definitions/#_v1_securitycontext), e.g.: -``` +```yaml apiVersion: v1 kind: Pod metadata: From fd0d4112b05302af5ee8e8e30d9cfd4e6f986c5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolai=20von=C2=A0Neudeck?= Date: Tue, 29 Nov 2016 00:43:01 +0100 Subject: [PATCH 008/247] fixed indentation, cleaner command --- docs/user-guide/containers.md | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/docs/user-guide/containers.md b/docs/user-guide/containers.md index c985c94f02..7c39f30f09 100644 --- a/docs/user-guide/containers.md +++ b/docs/user-guide/containers.md @@ -101,17 +101,16 @@ Capabilities are added/dropped in the [`SecurityContext`](http://kubernetes.io/d apiVersion: v1 kind: Pod metadata: - name: hello-world + name: hello-world spec: - containers: - - name: friendly-container - image: "alpine:3.4" - command: - - echo "hello" - securityContext: - capabilities: - add: - - SYS_NICE - drop: - - KILL + containers: + - name: friendly-container + image: "alpine:3.4" + command: ["/bin/echo", "hello", "world"] + securityContext: + capabilities: + add: + - SYS_NICE + drop: + - KILL ``` From 77c7980a7485374442f85297c94fa756a9360461 Mon Sep 17 00:00:00 2001 From: a-mccarthy Date: Tue, 29 Nov 2016 12:21:55 -0500 Subject: [PATCH 009/247] New page for reviewing issues process adds a new page to the contribute section and navigation that describes the reviewing and labeling process for backlog/newly created issues --- _data/support.yml | 2 + docs/contribute/review-issues.md | 65 ++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 docs/contribute/review-issues.md diff --git a/_data/support.yml b/_data/support.yml index 1b8e80699a..132a1013c3 100644 --- a/_data/support.yml +++ b/_data/support.yml @@ -14,6 +14,8 @@ toc: path: /docs/contribute/stage-documentation-changes/ - title: Using Page Templates path: /docs/contribute/page-templates/ + - title: Reviewing Documentation Issues + path: /docs/contribute/review-issues/ - title: Documentation Style Guide path: /docs/contribute/style-guide/ diff --git a/docs/contribute/review-issues.md b/docs/contribute/review-issues.md new file mode 100644 index 0000000000..c74404a08e --- /dev/null +++ b/docs/contribute/review-issues.md @@ -0,0 +1,65 @@ +--- +--- + +{% capture overview %} + +This page explains how you should review and prioritize documentation issues made for the [kubernetes/kubernetes.github.io](https://github.com/kubernetes/kubernetes.github.io){: target="_blank"} repository. The purpose is to provide a way to organize issues and make it easier to contribute to Kubernetes documentation. The following should be used as the standard way of prioritizing, labeling, and interacting with issues. +{% endcapture %} + +{% capture body %} + +## Categorizing issues +Issues should be sorted into different buckets of work using the following labels and definitions. If an issue doesn't have enough information to identify a problem that can be researched, reviewed, or worked on (i.e. the issue doesn't fit into any of the categories below) you should close the issue with a comment explaining why it is being closed. + + +#### Actionable +* Issues that can be worked on with current information (or may need a comment to explain what needs to be done to make it more clear) +* Allows contributors to have easy to find issues to work on + + +#### Tech Review Needed +* Issues that need more information in order to be worked on (the proposed solution needs to be proven, a SME needs to be involved, work needs to be done to understand the problem/resolution and if the issue is still relevant) +* Promotes transparency about level of work needed for the issue and that issue is in progress + +#### Docs Review Needed +* Issues that are suggestions for better processes or site improvements that require community agreement to be implemented +* Topics can be brought to SIG meetings as agenda items + + +## Prioritizing Issues +The following labels and definitions should be used to prioritize issues. If you change the priority of an issues, please comment on the issue with your reasoning for the change. + +#### P1 +* Major content errors affecting more than 1 page +* Broken code sample on a heavily trafficked page +* Errors on a “getting started” page +* Well known or highly publicized customer pain points +* Automation issues + +#### P2 +* Default for all new issues +* Broken code for sample that is not heavily used +* Minor content issues in a heavily trafficked page +* Major content issues on a lower-trafficked page + +#### P3 +* Typos and broken anchor links + +## Handling special issue types + +### Duplicate issues + +### Dead link issues +Depending on where the dead link is reported, different actions are required to resolve the issue. Dead links in the API and Kubectl docs are automation issues and should be assigned a P1 until the problem can be fully understood. All other dead links are issues that need to be manually fixed and can be assigned a P3. + +{% endcapture %} + + + +{% capture whatsnext %} +* Learn about [writing a new topic](/docs/contribute/write-new-topic). +* Learn about [using page templates](/docs/contribute/page-templates/). +* Learn about [staging your changes](/docs/contribute/stage-documentation-changes). +{% endcapture %} + +{% include templates/concept.md %} From 18252f80e453265ab491ba1664dbdcadbece8b2f Mon Sep 17 00:00:00 2001 From: a-mccarthy Date: Tue, 29 Nov 2016 12:33:35 -0500 Subject: [PATCH 010/247] adding in duplicate seciton which was weirdly left out adding in left out section --- docs/contribute/review-issues.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/contribute/review-issues.md b/docs/contribute/review-issues.md index c74404a08e..58a72f6697 100644 --- a/docs/contribute/review-issues.md +++ b/docs/contribute/review-issues.md @@ -48,6 +48,7 @@ The following labels and definitions should be used to prioritize issues. If you ## Handling special issue types ### Duplicate issues +If a single problem has one or more issues open for it, the problem should be consolodated into a single issue. You should decide which issue to keep open (or open a new issue), port over all relevant information, link related issues, and close all the other issues that describe the same problem. Only having a single issue to work on will help reduce confusion and avoid duplicating work on the same problem. ### Dead link issues Depending on where the dead link is reported, different actions are required to resolve the issue. Dead links in the API and Kubectl docs are automation issues and should be assigned a P1 until the problem can be fully understood. All other dead links are issues that need to be manually fixed and can be assigned a P3. From 4ed6b4e6f462955ad07457cbe030eb372070650c Mon Sep 17 00:00:00 2001 From: a-mccarthy Date: Fri, 9 Dec 2016 14:15:28 -0500 Subject: [PATCH 011/247] Fixed whats next section in TOC and SME --- docs/contribute/review-issues.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/contribute/review-issues.md b/docs/contribute/review-issues.md index 58a72f6697..51de679064 100644 --- a/docs/contribute/review-issues.md +++ b/docs/contribute/review-issues.md @@ -8,7 +8,7 @@ This page explains how you should review and prioritize documentation issues mad {% capture body %} -## Categorizing issues +### Categorizing issues Issues should be sorted into different buckets of work using the following labels and definitions. If an issue doesn't have enough information to identify a problem that can be researched, reviewed, or worked on (i.e. the issue doesn't fit into any of the categories below) you should close the issue with a comment explaining why it is being closed. @@ -18,7 +18,7 @@ Issues should be sorted into different buckets of work using the following label #### Tech Review Needed -* Issues that need more information in order to be worked on (the proposed solution needs to be proven, a SME needs to be involved, work needs to be done to understand the problem/resolution and if the issue is still relevant) +* Issues that need more information in order to be worked on (the proposed solution needs to be proven, a subject matter expert needs to be involved, work needs to be done to understand the problem/resolution and if the issue is still relevant) * Promotes transparency about level of work needed for the issue and that issue is in progress #### Docs Review Needed @@ -26,7 +26,7 @@ Issues should be sorted into different buckets of work using the following label * Topics can be brought to SIG meetings as agenda items -## Prioritizing Issues +### Prioritizing Issues The following labels and definitions should be used to prioritize issues. If you change the priority of an issues, please comment on the issue with your reasoning for the change. #### P1 @@ -45,12 +45,12 @@ The following labels and definitions should be used to prioritize issues. If you #### P3 * Typos and broken anchor links -## Handling special issue types +### Handling special issue types -### Duplicate issues +#### Duplicate issues If a single problem has one or more issues open for it, the problem should be consolodated into a single issue. You should decide which issue to keep open (or open a new issue), port over all relevant information, link related issues, and close all the other issues that describe the same problem. Only having a single issue to work on will help reduce confusion and avoid duplicating work on the same problem. -### Dead link issues +#### Dead link issues Depending on where the dead link is reported, different actions are required to resolve the issue. Dead links in the API and Kubectl docs are automation issues and should be assigned a P1 until the problem can be fully understood. All other dead links are issues that need to be manually fixed and can be assigned a P3. {% endcapture %} From 94ee42f6588192fbd7bd7ba263952df7197a641e Mon Sep 17 00:00:00 2001 From: xilabao Date: Mon, 26 Dec 2016 01:48:55 -0600 Subject: [PATCH 012/247] Add rbac command to kubectl get --help reference to https://github.com/kubernetes/kubernetes/pull/37366 --- docs/user-guide/kubectl-overview.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/user-guide/kubectl-overview.md b/docs/user-guide/kubectl-overview.md index 99c1575e84..31b55f161f 100644 --- a/docs/user-guide/kubectl-overview.md +++ b/docs/user-guide/kubectl-overview.md @@ -84,6 +84,8 @@ The following table includes a list of all the supported resource types and thei Resource type | Abbreviated alias -------------------- | -------------------- `clusters` | +`clusterrolebindings` | +`clusterroles` | `componentstatuses` |`cs` `configmaps` |`cm` `daemonsets` |`ds` @@ -105,6 +107,8 @@ Resource type | Abbreviated alias `replicasets` |`rs` `replicationcontrollers` |`rc` `resourcequotas` |`quota` +`rolebindings` | +`roles` | `secrets` | `serviceaccounts` |`sa` `services` |`svc` From d0b94ae1b759b6a60ef3aec4156ee4c8cd672818 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolai=20von=C2=A0Neudeck?= Date: Mon, 26 Dec 2016 21:04:03 +0100 Subject: [PATCH 013/247] Removed passive voice --- docs/user-guide/containers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user-guide/containers.md b/docs/user-guide/containers.md index 7c39f30f09..d760c3b84f 100644 --- a/docs/user-guide/containers.md +++ b/docs/user-guide/containers.md @@ -95,7 +95,7 @@ The relationship between Docker's capabilities and [Linux capabilities](http://m | WAKE_ALARM | CAP_WAKE_ALARM | | BLOCK_SUSPEND | CAP_BLOCK_SUSPEND | -Capabilities are added/dropped in the [`SecurityContext`](http://kubernetes.io/docs/api-reference/v1/definitions/#_v1_securitycontext), e.g.: +You can add/drop capabilities in the [`SecurityContext`](http://kubernetes.io/docs/api-reference/v1/definitions/#_v1_securitycontext), e.g.: ```yaml apiVersion: v1 From 9fe1e02e728db13a244765d5b977ffdda4839f73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nicolai=20von=C2=A0Neudeck?= Date: Mon, 26 Dec 2016 21:16:47 +0100 Subject: [PATCH 014/247] replaced "/" with "or" --- docs/user-guide/containers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user-guide/containers.md b/docs/user-guide/containers.md index d760c3b84f..e597279a4e 100644 --- a/docs/user-guide/containers.md +++ b/docs/user-guide/containers.md @@ -95,7 +95,7 @@ The relationship between Docker's capabilities and [Linux capabilities](http://m | WAKE_ALARM | CAP_WAKE_ALARM | | BLOCK_SUSPEND | CAP_BLOCK_SUSPEND | -You can add/drop capabilities in the [`SecurityContext`](http://kubernetes.io/docs/api-reference/v1/definitions/#_v1_securitycontext), e.g.: +You can add or drop capabilities in the [`SecurityContext`](http://kubernetes.io/docs/api-reference/v1/definitions/#_v1_securitycontext), e.g.: ```yaml apiVersion: v1 From 2f16fce28b50d3de8e6a2ce80f1aa31d387bfaf0 Mon Sep 17 00:00:00 2001 From: Janet Kuo Date: Tue, 20 Dec 2016 14:48:13 -0800 Subject: [PATCH 015/247] Add script for verifying docs without entry --- .travis.yml | 1 + skip_toc_check.txt | 3 +++ verify-entry-toc.sh | 20 ++++++++++++++++++++ 3 files changed, 24 insertions(+) create mode 100644 skip_toc_check.txt create mode 100755 verify-entry-toc.sh diff --git a/.travis.yml b/.travis.yml index 61caa32130..ba509e32d0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,3 +14,4 @@ install: script: - go test -v k8s.io/kubernetes.github.io/test - $GOPATH/bin/md-check --root-dir=$HOME/gopath/src/k8s.io/kubernetes.github.io +- ./verify-entry-toc.sh diff --git a/skip_toc_check.txt b/skip_toc_check.txt new file mode 100644 index 0000000000..eabcf6e724 --- /dev/null +++ b/skip_toc_check.txt @@ -0,0 +1,3 @@ +# Put files you want to skip table of contents entry check here: +docs/search.md +docs/sitemap.md diff --git a/verify-entry-toc.sh b/verify-entry-toc.sh new file mode 100755 index 0000000000..95ab757cda --- /dev/null +++ b/verify-entry-toc.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +no_entry=false + +# Verify all docs/.../*.md files are referenced in at least one of _data/*.yml +# files. Skip checking files in skip_toc_check.txt +for file in `find docs -name "*.md" -type f`; do + if ! grep -q "${file}" skip_toc_check.txt; then + path=${file%.*} + if ! grep -q "${path}" _data/*.yml; then + echo "Error: ${file} doesn't have an entry in the table of contents under _data/*.yml" + no_entry=true + fi + fi +done + +if ${no_entry}; then + echo "Found files without entries. For how to fix it, see http://kubernetes.io/docs/contribute/write-new-topic/#creating-an-entry-in-the-table-of-contents" + exit 1 +fi From 89765673af7b102f07a2c605c89ec8eddc9a23fa Mon Sep 17 00:00:00 2001 From: Janet Kuo Date: Tue, 27 Dec 2016 16:36:39 -0800 Subject: [PATCH 016/247] Update verify TOC rules for index.md --- skip_toc_check.txt | 2 ++ verify-entry-toc.sh | 2 ++ 2 files changed, 4 insertions(+) diff --git a/skip_toc_check.txt b/skip_toc_check.txt index eabcf6e724..e1a507b69a 100644 --- a/skip_toc_check.txt +++ b/skip_toc_check.txt @@ -1,3 +1,5 @@ # Put files you want to skip table of contents entry check here: docs/search.md docs/sitemap.md +docs/user-guide/pods/_viewing-a-pod.md +docs/user-guide/simple-yaml.md diff --git a/verify-entry-toc.sh b/verify-entry-toc.sh index 95ab757cda..7c0f13c518 100755 --- a/verify-entry-toc.sh +++ b/verify-entry-toc.sh @@ -7,6 +7,8 @@ no_entry=false for file in `find docs -name "*.md" -type f`; do if ! grep -q "${file}" skip_toc_check.txt; then path=${file%.*} + # abc/index.md should point to abc, not abc/index + path=${path%%index} if ! grep -q "${path}" _data/*.yml; then echo "Error: ${file} doesn't have an entry in the table of contents under _data/*.yml" no_entry=true From 99f964e072979a4c87978ffaa0ae787050ee0d21 Mon Sep 17 00:00:00 2001 From: chentao Date: Wed, 28 Dec 2016 14:13:54 +0800 Subject: [PATCH 017/247] Delete descriptions which related with removed or depreated values --- docs/admin/network-plugins.md | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/admin/network-plugins.md b/docs/admin/network-plugins.md index 27219bc5de..dd51a11b86 100644 --- a/docs/admin/network-plugins.md +++ b/docs/admin/network-plugins.md @@ -50,13 +50,10 @@ Kubenet is a very basic, simple network plugin, on Linux only. It does not, of Kubenet creates a Linux bridge named `cbr0` and creates a veth pair for each pod with the host end of each pair connected to `cbr0`. The pod end of the pair is assigned an IP address allocated from a range assigned to the node either through configuration or by the controller-manager. `cbr0` is assigned an MTU matching the smallest MTU of an enabled normal interface on the host. -The kubenet plugin is mutually exclusive with the --configure-cbr0 option. - The plugin requires a few things: * The standard CNI `bridge`, `lo` and `host-local` plugins are required, at minimum version 0.2.0. Kubenet will first search for them in `/opt/cni/bin`. Specify `network-plugin-dir` to supply additional search path. The first found match will take effect. * Kubelet must be run with the `--network-plugin=kubenet` argument to enable the plugin -* Kubelet must also be run with the `--reconcile-cidr` argument to ensure the IP subnet assigned to the node by configuration or the controller-manager is propagated to the plugin * Kubelet should also be run with the `--non-masquerade-cidr=` argumment to ensure traffic to IPs outside this range will use IP masquerade. * The node must be assigned an IP subnet through either the `--pod-cidr` kubelet command-line option or the `--allocate-node-cidrs=true --cluster-cidr=` controller-manager command-line options. From d420bea04c269f58fa3708dfa3ed4b8bad0d9bbe Mon Sep 17 00:00:00 2001 From: Premanand Chandrasekaran Date: Wed, 28 Dec 2016 06:36:52 -0500 Subject: [PATCH 018/247] Minor correction --- docs/user-guide/kubectl/kubectl_config.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user-guide/kubectl/kubectl_config.md b/docs/user-guide/kubectl/kubectl_config.md index 441db2334a..c19e98d381 100644 --- a/docs/user-guide/kubectl/kubectl_config.md +++ b/docs/user-guide/kubectl/kubectl_config.md @@ -14,7 +14,7 @@ Modify kubeconfig files using subcommands like "kubectl config set current-conte The loading order follows these rules: 1. If the --kubeconfig flag is set, then only that file is loaded. The flag may only be set once and no merging takes place. - 2. If $KUBECONFIG environment variable is set, then it is used a list of paths (normal path delimitting rules for your system). These paths are merged. When a value is modified, it is modified in the file that defines the stanza. When a value is created, it is created in the first file that exists. If no files in the chain exist, then it creates the last file in the list. + 2. If $KUBECONFIG environment variable is set, then it is used as a list of paths (normal path delimitting rules for your system). These paths are merged. When a value is modified, it is modified in the file that defines the stanza. When a value is created, it is created in the first file that exists. If no files in the chain exist, then it creates the last file in the list. 3. Otherwise, ${HOME}/.kube/config is used and no merging takes place. ``` From 9cd582fd7ad285280c3340799a50f1512c69d23f Mon Sep 17 00:00:00 2001 From: Alexander Kanevskiy Date: Fri, 23 Dec 2016 15:40:01 +0200 Subject: [PATCH 019/247] Append note about content and format of /etc/kubernetes/cloud-config. --- docs/admin/kubeadm.md | 3 +++ docs/getting-started-guides/kubeadm.md | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/admin/kubeadm.md b/docs/admin/kubeadm.md index 71095d0577..1014ee1ab6 100644 --- a/docs/admin/kubeadm.md +++ b/docs/admin/kubeadm.md @@ -84,6 +84,9 @@ Valid values are the ones supported by `controller-manager`, namely `"aws"`, the cloud provider, you should create a `/etc/kubernetes/cloud-config` file manually, before running `kubeadm init`. `kubeadm` automatically picks those settings up and ensures other nodes are configured correctly. +The exact format and content of the file `/etc/kubernetes/cloud-config` depends +on the type you specified for `--cloud-provider`; see the appropriate documentation +for your cloud provider for details. You must also set the `--cloud-provider` and `--cloud-config` parameters yourself by editing the `/etc/systemd/system/kubelet.service.d/10-kubeadm.conf` file appropriately. diff --git a/docs/getting-started-guides/kubeadm.md b/docs/getting-started-guides/kubeadm.md index d3ae5a2cad..74d2f18906 100644 --- a/docs/getting-started-guides/kubeadm.md +++ b/docs/getting-started-guides/kubeadm.md @@ -319,8 +319,9 @@ edit the `kubeadm` dropin for the `kubelet` service (`/etc/systemd/system/kubele If your cloud provider requires any extra packages installed on host, for example for volume mounting/unmounting, install those packages. Specify the `--cloud-provider` flag to kubelet and set it to the cloud of your choice. If your cloudprovider requires a configuration -file, create the file `/etc/kubernetes/cloud-config` on every node and set the values your cloud requires. Also append -`--cloud-config=/etc/kubernetes/cloud-config` to the kubelet arguments. +file, create the file `/etc/kubernetes/cloud-config` on every node. The exact format and content of that file depends on the requirements imposed by your cloud provider. +If you use the `/etc/kubernetes/cloud-config` file, you must append it to the `kubelet` arguments as follows: +`--cloud-config=/etc/kubernetes/cloud-config` Lastly, run `kubeadm init --cloud-provider=xxx` to bootstrap your cluster with cloud provider features. From 40841e0e7057851ff98e3468440dc9c3c142135b Mon Sep 17 00:00:00 2001 From: Mayank Kumar Date: Thu, 29 Dec 2016 00:12:50 -0800 Subject: [PATCH 020/247] add title for pod disruption budget --- docs/admin/disruptions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/admin/disruptions.md b/docs/admin/disruptions.md index df94c58cf2..6c4ee7df4a 100644 --- a/docs/admin/disruptions.md +++ b/docs/admin/disruptions.md @@ -1,7 +1,7 @@ --- assignees: - davidopp - +title: Pod Disruption Budget --- This guide is for anyone wishing to specify safety constraints on pods or anyone wishing to write software (typically automation software) that respects those From 8097c494449ef31231e9dd14ba42660bd2df4e3f Mon Sep 17 00:00:00 2001 From: Ritesh H Shukla Date: Thu, 29 Dec 2016 01:00:46 -0800 Subject: [PATCH 021/247] Getting Started vSphere: Minor formatting fixes --- docs/getting-started-guides/vsphere.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/getting-started-guides/vsphere.md b/docs/getting-started-guides/vsphere.md index 343b74dfe3..36372144c6 100644 --- a/docs/getting-started-guides/vsphere.md +++ b/docs/getting-started-guides/vsphere.md @@ -55,9 +55,10 @@ export GOVC_INSECURE=1 govc vm.change -e="disk.enableUUID=1" -vm= ``` -* Provide the cloud config file to each instance of kubelet, apiserver and controller manager via ```--cloud-config=``` flag. Cloud config [template can be found at Kubernetes-Anywhere] (https://github.com/kubernetes/kubernetes-anywhere/blob/master/phase1/vsphere/vsphere.conf) +* Provide the cloud config file to each instance of kubelet, apiserver and controller manager via ```--cloud-config=``` flag. Cloud config [template can be found at Kubernetes-Anywhere](https://github.com/kubernetes/kubernetes-anywhere/blob/master/phase1/vsphere/vsphere.conf) Sample Config: + ``` [Global] user = From a5ebaa54ff525a28c4d18ec3e89e8821a6f30ab8 Mon Sep 17 00:00:00 2001 From: Jared Bischof Date: Thu, 29 Dec 2016 16:34:27 -0600 Subject: [PATCH 022/247] Headless service spec missing attribute The headless service spec example requires the attribute clusterIP: None. Without this, the service that is created is not headless and the two example pods will not be able to nslookup one another. --- docs/admin/dns.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/admin/dns.md b/docs/admin/dns.md index f7536249f4..01f54d9167 100644 --- a/docs/admin/dns.md +++ b/docs/admin/dns.md @@ -100,6 +100,7 @@ metadata: spec: selector: name: busybox + clusterIP: None ports: - name: foo # Actually, no port is needed. port: 1234 From 8f100ece83462b71d35566820ddd598103e70f53 Mon Sep 17 00:00:00 2001 From: James Gregory Date: Fri, 30 Dec 2016 15:54:29 +1100 Subject: [PATCH 023/247] Fix "Deploying applications" link --- docs/tutorials/stateless-application/hello-minikube.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorials/stateless-application/hello-minikube.md b/docs/tutorials/stateless-application/hello-minikube.md index dad7158ac3..8066d34869 100644 --- a/docs/tutorials/stateless-application/hello-minikube.md +++ b/docs/tutorials/stateless-application/hello-minikube.md @@ -297,7 +297,7 @@ minikube stop {% capture whatsnext %} * Learn more about [Deployment objects](/docs/user-guide/deployments/). -* Learn more about [Deploying applications](http://localhost:4000/docs/user-guide/deploying-applications/). +* Learn more about [Deploying applications](/docs/user-guide/deploying-applications/). * Learn more about [Service objects](/docs/user-guide/services/). {% endcapture %} From eb4cbf9ef0aa44e47b96d355f5b196288db3c642 Mon Sep 17 00:00:00 2001 From: Ben Balter Date: Fri, 30 Dec 2016 12:49:42 -0500 Subject: [PATCH 024/247] Don't overwrite the global `page` object when building the table of contents --- _includes/tree.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/_includes/tree.html b/_includes/tree.html index 4aeaeb0176..78505504f1 100644 --- a/_includes/tree.html +++ b/_includes/tree.html @@ -12,9 +12,9 @@ {% assign path = item.path %} {% assign title = item.title %} {% else %} - {% assign page = site.pages | where: "path", item | first %} - {% assign title = page.title %} - {% assign path = page.url %} + {% assign found_page = site.pages | where: "path", item | first %} + {% assign title = found_page.title %} + {% assign path = found_page.url %} {% endif %} {% endcapture %} From f5ad6db8c2be5ef98ea07ea7f75aaf3c349e8026 Mon Sep 17 00:00:00 2001 From: Josh Mize Date: Sat, 31 Dec 2016 06:59:03 -0600 Subject: [PATCH 025/247] Fix #1552: dead link to kube-dns/README.md Fix dead link caused by renaming build-tools back to build in https://github.com/kubernetes/kubernetes/issues/38126 --- docs/admin/dns.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/admin/dns.md b/docs/admin/dns.md index 01f54d9167..0ee1fca395 100644 --- a/docs/admin/dns.md +++ b/docs/admin/dns.md @@ -384,7 +384,7 @@ for more information. ## References -- [Docs for the DNS cluster addon](http://releases.k8s.io/{{page.githubbranch}}/build-tools/kube-dns/README.md) +- [Docs for the DNS cluster addon](http://releases.k8s.io/{{page.githubbranch}}/build/kube-dns/README.md) ## What's next - [Autoscaling the DNS Service in a Cluster](/docs/tasks/administer-cluster/dns-horizontal-autoscaling/). From 1cc17e5fbc2e11c42cfdb2f2047ede8069bb272c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mika=C3=ABl=20Cluseau?= Date: Tue, 3 Jan 2017 08:13:26 +1100 Subject: [PATCH 026/247] fix(#1710): volume behavior is not documented MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Mikaël Cluseau --- docs/user-guide/volumes.md | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/docs/user-guide/volumes.md b/docs/user-guide/volumes.md index f2b5ff88a0..762518fc8f 100644 --- a/docs/user-guide/volumes.md +++ b/docs/user-guide/volumes.md @@ -531,6 +531,39 @@ before you can use it__ See the [Quobyte example](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/volumes/quobyte) for more details. +## Using subPath + +Sometimes, it is useful to share one volume for multiple uses in a single pod. The `volumeMounts.subPath` +property can be used to specify a sub-path inside the referenced volume instead of its root. + +Here is an example of a pod with a LAMP stack (Linux Apache Mysql PHP) using a single, shared volume. +The HTML contents are mapped to its `html` folder, and the databases will be stored in its `mysql` folder: + +```yaml +apiVersion: v1 +kind: Pod +metadata: + name: my-lamp-site +spec: + containers: + - name: mysql + image: mysql + volumeMounts: + - mountPath: /var/lib/mysql + name: site-data + subPath: mysql + - name: php + image: php + volumeMounts: + - mountPath: /var/www/html + name: site-data + subPath: html + volumes: + - name: site-data + persistentVolumeClaim: + claimName: my-lamp-site-data +``` + ## Resources The storage media (Disk, SSD, etc.) of an `emptyDir` volume is determined by the From 6ebd94302d6b758c3f7bc253a96d973573eaba20 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Mon, 2 Jan 2017 23:43:12 -0800 Subject: [PATCH 027/247] Add deprecation policy (#1856) --- docs/deprecation-policy.md | 186 +++++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 docs/deprecation-policy.md diff --git a/docs/deprecation-policy.md b/docs/deprecation-policy.md new file mode 100644 index 0000000000..90ac6ad91d --- /dev/null +++ b/docs/deprecation-policy.md @@ -0,0 +1,186 @@ +--- +assignees: +- bgrant0607 +- lavalamp +- thockin + +--- + +# Kubernetes Deprecation Policy + +Kubernetes is a large system with many components and many contributors.  As +with any such software, the feature set naturally evolves over time, and +sometimes a feature may need to be removed. This could include an API, a flag, +or even an entire feature. To avoid breaking existing users, Kubernetes follows +a deprecation policy for aspects of the system that are slated to be removed. + +This document details the deprecation policy for various facets of the system. + +## Deprecating parts of the API + +Since Kubernetes is an API-driven system, the API has evolved over time to +reflect the evolving understanding of the problem space. The Kubernetes API is +actually a set of APIs, called “API groups”, and each API group is +independently versioned. [API versions](http://kubernetes.io/docs/api/) fall +into 3 main tracks, each of which has different policies for deprecation: + +| Example | Track | +|----------|----------------------------------| +| v1 | GA (generally available, stable) | +| v1beta1 | Beta (pre-release) | +| v1alpha1 | Alpha (experimental) | + +A given release of Kubernetes can support any number of API groups and any +number of versions of each. + +The following rules govern the deprecation of elements of the API.  This +includes: + + * REST resources (aka API objects) + * Fields of REST resources + * Enumerated or constant values + * Component config structures + +These rules are enforced between official releases, not between +arbitrary commits to master or release branches. + +**Rule #1: API elements may only be removed by incrementing the version of the +API group.** + +Once an API element has been added to an API group at a particular version, it +can not be removed from that version or have its behavior significantly +changed, regardless of track. + +Note: For historical reasons, there are 2 “monolithic” API groups - “core” (no +group name) and “extensions”.  Resources will incrementally be moved from these +legacy API groups into more domain-specific API groups. + +**Rule #2: API objects must be able to round-trip between API versions in a given +release without information loss, with the exception of whole REST resources +that do not exist in some versions.** + +For example, an object can be written as v1 and then read back as v2 and +converted to v1, and the resulting v1 resource will be identical to the +original.  The representation in v2 might be different from v1, but the system +knows how to convert between them in both directions. Additionally, any new +field added in v2 must be able to round-trip to v1 and back, which means v1 +might have to add an equivalent field or represent it as an annotation. + +**Rule #3: An API version in a given track may not be deprecated until a new +API version at least as stable is released.** + +GA API versions can replace GA API versions as well as beta and alpha API +version. Beta API versions *may not* replace GA API versions. + +**Rule #4: Other than the most recent API version in each track, older API +versions must be supported after their announced deprecation for a duration of +no less than:** + * **GA: 1 year or 2 releases (whichever is longer)** + * **Beta: 3 months or 1 release (whichever is longer)** + * **Alpha: 0 releases** + +This is best illustrated by example.  Imagine a Kubernetes release, version X, +which supports a particular API group.  A new Kubernetes release is made every +approximately 3 months (4 per year).  The following table describes which API +versions are supported in a series of subsequent releases. + +| Release | API versions | Notes | +|---------|--------------|-------| +| X | v1 | | +| X+1 | v1, v2alpha1 | | +| X+2 | v1, v2alpha2 | * v2alpha1 is removed, “action required” relnote | +| X+3 | v1, v2beta1 | * v2alpha2 is removed, “action required” relnote | +| X+4 | v1, v2beta1, v2beta2 | * v2beta1 is deprecated, “action required” relnote | +| X+5 | v1, v2, v2beta2 | * v2beta1 is removed, “action required” relnote
* v2beta2 is deprecated, “action required” relnote
* v1 is deprecated, “action required” relnote | +| X+6 | v1, v2 | * v2beta2 is removed, “action required” relnote | +| X+7 | v1, v2 | | +| X+8 | v1, v2 | | +| X+9 | v2 | * v1 is removed, “action required” relnote | + +### REST resources (aka API objects) + +Consider a hypothetical REST resource named Widget, which was present in API v1 +in the above timeline, and which needs to be deprecated.  We +[document](http://kubernetes.io/docs/deprecated/) and +[announce](https://groups.google.com/forum/#!forum/kubernetes-announce) the +deprecation in sync with release X+1.  The Widget resource still exists in API +version v1 (deprecated) but not in v2alpha1.  The Widget resource continues to +exist and function in releases up to and including X+8.  Only in release X+9, +when API v1 has aged out, does the Widget resource cease to exist, and the +behavior get removed. + +### Fields of REST resources + +As with whole REST resources, an individual field which was present in API v1 +must exist and function until API v1 is removed.  Unlike whole resources, the +v2 APIs may choose a different representation for the field, as long as it can +be round-tripped.  For example a v1 field named “magnitude” which was +deprecated might be named “deprecatedMagnitude” in API v2.  When v1 is +eventually removed, the deprecated field can be removed from v2. + +### Enumerated or constant values + +As with whole REST resources and fields thereof, a constant value which was +supported in API v1 must exist and function until API v1 is removed. + +### Component config structures + +Component configs are versioned and managed just like REST resources. + +### Future work + +Over time, Kubernetes will introduce more fine-grained API versions, at which +point these rules will be adjusted as needed. + +## Deprecating a flag or CLI + +The Kubernetes system is comprised of several different programs cooperating. +Sometimes, a Kubernetes release might remove flags or CLI commands +(collectively “CLI elements”) in these programs.  The individual programs +naturally sort into two main groups - user-facing and admin-facing programs, +which vary slightly in their deprecation policies.  Unless a flag is explicitly +prefixed or documented as “alpha” or “beta”, it is considered GA. + +CLI elements are effectively part of the API to the system, but since they are +not versioned in the same way as the REST API, the rules for deprecation are as +follows: + +**Rule #5a: CLI elements of user-facing components (e.g. kubectl) must function +after their announced deprecation for no less than:** + * **GA: 1 year or 2 releases (whichever is longer)** + * **Beta: 3 months or 1 release (whichever is longer)** + * **Alpha: 0 releases** + +**Rule #5b: CLI elements of admin-facing components (e.g. kubelet) must function +after their announced deprecation for no less than:** + * **GA: 6 months or 1 release (whichever is longer)** + * **Beta: 3 months or 1 release (whichever is longer)** + * **Alpha: 0 releases** + +**Rule #6: Deprecated CLI elements must emit warnings (optionally disableable) +when used.** + +## Deprecating a feature or behavior + +Occasionally a Kubernetes release needs to deprecate some feature or behavior +of the system that is not controlled by the API or CLI.  In this case, the +rules for deprecation are as follows: + +**Rule #7: Deprecated behaviors must function for no less than 1 year after their +announced deprecation.** + +This does not imply that all changes to the system are governed by this policy. +This applies only to significant, user-visible behaviors which impact the +correctness of applications running on Kubernetes or that impact the +administration of Kubernetes clusters, and which are being removed entirely. + +## Exceptions + +No policy can cover every possible situation.  This policy is a living +document, and will evolve over time.  In practice, there will be situations +that do not fit neatly into this policy, or for which this policy becomes a +serious impediment.  Such situations should be discussed with SIGs and project +leaders to find the best solutions for those specific cases, always bearing in +mind that Kubernetes is committed to being a stable system that, as much as +possible, never breaks users. Exceptions will always be announced in all +relevant release notes. From 476fbee3344bbb2137f0dd58144216d1e11e2677 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Tue, 3 Jan 2017 00:28:28 -0800 Subject: [PATCH 028/247] Convert to pure ASCII (#2110) --- docs/deprecation-policy.md | 58 +++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/docs/deprecation-policy.md b/docs/deprecation-policy.md index 90ac6ad91d..14db737d13 100644 --- a/docs/deprecation-policy.md +++ b/docs/deprecation-policy.md @@ -8,7 +8,7 @@ assignees: # Kubernetes Deprecation Policy -Kubernetes is a large system with many components and many contributors.  As +Kubernetes is a large system with many components and many contributors. As with any such software, the feature set naturally evolves over time, and sometimes a feature may need to be removed. This could include an API, a flag, or even an entire feature. To avoid breaking existing users, Kubernetes follows @@ -20,7 +20,7 @@ This document details the deprecation policy for various facets of the system. Since Kubernetes is an API-driven system, the API has evolved over time to reflect the evolving understanding of the problem space. The Kubernetes API is -actually a set of APIs, called “API groups”, and each API group is +actually a set of APIs, called "API groups", and each API group is independently versioned. [API versions](http://kubernetes.io/docs/api/) fall into 3 main tracks, each of which has different policies for deprecation: @@ -33,7 +33,7 @@ into 3 main tracks, each of which has different policies for deprecation: A given release of Kubernetes can support any number of API groups and any number of versions of each. -The following rules govern the deprecation of elements of the API.  This +The following rules govern the deprecation of elements of the API. This includes: * REST resources (aka API objects) @@ -51,8 +51,8 @@ Once an API element has been added to an API group at a particular version, it can not be removed from that version or have its behavior significantly changed, regardless of track. -Note: For historical reasons, there are 2 “monolithic” API groups - “core” (no -group name) and “extensions”.  Resources will incrementally be moved from these +Note: For historical reasons, there are 2 "monolithic" API groups - "core" (no +group name) and "extensions". Resources will incrementally be moved from these legacy API groups into more domain-specific API groups. **Rule #2: API objects must be able to round-trip between API versions in a given @@ -61,7 +61,7 @@ that do not exist in some versions.** For example, an object can be written as v1 and then read back as v2 and converted to v1, and the resulting v1 resource will be identical to the -original.  The representation in v2 might be different from v1, but the system +original. The representation in v2 might be different from v1, but the system knows how to convert between them in both directions. Additionally, any new field added in v2 must be able to round-trip to v1 and back, which means v1 might have to add an equivalent field or represent it as an annotation. @@ -79,43 +79,43 @@ no less than:** * **Beta: 3 months or 1 release (whichever is longer)** * **Alpha: 0 releases** -This is best illustrated by example.  Imagine a Kubernetes release, version X, -which supports a particular API group.  A new Kubernetes release is made every -approximately 3 months (4 per year).  The following table describes which API +This is best illustrated by example. Imagine a Kubernetes release, version X, +which supports a particular API group. A new Kubernetes release is made every +approximately 3 months (4 per year). The following table describes which API versions are supported in a series of subsequent releases. | Release | API versions | Notes | |---------|--------------|-------| | X | v1 | | | X+1 | v1, v2alpha1 | | -| X+2 | v1, v2alpha2 | * v2alpha1 is removed, “action required” relnote | -| X+3 | v1, v2beta1 | * v2alpha2 is removed, “action required” relnote | -| X+4 | v1, v2beta1, v2beta2 | * v2beta1 is deprecated, “action required” relnote | -| X+5 | v1, v2, v2beta2 | * v2beta1 is removed, “action required” relnote
* v2beta2 is deprecated, “action required” relnote
* v1 is deprecated, “action required” relnote | -| X+6 | v1, v2 | * v2beta2 is removed, “action required” relnote | +| X+2 | v1, v2alpha2 | * v2alpha1 is removed, "action required" relnote | +| X+3 | v1, v2beta1 | * v2alpha2 is removed, "action required" relnote | +| X+4 | v1, v2beta1, v2beta2 | * v2beta1 is deprecated, "action required" relnote | +| X+5 | v1, v2, v2beta2 | * v2beta1 is removed, "action required" relnote
* v2beta2 is deprecated, "action required" relnote
* v1 is deprecated, "action required" relnote | +| X+6 | v1, v2 | * v2beta2 is removed, "action required" relnote | | X+7 | v1, v2 | | | X+8 | v1, v2 | | -| X+9 | v2 | * v1 is removed, “action required” relnote | +| X+9 | v2 | * v1 is removed, "action required" relnote | ### REST resources (aka API objects) Consider a hypothetical REST resource named Widget, which was present in API v1 -in the above timeline, and which needs to be deprecated.  We +in the above timeline, and which needs to be deprecated. We [document](http://kubernetes.io/docs/deprecated/) and [announce](https://groups.google.com/forum/#!forum/kubernetes-announce) the -deprecation in sync with release X+1.  The Widget resource still exists in API -version v1 (deprecated) but not in v2alpha1.  The Widget resource continues to -exist and function in releases up to and including X+8.  Only in release X+9, +deprecation in sync with release X+1. The Widget resource still exists in API +version v1 (deprecated) but not in v2alpha1. The Widget resource continues to +exist and function in releases up to and including X+8. Only in release X+9, when API v1 has aged out, does the Widget resource cease to exist, and the behavior get removed. ### Fields of REST resources As with whole REST resources, an individual field which was present in API v1 -must exist and function until API v1 is removed.  Unlike whole resources, the +must exist and function until API v1 is removed. Unlike whole resources, the v2 APIs may choose a different representation for the field, as long as it can -be round-tripped.  For example a v1 field named “magnitude” which was -deprecated might be named “deprecatedMagnitude” in API v2.  When v1 is +be round-tripped. For example a v1 field named "magnitude" which was +deprecated might be named "deprecatedMagnitude" in API v2. When v1 is eventually removed, the deprecated field can be removed from v2. ### Enumerated or constant values @@ -136,10 +136,10 @@ point these rules will be adjusted as needed. The Kubernetes system is comprised of several different programs cooperating. Sometimes, a Kubernetes release might remove flags or CLI commands -(collectively “CLI elements”) in these programs.  The individual programs +(collectively "CLI elements") in these programs. The individual programs naturally sort into two main groups - user-facing and admin-facing programs, -which vary slightly in their deprecation policies.  Unless a flag is explicitly -prefixed or documented as “alpha” or “beta”, it is considered GA. +which vary slightly in their deprecation policies. Unless a flag is explicitly +prefixed or documented as "alpha" or "beta", it is considered GA. CLI elements are effectively part of the API to the system, but since they are not versioned in the same way as the REST API, the rules for deprecation are as @@ -163,7 +163,7 @@ when used.** ## Deprecating a feature or behavior Occasionally a Kubernetes release needs to deprecate some feature or behavior -of the system that is not controlled by the API or CLI.  In this case, the +of the system that is not controlled by the API or CLI. In this case, the rules for deprecation are as follows: **Rule #7: Deprecated behaviors must function for no less than 1 year after their @@ -176,10 +176,10 @@ administration of Kubernetes clusters, and which are being removed entirely. ## Exceptions -No policy can cover every possible situation.  This policy is a living -document, and will evolve over time.  In practice, there will be situations +No policy can cover every possible situation. This policy is a living +document, and will evolve over time. In practice, there will be situations that do not fit neatly into this policy, or for which this policy becomes a -serious impediment.  Such situations should be discussed with SIGs and project +serious impediment. Such situations should be discussed with SIGs and project leaders to find the best solutions for those specific cases, always bearing in mind that Kubernetes is committed to being a stable system that, as much as possible, never breaks users. Exceptions will always be announced in all From a95cfcddf2c0217b9e8bc90737cca79263f2f371 Mon Sep 17 00:00:00 2001 From: tanshanshan Date: Tue, 3 Jan 2017 16:46:57 +0800 Subject: [PATCH 029/247] replace hack/build-go.sh with make --- docs/admin/multiple-schedulers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/admin/multiple-schedulers.md b/docs/admin/multiple-schedulers.md index eb1c4c44f9..5548f32904 100644 --- a/docs/admin/multiple-schedulers.md +++ b/docs/admin/multiple-schedulers.md @@ -26,7 +26,7 @@ and build the source. ```shell git clone https://github.com/kubernetes/kubernetes.git cd kubernetes -hack/build-go.sh +make ``` Create a container image containing the kube-scheduler binary. Here is the `Dockerfile` From 9e4d2515a44937dbf340c36092790fcd320dc534 Mon Sep 17 00:00:00 2001 From: Daniel Smith Date: Tue, 3 Jan 2017 10:24:15 -0800 Subject: [PATCH 030/247] Remove myself from OWNERS I don't want to block doc changes. --- OWNERS | 1 - 1 file changed, 1 deletion(-) diff --git a/OWNERS b/OWNERS index 247d39ea5e..055a328273 100644 --- a/OWNERS +++ b/OWNERS @@ -1,5 +1,4 @@ assignees: -- lavalamp - smarterclayton - janetkuo - pwittrock From 3ff8fd7a2c0cf7b2df6a2329d3689054eb50dbad Mon Sep 17 00:00:00 2001 From: devin-donnelly Date: Tue, 3 Jan 2017 10:48:19 -0800 Subject: [PATCH 031/247] Update deprecation-policy.md --- docs/deprecation-policy.md | 95 +++++++++++++++++++++++++++++++++----- 1 file changed, 83 insertions(+), 12 deletions(-) diff --git a/docs/deprecation-policy.md b/docs/deprecation-policy.md index 14db737d13..7f7011c6c8 100644 --- a/docs/deprecation-policy.md +++ b/docs/deprecation-policy.md @@ -84,18 +84,89 @@ which supports a particular API group. A new Kubernetes release is made every approximately 3 months (4 per year). The following table describes which API versions are supported in a series of subsequent releases. -| Release | API versions | Notes | -|---------|--------------|-------| -| X | v1 | | -| X+1 | v1, v2alpha1 | | -| X+2 | v1, v2alpha2 | * v2alpha1 is removed, "action required" relnote | -| X+3 | v1, v2beta1 | * v2alpha2 is removed, "action required" relnote | -| X+4 | v1, v2beta1, v2beta2 | * v2beta1 is deprecated, "action required" relnote | -| X+5 | v1, v2, v2beta2 | * v2beta1 is removed, "action required" relnote
* v2beta2 is deprecated, "action required" relnote
* v1 is deprecated, "action required" relnote | -| X+6 | v1, v2 | * v2beta2 is removed, "action required" relnote | -| X+7 | v1, v2 | | -| X+8 | v1, v2 | | -| X+9 | v2 | * v1 is removed, "action required" relnote | + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ReleaseAPI VersionsNotes
Xv1
X+1v1, v2alpha1
X+2v1, v2alpha2 +
    +
  • v2alpha1 is removed, "action required" relnote
  • +
+
X+3v1, v2beta1 +
    +
  • v2alpha2 is removed, "action required" relnote
  • +
+
X+4v1, v2beta1, v2beta2 +
    +
  • v2beta1 is deprecated, "action required" relnote
  • +
+
X+5v1, v2, v2beta2 +
    +
  • v2beta1 is removed, "action required" relnote
  • +
  • v2beta2 is deprecated, "action required" relnote
  • +
  • v1 is deprecated, "action required" relnote
  • +
+
X+6v1, v2 +
    +
  • v2beta2 is removed, "action required" relnote
  • +
+
X+7v1, v2
X+8v1, v2
X+9v1, v2 +
    +
  • v1 is removed, "action required" relnote
  • +
+
### REST resources (aka API objects) From 31bcde91223e6254cdf92e52c4078ffd63151659 Mon Sep 17 00:00:00 2001 From: devin-donnelly Date: Tue, 3 Jan 2017 10:55:16 -0800 Subject: [PATCH 032/247] Update deprecation-policy.md --- docs/deprecation-policy.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/deprecation-policy.md b/docs/deprecation-policy.md index 7f7011c6c8..dbc999a0c7 100644 --- a/docs/deprecation-policy.md +++ b/docs/deprecation-policy.md @@ -6,8 +6,6 @@ assignees: --- -# Kubernetes Deprecation Policy - Kubernetes is a large system with many components and many contributors. As with any such software, the feature set naturally evolves over time, and sometimes a feature may need to be removed. This could include an API, a flag, From 0f462317ca3611b8c68210419d2f828db7cc9fe7 Mon Sep 17 00:00:00 2001 From: devin-donnelly Date: Tue, 3 Jan 2017 10:58:59 -0800 Subject: [PATCH 033/247] Update deprecation-policy.md --- docs/deprecation-policy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/deprecation-policy.md b/docs/deprecation-policy.md index dbc999a0c7..fb17613ca1 100644 --- a/docs/deprecation-policy.md +++ b/docs/deprecation-policy.md @@ -3,7 +3,7 @@ assignees: - bgrant0607 - lavalamp - thockin - +title: Kubernetes Deprecation Policy --- Kubernetes is a large system with many components and many contributors. As From 8879175f851a8b914e345fa189e96e4fa00f7351 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Tue, 3 Jan 2017 12:37:15 -0800 Subject: [PATCH 035/247] Use thead/tbody style for manual table --- docs/deprecation-policy.md | 166 +++++++++++++++++++------------------ 1 file changed, 85 insertions(+), 81 deletions(-) diff --git a/docs/deprecation-policy.md b/docs/deprecation-policy.md index fb17613ca1..bd7645ea49 100644 --- a/docs/deprecation-policy.md +++ b/docs/deprecation-policy.md @@ -83,87 +83,91 @@ approximately 3 months (4 per year). The following table describes which API versions are supported in a series of subsequent releases. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
ReleaseAPI VersionsNotes
Xv1
X+1v1, v2alpha1
X+2v1, v2alpha2 -
    -
  • v2alpha1 is removed, "action required" relnote
  • -
-
X+3v1, v2beta1 -
    -
  • v2alpha2 is removed, "action required" relnote
  • -
-
X+4v1, v2beta1, v2beta2 -
    -
  • v2beta1 is deprecated, "action required" relnote
  • -
-
X+5v1, v2, v2beta2 -
    -
  • v2beta1 is removed, "action required" relnote
  • -
  • v2beta2 is deprecated, "action required" relnote
  • -
  • v1 is deprecated, "action required" relnote
  • -
-
X+6v1, v2 -
    -
  • v2beta2 is removed, "action required" relnote
  • -
-
X+7v1, v2
X+8v1, v2
X+9v1, v2 -
    -
  • v1 is removed, "action required" relnote
  • -
-
ReleaseAPI VersionsNotes
Xv1
X+1v1, v2alpha1
X+2v1, v2alpha2 +
    +
  • v2alpha1 is removed, "action required" relnote
  • +
+
X+3v1, v2beta1 +
    +
  • v2alpha2 is removed, "action required" relnote
  • +
+
X+4v1, v2beta1, v2beta2 +
    +
  • v2beta1 is deprecated, "action required" relnote
  • +
+
X+5v1, v2, v2beta2 +
    +
  • v2beta1 is removed, "action required" relnote
  • +
  • v2beta2 is deprecated, "action required" relnote
  • +
  • v1 is deprecated, "action required" relnote
  • +
+
X+6v1, v2 +
    +
  • v2beta2 is removed, "action required" relnote
  • +
+
X+7v1, v2
X+8v1, v2
X+9v1, v2 +
    +
  • v1 is removed, "action required" relnote
  • +
+
### REST resources (aka API objects) From 20c51c8c96c30c662855cad754cfc8ca50f30643 Mon Sep 17 00:00:00 2001 From: Elijah Caine Date: Tue, 3 Jan 2017 12:57:40 -0800 Subject: [PATCH 036/247] ReplicaSets: Correct paragraph spacing error --- docs/user-guide/replicasets.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/user-guide/replicasets.md b/docs/user-guide/replicasets.md index 769ea58c02..ea3e7bde14 100644 --- a/docs/user-guide/replicasets.md +++ b/docs/user-guide/replicasets.md @@ -37,7 +37,6 @@ their ReplicaSets. A ReplicaSet ensures that a specified number of pod “replicas” are running at any given time. However, a Deployment is a higher-level concept that manages ReplicaSets and - provides declarative updates to pods along with a lot of other useful features. Therefore, we recommend using Deployments instead of directly using ReplicaSets, unless you require custom update orchestration or don't require updates at all. From 70a269dd65d52a86573e8c753060b2cb557df0c7 Mon Sep 17 00:00:00 2001 From: devin-donnelly Date: Tue, 3 Jan 2017 14:02:18 -0800 Subject: [PATCH 037/247] Update support.yml --- _data/support.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/_data/support.yml b/_data/support.yml index efb049ccb1..ca1c96819a 100644 --- a/_data/support.yml +++ b/_data/support.yml @@ -39,3 +39,5 @@ toc: path: https://github.com/kubernetes/kubernetes/releases/ - title: Release Roadmap path: https://github.com/kubernetes/kubernetes/milestones/ + - title: Deprecation Policy + path: docs/deprecation-policy.md From 1a7a8b9ce0a2689919036730b8d227255d37c1d1 Mon Sep 17 00:00:00 2001 From: devin-donnelly Date: Tue, 3 Jan 2017 14:09:49 -0800 Subject: [PATCH 038/247] Update support.yml --- _data/support.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/_data/support.yml b/_data/support.yml index ca1c96819a..68142ca44c 100644 --- a/_data/support.yml +++ b/_data/support.yml @@ -40,4 +40,4 @@ toc: - title: Release Roadmap path: https://github.com/kubernetes/kubernetes/milestones/ - title: Deprecation Policy - path: docs/deprecation-policy.md + path: /docs/deprecation-policy.md From 611f07ba03938ce2afd0af4ae79423bf726a8f99 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Tue, 3 Jan 2017 14:11:48 -0800 Subject: [PATCH 039/247] Newline required before bullet-lists --- docs/deprecation-policy.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/deprecation-policy.md b/docs/deprecation-policy.md index bd7645ea49..d349e6c0b9 100644 --- a/docs/deprecation-policy.md +++ b/docs/deprecation-policy.md @@ -73,6 +73,7 @@ version. Beta API versions *may not* replace GA API versions. **Rule #4: Other than the most recent API version in each track, older API versions must be supported after their announced deprecation for a duration of no less than:** + * **GA: 1 year or 2 releases (whichever is longer)** * **Beta: 3 months or 1 release (whichever is longer)** * **Alpha: 0 releases** @@ -220,12 +221,14 @@ follows: **Rule #5a: CLI elements of user-facing components (e.g. kubectl) must function after their announced deprecation for no less than:** + * **GA: 1 year or 2 releases (whichever is longer)** * **Beta: 3 months or 1 release (whichever is longer)** * **Alpha: 0 releases** **Rule #5b: CLI elements of admin-facing components (e.g. kubelet) must function after their announced deprecation for no less than:** + * **GA: 6 months or 1 release (whichever is longer)** * **Beta: 3 months or 1 release (whichever is longer)** * **Alpha: 0 releases** From 01caaf43cf15fc94d18bcc7147982253ec78888d Mon Sep 17 00:00:00 2001 From: devin-donnelly Date: Tue, 3 Jan 2017 14:21:45 -0800 Subject: [PATCH 040/247] Update support.yml --- _data/support.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/_data/support.yml b/_data/support.yml index 68142ca44c..8647d1456d 100644 --- a/_data/support.yml +++ b/_data/support.yml @@ -39,5 +39,6 @@ toc: path: https://github.com/kubernetes/kubernetes/releases/ - title: Release Roadmap path: https://github.com/kubernetes/kubernetes/milestones/ - - title: Deprecation Policy - path: /docs/deprecation-policy.md + +- title: Deprecation Policy + path: /docs/deprecation-policy.md From 9300e36e564c90f1110a321554251de4691f8f27 Mon Sep 17 00:00:00 2001 From: Aaron Signorelli Date: Wed, 4 Jan 2017 00:38:40 +0000 Subject: [PATCH 041/247] Fixing typo .PONY -> .PHONY --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 64ceef89a0..3657cb577a 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PONY: all build build-preview help serve +.PHONY: all build build-preview help serve help: ## Show this help. @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {sub("\\\\n",sprintf("\n%22c"," "), $$2);printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) From b8b448fb63946bc8500cb5efa4250ad2a45cf3ef Mon Sep 17 00:00:00 2001 From: chentao1596 Date: Wed, 4 Jan 2017 09:16:51 +0800 Subject: [PATCH 042/247] change the flag which controlls the cbr0's create --- docs/admin/networking.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/admin/networking.md b/docs/admin/networking.md index e1de39fdbd..84e612bfdd 100644 --- a/docs/admin/networking.md +++ b/docs/admin/networking.md @@ -130,7 +130,7 @@ We start Docker with: DOCKER_OPTS="--bridge=cbr0 --iptables=false --ip-masq=false" ``` -This bridge is created by Kubelet (controlled by the `--configure-cbr0=true` +This bridge is created by Kubelet (controlled by the `--network-plugin=kubenet` flag) according to the `Node`'s `spec.podCIDR`. Docker will now allocate IPs from the `cbr-cidr` block. Containers can reach From ce6da11e11a9f36438cedf361335f68de21b5146 Mon Sep 17 00:00:00 2001 From: Peter Lee Date: Tue, 3 Jan 2017 10:24:54 +0800 Subject: [PATCH 043/247] fix typo 'ips' should be 'IPs' --- docs/user-guide/ingress.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/user-guide/ingress.md b/docs/user-guide/ingress.md index e0bebc4795..b9c371e2a1 100644 --- a/docs/user-guide/ingress.md +++ b/docs/user-guide/ingress.md @@ -107,7 +107,7 @@ Where `107.178.254.228` is the IP allocated by the Ingress controller to satisfy ### Simple fanout -As described previously, pods within kubernetes have ips only visible on the cluster network, so we need something at the edge accepting ingress traffic and proxying it to the right endpoints. This component is usually a highly available loadbalancer/s. An Ingress allows you to keep the number of loadbalancers down to a minimum, for example, a setup like: +As described previously, pods within kubernetes have IPs only visible on the cluster network, so we need something at the edge accepting ingress traffic and proxying it to the right endpoints. This component is usually a highly available loadbalancer/s. An Ingress allows you to keep the number of loadbalancers down to a minimum, for example, a setup like: ```shell foo.bar.com -> 178.91.123.132 -> / foo s1:80 From 2b386047e88b480ea2c4b58dd2ff2c6e2f0c6bfd Mon Sep 17 00:00:00 2001 From: Mik Vyatskov Date: Wed, 4 Jan 2017 14:00:22 +0100 Subject: [PATCH 044/247] Add cluster-level logging overview --- _data/guides.yml | 7 +- _data/support.yml | 1 - docs/admin/cluster-components.md | 11 +- docs/admin/index.md | 3 +- docs/getting-started-guides/gce.md | 2 +- docs/getting-started-guides/scratch.md | 8 +- docs/user-guide/docker-cli-to-kubectl.md | 2 +- docs/user-guide/index.md | 2 +- .../user-guide/introspection-and-debugging.md | 2 +- docs/user-guide/logging-demo/Makefile | 40 ------- docs/user-guide/logging-demo/OWNERS | 3 - docs/user-guide/logging-demo/README.md | 12 -- .../logging-demo/synthetic_0_25lps.yaml | 30 ----- .../logging-demo/synthetic_10lps.yaml | 30 ----- docs/user-guide/logging.md | 80 ------------- .../logging}/counter-pod.yaml | 0 .../logging/elasticsearch.md} | 18 +-- docs/user-guide/logging/overview.md | 107 ++++++++++++++++++ .../logging/stackdriver.md} | 48 ++++---- docs/user-guide/production-pods.md | 2 +- docs/whatisk8s.md | 2 +- .../logging/logging-from-application.png | Bin 0 -> 19696 bytes .../user-guide/logging/logging-node-level.png | Bin 0 -> 20164 bytes .../logging/logging-with-node-agent.png | Bin 0 -> 38071 bytes .../logging/logging-with-sidecar.png | Bin 0 -> 25512 bytes test/examples_test.go | 4 - 26 files changed, 159 insertions(+), 255 deletions(-) delete mode 100644 docs/user-guide/logging-demo/Makefile delete mode 100644 docs/user-guide/logging-demo/OWNERS delete mode 100644 docs/user-guide/logging-demo/README.md delete mode 100644 docs/user-guide/logging-demo/synthetic_0_25lps.yaml delete mode 100644 docs/user-guide/logging-demo/synthetic_10lps.yaml delete mode 100644 docs/user-guide/logging.md rename docs/{getting-started-guides => user-guide/logging}/counter-pod.yaml (100%) rename docs/{getting-started-guides/logging-elasticsearch.md => user-guide/logging/elasticsearch.md} (89%) create mode 100644 docs/user-guide/logging/overview.md rename docs/{getting-started-guides/logging.md => user-guide/logging/stackdriver.md} (64%) create mode 100644 images/docs/user-guide/logging/logging-from-application.png create mode 100644 images/docs/user-guide/logging/logging-node-level.png create mode 100644 images/docs/user-guide/logging/logging-with-node-agent.png create mode 100644 images/docs/user-guide/logging/logging-with-sidecar.png diff --git a/_data/guides.yml b/_data/guides.yml index 388f77289d..bb271a6183 100644 --- a/_data/guides.yml +++ b/_data/guides.yml @@ -84,8 +84,11 @@ toc: - title: Monitoring, Logging, and Debugging Containers section: - docs/user-guide/monitoring.md - - docs/getting-started-guides/logging.md - - docs/getting-started-guides/logging-elasticsearch.md + - title: Logging + section: + - docs/user-guide/logging/overview.md + - docs/user-guide/logging/stackdriver.md + - docs/user-guide/logging/elasticsearch.md - docs/user-guide/getting-into-containers.md - docs/user-guide/connecting-to-applications-proxy.md - docs/user-guide/connecting-to-applications-port-forward.md diff --git a/_data/support.yml b/_data/support.yml index 8647d1456d..3f3145fad0 100644 --- a/_data/support.yml +++ b/_data/support.yml @@ -16,7 +16,6 @@ toc: section: - docs/user-guide/debugging-pods-and-replication-controllers.md - docs/user-guide/introspection-and-debugging.md - - docs/user-guide/logging.md - docs/user-guide/application-troubleshooting.md - docs/admin/cluster-troubleshooting.md - docs/user-guide/debugging-services.md diff --git a/docs/admin/cluster-components.md b/docs/admin/cluster-components.md index aa79489bbb..8519a199f4 100644 --- a/docs/admin/cluster-components.md +++ b/docs/admin/cluster-components.md @@ -91,15 +91,8 @@ about containers in a central database, and provides a UI for browsing that data #### Cluster-level Logging -[Container Logging](/docs/user-guide/monitoring) saves container logs -to a central log store with search/browsing interface. There are two -implementations: - -* [Cluster-level logging to Google Cloud Logging]( -/docs/user-guide/logging/#cluster-level-logging-to-google-cloud-logging) - -* [Cluster-level Logging with Elasticsearch and Kibana]( -/docs/getting-started-guides/logging-elasticsearch/) +A [Cluster-level logging](/docs/user-guide/logging/overview) mechanism is responsible for +saving container logs to a central log store with search/browsing interface. ## Node components diff --git a/docs/admin/index.md b/docs/admin/index.md index 68b669cc10..d4111691c6 100644 --- a/docs/admin/index.md +++ b/docs/admin/index.md @@ -61,7 +61,8 @@ project](/docs/admin/salt). * **DNS Integration with SkyDNS** ([dns.md](/docs/admin/dns)): Resolving a DNS name directly to a Kubernetes service. -* **Logging** with [Kibana](/docs/user-guide/logging) +* [**Cluster-level logging**](/docs/user-guide/logging/overview) + Saving container logs to a central log store with search/browsing interface. ## Multi-tenant support diff --git a/docs/getting-started-guides/gce.md b/docs/getting-started-guides/gce.md index 29388ceb9a..245de295f9 100644 --- a/docs/getting-started-guides/gce.md +++ b/docs/getting-started-guides/gce.md @@ -46,7 +46,7 @@ wget -q -O - https://get.k8s.io | bash Once this command completes, you will have a master VM and four worker VMs, running as a Kubernetes cluster. -By default, some containers will already be running on your cluster. Containers like `fluentd` provide [logging](/docs/getting-started-guides/logging), while `heapster` provides [monitoring](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/cluster-monitoring/README.md) services. +By default, some containers will already be running on your cluster. Containers like `fluentd` provide [logging](/docs/user-guide/logging/overview), while `heapster` provides [monitoring](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/cluster-monitoring/README.md) services. The script run by the commands above creates a cluster with the name/prefix "kubernetes". It defines one specific cluster config, so you can't run it more than once. diff --git a/docs/getting-started-guides/scratch.md b/docs/getting-started-guides/scratch.md index 44ff8112c6..9b53e28e78 100644 --- a/docs/getting-started-guides/scratch.md +++ b/docs/getting-started-guides/scratch.md @@ -826,11 +826,9 @@ Notes for setting up each cluster service are given below: * [Setup instructions](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/dns/) * [Admin Guide](/docs/admin/dns/) * Cluster-level Logging - * Multiple implementations with different storage backends and UIs. - * [Elasticsearch Backend Setup Instructions](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/fluentd-elasticsearch/) - * [Google Cloud Logging Backend Setup Instructions](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/fluentd-gcp/). - * Both require running fluentd on each node. - * [User Guide](/docs/user-guide/logging/) + * [Cluster-level Logging Overview](/docs/user-guide/logging/overview) + * [Cluster-level Logging with Elasticsearch](/docs/user-guide/logging/elasticsearch) + * [Cluster-level Logging with Stackdriver Logging](/docs/user-guide/logging/stackdriver) * Container Resource Monitoring * [Setup instructions](http://releases.k8s.io/{{page.githubbranch}}/cluster/addons/cluster-monitoring/) * GUI diff --git a/docs/user-guide/docker-cli-to-kubectl.md b/docs/user-guide/docker-cli-to-kubectl.md index 152810e45c..8b92682874 100644 --- a/docs/user-guide/docker-cli-to-kubectl.md +++ b/docs/user-guide/docker-cli-to-kubectl.md @@ -172,7 +172,7 @@ $ kubectl logs --previous nginx-app-zibvs 10.240.63.110 - - [14/Jul/2015:01:09:02 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.26.0" "-" ``` -See [Logging](/docs/user-guide/logging) for more information. +See [Logging Overview](/docs/user-guide/logging/overview) for more information. #### docker stop and docker rm diff --git a/docs/user-guide/index.md b/docs/user-guide/index.md index 394aa3d131..9c69683525 100644 --- a/docs/user-guide/index.md +++ b/docs/user-guide/index.md @@ -22,7 +22,7 @@ The following topics in the Kubernetes User Guide can help you run applications 1. [Managing deployments](/docs/user-guide/managing-deployments/) 1. [Application introspection and debugging](/docs/user-guide/introspection-and-debugging/) 1. [Using the Kubernetes web user interface](/docs/user-guide/ui/) - 1. [Logging](/docs/user-guide/logging/) + 1. [Logging](/docs/user-guide/logging/overview/) 1. [Monitoring](/docs/user-guide/monitoring/) 1. [Getting into containers via `exec`](/docs/user-guide/getting-into-containers/) 1. [Connecting to containers via proxies](/docs/user-guide/connecting-to-applications-proxy/) diff --git a/docs/user-guide/introspection-and-debugging.md b/docs/user-guide/introspection-and-debugging.md index a8ff5351f5..47d1293900 100644 --- a/docs/user-guide/introspection-and-debugging.md +++ b/docs/user-guide/introspection-and-debugging.md @@ -347,7 +347,7 @@ status: Learn about additional debugging tools, including: -* [Logging](/docs/user-guide/logging) +* [Logging](/docs/user-guide/logging/overview) * [Monitoring](/docs/user-guide/monitoring) * [Getting into containers via `exec`](/docs/user-guide/getting-into-containers) * [Connecting to containers via proxies](/docs/user-guide/connecting-to-applications-proxy) diff --git a/docs/user-guide/logging-demo/Makefile b/docs/user-guide/logging-demo/Makefile deleted file mode 100644 index 90917f8ade..0000000000 --- a/docs/user-guide/logging-demo/Makefile +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2016 The Kubernetes Authors All rights reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Makefile for launching synthetic logging sources (any platform) -# and for reporting the forwarding rules for the -# Elasticsearch and Kibana pods for the GCE platform. -# For examples of how to observe the ingested logs please -# see the appropriate getting started guide e.g. -# Google Cloud Logging: http://kubernetes.io/docs/getting-started-guides/logging/ -# With Elasticsearch and Kibana logging: http://kubernetes.io/docs/getting-started-guides/logging-elasticsearch/ - -.PHONY: up down logger-up logger-down logger10-up logger10-down - -up: logger-up logger10-up - -down: logger-down logger10-down - -logger-up: - kubectl create -f synthetic_0_25lps.yaml - -logger-down: - kubectl delete pod synthetic-logger-0.25lps-pod - -logger10-up: - kubectl create -f synthetic_10lps.yaml - -logger10-down: - kubectl delete pod synthetic-logger-10lps-pod - diff --git a/docs/user-guide/logging-demo/OWNERS b/docs/user-guide/logging-demo/OWNERS deleted file mode 100644 index 9451be867c..0000000000 --- a/docs/user-guide/logging-demo/OWNERS +++ /dev/null @@ -1,3 +0,0 @@ -assignees: -- mikedanese - diff --git a/docs/user-guide/logging-demo/README.md b/docs/user-guide/logging-demo/README.md deleted file mode 100644 index d657947ec7..0000000000 --- a/docs/user-guide/logging-demo/README.md +++ /dev/null @@ -1,12 +0,0 @@ -This directory contains two [pod](https://kubernetes.io/docs/user-guide/pods) specifications which can be used as synthetic -logging sources. The pod specification in [synthetic_0_25lps.yaml](synthetic_0_25lps.yaml) -describes a pod that just emits a log message once every 4 seconds. The pod specification in -[synthetic_10lps.yaml](synthetic_10lps.yaml) -describes a pod that just emits 10 log lines per second. - -See [logging document](https://kubernetes.io/docs/user-guide/logging/) for more details about logging. To observe the ingested log lines when using Google Cloud Logging please see the getting -started instructions -at [Cluster Level Logging to Google Cloud Logging](https://kubernetes.io/docs/getting-started-guides/logging). -To observe the ingested log lines when using Elasticsearch and Kibana please see the getting -started instructions -at [Cluster Level Logging with Elasticsearch and Kibana](https://kubernetes.io/docs/getting-started-guides/logging-elasticsearch). diff --git a/docs/user-guide/logging-demo/synthetic_0_25lps.yaml b/docs/user-guide/logging-demo/synthetic_0_25lps.yaml deleted file mode 100644 index 93516706c0..0000000000 --- a/docs/user-guide/logging-demo/synthetic_0_25lps.yaml +++ /dev/null @@ -1,30 +0,0 @@ -# This pod specification creates an instance of a synthetic logger. The logger -# is simply a program that writes out the hostname of the pod, a count which increments -# by one on each iteration (to help notice missing log enteries) and the date using -# a long format (RFC-3339) to nano-second precision. This program logs at a frequency -# of 0.25 lines per second. The shellscript program is given directly to bash as -c argument -# and could have been written out as: -# i="0" -# while true -# do -# echo -n "`hostname`: $i: " -# date --rfc-3339 ns -# sleep 4 -# i=$[$i+1] -# done -apiVersion: v1 -kind: Pod -metadata: - labels: - name: synth-logging-source - name: synthetic-logger-0.25lps-pod -spec: - containers: - - name: synth-lgr - image: ubuntu:14.04 - args: - - bash - - -c - - 'i="0"; while true; do echo -n "`hostname`: $i: "; date --rfc-3339 ns; sleep - 4; i=$[$i+1]; done' - diff --git a/docs/user-guide/logging-demo/synthetic_10lps.yaml b/docs/user-guide/logging-demo/synthetic_10lps.yaml deleted file mode 100644 index 6e3c1ca929..0000000000 --- a/docs/user-guide/logging-demo/synthetic_10lps.yaml +++ /dev/null @@ -1,30 +0,0 @@ -# This pod specification creates an instance of a synthetic logger. The logger -# is simply a program that writes out the hostname of the pod, a count which increments -# by one on each iteration (to help notice missing log enteries) and the date using -# a long format (RFC-3339) to nano-second precision. This program logs at a frequency -# of 0.25 lines per second. The shellscript program is given directly to bash as -c argument -# and could have been written out as: -# i="0" -# while true -# do -# echo -n "`hostname`: $i: " -# date --rfc-3339 ns -# sleep 4 -# i=$[$i+1] -# done -apiVersion: v1 -kind: Pod -metadata: - labels: - name: synth-logging-source - name: synthetic-logger-10lps-pod -spec: - containers: - - name: synth-lgr - image: ubuntu:14.04 - args: - - bash - - -c - - 'i="0"; while true; do echo -n "`hostname`: $i: "; date --rfc-3339 ns; sleep - 0.1; i=$[$i+1]; done' - diff --git a/docs/user-guide/logging.md b/docs/user-guide/logging.md deleted file mode 100644 index 5df73928e0..0000000000 --- a/docs/user-guide/logging.md +++ /dev/null @@ -1,80 +0,0 @@ ---- -assignees: -- mikedanese -title: Retrieving Logs ---- - -This page is designed to help you use logs to troubleshoot issues with your Kubernetes solution. - -## Logging by Kubernetes Components - -Kubernetes components, such as kubelet and apiserver, use the [glog](https://godoc.org/github.com/golang/glog) logging library. Developer conventions for logging severity are described in [docs/devel/logging.md](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/docs/devel/logging.md). - -## Examining the logs of running containers - -The logs of a running container may be fetched using the command `kubectl logs`. For example, given -this pod specification [counter-pod.yaml](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/blog-logging/counter-pod.yaml), which has a container which writes out some text to standard -output every second. (You can find different pod specifications [here](https://github.com/kubernetes/kubernetes.github.io/tree/{{page.docsbranch}}/docs/user-guide/logging-demo/).) - -{% include code.html language="yaml" file="counter-pod.yaml" k8slink="/examples/blog-logging/counter-pod.yaml" %} - -we can run the pod: - -```shell -$ kubectl create -f ./counter-pod.yaml -pods/counter -``` - -and then fetch the logs: - -```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 -... -``` - -If a pod has more than one container then you need to specify which container's log files should -be fetched e.g. - -```shell -$ kubectl logs kube-dns-v3-7r1l9 etcd -2015/06/23 00:43:10 etcdserver: start to snapshot (applied: 30003, lastsnap: 20002) -2015/06/23 00:43:10 etcdserver: compacted log at index 30003 -2015/06/23 00:43:10 etcdserver: saved snapshot at index 30003 -2015/06/23 02:05:42 etcdserver: start to snapshot (applied: 40004, lastsnap: 30003) -2015/06/23 02:05:42 etcdserver: compacted log at index 40004 -2015/06/23 02:05:42 etcdserver: saved snapshot at index 40004 -2015/06/23 03:28:31 etcdserver: start to snapshot (applied: 50005, lastsnap: 40004) -2015/06/23 03:28:31 etcdserver: compacted log at index 50005 -2015/06/23 03:28:31 etcdserver: saved snapshot at index 50005 -2015/06/23 03:28:56 filePurge: successfully removed file default.etcd/member/wal/0000000000000000-0000000000000000.wal -2015/06/23 04:51:03 etcdserver: start to snapshot (applied: 60006, lastsnap: 50005) -2015/06/23 04:51:03 etcdserver: compacted log at index 60006 -2015/06/23 04:51:03 etcdserver: saved snapshot at index 60006 -... -``` - -## Cluster level logging to Google Cloud Logging - -The getting started guide [Cluster Level Logging to Google Cloud Logging](/docs/getting-started-guides/logging) -explains how container logs are ingested into [Google Cloud Logging](https://cloud.google.com/logging/docs/) -and shows how to query the ingested logs. - -## Cluster level logging with Elasticsearch and Kibana - -The getting started guide [Cluster Level Logging with Elasticsearch and Kibana](/docs/getting-started-guides/logging-elasticsearch) -describes how to ingest cluster level logs into Elasticsearch and view them using Kibana. - -## Ingesting Application Log Files - -Cluster level logging only collects the standard output and standard error output of the applications -running in containers. The guide [Collecting log files from within containers with Fluentd and sending them to the Google Cloud Logging service](https://github.com/kubernetes/contrib/blob/master/logging/fluentd-sidecar-gcp/README.md) explains how the log files of applications can also be ingested into Google Cloud logging. - -## Known issues - -Kubernetes does log rotation for Kubernetes components and docker containers. The command `kubectl logs` currently only read the latest logs, not all historical ones. \ No newline at end of file diff --git a/docs/getting-started-guides/counter-pod.yaml b/docs/user-guide/logging/counter-pod.yaml similarity index 100% rename from docs/getting-started-guides/counter-pod.yaml rename to docs/user-guide/logging/counter-pod.yaml diff --git a/docs/getting-started-guides/logging-elasticsearch.md b/docs/user-guide/logging/elasticsearch.md similarity index 89% rename from docs/getting-started-guides/logging-elasticsearch.md rename to docs/user-guide/logging/elasticsearch.md index 86fce1f02a..c61cfd7cd1 100644 --- a/docs/getting-started-guides/logging-elasticsearch.md +++ b/docs/user-guide/logging/elasticsearch.md @@ -1,18 +1,18 @@ --- assignees: -- lavalamp -- satnam6502 +- crassirostris +- piosz title: Logging with Elasticsearch and Kibana --- On the Google Compute Engine (GCE) platform, the default logging support targets -[Google Cloud Logging](https://cloud.google.com/logging/) as described in the -[Logging](/docs/getting-started-guides/logging) getting-started guide. Here we -describe how to set up a cluster to ingest logs into -[Elasticsearch](https://github.com/elastic/elasticsearch) and view -them using [Kibana](https://github.com/elastic/kibana) as an alternative to -Google Cloud Logging when running on GCE (note that this will not work as -written for Google Container Engine). +[Stackdriver Logging](https://cloud.google.com/logging/), which is described in detail +in the [Logging With Stackdriver Logging](/docs/user-guide/logging/stackdriver). + +This article describes how to set up a cluster to ingest logs into +[Elasticsearch](https://www.elastic.co/products/elasticsearch), and view +them using [Kibana](https://www.elastic.co/products/kibana), as an alternative to +Stackdriver Logging when running on GCE. Note that Elasticsearch and Kibana do not work with Kubernetes clusters hosted on Google Container Engine. To use Elasticsearch and Kibana for cluster logging, you should set the following environment variable as shown below when creating your cluster with diff --git a/docs/user-guide/logging/overview.md b/docs/user-guide/logging/overview.md new file mode 100644 index 0000000000..e1ac4885be --- /dev/null +++ b/docs/user-guide/logging/overview.md @@ -0,0 +1,107 @@ +--- +assignees: +- crassirostris +- piosz +title: Logging Overview +--- + +Application and systems logs can help you understand what is happening inside your cluster. The logs are particularly useful for debugging problems and monitoring cluster activity. Most modern applications have some kind of logging mechanism; as such, most container engines are likewise designed to support some kind of logging. The easiest and most embraced logging method for containerized applications is to write to the standard output and standard error streams. + +However, the native functionality provided by a container engine or runtime is usually not enough for a complete logging solution. For example, if a container crashes, a pod is evicted, or a node dies, you'll usually still want to access your application's logs. As such, logs should have a separate storage and lifecycle independent of nodes, pods, or containers; this concept is called __cluster-level-logging__. Cluster-level logging requires a separate back-end to store, analyze, and query logs. Kubernetes provides no native storage solution for logs data, but you can integrate many existing logging solutions into your Kubernetes cluster. + +In this document, you can find: + +* A basic demonstration of logging in Kubernetes using the standard output stream +* A detailed description of the node logging architecture in Kubernetes +* Guidance for implementing cluster-level logging in Kubernetes + +The guidance for cluster-level logging assumes that a logging back-end is present inside or outside of your cluster. If you're not interested in having cluster-level logging, you might still find the description how logs are stored and handled on the node to be useful. + +## Basic logging in Kubernetes + +In this section, you can see an example of basic logging in Kubernetes that outputs data to the standard output stream. This demonstration uses a [pod specification](/docs/user-guide/logging/counter-pod.yaml) with a container that writes some text to standard output once per second. + +{% include code.html language="yaml" file="counter-pod.yaml" %} + +To run this pod, use the following command: + +```shell +$ kubectl create -f counter-pod.yaml +pod "counter" created +``` + +To fetch the logs, use the `kubectl logs` command, as follows + +```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 +... +``` + +You can use `kubectl logs` to retrieve logs from a previous instantiation of a container with `--previous` flag, in case the container has crashed. If your pod has multiple containers, you should specify which container's logs you want to access by appending a container name to the command. See the [`kubectl logs` documentation](/docs/user-guide/kubectl/kubectl_logs) for more details. + +## Logging at the node level + +![Node level logging](/images/docs/user-guide/logging/logging-node-level.png) + +Everything a containerized application writes to `stdout` and `stderr` is handled and redirected somewhere by a container engine. For example, Docker container engine redirects those two streams to [a logging driver](https://docs.docker.com/engine/admin/logging/overview), which is configured in Kubernetes to write to a file in json format. + +**Note:** The Docker json logging driver treats each line as a separate message. When using the Docker logging driver, there is no direct support for multi-line messages. To do so, you'll need to handle these at the logging agent level or higher. + +By default, if a container restarts, kubelet keeps one terminated container with its logs. If a pod is evicted from the node, all corresponding containers are also evicted, along with their logs. + +An important consideration in node-level logging is implementing log rotation, so that logs don't consume all available storage on the node. Kubernetes uses the [`logrotate`](http://www.linuxcommand.org/man_pages/logrotate8.html) tool to implement log rotation. + +Kubernetes performs log rotation daily, or if the log file grows beyond 10MB in size. Each rotation belongs to a single container; if the container repeatedly fails or the pod is evicted, all previous rotations for the container are lost. By default, Kubernetes keeps up to five logging rotations per container. + +The Kubernetes logging configuration differs depending on the node type. For example, you can find detailed information for GCI in the corresponding [configure helper](https://github.com/kubernetes/kubernetes/blob/{{page.githubbranch}}/cluster/gce/gci/configure-helper.sh#L96). + +When you run [`kubectl logs`](/docs/user-guide/kubectl/kubectl_logs), as in the basic logging example, the kubelet on the node handles the request and reads directly from the log file, returning the contents in the response. Note that `kubectl logs` **only returns the last rotation**; you must manually extract prior rotations, if desired. + +### System components logs + +Kubernetes system components use a different logging mechanism than the application containers in pods. Components such as `kube-proxy` (among others) use the [glog](https://godoc.org/github.com/golang/glog) logging library. You can find the conventions for logging severity for those components in the [development docs on logging](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/docs/devel/logging.md). + +System components write directly to log files in the `/var/log` directory in the node's host filesystem. Like container logs, system component logs are rotated daily and based on size. However, system component logs have a higher size retention: by default, they store 100MB. + +## Cluster-level logging architectures + +While Kubernetes does not provide a native solution for cluster-level logging, there are several common approaches you can consider: + +* You can use a node-level logging agent that runs on every node. +* You can include a dedicated sidecar container for logging in an application pod. +* You can push logs directly to a back-end from within an application. + +### Using a node logging agent + +![Using a node level logging agent](/images/docs/user-guide/logging/logging-with-node-agent.png) + +You can implement cluster-level logging by including a _node-level logging agent_ on each node. The logging agent is a dedicated tool that exposes logs or pushes logs to a back-end. Commonly, the logging agent is a container that has access to a directory with log files from all of the application containers on that node. + +Because the logging agent must run on every node, it's common to implement it as either a DaemonSet replica, a manifest pod, or a dedicated native process on the node. However the latter two approaches are deprecated and highly discouraged. + +Using a node-level logging agent is the most common and encouraged approach for a Kubernetes cluster, since it creates only one agent per node and it doesn't require any changes to the applications running on the node. However, node-level logging _only works for applications' standard output and standard error_. + +Kubernetes doesn't specify a logging agent, but two optional logging agents are packaged with the Kubernetes release: [Stackdriver Logging](/docs/user-guide/logging/stackdriver) for use with Google Cloud Platform, and [Elasticsearch](/docs/user-guide/logging/elasticsearch). You can find more information and instructions in the dedicated documents. Both use [fluentd](http://www.fluentd.org/) with custom configuration as an agent on the node. + +### Using a sidecar container with the logging agent + +![Using a sidecar container with the logging agent](/images/docs/user-guide/logging/logging-with-sidecar.png) + +You can implement cluster-level logging by including a dedicated logging agent _for each application_ on your cluster. You can include this logging agent as a "sidecar" container in the pod spec for each application; the sidecar container should contain only the logging agent. + +The concrete implementation of the logging agent, the interface between agent and the application, and the interface between the logging agent and the logs back-end are completely up to a you. For an example implementation, see the [fluentd sidecar container](https://github.com/kubernetes/contrib/tree/b70447aa59ea14468f4cd349760e45b6a0a9b15d/logging/fluentd-sidecar-gcp) for the Stackdriver logging backend. + +**Note:** Using a sidecar container for logging may lead to significant resource consumption. + +### Exposing logs directly from the application + +![Exposing logs directly from the application](/images/docs/user-guide/logging/logging-from-application.png) + +You can implement cluster-level logging by exposing or pushing logs directly from every application itself; however, the implementation for such a logging mechanism is outside the scope of Kubernetes. + diff --git a/docs/getting-started-guides/logging.md b/docs/user-guide/logging/stackdriver.md similarity index 64% rename from docs/getting-started-guides/logging.md rename to docs/user-guide/logging/stackdriver.md index 05c41cd3c6..1648d651ec 100644 --- a/docs/getting-started-guides/logging.md +++ b/docs/user-guide/logging/stackdriver.md @@ -1,14 +1,17 @@ --- assignees: -- lavalamp -- satnam6502 -title: Logging +- crassirostris +- piosz +title: Logging with Stackdriver Logging --- -A Kubernetes cluster will typically be humming along running many system and application pods. How does the system administrator collect, manage and query the logs of the system pods? How does a user query the logs of their application which is composed of many pods which may be restarted or automatically generated by the Kubernetes system? These questions are addressed by the Kubernetes **cluster level logging** services. +Before reading this page, it's recommended to familiarize yourself with the [overview of logging in Kubernetes](/docs/user-guide/logging/overview). -Cluster level logging for Kubernetes allows us to collect logs which persist beyond the lifetime of the pod's container images or the lifetime of the pod or even cluster. In this article we assume that a Kubernetes cluster has been created with cluster level logging support for sending logs to Google Cloud Logging. After a cluster has been created you will have a collection of system pods running in the `kube-system` namespace that support monitoring, -logging and DNS resolution for names of Kubernetes services: +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 @@ -25,15 +28,14 @@ Here is the same information in a picture which shows how the pods might be plac ![image](/images/blog-logging/diagrams/cloud-logging.png) -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 Google Cloud Logging. A pod which provides the +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 let's start off with a synthetic log generator pod specification [counter-pod.yaml](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/blog-logging/counter-pod.yaml): +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" k8slink="/examples/blog-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. +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 @@ -54,7 +56,7 @@ One of the nodes is now running the counter pod: ![image](/images/blog-logging/diagrams/27gf-counter.png) -When the pod status changes to `Running` we can use the kubectl logs command to view the output of this 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 @@ -79,7 +81,13 @@ 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 ``` +<<<<<<< HEAD:docs/getting-started-guides/logging.md What happens if for any reason the image in this pod is killed off and then restarted by Kubernetes? Will we still see the log lines from the previous invocation of the container followed by the log lines for the started container? Or will we lose the log lines from the original container's execution and only see the log lines for the new container? Let's find out. First let's delete the currently running counter. +======= +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: +>>>>>>> 69304ab37e14fac33455b629442bdc3995d05ad2:docs/user-guide/logging/stackdriver.md ```shell $ kubectl delete pod counter @@ -108,15 +116,9 @@ $ kubectl logs counter 8: Tue Jun 2 21:51:48 UTC 2015 ``` -We've lost the log lines from the first invocation of the container in this pod! Ideally, we want to preserve all the log lines from each invocation of each container in the pod. Furthermore, even if the pod is restarted we would still like to preserve all the log lines that were ever emitted by the containers in the pod. But don't fear, this is the functionality provided by cluster level logging in Kubernetes. When a cluster is created, the standard output and standard error output of each container can be ingested using a [Fluentd](http://www.fluentd.org/) agent running on each node into either [Google Cloud Logging](https://cloud.google.com/logging/docs/) or into Elasticsearch and viewed with Kibana. +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. -When a Kubernetes cluster is created with logging to Google Cloud Logging enabled, the system creates a pod called `fluentd-cloud-logging` on each node of the cluster to collect Docker container logs. These pods were shown at the start of this blog article in the response to the first get pods command. - -This log collection pod has a specification which looks something like this: - -{% include code.html language="yaml" file="fluentd-gcp.yaml" k8slink="/cluster/saltbase/salt/fluentd-gcp/fluentd-gcp.yaml" %} - -This pod specification maps the directory on the host containing the Docker log files, `/var/lib/docker/containers`, to a directory inside the container which has the same path. The pod runs one image, `gcr.io/google_containers/fluentd-gcp:1.6`, which is configured to collect the Docker log files from the logs directory and ingest them into Google Cloud Logging. One instance of this pod runs on each node of the cluster. Kubernetes will notice if this pod fails and automatically restart it. +## 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: @@ -128,7 +130,7 @@ When we view the logs in the Developer Console we observe the logs for both invo 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 Google Cloud 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 + 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: @@ -165,6 +167,6 @@ $ cat 21\:00\:00_21\:59\:59_S0.json | jq '.structPayload.log' ... ``` -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 Google Cloud Logging service. +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) +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) diff --git a/docs/user-guide/production-pods.md b/docs/user-guide/production-pods.md index bd3724cc5e..586838f852 100644 --- a/docs/user-guide/production-pods.md +++ b/docs/user-guide/production-pods.md @@ -220,7 +220,7 @@ The specification of a pre-stop hook is similar to that of probes, but without t ## 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). 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`. +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: diff --git a/docs/whatisk8s.md b/docs/whatisk8s.md index d84be65f74..8a9d5b04db 100644 --- a/docs/whatisk8s.md +++ b/docs/whatisk8s.md @@ -76,7 +76,7 @@ Kubernetes satisfies a number of common needs of applications running in product * [load balancing](/docs/user-guide/services/), * [rolling updates](/docs/user-guide/update-demo/), * [resource monitoring](/docs/user-guide/monitoring/), -* [log access and ingestion](/docs/user-guide/logging/), +* [log access and ingestion](/docs/user-guide/logging/overview/), * [support for introspection and debugging](/docs/user-guide/introspection-and-debugging/), and * [identity and authorization](/docs/admin/authorization/). diff --git a/images/docs/user-guide/logging/logging-from-application.png b/images/docs/user-guide/logging/logging-from-application.png new file mode 100644 index 0000000000000000000000000000000000000000..67dfd9db927e35d2a750a45355a5d79801e4b8a2 GIT binary patch literal 19696 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%0A`i>n^6jVue+R02ubI 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 literal 0 HcmV?d00001 diff --git a/test/examples_test.go b/test/examples_test.go index 22e71c8bb0..14ae5f5061 100644 --- a/test/examples_test.go +++ b/test/examples_test.go @@ -301,10 +301,6 @@ func TestExampleObjectSchemas(t *testing.T) { "namespace": {&api.Namespace{}}, "valid-pod": {&api.Pod{}}, }, - "../docs/user-guide/logging-demo": { - "synthetic_0_25lps": {&api.Pod{}}, - "synthetic_10lps": {&api.Pod{}}, - }, "../docs/user-guide/node-selection": { "pod": {&api.Pod{}}, "pod-with-node-affinity": {&api.Pod{}}, From add6e30826bf907a129650bd292ae313f8645e50 Mon Sep 17 00:00:00 2001 From: mark007 Date: Wed, 4 Jan 2017 14:58:58 +0000 Subject: [PATCH 045/247] Update index.html --- docs/tutorials/kubernetes-basics/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tutorials/kubernetes-basics/index.html b/docs/tutorials/kubernetes-basics/index.html index eac6d89492..5fc4b5b9bb 100644 --- a/docs/tutorials/kubernetes-basics/index.html +++ b/docs/tutorials/kubernetes-basics/index.html @@ -34,7 +34,7 @@ title: Overview

What can Kubernetes do for you?

-

With modern web services, users expect applications to be available 24/7, and developers expect to deploy new versions of those applications several times a day. Containerization helps package software to serve these goals, enabling applications to be released and updated in an easy and fast way without downtime. Kubernetes helps you make sure those containerized applications run where and when you want, and helps them find the resources and tools they need to work. Kubernetes is a production-ready, open source platform designed with the Google's accumulated experience in container orchestration, combined with best-of-breed ideas from the community.

+

With modern web services, users expect applications to be available 24/7, and developers expect to deploy new versions of those applications several times a day. Containerization helps package software to serve these goals, enabling applications to be released and updated in an easy and fast way without downtime. Kubernetes helps you make sure those containerized applications run where and when you want, and helps them find the resources and tools they need to work. Kubernetes is a production-ready, open source platform designed with Google's accumulated experience in container orchestration, combined with best-of-breed ideas from the community.

From 52ec922685c22d93c82efb9969fca51d465f5dd8 Mon Sep 17 00:00:00 2001 From: Tim Hockin Date: Wed, 4 Jan 2017 08:56:49 -0800 Subject: [PATCH 046/247] deprecation policy bug: at X+9 we remove v1 --- docs/deprecation-policy.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/deprecation-policy.md b/docs/deprecation-policy.md index d349e6c0b9..c51326bbc5 100644 --- a/docs/deprecation-policy.md +++ b/docs/deprecation-policy.md @@ -161,7 +161,7 @@ versions are supported in a series of subsequent releases. X+9 - v1, v2 + v2