@@ -62,6 +62,7 @@ To avoid running into cloud provider quota issues, when creating a cluster with
...
@@ -62,6 +62,7 @@ To avoid running into cloud provider quota issues, when creating a cluster with
To prevent memory leaks or other resource issues in [cluster addons](../../cluster/addons/) from consuming all the resources available on a node, Kubernetes sets resource limits on addon containers to limit the CPU and Memory resources they can consume (See PR [#10653](https://github.com/GoogleCloudPlatform/kubernetes/pull/10653/files) and [#10778](https://github.com/GoogleCloudPlatform/kubernetes/pull/10778/files)).
To prevent memory leaks or other resource issues in [cluster addons](../../cluster/addons/) from consuming all the resources available on a node, Kubernetes sets resource limits on addon containers to limit the CPU and Memory resources they can consume (See PR [#10653](https://github.com/GoogleCloudPlatform/kubernetes/pull/10653/files) and [#10778](https://github.com/GoogleCloudPlatform/kubernetes/pull/10778/files)).
@@ -131,6 +131,7 @@ for ```${NODE_IP}``` on each machine.
...
@@ -131,6 +131,7 @@ for ```${NODE_IP}``` on each machine.
#### Validating your cluster
#### Validating your cluster
Once you copy this into all three nodes, you should have a clustered etcd set up. You can validate with
Once you copy this into all three nodes, you should have a clustered etcd set up. You can validate with
```
```
etcdctl member list
etcdctl member list
```
```
...
@@ -209,11 +210,12 @@ master election. On each of the three apiserver nodes, we run a small utility a
...
@@ -209,11 +210,12 @@ master election. On each of the three apiserver nodes, we run a small utility a
election protocol using etcd "compare and swap". If the apiserver node wins the election, it starts the master component it is managing (e.g. the scheduler), if it
election protocol using etcd "compare and swap". If the apiserver node wins the election, it starts the master component it is managing (e.g. the scheduler), if it
loses the election, it ensures that any master components running on the node (e.g. the scheduler) are stopped.
loses the election, it ensures that any master components running on the node (e.g. the scheduler) are stopped.
In the future, we expect to more tightly integrate this lease-locking into the scheduler and controller-manager binaries directly, as described in the [high availability design proposal](proposals/high-availability.md)
In the future, we expect to more tightly integrate this lease-locking into the scheduler and controller-manager binaries directly, as described in the [high availability design proposal](../proposals/high-availability.md)
### Installing configuration files
### Installing configuration files
First, create empty log files on each node, so that Docker will mount the files not make new directories:
First, create empty log files on each node, so that Docker will mount the files not make new directories:
```
```
touch /var/log/kube-scheduler.log
touch /var/log/kube-scheduler.log
touch /var/log/kube-controller-manager.log
touch /var/log/kube-controller-manager.log
...
@@ -244,7 +246,7 @@ set the ```--apiserver``` flag to your replicated endpoint.
...
@@ -244,7 +246,7 @@ set the ```--apiserver``` flag to your replicated endpoint.
##Vagrant up!
##Vagrant up!
We indeed have an initial proof of concept tester for this, which is available [here](../examples/high-availability/).
We indeed have an initial proof of concept tester for this, which is available [here](../../examples/high-availability/).
It implements the major concepts (with a few minor reductions for simplicity), of the podmaster HA implementation alongside a quick smoke test using k8petstore.
It implements the major concepts (with a few minor reductions for simplicity), of the podmaster HA implementation alongside a quick smoke test using k8petstore.
The salt-master is contacted by each salt-minion and depending upon the machine information presented, the salt-master will provision the machine as either a kubernetes-master or kubernetes-minion with all the required capabilities needed to run Kubernetes.
The salt-master is contacted by each salt-minion and depending upon the machine information presented, the salt-master will provision the machine as either a kubernetes-master or kubernetes-minion with all the required capabilities needed to run Kubernetes.
If you are running the Vagrant based environment, the **salt-api** service is running on the kubernetes-master. It is configured to enable the vagrant user to introspect the salt cluster in order to find out about machines in the Vagrant environment via a REST API.
If you are running the Vagrant based environment, the **salt-api** service is running on the kubernetes-master. It is configured to enable the vagrant user to introspect the salt cluster in order to find out about machines in the Vagrant environment via a REST API.
Both users and a number of system components, such as schedulers, (horizontal) auto-scalers, (vertical) auto-sizers, load balancers, and worker-pool managers need to reason about resource requirements of workloads, resource capacities of nodes, and resource usage. Kubernetes divides specifications of *desired state*, aka the Spec, and representations of *current state*, aka the Status. Resource requirements and total node capacity fall into the specification category, while resource usage, characterizations derived from usage (e.g., maximum usage, histograms), and other resource demand signals (e.g., CPU load) clearly fall into the status category and are discussed in the Appendix for now.
Both users and a number of system components, such as schedulers, (horizontal) auto-scalers, (vertical) auto-sizers, load balancers, and worker-pool managers need to reason about resource requirements of workloads, resource capacities of nodes, and resource usage. Kubernetes divides specifications of *desired state*, aka the Spec, and representations of *current state*, aka the Status. Resource requirements and total node capacity fall into the specification category, while resource usage, characterizations derived from usage (e.g., maximum usage, histograms), and other resource demand signals (e.g., CPU load) clearly fall into the status category and are discussed in the Appendix for now.
Resource requirements for a container or pod should have the following form:
Resource requirements for a container or pod should have the following form:
```
```
resourceRequirementSpec: [
resourceRequirementSpec: [
request: [ cpu: 2.5, memory: "40Mi" ],
request: [ cpu: 2.5, memory: "40Mi" ],
limit: [ cpu: 4.0, memory: "99Mi" ],
limit: [ cpu: 4.0, memory: "99Mi" ],
]
]
```
```
Where:
Where:
* _request_ [optional]: the amount of resources being requested, or that were requested and have been allocated. Scheduler algorithms will use these quantities to test feasibility (whether a pod will fit onto a node). If a container (or pod) tries to use more resources than its _request_, any associated SLOs are voided — e.g., the program it is running may be throttled (compressible resource types), or the attempt may be denied. If _request_ is omitted for a container, it defaults to _limit_ if that is explicitly specified, otherwise to an implementation-defined value; this will always be 0 for a user-defined resource type. If _request_ is omitted for a pod, it defaults to the sum of the (explicit or implicit) _request_ values for the containers it encloses.
* _request_ [optional]: the amount of resources being requested, or that were requested and have been allocated. Scheduler algorithms will use these quantities to test feasibility (whether a pod will fit onto a node). If a container (or pod) tries to use more resources than its _request_, any associated SLOs are voided — e.g., the program it is running may be throttled (compressible resource types), or the attempt may be denied. If _request_ is omitted for a container, it defaults to _limit_ if that is explicitly specified, otherwise to an implementation-defined value; this will always be 0 for a user-defined resource type. If _request_ is omitted for a pod, it defaults to the sum of the (explicit or implicit) _request_ values for the containers it encloses.
* _limit_ [optional]: an upper bound or cap on the maximum amount of resources that will be made available to a container or pod; if a container or pod uses more resources than its _limit_, it may be terminated. The _limit_ defaults to "unbounded"; in practice, this probably means the capacity of an enclosing container, pod, or node, but may result in non-deterministic behavior, especially for memory.
* _limit_ [optional]: an upper bound or cap on the maximum amount of resources that will be made available to a container or pod; if a container or pod uses more resources than its _limit_, it may be terminated. The _limit_ defaults to "unbounded"; in practice, this probably means the capacity of an enclosing container, pod, or node, but may result in non-deterministic behavior, especially for memory.
Total capacity for a node should have a similar structure:
Total capacity for a node should have a similar structure:
```
```
resourceCapacitySpec: [
resourceCapacitySpec: [
total: [ cpu: 12, memory: "128Gi" ]
total: [ cpu: 12, memory: "128Gi" ]
]
]
```
```
Where:
Where:
* _total_: the total allocatable resources of a node. Initially, the resources at a given scope will bound the resources of the sum of inner scopes.
* _total_: the total allocatable resources of a node. Initially, the resources at a given scope will bound the resources of the sum of inner scopes.
...
@@ -149,6 +153,7 @@ rather than decimal ones: "64MiB" rather than "64MB".
...
@@ -149,6 +153,7 @@ rather than decimal ones: "64MiB" rather than "64MB".
## Resource metadata
## Resource metadata
A resource type may have an associated read-only ResourceType structure, that contains metadata about the type. For example:
A resource type may have an associated read-only ResourceType structure, that contains metadata about the type. For example:
```
```
resourceTypes: [
resourceTypes: [
"kubernetes.io/memory": [
"kubernetes.io/memory": [
...
@@ -194,6 +199,7 @@ resourceStatus: [
...
@@ -194,6 +199,7 @@ resourceStatus: [
```
```
where a `<CPU-info>` or `<memory-info>` structure looks like this:
where a `<CPU-info>` or `<memory-info>` structure looks like this:
```
```
{
{
mean: <value> # arithmetic mean
mean: <value> # arithmetic mean
...
@@ -209,6 +215,7 @@ where a `<CPU-info>` or `<memory-info>` structure looks like this:
...
@@ -209,6 +215,7 @@ where a `<CPU-info>` or `<memory-info>` structure looks like this:
]
]
}
}
```
```
All parts of this structure are optional, although we strongly encourage including quantities for 50, 90, 95, 99, 99.5, and 99.9 percentiles. _[In practice, it will be important to include additional info such as the length of the time window over which the averages are calculated, the confidence level, and information-quality metrics such as the number of dropped or discarded data points.]_
All parts of this structure are optional, although we strongly encourage including quantities for 50, 90, 95, 99, 99.5, and 99.9 percentiles. _[In practice, it will be important to include additional info such as the length of the time window over which the averages are calculated, the confidence level, and information-quality metrics such as the number of dropped or discarded data points.]_
@@ -196,12 +196,15 @@ References in the status of the referee to the referrer may be permitted, when t
...
@@ -196,12 +196,15 @@ References in the status of the referee to the referrer may be permitted, when t
Discussed in [#2004](https://github.com/GoogleCloudPlatform/kubernetes/issues/2004) and elsewhere. There are no maps of subobjects in any API objects. Instead, the convention is to use a list of subobjects containing name fields.
Discussed in [#2004](https://github.com/GoogleCloudPlatform/kubernetes/issues/2004) and elsewhere. There are no maps of subobjects in any API objects. Instead, the convention is to use a list of subobjects containing name fields.
For example:
For example:
```yaml
```yaml
ports:
ports:
-name:www
-name:www
containerPort:80
containerPort:80
```
```
vs.
vs.
```yaml
```yaml
ports:
ports:
www:
www:
...
@@ -518,6 +521,7 @@ A ```Status``` kind will be returned by the API in two cases:
...
@@ -518,6 +521,7 @@ A ```Status``` kind will be returned by the API in two cases:
The status object is encoded as JSON and provided as the body of the response. The status object contains fields for humans and machine consumers of the API to get more detailed information for the cause of the failure. The information in the status object supplements, but does not override, the HTTP status code's meaning. When fields in the status object have the same meaning as generally defined HTTP headers and that header is returned with the response, the header should be considered as having higher priority.
The status object is encoded as JSON and provided as the body of the response. The status object contains fields for humans and machine consumers of the API to get more detailed information for the cause of the failure. The information in the status object supplements, but does not override, the HTTP status code's meaning. When fields in the status object have the same meaning as generally defined HTTP headers and that header is returned with the response, the header should be considered as having higher priority.
@@ -109,6 +109,7 @@ source control system). Use ```apt-get install mercurial``` or ```yum install m
...
@@ -109,6 +109,7 @@ source control system). Use ```apt-get install mercurial``` or ```yum install m
directly from mercurial.
directly from mercurial.
2) Create a new GOPATH for your tools and install godep:
2) Create a new GOPATH for your tools and install godep:
```
```
export GOPATH=$HOME/go-tools
export GOPATH=$HOME/go-tools
mkdir -p $GOPATH
mkdir -p $GOPATH
...
@@ -116,6 +117,7 @@ go get github.com/tools/godep
...
@@ -116,6 +117,7 @@ go get github.com/tools/godep
```
```
3) Add $GOPATH/bin to your path. Typically you'd add this to your ~/.profile:
3) Add $GOPATH/bin to your path. Typically you'd add this to your ~/.profile:
```
```
export GOPATH=$HOME/go-tools
export GOPATH=$HOME/go-tools
export PATH=$PATH:$GOPATH/bin
export PATH=$PATH:$GOPATH/bin
...
@@ -125,6 +127,7 @@ export PATH=$PATH:$GOPATH/bin
...
@@ -125,6 +127,7 @@ export PATH=$PATH:$GOPATH/bin
Here's a quick walkthrough of one way to use godeps to add or update a Kubernetes dependency into Godeps/_workspace. For more details, please see the instructions in [godep's documentation](https://github.com/tools/godep).
Here's a quick walkthrough of one way to use godeps to add or update a Kubernetes dependency into Godeps/_workspace. For more details, please see the instructions in [godep's documentation](https://github.com/tools/godep).
# Option A: this will let your builds see packages that exist elsewhere on your system.
# Option A: this will let your builds see packages that exist elsewhere on your system.
export GOPATH=$KPATH:$GOPATH
export GOPATH=$KPATH:$GOPATH
...
@@ -143,12 +147,14 @@ export GOPATH=$KPATH
...
@@ -143,12 +147,14 @@ export GOPATH=$KPATH
```
```
3) Populate your new GOPATH.
3) Populate your new GOPATH.
```
```
cd $KPATH/src/github.com/GoogleCloudPlatform/kubernetes
cd $KPATH/src/github.com/GoogleCloudPlatform/kubernetes
godep restore
godep restore
```
```
4) Next, you can either add a new dependency or update an existing one.
4) Next, you can either add a new dependency or update an existing one.
```
```
# To add a new dependency, do:
# To add a new dependency, do:
cd $KPATH/src/github.com/GoogleCloudPlatform/kubernetes
cd $KPATH/src/github.com/GoogleCloudPlatform/kubernetes
...
@@ -218,6 +224,7 @@ KUBE_COVER=y hack/test-go.sh
...
@@ -218,6 +224,7 @@ KUBE_COVER=y hack/test-go.sh
At the end of the run, an the HTML report will be generated with the path printed to stdout.
At the end of the run, an the HTML report will be generated with the path printed to stdout.
To run tests and collect coverage in only one package, pass its relative path under the `kubernetes` directory as an argument, for example:
To run tests and collect coverage in only one package, pass its relative path under the `kubernetes` directory as an argument, for example:
```
```
cd kubernetes
cd kubernetes
KUBE_COVER=y hack/test-go.sh pkg/kubectl
KUBE_COVER=y hack/test-go.sh pkg/kubectl
...
@@ -230,6 +237,7 @@ Coverage results for the project can also be viewed on [Coveralls](https://cover
...
@@ -230,6 +237,7 @@ Coverage results for the project can also be viewed on [Coveralls](https://cover
## Integration tests
## Integration tests
You need an [etcd](https://github.com/coreos/etcd/releases/tag/v2.0.0) in your path, please make sure it is installed and in your ``$PATH``.
You need an [etcd](https://github.com/coreos/etcd/releases/tag/v2.0.0) in your path, please make sure it is installed and in your ``$PATH``.
```
```
cd kubernetes
cd kubernetes
hack/test-integration.sh
hack/test-integration.sh
...
@@ -238,12 +246,14 @@ hack/test-integration.sh
...
@@ -238,12 +246,14 @@ hack/test-integration.sh
## End-to-End tests
## End-to-End tests
You can run an end-to-end test which will bring up a master and two nodes, perform some tests, and then tear everything down. Make sure you have followed the getting started steps for your chosen cloud platform (which might involve changing the `KUBERNETES_PROVIDER` environment variable to something other than "gce".
You can run an end-to-end test which will bring up a master and two nodes, perform some tests, and then tear everything down. Make sure you have followed the getting started steps for your chosen cloud platform (which might involve changing the `KUBERNETES_PROVIDER` environment variable to something other than "gce".
```
```
cd kubernetes
cd kubernetes
hack/e2e-test.sh
hack/e2e-test.sh
```
```
Pressing control-C should result in an orderly shutdown but if something goes wrong and you still have some VMs running you can force a cleanup with this command:
Pressing control-C should result in an orderly shutdown but if something goes wrong and you still have some VMs running you can force a cleanup with this command:
Note that we omit the labels and the selector fields of the replication controller, because they will be populated from the labels field of the pod template by default.
Note that we omit the labels and the selector fields of the replication controller, because they will be populated from the labels field of the pod template by default.
to the init(c *Config) method in 'pkg/master/master.go' and import 'net/http/pprof' package.
to the init(c *Config) method in 'pkg/master/master.go' and import 'net/http/pprof' package.
In most use cases to use profiler service it's enough to do 'import _ net/http/pprof', which automatically registers a handler in the default http.Server. Slight inconvenience is that APIserver uses default server for intra-cluster communication, so plugging profiler to it is not really useful. In 'pkg/master/server/server.go' more servers are created and started as separate goroutines. The one that is usually serving external traffic is secureServer. The handler for this traffic is defined in 'pkg/master/master.go' and stored in Handler variable. It is created from HTTP multiplexer, so the only thing that needs to be done is adding profiler handler functions to this multiplexer. This is exactly what lines after TL;DR do.
In most use cases to use profiler service it's enough to do 'import _ net/http/pprof', which automatically registers a handler in the default http.Server. Slight inconvenience is that APIserver uses default server for intra-cluster communication, so plugging profiler to it is not really useful. In 'pkg/master/server/server.go' more servers are created and started as separate goroutines. The one that is usually serving external traffic is secureServer. The handler for this traffic is defined in 'pkg/master/master.go' and stored in Handler variable. It is created from HTTP multiplexer, so the only thing that needs to be done is adding profiler handler functions to this multiplexer. This is exactly what lines after TL;DR do.
## Connecting to the profiler
## Connecting to the profiler
Even when running profiler I found not really straightforward to use 'go tool pprof' with it. The problem is that at least for dev purposes certificates generated for APIserver are not signed by anyone trusted and because secureServer serves only secure traffic it isn't straightforward to connect to the service. The best workaround I found is by creating an ssh tunnel from the kubernetes_master open unsecured port to some external server, and use this server as a proxy. To save everyone looking for correct ssh flags, it is done by running:
Even when running profiler I found not really straightforward to use 'go tool pprof' with it. The problem is that at least for dev purposes certificates generated for APIserver are not signed by anyone trusted and because secureServer serves only secure traffic it isn't straightforward to connect to the service. The best workaround I found is by creating an ssh tunnel from the kubernetes_master open unsecured port to some external server, and use this server as a proxy. To save everyone looking for correct ssh flags, it is done by running:
@@ -96,6 +96,7 @@ Alternately, you can download and install the latest Kubernetes release from [th
...
@@ -96,6 +96,7 @@ Alternately, you can download and install the latest Kubernetes release from [th
cd kubernetes
cd kubernetes
cluster/kube-up.sh
cluster/kube-up.sh
```
```
If you want more than one cluster running in your project, want to use a different name, or want a different number of worker nodes, see the `<kubernetes>/cluster/gce/config-default.sh` file for more fine-grained configuration before you start up your cluster.
If you want more than one cluster running in your project, want to use a different name, or want a different number of worker nodes, see the `<kubernetes>/cluster/gce/config-default.sh` file for more fine-grained configuration before you start up your cluster.
If you run into trouble, please see the section on [troubleshooting](gce.md#troubleshooting), post to the
If you run into trouble, please see the section on [troubleshooting](gce.md#troubleshooting), post to the
@@ -56,6 +56,7 @@ This diagram shows four nodes created on a Google Compute Engine cluster with th
...
@@ -56,6 +56,7 @@ This diagram shows four nodes created on a Google Compute Engine cluster with th
[cluster DNS service](../admin/dns.md) runs on one of the nodes and a pod which provides monitoring support runs on another node.
[cluster DNS service](../admin/dns.md) 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](../../examples/blog-logging/counter-pod.yaml):
To help explain how cluster level logging works let’s start off with a synthetic log generator pod specification [counter-pod.yaml](../../examples/blog-logging/counter-pod.yaml):
```
```
apiVersion: v1
apiVersion: v1
kind: Pod
kind: Pod
...
@@ -69,6 +70,7 @@ To help explain how cluster level logging works let’s start off with a synthet
...
@@ -69,6 +70,7 @@ To help explain how cluster level logging works let’s start off with a synthet
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
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.
namespace.
...
@@ -78,11 +80,13 @@ namespace.
...
@@ -78,11 +80,13 @@ namespace.
```
```
We can observe the running pod:
We can observe the running pod:
```
```
$ kubectl get pods
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
NAME READY STATUS RESTARTS AGE
counter 1/1 Running 0 5m
counter 1/1 Running 0 5m
```
```
This step may take a few minutes to download the ubuntu:14.04 image during which the pod status will be shown as `Pending`.
This step may take a few minutes to download the ubuntu:14.04 image during which the pod status will be shown as `Pending`.
One of the nodes is now running the counter pod:
One of the nodes is now running the counter pod:
...
@@ -127,6 +131,7 @@ Now let’s restart the counter.
...
@@ -127,6 +131,7 @@ Now let’s restart the counter.
If connectivity is OK, you will see an output of the available keys in etcd (if any).
If connectivity is OK, you will see an output of the available keys in etcd (if any).
### Start Kubernetes-Mesos Services
### Start Kubernetes-Mesos Services
Update your PATH to more easily run the Kubernetes-Mesos binaries:
Update your PATH to more easily run the Kubernetes-Mesos binaries:
```bash
```bash
$ export PATH="$(pwd)/_output/local/go/bin:$PATH"
$ export PATH="$(pwd)/_output/local/go/bin:$PATH"
```
```
Identify your Mesos master: depending on your Mesos installation this is either a `host:port` like `mesos_master:5050` or a ZooKeeper URL like `zk://zookeeper:2181/mesos`.
Identify your Mesos master: depending on your Mesos installation this is either a `host:port` like `mesos_master:5050` or a ZooKeeper URL like `zk://zookeeper:2181/mesos`.
In order to let Kubernetes survive Mesos master changes, the ZooKeeper URL is recommended for production environments.
In order to let Kubernetes survive Mesos master changes, the ZooKeeper URL is recommended for production environments.
```bash
```bash
$ export MESOS_MASTER=<host:port or zk:// url>
$ export MESOS_MASTER=<host:port or zk:// url>
```
```
Create a cloud config file `mesos-cloud.conf` in the current directory with the following contents:
Create a cloud config file `mesos-cloud.conf` in the current directory with the following contents:
```bash
```bash
$ cat<<EOF >mesos-cloud.conf
$ cat<<EOF >mesos-cloud.conf
[mesos-cloud]
[mesos-cloud]
...
@@ -166,6 +174,7 @@ Disown your background jobs so that they'll stay running if you log out.
...
@@ -166,6 +174,7 @@ Disown your background jobs so that they'll stay running if you log out.
```bash
```bash
$ disown-a
$ disown-a
```
```
#### Validate KM Services
#### Validate KM Services
Add the appropriate binary folder to your ```PATH``` to access kubectl:
Add the appropriate binary folder to your ```PATH``` to access kubectl:
@@ -47,20 +47,24 @@ We still have [a bunch of work](https://github.com/GoogleCloudPlatform/kubernete
...
@@ -47,20 +47,24 @@ We still have [a bunch of work](https://github.com/GoogleCloudPlatform/kubernete
More details about the networking of rkt can be found in the [documentation](https://github.com/coreos/rkt/blob/master/Documentation/networking.md).
More details about the networking of rkt can be found in the [documentation](https://github.com/coreos/rkt/blob/master/Documentation/networking.md).
To start the `rkt metadata service`, you can simply run:
To start the `rkt metadata service`, you can simply run:
```shell
```shell
$ sudo rkt metadata-service
$ sudo rkt metadata-service
```
```
If you want the service to be running as a systemd service, then:
If you want the service to be running as a systemd service, then:
```shell
```shell
$ sudo systemd-run rkt metadata-service
$ sudo systemd-run rkt metadata-service
```
```
Alternatively, you can use the [rkt-metadata.service](https://github.com/coreos/rkt/blob/master/dist/init/systemd/rkt-metadata.service) and [rkt-metadata.socket](https://github.com/coreos/rkt/blob/master/dist/init/systemd/rkt-metadata.socket) to start the service.
Alternatively, you can use the [rkt-metadata.service](https://github.com/coreos/rkt/blob/master/dist/init/systemd/rkt-metadata.service) and [rkt-metadata.socket](https://github.com/coreos/rkt/blob/master/dist/init/systemd/rkt-metadata.socket) to start the service.
### Local cluster
### Local cluster
To use rkt as the container runtime, you just need to set the environment variable `CONTAINER_RUNTIME`:
To use rkt as the container runtime, you just need to set the environment variable `CONTAINER_RUNTIME`:
```shell
```shell
$ export CONTAINER_RUNTIME=rkt
$ export CONTAINER_RUNTIME=rkt
$ hack/local-up-cluster.sh
$ hack/local-up-cluster.sh
...
@@ -69,6 +73,7 @@ $ hack/local-up-cluster.sh
...
@@ -69,6 +73,7 @@ $ hack/local-up-cluster.sh
### CoreOS cluster on Google Compute Engine (GCE)
### CoreOS cluster on Google Compute Engine (GCE)
To use rkt as the container runtime for your CoreOS cluster on GCE, you need to specify the OS distribution, project, image:
To use rkt as the container runtime for your CoreOS cluster on GCE, you need to specify the OS distribution, project, image:
@@ -207,6 +213,7 @@ You have several options for connecting to nodes, pods and services from outside
...
@@ -207,6 +213,7 @@ You have several options for connecting to nodes, pods and services from outside
Typically, there are several services which are started on a cluster by default. Get a list of these
Typically, there are several services which are started on a cluster by default. Get a list of these
with the `kubectl cluster-info` command:
with the `kubectl cluster-info` command:
```
```
$ kubectl cluster-info
$ kubectl cluster-info
...
@@ -217,6 +224,7 @@ $ kubectl cluster-info
...
@@ -217,6 +224,7 @@ $ kubectl cluster-info
grafana is running at https://104.197.5.247/api/v1/proxy/namespaces/default/services/monitoring-grafana
grafana is running at https://104.197.5.247/api/v1/proxy/namespaces/default/services/monitoring-grafana
heapster is running at https://104.197.5.247/api/v1/proxy/namespaces/default/services/monitoring-heapster
heapster is running at https://104.197.5.247/api/v1/proxy/namespaces/default/services/monitoring-heapster
```
```
This shows the proxy-verb URL for accessing each service.
This shows the proxy-verb URL for accessing each service.
For example, this cluster has cluster-level logging enabled (using Elasticsearch), which can be reached
For example, this cluster has cluster-level logging enabled (using Elasticsearch), which can be reached
at `https://104.197.5.247/api/v1/proxy/namespaces/default/services/elasticsearch-logging/` if suitable credentials are passed, or through a kubectl proxy at, for example:
at `https://104.197.5.247/api/v1/proxy/namespaces/default/services/elasticsearch-logging/` if suitable credentials are passed, or through a kubectl proxy at, for example:
...
@@ -232,6 +240,7 @@ about namespaces? 'proxy' verb? -->
...
@@ -232,6 +240,7 @@ about namespaces? 'proxy' verb? -->
##### Examples
##### Examples
* To access the Elasticsearch service endpoint `_search?q=user:kimchy`, you would use: `http://104.197.5.247/api/v1/proxy/namespaces/default/services/elasticsearch-logging/_search?q=user:kimchy`
* To access the Elasticsearch service endpoint `_search?q=user:kimchy`, you would use: `http://104.197.5.247/api/v1/proxy/namespaces/default/services/elasticsearch-logging/_search?q=user:kimchy`
* To access the Elasticsearch cluster health information `_cluster/health?pretty=true`, you would use: `https://104.197.5.247/api/v1/proxy/namespaces/default/services/elasticsearch-logging/_cluster/health?pretty=true`
* To access the Elasticsearch cluster health information `_cluster/health?pretty=true`, you would use: `https://104.197.5.247/api/v1/proxy/namespaces/default/services/elasticsearch-logging/_cluster/health?pretty=true`
@@ -37,6 +37,7 @@ We have [labels](labels.md) for identifying metadata.
...
@@ -37,6 +37,7 @@ We have [labels](labels.md) for identifying metadata.
It is also useful to be able to attach arbitrary non-identifying metadata, for retrieval by API clients such as tools, libraries, etc. This information may be large, may be structured or unstructured, may include characters not permitted by labels, etc. Such information would not be used for object selection and therefore doesn't belong in labels.
It is also useful to be able to attach arbitrary non-identifying metadata, for retrieval by API clients such as tools, libraries, etc. This information may be large, may be structured or unstructured, may include characters not permitted by labels, etc. Such information would not be used for object selection and therefore doesn't belong in labels.
@@ -152,6 +152,7 @@ then pod resource usage can be retrieved from the monitoring system.
...
@@ -152,6 +152,7 @@ then pod resource usage can be retrieved from the monitoring system.
If the scheduler cannot find any node where a pod can fit, then the pod will remain unscheduled
If the scheduler cannot find any node where a pod can fit, then the pod will remain unscheduled
until a place can be found. An event will be produced each time the scheduler fails to find a
until a place can be found. An event will be produced each time the scheduler fails to find a
place for the pod, like this:
place for the pod, like this:
```
```
$ kubectl describe pods/frontend | grep -A 3 Events
$ kubectl describe pods/frontend | grep -A 3 Events
Events:
Events:
...
@@ -217,11 +218,13 @@ The `Restart Count: 5` indicates that the `simmemleak` container in this pod wa
...
@@ -217,11 +218,13 @@ The `Restart Count: 5` indicates that the `simmemleak` container in this pod wa
Once [#10861](https://github.com/GoogleCloudPlatform/kubernetes/issues/10861) is resolved the reason for the termination of the last container will also be printed in this output.
Once [#10861](https://github.com/GoogleCloudPlatform/kubernetes/issues/10861) is resolved the reason for the termination of the last container will also be printed in this output.
Until then you can call `get pod` with the `-o template -t ...` option to fetch the status of previously terminated containers:
Until then you can call `get pod` with the `-o template -t ...` option to fetch the status of previously terminated containers:
```
```
[13:59:01] $ ./cluster/kubectl.sh get pod -o template -t '{{range.status.containerStatuses}}{{"Container Name: "}}{{.name}}{{"\r\nLastState: "}}{{.lastState}}{{end}}' simmemleak-60xbc
[13:59:01] $ ./cluster/kubectl.sh get pod -o template -t '{{range.status.containerStatuses}}{{"Container Name: "}}{{.name}}{{"\r\nLastState: "}}{{.lastState}}{{end}}' simmemleak-60xbc
@@ -68,6 +68,7 @@ spec: # specification of the pod’s contents
...
@@ -68,6 +68,7 @@ spec: # specification of the pod’s contents
image:"ubuntu:14.04"
image:"ubuntu:14.04"
command:["/bin/echo","hello”,”world"]
command:["/bin/echo","hello”,”world"]
```
```
The value of `metadata.name`, `hello-world`, will be the name of the pod resource created, and must be unique within the cluster, whereas `containers[0].name` is just a nickname for the container within that pod. `image` is the name of the Docker image, which Kubernetes expects to be able to pull from a registry, the [Docker Hub](https://registry.hub.docker.com/) by default.
The value of `metadata.name`, `hello-world`, will be the name of the pod resource created, and must be unique within the cluster, whereas `containers[0].name` is just a nickname for the container within that pod. `image` is the name of the Docker image, which Kubernetes expects to be able to pull from a registry, the [Docker Hub](https://registry.hub.docker.com/) by default.
`restartPolicy: Never` indicates that we just want to run the container once and then terminate the pod.
`restartPolicy: Never` indicates that we just want to run the container once and then terminate the pod.
...
@@ -80,30 +81,36 @@ The [`command`](containers.md#containers-and-commands) overrides the Docker cont
...
@@ -80,30 +81,36 @@ The [`command`](containers.md#containers-and-commands) overrides the Docker cont
```
```
This pod can be created using the `create` command:
This pod can be created using the `create` command:
```bash
```bash
$ kubectl create -f ./hello-world.yaml
$ kubectl create -f ./hello-world.yaml
pods/hello-world
pods/hello-world
```
```
`kubectl` prints the resource type and name of the resource created when successful.
`kubectl` prints the resource type and name of the resource created when successful.
## Validating configuration
## Validating configuration
If you’re not sure you specified the resource correctly, you can ask `kubectl` to validate it for you:
If you’re not sure you specified the resource correctly, you can ask `kubectl` to validate it for you:
```bash
```bash
$ kubectl create -f ./hello-world.yaml --validate
$ kubectl create -f ./hello-world.yaml --validate
```
```
Let’s say you specified `entrypoint` instead of `command`. You’d see output as follows:
Let’s say you specified `entrypoint` instead of `command`. You’d see output as follows:
I0709 06:33:05.600988 14160 schema.go:129] this may be a false alarm, see https://github.com/GoogleCloudPlatform/kubernetes/issues/6842
I0709 06:33:05.600988 14160 schema.go:129] this may be a false alarm, see https://github.com/GoogleCloudPlatform/kubernetes/issues/6842
pods/hello-world
pods/hello-world
```
```
`kubectl create --validate` currently warns about problems it detects, but creates the resource anyway, unless a required field is absent or a field value is invalid. Unknown API fields are ignored, so be careful. This pod was created, but with no `command`, which is an optional field, since the image may specify an `Entrypoint`.
`kubectl create --validate` currently warns about problems it detects, but creates the resource anyway, unless a required field is absent or a field value is invalid. Unknown API fields are ignored, so be careful. This pod was created, but with no `command`, which is an optional field, since the image may specify an `Entrypoint`.
## Environment variables and variable expansion
## Environment variables and variable expansion
Kubernetes [does not automatically run commands in a shell](https://github.com/GoogleCloudPlatform/kubernetes/wiki/User-FAQ#use-of-environment-variables-on-the-command-line)(not all images contain shells). If you would like to run your command in a shell, such as to expand environment variables (specified using `env`), you could do the following:
Kubernetes [does not automatically run commands in a shell](https://github.com/GoogleCloudPlatform/kubernetes/wiki/User-FAQ#use-of-environment-variables-on-the-command-line)(not all images contain shells). If you would like to run your command in a shell, such as to expand environment variables (specified using `env`), you could do the following:
```yaml
```yaml
apiVersion:v1
apiVersion:v1
kind:Pod
kind:Pod
...
@@ -122,52 +129,65 @@ spec: # specification of the pod’s contents
...
@@ -122,52 +129,65 @@ spec: # specification of the pod’s contents
```
```
However, a shell isn’t necessary just to expand environment variables. Kubernetes will do it for you if you use [`$(ENVVAR)` syntax](../../docs/design/expansion.md):
However, a shell isn’t necessary just to expand environment variables. Kubernetes will do it for you if you use [`$(ENVVAR)` syntax](../../docs/design/expansion.md):
```yaml
```yaml
command:["/bin/echo"]
command:["/bin/echo"]
args:["$(MESSAGE)"]
args:["$(MESSAGE)"]
```
```
## Viewing pod status
## Viewing pod status
You can see the pod you created (actually all of your cluster's pods) using the `get` command.
You can see the pod you created (actually all of your cluster's pods) using the `get` command.
If you’re quick, it will look as follows:
If you’re quick, it will look as follows:
```bash
```bash
$ kubectl get pods
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
NAME READY STATUS RESTARTS AGE
hello-world 0/1 Pending 0 0s
hello-world 0/1 Pending 0 0s
```
```
Initially, a newly created pod is unscheduled -- no node has been selected to run it. Scheduling happens after creation, but is fast, so you normally shouldn’t see pods in an unscheduled state unless there’s a problem.
Initially, a newly created pod is unscheduled -- no node has been selected to run it. Scheduling happens after creation, but is fast, so you normally shouldn’t see pods in an unscheduled state unless there’s a problem.
After the pod has been scheduled, the image may need to be pulled to the node on which it was scheduled, if it hadn’t be pulled already. After a few seconds, you should see the container running:
After the pod has been scheduled, the image may need to be pulled to the node on which it was scheduled, if it hadn’t be pulled already. After a few seconds, you should see the container running:
```bash
```bash
$ kubectl get pods
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
NAME READY STATUS RESTARTS AGE
hello-world 1/1 Running 0 5s
hello-world 1/1 Running 0 5s
```
```
The `READY` column shows how many containers in the pod are running.
The `READY` column shows how many containers in the pod are running.
Almost immediately after it starts running, this command will terminate. `kubectl` shows that the container is no longer running and displays the exit status:
Almost immediately after it starts running, this command will terminate. `kubectl` shows that the container is no longer running and displays the exit status:
```bash
```bash
$ kubectl get pods
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
NAME READY STATUS RESTARTS AGE
hello-world 0/1 ExitCode:0 0 15s
hello-world 0/1 ExitCode:0 0 15s
```
```
## Viewing pod output
## Viewing pod output
You probably want to see the output of the command you ran. As with [`docker logs`](https://docs.docker.com/userguide/usingdocker/), `kubectl logs` will show you the output:
You probably want to see the output of the command you ran. As with [`docker logs`](https://docs.docker.com/userguide/usingdocker/), `kubectl logs` will show you the output:
```bash
```bash
$ kubectl logs hello-world
$ kubectl logs hello-world
hello world
hello world
```
```
## Deleting pods
## Deleting pods
When you’re done looking at the output, you should delete the pod:
When you’re done looking at the output, you should delete the pod:
```bash
```bash
$ kubectl delete pod hello-world
$ kubectl delete pod hello-world
pods/hello-world
pods/hello-world
```
```
As with `create`, `kubectl` prints the resource type and name of the resource deleted when successful.
As with `create`, `kubectl` prints the resource type and name of the resource deleted when successful.
You can also use the resource/name format to specify the pod:
You can also use the resource/name format to specify the pod:
@@ -60,6 +60,7 @@ This guide uses a simple nginx server to demonstrate proof of concept. The same
...
@@ -60,6 +60,7 @@ This guide uses a simple nginx server to demonstrate proof of concept. The same
## Exposing pods to the cluster
## Exposing pods to the cluster
We did this in a previous example, but lets do it once again and focus on the networking perspective. Create an nginx pod, and note that it has a container port specification:
We did this in a previous example, but lets do it once again and focus on the networking perspective. Create an nginx pod, and note that it has a container port specification:
```yaml
```yaml
$ cat nginxrc.yaml
$ cat nginxrc.yaml
apiVersion:v1
apiVersion:v1
...
@@ -81,6 +82,7 @@ spec:
...
@@ -81,6 +82,7 @@ spec:
```
```
This makes it accessible from any node in your cluster. Check the nodes the pod is running on:
This makes it accessible from any node in your cluster. Check the nodes the pod is running on:
$ kubectl get pods -lapp=nginx -o json | grep podIP
$ kubectl get pods -lapp=nginx -o json | grep podIP
"podIP": "10.245.0.15",
"podIP": "10.245.0.15",
"podIP": "10.245.0.14",
"podIP": "10.245.0.14",
```
```
You should be able to ssh into any node in your cluster and curl both ips. Note that the containers are *not* using port 80 on the node, nor are there any special NAT rules to route traffic to the pod. This means you can run multiple nginx pods on the same node all using the same containerPort and access them from any other pod or node in your cluster using ip. Like Docker, ports can still be published to the host node's interface(s), but the need for this is radically diminished because of the networking model.
You should be able to ssh into any node in your cluster and curl both ips. Note that the containers are *not* using port 80 on the node, nor are there any special NAT rules to route traffic to the pod. This means you can run multiple nginx pods on the same node all using the same containerPort and access them from any other pod or node in your cluster using ip. Like Docker, ports can still be published to the host node's interface(s), but the need for this is radically diminished because of the networking model.
You can read more about [how we achieve this](../admin/networking.md#how-to-achieve-this) if you’re curious.
You can read more about [how we achieve this](../admin/networking.md#how-to-achieve-this) if you’re curious.
...
@@ -105,6 +109,7 @@ So we have pods running nginx in a flat, cluster wide, address space. In theory,
...
@@ -105,6 +109,7 @@ So we have pods running nginx in a flat, cluster wide, address space. In theory,
A Kubernetes Service is an abstraction which defines a logical set of Pods running somewhere in your cluster, that all provide the same functionality. When created, each Service is assigned a unique IP address (also called clusterIP). This address is tied to the lifespan of the Service, and will not change while the Service is alive. Pods can be configured to talk to the Service, and know that communication to the Service will be automatically load-balanced out to some pod that is a member of the Service.
A Kubernetes Service is an abstraction which defines a logical set of Pods running somewhere in your cluster, that all provide the same functionality. When created, each Service is assigned a unique IP address (also called clusterIP). This address is tied to the lifespan of the Service, and will not change while the Service is alive. Pods can be configured to talk to the Service, and know that communication to the Service will be automatically load-balanced out to some pod that is a member of the Service.
You can create a Service for your 2 nginx replicas with the following yaml:
You can create a Service for your 2 nginx replicas with the following yaml:
```yaml
```yaml
$ cat nginxsvc.yaml
$ cat nginxsvc.yaml
apiVersion:v1
apiVersion:v1
...
@@ -120,7 +125,9 @@ spec:
...
@@ -120,7 +125,9 @@ spec:
selector:
selector:
app:nginx
app:nginx
```
```
This specification will create a Service which targets TCP port 80 on any Pod with the `app=nginx` label, and expose it on an abstracted Service port (`targetPort`: is the port the container accepts traffic on, `port`: is the abstracted Service port, which can be any port other pods use to access the Service). Check your Service:
This specification will create a Service which targets TCP port 80 on any Pod with the `app=nginx` label, and expose it on an abstracted Service port (`targetPort`: is the port the container accepts traffic on, `port`: is the abstracted Service port, which can be any port other pods use to access the Service). Check your Service:
As mentioned previously, a Service is backed by a group of pods. These pods are exposed through `endpoints`. The Service's selector will be evaluated continuously and the results will be POSTed to an Endpoints object also named `nginxsvc`. When a pod dies, it is automatically removed from the endpoints, and new pods matching the Service’s selector will automatically get added to the endpoints. Check the endpoints, and note that the ips are the same as the pods created in the first step:
As mentioned previously, a Service is backed by a group of pods. These pods are exposed through `endpoints`. The Service's selector will be evaluated continuously and the results will be POSTed to an Endpoints object also named `nginxsvc`. When a pod dies, it is automatically removed from the endpoints, and new pods matching the Service’s selector will automatically get added to the endpoints. Check the endpoints, and note that the ips are the same as the pods created in the first step:
```shell
```shell
$ kubectl describe svc nginxsvc
$ kubectl describe svc nginxsvc
Name: nginxsvc
Name: nginxsvc
...
@@ -145,6 +153,7 @@ $ kubectl get ep
...
@@ -145,6 +153,7 @@ $ kubectl get ep
NAME ENDPOINTS
NAME ENDPOINTS
nginxsvc 10.245.0.14:80,10.245.0.15:80
nginxsvc 10.245.0.14:80,10.245.0.15:80
```
```
You should now be able to curl the nginx Service on `10.0.116.146:80` from any node in your cluster. Note that the Service ip is completely virtual, it never hits the wire, if you’re curious about how this works you can read more about the [service proxy](services.md#virtual-ips-and-service-proxies).
You should now be able to curl the nginx Service on `10.0.116.146:80` from any node in your cluster. Note that the Service ip is completely virtual, it never hits the wire, if you’re curious about how this works you can read more about the [service proxy](services.md#virtual-ips-and-service-proxies).
## Accessing the Service
## Accessing the Service
...
@@ -153,12 +162,15 @@ Kubernetes supports 2 primary modes of finding a Service - environment variables
...
@@ -153,12 +162,15 @@ Kubernetes supports 2 primary modes of finding a Service - environment variables
### Environment Variables
### Environment Variables
When a Pod is run on a Node, the kubelet adds a set of environment variables for each active Service. This introduces an ordering problem. To see why, inspect the environment of your running nginx pods:
When a Pod is run on a Node, the kubelet adds a set of environment variables for each active Service. This introduces an ordering problem. To see why, inspect the environment of your running nginx pods:
```shell
```shell
$ kubectl exec my-nginx-6isf4 --printenv | grep SERVICE
$ kubectl exec my-nginx-6isf4 --printenv | grep SERVICE
KUBERNETES_SERVICE_HOST=10.0.0.1
KUBERNETES_SERVICE_HOST=10.0.0.1
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT=443
```
```
Note there’s no mention of your Service. This is because you created the replicas before the Service. Another disadvantage of doing this is that the scheduler might put both pods on the same machine, which will take your entire Service down if it dies. We can do this the right way by killing the 2 pods and waiting for the replication controller to recreate them. This time around the Service exists *before* the replicas. This will given you scheduler level Service spreading of your pods (provided all your nodes have equal capacity), as well as the right environment variables:
Note there’s no mention of your Service. This is because you created the replicas before the Service. Another disadvantage of doing this is that the scheduler might put both pods on the same machine, which will take your entire Service down if it dies. We can do this the right way by killing the 2 pods and waiting for the replication controller to recreate them. This time around the Service exists *before* the replicas. This will given you scheduler level Service spreading of your pods (provided all your nodes have equal capacity), as well as the right environment variables:
Kubernetes offers a DNS cluster addon Service that uses skydns to automatically assign dns names to other Services. You can check if it’s running on your cluster:
Kubernetes offers a DNS cluster addon Service that uses skydns to automatically assign dns names to other Services. You can check if it’s running on your cluster:
```shell
```shell
$ kubectl get services kube-dns --namespace=kube-system
$ kubectl get services kube-dns --namespace=kube-system
NAME LABELS SELECTOR IP(S) PORT(S)
NAME LABELS SELECTOR IP(S) PORT(S)
kube-dns <none> k8s-app=kube-dns 10.0.0.10 53/UDP
kube-dns <none> k8s-app=kube-dns 10.0.0.10 53/UDP
53/TCP
53/TCP
```
```
If it isn’t running, you can [enable it](../../cluster/addons/dns/README.md#how-do-i-configure-it). The rest of this section will assume you have a Service with a long lived ip (nginxsvc), and a dns server that has assigned a name to that ip (the kube-dns cluster addon), so you can talk to the Service from any pod in your cluster using standard methods (e.g. gethostbyname). Let’s create another pod to test this:
If it isn’t running, you can [enable it](../../cluster/addons/dns/README.md#how-do-i-configure-it). The rest of this section will assume you have a Service with a long lived ip (nginxsvc), and a dns server that has assigned a name to that ip (the kube-dns cluster addon), so you can talk to the Service from any pod in your cluster using standard methods (e.g. gethostbyname). Let’s create another pod to test this:
```yaml
```yaml
...
@@ -199,7 +213,9 @@ spec:
...
@@ -199,7 +213,9 @@ spec:
name:curlcontainer
name:curlcontainer
restartPolicy:Always
restartPolicy:Always
```
```
And perform a lookup of the nginx Service
And perform a lookup of the nginx Service
```shell
```shell
$ kubectl create -f ./curlpod.yaml
$ kubectl create -f ./curlpod.yaml
default/curlpod
default/curlpod
...
@@ -222,6 +238,7 @@ Till now we have only accessed the nginx server from within the cluster. Before
...
@@ -222,6 +238,7 @@ Till now we have only accessed the nginx server from within the cluster. Before
* A [secret](secrets.md) that makes the certificates accessible to pods
* A [secret](secrets.md) that makes the certificates accessible to pods
You can acquire all these from the [nginx https example](../../examples/https-nginx/README.md), in short:
You can acquire all these from the [nginx https example](../../examples/https-nginx/README.md), in short:
```shell
```shell
$ make keys secret KEY=/tmp/nginx.key CERT=/tmp/nginx.crt SECRET=/tmp/secret.json
$ make keys secret KEY=/tmp/nginx.key CERT=/tmp/nginx.crt SECRET=/tmp/secret.json
$ kubectl create -f /tmp/secret.json
$ kubectl create -f /tmp/secret.json
...
@@ -233,6 +250,7 @@ nginxsecret Opaque 2
...
@@ -233,6 +250,7 @@ nginxsecret Opaque 2
```
```
Now modify your nginx replicas to start a https server using the certificate in the secret, and the Service, to expose both ports (80 and 443):
Now modify your nginx replicas to start a https server using the certificate in the secret, and the Service, to expose both ports (80 and 443):
```yaml
```yaml
$ cat nginx-app.yaml
$ cat nginx-app.yaml
apiVersion:v1
apiVersion:v1
...
@@ -279,6 +297,7 @@ spec:
...
@@ -279,6 +297,7 @@ spec:
-mountPath:/etc/nginx/ssl
-mountPath:/etc/nginx/ssl
name:secret-volume
name:secret-volume
```
```
Noteworthy points about the nginx-app manifest:
Noteworthy points about the nginx-app manifest:
- It contains both rc and service specification in the same file
- It contains both rc and service specification in the same file
- The [nginx server](../../examples/https-nginx/default.conf) serves http traffic on port 80 and https traffic on 443, and nginx Service exposes both ports.
- The [nginx server](../../examples/https-nginx/default.conf) serves http traffic on port 80 and https traffic on 443, and nginx Service exposes both ports.
@@ -35,11 +35,14 @@ Documentation for other releases can be found at
...
@@ -35,11 +35,14 @@ Documentation for other releases can be found at
kubectl port-forward forwards connections to a local port to a port on a pod. Its man page is available [here](kubectl/kubectl_port-forward.md). Compared to [kubectl proxy](accessing-the-cluster.md#using-kubectl-proxy), `kubectl port-forward` is more generic as it can forward TCP traffic while `kubectl proxy` can only forward HTTP traffic. This guide demonstrates how to use `kubectl port-forward` to connect to a Redis database, which may be useful for database debugging.
kubectl port-forward forwards connections to a local port to a port on a pod. Its man page is available [here](kubectl/kubectl_port-forward.md). Compared to [kubectl proxy](accessing-the-cluster.md#using-kubectl-proxy), `kubectl port-forward` is more generic as it can forward TCP traffic while `kubectl proxy` can only forward HTTP traffic. This guide demonstrates how to use `kubectl port-forward` to connect to a Redis database, which may be useful for database debugging.
## Creating a Redis master
## Creating a Redis master
```
```
$kubectl create examples/redis/redis-master.yaml
$kubectl create examples/redis/redis-master.yaml
pods/redis-master
pods/redis-master
```
```
wait until the Redis master pod is Running and Ready,
wait until the Redis master pod is Running and Ready,
```
```
$ kubectl get pods
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
NAME READY STATUS RESTARTS AGE
...
@@ -49,6 +52,7 @@ redis-master 2/2 Running 0 41s
...
@@ -49,6 +52,7 @@ redis-master 2/2 Running 0 41s
## Connecting to the Redis master[a]
## Connecting to the Redis master[a]
The Redis master is listening on port 6397, to verify this,
The Redis master is listening on port 6397, to verify this,
```
```
$ kubectl get pods redis-master -t='{{(index (index .spec.containers 0).ports 0).containerPort}}{{"\n"}}'
$ kubectl get pods redis-master -t='{{(index (index .spec.containers 0).ports 0).containerPort}}{{"\n"}}'
@@ -36,19 +36,23 @@ You have seen the [basics](accessing-the-cluster.md) about `kubectl proxy` and `
...
@@ -36,19 +36,23 @@ You have seen the [basics](accessing-the-cluster.md) about `kubectl proxy` and `
##Getting the apiserver proxy URL of kube-ui
##Getting the apiserver proxy URL of kube-ui
kube-ui is deployed as a cluster add-on. To find its apiserver proxy URL,
kube-ui is deployed as a cluster add-on. To find its apiserver proxy URL,
```
```
$ kubectl cluster-info | grep "KubeUI"
$ kubectl cluster-info | grep "KubeUI"
KubeUI is running at https://173.255.119.104/api/v1/proxy/namespaces/kube-system/services/kube-ui
KubeUI is running at https://173.255.119.104/api/v1/proxy/namespaces/kube-system/services/kube-ui
```
```
if this command does not find the URL, try the steps [here](ui.md#accessing-the-ui).
if this command does not find the URL, try the steps [here](ui.md#accessing-the-ui).
##Connecting to the kube-ui service from your local workstation
##Connecting to the kube-ui service from your local workstation
The above proxy URL is an access to the kube-ui service provided by the apiserver. To access it, you still need to authenticate to the apiserver. `kubectl proxy` can handle the authentication.
The above proxy URL is an access to the kube-ui service provided by the apiserver. To access it, you still need to authenticate to the apiserver. `kubectl proxy` can handle the authentication.
```
```
$ kubectl proxy --port=8001
$ kubectl proxy --port=8001
Starting to serve on localhost:8001
Starting to serve on localhost:8001
```
```
Now you can access the kube-ui service on your local workstation at [http://localhost:8001/api/v1/proxy/namespaces/kube-system/services/kube-ui](http://localhost:8001/api/v1/proxy/namespaces/kube-system/services/kube-ui)
Now you can access the kube-ui service on your local workstation at [http://localhost:8001/api/v1/proxy/namespaces/kube-system/services/kube-ui](http://localhost:8001/api/v1/proxy/namespaces/kube-system/services/kube-ui)
@@ -52,6 +52,7 @@ Kubernetes creates and manages sets of replicated containers (actually, replicat
...
@@ -52,6 +52,7 @@ Kubernetes creates and manages sets of replicated containers (actually, replicat
A replication controller simply ensures that a specified number of pod "replicas" are running at any one time. If there are too many, it will kill some. If there are too few, it will start more. It’s analogous to Google Compute Engine’s [Instance Group Manager](https://cloud.google.com/compute/docs/instance-groups/manager/) or AWS’s [Auto-scaling Group](http://docs.aws.amazon.com/AutoScaling/latest/DeveloperGuide/AutoScalingGroup.html)(with no scaling policies).
A replication controller simply ensures that a specified number of pod "replicas" are running at any one time. If there are too many, it will kill some. If there are too few, it will start more. It’s analogous to Google Compute Engine’s [Instance Group Manager](https://cloud.google.com/compute/docs/instance-groups/manager/) or AWS’s [Auto-scaling Group](http://docs.aws.amazon.com/AutoScaling/latest/DeveloperGuide/AutoScalingGroup.html)(with no scaling policies).
The replication controller created to run nginx by `kubctl run` in the [Quick start](quick-start.md) could be specified using YAML as follows:
The replication controller created to run nginx by `kubctl run` in the [Quick start](quick-start.md) could be specified using YAML as follows:
```yaml
```yaml
apiVersion:v1
apiVersion:v1
kind:ReplicationController
kind:ReplicationController
...
@@ -70,9 +71,11 @@ spec:
...
@@ -70,9 +71,11 @@ spec:
ports:
ports:
-containerPort:80
-containerPort:80
```
```
Some differences compared to specifying just a pod are that the `kind` is `ReplicationController`, the number of `replicas` desired is specified, and the pod specification is under the `template` field. The names of the pods don’t need to be specified explicitly because they are generated from the name of the replication controller.
Some differences compared to specifying just a pod are that the `kind` is `ReplicationController`, the number of `replicas` desired is specified, and the pod specification is under the `template` field. The names of the pods don’t need to be specified explicitly because they are generated from the name of the replication controller.
This replication controller can be created using `create`, just as with pods:
This replication controller can be created using `create`, just as with pods:
```bash
```bash
$ kubectl create -f ./nginx-rc.yaml
$ kubectl create -f ./nginx-rc.yaml
replicationcontrollers/my-nginx
replicationcontrollers/my-nginx
...
@@ -83,23 +86,28 @@ Unlike in the case where you directly create pods, a replication controller repl
...
@@ -83,23 +86,28 @@ Unlike in the case where you directly create pods, a replication controller repl
## Viewing replication controller status
## Viewing replication controller status
You can view the replication controller you created using `get`:
You can view the replication controller you created using `get`:
This tells you that your controller will ensure that you have two nginx replicas.
This tells you that your controller will ensure that you have two nginx replicas.
You can see those replicas using `get`, just as with pods you created directly:
You can see those replicas using `get`, just as with pods you created directly:
```bash
```bash
$ kubectl get pods
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
NAME READY STATUS RESTARTS AGE
my-nginx-065jq 1/1 Running 0 51s
my-nginx-065jq 1/1 Running 0 51s
my-nginx-buaiq 1/1 Running 0 51s
my-nginx-buaiq 1/1 Running 0 51s
```
```
## Deleting replication controllers
## Deleting replication controllers
When you want to kill your application, delete your replication controller, as in the [Quick start](quick-start.md):
When you want to kill your application, delete your replication controller, as in the [Quick start](quick-start.md):
```bash
```bash
$ kubectl delete rc my-nginx
$ kubectl delete rc my-nginx
replicationcontrollers/my-nginx
replicationcontrollers/my-nginx
...
@@ -112,6 +120,7 @@ If you try to delete the pods before deleting the replication controller, it wil
...
@@ -112,6 +120,7 @@ If you try to delete the pods before deleting the replication controller, it wil
## Labels
## Labels
Kubernetes uses user-defined key-value attributes called [*labels*](labels.md) to categorize and identify sets of resources, such as pods and replication controllers. The example above specified a single label in the pod template, with key `app` and value `nginx`. All pods created carry that label, which can be viewed using `-L`:
Kubernetes uses user-defined key-value attributes called [*labels*](labels.md) to categorize and identify sets of resources, such as pods and replication controllers. The example above specified a single label in the pod template, with key `app` and value `nginx`. All pods created carry that label, which can be viewed using `-L`:
More importantly, the pod template’s labels are used to create a [`selector`](labels.md#label-selectors) that will match pods carrying those labels. You can see this field by requesting it using the [Go template output format of `kubectl get`](kubectl/kubectl_get.md):
More importantly, the pod template’s labels are used to create a [`selector`](labels.md#label-selectors) that will match pods carrying those labels. You can see this field by requesting it using the [Go template output format of `kubectl get`](kubectl/kubectl_get.md):
```bash
```bash
$ kubectl get rc my-nginx -o template --template="{{.spec.selector}}"
$ kubectl get rc my-nginx -o template --template="{{.spec.selector}}"
@@ -36,6 +36,7 @@ _Labels_ are key/value pairs that are attached to objects, such as pods.
...
@@ -36,6 +36,7 @@ _Labels_ are key/value pairs that are attached to objects, such as pods.
Labels are intended to be used to specify identifying attributes of objects that are meaningful and relevant to users, but which do not directly imply semantics to the core system.
Labels are intended to be used to specify identifying attributes of objects that are meaningful and relevant to users, but which do not directly imply semantics to the core system.
Labels can be used to organize and to select subsets of objects. Labels can be attached to objects at creation time and subsequently added and modified at any time.
Labels can be used to organize and to select subsets of objects. Labels can be attached to objects at creation time and subsequently added and modified at any time.
Each object can have a set of key/value labels defined. Each Key must be unique for a given object.
Each object can have a set of key/value labels defined. Each Key must be unique for a given object.
```
```
"labels": {
"labels": {
"key1" : "value1",
"key1" : "value1",
...
@@ -85,6 +86,7 @@ An empty label selector (that is, one with zero requirements) selects every obje
...
@@ -85,6 +86,7 @@ An empty label selector (that is, one with zero requirements) selects every obje
_Equality-_ or _inequality-based_ requirements allow filtering by label keys and values. Matching objects must have all of the specified labels (both keys and values), though they may have additional labels as well.
_Equality-_ or _inequality-based_ requirements allow filtering by label keys and values. Matching objects must have all of the specified labels (both keys and values), though they may have additional labels as well.
Three kinds of operators are admitted `=`,`==`,`!=`. The first two represent _equality_ and are simply synonyms. While the latter represents _inequality_. For example:
Three kinds of operators are admitted `=`,`==`,`!=`. The first two represent _equality_ and are simply synonyms. While the latter represents _inequality_. For example:
```
```
environment = production
environment = production
tier != frontend
tier != frontend
...
@@ -98,11 +100,13 @@ One could filter for resources in `production` but not `frontend` using the comm
...
@@ -98,11 +100,13 @@ One could filter for resources in `production` but not `frontend` using the comm
### _Set-based_ requirement
### _Set-based_ requirement
_Set-based_ label requirements allow filtering keys according to a set of values. Matching objects must have all of the specified labels (i.e. all keys and at least one of the values specified for each key). Three kind of operators are supported: `in`,`notin` and exists (only the key identifier). For example:
_Set-based_ label requirements allow filtering keys according to a set of values. Matching objects must have all of the specified labels (i.e. all keys and at least one of the values specified for each key). Three kind of operators are supported: `in`,`notin` and exists (only the key identifier). For example:
```
```
environment in (production, qa)
environment in (production, qa)
tier notin (frontend, backend)
tier notin (frontend, backend)
partition
partition
```
```
The first example selects all resources with key equal to `environment` and value equal to `production` or `qa`.
The first example selects all resources with key equal to `environment` and value equal to `production` or `qa`.
The second example selects all resources with key equal to `tier` and value other than `frontend` and `backend`.
The second example selects all resources with key equal to `tier` and value other than `frontend` and `backend`.
The third example selects all resources including a label with key `partition`; no values are checked.
The third example selects all resources including a label with key `partition`; no values are checked.
@@ -34,6 +34,7 @@ Documentation for other releases can be found at
...
@@ -34,6 +34,7 @@ Documentation for other releases can be found at
This example shows two types of pod [health checks](../production-pods.md#liveness-and-readiness-probes-aka-health-checks): HTTP checks and container execution checks.
This example shows two types of pod [health checks](../production-pods.md#liveness-and-readiness-probes-aka-health-checks): HTTP checks and container execution checks.
The [exec-liveness.yaml](exec-liveness.yaml) demonstrates the container execution check.
The [exec-liveness.yaml](exec-liveness.yaml) demonstrates the container execution check.
```
```
livenessProbe:
livenessProbe:
exec:
exec:
...
@@ -43,16 +44,20 @@ The [exec-liveness.yaml](exec-liveness.yaml) demonstrates the container executio
...
@@ -43,16 +44,20 @@ The [exec-liveness.yaml](exec-liveness.yaml) demonstrates the container executio
initialDelaySeconds: 15
initialDelaySeconds: 15
timeoutSeconds: 1
timeoutSeconds: 1
```
```
Kubelet executes the command `cat /tmp/health` in the container and reports failure if the command returns a non-zero exit code.
Kubelet executes the command `cat /tmp/health` in the container and reports failure if the command returns a non-zero exit code.
Note that the container removes the `/tmp/health` file after 10 seconds,
Note that the container removes the `/tmp/health` file after 10 seconds,
so when Kubelet executes the health check 15 seconds (defined by initialDelaySeconds) after the container started, the check would fail.
so when Kubelet executes the health check 15 seconds (defined by initialDelaySeconds) after the container started, the check would fail.
The [http-liveness.yaml](http-liveness.yaml) demonstrates the HTTP check.
The [http-liveness.yaml](http-liveness.yaml) demonstrates the HTTP check.
```
```
livenessProbe:
livenessProbe:
httpGet:
httpGet:
...
@@ -61,18 +66,21 @@ The [http-liveness.yaml](http-liveness.yaml) demonstrates the HTTP check.
...
@@ -61,18 +66,21 @@ The [http-liveness.yaml](http-liveness.yaml) demonstrates the HTTP check.
initialDelaySeconds: 15
initialDelaySeconds: 15
timeoutSeconds: 1
timeoutSeconds: 1
```
```
The Kubelet sends a HTTP request to the specified path and port to perform the health check. If you take a look at image/server.go, you will see the server starts to respond with an error code 500 after 10 seconds, so the check fails.
The Kubelet sends a HTTP request to the specified path and port to perform the health check. If you take a look at image/server.go, you will see the server starts to respond with an error code 500 after 10 seconds, so the check fails.
This [guide](../walkthrough/k8s201.md#health-checking) has more information on health checks.
This [guide](../walkthrough/k8s201.md#health-checking) has more information on health checks.
## Get your hands dirty
## Get your hands dirty
To show the health check is actually working, first create the pods:
To show the health check is actually working, first create the pods:
Check the status of the pods once they are created:
Check the status of the pods once they are created:
```
```
# kubectl get pods
# kubectl get pods
NAME READY STATUS RESTARTS AGE
NAME READY STATUS RESTARTS AGE
...
@@ -80,7 +88,9 @@ NAME READY STATUS RESTARTS
...
@@ -80,7 +88,9 @@ NAME READY STATUS RESTARTS
liveness-exec 1/1 Running 0 13s
liveness-exec 1/1 Running 0 13s
liveness-http 1/1 Running 0 13s
liveness-http 1/1 Running 0 13s
```
```
Check the status half a minute later, you will see the container restart count being incremented:
Check the status half a minute later, you will see the container restart count being incremented:
```
```
# kubectl get pods
# kubectl get pods
mwielgus@mwielgusd:~/test/k2/kubernetes/examples/liveness$ kubectl get pods
mwielgus@mwielgusd:~/test/k2/kubernetes/examples/liveness$ kubectl get pods
...
@@ -89,6 +99,7 @@ NAME READY STATUS RESTARTS
...
@@ -89,6 +99,7 @@ NAME READY STATUS RESTARTS
liveness-exec 1/1 Running 1 36s
liveness-exec 1/1 Running 1 36s
liveness-http 1/1 Running 1 36s
liveness-http 1/1 Running 1 36s
```
```
At the bottom of the *kubectl describe* output there are messages indicating that the liveness probes have failed, and the containers have been killed and recreated.
At the bottom of the *kubectl describe* output there are messages indicating that the liveness probes have failed, and the containers have been killed and recreated.
@@ -54,6 +54,7 @@ You’ve seen [how to configure and deploy pods and containers](configuring-cont
...
@@ -54,6 +54,7 @@ You’ve seen [how to configure and deploy pods and containers](configuring-cont
The container file system only lives as long as the container does, so when a container crashes and restarts, changes to the filesystem will be lost and the container will restart from a clean slate. To access more-persistent storage, outside the container file system, you need a [*volume*](volumes.md). This is especially important to stateful applications, such as key-value stores and databases.
The container file system only lives as long as the container does, so when a container crashes and restarts, changes to the filesystem will be lost and the container will restart from a clean slate. To access more-persistent storage, outside the container file system, you need a [*volume*](volumes.md). This is especially important to stateful applications, such as key-value stores and databases.
For example, [Redis](http://redis.io/) is a key-value cache and store, which we use in the [guestbook](../../examples/guestbook/) and other examples. We can add a volume to it to store persistent data as follows:
For example, [Redis](http://redis.io/) is a key-value cache and store, which we use in the [guestbook](../../examples/guestbook/) and other examples. We can add a volume to it to store persistent data as follows:
```yaml
```yaml
apiVersion:v1
apiVersion:v1
kind:ReplicationController
kind:ReplicationController
...
@@ -80,6 +81,7 @@ spec:
...
@@ -80,6 +81,7 @@ spec:
-mountPath:/redis-master-data
-mountPath:/redis-master-data
name:data# must match the name of the volume, above
name:data# must match the name of the volume, above
```
```
`emptyDir` volumes live for the lifespan of the [pod](pods.md), which is longer than the lifespan of any one container, so if the container fails and is restarted, our storage will live on.
`emptyDir` volumes live for the lifespan of the [pod](pods.md), which is longer than the lifespan of any one container, so if the container fails and is restarted, our storage will live on.
In addition to the local disk storage provided by `emptyDir`, Kubernetes supports many different network-attached storage solutions, including PD on GCE and EBS on EC2, which are preferred for critical data, and will handle details such as mounting and unmounting the devices on the nodes. See [the volumes doc](volumes.md) for more details.
In addition to the local disk storage provided by `emptyDir`, Kubernetes supports many different network-attached storage solutions, including PD on GCE and EBS on EC2, which are preferred for critical data, and will handle details such as mounting and unmounting the devices on the nodes. See [the volumes doc](volumes.md) for more details.
...
@@ -89,6 +91,7 @@ In addition to the local disk storage provided by `emptyDir`, Kubernetes support
...
@@ -89,6 +91,7 @@ In addition to the local disk storage provided by `emptyDir`, Kubernetes support
Many applications need credentials, such as passwords, OAuth tokens, and TLS keys, to authenticate with other applications, databases, and services. Storing these credentials in container images or environment variables is less than ideal, since the credentials can then be copied by anyone with access to the image, pod/container specification, host file system, or host Docker daemon.
Many applications need credentials, such as passwords, OAuth tokens, and TLS keys, to authenticate with other applications, databases, and services. Storing these credentials in container images or environment variables is less than ideal, since the credentials can then be copied by anyone with access to the image, pod/container specification, host file system, or host Docker daemon.
Kubernetes provides a mechanism, called [*secrets*](secrets.md), that facilitates delivery of sensitive credentials to applications. A `Secret` is a simple resource containing a map of data. For instance, a simple secret with a username and password might look as follows:
Kubernetes provides a mechanism, called [*secrets*](secrets.md), that facilitates delivery of sensitive credentials to applications. A `Secret` is a simple resource containing a map of data. For instance, a simple secret with a username and password might look as follows:
```yaml
```yaml
apiVersion:v1
apiVersion:v1
kind:Secret
kind:Secret
...
@@ -99,7 +102,9 @@ data:
...
@@ -99,7 +102,9 @@ data:
password:dmFsdWUtMg0K
password:dmFsdWUtMg0K
username:dmFsdWUtMQ0K
username:dmFsdWUtMQ0K
```
```
As with other resources, this secret can be instantiated using `create` and can be viewed with `get`:
As with other resources, this secret can be instantiated using `create` and can be viewed with `get`:
```bash
```bash
$ kubectl create -f ./secret.yaml
$ kubectl create -f ./secret.yaml
secrets/mysecret
secrets/mysecret
...
@@ -150,6 +155,7 @@ Secrets can also be used to pass [image registry credentials](images.md#using-a-
...
@@ -150,6 +155,7 @@ Secrets can also be used to pass [image registry credentials](images.md#using-a-
First, create a `.dockercfg` file, such as running `docker login <registry.domain>`.
First, create a `.dockercfg` file, such as running `docker login <registry.domain>`.
Then put the resulting `.dockercfg` file into a [secret resource](secrets.md). For example:
Then put the resulting `.dockercfg` file into a [secret resource](secrets.md). For example:
```
```
$ docker login
$ docker login
Username: janedoe
Username: janedoe
...
@@ -180,6 +186,7 @@ secrets/myregistrykey
...
@@ -180,6 +186,7 @@ secrets/myregistrykey
Now, you can create pods which reference that secret by adding an `imagePullSecrets`
Now, you can create pods which reference that secret by adding an `imagePullSecrets`
section to a pod definition.
section to a pod definition.
```
```
apiVersion: v1
apiVersion: v1
kind: Pod
kind: Pod
...
@@ -198,6 +205,7 @@ spec:
...
@@ -198,6 +205,7 @@ spec:
[Pods](pods.md) support running multiple containers co-located together. They can be used to host vertically integrated application stacks, but their primary motivation is to support auxiliary helper programs that assist the primary application. Typical examples are data pullers, data pushers, and proxies.
[Pods](pods.md) support running multiple containers co-located together. They can be used to host vertically integrated application stacks, but their primary motivation is to support auxiliary helper programs that assist the primary application. Typical examples are data pullers, data pushers, and proxies.
Such containers typically need to communicate with one another, often through the file system. This can be achieved by mounting the same volume into both containers. An example of this pattern would be a web server with a [program that polls a git repository](../../contrib/git-sync/) for new updates:
Such containers typically need to communicate with one another, often through the file system. This can be achieved by mounting the same volume into both containers. An example of this pattern would be a web server with a [program that polls a git repository](../../contrib/git-sync/) for new updates:
```yaml
```yaml
apiVersion:v1
apiVersion:v1
kind:ReplicationController
kind:ReplicationController
...
@@ -238,6 +246,7 @@ More examples can be found in our [blog article](http://blog.kubernetes.io/2015/
...
@@ -238,6 +246,7 @@ More examples can be found in our [blog article](http://blog.kubernetes.io/2015/
Kubernetes’s scheduler will place applications only where they have adequate CPU and memory, but it can only do so if it knows how much [resources they require](compute-resources.md). The consequence of specifying too little CPU is that the containers could be starved of CPU if too many other containers were scheduled onto the same node. Similarly, containers could die unpredictably due to running out of memory if no memory were requested, which can be especially likely for large-memory applications.
Kubernetes’s scheduler will place applications only where they have adequate CPU and memory, but it can only do so if it knows how much [resources they require](compute-resources.md). The consequence of specifying too little CPU is that the containers could be starved of CPU if too many other containers were scheduled onto the same node. Similarly, containers could die unpredictably due to running out of memory if no memory were requested, which can be especially likely for large-memory applications.
If no resource requirements are specified, a nominal amount of resources is assumed. (This default is applied via a [LimitRange](limitrange/) for the default [Namespace](namespaces.md). It can be viewed with `kubectl describe limitrange limits`.) You may explicitly specify the amount of resources required as follows:
If no resource requirements are specified, a nominal amount of resources is assumed. (This default is applied via a [LimitRange](limitrange/) for the default [Namespace](namespaces.md). It can be viewed with `kubectl describe limitrange limits`.) You may explicitly specify the amount of resources required as follows:
```yaml
```yaml
apiVersion:v1
apiVersion:v1
kind:ReplicationController
kind:ReplicationController
...
@@ -262,6 +271,7 @@ spec:
...
@@ -262,6 +271,7 @@ spec:
# memory units are bytes
# memory units are bytes
memory:64Mi
memory:64Mi
```
```
The container will die due to OOM (out of memory) if it exceeds its specified limit, so specifying a value a little higher than expected generally improves reliability.
The container will die due to OOM (out of memory) if it exceeds its specified limit, so specifying a value a little higher than expected generally improves reliability.
If you’re not sure how much resources to request, you can first launch the application without specifying resources, and use [resource usage monitoring](monitoring.md) to determine appropriate values.
If you’re not sure how much resources to request, you can first launch the application without specifying resources, and use [resource usage monitoring](monitoring.md) to determine appropriate values.
...
@@ -271,6 +281,7 @@ If you’re not sure how much resources to request, you can first launch the app
...
@@ -271,6 +281,7 @@ If you’re not sure how much resources to request, you can first launch the app
Many applications running for long periods of time eventually transition to broken states, and cannot recover except by restarting them. Kubernetes provides [*liveness probes*](pod-states.md#container-probes) to detect and remedy such situations.
Many applications running for long periods of time eventually transition to broken states, and cannot recover except by restarting them. Kubernetes provides [*liveness probes*](pod-states.md#container-probes) to detect and remedy such situations.
A common way to probe an application is using HTTP, which can be specified as follows:
A common way to probe an application is using HTTP, which can be specified as follows:
```yaml
```yaml
apiVersion:v1
apiVersion:v1
kind:ReplicationController
kind:ReplicationController
...
@@ -308,6 +319,7 @@ Kubernetes will send SIGTERM to applications, which can be handled in order to e
...
@@ -308,6 +319,7 @@ Kubernetes will send SIGTERM to applications, which can be handled in order to e
Kubernetes supports the (optional) specification of a [*pre-stop lifecycle hook*](container-environment.md#container-hooks), which will execute prior to sending SIGTERM.
Kubernetes supports the (optional) specification of a [*pre-stop lifecycle hook*](container-environment.md#container-hooks), which will execute prior to sending SIGTERM.
The specification of a pre-stop hook is similar to that of probes, but without the timing-related parameters. For example:
The specification of a pre-stop hook is similar to that of probes, but without the timing-related parameters. For example:
```yaml
```yaml
apiVersion:v1
apiVersion:v1
kind:ReplicationController
kind:ReplicationController
...
@@ -337,6 +349,7 @@ spec:
...
@@ -337,6 +349,7 @@ spec:
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`](kubectl/kubectl.md) or the [UI](ui.md), in addition to general [log collection](logging.md). 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`](kubectl/kubectl.md) or the [UI](ui.md), in addition to general [log collection](logging.md). 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:
Here is a toy example:
```yaml
```yaml
apiVersion:v1
apiVersion:v1
kind:Pod
kind:Pod
...
@@ -351,6 +364,7 @@ spec:
...
@@ -351,6 +364,7 @@ spec:
```
```
The message is recorded along with the other state of the last (i.e., most recent) termination:
The message is recorded along with the other state of the last (i.e., most recent) termination:
@@ -37,10 +37,12 @@ Kubernetes has a web-based user interface that displays the current cluster stat
...
@@ -37,10 +37,12 @@ Kubernetes has a web-based user interface that displays the current cluster stat
By default, the Kubernetes UI is deployed as a cluster addon. To access it, visit `https://<kubernetes-master>/ui`, which redirects to `https://<kubernetes-master>/api/v1/proxy/namespaces/kube-system/services/kube-ui/#/dashboard/`.
By default, the Kubernetes UI is deployed as a cluster addon. To access it, visit `https://<kubernetes-master>/ui`, which redirects to `https://<kubernetes-master>/api/v1/proxy/namespaces/kube-system/services/kube-ui/#/dashboard/`.
If you find that you're not able to access the UI, it may be because the kube-ui service has not been started on your cluster. In that case, you can start it manually with:
If you find that you're not able to access the UI, it may be because the kube-ui service has not been started on your cluster. In that case, you can start it manually with:
Normally, this should be taken care of automatically by the [`kube-addons.sh`](../../cluster/saltbase/salt/kube-addons/kube-addons.sh) script that runs on the master.
Normally, this should be taken care of automatically by the [`kube-addons.sh`](../../cluster/saltbase/salt/kube-addons/kube-addons.sh) script that runs on the master.
The rolling-update command in kubectl will do 2 things:
The rolling-update command in kubectl will do 2 things:
1. Create a new [replication controller](../../../docs/user-guide/replication-controller.md) with a pod template that uses the new image (`gcr.io/google_containers/update-demo:kitten`)
1. Create a new [replication controller](../../../docs/user-guide/replication-controller.md) with a pod template that uses the new image (`gcr.io/google_containers/update-demo:kitten`)
@@ -96,6 +96,7 @@ In theory could create a single Cassandra pod right now but since `KubernetesSee
...
@@ -96,6 +96,7 @@ In theory could create a single Cassandra pod right now but since `KubernetesSee
In Kubernetes a _[Service](../../docs/user-guide/services.md)_ describes a set of Pods that perform the same task. For example, the set of Pods in a Cassandra cluster can be a Kubernetes Service, or even just the single Pod we created above. An important use for a Service is to create a load balancer which distributes traffic across members of the set of Pods. But a _Service_ can also be used as a standing query which makes a dynamically changing set of Pods (or the single Pod we've already created) available via the Kubernetes API. This is the way that we use initially use Services with Cassandra.
In Kubernetes a _[Service](../../docs/user-guide/services.md)_ describes a set of Pods that perform the same task. For example, the set of Pods in a Cassandra cluster can be a Kubernetes Service, or even just the single Pod we created above. An important use for a Service is to create a load balancer which distributes traffic across members of the set of Pods. But a _Service_ can also be used as a standing query which makes a dynamically changing set of Pods (or the single Pod we've already created) available via the Kubernetes API. This is the way that we use initially use Services with Cassandra.
Here is the service description:
Here is the service description:
```yaml
```yaml
apiVersion:v1
apiVersion:v1
kind:Service
kind:Service
...
@@ -113,6 +114,7 @@ spec:
...
@@ -113,6 +114,7 @@ spec:
The important thing to note here is the ```selector```. It is a query over labels, that identifies the set of _Pods_ contained by the _Service_. In this case the selector is ```name=cassandra```. If you look back at the Pod specification above, you'll see that the pod has the corresponding label, so it will be selected for membership in this Service.
The important thing to note here is the ```selector```. It is a query over labels, that identifies the set of _Pods_ contained by the _Service_. In this case the selector is ```name=cassandra```. If you look back at the Pod specification above, you'll see that the pod has the corresponding label, so it will be selected for membership in this Service.
This shows 4 instances of Elasticsearch running. After making sure that port 9200 is accessible for this cluster (e.g. using a firewall rule for Google Compute Engine) we can make queries via the service which will be fielded by the matching Elasticsearch pods.
This shows 4 instances of Elasticsearch running. After making sure that port 9200 is accessible for this cluster (e.g. using a firewall rule for Google Compute Engine) we can make queries via the service which will be fielded by the matching Elasticsearch pods.
```
```
$ curl 104.197.12.157:9200
$ curl 104.197.12.157:9200
{
{
...
@@ -218,7 +237,9 @@ $ curl 104.197.12.157:9200
...
@@ -218,7 +237,9 @@ $ curl 104.197.12.157:9200
"tagline" : "You Know, for Search"
"tagline" : "You Know, for Search"
}
}
```
```
We can query the nodes to confirm that an Elasticsearch cluster has been formed.
We can query the nodes to confirm that an Elasticsearch cluster has been formed.
@@ -56,14 +56,17 @@ Here is a snippet of [glusterfs-endpoints.json](glusterfs-endpoints.json),
...
@@ -56,14 +56,17 @@ Here is a snippet of [glusterfs-endpoints.json](glusterfs-endpoints.json),
]
]
```
```
The "IP" field should be filled with the address of a node in the Glusterfs server cluster. In this example, it is fine to give any valid value (from 1 to 65535) to the "port" field.
The "IP" field should be filled with the address of a node in the Glusterfs server cluster. In this example, it is fine to give any valid value (from 1 to 65535) to the "port" field.
You may ssh to the host (the hostIP) and run 'mount' to see if the Glusterfs volume is mounted,
You may ssh to the host (the hostIP) and run 'mount' to see if the Glusterfs volume is mounted,
```shell
```shell
$ mount | grep kube_vol
$ mount | grep kube_vol
10.240.106.152:kube_vol on /var/lib/kubelet/pods/f164a571-fa68-11e4-ad5c-42010af019b7/volumes/kubernetes.io~glusterfs/glusterfsvol type fuse.glusterfs (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other,max_read=131072)
10.240.106.152:kube_vol on /var/lib/kubelet/pods/f164a571-fa68-11e4-ad5c-42010af019b7/volumes/kubernetes.io~glusterfs/glusterfsvol type fuse.glusterfs (rw,relatime,user_id=0,group_id=0,default_permissions,allow_other,max_read=131072)
(Note that an initial `docker pull` to grab a container image may take a few minutes, depending on network conditions. A pod will be reported as `Pending` while its image is being downloaded.)
(Note that an initial `docker pull` to grab a container image may take a few minutes, depending on network conditions. A pod will be reported as `Pending` while its image is being downloaded.)
#### Optional Interlude
#### Optional Interlude
...
@@ -221,6 +222,7 @@ Create the service by running:
...
@@ -221,6 +222,7 @@ Create the service by running:
@@ -61,6 +61,7 @@ In this case, we shall not run a single Hazelcast pod, because the discovery mec
...
@@ -61,6 +61,7 @@ In this case, we shall not run a single Hazelcast pod, because the discovery mec
In Kubernetes a _[Service](../../docs/user-guide/services.md)_ describes a set of Pods that perform the same task. For example, the set of nodes in a Hazelcast cluster. An important use for a Service is to create a load balancer which distributes traffic across members of the set. But a _Service_ can also be used as a standing query which makes a dynamically changing set of Pods available via the Kubernetes API. This is actually how our discovery mechanism works, by relying on the service to discover other Hazelcast pods.
In Kubernetes a _[Service](../../docs/user-guide/services.md)_ describes a set of Pods that perform the same task. For example, the set of nodes in a Hazelcast cluster. An important use for a Service is to create a load balancer which distributes traffic across members of the set. But a _Service_ can also be used as a standing query which makes a dynamically changing set of Pods available via the Kubernetes API. This is actually how our discovery mechanism works, by relying on the service to discover other Hazelcast pods.
Here is the service description:
Here is the service description:
```yaml
```yaml
apiVersion:v1
apiVersion:v1
kind:Service
kind:Service
...
@@ -78,6 +79,7 @@ spec:
...
@@ -78,6 +79,7 @@ spec:
The important thing to note here is the `selector`. It is a query over labels, that identifies the set of _Pods_ contained by the _Service_. In this case the selector is `name: hazelcast`. If you look at the Replication Controller specification below, you'll see that the pod has the corresponding label, so it will be selected for membership in this Service.
The important thing to note here is the `selector`. It is a query over labels, that identifies the set of _Pods_ contained by the _Service_. In this case the selector is `name: hazelcast`. If you look at the Replication Controller specification below, you'll see that the pod has the corresponding label, so it will be selected for membership in this Service.
@@ -106,6 +109,7 @@ Unlike our original redis-master pod, these pods exist independently, and they u
...
@@ -106,6 +109,7 @@ Unlike our original redis-master pod, these pods exist independently, and they u
The final step in the cluster turn up is to delete the original redis-master pod that we created manually. While it was useful for bootstrapping discovery in the cluster, we really don't want the lifespan of our sentinel to be tied to the lifespan of one of our redis servers, and now that we have a successful, replicated redis sentinel service up and running, the binding is unnecessary.
The final step in the cluster turn up is to delete the original redis-master pod that we created manually. While it was useful for bootstrapping discovery in the cluster, we really don't want the lifespan of our sentinel to be tied to the lifespan of one of our redis servers, and now that we have a successful, replicated redis sentinel service up and running, the binding is unnecessary.
@@ -154,7 +155,7 @@ since the ui is not stateless when playing with Web Admin UI will cause `Connect
...
@@ -154,7 +155,7 @@ since the ui is not stateless when playing with Web Admin UI will cause `Connect
*`gen_pod.sh` is using to generate pod templates for my local cluster,
*`gen_pod.sh` is using to generate pod templates for my local cluster,
the generated pods which is using `nodeSelector` to force k8s to schedule containers to my designate nodes, for I need to access persistent data on my host dirs. Note that one needs to label the node before 'nodeSelector' can work, see this [tutorial](../../docs/user-guide/node-selection/)
the generated pods which is using `nodeSelector` to force k8s to schedule containers to my designate nodes, for I need to access persistent data on my host dirs. Note that one needs to label the node before 'nodeSelector' can work, see this [tutorial](../../docs/user-guide/node-selection/)
* see [/antmanler/rethinkdb-k8s](https://github.com/antmanler/rethinkdb-k8s) for detail
* see [antmanler/rethinkdb-k8s](https://github.com/antmanler/rethinkdb-k8s) for detail