diff --git a/examples/examples_test.go b/examples/examples_test.go index 877d84829e8..103d28a6c18 100644 --- a/examples/examples_test.go +++ b/examples/examples_test.go @@ -291,7 +291,9 @@ func TestExampleObjectSchemas(t *testing.T) { "redis-sentinel-service": &api.Service{}, }, "../examples/resourcequota": { - "resource-quota": &api.ResourceQuota{}, + "namespace": &api.Namespace{}, + "limits": &api.LimitRange{}, + "quota": &api.ResourceQuota{}, }, "../examples/rethinkdb": { "admin-pod": &api.Pod{}, diff --git a/examples/resourcequota/README.md b/examples/resourcequota/README.md new file mode 100644 index 00000000000..f5425bbb049 --- /dev/null +++ b/examples/resourcequota/README.md @@ -0,0 +1,152 @@ +Resource Quota +======================================== +This example demonstrates how resource quota and limits can be applied to a Kubernetes namespace. + +This example assumes you have a functional Kubernetes setup. + +Step 1: Create a namespace +----------------------------------------- +This example will work in a custom namespace to demonstrate the concepts involved. + +Let's create a new namespace called quota-example: + +```shell +$ cluster/kubectl.sh create -f namespace.yaml +$ cluster/kubectl.sh get namespaces +NAME LABELS STATUS +default Active +quota-example Active +``` + +Step 2: Apply a quota to the namespace +----------------------------------------- +By default, a pod will run with unbounded CPU and memory limits. This means that any pod in the +system will be able to consume as much CPU and memory on the node that executes the pod. + +Users may want to restrict how much of the cluster resources a given namespace may consume +across all of its pods in order to manage cluster usage. To do this, a user applies a quota to +a namespace. A quota lets the user set hard limits on the total amount of node resources (cpu, memory) +and API resources (pods, services, etc.) that a namespace may consume. + +Let's create a simple quota in our namespace: + +```shell +$ cluster/kubectl.sh create -f quota.yaml --namespace=quota-example +``` + +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. + +``` +$ cluster/kubectl.sh describe quota quota --namespace=quota-example +Name: quota +Resource Used Hard +-------- ---- ---- +cpu 0m 20 +memory 0m 1Gi +persistentvolumeclaims 0m 10 +pods 0m 10 +replicationcontrollers 0m 20 +resourcequotas 1 1 +secrets 1 10 +services 0m 5 +``` + +Step 3: Applying default resource limits +----------------------------------------- +Pod authors rarely specify resource limits for their pods. + +Since we applied a quota to our project, let's see what happens when an end-user creates a pod that has unbounded +cpu and memory by creating an nginx container. + +To demonstrate, lets create a replication controller that runs nginx: + +```shell +$ cluster/kubectl.sh run nginx --image=nginx --replicas=1 --namespace=quota-example +CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS +nginx nginx nginx run=nginx 1 +``` + +Now let's look at the pods that were created. + +```shell +$ cluster/kubectl.sh get pods --namespace=quota-example +POD IP CONTAINER(S) IMAGE(S) HOST LABELS STATUS CREATED MESSAGE +``` + +What happened? I have no pods! Let's describe the replication controller to get a view of what is happening. + +```shell +cluster/kubectl.sh describe rc nginx --namespace=quota-example +Name: nginx +Image(s): nginx +Selector: run=nginx +Labels: run=nginx +Replicas: 0 current / 1 desired +Pods Status: 0 Running / 0 Waiting / 0 Succeeded / 0 Failed +Events: + FirstSeen LastSeen Count From SubobjectPath Reason Message + Mon, 01 Jun 2015 22:49:31 -0400 Mon, 01 Jun 2015 22:52:22 -0400 7 {replication-controller } failedCreate Error creating: Pod "nginx-" is forbidden: Limited to 1Gi memory, but pod has no specified memory limit +``` + +The Kubernetes API server is rejecting the replication controllers requests to create a pod because our pods +do not specify any memory usage. + +So let's set some default limits for the amount of cpu and memory a pod can consume: + +```shell +$ cluster/kubectl.sh create -f limits.yaml --namespace=quota-example +limitranges/limits +$ cluster/kubectl.sh describe limits limits --namespace=quota-example +Name: limits +Type Resource Min Max Default +---- -------- --- --- --- +Container cpu - - 100m +Container memory - - 512Mi +``` + +Now any time a pod is created in this namespace, if it has not specified any resource limits, the default +amount of cpu and memory per container will be applied as part of admission control. + +Now that we have applied default limits for our namespace, our replication controller should be able to +create its pods. + +```shell +$ cluster/kubectl.sh get pods --namespace=quota-example +POD IP CONTAINER(S) IMAGE(S) HOST LABELS STATUS CREATED MESSAGE +nginx-t40zm 10.0.0.2 10.245.1.3/10.245.1.3 run=nginx Running 2 minutes + nginx nginx Running 2 minutes +``` + +And if we print out our quota usage in the namespace: + +```shell +cluster/kubectl.sh describe quota quota --namespace=quota-example +Name: quota +Resource Used Hard +-------- ---- ---- +cpu 100m 20 +memory 536870912 1Gi +persistentvolumeclaims 0m 10 +pods 1 10 +replicationcontrollers 1 20 +resourcequotas 1 1 +secrets 1 10 +services 0m 5 +``` + +You can now see the pod that was created is consuming explicit amounts of resources, 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. + +Any action that consumes those resources can be tweaked, or can pick up namespace level defaults to +meet your end goal. + +[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/examples/resourcequota/README.md?pixel)]() diff --git a/examples/resourcequota/limits.yaml b/examples/resourcequota/limits.yaml new file mode 100644 index 00000000000..edba3d8318c --- /dev/null +++ b/examples/resourcequota/limits.yaml @@ -0,0 +1,10 @@ +apiVersion: v1beta3 +kind: LimitRange +metadata: + name: limits +spec: + limits: + - default: + cpu: 100m + memory: 512Mi + type: Container diff --git a/examples/resourcequota/namespace.yaml b/examples/resourcequota/namespace.yaml new file mode 100644 index 00000000000..93f3dfb8fc8 --- /dev/null +++ b/examples/resourcequota/namespace.yaml @@ -0,0 +1,4 @@ +apiVersion: v1beta3 +kind: Namespace +metadata: + name: quota-example diff --git a/examples/resourcequota/quota.yaml b/examples/resourcequota/quota.yaml new file mode 100644 index 00000000000..61493a0167c --- /dev/null +++ b/examples/resourcequota/quota.yaml @@ -0,0 +1,14 @@ +apiVersion: v1beta3 +kind: ResourceQuota +metadata: + name: quota +spec: + hard: + cpu: "20" + memory: 1Gi + persistentvolumeclaims: "10" + pods: "10" + replicationcontrollers: "20" + resourcequotas: "1" + secrets: "10" + services: "5" diff --git a/examples/resourcequota/resource-quota.json b/examples/resourcequota/resource-quota.json deleted file mode 100644 index c062eb82e6f..00000000000 --- a/examples/resourcequota/resource-quota.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "apiVersion": "v1beta3", - "kind": "ResourceQuota", - "metadata": { - "name": "quota" - }, - "spec": { - "hard": { - "memory": "1Gi", - "cpu": "20", - "pods": "10", - "services": "5", - "replicationcontrollers":"20", - "resourcequotas":"1", - "secrets":"10", - "persistentvolumeclaims":"10" - } - } -}