Skip to content

Commit

Permalink
config best practices doc edits
Browse files Browse the repository at this point in the history
  • Loading branch information
amygdala committed Dec 16, 2015
1 parent 3415f1d commit b1f99ec
Show file tree
Hide file tree
Showing 6 changed files with 133 additions and 28 deletions.
3 changes: 2 additions & 1 deletion docs/devel/coding-conventions.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ Directory and file conventions
- Package directories should generally avoid using separators as much as possible (when packages are multiple words, they usually should be in nested subdirectories).
- Document directories and filenames should use dashes rather than underscores
- Contrived examples that illustrate system features belong in /docs/user-guide or /docs/admin, depending on whether it is a feature primarily intended for users that deploy applications or cluster administrators, respectively. Actual application examples belong in /examples.
- Examples should also illustrate [best practices for using the system](../user-guide/config-best-practices.md)
- Examples should also illustrate
[best practices for configuration and using the system](../user-guide/config-best-practices.md)
- Third-party code
- Third-party Go code is managed using Godeps
- Other third-party code belongs in /third_party
Expand Down
2 changes: 1 addition & 1 deletion docs/user-guide/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ If you don't have much familiarity with Kubernetes, we recommend you read the fo
* [Downward API: accessing system configuration from a pod](downward-api.md)
* [Images and registries](images.md)
* [Migrating from docker-cli to kubectl](docker-cli-to-kubectl.md)
* [Tips and tricks when working with config](config-best-practices.md)
* [Configuration Best Practices and Tips](config-best-practices.md)
* [Assign pods to selected nodes](node-selection/)
* [Perform a rolling update on a running group of pods](update-demo/)

Expand Down
146 changes: 125 additions & 21 deletions docs/user-guide/config-best-practices.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,27 +31,131 @@ Documentation for other releases can be found at

<!-- END MUNGE: UNVERSIONED_WARNING -->

# Tips and tricks when working with config

This document is meant to highlight and consolidate in one place configuration best practices that are introduced throughout the user-guide and getting-started documentation and examples. This is a living document so if you think of something that is not on this list but might be useful to others, please don't hesitate to file an issue or submit a PR.

