Syntax highlighting manual fixes up to mesos.md (next is scratch.md)

This commit is contained in:
John Mulhausen
2016-02-16 19:28:28 -08:00
parent ee72211075
commit beda532ca4
128 changed files with 1765 additions and 3547 deletions
+1 -6
View File
@@ -127,11 +127,6 @@ Yes.
For Kubernetes 1.0, we strongly recommend running the following set of admission control plug-ins (order matters):
```
```shell
--admission-control=NamespaceLifecycle,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota
```
+2 -11
View File
@@ -88,26 +88,19 @@ To permit an action Policy with an unset namespace applies regardless of namespa
A service account automatically generates a user. The user's name is generated according to the naming convention:
```
```shell
system:serviceaccount:<namespace>:<serviceaccountname>
```
Creating a new namespace also causes a new service account to be created, of this form:*
```
```shell
system:serviceaccount:<namespace>:default
```
For example, if you wanted to grant the default service account in the kube-system full privilege to the API, you would add this line to your policy file:
```json
{"user":"system:serviceaccount:kube-system:default"}
```
The apiserver will need to be restarted to pickup the new policy lines.
@@ -118,11 +111,9 @@ Other implementations can be developed fairly easily.
The APIserver calls the Authorizer interface:
```go
type Authorizer interface {
Authorize(a Attributes) error
}
```
to determine whether or not to allow each API action.
+3 -3
View File
@@ -40,7 +40,7 @@ To prevent memory leaks or other resource issues in [cluster addons](https://rel
For example:
```yaml
```yaml
containers:
- image: gcr.io/google_containers/heapster:v0.15.0
name: heapster
@@ -48,8 +48,8 @@ containers:
limits:
cpu: 100m
memory: 200Mi
```
```
These limits, however, are based on data collected from addons running on 4-node clusters (see [#10335](http://issue.k8s.io/10335#issuecomment-117861225)). The addons consume a lot more resources when running on large deployment clusters (see [#5880](http://issue.k8s.io/5880#issuecomment-113984085)). So, if a large cluster is deployed without adjusting these values, the addons may continuously get killed because they keep hitting the limits.
To avoid running into cluster addon resource issues, when creating a cluster with many nodes, consider the following:
+14 -30
View File
@@ -40,24 +40,20 @@ The node upgrade process is user-initiated and is described in the [GKE document
### Upgrading open source Google Compute Engine clusters
Upgrades on open source Google Compute Engine (GCE) clusters are controlled by the ```cluster/gce/upgrade.sh``` script.
Upgrades on open source Google Compute Engine (GCE) clusters are controlled by the `cluster/gce/upgrade.sh` script.
Get its usage by running `cluster/gce/upgrade.sh -h`.
For example, to upgrade just your master to a specific version (v1.0.2):
```shell
cluster/gce/upgrade.sh -M v1.0.2
```
Alternatively, to upgrade your entire cluster to the latest stable release:
```shell
cluster/gce/upgrade.sh release/stable
```
### Other platforms
@@ -70,10 +66,8 @@ recommend testing the upgrade on an experimental cluster before performing the u
If your cluster runs short on resources you can easily add more machines to it if your cluster is running in [Node self-registration mode](node.html#self-registration-of-nodes).
If you're using GCE or GKE it's done by resizing Instance Group managing your Nodes. It can be accomplished by modifying number of instances on `Compute > Compute Engine > Instance groups > your group > Edit group` [Google Cloud Console page](https://console.developers.google.com) or using gcloud CLI:
```
```shell
gcloud compute instance-groups managed --zone compute-zone resize my-cluster-minon-group --new-size 42
```
Instance Group will take care of putting appropriate image on new machines and start them, while Kubelet will register its Node with API server to make it available for scheduling. If you scale the instance group down, system will randomly choose Nodes to kill.
@@ -84,31 +78,32 @@ In other environments you may need to configure the machine yourself and tell th
### Horizontal auto-scaling of nodes (GCE)
If you are using GCE, you can configure your cluster so that the number of nodes will be automatically scaled based on their CPU and memory utilization.
Before setting up the cluster by ```kube-up.sh```, you can set ```KUBE_ENABLE_NODE_AUTOSCALER``` environment variable to ```true``` and export it.
Before setting up the cluster by `kube-up.sh`, you can set `KUBE_ENABLE_NODE_AUTOSCALE`
environment variable to `true`
and export it.
The script will create an autoscaler for the instance group managing your nodes.
The autoscaler will try to maintain the average CPU and memory utilization of nodes within the cluster close to the target value.
The target value can be configured by ```KUBE_TARGET_NODE_UTILIZATION``` environment variable (default: 0.7) for ``kube-up.sh`` when creating the cluster.
The target value can be configured by `KUBE_TARGET_NODE_UTILIZATION`
environment variable (default: 0.7) for `kube-up.sh` when creating the cluster.
The node utilization is the total node's CPU/memory usage (OS + k8s + user load) divided by the node's capacity.
If the desired numbers of nodes in the cluster resulting from CPU utilization and memory utilization are different,
the autoscaler will choose the bigger number.
The number of nodes in the cluster set by the autoscaler will be limited from ```KUBE_AUTOSCALER_MIN_NODES``` (default: 1)
to ```KUBE_AUTOSCALER_MAX_NODES``` (default: the initial number of nodes in the cluster).
The number of nodes in the cluster set by the autoscaler will be limited from `KUBE_AUTOSCALER_MIN_NODES`
(default: 1)
to `KUBE_AUTOSCALER_MAX_NODES`
(default: the initial number of nodes in the cluster).
The autoscaler is implemented as a Compute Engine Autoscaler.
The initial values of the autoscaler parameters set by ``kube-up.sh`` and some more advanced options can be tweaked on
The initial values of the autoscaler parameters set by `kube-up.sh` and some more advanced options can be tweaked on
`Compute > Compute Engine > Instance groups > your group > Edit group`[Google Cloud Console page](https://console.developers.google.com)
or using gcloud CLI:
```
```shell
gcloud preview autoscaler --zone compute-zone <command>
```
Note that autoscaling will work properly only if node metrics are accessible in Google Cloud Monitoring.
To make the metrics accessible, you need to create your cluster with ```KUBE_ENABLE_CLUSTER_MONITORING```
equal to ```google``` or ```googleinfluxdb``` (```googleinfluxdb``` is the default value).
Note that autoscaling will work properly only if node metrics are accessible in Google Cloud Monitoring. To make the metrics accessible, you need to create your cluster with `KUBE_ENABLE_CLUSTER_MONITORING` equal to `google` or `googleinfluxdb` (`googleinfluxdb` is the default value).
## Maintenance on a Node
@@ -123,9 +118,7 @@ If you want more control over the upgrading process, you may use the following w
Mark the node to be rebooted as unschedulable:
```shell
kubectl replace nodes $NODENAME --patch='{"apiVersion": "v1", "spec": {"unschedulable": true}}'
```
This keeps new pods from landing on the node while you are trying to get them off.
@@ -135,9 +128,7 @@ Get the pods off the machine, via any of the following strategies:
* Delete pods with:
```shell
kubectl delete pods $PODNAME
```
For pods with a replication controller, the pod will eventually be replaced by a new pod which will be scheduled to a new node. Additionally, if the pod is part of a service, then clients will automatically be redirected to the new pod.
@@ -149,9 +140,7 @@ Perform maintenance work on the node.
Make the node schedulable again:
```shell
kubectl replace nodes $NODENAME --patch='{"apiVersion": "v1", "spec": {"unschedulable": false}}'
```
If you deleted the node's VM instance and created a new one, then a new schedulable node resource will
@@ -193,11 +182,6 @@ for changes to this variable to take effect.
You can use the `kube-version-change` utility to convert config files between different API versions.
```shell
$ hack/build-go.sh cmd/kube-version-change
$ _output/local/go/bin/kube-version-change -i myPod.v1beta3.yaml -o myPod.v1.yaml
```
+1 -6
View File
@@ -13,9 +13,7 @@ The first thing to debug in your cluster is if your nodes are all registered cor
Run
```shell
kubectl get nodes
```
And verify that all of the nodes you expect to see are present and that they are all in the `Ready` state.
@@ -108,7 +106,4 @@ Mitigations:
- Mitigates: Kubelet software fault
- Action: [Multiple independent clusters](multi-cluster) (and avoid making risky changes to all clusters at once)
- Mitigates: Everything listed above.
- Mitigates: Everything listed above.
-5
View File
@@ -42,10 +42,5 @@ test key. On your master VM (or somewhere with firewalls configured such that
you can talk to your cluster's etcd), try:
```shell
curl -fs -X PUT "http://${host}:${port}/v2/keys/_test"
```
+21 -24
View File
@@ -12,8 +12,6 @@ or try [Google Container Engine](https://cloud.google.com/container-engine/) for
Also, at this time high availability support for Kubernetes is not continuously tested in our end-to-end (e2e) testing. We will
be working to add this continuous testing, but for now the single-node master installations are more heavily tested.
{% include pagetoc.html %}
## Overview
@@ -85,10 +83,10 @@ a simple cluster set up, using etcd's built in discovery to build our cluster.
First, hit the etcd discovery service to create a new token:
```shell
curl https://discovery.etcd.io/new?size=3
```shell
curl https://discovery.etcd.io/new?size=3
```
On each node, copy the [etcd.yaml](high-availability/etcd.yaml) file into `/etc/kubernetes/manifests/etcd.yaml`
The kubelet on each node actively monitors the contents of that directory, and it will create an instance of the `etcd`
@@ -103,16 +101,16 @@ for `${NODE_IP}` on each machine.
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
```shell
```shell
etcdctl member list
```
and
```
and
```shell
etcdctl cluster-health
```
You can also validate that this is working with `etcdctl set foo bar` on one node, and `etcd get foo`
on a different node.
@@ -141,10 +139,10 @@ Once you have replicated etcd set up correctly, we will also install the apiserv
First you need to create the initial log file, so that Docker mounts a file instead of a directory:
Once you have replicated etcd set up correctly, we will also install the apiserver using the kubelet.
### Installing configuration files
```shell
touch /var/log/kube-apiserver.log
```
Next, you need to create a `/srv/kubernetes/` directory on each node. This directory includes:
* basic_auth.csv - basic auth user and password
* ca.crt - Certificate Authority cert
@@ -193,14 +191,13 @@ In the future, we expect to more tightly integrate this lease-locking into the s
First, create empty log files on each node, so that Docker will mount the files not make new directories:
loses the election, it ensures that any master components running on the node (e.g. the scheduler) are stopped.
```shell
touch /var/log/kube-scheduler.log
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)
### Installing configuration files
touch /var/log/kube-controller-manager.log
```
Next, set up the descriptions of the scheduler and controller manager pods on each node.
First, create empty log files on each node, so that Docker will mount the files not make new directories:
by copying [kube-scheduler.yaml](high-availability/kube-scheduler.yaml) and [kube-controller-manager.yaml](high-availability/kube-controller-manager.yaml) into the `/srv/kubernetes/` directory.
### Running the podmaster
+32 -58
View File
@@ -40,32 +40,27 @@ This example will work in a custom namespace to demonstrate the concepts involve
Let's create a new namespace called limit-example:
```shell
```shell
$ kubectl create -f docs/admin/limitrange/namespace.yaml
namespace "limit-example" created
$ kubectl get namespaces
NAME LABELS STATUS AGE
default <none> Active 5m
limit-example <none> Active 53s
```
```
## Step 2: Apply a limit to the namespace
Let's create a simple limit in our namespace.
```shell
```shell
$ kubectl create -f docs/admin/limitrange/limits.yaml --namespace=limit-example
limitrange "mylimits" created
```
```
Let's describe the limits that we have imposed in our namespace.
```shell
```shell
$ kubectl describe limits mylimits --namespace=limit-example
Name: mylimits
Namespace: limit-example
@@ -75,9 +70,8 @@ Pod cpu 200m 2 - - -
Pod memory 6Mi 1Gi - - -
Container cpu 100m 2 200m 300m -
Container memory 3Mi 1Gi 100Mi 200Mi -
```
```
In this scenario, we have said the following:
1. If a max constraint is specified for a resource (2 CPU and 1Gi memory in this case), then a limit
@@ -104,20 +98,17 @@ of creation explaining why.
Let's first spin up a replication controller that creates a single container pod to demonstrate
how default values are applied to each pod.
```shell
```shell
$ kubectl run nginx --image=nginx --replicas=1 --namespace=limit-example
replicationcontroller "nginx" created
$ kubectl get pods --namespace=limit-example
NAME READY STATUS RESTARTS AGE
nginx-aq0mf 1/1 Running 0 35s
$ kubectl get pods nginx-aq0mf --namespace=limit-example -o yaml | grep resources -C 8
```
```yaml
resourceVersion: "127"
```
```yaml
resourceVersion: "127"
selfLink: /api/v1/namespaces/limit-example/pods/nginx-aq0mf
uid: 51be42a7-7156-11e5-9921-286ed488f785
spec:
@@ -134,33 +125,27 @@ spec:
memory: 100Mi
terminationMessagePath: /dev/termination-log
volumeMounts:
```
```
Note that our nginx container has picked up the namespace default cpu and memory resource *limits* and *requests*.
Let's create a pod that exceeds our allowed limits by having it have a container that requests 3 cpu cores.
```shell
```shell
$ kubectl create -f docs/admin/limitrange/invalid-pod.yaml --namespace=limit-example
Error from server: error when creating "docs/admin/limitrange/invalid-pod.yaml": Pod "invalid-pod" is forbidden: [Maximum cpu usage per Pod is 2, but limit is 3., Maximum cpu usage per Container is 2, but limit is 3.]
```
```
Let's create a pod that falls within the allowed limit boundaries.
```shell
```shell
$ kubectl create -f docs/admin/limitrange/valid-pod.yaml --namespace=limit-example
pod "valid-pod" created
$ kubectl get pods valid-pod --namespace=limit-example -o yaml | grep -C 6 resources
```
```yaml
uid: 162a12aa-7157-11e5-9921-286ed488f785
```
```yaml
uid: 162a12aa-7157-11e5-9921-286ed488f785
spec:
containers:
- image: gcr.io/google_containers/serve_hostname
@@ -173,47 +158,36 @@ spec:
requests:
cpu: "1"
memory: 512Mi
```
```
Note that this pod specifies explicit resource *limits* and *requests* so it did not pick up the namespace
default values.
Note: The *limits* for CPU resource are not enforced in the default Kubernetes setup on the physical node
that runs the container unless the administrator deploys the kubelet with the folllowing flag:
```
```
$ kubelet --help
Usage of kubelet
....
--cpu-cfs-quota[=false]: Enable CPU CFS quota enforcement for containers that specify CPU limits
$ kubelet --cpu-cfs-quota=true ...
```
```
## Step 4: Cleanup
To remove the resources used by this example, you can just delete the limit-example namespace.
```shell
```shell
$ kubectl delete namespace limit-example
namespace "limit-example" deleted
$ kubectl get namespaces
NAME LABELS STATUS AGE
default <none> Active 20m
```
```
## Summary
Cluster operators that want to restrict the amount of resources a single container or pod may consume
are able to define allowable ranges per Kubernetes namespace. In the absence of any explicit assignments,
the Kubernetes system is able to apply default resource *limits* and *requests* if desired in order to
constrain the amount of resource a pod consumes on a node.
constrain the amount of resource a pod consumes on a node.
+33 -58
View File
@@ -40,32 +40,27 @@ This example will work in a custom namespace to demonstrate the concepts involve
Let's create a new namespace called limit-example:
```shell
```shell
$ kubectl create -f docs/admin/limitrange/namespace.yaml
namespace "limit-example" created
$ kubectl get namespaces
NAME LABELS STATUS AGE
default <none> Active 5m
limit-example <none> Active 53s
```
```
## Step 2: Apply a limit to the namespace
Let's create a simple limit in our namespace.
```shell
```shell
$ kubectl create -f docs/admin/limitrange/limits.yaml --namespace=limit-example
limitrange "mylimits" created
```
```
Let's describe the limits that we have imposed in our namespace.
```shell
```shell
$ kubectl describe limits mylimits --namespace=limit-example
Name: mylimits
Namespace: limit-example
@@ -75,9 +70,8 @@ Pod cpu 200m 2 - - -
Pod memory 6Mi 1Gi - - -
Container cpu 100m 2 200m 300m -
Container memory 3Mi 1Gi 100Mi 200Mi -
```
```
In this scenario, we have said the following:
1. If a max constraint is specified for a resource (2 CPU and 1Gi memory in this case), then a limit
@@ -104,20 +98,17 @@ of creation explaining why.
Let's first spin up a replication controller that creates a single container pod to demonstrate
how default values are applied to each pod.
```shell
```shell
$ kubectl run nginx --image=nginx --replicas=1 --namespace=limit-example
replicationcontroller "nginx" created
$ kubectl get pods --namespace=limit-example
NAME READY STATUS RESTARTS AGE
nginx-aq0mf 1/1 Running 0 35s
$ kubectl get pods nginx-aq0mf --namespace=limit-example -o yaml | grep resources -C 8
```
```yaml
resourceVersion: "127"
```
```yaml
resourceVersion: "127"
selfLink: /api/v1/namespaces/limit-example/pods/nginx-aq0mf
uid: 51be42a7-7156-11e5-9921-286ed488f785
spec:
@@ -134,33 +125,27 @@ spec:
memory: 100Mi
terminationMessagePath: /dev/termination-log
volumeMounts:
```
```
Note that our nginx container has picked up the namespace default cpu and memory resource *limits* and *requests*.
Let's create a pod that exceeds our allowed limits by having it have a container that requests 3 cpu cores.
```shell
```shell
$ kubectl create -f docs/admin/limitrange/invalid-pod.yaml --namespace=limit-example
Error from server: error when creating "docs/admin/limitrange/invalid-pod.yaml": Pod "invalid-pod" is forbidden: [Maximum cpu usage per Pod is 2, but limit is 3., Maximum cpu usage per Container is 2, but limit is 3.]
```
```
Let's create a pod that falls within the allowed limit boundaries.
```shell
```shell
$ kubectl create -f docs/admin/limitrange/valid-pod.yaml --namespace=limit-example
pod "valid-pod" created
$ kubectl get pods valid-pod --namespace=limit-example -o yaml | grep -C 6 resources
```
```yaml
uid: 162a12aa-7157-11e5-9921-286ed488f785
```
```yaml
uid: 162a12aa-7157-11e5-9921-286ed488f785
spec:
containers:
- image: gcr.io/google_containers/serve_hostname
@@ -173,47 +158,37 @@ spec:
requests:
cpu: "1"
memory: 512Mi
```
```
Note that this pod specifies explicit resource *limits* and *requests* so it did not pick up the namespace
default values.
Note: The *limits* for CPU resource are not enforced in the default Kubernetes setup on the physical node
that runs the container unless the administrator deploys the kubelet with the folllowing flag:
```
```shell
$ kubelet --help
Usage of kubelet
....
--cpu-cfs-quota[=false]: Enable CPU CFS quota enforcement for containers that specify CPU limits
$ kubelet --cpu-cfs-quota=true ...
```
```
## Step 4: Cleanup
To remove the resources used by this example, you can just delete the limit-example namespace.
```shell
```shell
$ kubectl delete namespace limit-example
namespace "limit-example" deleted
$ kubectl get namespaces
NAME LABELS STATUS AGE
default <none> Active 20m
```
```
## Summary
Cluster operators that want to restrict the amount of resources a single container or pod may consume
are able to define allowable ranges per Kubernetes namespace. In the absence of any explicit assignments,
the Kubernetes system is able to apply default resource *limits* and *requests* if desired in order to
constrain the amount of resource a pod consumes on a node.
constrain the amount of resource a pod consumes on a node.
+1 -16
View File
@@ -46,12 +46,10 @@ Look [here](namespaces/) for an in depth example of namespaces.
You can list the current namespaces in a cluster using:
```shell
$ kubectl get namespaces
NAME LABELS STATUS
default <none> Active
kube-system <none> Active
```
Kubernetes starts with two initial namespaces:
@@ -61,15 +59,12 @@ Kubernetes starts with two initial namespaces:
You can also get the summary of a specific namespace using:
```shell
$ kubectl get namespaces <name>
```
Or you can get detailed information with:
```shell
$ kubectl describe namespaces <name>
Name: default
Labels: <none>
@@ -81,7 +76,6 @@ Resource Limits
Type Resource Min Max Default
---- -------- --- --- ---
Container cpu - - 100m
```
Note that these details show both resource quota (if present) as well as resource limit ranges.
@@ -105,12 +99,10 @@ See the [design doc](../design/namespaces.html#phases) for more details.
To create a new namespace, first create a new YAML file called `my-namespace.yaml` with the contents:
```yaml
apiVersion: v1
kind: Namespace
metadata:
name: <insert-namespace-name-here>
```
Note that the name of your namespace must be a DNS compatible label.
@@ -120,9 +112,7 @@ More information on the `finalizers` field can be found in the namespace [design
Then run:
```shell
$ kubectl create -f ./my-namespace.yaml
```
### Working in namespaces
@@ -135,9 +125,7 @@ and [Setting the namespace preference](/{{page.version}}/docs/user-guide/namespa
You can delete a namespace with
```shell
$ kubectl delete namespaces <insert-some-namespace-name>
```
**WARNING, this deletes _everything_ under the namespace!**
@@ -156,7 +144,4 @@ across namespaces, you need to use the fully qualified domain name (FQDN).
## Design
Details of the design of namespaces in Kubernetes, including a [detailed example](../design/namespaces.html#example-openshift-origin-managing-a-kubernetes-namespace)
can be found in the [namespaces design doc](../design/namespaces)
can be found in the [namespaces design doc](../design/namespaces)
+60 -61
View File
@@ -27,12 +27,12 @@ services, and replication controllers used by the cluster.
Assuming you have a fresh cluster, you can introspect the available namespace's by doing the following:
```shell
```shell
$ kubectl get namespaces
NAME LABELS
NAME LABELS
default <none>
default <none>
```
### Step Two: Create new namespaces
For this exercise, we will create two additional Kubernetes namespaces to hold our content.
@@ -54,7 +54,7 @@ Use the file [`namespace-dev.json`](namespace-dev.json) which describes a develo
<!-- BEGIN MUNGE: EXAMPLE namespace-dev.json -->
<!-- BEGIN MUNGE: EXAMPLE namespace-dev.json -->
```json
{
"kind": "Namespace",
"apiVersion": "v1",
@@ -64,35 +64,34 @@ Use the file [`namespace-dev.json`](namespace-dev.json) which describes a develo
"name": "development"
}
}
"name": "development"
}
}
}
```
[Download example](namespace-dev.json)
<!-- END MUNGE: EXAMPLE namespace-dev.json -->
Create the development namespace using kubectl.
<!-- END MUNGE: EXAMPLE namespace-dev.json -->
Create the development namespace using kubectl.
```shell
$ kubectl create -f docs/admin/namespaces/namespace-dev.json
```
And then lets create the production namespace using kubectl.
$ kubectl create -f docs/admin/namespaces/namespace-dev.json
```
```shell
$ kubectl create -f docs/admin/namespaces/namespace-prod.json
```
To be sure things are right, let's list all of the namespaces in our cluster.
```shell
```shell
$ kubectl get namespaces
NAME LABELS STATUS
default <none> Active
development name=development Active
To be sure things are right, let's list all of the namespaces in our cluster.
```shell
production name=production Active
```
### Step Three: Create pods in each namespace
A Kubernetes namespace provides the scope for pods, services, and replication controllers in the cluster.
@@ -103,7 +102,7 @@ To demonstrate this, let's spin up a simple replication controller and pod in th
We first check what is the current context:
### Step Three: Create pods in each namespace
```yaml
apiVersion: v1
clusters:
- cluster:
@@ -127,32 +126,32 @@ users:
- name: lithe-cocoa-92103_kubernetes-basic-auth
user:
password: h5M0FtUUIflBSdI7
kind: Config
preferences: {}
users:
username: admin
```
The next step is to define a context for the kubectl client to work in each namespace. The value of "cluster" and "user" fields are copied from the current context.
client-certificate-data: REDACTED
```shell
$ kubectl config set-context dev --namespace=development --cluster=lithe-cocoa-92103_kubernetes --user=lithe-cocoa-92103_kubernetes
token: 65rZW78y8HbwXXtSXuUw9DbP4FLjHi4b
- name: lithe-cocoa-92103_kubernetes-basic-auth
user:
$ kubectl config set-context prod --namespace=production --cluster=lithe-cocoa-92103_kubernetes --user=lithe-cocoa-92103_kubernetes
```
The above commands provided two request contexts you can alternate against depending on what namespace you
wish to work against.
Let's switch to operate in the development namespace.
The next step is to define a context for the kubectl client to work in each namespace. The value of "cluster" and "user" fields are copied from the current context.
```shell
```shell
$ kubectl config use-context dev
```
You can verify your current context by doing the following:
```
The above commands provided two request contexts you can alternate against depending on what namespace you
wish to work against.
```shell
$ kubectl config view
```
```yaml
apiVersion: v1
clusters:
- cluster:
@@ -186,20 +185,20 @@ users:
- name: lithe-cocoa-92103_kubernetes-basic-auth
user:
password: h5M0FtUUIflBSdI7
user: lithe-cocoa-92103_kubernetes
name: lithe-cocoa-92103_kubernetes
- context:
username: admin
```
At this point, all requests we make to the Kubernetes cluster from the command line are scoped to the development namespace.
Let's create some content.
current-context: dev
kind: Config
preferences: {}
users:
```shell
$ kubectl run snowflake --image=kubernetes/serve_hostname --replicas=2
```
We have just created a replication controller whose replica size is 2 that is running the pod called snowflake with a basic container that just serves the hostname.
client-certificate-data: REDACTED
```shell
$ kubectl get rc
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
snowflake snowflake kubernetes/serve_hostname run=snowflake 2
@@ -207,30 +206,30 @@ snowflake snowflake kubernetes/serve_hostname run=snowflake 2
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
snowflake-8w0qn 1/1 Running 0 22s
```
At this point, all requests we make to the Kubernetes cluster from the command line are scoped to the development namespace.
snowflake-jrpzb 1/1 Running 0 22s
```
And this is great, developers are able to do what they want, and they do not have to worry about affecting content in the production namespace.
Let's switch to the production namespace and show how resources in one namespace are hidden from the other.
$ kubectl run snowflake --image=kubernetes/serve_hostname --replicas=2
```
```shell
$ kubectl config use-context prod
```
The production namespace should be empty.
```shell
$ kubectl get rc
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
$ kubectl get pods
snowflake snowflake kubernetes/serve_hostname run=snowflake 2
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
```
Production likes to run cattle, so let's create some cattle pods.
snowflake-jrpzb 1/1 Running 0 22s
```shell
$ kubectl run cattle --image=kubernetes/serve_hostname --replicas=5
$ kubectl get rc
@@ -243,9 +242,9 @@ cattle-97rva 1/1 Running 0 12s
cattle-i9ojn 1/1 Running 0 12s
cattle-qj3yv 1/1 Running 0 12s
cattle-yc7vn 1/1 Running 0 12s
The production namespace should be empty.
cattle-zz7ea 1/1 Running 0 12s
```
At this point, it should be clear that the resources users create in one namespace are hidden from the other namespace.
As the policy support in Kubernetes evolves, we will extend this scenario to show how you can provide different
+1 -35
View File
@@ -27,11 +27,9 @@ services, and replication controllers used by the cluster.
Assuming you have a fresh cluster, you can introspect the available namespace's by doing the following:
```shell
$ kubectl get namespaces
NAME LABELS
default <none>
```
### Step Two: Create new namespaces
@@ -56,7 +54,6 @@ Use the file [`namespace-dev.json`](namespace-dev.json) which describes a develo
<!-- BEGIN MUNGE: EXAMPLE namespace-dev.json -->
```json
{
"kind": "Namespace",
"apiVersion": "v1",
@@ -67,7 +64,6 @@ Use the file [`namespace-dev.json`](namespace-dev.json) which describes a develo
}
}
}
```
[Download example](namespace-dev.json)
@@ -76,32 +72,25 @@ Use the file [`namespace-dev.json`](namespace-dev.json) which describes a develo
Create the development namespace using kubectl.
```shell
$ kubectl create -f docs/admin/namespaces/namespace-dev.json
```
And then lets create the production namespace using kubectl.
```shell
$ kubectl create -f docs/admin/namespaces/namespace-prod.json
```
To be sure things are right, let's list all of the namespaces in our cluster.
```shell
$ kubectl get namespaces
NAME LABELS STATUS
default <none> Active
development name=development Active
production name=production Active
```
### Step Three: Create pods in each namespace
A Kubernetes namespace provides the scope for pods, services, and replication controllers in the cluster.
@@ -113,7 +102,6 @@ To demonstrate this, let's spin up a simple replication controller and pod in th
We first check what is the current context:
```yaml
apiVersion: v1
clusters:
- cluster:
@@ -138,16 +126,13 @@ users:
user:
password: h5M0FtUUIflBSdI7
username: admin
```
The next step is to define a context for the kubectl client to work in each namespace. The value of "cluster" and "user" fields are copied from the current context.
```shell
$ kubectl config set-context dev --namespace=development --cluster=lithe-cocoa-92103_kubernetes --user=lithe-cocoa-92103_kubernetes
$ kubectl config set-context prod --namespace=production --cluster=lithe-cocoa-92103_kubernetes --user=lithe-cocoa-92103_kubernetes
```
The above commands provided two request contexts you can alternate against depending on what namespace you
@@ -156,21 +141,16 @@ wish to work against.
Let's switch to operate in the development namespace.
```shell
$ kubectl config use-context dev
```
You can verify your current context by doing the following:
```shell
$ kubectl config view
```
```yaml
apiVersion: v1
clusters:
- cluster:
@@ -205,7 +185,6 @@ users:
user:
password: h5M0FtUUIflBSdI7
username: admin
```
At this point, all requests we make to the Kubernetes cluster from the command line are scoped to the development namespace.
@@ -213,15 +192,12 @@ At this point, all requests we make to the Kubernetes cluster from the command l
Let's create some content.
```shell
$ kubectl run snowflake --image=kubernetes/serve_hostname --replicas=2
```
We have just created a replication controller whose replica size is 2 that is running the pod called snowflake with a basic container that just serves the hostname.
```shell
$ kubectl get rc
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
snowflake snowflake kubernetes/serve_hostname run=snowflake 2
@@ -230,7 +206,6 @@ $ kubectl get pods
NAME READY STATUS RESTARTS AGE
snowflake-8w0qn 1/1 Running 0 22s
snowflake-jrpzb 1/1 Running 0 22s
```
And this is great, developers are able to do what they want, and they do not have to worry about affecting content in the production namespace.
@@ -238,27 +213,22 @@ And this is great, developers are able to do what they want, and they do not hav
Let's switch to the production namespace and show how resources in one namespace are hidden from the other.
```shell
$ kubectl config use-context prod
```
The production namespace should be empty.
```shell
$ kubectl get rc
CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
```
Production likes to run cattle, so let's create some cattle pods.
```shell
$ kubectl run cattle --image=kubernetes/serve_hostname --replicas=5
$ kubectl get rc
@@ -272,13 +242,9 @@ cattle-i9ojn 1/1 Running 0 12s
cattle-qj3yv 1/1 Running 0 12s
cattle-yc7vn 1/1 Running 0 12s
cattle-zz7ea 1/1 Running 0 12s
```
At this point, it should be clear that the resources users create in one namespace are hidden from the other namespace.
As the policy support in Kubernetes evolves, we will extend this scenario to show how you can provide different
authorization rules for each namespace.
authorization rules for each namespace.
+2 -11
View File
@@ -108,9 +108,7 @@ on that subnet, and is passed to docker's `--bridge` flag.
We start Docker with:
```shell
DOCKER_OPTS="--bridge=cbr0 --iptables=false --ip-masq=false"
DOCKER_OPTS="--bridge=cbr0 --iptables=false --ip-masq=false"
```
This bridge is created by Kubelet (controlled by the `--configure-cbr0=true`
@@ -127,18 +125,14 @@ itself) traffic that is bound for IPs outside the GCE project network
(10.0.0.0/8).
```shell
iptables -t nat -A POSTROUTING ! -d 10.0.0.0/8 -o eth0 -j MASQUERADE
```
Lastly we enable IP forwarding in the kernel (so the kernel will process
packets for bridged containers):
```shell
sysctl net.ipv4.ip_forward=1
```
The result of all this is that all `Pods` can reach each other and can egress
@@ -183,7 +177,4 @@ IPs.
The early design of the networking model and its rationale, and some future
plans are described in more detail in the [networking design
document](../design/networking).
document](../design/networking).
-11
View File
@@ -57,14 +57,12 @@ Node condition is represented as a json object. For example,
the following conditions mean the node is in sane state:
```json
"conditions": [
{
"kind": "Ready",
"status": "True",
},
]
```
If the Status of the Ready condition
@@ -91,7 +89,6 @@ After creation, Kubernetes will check whether the node is valid or not.
For example, if you try to create a node from the following content:
```json
{
"kind": "Node",
"apiVersion": "v1",
@@ -102,7 +99,6 @@ For example, if you try to create a node from the following content:
}
}
}
```
Kubernetes will create a Node object internally (the representation), and
@@ -165,9 +161,7 @@ preparatory step before a node reboot, etc. For example, to mark a node
unschedulable, run this command:
```shell
kubectl replace nodes 10.1.2.3 --patch='{"apiVersion": "v1", "unschedulable": true}'
```
Note that pods which are created by a daemonSet controller bypass the Kubernetes scheduler,
@@ -190,7 +184,6 @@ If you want to explicitly reserve resources for non-Pod processes, you can creat
pod. Use the following template:
```yaml
apiVersion: v1
kind: Pod
metadata:
@@ -203,7 +196,6 @@ spec:
limits:
cpu: 100m
memory: 100Mi
```
Set the `cpu` and `memory` values to the amount of resources you want to reserve.
@@ -216,6 +208,3 @@ on each kubelet where you want to reserve resources.
Node is a top-level resource in the kubernetes REST API. More details about the
API object can be found at: [Node API
object](http://kubernetes.io/v1.1/docs/api-reference/v1/definitions.html#_v1_node).
+1 -6
View File
@@ -87,7 +87,6 @@ supply of Pod IPs.
Kubectl supports creating, updating, and viewing quotas:
```shell
$ kubectl namespace myspace
$ cat <<EOF > quota.json
{
@@ -122,7 +121,6 @@ pods 5 10
replicationcontrollers 5 20
resourcequotas 1 1
services 3 5
```
## Quota and Cluster Capacity
@@ -146,11 +144,8 @@ restrictions around nodes: pods from several namespaces may run on the same node
## Example
See a [detailed example for how to use resource quota](resourcequota/)..
See a [detailed example for how to use resource quota](resourcequota/).
## Read More
See [ResourceQuota design doc](../design/admission_control_resource_quota) for more information.
+28 -50
View File
@@ -13,17 +13,15 @@ This example will work in a custom namespace to demonstrate the concepts involve
Let's create a new namespace called quota-example:
```shell
```shell
$ kubectl create -f docs/admin/resourcequota/namespace.yaml
namespace "quota-example" created
$ kubectl get namespaces
NAME LABELS STATUS AGE
default <none> Active 2m
quota-example <none> Active 39s
```
```
## Step 2: Apply a quota to the namespace
By default, a pod will run with unbounded CPU and memory requests/limits. This means that any pod in the
@@ -37,21 +35,18 @@ checks the total resource *requests*, not resource *limits* of all containers/po
Let's create a simple quota in our namespace:
```shell
```shell
$ kubectl create -f docs/admin/resourcequota/quota.yaml --namespace=quota-example
resourcequota "quota" created
```
```
Once your quota is applied to a namespace, the system will restrict any creation of content
in the namespace until the quota usage has been calculated. This should happen quickly.
You can describe your current quota usage to see what resources are being consumed in your
namespace.
```shell
```shell
$ kubectl describe quota quota --namespace=quota-example
Name: quota
Namespace: quota-example
@@ -65,9 +60,8 @@ replicationcontrollers 0 20
resourcequotas 1 1
secrets 1 10
services 0 5
```
```
## Step 3: Applying default resource requests and limits
Pod authors rarely specify resource requests and limits for their pods.
@@ -77,26 +71,21 @@ cpu and memory by creating an nginx container.
To demonstrate, lets create a replication controller that runs nginx:
```shell
```shell
$ kubectl run nginx --image=nginx --replicas=1 --namespace=quota-example
replicationcontroller "nginx" created
```
```
Now let's look at the pods that were created.
```shell
```shell
$ kubectl get pods --namespace=quota-example
NAME READY STATUS RESTARTS AGE
```
```
What happened? I have no pods! Let's describe the replication controller to get a view of what is happening.
```shell
```shell
kubectl describe rc nginx --namespace=quota-example
Name: nginx
Namespace: quota-example
@@ -109,16 +98,14 @@ No volumes.
Events:
FirstSeen LastSeen Count From SubobjectPath Reason Message
42s 11s 3 {replication-controller } FailedCreate Error creating: Pod "nginx-" is forbidden: Must make a non-zero request for memory since it is tracked by quota.
```
```
The Kubernetes API server is rejecting the replication controllers requests to create a pod because our pods
do not specify any memory usage *request*.
So let's set some default values for the amount of cpu and memory a pod can consume:
```shell
```shell
$ kubectl create -f docs/admin/resourcequota/limits.yaml --namespace=quota-example
limitrange "limits" created
$ kubectl describe limits limits --namespace=quota-example
@@ -128,27 +115,23 @@ Type Resource Min Max Request Limit Limit/Request
---- -------- --- --- ------- ----- -------------
Container memory - - 256Mi 512Mi -
Container cpu - - 100m 200m -
```
```
Now any time a pod is created in this namespace, if it has not specified any resource request/limit, the default
amount of cpu and memory per container will be applied, and the request will be used as part of admission control.
Now that we have applied default resource *request* for our namespace, our replication controller should be able to
create its pods.
```shell
```shell
$ kubectl get pods --namespace=quota-example
NAME READY STATUS RESTARTS AGE
nginx-fca65 1/1 Running 0 1m
```
```
And if we print out our quota usage in the namespace:
```shell
```shell
$ kubectl describe quota quota --namespace=quota-example
Name: quota
Namespace: quota-example
@@ -162,9 +145,8 @@ replicationcontrollers 1 20
resourcequotas 1 1
secrets 1 10
services 0 5
```
```
You can now see the pod that was created is consuming explicit amounts of resources (specified by resource *request*),
and the usage is being tracked by the Kubernetes system properly.
@@ -173,8 +155,4 @@ and the usage is being tracked by the Kubernetes system properly.
Actions that consume node resources for cpu and memory can be subject to hard quota limits defined
by the namespace quota. The resource consumption is measured by resource *request* in pod specification.
Any action that consumes those resources can be tweaked, or can pick up namespace level defaults to
meet your end goal.
Any action that consumes those resources can be tweaked, or can pick up namespace level defaults to meet your end goal.
+30 -54
View File
@@ -13,17 +13,15 @@ This example will work in a custom namespace to demonstrate the concepts involve
Let's create a new namespace called quota-example:
```shell
```shell
$ kubectl create -f docs/admin/resourcequota/namespace.yaml
namespace "quota-example" created
$ kubectl get namespaces
NAME LABELS STATUS AGE
default <none> Active 2m
quota-example <none> Active 39s
```
```
## Step 2: Apply a quota to the namespace
By default, a pod will run with unbounded CPU and memory requests/limits. This means that any pod in the
@@ -37,21 +35,18 @@ checks the total resource *requests*, not resource *limits* of all containers/po
Let's create a simple quota in our namespace:
```shell
```shell
$ kubectl create -f docs/admin/resourcequota/quota.yaml --namespace=quota-example
resourcequota "quota" created
```
```
Once your quota is applied to a namespace, the system will restrict any creation of content
in the namespace until the quota usage has been calculated. This should happen quickly.
You can describe your current quota usage to see what resources are being consumed in your
namespace.
```shell
```shell
$ kubectl describe quota quota --namespace=quota-example
Name: quota
Namespace: quota-example
@@ -65,9 +60,8 @@ replicationcontrollers 0 20
resourcequotas 1 1
secrets 1 10
services 0 5
```
```
## Step 3: Applying default resource requests and limits
Pod authors rarely specify resource requests and limits for their pods.
@@ -77,26 +71,21 @@ cpu and memory by creating an nginx container.
To demonstrate, lets create a replication controller that runs nginx:
```shell
```shell
$ kubectl run nginx --image=nginx --replicas=1 --namespace=quota-example
replicationcontroller "nginx" created
```
```
Now let's look at the pods that were created.
```shell
```shell
$ kubectl get pods --namespace=quota-example
NAME READY STATUS RESTARTS AGE
```
```
What happened? I have no pods! Let's describe the replication controller to get a view of what is happening.
```shell
```shell
kubectl describe rc nginx --namespace=quota-example
Name: nginx
Namespace: quota-example
@@ -109,16 +98,14 @@ No volumes.
Events:
FirstSeen LastSeen Count From SubobjectPath Reason Message
42s 11s 3 {replication-controller } FailedCreate Error creating: Pod "nginx-" is forbidden: Must make a non-zero request for memory since it is tracked by quota.
```
```
The Kubernetes API server is rejecting the replication controllers requests to create a pod because our pods
do not specify any memory usage *request*.
So let's set some default values for the amount of cpu and memory a pod can consume:
```shell
```shell
$ kubectl create -f docs/admin/resourcequota/limits.yaml --namespace=quota-example
limitrange "limits" created
$ kubectl describe limits limits --namespace=quota-example
@@ -128,27 +115,23 @@ Type Resource Min Max Request Limit Limit/Request
---- -------- --- --- ------- ----- -------------
Container memory - - 256Mi 512Mi -
Container cpu - - 100m 200m -
```
```
Now any time a pod is created in this namespace, if it has not specified any resource request/limit, the default
amount of cpu and memory per container will be applied, and the request will be used as part of admission control.
Now that we have applied default resource *request* for our namespace, our replication controller should be able to
create its pods.
```shell
```shell
$ kubectl get pods --namespace=quota-example
NAME READY STATUS RESTARTS AGE
nginx-fca65 1/1 Running 0 1m
```
```
And if we print out our quota usage in the namespace:
```shell
```shell
$ kubectl describe quota quota --namespace=quota-example
Name: quota
Namespace: quota-example
@@ -162,19 +145,12 @@ replicationcontrollers 1 20
resourcequotas 1 1
secrets 1 10
services 0 5
```
You can now see the pod that was created is consuming explicit amounts of resources (specified by resource *request*),
and the usage is being tracked by the Kubernetes system properly.
```
You can now see the pod that was created is consuming explicit amounts of resources (specified by resource *request*), and the usage is being tracked by the Kubernetes system properly.
## Summary
Actions that consume node resources for cpu and memory can be subject to hard quota limits defined
by the namespace quota. The resource consumption is measured by resource *request* in pod specification.
Any action that consumes those resources can be tweaked, or can pick up namespace level defaults to
meet your end goal.
Actions that consume node resources for cpu and memory can be subject to hard quota limits defined by the namespace quota. The resource consumption is measured by resource *request* in pod specification.
Any action that consumes those resources can be tweaked, or can pick up namespace level defaults to meet your end goal.
+11 -11
View File
@@ -13,11 +13,11 @@ The **salt-minion** service runs on the kubernetes-master and each kubernetes-no
Each salt-minion service is configured to interact with the **salt-master** service hosted on the kubernetes-master via the **master.conf** file [(except on GCE)](#standalone-salt-configuration-on-gce).
```shell
```shell
[root@kubernetes-master] $ cat /etc/salt/minion.d/master.conf
master: kubernetes-master
```
```
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-node 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.
@@ -34,27 +34,27 @@ All remaining sections that refer to master/minion setups should be ignored for
Security is not enabled on the salt-master, and the salt-master is configured to auto-accept incoming requests from minions. It is not recommended to use this security configuration in production environments without deeper study. (In some environments this isn't as bad as it might sound if the salt master port isn't externally accessible and you trust everyone on your network.)
```shell
```shell
[root@kubernetes-master] $ cat /etc/salt/master.d/auto-accept.conf
open_mode: True
auto_accept: True
```
```
## Salt minion configuration
Each minion in the salt cluster has an associated configuration that instructs the salt-master how to provision the required resources on the machine.
An example file is presented below using the Vagrant based environment.
```shell
```shell
[root@kubernetes-master] $ cat /etc/salt/minion.d/grains.conf
grains:
etcd_servers: $MASTER_IP
cloud_provider: vagrant
roles:
- kubernetes-master
```
```
Each hosting environment has a slightly different grains.conf file that is used to build conditional logic where required in the Salt files.
The following enumerates the set of defined key/value pairs that are supported today. If you add new ones, please make sure to update this list.
@@ -85,8 +85,8 @@ In addition, a cluster may be running a Debian based operating system or Red Hat
// something specific to Debian environment (apt-get, initd)
{% endif %}
{% endraw %}
```
```
## Best Practices
1. When configuring default arguments for processes, it's best to avoid the use of EnvironmentFiles (Systemd in Red Hat environments) or init.d files (Debian distributions) to hold default values that should be common across operating system environments. This helps keep our Salt template files easy to understand for editors who may not be familiar with the particulars of each distribution.
+1 -10
View File
@@ -62,7 +62,6 @@ of type `ServiceAccountToken` with an annotation referencing the service
account, and the controller will update it with a generated token:
```json
secret.json:
{
"kind": "Secret",
@@ -75,28 +74,20 @@ secret.json:
},
"type": "kubernetes.io/service-account-token"
}
```
```shell
kubectl create -f ./secret.json
kubectl describe secret mysecretname
```
#### To delete/invalidate a service account token
```shell
kubectl delete secret mysecretname
```
### Service Account Controller
Service Account Controller manages ServiceAccount inside namespaces, and ensures
a ServiceAccount named "default" exists in every active namespace.
a ServiceAccount named "default" exists in every active namespace.
+37 -44
View File
@@ -20,14 +20,14 @@ For example, this is how to start a simple web server as a static pod:
1. Choose a node where we want to run the static pod. In this example, it's `my-minion1`.
```shell
[joe@host ~] $ ssh my-minion1
```
```shell
[joe@host ~] $ ssh my-minion1
```
2. Choose a directory, say `/etc/kubelet.d` and place a web server pod definition there, e.g. `/etc/kubernetes.d/static-web.yaml`:
```shell
[root@my-minion1 ~] $ mkdir /etc/kubernetes.d/
```shell
[root@my-minion1 ~] $ mkdir /etc/kubernetes.d/
[root@my-minion1 ~] $ cat <<EOF >/etc/kubernetes.d/static-web.yaml
apiVersion: v1
kind: Pod
@@ -43,23 +43,22 @@ For example, this is how to start a simple web server as a static pod:
- name: web
containerPort: 80
protocol: tcp
EOF
```
EOF
```
2. Configure your kubelet daemon on the node to use this directory by running it with `--config=/etc/kubelet.d/` argument. On Fedora Fedora 21 with Kubernetes 0.17 edit `/etc/kubernetes/kubelet` to include this line:
```
KUBELET_ARGS="--cluster-dns=10.254.0.10 --cluster-domain=kube.local --config=/etc/kubelet.d/"
```
Instructions for other distributions or Kubernetes installations may vary.
```
KUBELET_ARGS="--cluster-dns=10.254.0.10 --cluster-domain=kube.local --config=/etc/kubelet.d/"
```
Instructions for other distributions or Kubernetes installations may vary.
3. Restart kubelet. On Fedora 21, this is:
```shell
[root@my-minion1 ~] $ systemctl restart kubelet
```
```shell
[root@my-minion1 ~] $ systemctl restart kubelet
```
## Pods created via HTTP
Kubelet periodically downloads a file specified by `--manifest-url=<URL>` argument and interprets it as a json/yaml file with a pod definition. It works the same as `--config=<directory>`, i.e. it's reloaded every now and then and changes are applied to running static pods (see below).
@@ -68,50 +67,50 @@ Kubelet periodically downloads a file specified by `--manifest-url=<URL>` argume
When kubelet starts, it automatically starts all pods defined in directory specified in `--config=` or `--manifest-url=` arguments, i.e. our static-web. (It may take some time to pull nginx image, be patient'|):
```shell
```shell
[joe@my-minion1 ~] $ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES
f6d05272b57e nginx:latest "nginx" 8 minutes ago Up 8 minutes k8s_web.6f802af4_static-web-fk-minion1_default_67e24ed9466ba55986d120c867395f3c_378e5f3c
```
f6d05272b57e nginx:latest "nginx" 8 minutes ago Up 8 minutes k8s_web.6f802af4_static-web-fk-minion1_default_67e24ed9466ba55986d120c867395f3c_378e5f3c
```
If we look at our Kubernetes API server (running on host `my-master`), we see that a new mirror-pod was created there too:
```shell
```shell
[joe@host ~] $ ssh my-master
[joe@my-master ~] $ kubectl get pods
POD IP CONTAINER(S) IMAGE(S) HOST LABELS STATUS CREATED MESSAGE
static-web-my-minion1 172.17.0.3 my-minion1/192.168.100.71 role=myrole Running 11 minutes
web nginx Running 11 minutes
```
web nginx Running 11 minutes
```
Labels from the static pod are propagated into the mirror-pod and can be used as usual for filtering.
Notice we cannot delete the pod with the API server (e.g. via [`kubectl`](../user-guide/kubectl/kubectl) command), kubelet simply won't remove it.
```shell
```shell
[joe@my-master ~] $ kubectl delete pod static-web-my-minion1
pods/static-web-my-minion1
[joe@my-master ~] $ kubectl get pods
POD IP CONTAINER(S) IMAGE(S) HOST ...
static-web-my-minion1 172.17.0.3 my-minion1/192.168.100.71 ...
```
static-web-my-minion1 172.17.0.3 my-minion1/192.168.100.71 ...
```
Back to our `my-minion1` host, we can try to stop the container manually and see, that kubelet automatically restarts it in a while:
```shell
```shell
[joe@host ~] $ ssh my-minion1
[joe@my-minion1 ~] $ docker stop f6d05272b57e
[joe@my-minion1 ~] $ sleep 20
[joe@my-minion1 ~] $ docker ps
CONTAINER ID IMAGE COMMAND CREATED ...
5b920cbaf8b1 nginx:latest "nginx -g 'daemon of 2 seconds ago ...
```
5b920cbaf8b1 nginx:latest "nginx -g 'daemon of 2 seconds ago ...
```
## Dynamic addition and removal of static pods
Running kubelet periodically scans the configured directory (`/etc/kubelet.d` in our example) for changes and adds/removes pods as files appear/disappear in this directory.
```shell
```shell
[joe@my-minion1 ~] $ mv /etc/kubernetes.d/static-web.yaml /tmp
[joe@my-minion1 ~] $ sleep 20
[joe@my-minion1 ~] $ docker ps
@@ -120,11 +119,5 @@ Running kubelet periodically scans the configured directory (`/etc/kubelet.d` in
[joe@my-minion1 ~] $ sleep 20
[joe@my-minion1 ~] $ docker ps
CONTAINER ID IMAGE COMMAND CREATED ...
e7a62e3427f1 nginx:latest "nginx -g 'daemon of 27 seconds ago
```
e7a62e3427f1 nginx:latest "nginx -g 'daemon of 27 seconds ago
```