1. When writing configuration, use the latest stable API version (currently v1).
1. Configuration should be stored in version control before being pushed to the cluster. This allows configuration to be quickly rolled back if needed and will aid with cluster re-creation and restoration if the worst were to happen.
1. Use YAML rather than JSON. They can be used interchangeably in almost all scenarios but YAML tends to be more user-friendly for config.
1. Group related objects together in a single file. This is often better than separate files.
1. Use `kubectl create -f <directory>` where possible. This looks for config objects in all `.yaml`, `.yml`, and `.json` files in `<directory>` and passes them to create.
1. Create a service before corresponding replication controllers so that the scheduler can spread the pods comprising the service. You can also create the replication controller without specifying replicas, create the service, then scale up the replication controller, which may work better in an example using progressive disclosure and may have benefits in real scenarios also, such as ensuring one replica works before creating lots of them)
1. Don't use `hostPort` unless absolutely necessary (e.g., for a node daemon) as it will prevent certain scheduling configurations due to port conflicts. Use the apiserver proxying or port forwarding for debug/admin access, or a service for external service access. If you need to expose a pod's port on the host machine, consider using a [NodePort](services.md#type--loadbalancer) service before resorting to `hostPort`. If you only need access to the port for debugging purposes, you can also use the [kubectl proxy and apiserver proxy](connecting-to-applications-proxy.md) or [kubectl port-forward](connecting-to-applications-port-forward.md).
1. Don't use `hostNetwork` for the same reasons as `hostPort`.
1. Don't specify default values unnecessarily, to simplify and minimize configs. For example, omit the selector and labels in ReplicationController if you want them to be the same as the labels in its podTemplate, since those fields are populated from the podTemplate labels by default.
1. Instead of attaching one label to a set of pods to represent a service (e.g., `service: myservice`) and another to represent the replication controller managing the pods (e.g., `controller: mycontroller`), attach labels that identify semantic attributes of your application or deployment and select the appropriate subsets in your service and replication controller, such as `{ app: myapp, tier: frontend, deployment: v3 }`. A service can be made to span multiple deployments, such as across rolling updates, by simply omitting release-specific labels from its selector, rather than updating a service's selector to match the replication controller's selector fully.
1. Use kubectl bulk operations (via files and/or labels) for get and delete. See [label selectors](labels.md#label-selectors) and [using labels effectively](managing-deployments.md#using-labels-effectively).
1. Use kubectl run and expose to quickly create and expose single container replication controllers. See the [quick start guide](quick-start.md) for an example.
1. Use headless services for easy service discovery when you don't need kube-proxy load balancing. See [headless services](services.md#headless-services).
1. Use kubectl delete rather than stop. Delete has a superset of the functionality of stop and stop is deprecated.
1. If there is a viable alternative to naked pods (i.e. pods not bound to a controller), go with the alternative. Controllers are almost always preferable to creating pods (except for some `restartPolicy: Never` scenarios). A minimal Job is coming. See [#1624](http://issue.k8s.io/1624). Naked pods will not be rescheduled in the event of node failure.
1. Put a version number or hash as a suffix to the name and in a label on a replication controller to facilitate rolling update, as we do for [--image](kubectl/kubectl_rolling-update.md). This is necessary because rolling-update actually creates a new controller as opposed to modifying the existing controller. This does not play well with version agnostic controller names.
1. Put an object description in an annotation to allow better introspection.
# Configuration Best Practices and Tips

**Table of Contents**
<!-- BEGIN MUNGE: GENERATED_TOC -->

- [Configuration Best Practices and Tips](#configuration-best-practices-and-tips)
- [General Config Tips](#general-config-tips)
- ["Naked" Pods vs Replication Controllers and Jobs](#naked-pods-vs-replication-controllers-and-jobs)
- [Services](#services)
- [Using Labels](#using-labels)
- [Container Images](#container-images)
- [Using kubectl](#using-kubectl)

<!-- END MUNGE: GENERATED_TOC -->


This document is meant to highlight and consolidate in one place configuration best practices that are introduced throughout the user-guide and getting-started documentation and examples. This is a living document, so if you think of something that is not on this list but might be useful to others, please don't hesitate to file an issue or submit a PR.

## General Config Tips

- When defining configurations, specify the latest stable API version (currently v1).

- Configuration files should be stored in version control before being pushed to the cluster. This allows a configuration to be quickly rolled back if needed, and will aid with cluster re-creation and restoration if necessary.

- Write your configuration files using YAML rather than JSON. They can be used interchangeably in almost all scenarios, but YAML tends to be more user-friendly for config.

- Group related objects together in a single file where this makes sense. This format is often easier to manage than separate files. See the [guestbook-all-in-one.yaml](../../examples/guestbook/all-in-one/guestbook-all-in-one.yaml) file as an example of this syntax.
(Note also that many `kubectl` commands can be called on a directory, and so you can also call
`kubectl create` on a directory of config files— see below for more detail).

- Don't specify default values unnecessarily, in order to simplify and minimize configs, and to
reduce error. For example, omit the selector and labels in a `ReplicationController` if you want
them to be the same as the labels in its `podTemplate`, since those fields are populated from the
`podTemplate` labels by default. See the [guestbook app's](../../examples/guestbook/) .yaml files for some [examples](../../examples/guestbook/frontend-controller.yaml) of this.

- Put an object description in an annotation to allow better introspection.


## "Naked" Pods vs Replication Controllers and Jobs

- If there is a viable alternative to naked pods (i.e., pods not bound to a [replication controller
](replication-controller.md)), go with the alternative. Naked pods will not be rescheduled in the
event of node failure.

Replication controllers are almost always preferable to creating pods, except for some explicit
[`restartPolicy: Never`](pod-states.md#restartpolicy) scenarios. A
[Job](jobs.md) object (currently in Beta), may also be appropriate.


## Services

- It's typically best to create a [service](services.md) before corresponding [replication
controllers](replication-controller.md), so that the scheduler can spread the pods comprising the
service. You can also create a replication controller without specifying replicas (this will set
replicas=1), create a service, then scale up the replication controller. This can be useful in
ensuring that one replica works before creating lots of them.

- Don't use `hostPort` (which specifies the port number to expose on the host) unless absolutely
necessary, e.g., for a node daemon. When you bind a Pod to a `hostPort`, there are a limited
number of places that pod can be scheduled, due to port conflicts— you can only schedule as many
such Pods as there are nodes in your Kubernetes cluster.

If you only need access to the port for debugging purposes, you can use the [kubectl proxy and apiserver proxy](connecting-to-applications-proxy.md) or [kubectl port-forward](connecting-to-applications-port-forward.md).
You can use a [Service](services.md) object for external service access.
If you do need to expose a pod's port on the host machine, consider using a [NodePort](services.md#type-nodeport) service before resorting to `hostPort`.

- Avoid using `hostNetwork`, for the same reasons as `hostPort`.

- Use _headless services_ for easy service discovery when you don't need kube-proxy load balancing.
See [headless services](services.md#headless-services).

## Using Labels

- Define and use [labels](labels.md) that identify __semantic attributes__ of your application or
deployment. For example, instead of attaching a label to a set of pods to explicitly represent
some service (e.g., `service: myservice`), or explicitly representing the replication
controller managing the pods (e.g., `controller: mycontroller`), attach labels that identify
semantic attributes, such as `{ app: myapp, tier: frontend, phase: test, deployment: v3 }`. This
will let you select the object groups appropriate to the context— e.g., a service for all "tier:
frontend" pods, or all "test" phase components of app "myapp". See the
[guestbook](../../examples/guestbook/) app for an example of this approach.

A service can be made to span multiple deployments, such as is done across [rolling updates](kubectl/kubectl_rolling-update.md), by simply omitting release-specific labels from its selector, rather than updating a service's selector to match the replication controller's selector fully.

- To facilitate rolling updates, include version info in replication controller names, e.g. as a
suffix to the name. It is useful to set a 'version' label as well. The rolling update creates a
new controller as opposed to modifying the existing controller. So, there will be issues with
version-agnostic controller names. See the [documentation](kubectl/kubectl_rolling-update.md) on
the rolling-update command for more detail.

Note that the [Deployment](deployments.md) object obviates the need to manage replication
controller 'version names'. A desired state of an object is described by a Deployment, and if
changes to that spec are _applied_, the deployment controller changes the actual state to the
desired state at a controlled rate. (Deployment objects are currently part of the [`extensions`
API Group](../api.md#api- groups), and are not enabled by default.)

- You can manipulate labels for debugging. Because Kubernetes replication controllers and services
match to pods using labels, this allows you to remove a pod from being considered by a
controller, or served traffic by a service, by removing the relevant selector labels. If you
remove the labels of an existing pod, its controller will create a new pod to take its place.
This is a useful way to debug a previously "live" pod in a quarantine environment. See the
[`kubectl label`](kubectl/kubectl_label.md) command.

## Container Images

- The [default container image pull policy](images.md) is `IfNotPresent`, which causes the
[Kubelet](../admin/kubelet.md) to not pull an image if it already exists. If you would like to
always force a pull, you must specify a pull image policy of `Always` in your .yaml file
(`imagePullPolicy: Always`) or specify a `:latest` tag on your image.

That is, if you're specifying an image with other than the `:latest` tag, e.g. `myimage:v1`, and
there is an image update to that same tag, the Kubelet won't pull the updated image. You can
address this by ensuring that any updates to an image bump the image tag as well (e.g.
`myimage:v2`), and ensuring that your configs point to the correct version.

## Using kubectl

- Use `kubectl create -f <directory>` where possible. This looks for config objects in all `.yaml`, `.yml`, and `.json` files in `<directory>` and passes them to `create`.

- Use `kubectl delete` rather than `stop`. `Delete` has a superset of the functionality of `stop`, and `stop` is deprecated.

- Use kubectl bulk operations (via files and/or labels) for get and delete. See [label selectors](labels.md#label-selectors) and [using labels effectively](managing-deployments.md#using-labels-effectively).

- Use `kubectl run` and `expose` to quickly create and expose single container replication controllers. See the [quick start guide](quick-start.md) for an example.



<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
Expand Down
2 changes: 1 addition & 1 deletion docs/user-guide/kubectl-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ where `command`, `TYPE`, `NAME`, and `flags` are:
* To specify multiple resource types individually: `TYPE1/name1 TYPE1/name2 TYPE2/name3 TYPE<#>/name<#>`<br/>
Example: `$ kubectl get pod/example-pod1 replicationcontroller/example-rc1`
* To specify resources with one or more files: `-f file1 -f file2 -f file<#>`
[Use YAML rather than JSON](config-best-practices.md) since YAML tends to be more user-friendly, especially for configuration files.<br/>
[Use YAML rather than JSON](config-best-practices.md#general-config-tips) since YAML tends to be more user-friendly, especially for configuration files.<br/>
Example: `$ kubectl get pod -f ./pod.yaml`
* `flags`: Specifies optional flags. For example, you can use the `-s` or `--server` flags to specify the address and port of the Kubernetes API server.<br/>
**Important**: Flags that you specify from the command line override default values and any corresponding environment variables.
Expand Down
2 changes: 1 addition & 1 deletion docs/user-guide/managing-deployments.md
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,7 @@ replicationcontrollers "my-nginx-v4" replaced
## What's next?

- [Learn about how to use `kubectl` for application introspection and debugging.](introspection-and-debugging.md)
- [Tips and tricks when working with config](config-best-practices.md)
- [Configuration Best Practices and Tips](config-best-practices.md)


<!-- BEGIN MUNGE: GENERATED_ANALYTICS -->
Expand Down
6 changes: 3 additions & 3 deletions examples/guestbook/frontend-controller.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ metadata:
name: frontend
# these labels can be applied automatically
# from the labels in the pod template if not set
labels:
app: guestbook
tier: frontend
# labels:
# app: guestbook
# tier: frontend
spec:
# this replicas value is default
# modify it according to your case
Expand Down

1 comment on commit b1f99ec

@k8s-teamcity-mesosphere

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TeamCity OSS :: Kubernetes Mesos :: 4 - Smoke Tests Build 9588 outcome was SUCCESS
Summary: Tests passed: 1, ignored: 206 Build time: 00:04:03

Please sign in to comment.