diff --git a/Makefile b/Makefile index 3657cb577a..ff308061a4 100644 --- a/Makefile +++ b/Makefile @@ -13,3 +13,6 @@ build-preview: ## Build site with drafts and future posts enabled. serve: ## Boot the development server. jekyll serve + +stage: ## Run the Jekyll staging container. + docker run -ti --rm -v "$PWD":/k8sdocs -p 4000:4000 gcr.io/google-samples/k8sdocs:1.1 diff --git a/_data/tasks.yml b/_data/tasks.yml index 08b45308d4..9452aaad35 100644 --- a/_data/tasks.yml +++ b/_data/tasks.yml @@ -11,7 +11,11 @@ toc: - title: Configure Pods and Containers section: + - docs/tasks/configure-pod-container/assign-memory-resource.md + - docs/tasks/configure-pod-container/assign-cpu-resource.md + - docs/tasks/configure-pod-container/quality-service-pod.md - docs/tasks/configure-pod-container/assign-cpu-ram-container.md + - docs/tasks/configure-pod-container/opaque-integer-resource.md - docs/tasks/configure-pod-container/configure-volume-storage.md - docs/tasks/configure-pod-container/configure-persistent-volume-storage.md - docs/tasks/configure-pod-container/configure-projected-volume-storage.md @@ -108,17 +112,23 @@ toc: - title: Administer a Cluster section: + - title: Manage Memory, CPU, and API Resources + section: + - docs/tasks/administer-cluster/memory-default-namespace.md + - docs/tasks/administer-cluster/cpu-default-namespace.md + - docs/tasks/administer-cluster/memory-constraint-namespace.md + - docs/tasks/administer-cluster/cpu-constraint-namespace.md + - docs/tasks/administer-cluster/apply-resource-quota-limit.md + - docs/tasks/administer-cluster/quota-memory-cpu-namespace.md + - docs/tasks/administer-cluster/quota-pod-namespace.md + - docs/tasks/administer-cluster/quota-api-object.md + - docs/tasks/administer-cluster/opaque-integer-resource-node.md - docs/tasks/administer-cluster/access-cluster-api.md - docs/tasks/administer-cluster/access-cluster-services.md - docs/tasks/administer-cluster/securing-a-cluster.md - docs/tasks/administer-cluster/encrypt-data.md - docs/tasks/administer-cluster/configure-upgrade-etcd.md - - docs/tasks/administer-cluster/apply-resource-quota-limit.md - - docs/tasks/administer-cluster/out-of-resource.md - - docs/tasks/administer-cluster/cpu-memory-limit.md - - docs/tasks/administer-cluster/reserve-compute-resources.md - docs/tasks/administer-cluster/static-pod.md - - docs/tasks/administer-cluster/guaranteed-scheduling-critical-addon-pods.md - docs/tasks/administer-cluster/cluster-management.md - docs/tasks/administer-cluster/upgrade-1-6.md - docs/tasks/administer-cluster/kubeadm-upgrade-1-7.md @@ -126,6 +136,10 @@ toc: - docs/tasks/administer-cluster/namespaces-walkthrough.md - docs/tasks/administer-cluster/dns-horizontal-autoscaling.md - docs/tasks/administer-cluster/safely-drain-node.md + - docs/tasks/administer-cluster/cpu-memory-limit.md + - docs/tasks/administer-cluster/out-of-resource.md + - docs/tasks/administer-cluster/reserve-compute-resources.md + - docs/tasks/administer-cluster/guaranteed-scheduling-critical-addon-pods.md - docs/tasks/administer-cluster/declare-network-policy.md - title: Install Network Policy Provider section: diff --git a/_redirects b/_redirects index 70e111ece7..d97fcabfb4 100644 --- a/_redirects +++ b/_redirects @@ -1,7 +1,7 @@ -# -# set server-side redirects in this file -# see https://www.netlify.com/docs/redirects/ -# +############################################### +# set server-side redirects in this file # +# see https://www.netlify.com/docs/redirects/ # +############################################### /docs/admin/addons /docs/concepts/cluster-administration/addons 301 /docs/admin/apparmor/ /docs/tutorials/clusters/apparmor 301 @@ -32,7 +32,6 @@ /docs/admin/node-problem /docs/tasks/debug-application-cluster/monitor-node-health 301 /docs/admin/out-of-resource /docs/tasks/administer-cluster/out-of-resource 301 /docs/admin/rescheduler /docs/tasks/administer-cluster/guaranteed-scheduling-critical-addon-pods 301 -/docs/admin/resourcequota/ /docs/concepts/policy/resource-quotas 301 /docs/admin/resourcequota/limitstorageconsumption /docs/tasks/administer-cluster/limit-storage-consumption 301 /docs/admin/resourcequota/walkthrough /docs/tasks/administer-cluster/apply-resource-quota-limit 301 /docs/admin/static-pods /docs/tasks/administer-cluster/static-pod 301 @@ -88,6 +87,7 @@ /docs/samples /docs/tutorials/ 301 /docs/tasks/administer-cluster/assign-pods-nodes /docs/tasks/configure-pod-container/assign-pods-nodes 301 /docs/tasks/administer-cluster/overview /docs/concepts/cluster-administration/cluster-administration-overview 301 +/docs/tasks/administer-cluster/cpu-memory-limit /docs/tasks/administer-cluster/memory-default-namespace 301 /docs/tasks/configure-pod-container/apply-resource-quota-limit /docs/tasks/administer-cluster/apply-resource-quota-limit 301 /docs/tasks/configure-pod-container/calico-network-policy /docs/tasks/administer-cluster/calico-network-policy 301 @@ -99,13 +99,15 @@ /docs/tasks/configure-pod-container/environment-variable-expose-pod-information /docs/tasks/inject-data-application/environment-variable-expose-pod-information 301 /docs/tasks/configure-pod-container/limit-range /docs/tasks/administer-cluster/cpu-memory-limit 301 /docs/tasks/configure-pod-container/romana-network-policy /docs/tasks/administer-cluster/romana-network-policy 301 -/docs/tasks/configure-pod-container/weave-network-policy /docs/tasks/administer-cluster/weave-network-policy 301 +/docs/tasks/configure-pod-container/weave-network-policy /docs/tasks/administer-cluster/weave-network-policy 301 +/docs/tasks/configure-pod-container/assign-cpu-ram-container /docs/tasks/configure-pod-container/assign-memory-resource 301 /docs/tasks/kubectl/get-shell-running-container /docs/tasks/debug-application-cluster/get-shell-running-container 301 /docs/tasks/kubectl/install /docs/tasks/tools/install-kubectl 301 /docs/tasks/kubectl/list-all-running-container-images /docs/tasks/access-application-cluster/list-all-running-container-images 301 /docs/tasks/manage-stateful-set/debugging-a-statefulset /docs/tasks/debug-application-cluster/debug-stateful-set 301 +/docs/tasks/manage-stateful-set/delete-pods docs/tasks/run-application/force-delete-stateful-set-pod 301 /docs/tasks/manage-stateful-set/deleting-a-statefulset /docs/tasks/run-application/delete-stateful-set 301 /docs/tasks/manage-stateful-set/scale-stateful-set /docs/tasks/run-application/scale-stateful-set 301 /docs/tasks/manage-stateful-set/upgrade-pet-set-to-stateful-set /docs/tasks/run-application/upgrade-pet-set-to-stateful-set 301 @@ -220,7 +222,115 @@ /docs/whatisk8s /docs/concepts/overview/what-is-kubernetes 301 + +############## +# address 404s # +/concepts/containers/container-lifecycle-hooks /docs/concepts/containers/container-lifecycle-hooks 301 + +/docs/api-reference/apps/v1alpha1/definitions https://v1-4.docs.kubernetes.io/docs/api-reference/apps/v1alpha1/definitions 301 +/docs/api-reference/apps/v1beta1/operations https://v1-4.docs.kubernetes.io/docs/api-reference/apps/v1beta1/operations 301 +/docs/api-reference/authorization.k8s.io/v1beta1/definitions https://v1-4.docs.kubernetes.io/docs/api-reference/authorization.k8s.io/v1beta1/definitions 301 +/docs/api-reference/authorization.k8s.io/v1beta1/operations https://v1-4.docs.kubernetes.io/docs/api-reference/authorization.k8s.io/v1beta1/operations 301 +/docs/api-reference/autoscaling/v1/operations https://v1-4.docs.kubernetes.io/docs/api-reference/autoscaling/v1/operations 301 +/docs/api-reference/batch/v1/operations https://v1-4.docs.kubernetes.io/docs/api-reference/batch/v1/operations 301 +/docs/api-reference/batch/v2alpha1/definitions https://v1-4.docs.kubernetes.io/docs/api-reference/batch/v2alpha1/definitions 301 +/docs/api-reference/certificates.k8s.io/v1alpha1/definitions https://v1-4.docs.kubernetes.io/docs/api-reference/certificates.k8s.io/v1alpha1/definitions 301 +/docs/api-reference/certificates/v1alpha1/operations https://v1-4.docs.kubernetes.io/docs/api-reference/certificates/v1alpha1/operations 301 +/docs/api-reference/extensions/v1beta1/operations https://v1-4.docs.kubernetes.io/docs/api-reference/extensions/v1beta1/operations 301 +/docs/api-reference/policy/v1alpha1/definitions https://v1-4.docs.kubernetes.io/docs/api-reference/policy/v1alpha1/definitions 301 +/docs/api-reference/policy/v1beta1/definitions https://v1-4.docs.kubernetes.io/docs/api-reference/policy/v1beta1/definitions 301 +/docs/api-reference/README https://v1-4.docs.kubernetes.io/docs/api-reference/README 301 +/docs/api-reference/storage.k8s.io/v1beta1/operations https://v1-4.docs.kubernetes.io/docs/api-reference/storage.k8s.io/v1beta1/operations 301 + +/docs/api-reference/v1/definitions /docs/api-reference/v1.7 301 + +/docs/concepts/cluster /docs/concepts/cluster-administration/cluster-administration-overview/ 301 +/docs/concepts/object-metadata/annotations /docs/concepts/overview/working-with-objects/annotations 301 + +/docs/concepts/workloads/controllers/daemonset/docs/concepts/workloads/pods/pod /docs/concepts/workloads/pods/pod 301 +/docs/concepts/workloads/controllers/deployment/docs/concepts/workloads/pods/pod /docs/concepts/workloads/pods/pod 301 + +/docs/contribute/write-new-topic /docs/home/contribute/write-new-topic 301 + +/docs/getting-started-guides/coreos/azure /docs/getting-started-guides/coreos 301 +/docs/getting-started-guides/coreos/bare_metal_calico /docs/getting-started-guides/coreos 301 +/docs/getting-started-guides/juju /docs/getting-started-guides/ubuntu/installation 301 +/docs/getting-started-guides/kargo /docs/getting-started-guides/kubespray 301 +/docs/getting-started-guides/logging-elasticsearch /docs/tasks/debug-application-cluster/logging-elasticsearch-kibana 301 +/docs/getting-started-guides/logging /docs/concepts/cluster-administration/logging 301 +/docs/getting-started-guides/rackspace /docs/setup/pick-right-solution 301 +/docs/getting-started-guides/ubuntu-calico /docs/getting-started-guides/ubuntu 301 +/docs/getting-started-guides/ubuntu/automated /docs/getting-started-guides/ubuntu 301 +/docs/getting-started-guides/vagrant /docs/getting-started-guides/alternatives 301 +/docs/getting-started-guides/windows/While /docs/getting-started-guides/windows 301 + +/docs/federation/api-reference/extensions/v1beta1/definitions /docs/reference/federation/extensions/v1beta1/definitions 301 +/docs/federation/api-reference/federation/v1beta1/definitions /docs/reference/federation/extensions/v1beta1/definitions 301 +/docs/federation/api-reference/README /docs/reference/federation 301 +/docs/federation/api-reference/v1/definitions /docs/reference/federation/v1/definitions 301 +/docs/reference/federation/v1beta1/definitions /docs/reference/federation/extensions/v1beta1/definitions 301 +/docs/reference/federation/v1beta1/operations /docs/reference/federation/extensions/v1beta1/operations 301 + +/docs/reporting-security-issues /security 301 + +/docs/stable/user-guide/labels /docs/concepts/overview/working-with-objects/labels 301 +/docs/tasks/access-application-cluster/access-cluster.md /docs/tasks/access-application-cluster/access-cluster 301 +/docs/tasks/access-kubernetes-api/access-kubernetes-api/http-proxy-access-api /docs/tasks/access-kubernetes-api/http-proxy-access-api 301 +/docs/tasks/administer-cluster/reserve-compute-resources/out-of-resource.md /docs/tasks/administer-cluster/out-of-resource 301 +/docs/tasks/configure-pod-container/configure-pod-disruption-budget /docs/tasks/run-application/configure-pdb 301 +/docs/tasks/configure-pod-container/define-command-argument-container /docs/tasks/inject-data-application/define-command-argument-container 301 +/docs/tasks/debug-application-cluster/sematext-logging-monitoring https://sematext.com/kubernetes/ 301 +/docs/tasks/job/work-queue-1 /docs/concepts/workloads/controllers/jobs-run-to-completion 301 +/docs/tasks/manage-stateful-set/delete-pods /docs/tasks/run-application/delete-stateful-set 301 + +/docs/tutorials/getting-started/cluster-intro /docs/tutorials/kubernetes-basics/cluster-intro 301 +/docs/tutorials/getting-started/expose-intro /docs/tutorials/kubernetes-basics/expose-intro 301 +/docs/tutorials/getting-started/scale-app /docs/tutorials/kubernetes-basics/scale-interactive 301 +/docs/tutorials/getting-started/scale-intro /docs/tutorials/kubernetes-basics/scale-intro 301 +/docs/tutorials/getting-started/update-interactive /docs/tutorials/kubernetes-basics/update-interactive 301 +/docs/tutorials/getting-started/update-intro /docs/tutorials/kubernetes-basics/ 301 + +/docs/user-guide/containers /docs/tasks/inject-data-application/define-command-argument-container 301 +/docs/user-guide/horizontal-pod-autoscaling/walkthrough.md /docs/tasks/run-application/horizontal-pod-autoscale-walkthrough 301 +/docs/user-guide/ingress.md /docs/concepts/services-networking/ingress 301 +/docs/user-guide/replication-controller/operations /docs/concepts/workloads/controllers/replicationcontroller 301 +/docs/user-guide/resizing-a-replication-controller /docs/concepts/workloads/controllers/replicationcontroller 301 +/docs/user-guide/scheduled-jobs /docs/concepts/workloads/controllers/cron-jobs 301 +/docs/user-guide/security-context /docs/tasks/configure-pod-container/security-context 301 + +/kubernetes-bootcamp/2-1.html /docs/tutorials/kubernetes-basics 301 +/kubernetes-bootcamp/2-3-2.html /docs/tutorials/kubernetes-basics 301 +/kubernetes /docs 301 +/kubernetes/swagger-spec https://github.com/kubernetes/kubernetes/tree/master/api/swagger-spec 301 +/serviceaccount/token /docs/tasks/configure-pod-container/configure-service-account 301 + +/v1.1/docs/admin/networking.html /docs/concepts/cluster-administration/networking 301 + + +############################ +# pattern matching redirects +# +/docs/user-guide/kubectl/kubectl_* /docs/user-guide/kubectl/v1.7/#:splat 200 + +/docs/user-guide/kubectl/1_5/* https://v1-5.docs.kubernetes.io/docs/user-guide/kubectl/v1.5 301 +/docs/user-guide/kubectl/v1.5/node_modules/* https://v1-5.docs.kubernetes.io/docs/user-guide/kubectl/v1.5 301 +/docs/resources-reference/1_5/* https://v1-5.docs.kubernetes.io/docs/resources-reference/v1.5 301 +/docs/resources-reference/v1.5/node_modules/* https://v1-5.docs.kubernetes.io/docs/resources-reference/v1.5 301 +/docs/api-reference/1_5/* https://v1-5.docs.kubernetes.io/docs/api-reference/v1.5 301 +/docs/api-reference/v1.5/node_modules/* https://v1-5.docs.kubernetes.io/docs/api-reference/v1.5 301 + +/docs/user-guide/kubectl/v1.6/node_modules/* https://v1-6.docs.kubernetes.io/docs/user-guide/kubectl/v1.6 301 +/docs/api-reference/v1.6/node_modules/* https://v1-6.docs.kubernetes.io/docs/api-reference/v1.6 301 + +/docs/api-reference/v1.7/node_modules/* /docs/api-reference/v1.7 301 + +/docs/getting-started-guides/docker-multinode/* /docs/setup/independent/create-cluster-kubeadm 301 + +/docs/admin/resourcequota/* /docs/concepts/policy/resource-quotas 301 + + +################################# # redirects from /js/redirects.js # /resource-quota /docs/concepts/policy/resource-quotas 301 @@ -236,7 +346,8 @@ /v1.1 / 301 /v1.0 / 301 -# + +######################################################## # Redirect users with chinese language preference to /cn # #/ /cn 302 Language=zh diff --git a/docs/admin/bootstrap-tokens.md b/docs/admin/bootstrap-tokens.md index 3449b82b1c..c0456c9dc4 100644 --- a/docs/admin/bootstrap-tokens.md +++ b/docs/admin/bootstrap-tokens.md @@ -43,7 +43,7 @@ All features for Bootstrap Tokens are disabled by default in Kubernetes v1.6. You can enable the Bootstrap Token authenticator with the `--experimental-bootstrap-token-auth` flag on the API server. You can enable -the Bootstrap controllers by specifying them withthe `--controllers` flag on the +the Bootstrap controllers by specifying them with the `--controllers` flag on the controller manager with something like `--controllers=*,tokencleaner,bootstrapsigner`. This is done automatically when using `kubeadm`. diff --git a/docs/admin/extensible-admission-controllers.md b/docs/admin/extensible-admission-controllers.md index fb4ca7bfa9..1828ba507c 100644 --- a/docs/admin/extensible-admission-controllers.md +++ b/docs/admin/extensible-admission-controllers.md @@ -283,5 +283,5 @@ and `Fail` policies, meaning that upon a communication error with the webhook admission controller, the `GenericAdmissionWebhook` can admit or reject the operation based on the configured policy. -After you create the `initializerConfiguration`, the system will take a few +After you create the `externalAdmissionHookConfiguration`, the system will take a few seconds to honor the new configuration. diff --git a/docs/concepts/architecture/nodes.md b/docs/concepts/architecture/nodes.md index 5a6e051a6c..54350a978b 100644 --- a/docs/concepts/architecture/nodes.md +++ b/docs/concepts/architecture/nodes.md @@ -122,7 +122,7 @@ CIDR block to the node when it is registered (if CIDR assignment is turned on). The second is keeping the node controller's internal list of nodes up to date with the cloud provider's list of available machines. When running in a cloud -environment, whenever a node is unhealthy the node controller asks the cloud +environment, whenever a node is unhealthy, the node controller asks the cloud provider if the VM for that node is still available. If not, the node controller deletes the node from its list of nodes. diff --git a/docs/concepts/overview/kubernetes-api.md b/docs/concepts/overview/kubernetes-api.md index 6307d5b2ec..a3218d8db7 100644 --- a/docs/concepts/overview/kubernetes-api.md +++ b/docs/concepts/overview/kubernetes-api.md @@ -73,9 +73,9 @@ The API group is specified in a REST path and in the `apiVersion` field of a ser Currently there are several API groups in use: -1. the "core" (oftentimes called "legacy", due to not having explicit group name) group, which is at +1. The "core" (oftentimes called "legacy", due to not having explicit group name) group, which is at REST path `/api/v1` and is not specified as part of the `apiVersion` field, e.g. `apiVersion: v1`. -1. the named groups are at REST path `/apis/$GROUP_NAME/$VERSION`, and use `apiVersion: $GROUP_NAME/$VERSION` +1. The named groups are at REST path `/apis/$GROUP_NAME/$VERSION`, and use `apiVersion: $GROUP_NAME/$VERSION` (e.g. `apiVersion: batch/v1`). Full list of supported API groups can be seen in [Kubernetes API reference](/docs/reference/). diff --git a/docs/concepts/workloads/controllers/daemonset.md b/docs/concepts/workloads/controllers/daemonset.md index 212154b2a2..57b67447ae 100644 --- a/docs/concepts/workloads/controllers/daemonset.md +++ b/docs/concepts/workloads/controllers/daemonset.md @@ -26,13 +26,13 @@ different flags and/or different memory and cpu requests for different hardware ## Writing a DaemonSet Spec -### Create a DeamonSet +### Create a DaemonSet -You can describe a DeamonSet in a YAML file. For example, the deamonset.yaml file below describes a DeamonSet that runs the fluentd-elasticsearch Docker image: +You can describe a DaemonSet in a YAML file. For example, the deamonset.yaml file below describes a DaemonSet that runs the fluentd-elasticsearch Docker image: {% include code.html language="yaml" file="deamonset.yaml" ghlink="/docs/concepts/workloads/controllers/deamonset.yaml" %} -* Create a DeamonSet based on the YAML file: +* Create a DaemonSet based on the YAML file: ``` kubectl create -f deamonset.yaml ``` @@ -49,7 +49,7 @@ A DaemonSet also needs a [`.spec`](https://git.k8s.io/community/contributors/dev The `.spec.template` is the only required field of the `.spec`. -The `.spec.template` is a [pod template](/docs/concepts/workloads/pods/pod-overview/#pod-templates). It has exactly the same schema as a [pod](docs/concepts/workloads/pods/pod/), except it is nested and does not have an `apiVersion` or `kind`. +The `.spec.template` is a [pod template](/docs/concepts/workloads/pods/pod-overview/#pod-templates). It has exactly the same schema as a [pod](/docs/concepts/workloads/pods/pod/), except it is nested and does not have an `apiVersion` or `kind`. In addition to required fields for a pod, a pod template in a DaemonSet has to specify appropriate labels (see [pod selector](#pod-selector)). diff --git a/docs/concepts/workloads/controllers/deployment.md b/docs/concepts/workloads/controllers/deployment.md index c056f8b4fe..f31e12792b 100644 --- a/docs/concepts/workloads/controllers/deployment.md +++ b/docs/concepts/workloads/controllers/deployment.md @@ -787,7 +787,7 @@ A Deployment also needs a [`.spec` section](https://git.k8s.io/community/contrib The `.spec.template` is the only required field of the `.spec`. -The `.spec.template` is a [pod template](/docs/concepts/workloads/pods/pod-overview/#pod-templates). It has exactly the same schema as a [Pod](docs/concepts/workloads/pods/pod/), except it is nested and does not have an +The `.spec.template` is a [pod template](/docs/concepts/workloads/pods/pod-overview/#pod-templates). It has exactly the same schema as a [Pod](/docs/concepts/workloads/pods/pod/), except it is nested and does not have an `apiVersion` or `kind`. In addition to required fields for a Pod, a pod template in a Deployment must specify appropriate @@ -810,7 +810,7 @@ the API. If `.spec.selector` is unspecified, `.spec.selector.matchLabels` defau `.spec.template.metadata.labels`. A Deployment may terminate Pods whose labels match the selector if their template is different -tfrom `.spec.template` or if the total number of such Pods exceeds `.spec.replicas`. It brings up new +from `.spec.template` or if the total number of such Pods exceeds `.spec.replicas`. It brings up new Pods with `.spec.template` if the number of Pods is less than the desired number. **Note:** You should not create other pods whose labels match this selector, either directly, by creating diff --git a/docs/concepts/workloads/controllers/garbage-collection.md b/docs/concepts/workloads/controllers/garbage-collection.md index 6c9d0d8224..b03a19a042 100644 --- a/docs/concepts/workloads/controllers/garbage-collection.md +++ b/docs/concepts/workloads/controllers/garbage-collection.md @@ -147,6 +147,13 @@ Here's an example that orphans the dependents of a ReplicaSet: kubectl delete replicaset my-repset --cascade=false ``` +### Addtional note on Deployments + +When using cascading deletes with Deployments you *must* use `propagationPolicy: Foreground` +to delete not only the ReplicaSets created, but also their Pods. If this type of _propagationPolicy_ +is not used, only the ReplicaSets will be deleted, and the Pods will be orphaned. +See [kubeadm/#149](https://github.com/kubernetes/kubeadm/issues/149#issuecomment-284766613) for more information. + ## Known issues Tracked at [#26120](https://github.com/kubernetes/kubernetes/issues/26120) diff --git a/docs/concepts/workloads/pods/disruptions.md b/docs/concepts/workloads/pods/disruptions.md index 192a7e9086..0b78f1005d 100644 --- a/docs/concepts/workloads/pods/disruptions.md +++ b/docs/concepts/workloads/pods/disruptions.md @@ -192,7 +192,7 @@ The cluster state now looks like this: | | pod-b *available* | pod-c *available* | | | pod-d *available* | pod-y | -Now, the cluster admin tries to drain `node-2`. +Now, the cluster administrator tries to drain `node-2`. The drain command will try to evict the two pods in some order, say `pod-b` first and then `pod-d`. It will succeed at evicting `pod-b`. But, when it tries to evict `pod-d`, it will be refused because that would leave only diff --git a/docs/getting-started-guides/ubuntu/index.md b/docs/getting-started-guides/ubuntu/index.md index e732c75d0a..576f35d09a 100644 --- a/docs/getting-started-guides/ubuntu/index.md +++ b/docs/getting-started-guides/ubuntu/index.md @@ -55,12 +55,6 @@ These are more in-depth guides for users choosing to run Kubernetes in productio - [Localhost using LXD](/docs/getting-started-guides/ubuntu/local) -## Community Ubuntu Guides - - - [Calico Configuration](/docs/getting-started-guides/ubuntu/calico) - -Please feel free to submit guides to this section. - ## Where to find us We're normally following the following Slack channels: diff --git a/docs/home/contribute/stage-documentation-changes.md b/docs/home/contribute/stage-documentation-changes.md index 8fdfc43887..c81ea176ed 100644 --- a/docs/home/contribute/stage-documentation-changes.md +++ b/docs/home/contribute/stage-documentation-changes.md @@ -43,10 +43,13 @@ for this image. 1. In the root of your cloned repository, enter this command to start a local web server: - docker run -ti --rm -v "$PWD":/k8sdocs -p 4000:4000 gcr.io/google-samples/k8sdocs:1.1 + make stage -1. View your staged content at -http://localhost:4000. + This will run the following command: + + docker run -ti --rm -v "$PWD":/k8sdocs -p 4000:4000 gcr.io/google-samples/k8sdocs:1.1 + +1. View your staged content at `http://localhost:4000`. ## Staging locally without Docker @@ -56,21 +59,20 @@ http://localhost:4000. 1. Verify that Ruby and RubyGems are installed: - gem --version + gem --version 1. Install the GitHub Pages package, which includes Jekyll: - gem install github-pages + gem install github-pages 1. Clone your fork to your local development machine. 1. In the root of your cloned repository, enter this command to start a local web server: - jekyll serve + jekyll serve -1. View your staged content at -http://localhost:4000. +1. View your staged content at `http://localhost:4000`. NOTE: If you do not want Jekyll to interfere with your other globally installed gems, you can use `bundler`: diff --git a/docs/setup/independent/create-cluster-kubeadm.md b/docs/setup/independent/create-cluster-kubeadm.md index 57240bed84..3878c48231 100644 --- a/docs/setup/independent/create-cluster-kubeadm.md +++ b/docs/setup/independent/create-cluster-kubeadm.md @@ -452,6 +452,7 @@ control of your Kubernetes cluster. * Learn about kubeadm's advanced usage on the [advanced reference doc](/docs/admin/kubeadm/). * Learn more about Kubernetes [concepts](/docs/concepts/) and [`kubectl`](/docs/user-guide/kubectl-overview/). +* Configure log rotation. You can use **logrotate** for that. When using Docker, you can specify log rotation options for Docker daemon, for example `--log-driver=json-file --log-opt=max-size=10m --log-opt=max-file=5`. See [Configure and troubleshoot the Docker daemon](https://docs.docker.com/engine/admin/) for more details. ## Feedback diff --git a/docs/tasks/access-application-cluster/load-balance-access-application-cluster.md b/docs/tasks/access-application-cluster/load-balance-access-application-cluster.md index 873de6b2a2..91de9ece98 100644 --- a/docs/tasks/access-application-cluster/load-balance-access-application-cluster.md +++ b/docs/tasks/access-application-cluster/load-balance-access-application-cluster.md @@ -40,9 +40,9 @@ load-balanced access to an application running in a cluster. The output is similar to this: - NAME READY STATUS RESTARTS AGE - hello-world-2189936611-8fyp0 1/1 Running 0 6m - hello-world-2189936611-9isq8 1/1 Running 0 6m + NAME READY STATUS RESTARTS AGE + hello-world-2189936611-8fyp0 1/1 Running 0 6m + hello-world-2189936611-9isq8 1/1 Running 0 6m 1. List the replica set for the two Hello World pods: @@ -50,8 +50,8 @@ load-balanced access to an application running in a cluster. The output is similar to this: - NAME DESIRED CURRENT AGE - hello-world-2189936611 2 2 12m + NAME DESIRED CURRENT AGE + hello-world-2189936611 2 2 12m 1. Create a Service object that exposes the replica set: @@ -75,14 +75,14 @@ load-balanced access to an application running in a cluster. 1. Use your Service object to access the Hello World application: - curl :8080 + curl :8080 where `` is the external IP address of your service. The output is a hello message from the application: - Hello Kubernetes! + Hello Kubernetes! Note: If you are using Minikube, enter these commands: @@ -93,7 +93,7 @@ load-balanced access to an application running in a cluster. value for your service. Then enter this command to access the Hello World application: - curl : + curl : where `` us the IP address of your Minikube node, and `` is the NodePort value for your service. diff --git a/docs/tasks/access-application-cluster/web-ui-dashboard.md b/docs/tasks/access-application-cluster/web-ui-dashboard.md index 3683ca30b4..aa3a9ddf1d 100644 --- a/docs/tasks/access-application-cluster/web-ui-dashboard.md +++ b/docs/tasks/access-application-cluster/web-ui-dashboard.md @@ -156,7 +156,7 @@ Services and discovery view shows Kubernetes resources that allow for exposing s Storage view shows Persistent Volume Claim resources which are used by applications for storing data. #### Config -Config view show all Kubernetes resources that are used for live configuration of applications running in clusters. This is now Config Maps and Secrets. Thie views allows for editing and managing config objects and displays secrets hidden by default. +Config view show all Kubernetes resources that are used for live configuration of applications running in clusters. This is now Config Maps and Secrets. The view allows for editing and managing config objects and displays secrets hidden by default. ![Secret detail view](/images/docs/ui-dashboard-secret-detail.png) diff --git a/docs/tasks/administer-cluster/access-cluster-api.md b/docs/tasks/administer-cluster/access-cluster-api.md index c96524252a..1fd97c9f07 100644 --- a/docs/tasks/administer-cluster/access-cluster-api.md +++ b/docs/tasks/administer-cluster/access-cluster-api.md @@ -121,7 +121,7 @@ Kubernetes officially supports client libraries for [Go](#go-client) and * Write an application atop of the client-go clients. Note that client-go defines its own API objects, so if needed, please import API definitions from client-go rather than from the main repository, e.g., `import "k8s.io/client-go/1.4/pkg/api/v1"` is correct. The Go client can use the same [kubeconfig file](/docs/concepts/cluster-administration/authenticate-across-clusters-kubeconfig/) -as the kubectl CLI does to locate and authenticate to the apiserver. See this [example](https://git.k8s.io/client-go/examples/out-of-cluster/main.go): +as the kubectl CLI does to locate and authenticate to the apiserver. See this [example](https://git.k8s.io/client-go/examples/out-of-cluster-client-configuration/main.go): ```golang import ( @@ -196,7 +196,7 @@ From within a pod the recommended ways to connect to API are: in any container of the pod can access it. See this [example of using kubectl proxy in a pod](https://github.com/kubernetes/kubernetes/tree/{{page.githubbranch}}/examples/kubectl-container/). - use the Go client library, and create a client using the `rest.InClusterConfig()` and `kubernetes.NewForConfig()` functions. - They handle locating and authenticating to the apiserver. [example](https://git.k8s.io/client-go/examples/in-cluster/main.go) + They handle locating and authenticating to the apiserver. [example](https://git.k8s.io/client-go/examples/in-cluster-client-configuration/main.go) In each case, the credentials of the pod are used to communicate securely with the apiserver. diff --git a/docs/tasks/administer-cluster/apply-resource-quota-limit.md b/docs/tasks/administer-cluster/apply-resource-quota-limit.md deleted file mode 100644 index 1ddae96bb8..0000000000 --- a/docs/tasks/administer-cluster/apply-resource-quota-limit.md +++ /dev/null @@ -1,378 +0,0 @@ ---- -approvers: -- derekwaynecarr -- janetkuo -title: Apply Resource Quotas and Limits ---- - -{% capture overview %} - -This example demonstrates a typical setup to control resource usage in a namespace. - -It demonstrates using the following resources: [Namespace](/docs/admin/namespaces), [ResourceQuota](/docs/concepts/policy/resource-quotas/), and [LimitRange](/docs/tasks/configure-pod-container/limit-range/). - -{% endcapture %} - -{% capture prerequisites %} - -* {% include task-tutorial-prereqs.md %} - -{% endcapture %} - -{% capture steps %} -## Scenario - -The cluster-admin is operating a cluster on behalf of a user population and the cluster-admin -wants to control the amount of resources that can be consumed in a particular namespace to promote -fair sharing of the cluster and control cost. - -The cluster-admin has the following goals: - -* Limit the amount of compute resource for running pods -* Limit the number of persistent volume claims to control access to storage -* Limit the number of load balancers to control cost -* Prevent the use of node ports to preserve scarce resources -* Provide default compute resource requests to enable better scheduling decisions - -## 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 -$ kubectl create namespace quota-example -namespace "quota-example" created -$ kubectl get namespaces -NAME STATUS AGE -default Active 2m -kube-system Active 2m -quota-example Active 39s -``` - -## Apply an object-count quota to the namespace - -The cluster-admin wants to control the following resources: - -* persistent volume claims -* load balancers -* node ports - -Let's create a simple quota that controls object counts for those resource types in this namespace. - -```shell -$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/rq-object-counts.yaml --namespace=quota-example -resourcequota "object-counts" created -``` - -The quota system will observe that a quota has been created, and will calculate consumption -in the namespace in response. This should happen quickly. - -Let's describe the quota to see what is currently being consumed in this namespace: - -```shell -$ kubectl describe quota object-counts --namespace=quota-example -Name: object-counts -Namespace: quota-example -Resource Used Hard --------- ---- ---- -persistentvolumeclaims 0 2 -services.loadbalancers 0 2 -services.nodeports 0 0 -``` - -The quota system will now prevent users from creating more than the specified amount for each resource. - - -## Apply a compute-resource quota to the namespace - -To limit the amount of compute resource that can be consumed in this namespace, -let's create a quota that tracks compute resources. - -```shell -$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/rq-compute-resources.yaml --namespace=quota-example -resourcequota "compute-resources" created -``` - -Let's describe the quota to see what is currently being consumed in this namespace: - -```shell -$ kubectl describe quota compute-resources --namespace=quota-example -Name: compute-resources -Namespace: quota-example -Resource Used Hard --------- ---- ---- -limits.cpu 0 2 -limits.memory 0 2Gi -pods 0 4 -requests.cpu 0 1 -requests.memory 0 1Gi -``` - -The quota system will now prevent the namespace from having more than 4 non-terminal pods. In -addition, it will enforce that each container in a pod makes a `request` and defines a `limit` for -`cpu` and `memory`. - -## Applying default resource requests and limits - -Pod authors rarely specify resource requests and 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 deployment that runs nginx: - -```shell -$ kubectl run nginx --image=nginx --replicas=1 --namespace=quota-example -deployment "nginx" created -``` - -Now let's look at the pods that were created. - -```shell -$ kubectl get pods --namespace=quota-example -``` - -What happened? I have no pods! Let's describe the deployment to get a view of what is happening. - -```shell -$ kubectl describe deployment nginx --namespace=quota-example -Name: nginx -Namespace: quota-example -CreationTimestamp: Mon, 06 Jun 2016 16:11:37 -0400 -Labels: run=nginx -Selector: run=nginx -Replicas: 0 updated | 1 total | 0 available | 1 unavailable -StrategyType: RollingUpdate -MinReadySeconds: 0 -RollingUpdateStrategy: 1 max unavailable, 1 max surge -OldReplicaSets: -NewReplicaSet: nginx-3137573019 (0/1 replicas created) -... -``` - -A deployment created a corresponding replica set and attempted to size it to create a single pod. - -Let's look at the replica set to get more detail. - -```shell -$ kubectl describe rs nginx-3137573019 --namespace=quota-example -Name: nginx-3137573019 -Namespace: quota-example -Image(s): nginx -Selector: pod-template-hash=3137573019,run=nginx -Labels: pod-template-hash=3137573019 - run=nginx -Replicas: 0 current / 1 desired -Pods Status: 0 Running / 0 Waiting / 0 Succeeded / 0 Failed -No volumes. -Events: - FirstSeen LastSeen Count From SubobjectPath Type Reason Message - --------- -------- ----- ---- ------------- -------- ------ ------- - 4m 7s 11 {replicaset-controller } Warning FailedCreate Error creating: pods "nginx-3137573019-" is forbidden: Failed quota: compute-resources: must specify limits.cpu,limits.memory,requests.cpu,requests.memory -``` - -The Kubernetes API server is rejecting the replica set requests to create a pod because our pods -do not specify `requests` or `limits` for `cpu` and `memory`. - -So let's set some default values for the amount of `cpu` and `memory` a pod can consume: - -```shell -$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/rq-limits.yaml --namespace=quota-example -limitrange "limits" created -$ kubectl describe limits limits --namespace=quota-example -Name: limits -Namespace: quota-example -Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio ----- -------- --- --- --------------- ------------- ----------------------- -Container memory - - 256Mi 512Mi - -Container cpu - - 100m 200m - -``` - -If the Kubernetes API server observes a request to create a pod in this namespace, and the containers -in that pod do not make any compute resource requests, a default request and default limit will be applied -as part of admission control. - -In this example, each pod created will have compute resources equivalent to the following: - -```shell -$ kubectl run nginx \ - --image=nginx \ - --replicas=1 \ - --requests=cpu=100m,memory=256Mi \ - --limits=cpu=200m,memory=512Mi \ - --namespace=quota-example -``` - -Now that we have applied default compute resources for our namespace, our replica set should be able to create -its pods. - -```shell -$ kubectl get pods --namespace=quota-example -NAME READY STATUS RESTARTS AGE -nginx-3137573019-fvrig 1/1 Running 0 6m -``` - -And if we print out our quota usage in the namespace: - -```shell -$ kubectl describe quota --namespace=quota-example -Name: compute-resources -Namespace: quota-example -Resource Used Hard --------- ---- ---- -limits.cpu 200m 2 -limits.memory 512Mi 2Gi -pods 1 4 -requests.cpu 100m 1 -requests.memory 256Mi 1Gi - - -Name: object-counts -Namespace: quota-example -Resource Used Hard --------- ---- ---- -persistentvolumeclaims 0 2 -services.loadbalancers 0 2 -services.nodeports 0 0 -``` - -As you can see, the pod that was created is consuming explicit amounts of compute resources, and the usage is being -tracked by Kubernetes properly. - -## Advanced quota scopes - -Let's imagine you did not want to specify default compute resource consumption in your namespace. - -Instead, you want to let users run a specific number of `BestEffort` pods in their namespace to take -advantage of slack compute resources, and then require that users make an explicit resource request for -pods that require a higher quality of service. - -Let's create a new namespace with two quotas to demonstrate this behavior: - -```shell -$ kubectl create namespace quota-scopes -namespace "quota-scopes" created -$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/rq-best-effort.yaml --namespace=quota-scopes -resourcequota "best-effort" created -$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/rq-not-best-effort.yaml --namespace=quota-scopes -resourcequota "not-best-effort" created -$ kubectl describe quota --namespace=quota-scopes -Name: best-effort -Namespace: quota-scopes -Scopes: BestEffort - * Matches all pods that have best effort quality of service. -Resource Used Hard --------- ---- ---- -pods 0 10 - - -Name: not-best-effort -Namespace: quota-scopes -Scopes: NotBestEffort - * Matches all pods that do not have best effort quality of service. -Resource Used Hard --------- ---- ---- -limits.cpu 0 2 -limits.memory 0 2Gi -pods 0 4 -requests.cpu 0 1 -requests.memory 0 1Gi -``` - -In this scenario, a pod that makes no compute resource requests will be tracked by the `best-effort` quota. - -A pod that does make compute resource requests will be tracked by the `not-best-effort` quota. - -Let's demonstrate this by creating two deployments: - -```shell -$ kubectl run best-effort-nginx --image=nginx --replicas=8 --namespace=quota-scopes -deployment "best-effort-nginx" created -$ kubectl run not-best-effort-nginx \ - --image=nginx \ - --replicas=2 \ - --requests=cpu=100m,memory=256Mi \ - --limits=cpu=200m,memory=512Mi \ - --namespace=quota-scopes -deployment "not-best-effort-nginx" created -``` - -Even though no default limits were specified, the `best-effort-nginx` deployment will create -all 8 pods. This is because it is tracked by the `best-effort` quota, and the `not-best-effort` -quota will just ignore it. The `not-best-effort` quota will track the `not-best-effort-nginx` -deployment since it creates pods with `Burstable` quality of service. - -Let's list the pods in the namespace: - -```shell -$ kubectl get pods --namespace=quota-scopes -NAME READY STATUS RESTARTS AGE -best-effort-nginx-3488455095-2qb41 1/1 Running 0 51s -best-effort-nginx-3488455095-3go7n 1/1 Running 0 51s -best-effort-nginx-3488455095-9o2xg 1/1 Running 0 51s -best-effort-nginx-3488455095-eyg40 1/1 Running 0 51s -best-effort-nginx-3488455095-gcs3v 1/1 Running 0 51s -best-effort-nginx-3488455095-rq8p1 1/1 Running 0 51s -best-effort-nginx-3488455095-udhhd 1/1 Running 0 51s -best-effort-nginx-3488455095-zmk12 1/1 Running 0 51s -not-best-effort-nginx-2204666826-7sl61 1/1 Running 0 23s -not-best-effort-nginx-2204666826-ke746 1/1 Running 0 23s -``` - -As you can see, all 10 pods have been allowed to be created. - -Let's describe current quota usage in the namespace: - -```shell -$ kubectl describe quota --namespace=quota-scopes -Name: best-effort -Namespace: quota-scopes -Scopes: BestEffort - * Matches all pods that have best effort quality of service. -Resource Used Hard --------- ---- ---- -pods 8 10 - - -Name: not-best-effort -Namespace: quota-scopes -Scopes: NotBestEffort - * Matches all pods that do not have best effort quality of service. -Resource Used Hard --------- ---- ---- -limits.cpu 400m 2 -limits.memory 1Gi 2Gi -pods 2 4 -requests.cpu 200m 1 -requests.memory 512Mi 1Gi -``` - -As you can see, the `best-effort` quota has tracked the usage for the 8 pods we created in -the `best-effort-nginx` deployment, and the `not-best-effort` quota has tracked the usage for -the 2 pods we created in the `not-best-effort-nginx` quota. - -Scopes provide a mechanism to subdivide the set of resources that are tracked by -any quota document to allow greater flexibility in how operators deploy and track resource -consumption. - -In addition to `BestEffort` and `NotBestEffort` scopes, there are scopes to restrict -long-running versus time-bound pods. The `Terminating` scope will match any pod -where `spec.activeDeadlineSeconds is not nil`. The `NotTerminating` scope will match any pod -where `spec.activeDeadlineSeconds is nil`. These scopes allow you to quota pods based on their -anticipated permanence on a node in your cluster. - -{% endcapture %} - -{% capture discussion %} -## 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. - -Quota can be apportioned based on quality of service and anticipated permanence on a node in your cluster. - -{% endcapture %} - -{% include templates/task.md %} diff --git a/docs/tasks/administer-cluster/cpu-constraint-namespace.md b/docs/tasks/administer-cluster/cpu-constraint-namespace.md new file mode 100644 index 0000000000..e1d5e04080 --- /dev/null +++ b/docs/tasks/administer-cluster/cpu-constraint-namespace.md @@ -0,0 +1,270 @@ +--- +title: Configure Minimum and Maximum CPU Constraints for a Namespace +--- + + +{% capture overview %} + +This page shows how to set minimum and maximum values for the CPU resources used by Containers +and Pods in a namespace. You specify minimum and maximum CPU values in a +[LimitRange](/docs/api-reference/v1.6/#limitrange-v1-core) +object. If a Pod does not meet the constraints imposed by the LimitRange, it cannot be created +in the namespace. + +{% endcapture %} + + +{% capture prerequisites %} + +{% include task-tutorial-prereqs.md %} + +Each node in your cluster must have at least 1 CPU. + +{% endcapture %} + + +{% capture steps %} + +## Create a namespace + +Create a namespace so that the resources you create in this exercise are +isolated from the rest of your cluster. + +```shell +kubectl create namespace constraints-cpu-example +``` + +## Create a LimitRange and a Pod + +Here's the configuration file for a LimitRange: + +{% include code.html language="yaml" file="cpu-constraints.yaml" ghlink="/docs/tasks/administer-cluster/cpu-constraints.yaml" %} + +Create the LimitRange: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/cpu-constraints.yaml --namespace=constraints-cpu-example +``` + +View detailed information about the LimitRange: + +```shell +kubectl get limitrange cpu-min-max-demo-lr --output=yaml --namespace=constraints-cpu-example +``` + +The output shows the minimum and maximum CPU constraints as expected. But +notice that even though you didn't specify default values in the configuration +file for the LimitRange, they were created automatically. + +```yaml +limits: +- default: + cpu: 800m + defaultRequest: + cpu: 800m + max: + cpu: 800m + min: + cpu: 200m + type: Container +``` + +Now whenever a Container is created in the constraints-cpu-example namespace, Kubernetes +performs these steps: + +* If the Container does not specify its own CPU request and limit, assign the default +CPU request and limit to the Container. + +* Verify that the Container specifies a CPU request that is greater than or equal to 200 millicpu. + +* Verify that the Container specifies a memory limit that is less than or equal to 800 millicpu. + +Here's the configuration file for a Pod that has one Container. The Container manifest +specifies a CPU request of 500 millicpu and a CPU limit of 800 millicpu. These satisfy the +minimum and maximum CPU constraints imposed by the LimitRange. + +{% include code.html language="yaml" file="cpu-constraints-pod.yaml" ghlink="/docs/tasks/administer-cluster/cpu-constraints-pod.yaml" %} + +Create the Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/cpu-constraints-pod.yaml --namespace=constraints-cpu-example +``` + +Verify that the Pod's Container is running: + +```shell +kubectl get pod constraints-cpu-demo --namespace=constraints-cpu-example +``` + +View detailed information about the Pod: + +```shell +kubectl get pod constraints-cpu-demo --output=yaml --namespace=constraints-cpu-example +``` + +The output shows that the Container has a CPU request of 500 millicpu and CPU limit +of 800 millicpu. These satisfy the constraints imposed by the LimitRange. + +```yaml +resources: + limits: + cpu: 800m + requests: + cpu: 500m +``` + +## Delete the Pod + +```shell +kubectl delete pod constraints-cpu-demo --namespace=constraints-cpu-example +``` + +## Attempt to create a Pod that exceeds the maximum CPU constraint + +Here's the configuration file for a Pod that has one Container. The Container specifies a +CPU request of 500 millicpu and a cpu limit of 1.5 cpu. + +{% include code.html language="yaml" file="cpu-constraints-pod-2.yaml" ghlink="/docs/tasks/administer-cluster/cpu-constraints-pod-2.yaml" %} + +Attempt to create the Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/cpu-constraints-pod-2.yaml --namespace=constraints-cpu-example +``` + +The output shows that the Pod does not get created, because the Container specifies a CPU limit that is +too large: + +``` +Error from server (Forbidden): error when creating "docs/tasks/administer-cluster/cpu-constraints-pod-2.yaml": +pods "constraints-cpu-demo-2" is forbidden: maximum cpu usage per Container is 800m, but limit is 1500m. +``` + +## Attempt to create a Pod that does not meet the minimum CPU request + +Here's the configuration file for a Pod that has one Container. The Container specifies a +CPU request of 100 millicpu and a CPU limit of 800 millicpu. + +{% include code.html language="yaml" file="cpu-constraints-pod-3.yaml" ghlink="/docs/tasks/administer-cluster/cpu-constraints-pod-3.yaml" %} + +Attempt to create the Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/cpu-constraints-pod-3.yaml --namespace=constraints-cpu-example +``` + +The output shows that the Pod does not get created, because the Container specifies a CPU +request that is too small: + +``` +Error from server (Forbidden): error when creating "docs/tasks/administer-cluster/cpu-constraints-pod-3.yaml": +pods "constraints-cpu-demo-4" is forbidden: minimum cpu usage per Container is 200m, but request is 100m. +``` + +## Create a Pod that does not specify any CPU request or limit + +Here's the configuration file for a Pod that has one Container. The Container does not +specify a CPU request, and it does not specify a CPU limit. + +{% include code.html language="yaml" file="cpu-constraints-pod-4.yaml" ghlink="/docs/tasks/administer-cluster/cpu-constraints-pod-4.yaml" %} + +Create the Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/cpu-constraints-pod-4.yaml --namespace=constraints-cpu-example +``` + +View detailed information about the Pod: + +``` +kubectl get pod constraints-cpu-demo-4 --namespace=constraints-cpu-example --output=yaml +``` + +The output shows that the Pod's Container has a CPU request of 800 millicpu and a CPU limit of 800 millicpu. +How did the Container get those values? + +```yaml +resources: + limits: + cpu: 800m + requests: + cpu: 800m +``` + +Because your Container did not specify its own CPU request and limit, it was given the +[default CPU request and limit](/docs/tasks/administer-cluster/default-cpu-request-limit/) +from the LimitRange. +* [Configure Memory and CPU Quotas for a Namespace](docs/tasks/administer-cluster/quota-memory-cpu-namespace) +At this point, your Container might be running or it might not be running. Recall that a prerequisite +for this task is that your Nodes have at least 1 CPU. If each of your Nodes has only +1 CPU, then there might not be enough allocatable CPU on any Node to accommodate a request +of 800 millicpu. If you happen to be using Nodes with 2 CPU, then you probably have +enough CPU to accommodate the 800 millicpu request. + +Delete your Pod: + +``` +kubectl delete pod constraints-cpu-demo-4 --namespace=constraints-cpu-example +``` + +## Enforcement of minimum and maximum CPU constraints + +The maximum and minimum CPU constraints imposed on a namespace by a LimitRange are enforced only +when a Pod is created or updated. If you change the LimitRange, it does not affect +Pods that were created previously. + +## Motivation for minimum and maximum CPU constraints + +As a cluster administrator, you might want to impose restrictions on the CPU resources that Pods can use. +For example: + +* Each Node in a cluster has 2 cpu. You do not want to accept any Pod that requests +more than 2 cpu, because no Node in the cluster can support the request. + +* A cluster is shared by your production and development departments. +You want to allow production workloads to consume up to 3 cpu, but you want development workloads to be limited +to 1 cpu. You create separate namespaces for production and development, and you apply CPU constraints to +each namespace. + +## Clean up + +Delete your namespace: + +```shell +kubectl delete namespace constraints-cpu-example +``` + +{% endcapture %} + +{% capture whatsnext %} + +### For cluster administrators + +* [Configure Default Memory Requests and Limits for a Namespace](docs/tasks/administer-cluster/default-memory-request-limit/) + +* [Configure Default CPU Requests and Limits for a Namespace](docs/tasks/administer-cluster/default-cpu-request-limit/) + +* [Configure Minimum and Maximum Memory Constraints for a Namespace](/docs/tasks/administer-cluster/memory-constraint-namespace/) + +* [Configure Memory and CPU Quotas for a Namespace](/docs/tasks/administer-cluster/quota-memory-cpu-namespace/) + +* [Configure a Pod Quota for a Namespace](/docs/tasks/administer-cluster/quota-pod-namespace/) + +* [Configure Quotas for API Objects](/docs/tasks/administer-cluster/quota-api-object/) + +### For app developers + +* [Assign Memory Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-memory-resource/) + +* [Assign CPU Resources to Containers and Pods](docs/tasks/configure-pod-container/assign-cpu-resource/) + +* [Configure Quality of Service for Pods](/docs/tasks/configure-pod-container/quality-service-pod/) + + +{% endcapture %} + + +{% include templates/task.md %} + + diff --git a/docs/tasks/administer-cluster/cpu-constraints-pod-2.yaml b/docs/tasks/administer-cluster/cpu-constraints-pod-2.yaml new file mode 100644 index 0000000000..b5c7348f26 --- /dev/null +++ b/docs/tasks/administer-cluster/cpu-constraints-pod-2.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: constraints-cpu-demo-2 +spec: + containers: + - name: constraints-cpu-demo-2-ctr + image: nginx + resources: + limits: + cpu: "1.5" + requests: + cpu: "500m" diff --git a/docs/tasks/administer-cluster/cpu-constraints-pod-3.yaml b/docs/tasks/administer-cluster/cpu-constraints-pod-3.yaml new file mode 100644 index 0000000000..896d98ec2f --- /dev/null +++ b/docs/tasks/administer-cluster/cpu-constraints-pod-3.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: constraints-cpu-demo-4 +spec: + containers: + - name: constraints-cpu-demo-4-ctr + image: nginx + resources: + limits: + cpu: "800m" + requests: + cpu: "100m" diff --git a/docs/tasks/administer-cluster/cpu-constraints-pod-4.yaml b/docs/tasks/administer-cluster/cpu-constraints-pod-4.yaml new file mode 100644 index 0000000000..3c102158db --- /dev/null +++ b/docs/tasks/administer-cluster/cpu-constraints-pod-4.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Pod +metadata: + name: constraints-cpu-demo-4 +spec: + containers: + - name: constraints-cpu-demo-4-ctr + image: vish/stress diff --git a/docs/tasks/administer-cluster/cpu-constraints-pod.yaml b/docs/tasks/administer-cluster/cpu-constraints-pod.yaml new file mode 100644 index 0000000000..7db23f26c8 --- /dev/null +++ b/docs/tasks/administer-cluster/cpu-constraints-pod.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: constraints-cpu-demo +spec: + containers: + - name: constraints-cpu-demo-ctr + image: nginx + resources: + limits: + cpu: "800m" + requests: + cpu: "500m" diff --git a/docs/tasks/administer-cluster/cpu-constraints.yaml b/docs/tasks/administer-cluster/cpu-constraints.yaml new file mode 100644 index 0000000000..6fc4239027 --- /dev/null +++ b/docs/tasks/administer-cluster/cpu-constraints.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: LimitRange +metadata: + name: cpu-min-max-demo-lr +spec: + limits: + - max: + cpu: "800m" + min: + cpu: "200m" + type: Container diff --git a/docs/tasks/administer-cluster/cpu-default-namespace.md b/docs/tasks/administer-cluster/cpu-default-namespace.md new file mode 100644 index 0000000000..562a5d65f3 --- /dev/null +++ b/docs/tasks/administer-cluster/cpu-default-namespace.md @@ -0,0 +1,178 @@ +--- +title: Configure Default CPU Requests and Limits for a Namespace +--- + +{% capture overview %} + +This page shows how to configure default CPU requests and limits for a namespace. +A Kubernetes cluster can be divided into namespaces. If a Container is created in a namespace +that has a default CPU limit, and the Container does not specify its own CPU limit, then +the Container is assigned the default CPU limit. Kubernetes assigns a default CPU request +under certain conditions that are explained later in this topic. + +{% endcapture %} + +{% capture prerequisites %} + +{% include task-tutorial-prereqs.md %} +{% endcapture %} + +{% capture steps %} + +## Create a namespace + +Create a namespace so that the resources you create in this exercise are +isolated from the rest of your cluster. + +```shell +kubectl create namespace default-cpu-example +``` + +## Create a LimitRange and a Pod + +Here's the configuration file for a LimitRange object. The configuration specifies +a default CPU request and a default CPU limit. + +{% include code.html language="yaml" file="cpu-defaults.yaml" ghlink="/docs/tasks/administer-cluster/cpu-defaults.yaml" %} + +Create the LimitRange in the default-cpu-example namespace: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/cpu-defaults.yaml --namespace=default-cpu-example +``` + +Now if a Container is created in the default-cpu-example namespace, and the +Container does not specify its own values for CPU request and CPU limit, +the Container is given a default CPU request of 0.5 and a default +CPU limit of 1. + +Here's the configuration file for a Pod that has one Container. The Container +does not specify a CPU request and limit. + +{% include code.html language="yaml" file="cpu-defaults-pod.yaml" ghlink="/docs/tasks/administer-cluster/cpu-defaults-pod.yaml" %} + +Create the Pod. + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/cpu-defaults-pod.yaml --namespace=default-cpu-example +``` + +View the Pod's specification: + +```shell +kubectl get pod default-cpu-demo --output=yaml --namespace=default-cpu-example +``` + +The output shows that the Pod's Container has a CPU request of 500 millicpus and +a CPU limit of 1 cpu. These are the default values specified by the LimitRange. + +```shel +containers: +- image: nginx + imagePullPolicy: Always + name: default-cpu-demo-ctr + resources: + limits: + cpu: "1" + requests: + cpu: 500m +``` + +## What if you specify a Container's limit, but not its request? + +Here's the configuration file for a Pod that has one Container. The Container +specifies a CPU limit, but not a request: + +{% include code.html language="yaml" file="cpu-defaults-pod-2.yaml" ghlink="/docs/tasks/administer-cluster/cpu-defaults-pod-2.yaml" %} + +Create the Pod: + + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/cpu-defaults-pod-2.yaml --namespace=default-cpu-example +``` + +View the Pod specification: + +``` +kubectl get pod cpu-limit-no-request --output=yaml --namespace=default-cpu-example +``` + +The output shows that the Container's CPU request is set to match its CPU limit. +Notice that the Container was not assigned the default CPU request value of 0.5 cpu. + +``` +resources: + limits: + cpu: "1" + requests: + cpu: "1" +``` + +## What if you specify a Container's request, but not its limit? + +Here's the configuration file for a Pod that has one Container. The Container +specifies a CPU request, but not a limit: + +{% include code.html language="yaml" file="cpu-defaults-pod-3.yaml" ghlink="/docs/tasks/administer-cluster/cpu-defaults-pod-3.yaml" %} + +Create the Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/cpu-defaults-pod-3.yaml --namespace=default-cpu-example +``` + +The output shows that the Container's CPU request is set to the value specified in the +Container's configuration file. The Container's CPU limit is set to 1 cpu, wh70cb02113b7c7cc1604d1951ef82e1c82850eef2ich is the +default CPU limit for the namespace. + +``` +resources: + limits: + cpu: "1" + requests: + cpu: 750m +``` + +## Motivation for default CPU limits and requests + +If your namespace has a +[resource quota](), +it is helpful to have a default value in place for CPU limit. +Here are two of the restrictions that a resource quota imposes on a namespace: + +* Every Container that runs in the namespace must have its own CPU limit. +* The total amount of CPU used by all Containers in the namespace must not exceed a specified limit. + +If a Container does not specify its own CPU limit, it is given the default limit, and then +it can be allowed to run in a namespace that is restricted by a quota. + +{% endcapture %} + +{% capture whatsnext %} + +### For cluster administrators + +* [Configure Default Memory Requests and Limits for a Namespace](docs/tasks/administer-cluster/default-memory-request-limit/) + +* [Configure Minimum and Maximum Memory Constraints for a Namespace](/docs/tasks/administer-cluster/memory-constraint-namespace/) + +* [Configure Minimum and Maximum CPU Constraints for a Namespace](/docs/tasks/administer-cluster/cpu-constraint-namespace/) + +* [Configure Memory and CPU Quotas for a Namespace](/docs/tasks/administer-cluster/quota-memory-cpu-namespace/) + +* [Configure a Pod Quota for a Namespace](/docs/tasks/administer-cluster/quota-pod-namespace/) + +* [Configure Quotas for API Objects](/docs/tasks/administer-cluster/quota-api-object/) + +### For app developers + +* [Assign Memory Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-memory-resource/) + +* [Assign CPU Resources to Containers and Pods](docs/tasks/configure-pod-container/assign-cpu-resource/) + +* [Configure Quality of Service for Pods](/docs/tasks/configure-pod-container/quality-service-pod/) + +{% endcapture %} + +{% include templates/task.md %} diff --git a/docs/tasks/administer-cluster/cpu-defaults-pod-2.yaml b/docs/tasks/administer-cluster/cpu-defaults-pod-2.yaml new file mode 100644 index 0000000000..9ca216dee1 --- /dev/null +++ b/docs/tasks/administer-cluster/cpu-defaults-pod-2.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: default-cpu-demo-2 +spec: + containers: + - name: default-cpu-demo-2-ctr + image: nginx + resources: + limits: + cpu: "1" diff --git a/docs/tasks/administer-cluster/cpu-defaults-pod-3.yaml b/docs/tasks/administer-cluster/cpu-defaults-pod-3.yaml new file mode 100644 index 0000000000..214cdee34b --- /dev/null +++ b/docs/tasks/administer-cluster/cpu-defaults-pod-3.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: default-cpu-demo-3 +spec: + containers: + - name: default-cpu-demo-3-ctr + image: nginx + resources: + requests: + cpu: "0.75" diff --git a/docs/tasks/administer-cluster/cpu-defaults-pod.yaml b/docs/tasks/administer-cluster/cpu-defaults-pod.yaml new file mode 100644 index 0000000000..56b06d9a69 --- /dev/null +++ b/docs/tasks/administer-cluster/cpu-defaults-pod.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Pod +metadata: + name: default-cpu-demo +spec: + containers: + - name: default-cpu-demo-ctr + image: nginx diff --git a/docs/tasks/administer-cluster/cpu-defaults.yaml b/docs/tasks/administer-cluster/cpu-defaults.yaml new file mode 100644 index 0000000000..b53d297181 --- /dev/null +++ b/docs/tasks/administer-cluster/cpu-defaults.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: LimitRange +metadata: + name: cpu-limit-range +spec: + limits: + - default: + cpu: 1 + defaultRequest: + cpu: 0.5 + type: Container diff --git a/docs/tasks/administer-cluster/cpu-memory-limit.md b/docs/tasks/administer-cluster/cpu-memory-limit.md deleted file mode 100644 index 02132c818a..0000000000 --- a/docs/tasks/administer-cluster/cpu-memory-limit.md +++ /dev/null @@ -1,229 +0,0 @@ ---- -approvers: -- derekwaynecarr -- janetkuo -title: Set Pod CPU and Memory Limits ---- - -{% capture overview %} - -By default, pods 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 as is on the node that executes the pod. - -This example demonstrates how limits can be applied to a Kubernetes [namespace](/docs/tasks/administer-cluster/namespaces-walkthrough/) to control -min/max resource limits per pod. In addition, this example demonstrates how you can -apply default resource limits to pods in the absence of an end-user specified value. - -{% endcapture %} - -{% capture prerequisites %} - -* {% include task-tutorial-prereqs.md %} - -{% endcapture %} - -{% capture steps %} -## Create a namespace - -This example will work in a custom namespace to demonstrate the concepts involved. - -Let's create a new namespace called limit-example: - -```shell -$ kubectl create namespace limit-example -namespace "limit-example" created -``` - -Note that `kubectl` commands will print the type and name of the resource created or mutated, which can then be used in subsequent commands: - -```shell -$ kubectl get namespaces -NAME STATUS AGE -default Active 51s -limit-example Active 45s -``` - -## Apply a limit to the namespace - -Let's create a simple limit in our namespace. - -```shell -$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/limits.yaml --namespace=limit-example -limitrange "mylimits" created -``` - -Let's describe the limits that were imposed in the namespace. - -```shell -$ kubectl describe limits mylimits --namespace=limit-example -Name: mylimits -Namespace: limit-example -Type Resource Min Max Default Request Default Limit Max Limit/Request Ratio ----- -------- --- --- --------------- ------------- ----------------------- -Pod cpu 200m 2 - - - -Pod memory 6Mi 1Gi - - - -Container cpu 100m 2 200m 300m - -Container memory 3Mi 1Gi 100Mi 200Mi - -``` - -In this scenario, the following limits were specified: - -1. If a max constraint is specified for a resource (2 CPU and 1Gi memory in this case), then a limit -must be specified for that resource across all containers. Failure to specify a limit will result in -a validation error when attempting to create the pod. Note that a default value of limit is set by -*default* in file `limits.yaml` (300m CPU and 200Mi memory). -2. If a min constraint is specified for a resource (100m CPU and 3Mi memory in this case), then a -request must be specified for that resource across all containers. Failure to specify a request will -result in a validation error when attempting to create the pod. Note that a default value of request is -set by *defaultRequest* in file `limits.yaml` (200m CPU and 100Mi memory). -3. For any pod, the sum of all containers memory requests must be >= 6Mi and the sum of all containers -memory limits must be <= 1Gi; the sum of all containers CPU requests must be >= 200m and the sum of all -containers CPU limits must be <= 2. - -## Enforcing limits at point of creation - -The limits enumerated in a namespace are only enforced when a pod is created or updated in -the cluster. If you change the limits to a different value range, it does not affect pods that -were previously created in a namespace. - -If a resource (CPU or memory) is being restricted by a limit, the user will get an error at time -of creation explaining why. - -Let's first spin up a [Deployment](/docs/concepts/workloads/controllers/deployment/) that creates a single container Pod to demonstrate -how default values are applied to each pod. - -```shell -$ kubectl run nginx --image=nginx --replicas=1 --namespace=limit-example -deployment "nginx" created -``` - -Note that `kubectl run` creates a Deployment named "nginx" on Kubernetes cluster >= v1.2. If you are running older versions, it creates replication controllers instead. -If you want to obtain the old behavior, use `--generator=run/v1` to create replication controllers. See [`kubectl run`](/docs/user-guide/kubectl/{{page.version}}/#run) for more details. -The Deployment manages 1 replica of single container Pod. Let's take a look at the Pod it manages. First, find the name of the Pod: - -```shell -$ kubectl get pods --namespace=limit-example -NAME READY STATUS RESTARTS AGE -nginx-2040093540-s8vzu 1/1 Running 0 11s -``` - -Let's print this Pod with yaml output format (using `-o yaml` flag), and then `grep` the `resources` field. Note that your pod name will be different. - -```shell -$ kubectl get pods nginx-2040093540-s8vzu --namespace=limit-example -o yaml | grep resources -C 8 - resourceVersion: "57" - selfLink: /api/v1/namespaces/limit-example/pods/nginx-2040093540-ivimu - uid: 67b20741-f53b-11e5-b066-64510658e388 -spec: - containers: - - image: nginx - imagePullPolicy: Always - name: nginx - resources: - limits: - cpu: 300m - memory: 200Mi - requests: - cpu: 200m - 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 -$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/invalid-pod.yaml --namespace=limit-example -Error from server: error when creating "http://k8s.io/docs/tasks/configure-pod-container/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 -$ kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/valid-pod.yaml --namespace=limit-example -pod "valid-pod" created -``` - -Now look at the Pod's resources field: - -```shell -$ kubectl get pods valid-pod --namespace=limit-example -o yaml | grep -C 6 resources - uid: 3b1bfd7a-f53c-11e5-b066-64510658e388 -spec: - containers: - - image: gcr.io/google_containers/serve_hostname - imagePullPolicy: Always - name: kubernetes-serve-hostname - resources: - limits: - cpu: "1" - memory: 512Mi - 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 enforced in the default Kubernetes setup on the physical node -that runs the container unless the administrator deploys the kubelet with the following flag: - -```shell -$ kubelet --help -Usage of kubelet -.... - --cpu-cfs-quota[=true]: Enable CPU CFS quota enforcement for containers that specify CPU limits -$ kubelet --cpu-cfs-quota=false ... -``` - -## Cleanup - -To remove the resources used by this example, you can just delete the limit-example namespace. - -```shell -$ kubectl delete namespace limit-example -namespace "limit-example" deleted -$ kubectl get namespaces -NAME STATUS AGE -default Active 12m -``` -{% endcapture %} - -{% capture discussion %} -## Motivation for setting resource limits - -Users may want to impose restrictions on the amount of resources a single pod in the system may consume -for a variety of reasons. - -For example: - -1. Each node in the cluster has 2GB of memory. The cluster operator does not want to accept pods -that require more than 2GB of memory since no node in the cluster can support the requirement. To prevent a -pod from being permanently unscheduled to a node, the operator instead chooses to reject pods that exceed 2GB -of memory as part of admission control. -2. A cluster is shared by two communities in an organization that runs production and development workloads -respectively. Production workloads may consume up to 8GB of memory, but development workloads may consume up -to 512MB of memory. The cluster operator creates a separate namespace for each workload, and applies limits to -each namespace. -3. Users may create a pod which consumes resources just below the capacity of a machine. The left over space -may be too small to be useful, but big enough for the waste to be costly over the entire cluster. As a result, -the cluster operator may want to set limits that a pod must consume no more than 20% of the memory and CPU of -their average node size in order to provide for more uniform scheduling and limit waste. - -## 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. -{% endcapture %} - -{% capture whatsnext %} -* See [LimitRange design doc](https://git.k8s.io/community/contributors/design-proposals/admission_control_limit_range.md) for more information. -* See [Resources](/docs/concepts/configuration/manage-compute-resources-container/) for a detailed description of the Kubernetes resource model. -{% endcapture %} - -{% include templates/task.md %} diff --git a/docs/tasks/administer-cluster/encrypt-data.md b/docs/tasks/administer-cluster/encrypt-data.md index e6004c1af0..dc0889295a 100644 --- a/docs/tasks/administer-cluster/encrypt-data.md +++ b/docs/tasks/administer-cluster/encrypt-data.md @@ -109,7 +109,7 @@ To create a new secret perform the following steps: 2. Place that value in the secret field. 3. Set the `--experimental-encryption-provider-config` flag on the `kube-apiserver` to point to the location of the config file -4. restart your API server. +4. Restart your API server. **IMPORTANT:** Your config file contains keys that can decrypt content in etcd, so you must properly restrict permissions on your masters so only the user who runs the kube-apiserver can read it. diff --git a/docs/tasks/administer-cluster/memory-constraint-namespace.md b/docs/tasks/administer-cluster/memory-constraint-namespace.md new file mode 100644 index 0000000000..ac4afcdff5 --- /dev/null +++ b/docs/tasks/administer-cluster/memory-constraint-namespace.md @@ -0,0 +1,271 @@ +--- +title: Configure Minimum and Maximum Memory Constraints for a Namespace +--- + + +{% capture overview %} + +This page shows how to set minimum and maximum values for memory used by Containers +running in a namespace. You specify minimum and maximum memory values in a +[LimitRange](/docs/api-reference/v1.6/#limitrange-v1-core) +object. If a Pod does not meet the constraints imposed by the LimitRange, +it cannot be created in the namespace. + +{% endcapture %} + + +{% capture prerequisites %} + +{% include task-tutorial-prereqs.md %} + +Each node in your cluster must have at least 1 GiB of memory. + +{% endcapture %} + + +{% capture steps %} + +## Create a namespace + +Create a namespace so that the resources you create in this exercise are +isolated from the rest of your cluster. + +```shell +kubectl create namespace constraints-mem-example +``` + +## Create a LimitRange and a Pod + +Here's the configuration file for a LimitRange: + +{% include code.html language="yaml" file="memory-constraints.yaml" ghlink="/docs/tasks/administer-cluster/memory-constraints.yaml" %} + +Create the LimitRange: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/memory-constraints.yaml --namespace=constraints-mem-example +``` + +View detailed information about the LimitRange: + +```shell +kubectl get limitrange cpu-min-max-demo --namespace=constraints-mem-example --output=yaml +``` + +The output shows the minimum and maximum memory constraints as expected. But +notice that even though you didn't specify default values in the configuration +file for the LimitRange, they were created automatically. + +``` + limits: + - default: + memory: 1Gi + defaultRequest: + memory: 1Gi + max: + memory: 1Gi + min: + memory: 500Mi + type: Container +``` + +Now whenever a Container is created in the constraints-mem-example namespace, Kubernetes +performs these steps: + +* If the Container does not specify its own memory request and limit, assign the default +memory request and limit to the Container. + +* Verify that the Container has a memory request that is greater than or equal to 500 MiB. + +* Verify that the Container has a memory limit that is less than or equal to 1 GiB. + +Here's the configuration file for a Pod that has one Container. The Container manifest +specifies a memory request of 600 MiB and a memory limit of 800 MiB. These satisfy the +minimum and maximum memory constraints imposed by the LimitRange. + +{% include code.html language="yaml" file="memory-constraints-pod.yaml" ghlink="/docs/tasks/administer-cluster/memory-constraints-pod.yaml" %} + +Create the Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/memory-constraints-pod.yaml --namespace=constraints-mem-example +``` + +Verify that the Pod's Container is running: + +```shell +kubectl get pod constraints-mem-demo --namespace=constraints-mem-example +``` + +View detailed information about the Pod: + +```shell +kubectl get pod constraints-mem-demo --output=yaml --namespace=constraints-mem-example +``` + +The output shows that the Container has a memory request of 600 MiB and a memory limit +of 800 MiB. These satisfy the constraints imposed by the LimitRange. + +```yaml +resources: + limits: + memory: 800Mi + requests: + memory: 600Mi +``` + +Delete your Pod: + +```shell +kubectl delete pod constraints-mem-demo --namespace=constraints-mem-example +``` + +## Attempt to create a Pod that exceeds the maximum memory constraint + +Here's the configuration file for a Pod that has one Container. The Container specifies a +memory request of 700 MiB and a memory limit of 1.5 GiB. + +{% include code.html language="yaml" file="memory-constraints-pod-2.yaml" ghlink="/docs/tasks/administer-cluster/memory-constraints-pod-2.yaml" %} + +Attempt to create the Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/memory-constraints-pod-2.yaml --namespace=constraints-mem-example +``` + +The output shows that the Pod does not get created, because the Container specifies a memory limit that is +too large: + +``` +Error from server (Forbidden): error when creating "docs/tasks/administer-cluster/memory-constraints-pod-2.yaml": +pods "constraints-mem-demo-2" is forbidden: maximum memory usage per Container is 1Gi, but limit is 1536Mi. +``` + +## Attempt to create a Pod that does not meet the minimum memory request + +Here's the configuration file for a Pod that has one Container. The Container specifies a +memory request of 200 MiB and a memory limit of 800 MiB. + +{% include code.html language="yaml" file="memory-constraints-pod-3.yaml" ghlink="/docs/tasks/administer-cluster/memory-constraints-pod-3.yaml" %} + +Attempt to create the Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/memory-constraints-pod-3.yaml --namespace=constraints-mem-example +``` + +The output shows that the Pod does not get created, because the Container specifies a memory +request that is too small: + +``` +Error from server (Forbidden): error when creating "docs/tasks/administer-cluster/memory-constraints-pod-3.yaml": +pods "constraints-mem-demo-3" is forbidden: minimum memory usage per Container is 500Mi, but request is 100Mi. +``` + +## Create a Pod that does not specify any CPU request or limit + + + +Here's the configuration file for a Pod that has one Container. The Container does not +specify a memory request, and it does not specify a memory limit. + +{% include code.html language="yaml" file="memory-constraints-pod-4.yaml" ghlink="/docs/tasks/administer-cluster/memory-constraints-pod-4.yaml" %} + +Create the Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/memory-constraints-pod-4.yaml --namespace=constraints-mem-example +``` + +View detailed information about the Pod: + +``` +kubectl get pod constraints-mem-demo-4 --namespace=constraints-mem-example --output=yaml +``` + +The output shows that the Pod's Container has a memory request of 1 GiB and a memory limit of 1 GiB. +How did the Container get those values? + +``` +resources: + limits: + memory: 1Gi + requests: + memory: 1Gi +``` + +Because your Container did not specify its own memory request and limit, it was given the +[default memory request and limit](/docs/tasks/administer-cluster/default-memory-request-limit/) +from the LimitRange. + +At this point, your Container might be running or it might not be running. Recall that a prerequisite +for this task is that your Nodes have at least 1 GiB of memory. If each of your Nodes has only +1 GiB of memory, then there is not enough allocatable memory on any Node to accommodate a memory +request of 1 GiB. If you happen to be using Nodes with 2 GiB of memory, then you probably have +enough space to accommodate the 1 GiB request. + +Delete your Pod: + +``` +kubectl delete pod constraints-mem-demo-4 --namespace=constraints-mem-example +``` + +## Enforcement of minimum and maximum memory constraints + +The maximum and minimum memory constraints imposed on a namespace by a LimitRange are enforced only +when a Pod is created or updated. If you change the LimitRange, it does not affect +Pods that were created previously. + +## Motivation for minimum and maximum memory constraints + +As a cluster administrator, you might want to impose restrictions on the amount of memory that Pods can use. +For example: + +* Each Node in a cluster has 2 GB of memory. You do not want to accept any Pod that requests +more than 2 GB of memory, because no Node in the cluster can support the request. + +* A cluster is shared by your production and development departments. +You want to allow production workloads to consume up to 8 GB of memory, but +you want development workloads to be limited to 512 MB. You create separate namespaces +for production and development, and you apply memory constraints to each namespace. + +## Clean up + +Delete your namespace: + +```shell +kubectl delete namespace constraints-mem-example +``` + +{% endcapture %} + +{% capture whatsnext %} + +### For cluster administrators + +* [Configure Default Memory Requests and Limits for a Namespace](docs/tasks/administer-cluster/default-memory-request-limit/) + +* [Configure Default CPU Requests and Limits for a Namespace](docs/tasks/administer-cluster/default-cpu-request-limit/) + +* [Configure Minimum and Maximum CPU Constraints for a Namespace](/docs/tasks/administer-cluster/cpu-constraint-namespace/) + +* [Configure Memory and CPU Quotas for a Namespace](/docs/tasks/administer-cluster/quota-memory-cpu-namespace/) + +* [Configure a Pod Quota for a Namespace](/docs/tasks/administer-cluster/quota-pod-namespace/) + +* [Configure Quotas for API Objects](/docs/tasks/administer-cluster/quota-api-object/) + +### For app developers + +* [Assign Memory Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-memory-resource/) + +* [Assign CPU Resources to Containers and Pods](docs/tasks/configure-pod-container/assign-cpu-resource/) + +* [Configure Quality of Service for Pods](/docs/tasks/configure-pod-container/quality-service-pod/) + +{% endcapture %} + + +{% include templates/task.md %} + + diff --git a/docs/tasks/administer-cluster/memory-constraints-pod-2.yaml b/docs/tasks/administer-cluster/memory-constraints-pod-2.yaml new file mode 100644 index 0000000000..0b1ae569c4 --- /dev/null +++ b/docs/tasks/administer-cluster/memory-constraints-pod-2.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: constraints-mem-demo-2 +spec: + containers: + - name: constraints-mem-demo-2-ctr + image: nginx + resources: + limits: + memory: "1.5Gi" + requests: + memory: "800Mi" diff --git a/docs/tasks/administer-cluster/memory-constraints-pod-3.yaml b/docs/tasks/administer-cluster/memory-constraints-pod-3.yaml new file mode 100644 index 0000000000..f97cd4a8ac --- /dev/null +++ b/docs/tasks/administer-cluster/memory-constraints-pod-3.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: constraints-mem-demo-3 +spec: + containers: + - name: constraints-mem-demo-3-ctr + image: nginx + resources: + limits: + memory: "800Mi" + requests: + memory: "100Mi" diff --git a/docs/tasks/administer-cluster/memory-constraints-pod-4.yaml b/docs/tasks/administer-cluster/memory-constraints-pod-4.yaml new file mode 100644 index 0000000000..657530c41e --- /dev/null +++ b/docs/tasks/administer-cluster/memory-constraints-pod-4.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Pod +metadata: + name: constraints-mem-demo-4 +spec: + containers: + - name: constraints-mem-demo-4-ctr + image: nginx + diff --git a/docs/tasks/administer-cluster/memory-constraints-pod.yaml b/docs/tasks/administer-cluster/memory-constraints-pod.yaml new file mode 100644 index 0000000000..06954d10d6 --- /dev/null +++ b/docs/tasks/administer-cluster/memory-constraints-pod.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: constraints-mem-demo +spec: + containers: + - name: constraints-mem-demo-ctr + image: nginx + resources: + limits: + memory: "800Mi" + requests: + memory: "600Mi" diff --git a/docs/tasks/administer-cluster/memory-constraints.yaml b/docs/tasks/administer-cluster/memory-constraints.yaml new file mode 100644 index 0000000000..3a2924c032 --- /dev/null +++ b/docs/tasks/administer-cluster/memory-constraints.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: LimitRange +metadata: + name: mem-min-max-demo-lr +spec: + limits: + - max: + memory: 1Gi + min: + memory: 500Mi + type: Container diff --git a/docs/tasks/administer-cluster/memory-default-namespace.md b/docs/tasks/administer-cluster/memory-default-namespace.md new file mode 100644 index 0000000000..7c151d9896 --- /dev/null +++ b/docs/tasks/administer-cluster/memory-default-namespace.md @@ -0,0 +1,191 @@ +--- +title: Configure Default Memory Requests and Limits for a Namespace +--- + +{% capture overview %} + +This page shows how to configure default memory requests and limits for a namespace. +If a Container is created in a namespace that has a default memory limit, and the Container +does not specify its own memory limit, then the Container is assigned the default memory limit. +Kubernetes assigns a default memory request under certain conditions that are explained later in this topic. + +{% endcapture %} + +{% capture prerequisites %} + +{% include task-tutorial-prereqs.md %} + +Each node in your cluster must have at least 300 GiB of memory. + +{% endcapture %} + +{% capture steps %} + +## Create a namespace + +Create a namespace so that the resources you create in this exercise are +isolated from the rest of your cluster. + +```shell +kubectl create namespace default-mem-example +``` + +## Create a LimitRange and a Pod + +Here's the configuration file for a LimitRange object. The configuration specifies +a default memory request and a default memory limit. + +{% include code.html language="yaml" file="memory-defaults.yaml" ghlink="/docs/tasks/administer-cluster/memory-defaults.yaml" %} + +Create the LimitRange in the default-mem-example namespace: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/memory-defaults.yaml --namespace=default-mem-example +``` + +Now if a Container is created in the default-mem-example namespace, and the +Container does not specify its own values for memory request and memory limit, +the Container is given a default memory request of 256 MiB and a default +memory limit of 512 MiB. + +Here's the configuration file for a Pod that has one Container. The Container +does not specify a memory request and limit. + +{% include code.html language="yaml" file="memory-defaults-pod.yaml" ghlink="/docs/tasks/administer-cluster/memory-defaults-pod.yaml" %} + +Create the Pod. + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/memory-defaults-pod.yaml --namespace=default-mem-example +``` + +View detailed information about the Pod: + +```shell +kubectl get pod default-mem-demo --output=yaml --namespace=default-mem-example +``` + +The output shows that the Pod's Container has a memory request of 256 MiB and +a memory limit of 512 MiB. These are the default values specified by the LimitRange. + +```shel +containers: +- image: nginx + imagePullPolicy: Always + name: default-mem-demo-ctr + resources: + limits: + memory: 512Mi + requests: + memory: 256Mi +``` + +Delete your Pod: + +```shell +kubectl delete pod default-mem-demo --namespace=default-mem-example +``` + +## What if you specify a Container's limit, but not its request? + +Here's the configuration file for a Pod that has one Container. The Container +specifies a memory limit, but not a request: + +{% include code.html language="yaml" file="memory-defaults-pod-2.yaml" ghlink="/docs/tasks/administer-cluster/memory-defaults-pod-2.yaml" %} + +Create the Pod: + + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/memory-defaults-pod-2.yaml --namespace=default-mem-example +``` + +View detailed information about the Pod: + +```shell +kubectl get pod mem-limit-no-request --output=yaml --namespace=default-mem-example +``` + +The output shows that the Container's memory request is set to match its memory limit. +Notice that the Container was not assigned the default memory request value of 256Mi. + +``` +resources: + limits: + memory: 1Gi + requests: + memory: 1Gi +``` + +## What if you specify a Container's request, but not its limit? + +Here's the configuration file for a Pod that has one Container. The Container +specifies a memory request, but not a limit: + +{% include code.html language="yaml" file="memory-defaults-pod-3.yaml" ghlink="/docs/tasks/administer-cluster/memory-defaults-pod-3.yaml" %} + +Create the Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/memory-defaults-pod-3.yaml --namespace=default-mem-example +``` + +View the Pod's specification: + +```shell +kubectl get pod default-mem-request-no-limit --output=yaml --namespace=default-mem-example +``` + +The output shows that the Container's memory request is set to the value specified in the +Container's configuration file. The Container's memory limit is set to 512Mi, which is the +default memory limit for the namespace. + +``` +resources: + limits: + memory: 512Mi + requests: + memory: 128Mi +``` + +## Motivation for default memory limits and requests + +If your namespace has a resource quota, +it is helpful to have a default value in place for memory limit. +Here are two of the restrictions that a resource quota imposes on a namespace: + +* Every Container that runs in the namespace must have its own memory limit. +* The total amount of memory used by all Containers in the namespace must not exceed a specified limit. + +If a Container does not specify its own memory limit, it is given the default limit, and then +it can be allowed to run in a namespace that is restricted by a quota. + +{% endcapture %} + +{% capture whatsnext %} + +### For cluster administrators + +* [Configure Default CPU Requests and Limits for a Namespace](docs/tasks/administer-cluster/default-cpu-request-limit/) + +* [Configure Minimum and Maximum Memory Constraints for a Namespace](/docs/tasks/administer-cluster/memory-constraint-namespace/) + +* [Configure Minimum and Maximum CPU Constraints for a Namespace](/docs/tasks/administer-cluster/cpu-constraint-namespace/) + +* [Configure Memory and CPU Quotas for a Namespace](/docs/tasks/administer-cluster/quota-memory-cpu-namespace/) + +* [Configure a Pod Quota for a Namespace](/docs/tasks/administer-cluster/quota-pod-namespace/) + +* [Configure Quotas for API Objects](/docs/tasks/administer-cluster/quota-api-object/) + +### For app developers + +* [Assign Memory Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-memory-resource/) + +* [Assign CPU Resources to Containers and Pods](docs/tasks/configure-pod-container/assign-cpu-resource/) + +* [Configure Quality of Service for Pods](/docs/tasks/configure-pod-container/quality-service-pod/) + +{% endcapture %} + +{% include templates/task.md %} diff --git a/docs/tasks/administer-cluster/memory-defaults-pod-2.yaml b/docs/tasks/administer-cluster/memory-defaults-pod-2.yaml new file mode 100644 index 0000000000..1013293edd --- /dev/null +++ b/docs/tasks/administer-cluster/memory-defaults-pod-2.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: default-mem-demo-2 +spec: + containers: + - name: defalt-mem-demo-2-ctr + image: nginx + resources: + limits: + memory: "1Gi" diff --git a/docs/tasks/administer-cluster/memory-defaults-pod-3.yaml b/docs/tasks/administer-cluster/memory-defaults-pod-3.yaml new file mode 100644 index 0000000000..09ee8b39a9 --- /dev/null +++ b/docs/tasks/administer-cluster/memory-defaults-pod-3.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: default-mem-demo-3 +spec: + containers: + - name: default-mem-demo-3-ctr + image: nginx + resources: + requests: + memory: "128Mi" diff --git a/docs/tasks/administer-cluster/memory-defaults-pod.yaml b/docs/tasks/administer-cluster/memory-defaults-pod.yaml new file mode 100644 index 0000000000..ce7a50fb55 --- /dev/null +++ b/docs/tasks/administer-cluster/memory-defaults-pod.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Pod +metadata: + name: default-mem-demo +spec: + containers: + - name: default-mem-demo-ctr + image: nginx diff --git a/docs/tasks/configure-pod-container/rq-limits.yaml b/docs/tasks/administer-cluster/memory-defaults.yaml old mode 100755 new mode 100644 similarity index 76% rename from docs/tasks/configure-pod-container/rq-limits.yaml rename to docs/tasks/administer-cluster/memory-defaults.yaml index 84b50b4e2a..b98a5ae262 --- a/docs/tasks/configure-pod-container/rq-limits.yaml +++ b/docs/tasks/administer-cluster/memory-defaults.yaml @@ -1,13 +1,11 @@ apiVersion: v1 kind: LimitRange metadata: - name: limits + name: mem-limit-range spec: limits: - default: - cpu: 200m memory: 512Mi defaultRequest: - cpu: 100m memory: 256Mi type: Container diff --git a/docs/tasks/administer-cluster/opaque-integer-resource-node.md b/docs/tasks/administer-cluster/opaque-integer-resource-node.md new file mode 100644 index 0000000000..71925c1642 --- /dev/null +++ b/docs/tasks/administer-cluster/opaque-integer-resource-node.md @@ -0,0 +1,210 @@ +--- +title: Advertise Opaque Integer Resources for a Node +--- + + +{% capture overview %} + +This page shows how to specify opaque integer resources for a Node. +Opaque integer resources allow cluster administrators to advertise node-level +resources that would otherwise be unknown to Kubernetes. + +{% include feature-state-alpha.md %} + +{% endcapture %} + + +{% capture prerequisites %} + +{% include task-tutorial-prereqs.md %} + +{% endcapture %} + + +{% capture steps %} + +## Get the names of your Nodes + +```shell +kubectl get nodes +``` + +Choose one of your Nodes to use for this exercise. + +## Advertise a new opaque integer resource on one of your Nodes + +To advertise a new opaque integer resource on a Node, send an HTTP PATCH request to +the Kubernetes API server. For example, suppose one of your Nodes has four dongles +attached. Here's an example of a PATCH request that advertises four dongle resources +for your Node. + +```shell +PATCH /api/v1/nodes//status HTTP/1.1 +Accept: application/json +Content-Type: application/json-patch+json +Host: k8s-master:8080 + +[ + { + "op": "add", + "path": "/status/capacity/pod.alpha.kubernetes.io~1opaque-int-resource-dongle", + "value": "4" + } +] +``` + +Note that Kubernetes does not need to know what a dongle is or what a dongle is for. +The preceding PATCH request just tells Kubernetes that your Node has four things that +you call dongles. + +Start a proxy, so that you can easily send requests to the Kubernetes API server: + +``` +kubectl proxy +``` + +In another command window, send the HTTP PATCH request. +Replace `` with the name of your Node: + +```shell +curl --header "Content-Type: application/json-patch+json" \ +--request PATCH \ +--data '[{"op": "add", "path": "/status/capacity/pod.alpha.kubernetes.io~1opaque-int-resource-dongle", "value": "4"}]' \ +http://localhost:8001/api/v1/nodes//status +``` + +**Note**: In the preceding request, `~1` is the encoding for the character / in +the patch path. The operation path value in JSON-Patch is interpreted as a +JSON-Pointer. For more details, see +[IETF RFC 6901](https://tools.ietf.org/html/rfc6901), section 3. + +The output shows that the Node has a capacity of 4 dongles: + +``` +"capacity": { + "alpha.kubernetes.io/nvidia-gpu": "0", + "cpu": "2", + "memory": "2049008Ki", + "pod.alpha.kubernetes.io/opaque-int-resource-dongle": "4", +``` + +Describe your Node: + +``` +kubectl describe node +``` + +Once again, the output shows the dongle resource: + +```yaml +Capacity: + alpha.kubernetes.io/nvidia-gpu: 0 + cpu: 2 + memory: 2049008Ki + pod.alpha.kubernetes.io/opaque-int-resource-dongle: 4 +``` + +Now, application developers can create Pods that request a certain +number of dongles. See +[Assign Opaque Integer Resources to a Container](/docs/tasks/configure-pod-container/opaque-integer-resource/). + +## Discussion + +Opaque integer resources are similar to memory and CPU resources. For example, +just as a Node has a certain amount of memory and CPU to be shared by all components +running on the Node, it can have a certain number of dongles to be shared +by all components running on the Node. And just as application developers +can create Pods that request a certain amount of memory and CPU, they can +create Pods that request a certain number of dongles. + +Opaque integer resources are called opaque because Kubernetes does not +know anything about what they are. Kubernetes knows only that a Node +has a certain number of them. They are called integer resources because +they must be advertised in integer amounts. For example, a Node can advertise +four dongles, but not 4.5 dongles. + +### Storage example + +Suppose a Node has 800 GiB of a special kind of disk storage. You could +create a name for the special storage, say opaque-int-resource-special-storage. +Then you could advertise it in chunks of a certain size, say 100 GiB. In that case, +your Node would advertise that it has eight resources of type +opaque-int-resource-special-storage. + +```yaml +Capacity: + ... + pod.alpha.kubernetes.io/opaque-int-special-storage: 8 +``` + +If you want to allow arbitrary requests for special storage, you +could advertise special storage in chunks of size 1 byte. In that case, you would advertise +800Gi resources of type opaque-int-resource-special-storage. + +```yaml +Capacity: + ... + pod.alpha.kubernetes.io/opaque-int-special-storage: 8Gi +``` + +Then a Container could request any number of bytes of special storage, up to 800Gi. + +## Clean up + +Here is a PATCH request that removes the dongle advertisement from a Node. + +```shell +PATCH /api/v1/nodes//status HTTP/1.1 +Accept: application/json +Content-Type: application/json-patch+json +Host: k8s-master:8080 + +[ + { + "op": "remove", + "path": "/status/capacity/pod.alpha.kubernetes.io~1opaque-int-resource-dongle", + } +] +``` + +Start a proxy, so that you can easily send requests to the Kubernetes API server: + +``` +kubectl proxy +``` + +In another command window, send the HTTP PATCH request. +Replace `` with the name of your Node: + +```shell +curl --header "Content-Type: application/json-patch+json" \ +--request PATCH \ +--data '[{"op": "remove", "path": "/status/capacity/pod.alpha.kubernetes.io~1opaque-int-resource-dongle"}]' \ +http://localhost:8001/api/v1/nodes//status +``` + +Verify that the dongle advertisement has been removed: + +``` +kubectl describe node | grep dongle +``` + +{% endcapture %} + + +{% capture whatsnext %} + +### For application developers + +* [Assign Opaque Integer Resources to a Container](/docs/tasks/configure-pod-container/opaque-integer-resource/) + +### For cluster administrators + +* [Configure Minimum and Maximum Memory Constraints for a Namespace](/docs/tasks/administer-cluster/memory-constraint-namespace/) +* [Configure Minimum and Maximum CPU Constraints for a Namespace](/docs/tasks/administer-cluster/cpu-constraint-namespace/) + + +{% endcapture %} + + +{% include templates/task.md %} diff --git a/docs/tasks/administer-cluster/quota-api-object.md b/docs/tasks/administer-cluster/quota-api-object.md new file mode 100644 index 0000000000..7ef75d34df --- /dev/null +++ b/docs/tasks/administer-cluster/quota-api-object.md @@ -0,0 +1,174 @@ +--- +title: Configure Quotas for API Objects +--- + + +{% capture overview %} + +This page shows how to configure quotas for API objects, including +PersistentVolumeClaims and Services. A quota restricts the number of +objects, of a particular type, that can be created in a namespace. +You specify quotas in a +[ResourceQuota](/docs/api-reference/v1.7/#resourcequota-v1-core) +object. + +{% endcapture %} + + +{% capture prerequisites %} + +{% include task-tutorial-prereqs.md %} + +{% endcapture %} + + +{% capture steps %} + +## Create a namespace + +Create a namespace so that the resources you create in this exercise are +isolated from the rest of your cluster. + +```shell +kubectl create namespace quota-object-example +``` + +## Create a ResourceQuota + +Here is the configuration file for a ResourceQuota object: + +{% include code.html language="yaml" file="quota-objects.yaml" ghlink="/docs/tasks/administer-cluster/quota-objects.yaml" %} + +Create the ResourceQuota: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/quota-objects.yaml --namespace=quota-object-example +``` + +View detailed information about the ResourceQuota: + +```shell +kubectl get resourcequota object-quota-demo --namespace=quota-object-example --output=yaml +``` + +The output shows that in the quota-object-example namespace, there can be at most +one PersistentVolumeClaim, at most two Services of type LoadBalancer, and no Services +of type NodePort. + +```yaml +status: + hard: + persistentvolumeclaims: "1" + services.loadbalancers: "2" + services.nodeports: "0" + used: + persistentvolumeclaims: "0" + services.loadbalancers: "0" + services.nodeports: "0" +``` + +## Create a PersistentVolumeClaim: + +Here is the configuration file for a PersistentVolumeClaim object: + +{% include code.html language="yaml" file="quota-objects-pvc.yaml" ghlink="/docs/tasks/administer-cluster/quota-objects-pvc.yaml" %} + +Create the PersistentVolumeClaim: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/quota-objects-pvc.yaml --namespace=quota-object-example +``` + +Verify that the PersistentVolumeClaim was created: + +```shell +kubectl get persistentvolumeclaims --namespace=quota-object-example +``` + +The output shows that the PersistentVolumeClaim exists and has status Pending: + +```shell +NAME STATUS +pvc-quota-demo Pending +``` + +## Attempt to create a second PersistentVolumeClaim: + +Here is the configuration file for a second PersistentVolumeClaim: + +{% include code.html language="yaml" file="quota-objects-pvc-2.yaml" ghlink="/docs/tasks/administer-cluster/quota-objects-pvc-2.yaml" %} + +Attempt to create the second PersistentVolumeClaim: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/quota-objects-pvc-2.yaml --namespace=quota-object-example +``` + +The output shows that the second PersistentVolumeClaim was not created, +because it would have exceeded the quota for the namespace. + +``` +persistentvolumeclaims "pvc-quota-demo-2" is forbidden: +exceeded quota: object-quota-demo, requested: persistentvolumeclaims=1, +used: persistentvolumeclaims=1, limited: persistentvolumeclaims=1 +``` + +## Notes + +These are the strings used to identify API resources that can be constrained +by quotas: + + + + + + + + + + + + +
StringAPI Object
"pods"Pod
"servicesService
"replicationcontrollers"ReplicationController
"resourcequotas"ResourceQuota
"secrets"Secret
"configmaps"ConfigMap
"persistentvolumeclaims"PersistentVolumeClaim
"services.nodeports"Service of type NodePort
"services.loadbalancers"Service of type LoadBalancer
+ +## Clean up + +Delete your namespace: + +```shell +kubectl delete namespace quota-object-example +``` + +{% endcapture %} + +{% capture whatsnext %} + +### For cluster administrators + +* [Configure Default Memory Requests and Limits for a Namespace](docs/tasks/administer-cluster/default-memory-request-limit/) + +* [Configure Default CPU Requests and Limits for a Namespace](docs/tasks/administer-cluster/default-cpu-request-limit/) + +* [Configure Minimum and Maximum Memory Constraints for a Namespace](/docs/tasks/administer-cluster/memory-constraint-namespace/) + +* [Configure Minimum and Maximum CPU Constraints for a Namespace](/docs/tasks/administer-cluster/cpu-constraint-namespace/) + +* [Configure Memory and CPU Quotas for a Namespace](/docs/tasks/administer-cluster/quota-memory-cpu-namespace/) + +* [Configure a Pod Quota for a Namespace](/docs/tasks/administer-cluster/quota-pod-namespace/) + +### For app developers + +* [Assign Memory Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-memory-resource/) + +* [Assign CPU Resources to Containers and Pods](docs/tasks/configure-pod-container/assign-cpu-resource/) + +* [Configure Quality of Service for Pods](/docs/tasks/configure-pod-container/quality-service-pod/) + + +{% endcapture %} + + +{% include templates/task.md %} + + diff --git a/docs/tasks/administer-cluster/quota-mem-cpu-pod-2.yaml b/docs/tasks/administer-cluster/quota-mem-cpu-pod-2.yaml new file mode 100644 index 0000000000..22726c600a --- /dev/null +++ b/docs/tasks/administer-cluster/quota-mem-cpu-pod-2.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: quota-mem-cpu-demo-2 +spec: + containers: + - name: quota-mem-cpu-demo-2-ctr + image: redis + resources: + limits: + memory: "1Gi" + cpu: "800m" + requests: + memory: "700Mi" + cpu: "400m" + diff --git a/docs/tasks/administer-cluster/quota-mem-cpu-pod.yaml b/docs/tasks/administer-cluster/quota-mem-cpu-pod.yaml new file mode 100644 index 0000000000..ba27bf5ccf --- /dev/null +++ b/docs/tasks/administer-cluster/quota-mem-cpu-pod.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: quota-mem-cpu-demo +spec: + containers: + - name: quota-mem-cpu-demo-ctr + image: nginx + resources: + limits: + memory: "800Mi" + cpu: "800m" + requests: + memory: "600Mi" + cpu: "400m" + diff --git a/docs/tasks/configure-pod-container/rq-not-best-effort.yaml b/docs/tasks/administer-cluster/quota-mem-cpu.yaml similarity index 57% rename from docs/tasks/configure-pod-container/rq-not-best-effort.yaml rename to docs/tasks/administer-cluster/quota-mem-cpu.yaml index 82666058e1..5c4bcd81b8 100644 --- a/docs/tasks/configure-pod-container/rq-not-best-effort.yaml +++ b/docs/tasks/administer-cluster/quota-mem-cpu.yaml @@ -1,13 +1,10 @@ apiVersion: v1 kind: ResourceQuota metadata: - name: not-best-effort + name: mem-cpu-demo spec: hard: - pods: "4" requests.cpu: "1" - requests.memory: 1Gi + requests.memory: 1Gi limits.cpu: "2" limits.memory: 2Gi - scopes: - - NotBestEffort diff --git a/docs/tasks/administer-cluster/quota-memory-cpu-namespace.md b/docs/tasks/administer-cluster/quota-memory-cpu-namespace.md new file mode 100644 index 0000000000..e27e6192ce --- /dev/null +++ b/docs/tasks/administer-cluster/quota-memory-cpu-namespace.md @@ -0,0 +1,178 @@ +--- +title: Configure Memory and CPU Quotas for a Namespace +--- + + +{% capture overview %} + +This page shows how to set quotas for the total amount memory and CPU that +can be used by all Containers running in a namespace. You specify quotas in a +[ResourceQuota](/docs/api-reference/v1.7/#resourcequota-v1-core) +object. + +{% endcapture %} + + +{% capture prerequisites %} + +{% include task-tutorial-prereqs.md %} + +Each node in your cluster must have at least 1 GiB of memory. + +{% endcapture %} + + +{% capture steps %} + +## Create a namespace + +Create a namespace so that the resources you create in this exercise are +isolated from the rest of your cluster. + +```shell +kubectl create namespace quota-mem-cpu-example +``` + +## Create a ResourceQuota + +Here is the configuration file for a ResourceQuota object: + +{% include code.html language="yaml" file="quota-mem-cpu.yaml" ghlink="/docs/tasks/administer-cluster/quota-mem-cpu.yaml" %} + +Create the ResourceQuota: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/quota-mem-cpu.yaml --namespace=quota-mem-cpu-example +``` + +View detailed information about the ResourceQuota: + +```shell +kubectl get resourcequota mem-cpu-demo --namespace=quota-mem-cpu-example --output=yaml +``` + +The ResourceQuota places these requirements on the quota-mem-cpu-example namespace: + +* Every Container must have a memory request, memory limit, cpu request, and cpu limit. +* The memory request total for all Containers must not exceed 1 GiB. +* The memory limit total for all Containers must not exceed 2 GiB. +* The CPU request total for all Containers must not exceed 1 cpu. +* The CPU limit total for all Containers must not exceed 2 cpu. + +## Create a Pod + +Here is the configuration file for a Pod: + +{% include code.html language="yaml" file="quota-mem-cpu-pod.yaml" ghlink="/docs/tasks/administer-cluster/quota-mem-cpu-pod.yaml" %} + + +Create the Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/quota-mem-cpu-pod.yaml --namespace=quota-mem-cpu-example +``` + +Verify that the Pod's Container is running: + +``` +kubectl get pod quota-mem-cpu-demo --namespace=quota-mem-cpu-example +``` + +Once again, view detailed information about the ResourceQuota: + +``` +kubectl get resourcequota mem-cpu-demo --namespace=quota-mem-cpu-example --output=yaml +``` + +The output shows the quota along with how much of the quota has been used. +You can see that the memory and CPU requests and limits for your Pod do not +exceed the quota. + +``` +status: + hard: + limits.cpu: "2" + limits.memory: 2Gi + requests.cpu: "1" + requests.memory: 1Gi + used: + limits.cpu: 800m + limits.memory: 800Mi + requests.cpu: 400m + requests.memory: 600Mi +``` + +## Attempt to create a second Pod + +Here is the configuration file for a second Pod: + +{% include code.html language="yaml" file="quota-mem-cpu-pod-2.yaml" ghlink="/docs/tasks/administer-cluster/quota-mem-cpu-pod-2.yaml" %} + +In the configuration file, you can see that the Pod has a memory request of 700 MiB. +Notice that the sum of the used memory request and this new memory +request exceeds the memory request quota. 600 MiB + 700 MiB > 1 GiB. + +Attempt to create the Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/quota-mem-cpu-pod-2.yaml --namespace=quota-mem-cpu-example +``` + +The second Pod does not get created. The output shows that creating the second Pod +would cause the memory request total to exceed the memory request quota. + +``` +Error from server (Forbidden): error when creating "docs/tasks/administer-cluster/quota-mem-cpu-pod-2.yaml": +pods "quota-mem-cpu-demo-2" is forbidden: exceeded quota: mem-cpu-demo, +requested: requests.memory=700Mi,used: requests.memory=600Mi, limited: requests.memory=1Gi +``` + +## Discussion + +As you have seen in this exercise, you can use a ResourceQuota to restrict +the memory request total for all Containers running in a namespace. +You can also restrict the totals for memory limit, cpu request, and cpu limit. + +If you want to restrict individual Containers, instead of totals for all Containers, use a +[LimitRange](/docs/tasks/administer-cluster/memory-constraint-namespace/). + +## Clean up + +Delete your namespace: + +```shell +kubectl delete namespace quota-mem-cpu-example +``` + +{% endcapture %} + +{% capture whatsnext %} + +### For cluster administrators + +* [Configure Default Memory Requests and Limits for a Namespace](docs/tasks/administer-cluster/default-memory-request-limit/) + +* [Configure Default CPU Requests and Limits for a Namespace](docs/tasks/administer-cluster/default-cpu-request-limit/) + +* [Configure Minimum and Maximum Memory Constraints for a Namespace](/docs/tasks/administer-cluster/memory-constraint-namespace/) + +* [Configure Minimum and Maximum CPU Constraints for a Namespace](/docs/tasks/administer-cluster/cpu-constraint-namespace/) + +* [Configure a Pod Quota for a Namespace](/docs/tasks/administer-cluster/quota-pod-namespace/) + +* [Configure Quotas for API Objects](/docs/tasks/administer-cluster/quota-api-object/) + +### For app developers + +* [Assign Memory Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-memory-resource/) + +* [Assign CPU Resources to Containers and Pods](docs/tasks/configure-pod-container/assign-cpu-resource/) + +* [Configure Quality of Service for Pods](/docs/tasks/configure-pod-container/quality-service-pod/) + +{% endcapture %} + + +{% include templates/task.md %} + + diff --git a/docs/tasks/administer-cluster/quota-objects-pvc-2.yaml b/docs/tasks/administer-cluster/quota-objects-pvc-2.yaml new file mode 100644 index 0000000000..88c165d144 --- /dev/null +++ b/docs/tasks/administer-cluster/quota-objects-pvc-2.yaml @@ -0,0 +1,11 @@ +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: pvc-quota-demo-2 +spec: + storageClassName: manual + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 4Gi diff --git a/docs/tasks/administer-cluster/quota-objects-pvc.yaml b/docs/tasks/administer-cluster/quota-objects-pvc.yaml new file mode 100644 index 0000000000..b38256b897 --- /dev/null +++ b/docs/tasks/administer-cluster/quota-objects-pvc.yaml @@ -0,0 +1,11 @@ +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: pvc-quota-demo +spec: + storageClassName: manual + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 3Gi diff --git a/docs/tasks/administer-cluster/quota-objects.yaml b/docs/tasks/administer-cluster/quota-objects.yaml new file mode 100644 index 0000000000..e97748decd --- /dev/null +++ b/docs/tasks/administer-cluster/quota-objects.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: ResourceQuota +metadata: + name: object-quota-demo +spec: + hard: + persistentvolumeclaims: "1" + services.loadbalancers: "2" + services.nodeports: "0" diff --git a/docs/tasks/administer-cluster/quota-pod-deployment.yaml b/docs/tasks/administer-cluster/quota-pod-deployment.yaml new file mode 100644 index 0000000000..6d6302a8f4 --- /dev/null +++ b/docs/tasks/administer-cluster/quota-pod-deployment.yaml @@ -0,0 +1,14 @@ +apiVersion: apps/v1beta1 +kind: Deployment +metadata: + name: pod-quota-demo +spec: + replicas: 3 + template: + metadata: + labels: + purpose: quota-demo + spec: + containers: + - name: pod-quota-demo + image: nginx diff --git a/docs/tasks/administer-cluster/quota-pod-namespace.md b/docs/tasks/administer-cluster/quota-pod-namespace.md new file mode 100644 index 0000000000..6d21937593 --- /dev/null +++ b/docs/tasks/administer-cluster/quota-pod-namespace.md @@ -0,0 +1,139 @@ +--- +title: Configure a Pod Quota for a Namespace +--- + + +{% capture overview %} + +This page shows how to set a quota for the total number of Pods that can run +in a namespace. You specify quotas in a +[ResourceQuota](/docs/api-reference/v1.7/#resourcequota-v1-core) +object. + +{% endcapture %} + + +{% capture prerequisites %} + +{% include task-tutorial-prereqs.md %} + +{% endcapture %} + + +{% capture steps %} + +## Create a namespace + +Create a namespace so that the resources you create in this exercise are +isolated from the rest of your cluster. + +```shell +kubectl create namespace quota-pod-example +``` + +## Create a ResourceQuota + +Here is the configuration file for a ResourceQuota object: + +{% include code.html language="yaml" file="quota-pod.yaml" ghlink="/docs/tasks/administer-cluster/quota-pod.yaml" %} + +Create the ResourceQuota: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/quota-pod.yaml --namespace=quota-pod-example +``` + +View detailed information about the ResourceQuota: + +```shell +kubectl get resourcequota pod-demo --namespace=quota-pod-example --output=yaml +``` + +The output shows that the namespace has a quota of two Pods, and that currently there are +no Pods; that is, none of the quota is used. + +```yaml +spec: + hard: + pods: "2" +status: + hard: + pods: "2" + used: + pods: "0" +``` + +Here is the configuration file for a Deployment: + +{% include code.html language="yaml" file="quota-pod-deployment.yaml" ghlink="/docs/tasks/administer-cluster/quota-pod-deployment.yaml" %} + +In the configuration file, `replicas: 3` tells Kubernetes to attempt to create three Pods, all running the same application. + +Create the Deployment: + +```shell +kubectl create -f https://k8s.io/docs/tasks/administer-cluster/quota-pod-deployment.yaml --namespace=quota-pod-example +``` + +View detailed information about the Deployment: + +```shell +kubectl get deployment pod-quota-demo --namespace=quota-pod-example --output=yaml +``` + +The output shows that even though the Deployment specifies three replicas, only two +Pods were created because of the quota. + +```yaml +spec: + ... + replicas: 3 +... +status: + availableReplicas: 2 +... +lastUpdateTime: 2017-07-07T20:57:05Z + message: 'unable to create pods: pods "pod-quota-demo-1650323038-" is forbidden: + exceeded quota: pod-demo, requested: pods=1, used: pods=2, limited: pods=2' +``` + +## Clean up + +Delete your namespace: + +```shell +kubectl delete namespace quota-pod-example +``` + +{% endcapture %} + +{% capture whatsnext %} + +### For cluster administrators + +* [Configure Default Memory Requests and Limits for a Namespace](docs/tasks/administer-cluster/default-memory-request-limit/) + +* [Configure Default CPU Requests and Limits for a Namespace](docs/tasks/administer-cluster/default-cpu-request-limit/) + +* [Configure Minimum and Maximum Memory Constraints for a Namespace](/docs/tasks/administer-cluster/memory-constraint-namespace/) + +* [Configure Minimum and Maximum CPU Constraints for a Namespace](/docs/tasks/administer-cluster/cpu-constraint-namespace/) + +* [Configure Memory and CPU Quotas for a Namespace](/docs/tasks/administer-cluster/quota-memory-cpu-namespace/) + +* [Configure Quotas for API Objects](/docs/tasks/administer-cluster/quota-api-object/) + +### For app developers + +* [Assign Memory Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-memory-resource/) + +* [Assign CPU Resources to Containers and Pods](docs/tasks/configure-pod-container/assign-cpu-resource/) + +* [Configure Quality of Service for Pods](/docs/tasks/configure-pod-container/quality-service-pod/) + +{% endcapture %} + + +{% include templates/task.md %} + + diff --git a/docs/tasks/administer-cluster/quota-pod.yaml b/docs/tasks/administer-cluster/quota-pod.yaml new file mode 100644 index 0000000000..0a07f055ca --- /dev/null +++ b/docs/tasks/administer-cluster/quota-pod.yaml @@ -0,0 +1,7 @@ +apiVersion: v1 +kind: ResourceQuota +metadata: + name: pod-demo +spec: + hard: + pods: "2" diff --git a/docs/tasks/administer-cluster/quota-pvc-2.yaml b/docs/tasks/administer-cluster/quota-pvc-2.yaml new file mode 100644 index 0000000000..88c165d144 --- /dev/null +++ b/docs/tasks/administer-cluster/quota-pvc-2.yaml @@ -0,0 +1,11 @@ +kind: PersistentVolumeClaim +apiVersion: v1 +metadata: + name: pvc-quota-demo-2 +spec: + storageClassName: manual + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 4Gi diff --git a/docs/tasks/configure-pod-container/assign-cpu-ram-container.md b/docs/tasks/configure-pod-container/assign-cpu-ram-container.md deleted file mode 100644 index cab0d329b6..0000000000 --- a/docs/tasks/configure-pod-container/assign-cpu-ram-container.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: Assign CPU and RAM Resources to a Container -description: When you create a Pod, you can request CPU and RAM resources for the containers that run in the Pod. You can also set limits for CPU and RAM use. ---- - -{% capture overview %} - -This page shows how to assign CPU and RAM resources to containers running -in a Kubernetes Pod. - -{% endcapture %} - - -{% capture prerequisites %} - -{% include task-tutorial-prereqs.md %} - -{% endcapture %} - - -{% capture steps %} - -## Assign CPU and RAM resources to a container - -When you create a Pod, you can request CPU and RAM resources for the containers -that run in the Pod. You can also set limits for CPU and RAM resources. To -request CPU and RAM resources, include the `resources:requests` field in the -configuration file. To set limits on CPU and RAM resources, include the -`resources:limits` field. - -Kubernetes schedules a Pod to run on a Node only if the Node has enough CPU and -RAM available to satisfy the total CPU and RAM requested by all of the -containers in the Pod. Also, as a container runs on a Node, Kubernetes doesn't -allow the CPU and RAM consumed by the container to exceed the limits you specify -for the container. If a container exceeds its RAM limit, it is terminated. If a -container exceeds its CPU limit, it becomes a candidate for having its CPU use -throttled. - -In this exercise, you create a Pod that runs one container. The configuration -file for the Pod requests 250 milicpu and 64 mebibytes of RAM. It also sets -upper limits of 1 cpu and 128 mebibytes of RAM. Here is the configuration file -for the `Pod`: - -{% include code.html language="yaml" file="cpu-ram.yaml" ghlink="/docs/tasks/configure-pod-container/cpu-ram.yaml" %} - -1. Create a Pod based on the YAML configuration file: - - kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/cpu-ram.yaml - -1. Display information about the pod: - - kubectl describe pod cpu-ram-demo - - The output is similar to this: - - Name: cpu-ram-demo - ... - Containers: - cpu-ram-demo-container: - ... - Limits: - cpu: 1 - memory: 128Mi - Requests: - cpu: 250m - memory: 64Mi - -## CPU and RAM units - -The CPU resource is measured in *cpu*s. Fractional values are allowed. You can -use the suffix *m* to mean mili. For example 100m cpu is 100 milicpu, and is -the same as 0.1 cpu. - -The RAM resource is measured in bytes. You can express RAM as a plain integer -or a fixed-point integer with one of these suffixes: E, P, T, G, M, K, Ei, Pi, -Ti, Gi, Mi, Ki. For example, the following represent approximately the same value: - - 128974848, 129e6, 129M , 123Mi - -If you're not sure how much resources to request, you can first launch the -application without specifying resources, and use -[resource usage monitoring](/docs/user-guide/monitoring) to determine -appropriate values. - -If a Container exceeds its RAM limit, it dies from an out-of-memory condition. -You can improve reliability by specifying a value that is a little higher -than what you expect to use. - -If you specify a request, a Pod is guaranteed to be able to use that much -of the resource. See -[Resource QoS](https://git.k8s.io/community/contributors/design-proposals/resource-qos.md) for the difference between resource limits and requests. - -## If you don't specify limits or requests - -If you don't specify a RAM limit, Kubernetes places no upper bound on the -amount of RAM a Container can use. A Container could use all the RAM -available on the Node where the Container is running. Similarly, if you don't -specify a CPU limit, Kubernetes places no upper bound on CPU resources, and a -Container could use all of the CPU resources available on the Node. - -Default limits are applied according to a limit range for the default -[namespace](/docs/user-guide/namespaces). You can use `kubectl describe limitrange limits` -to see the default limits. - -For information about why you would want to specify limits, see -[Setting Pod CPU and Memory Limits](/docs/tasks/configure-pod-container/limit-range/). - -For information about what happens if you don't specify CPU and RAM requests, see -[Resource Requests and Limits of Pod and Container](/docs/concepts/configuration/manage-compute-resources-container/). - -{% endcapture %} - -{% capture whatsnext %} - -* Learn more about [managing compute resources](/docs/concepts/configuration/manage-compute-resources-container/). -* See [ResourceRequirements](/docs/api-reference/{{page.version}}/#resourcerequirements-v1-core). - -{% endcapture %} - - -{% include templates/task.md %} - diff --git a/docs/tasks/configure-pod-container/assign-cpu-resource.md b/docs/tasks/configure-pod-container/assign-cpu-resource.md new file mode 100644 index 0000000000..6a84b9e44b --- /dev/null +++ b/docs/tasks/configure-pod-container/assign-cpu-resource.md @@ -0,0 +1,273 @@ +--- +title: Assign CPU Resources to Containers and Pods +--- + +{% capture overview %} + +This page shows how to assign a CPU *request* and a CPU *limit* to +a Container. A Container is guaranteed to have as much CPU as it requests, +but is not allowed to use more CPU than its limit. + + +{% endcapture %} + + +{% capture prerequisites %} + +{% include task-tutorial-prereqs.md %} + +Each node in your cluster must have at least 1 CPU. + +A few of the steps on this page require that the +[Heapster](https://github.com/kubernetes/heapster) service is running +in your cluster. But if you don't have Heapster running, you can do most +of the steps, and it won't be a problem if you skip the Heapster steps. + +To see whether the Heapster service is running, enter this command: + +```shell +kubectl get services --namespace=kube-system +``` + +If the heapster service is running, it shows in the output: + +```shell +NAMESPACE NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE +kube-system heapster 10.11.240.9 80/TCP 6d +``` + +{% endcapture %} + + +{% capture steps %} + +## Create a namespace + +Create a namespace so that the resources you create in this exercise are +isolated from the rest of your cluster. + +```shell +kubectl create namespace cpu-example +``` + +## Specify a CPU request and a CPU limit + +To specify a CPU request for a Container, include the `resources:requests` field +in the Container's resource manifest. To specify a CPU limit, include `resources:limits`. + +In this exercise, you create a Pod that has one Container. The container has a CPU +request of 0.5 cpu and a CPU limit of 1 cpu. Here's the configuration file +for the Pod: + +{% include code.html language="yaml" file="cpu-request-limit.yaml" ghlink="/docs/tasks/configure-pod-container/cpu-request-limit.yaml" %} + +In the configuration file, the `args` section provides arguments for the Container when it starts. +The `-cpus "2"` argument tells the Container to attempt to use 2 cpus. + +Create the Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/cpu-request-limit.yaml --namespace=cpu-example +``` + +Verify that the Pod's Container is running: + +```shell +kubectl get pod cpu-demo --namespace=cpu-example +``` + +View detailed information about the Pod: + +```shell +kubectl get pod cpu-demo --output=yaml --namespace=cpu-example +``` + +The output shows that the one Container in the Pod has a CPU request of 500 millicpu +and a CPU limit of 1 cpu. + +```shell +resources: + limits: + cpu: "1" + requests: + cpu: 500m +``` + +Start a proxy so that you can call the heapster service: + +```shell +kubectl proxy +``` + +In another command window, get the CPU usage rate from the heapster service: + +``` +curl http://localhost:8001/api/v1/proxy/namespaces/kube-system/services/heapster/api/v1/model/namespaces/cpu-example/pods/cpu-demo/metrics/cpu/usage_rate +``` + +The output shows that the Pod is using 974 millicpu, which is just a bit less than +the limit of 1 cpu specified in the Pod's configuration file. + +```json +{ + "timestamp": "2017-06-22T18:48:00Z", + "value": 974 +} +``` + +Recall that by setting `-cpu "2"`, you configured the Container to attempt to use 2 cpus. +But the container is only being allowed to use about 1 cpu. The Container's CPU use is being +throttled, because the Container is attempting to use more CPU resources than its limit. + +Note: There's another possible explanation for the CPU throttling. The Node might not have +enough CPU resources available. Recall that the prerequisites for this exercise require that each of +your Nodes has at least 1 cpu. If your Container is running on a Node that has only 1 cpu, the Container +cannot use more than 1 cpu regardless of the CPU limit specified for the Container. + +## CPU units + +The CPU resource is measured in *cpu* units. One cpu, in Kubernetes, is equivalent to: + +* 1 AWS vCPU +* 1 GCP Core +* 1 Azure vCore +* 1 Hyperthread on a bare-metal Intel processor with Hyperthreading + +Fractional values are allowed. A Container that requests 0.5 cpu is guaranteed half as much +CPU as a Container that requests 1 cpu. You can use the suffix m to mean milli. For example +100m cpu, 100 millicpu, and 0.1 cpu are all the same. Precision finer than 1m is not allowed. + +CPU is always requested as an absolute quantity, never as a relative quantity; 0.1 is the same +amount of CPU on a single-core, dual-core, or 48-core machine. + +Delete your Pod: + +```shell +kubectl delete pod cpu-demo --namespace=cpu-example +``` + +## Specify a CPU request that is too big for your Nodes + +CPU requests and limits are associated with Containers, but it is useful to think +of a Pod as having a CPU request and limit. The CPU request for a Pod is the sum +of the CPU requests for all the Containers in the Pod. Likewise, the CPU limit for +a Pod is the sum of the CPU limits for all the Containers in the Pod. + +Pod scheduling is based on requests. A Pod is scheduled to run on a Node only if +the Node has enough CPU resources available to satisfy the Pod’s CPU request. + +In this exercise, you create a Pod that has a CPU request so big that it exceeds +the capacity of any Node in your cluster. Here is the configuration file for a Pod +that has one Container. The Container requests 100 cpu, which is likely to exceed the +capacity of any Node in your cluster. + +{% include code.html language="yaml" file="cpu-request-limit-2.yaml" ghlink="/docs/tasks/configure-pod-container/cpu-request-limit-2.yaml" %} + +Create the Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/cpu-request-limit-2.yaml --namespace=cpu-example +``` + +View the Pod's status: + +```shell +kubectl get pod cpu-demo-2 --namespace=cpu-example +``` + +The output shows that the Pod's status is Pending. That is, the Pod has not been +scheduled to run on any Node, and it will remain in the Pending state indefinitely: + + +``` +kubectl get pod cpu-demo-2 --namespace=cpu-example +NAME READY STATUS RESTARTS AGE +cpu-demo-2 0/1 Pending 0 7m +``` + +View detailed information about the Pod, including events: + + +```shell +kubectl describe pod cpu-demo-2 --namespace=cpu-example +``` + +The output shows that the Container cannot be scheduled because of insufficient +CPU resources on the Nodes: + + +```shell +Events: + Reason Message + ------ ------- + FailedScheduling No nodes are available that match all of the following predicates:: Insufficient cpu (3). + +``` + +Delete your Pod: + +```shell +kubectl delete pod cpu-demo-2 --namespace=cpu-example +``` + +## If you don’t specify a CPU limit + +If you don’t specify a CPU limit for a Container, then one of these situations applies: + +* The Container has no upper bound on the CPU resources it can use. The Container +could use all of the CPU resources available on the Node where it is running. + +* The Container is running in a namespace that has a default CPU limit, and the +Container is automatically assigned the default limit. Cluster administrators can use a +[LimitRange](https://kubernetes.io/docs/api-reference/v1.6/) +to specify a default value for the CPU limit. + +## Motivation for CPU requests and limits + +By configuring the CPU requests and limits of the Containers that run in your +cluster, you can make efficient use of the CPU resources available on your cluster's +Nodes. By keeping a Pod's CPU request low, you give the Pod a good chance of being +scheduled. By having a CPU limit that is greater than the CPU request, you accomplish two things: + +* The Pod can have bursts of activity where it makes use of CPU resources that happen to be available. +* The amount of CPU resources a Pod can use during a burst is limited to some reasonable amount. + +## Clean up + +Delete your namespace: + +```shell +kubectl delete namespace cpu-example +``` + +{% endcapture %} + +{% capture whatsnext %} + + +### For app developers + +* [Assign Memory Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-memory-resource/) + +* [Configure Quality of Service for Pods](/docs/tasks/configure-pod-container/quality-service-pod/) + +### For cluster administrators + +* [Configure Default Memory Requests and Limits for a Namespace](docs/tasks/administer-cluster/default-memory-request-limit/) + +* [Configure Default CPU Requests and Limits for a Namespace](docs/tasks/administer-cluster/default-cpu-request-limit/) + +* [Configure Minimum and Maximum Memory Constraints for a Namespace](/docs/tasks/administer-cluster/memory-constraint-namespace/) + +* [Configure Minimum and Maximum CPU Constraints for a Namespace](/docs/tasks/administer-cluster/cpu-constraint-namespace/) + +* [Configure Memory and CPU Quotas for a Namespace](/docs/tasks/administer-cluster/quota-memory-cpu-namespace/) + +* [Configure a Pod Quota for a Namespace](/docs/tasks/administer-cluster/quota-pod-namespace/) + +* [Configure Quotas for API Objects](/docs/tasks/administer-cluster/quota-api-object/) + +{% endcapture %} + + +{% include templates/task.md %} diff --git a/docs/tasks/configure-pod-container/assign-memory-resource.md b/docs/tasks/configure-pod-container/assign-memory-resource.md new file mode 100644 index 0000000000..64f8855929 --- /dev/null +++ b/docs/tasks/configure-pod-container/assign-memory-resource.md @@ -0,0 +1,368 @@ +--- +title: Assign Memory Resources to Containers and Pods +--- + +{% capture overview %} + +This page shows how to assign a memory *request* and a memory *limit* to a +Container. A Container is guaranteed to have as much memory as it requests, +but is not allowed to use more memory than its limit. + +{% endcapture %} + + +{% capture prerequisites %} + +{% include task-tutorial-prereqs.md %} + +Each node in your cluster must have at least 300 MiB of memory. + +A few of the steps on this page require that the +[Heapster](https://github.com/kubernetes/heapster) service is running +in your cluster. But if you don't have Heapster running, you can do most +of the steps, and it won't be a problem if you skip the Heapster steps. + +To see whether the Heapster service is running, enter this command: + +```shell +kubectl get services --namespace=kube-system +``` + +If the Heapster service is running, it shows in the output: + +```shell +NAMESPACE NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE +kube-system heapster 10.11.240.9 80/TCP 6d +``` + +{% endcapture %} + + +{% capture steps %} + +## Create a namespace + +Create a namespace so that the resources you create in this exercise are +isolated from the rest of your cluster. + +```shell +kubectl create namespace mem-example +``` + +## Specify a memory request and a memory limit + +To specify a memory request for a Container, include the `resources:requests` field +in the Container's resource manifest. To specify a memory limit, include `resources:limits`. + +In this exercise, you create a Pod that has one Container. The container has a memory +request of 100 MiB and a memory limit of 200 MiB. Here's the configuration file +for the Pod: + +{% include code.html language="yaml" file="memory-request-limit.yaml" ghlink="/docs/tasks/configure-pod-container/memory-request-limit.yaml" %} + +In the configuration file, the `args` section provides arguments for the Container when it starts. +The `-mem-total 150Mi` argument tells the Container to attempt to allocate 150 MiB of memory. + +Create the Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/memory-request-limit.yaml --namespace=mem-example +``` + +Verify that the Pod's Container is running: + +```shell +kubectl get pod memory-demo --namespace=mem-example +``` + +View detailed information about the Pod: + +```shell +kubectl get pod memory-demo --output=yaml --namespace=mem-example +``` + +The output shows that the one Container in the Pod has a memory request of 100 MiB +and a memory limit of 200 MiB. + + +```yaml +... +resources: + limits: + memory: 200Mi + requests: + memory: 100Mi +... +``` + +Start a proxy so that you can call the Heapster service: + +```shell +kubectl proxy +``` + +In another command window, get the memory usage from the Heapster service: + +``` +curl http://localhost:8001/api/v1/proxy/namespaces/kube-system/services/heapster/api/v1/model/namespaces/mem-example/pods/memory-demo/metrics/memory/usage +``` + +The output shows that the Pod is using about 162,900,000 bytes of memory, which +is about 150 MiB. This is greater than the Pod's 100 MiB request, but within the +Pod's 200 MiB limit. + +```json +{ + "timestamp": "2017-06-20T18:54:00Z", + "value": 162856960 +} +``` + +Delete your Pod: + +```shell +kubectl delete pod memory-demo --namespace=mem-example +``` + +## Exceed a Container's memory limit + +A Container can exceed its memory request if the Node has memory available. But a Container +is not allowed to use more than its memory limit. If a container allocates more memory than +its limit, the Container becomes a candidate for termination. If the Container continues to +to consume memory beyond its limit, the Container is terminated. If a terminated Container is +restartable, the kubelet will restart it, as with any other type of runtime failure. + +In this exercise, you create a Pod that attempts to allocate more memory than its limit. +Here is the configuration file for a Pod that has one Container. The Container has a +memory request of 50 MiB and a memory limit of 100 MiB. + +{% include code.html language="yaml" file="memory-request-limit-2.yaml" ghlink="/docs/tasks/configure-pod-container/memory-request-limit-2.yaml" %} + +In the configuration file, in the `args` section, you can see that the Container +will attempt to allocate 250 MiB of memory, which is well above the 100 MiB limit. + +Create the Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/memory-request-limit-2.yaml --namespace=mem-example +``` + +View detailed information about the Pod: + +```shell +kubectl get pod memory-demo-2 --namespace=mem-example +``` + +At this point, the Container might be running, or it might have been killed. If the +Container has not yet been killed, repeat the preceding command until you see that +the Container has been killed: + +```shell +NAME READY STATUS RESTARTS AGE +memory-demo-2 0/1 OOMKilled 1 24s +``` + +Get a more detailed view of the Container's status: + +```shell +kubectl get pod memory-demo-2 --output=yaml --namespace=mem-example +``` + +The output shows that the Container has been killed because it is out of memory (OOM). + +```shell +lastState: + terminated: + containerID: docker://65183c1877aaec2e8427bc95609cc52677a454b56fcb24340dbd22917c23b10f + exitCode: 137 + finishedAt: 2017-06-20T20:52:19Z + reason: OOMKilled + startedAt: null +``` + +The Container in this exercise is restartable, so the kubelet will restart it. Enter +this command several times to see that the Container gets repeatedly killed and restarted: + +```shell +kubectl get pod memory-demo-2 --namespace=mem-example +``` + +The output shows that the Container gets killed, restarted, killed again, restarted again, and so on: + +``` +stevepe@sperry-1:~/steveperry-53.github.io$ kubectl get pod memory-demo-2 --namespace=mem-example +NAME READY STATUS RESTARTS AGE +memory-demo-2 0/1 OOMKilled 1 37s +stevepe@sperry-1:~/steveperry-53.github.io$ kubectl get pod memory-demo-2 --namespace=mem-example +NAME READY STATUS RESTARTS AGE +memory-demo-2 1/1 Running 2 40s +``` + +View detailed information about the Pod's history: + + +``` +kubectl describe pod memory-demo-2 --namespace=mem-example +``` + +The output shows that the Container starts and fails repeatedly: + + +``` +... Normal Created Created container with id 66a3a20aa7980e61be4922780bf9d24d1a1d8b7395c09861225b0eba1b1f8511 +... Warning BackOff Back-off restarting failed container + +``` + +View detailed information about your cluster's Nodes: + + +``` +kubectl describe nodes +``` + +The output includes a record of the Container being killed because of an out-of-memory condition: + +``` +Warning OOMKilling Memory cgroup out of memory: Kill process 4481 (stress) score 1994 or sacrifice child +``` + +Delete your Pod: + +```shell +kubectl delete pod memory-demo-2 --namespace=mem-example +``` + +## Specify a memory request that is too big for your Nodes + +Memory requests and limits are associated with Containers, but it is useful to think +of a Pod as having a memory request and limit. The memory request for the Pod is the +sum of the memory requests for all the Containers in the Pod. Likewise, the memory +limit for the Pod is the sum of the limits of all the Containers in the Pod. + +Pod scheduling is based on requests. A Pod is scheduled to run on a Node only if the Node +has enough available memory to satisfy the Pod's memory request. + +In this exercise, you create a Pod that has a memory request so big that it exceeds the +capacity of any Node in your cluster. Here is the configuration file for a Pod that has one +Container. The Container requests 1000 GiB of memory, which is likely to exceed the capacity +of any Node in your cluster. + +{% include code.html language="yaml" file="memory-request-limit-3.yaml" ghlink="/docs/tasks/configure-pod-container/memory-request-limit-3.yaml" %} + +Create the Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/memory-request-limit-3.yaml --namespace=mem-example +``` + +View the Pod's status: + +```shell +kubectl get pod memory-demo-3 --namespace=mem-example +``` + +The output shows that the Pod's status is PENDING. That is, the Pod has not been +scheduled to run on any Node, and it will remain in the PENDING state indefinitely: + + +``` +kubectl get pod memory-demo-3 --namespace=mem-example +NAME READY STATUS RESTARTS AGE +memory-demo-3 0/1 Pending 0 25s +``` + +View detailed information about the Pod, including events: + + +```shell +kubectl describe pod memory-demo-3 --namespace=mem-example +``` + +The output shows that the Container cannot be scheduled because of insufficient memory on the Nodes: + + +```shell +Events: + ... Reason Message + ------ ------- + ... FailedScheduling No nodes are available that match all of the following predicates:: Insufficient memory (3). +``` + +## Memory units + +The memory resource is measured in bytes. You can express memory as a plain integer or a +fixed-point integer with one of these suffixes: E, P, T, G, M, K, Ei, Pi, Ti, Gi, Mi, Ki. +For example, the following represent approximately the same value: + +```shell +128974848, 129e6, 129M , 123Mi +``` + +Delete your Pod: + +```shell +kubectl delete pod memory-demo-3 --namespace=mem-example +``` + +## If you don’t specify a memory limit + +If you don’t specify a memory limit for a Container, then one of these situations applies: + +* The Container has no upper bound on the amount of memory it uses. The Container +could use all of the memory available on the Node where it is running. + +* The Container is running in a namespace that has a default memory limit, and the +Container is automatically assigned the default limit. Cluster administrators can use a +[LimitRange](https://kubernetes.io/docs/api-reference/v1.6/) +to specify a default value for the memory limit. + +## Motivation for memory requests and limits + +By configuring memory requests and limits for the Containers that run in your +cluster, you can make efficient use of the memory resources available on your cluster's +Nodes. By keeping a Pod's memory request low, you give the Pod a good chance of being +scheduled. By having a memory limit that is greater than the memory request, you accomplish two things: + +* The Pod can have bursts of activity where it makes use of memory that happens to be available. +* The amount of memory a Pod can use during a burst is limited to some reasonable amount. + +## Clean up + +Delete your namespace. This deletes all the Pods that you created for this task: + +```shell +kubectl delete namespace mem-example +``` + +{% endcapture %} + +{% capture whatsnext %} + +### For app developers + +* [Assign CPU Resources to Containers and Pods](docs/tasks/configure-pod-container/assign-cpu-resource/) + +* [Configure Quality of Service for Pods](/docs/tasks/configure-pod-container/quality-service-pod/) + +### For cluster administrators + +* [Configure Default Memory Requests and Limits for a Namespace](docs/tasks/administer-cluster/default-memory-request-limit/) + +* [Configure Default CPU Requests and Limits for a Namespace](docs/tasks/administer-cluster/default-cpu-request-limit/) + +* [Configure Minimum and Maximum Memory Constraints for a Namespace](/docs/tasks/administer-cluster/memory-constraint-namespace/) + +* [Configure Minimum and Maximum CPU Constraints for a Namespace](/docs/tasks/administer-cluster/cpu-constraint-namespace/) + +* [Configure Memory and CPU Quotas for a Namespace](/docs/tasks/administer-cluster/quota-memory-cpu-namespace/) + +* [Configure a Pod Quota for a Namespace](/docs/tasks/administer-cluster/quota-pod-namespace/) + +* [Configure Quotas for API Objects](/docs/tasks/administer-cluster/quota-api-object/) + +{% endcapture %} + + +{% include templates/task.md %} + diff --git a/docs/tasks/configure-pod-container/cpu-ram.yaml b/docs/tasks/configure-pod-container/cpu-ram.yaml deleted file mode 100644 index c45189fb1e..0000000000 --- a/docs/tasks/configure-pod-container/cpu-ram.yaml +++ /dev/null @@ -1,15 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: cpu-ram-demo -spec: - containers: - - name: cpu-ram-demo-container - image: gcr.io/google-samples/node-hello:1.0 - resources: - requests: - memory: "64Mi" - cpu: "250m" - limits: - memory: "128Mi" - cpu: "1" diff --git a/docs/tasks/configure-pod-container/cpu-request-limit-2.yaml b/docs/tasks/configure-pod-container/cpu-request-limit-2.yaml new file mode 100644 index 0000000000..afb5562d59 --- /dev/null +++ b/docs/tasks/configure-pod-container/cpu-request-limit-2.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: cpu-demo-2 +spec: + containers: + - name: cpu-demo-ctr-2 + image: vish/stress + resources: + limits: + cpu: "100" + requests: + cpu: "100" + args: + - -cpus + - "2" diff --git a/docs/tasks/configure-pod-container/cpu-request-limit.yaml b/docs/tasks/configure-pod-container/cpu-request-limit.yaml new file mode 100644 index 0000000000..a85dde6181 --- /dev/null +++ b/docs/tasks/configure-pod-container/cpu-request-limit.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Pod +metadata: + name: cpu-demo +spec: + containers: + - name: cpu-demo-ctr + image: vish/stress + resources: + limits: + cpu: "1" + requests: + cpu: "0.5" + args: + - -cpus + - "2" diff --git a/docs/tasks/configure-pod-container/invalid-pod.yaml b/docs/tasks/configure-pod-container/invalid-pod.yaml deleted file mode 100644 index b63f25deba..0000000000 --- a/docs/tasks/configure-pod-container/invalid-pod.yaml +++ /dev/null @@ -1,12 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: invalid-pod -spec: - containers: - - name: kubernetes-serve-hostname - image: gcr.io/google_containers/serve_hostname - resources: - limits: - cpu: "3" - memory: 100Mi diff --git a/docs/tasks/configure-pod-container/limits.yaml b/docs/tasks/configure-pod-container/limits.yaml deleted file mode 100644 index 5de4841705..0000000000 --- a/docs/tasks/configure-pod-container/limits.yaml +++ /dev/null @@ -1,26 +0,0 @@ -apiVersion: v1 -kind: LimitRange -metadata: - name: mylimits -spec: - limits: - - max: - cpu: "2" - memory: 1Gi - min: - cpu: 200m - memory: 6Mi - type: Pod - - default: - cpu: 300m - memory: 200Mi - defaultRequest: - cpu: 200m - memory: 100Mi - max: - cpu: "2" - memory: 1Gi - min: - cpu: 100m - memory: 3Mi - type: Container diff --git a/docs/tasks/configure-pod-container/mem-limit-range.yaml b/docs/tasks/configure-pod-container/mem-limit-range.yaml new file mode 100644 index 0000000000..b98a5ae262 --- /dev/null +++ b/docs/tasks/configure-pod-container/mem-limit-range.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: LimitRange +metadata: + name: mem-limit-range +spec: + limits: + - default: + memory: 512Mi + defaultRequest: + memory: 256Mi + type: Container diff --git a/docs/tasks/configure-pod-container/memory-request-limit-2.yaml b/docs/tasks/configure-pod-container/memory-request-limit-2.yaml new file mode 100644 index 0000000000..ca16c1de4a --- /dev/null +++ b/docs/tasks/configure-pod-container/memory-request-limit-2.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Pod +metadata: + name: memory-demo-2 +spec: + containers: + - name: memory-demo-2-ctr + image: vish/stress + resources: + requests: + memory: 50Mi + limits: + memory: "100Mi" + args: + - -mem-total + - 250Mi + - -mem-alloc-size + - 10Mi + - -mem-alloc-sleep + - 1s diff --git a/docs/tasks/configure-pod-container/memory-request-limit-3.yaml b/docs/tasks/configure-pod-container/memory-request-limit-3.yaml new file mode 100644 index 0000000000..394ec9c2d4 --- /dev/null +++ b/docs/tasks/configure-pod-container/memory-request-limit-3.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Pod +metadata: + name: memory-demo-3 +spec: + containers: + - name: memory-demo-3-ctr + image: vish/stress + resources: + limits: + memory: "1000Gi" + requests: + memory: "1000Gi" + args: + - -mem-total + - 150Mi + - -mem-alloc-size + - 10Mi + - -mem-alloc-sleep + - 1s diff --git a/docs/tasks/configure-pod-container/memory-request-limit.yaml b/docs/tasks/configure-pod-container/memory-request-limit.yaml new file mode 100644 index 0000000000..22f0d9e0c7 --- /dev/null +++ b/docs/tasks/configure-pod-container/memory-request-limit.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Pod +metadata: + name: memory-demo +spec: + containers: + - name: memory-demo-ctr + image: vish/stress + resources: + limits: + memory: "200Mi" + requests: + memory: "100Mi" + args: + - -mem-total + - 150Mi + - -mem-alloc-size + - 10Mi + - -mem-alloc-sleep + - 1s diff --git a/docs/tasks/configure-pod-container/oir-pod-2.yaml b/docs/tasks/configure-pod-container/oir-pod-2.yaml new file mode 100644 index 0000000000..cfe4b96076 --- /dev/null +++ b/docs/tasks/configure-pod-container/oir-pod-2.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: oir-demo-2 +spec: + containers: + - name: oir-demo-2-ctr + image: nginx + resources: + requests: + pod.alpha.kubernetes.io/opaque-int-resource-dongle: 2 diff --git a/docs/tasks/configure-pod-container/oir-pod.yaml b/docs/tasks/configure-pod-container/oir-pod.yaml new file mode 100644 index 0000000000..bd85a5d4f6 --- /dev/null +++ b/docs/tasks/configure-pod-container/oir-pod.yaml @@ -0,0 +1,11 @@ +apiVersion: v1 +kind: Pod +metadata: + name: oir-demo +spec: + containers: + - name: oir-demo-ctr + image: nginx + resources: + requests: + pod.alpha.kubernetes.io/opaque-int-resource-dongle: 3 diff --git a/docs/tasks/configure-pod-container/opaque-integer-resource.md b/docs/tasks/configure-pod-container/opaque-integer-resource.md new file mode 100644 index 0000000000..7451f3b774 --- /dev/null +++ b/docs/tasks/configure-pod-container/opaque-integer-resource.md @@ -0,0 +1,141 @@ +--- +title: Assign Opaque Integer Resources to a Container +--- + +{% capture overview %} + +This page shows how to assign opaque integer resources to a Container. + +{% include feature-state-alpha.md %} + +{% endcapture %} + + +{% capture prerequisites %} + +{% include task-tutorial-prereqs.md %} + +Before you do this exercise, do the exercise in +[Advertise Opaque Integer Resources for a Node](/docs/tasks/administer-cluster/opaque-integer-resource-node/). +That will configure one of your Nodes to advertise a dongle resource. + +{% endcapture %} + + +{% capture steps %} + +## Assign an opaque integer resource to a Pod + +To request an opaque integer resource, include the `resources:requests` field in your +Container manifest. Opaque integer resources have the prefix `pod.alpha.kubernetes.io/opaque-int-resource-`. + +Here is the configuration file for a Pod that has one Container: + +{% include code.html language="yaml" file="oir-pod.yaml" ghlink="/docs/tasks/configure-pod-container/oir-pod.yaml" %} + +In the configuration file, you can see that the Container requests 3 dongles. + +Create a Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/oir-pod.yaml +``` + +Verify that the Pod is running: + +```shell +kubectl get pod oir-demo +``` + +Describe the Pod: + +```shell +kubectl describe pod oir-demo +``` + +The output shows the memory, CPU, and dongle requests: + +```yaml +Requests: + pod.alpha.kubernetes.io/opaque-int-resource-dongle: 3 +``` + +## Attempt to create a second Pod + +Here is the configuration file for a Pod that has one Container. The Container requests +two dongles. + +{% include code.html language="yaml" file="oir-pod-2.yaml" ghlink="/docs/tasks/configure-pod-container/oir-pod-2.yaml" %} + +Kubernetes will not be able to satisfy the request for two dongles, because the first Pod +used three of the four available dongles. + +Attempt to create a Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/oir-pod-2.yaml +``` + +Describe the Pod + +```shell +kubectl describe pod oir-demo-2 +``` + +The output shows that the Pod cannot be scheduled, because there is no Node that has +2 dongles available: + + +``` +Conditions: + Type Status + PodScheduled False +... +Events: + ... + ... Warning FailedScheduling pod (oir-demo-2) failed to fit in any node +fit failure summary on nodes : Insufficient pod.alpha.kubernetes.io/opaque-int-resource-dongle (1) +``` + +View the Pod status: + +```shell +kubectl get pod oir-demo-2 +``` + +The output shows that the Pod was created, but not scheduled to run on a Node. +It has a status of Pending: + +```yaml +NAME READY STATUS RESTARTS AGE +oir-demo-2 0/1 Pending 0 6m +``` + +## Clean up + +Delete the Pod that you created for this exercise: + +```shell +kubectl delete pod oir-demo +``` + +{% endcapture %} + +{% capture whatsnext %} + +### For application developers + +* [Assign Memory Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-memory-resource/) +* [Assign CPU Resources to Containers and Pods](docs/tasks/configure-pod-container/assign-cpu-resource/) + +### For cluster administrators + +* [Advertise Opaque Integer Resources for a Node](/docs/tasks/administer-cluster/opaque-integer-resource-node/) + +{% endcapture %} + + +{% include templates/task.md %} + + + diff --git a/docs/tasks/configure-pod-container/qos-pod-2.yaml b/docs/tasks/configure-pod-container/qos-pod-2.yaml new file mode 100644 index 0000000000..8e26f6bb37 --- /dev/null +++ b/docs/tasks/configure-pod-container/qos-pod-2.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: Pod +metadata: + name: qos-demo-2 +spec: + containers: + - name: qos-demo-2-ctr + image: nginx + resources: + limits: + memory: "200Mi" + requests: + memory: "100Mi" diff --git a/docs/tasks/configure-pod-container/qos-pod-3.yaml b/docs/tasks/configure-pod-container/qos-pod-3.yaml new file mode 100644 index 0000000000..c31ea25257 --- /dev/null +++ b/docs/tasks/configure-pod-container/qos-pod-3.yaml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Pod +metadata: + name: qos-demo-3 +spec: + containers: + - name: qos-demo-3-ctr + image: nginx diff --git a/docs/tasks/configure-pod-container/qos-pod-4.yaml b/docs/tasks/configure-pod-container/qos-pod-4.yaml new file mode 100644 index 0000000000..eebb1739d2 --- /dev/null +++ b/docs/tasks/configure-pod-container/qos-pod-4.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: qos-demo-4 +spec: + containers: + + - name: qos-demo-4-ctr-1 + image: nginx + resources: + requests: + memory: "200Mi" + + - name: qos-demo-4-ctr-2 + image: redis diff --git a/docs/tasks/configure-pod-container/qos-pod.yaml b/docs/tasks/configure-pod-container/qos-pod.yaml new file mode 100644 index 0000000000..a54d2b961f --- /dev/null +++ b/docs/tasks/configure-pod-container/qos-pod.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: qos-demo +spec: + containers: + - name: qos-demo-ctr + image: nginx + resources: + limits: + memory: "200Mi" + cpu: "700m" + requests: + memory: "200Mi" + cpu: "700m" diff --git a/docs/tasks/configure-pod-container/quality-service-pod.md b/docs/tasks/configure-pod-container/quality-service-pod.md new file mode 100644 index 0000000000..44407e639b --- /dev/null +++ b/docs/tasks/configure-pod-container/quality-service-pod.md @@ -0,0 +1,265 @@ +--- +title: Configure Quality of Service for Pods +--- + + +{% capture overview %} + +This page shows how to configure Pods so that they will be assigned particular +Quality of Service (QoS) classes. Kubernetes uses QoS classes to make decisions about +scheduling and evicting Pods. + +{% endcapture %} + + +{% capture prerequisites %} + +{% include task-tutorial-prereqs.md %} + +{% endcapture %} + + +{% capture steps %} + +## QoS classes + +When Kubernetes creates a Pod it assigns one of these QoS classes to the Pod: + +* Guaranteed +* Burstable +* BestEffort + +## Create a namespace + +Create a namespace so that the resources you create in this exercise are +isolated from the rest of your cluster. + +```shell +kubectl create namespace qos-example +``` + +## Create a Pod that gets assigned a QoS class of Guaranteed + +For a Pod to be given a QoS class of Guaranteed: + +* Every Container in the Pod must have a memory limit and a memory request, and they must be the same. +* Every Container in the Pod must have a cpu limit and a cpu request, and they must be the same. + +Here is the configuration file for a Pod that has one Container. The Container has a memory limit and a +memory request, both equal to 200 MiB. The Container has a cpu limit and a cpu request, both equal to 700 millicpu: + +{% include code.html language="yaml" file="qos-pod.yaml" ghlink="/docs/tasks/configure-pod-container/qos-pod.yaml" %} + +Create the Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/qos-pod.yaml --namespace=qos-example +``` + +View detailed information about the Pod: + +```shell +kubectl get pod qos-demo --namespace=qos-example --output=yaml +``` + +The output shows that Kubernetes gave the Pod a QoS class of Guaranteed. The output also +verifies that the Pod's Container has a memory request that matches its memory limit, and it has +a cpu request that matches its cpu limit. + +```yaml +spec: + containers: + ... + resources: + limits: + cpu: 700m + memory: 200Mi + requests: + cpu: 700m + memory: 200Mi +... + qosClass: Guaranteed +``` + +**Note**: If a Container specifies its own memory limit, but does not specify a memory request, Kubernetes +automatically assigns a memory request that matches the limit. Similarly, if a Container specifies its own +cpu limit, but does not specify a cpu request, Kubernetes automatically assigns a cpu request that matches +the limit. + +Delete your Pod: + +```shell +kubectl delete pod qos-demo --namespace=qos-example +``` + +## Create a Pod that gets assigned a QoS class of Burstable + +A Pod is given a QoS class of Burstable if: + +* The Pod does not meet the criteria for QoS class Guaranteed. +* At least one Container in the Pod has a memory or cpu request. + +Here is the configuration file for a Pod that has one Container. The Container has a memory limit of 200 MiB +and a memory request of 100 MiB. + +{% include code.html language="yaml" file="qos-pod-2.yaml" ghlink="/docs/tasks/configure-pod-container/qos-pod-2.yaml" %} + +Create the Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/qos-pod-2.yaml --namespace=qos-example +``` + +View detailed information about the Pod: + +```shell +kubectl get pod qos-demo-2 --namespace=qos-example --output=yaml +``` + +The output shows that Kubernetes gave the Pod a QoS class of Burstable. + +```yaml +spec: + containers: + - image: nginx + imagePullPolicy: Always + name: qos-demo-2-ctr + resources: + limits: + memory: 200Mi + requests: + memory: 100Mi +... + qosClass: Burstable +``` + +Delete your Pod: + +```shell +kubectl delete pod qos-demo-2 --namespace=qos-example +``` + +## Create a Pod that gets assigned a QoS class of BestEffort + +For a Pod to be given a QoS class of BestEffort, the Containers in the Pod must not +have any memory or cpu limits or requests. + +Here is the configuration file for a Pod that has one Container. The Container has no memory or cpu +limits or requests: + +{% include code.html language="yaml" file="qos-pod-3.yaml" ghlink="/docs/tasks/configure-pod-container/qos-pod-3.yaml" %} + +Create the Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/qos-pod-3.yaml --namespace=qos-example +``` + +View detailed information about the Pod: + +```shell +kubectl get pod qos-demo-3 --namespace=qos-example --output=yaml +``` + +The output shows that Kubernetes gave the Pod a QoS class of BestEffort. + +```yaml +spec: + containers: + ... + resources: {} + ... + qosClass: BestEffort +``` + +Delete your Pod: + +```shell +kubectl delete pod qos-demo-3 --namespace=qos-example +``` + +## Create a Pod that has two Containers + +Here is the configuration file for a Pod that has two Containers. One container specifies a memory +request of 200 MiB. The other Container does not specify any requests or limits. + +{% include code.html language="yaml" file="qos-pod-4.yaml" ghlink="/docs/tasks/configure-pod-container/qos-pod-4.yaml" %} + +Notice that this Pod meets the criteria for QoS class Burstable. That is, it does not meet the +criteria for QoS class Guaranteed, and one of its Containers has a memory request. + +Create the Pod: + +```shell +kubectl create -f https://k8s.io/docs/tasks/configure-pod-container/qos-pod-4.yaml --namespace=qos-example +``` + +View detailed information about the Pod: + +```shell +kubectl get pod qos-demo-4 --namespace=qos-example --output=yaml +``` + +The output shows that Kubernetes gave the Pod a QoS class of Burstable: + +```yaml +spec: + containers: + ... + name: qos-demo-4-ctr-1 + resources: + requests: + memory: 200Mi + ... + name: qos-demo-4-ctr-2 + resources: {} + ... + qosClass: Burstable +``` + +Delete your Pod: + +```shell +kubectl delete pod qos-demo-4 --namespace=qos-example +``` + +## Clean up + +Delete your namespace: + +```shell +kubectl delete namespace qos-example +``` + +{% endcapture %} + +{% capture whatsnext %} + + +### For app developers + +* [Assign Memory Resources to Containers and Pods](/docs/tasks/configure-pod-container/assign-memory-resource/) + +* [Assign CPU Resources to Containers and Pods](docs/tasks/configure-pod-container/assign-cpu-resource/) + +### For cluster administrators + +* [Configure Default Memory Requests and Limits for a Namespace](docs/tasks/administer-cluster/default-memory-request-limit/) + +* [Configure Default CPU Requests and Limits for a Namespace](docs/tasks/administer-cluster/default-cpu-request-limit/) + +* [Configure Minimum and Maximum Memory Constraints for a Namespace](/docs/tasks/administer-cluster/memory-constraint-namespace/) + +* [Configure Minimum and Maximum CPU Constraints for a Namespace](/docs/tasks/administer-cluster/cpu-constraint-namespace/) + +* [Configure Memory and CPU Quotas for a Namespace](/docs/tasks/administer-cluster/quota-memory-cpu-namespace/) + +* [Configure a Pod Quota for a Namespace](/docs/tasks/administer-cluster/quota-pod-namespace/) + +* [Configure Quotas for API Objects](/docs/tasks/administer-cluster/quota-api-object/) +{% endcapture %} + + +{% include templates/task.md %} + + diff --git a/docs/tasks/configure-pod-container/rq-best-effort.yaml b/docs/tasks/configure-pod-container/rq-best-effort.yaml deleted file mode 100644 index 5bd6efdcfd..0000000000 --- a/docs/tasks/configure-pod-container/rq-best-effort.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -kind: ResourceQuota -metadata: - name: best-effort -spec: - hard: - pods: "10" - scopes: - - BestEffort diff --git a/docs/tasks/configure-pod-container/rq-object-counts.yaml b/docs/tasks/configure-pod-container/rq-object-counts.yaml deleted file mode 100644 index b36f14611a..0000000000 --- a/docs/tasks/configure-pod-container/rq-object-counts.yaml +++ /dev/null @@ -1,9 +0,0 @@ -apiVersion: v1 -kind: ResourceQuota -metadata: - name: object-counts -spec: - hard: - persistentvolumeclaims: "2" - services.loadbalancers: "2" - services.nodeports: "0" \ No newline at end of file diff --git a/docs/tasks/configure-pod-container/valid-pod.yaml b/docs/tasks/configure-pod-container/valid-pod.yaml deleted file mode 100644 index c1ec54183b..0000000000 --- a/docs/tasks/configure-pod-container/valid-pod.yaml +++ /dev/null @@ -1,14 +0,0 @@ -apiVersion: v1 -kind: Pod -metadata: - name: valid-pod - labels: - name: valid-pod -spec: - containers: - - name: kubernetes-serve-hostname - image: gcr.io/google_containers/serve_hostname - resources: - limits: - cpu: "1" - memory: 512Mi diff --git a/docs/tasks/job/fine-parallel-processing-work-queue/index.md b/docs/tasks/job/fine-parallel-processing-work-queue/index.md index 660f38bcf5..a3818c89f1 100644 --- a/docs/tasks/job/fine-parallel-processing-work-queue/index.md +++ b/docs/tasks/job/fine-parallel-processing-work-queue/index.md @@ -30,7 +30,7 @@ Here is an overview of the steps in this example: ## Starting Redis -For this example, for simplicitly, we will start a single instance of Redis. +For this example, for simplicity, we will start a single instance of Redis. See the [Redis Example](https://git.k8s.io/kubernetes/examples/guestbook) for an example of deploying Redis scalably and redundantly. diff --git a/docs/tasks/manage-gpus/scheduling-gpus.md b/docs/tasks/manage-gpus/scheduling-gpus.md index 01688d763d..7ee29102ed 100644 --- a/docs/tasks/manage-gpus/scheduling-gpus.md +++ b/docs/tasks/manage-gpus/scheduling-gpus.md @@ -123,8 +123,6 @@ spec: containers: - name: gpu-container-1 image: gcr.io/google_containers/pause:2.0 - securityContext: - privileged: true resources: limits: alpha.kubernetes.io/nvidia-gpu: 1 diff --git a/docs/tasks/run-application/force-delete-stateful-set-pod.md b/docs/tasks/run-application/force-delete-stateful-set-pod.md index e8536db68e..f1988338dd 100644 --- a/docs/tasks/run-application/force-delete-stateful-set-pod.md +++ b/docs/tasks/run-application/force-delete-stateful-set-pod.md @@ -5,9 +5,6 @@ approvers: - foxish - smarterclayton title: Force Delete StatefulSet Pods -redirect:from: -- "/docs/tasks/manage-stateful-set/delete-pods/" -- "/docs/tasks/manage-stateful-set/delete-pods.html" --- {% capture overview %} @@ -28,7 +25,7 @@ This page shows how to delete Pods which are part of a stateful set, and explain In normal operation of a StatefulSet, there is **never** a need to force delete a StatefulSet Pod. The StatefulSet controller is responsible for creating, scaling and deleting members of the StatefulSet. It tries to ensure that the specified number of Pods from ordinal 0 through N-1 are alive and ready. StatefulSet ensures that, at any time, there is at most one Pod with a given identity running in a cluster. This is referred to as *at most one* semantics provided by a StatefulSet. -Manual force deletion should be undertaken with caution, as it has the potential to violate the at most one semantics inherent to StatefulSet. StatefulSets may be used to run distributed and clustered applications which have a need for a stable network identity and stable storage. These applications often have configuration which relies on an ensemble of a fixed number of members with fixed identities. Having multiple members with the same identity can be disastrous and may lead to data loss (e.g. split brain scenario in quorum-based systems). +Manual force deletion should be undertaken with caution, as it has the potential to violate the at most one semantics inherent to StatefulSet. StatefulSets may be used to run distributed and clustered applications which have a need for a stable network identity and stable storage. These applications often have configuration which relies on an ensemble of a fixed number of members with fixed identities. Having multiple members with the same identity can be disastrous and may lead to data loss (e.g. split brain scenario in quorum-based systems). ## Delete Pods @@ -38,14 +35,14 @@ You can perform a graceful pod deletion with the following command: kubectl delete pods ``` -For the above to lead to graceful termination, the Pod **must not** specify a `pod.Spec.TerminationGracePeriodSeconds` of 0. The practice of setting a `pod.Spec.TerminationGracePeriodSeconds` of 0 seconds is unsafe and strongly discouraged for StatefulSet Pods. Graceful deletion is safe and will ensure that the [Pod shuts down gracefully](/docs/user-guide/pods/#termination-of-pods) before the kubelet deletes the name from the apiserver. +For the above to lead to graceful termination, the Pod **must not** specify a `pod.Spec.TerminationGracePeriodSeconds` of 0. The practice of setting a `pod.Spec.TerminationGracePeriodSeconds` of 0 seconds is unsafe and strongly discouraged for StatefulSet Pods. Graceful deletion is safe and will ensure that the [Pod shuts down gracefully](/docs/user-guide/pods/#termination-of-pods) before the kubelet deletes the name from the apiserver. Kubernetes (versions 1.5 or newer) will not delete Pods just because a Node is unreachable. The Pods running on an unreachable Node enter the 'Terminating' or 'Unknown' state after a [timeout](/docs/admin/node/#node-condition). Pods may also enter these states when the user attempts graceful deletion of a Pod on an unreachable Node. The only ways in which a Pod in such a state can be removed from the apiserver are as follows: * The Node object is deleted (either by you, or by the [Node Controller](/docs/admin/node)). - * The kubelet on the unresponsive Node starts responding, kills the Pod and removes the entry from the apiserver. + * The kubelet on the unresponsive Node starts responding, kills the Pod and removes the entry from the apiserver. * Force deletion of the Pod by the user. - -The recommended best practice is to use the first or second approach. If a Node is confirmed to be dead (e.g. permanently disconnected from the network, powered down, etc), then delete the node object. If the node is suffering from a network partition, then try to resolve this or wait for it to resolve. When the partition heals, the kubelet will complete the deletion of the Pod and free up its name in the apiserver. + +The recommended best practice is to use the first or second approach. If a Node is confirmed to be dead (e.g. permanently disconnected from the network, powered down, etc), then delete the node object. If the node is suffering from a network partition, then try to resolve this or wait for it to resolve. When the partition heals, the kubelet will complete the deletion of the Pod and free up its name in the apiserver. Normally, the system completes the deletion once the Pod is no longer running on a Node, or the Node is deleted by an administrator. You may override this by force deleting the Pod. @@ -53,7 +50,7 @@ Normally, the system completes the deletion once the Pod is no longer running on Force deletions **do not** wait for confirmation from the kubelet that the Pod has been terminated. Irrespective of whether a force deletion is successful in killing a Pod, it will immediately free up the name from the apiserver. This would let the StatefulSet controller create a replacement Pod with that same identity; this can lead to the duplication of a still-running Pod, and if said Pod can still communicate with the other members of the StatefulSet, will violate the at most one semantics that StatefulSet is designed to guarantee. -When you force delete a StatefulSet pod, you are asserting that the Pod in question will never again make contact with other Pods in the StatefulSet and its name can be safely freed up for a replacement to be created. +When you force delete a StatefulSet pod, you are asserting that the Pod in question will never again make contact with other Pods in the StatefulSet and its name can be safely freed up for a replacement to be created. If you want to delete a Pod forcibly using kubectl version >= 1.5, do the following: @@ -73,7 +70,7 @@ Always perform force deletion of StatefulSet Pods carefully and with complete kn {% capture whatsnext %} -Learn more about [debugging a StatefulSet](/docs/tasks/manage-stateful-set/debugging-a-statefulset/). +Learn more about [debugging a StatefulSet](/docs/tasks/manage-stateful-set/debugging-a-statefulset/). {% endcapture %} diff --git a/docs/tasks/tls/managing-tls-in-a-cluster.md b/docs/tasks/tls/managing-tls-in-a-cluster.md index ce149f5735..bae41b6c90 100644 --- a/docs/tasks/tls/managing-tls-in-a-cluster.md +++ b/docs/tasks/tls/managing-tls-in-a-cluster.md @@ -191,7 +191,7 @@ the CSR and otherwise should deny the CSR. The ability to approve CSRs decides who trusts who within the cluster. This includes who the Kubernetes API trusts. The ability to approve CSRs should not be granted broadly or lightly. The requirements of the challenge -noted in the previous section and the reprecussions of issuing a specific +noted in the previous section and the repercussions of issuing a specific certificate should be fully understood before granting this permission. See [here](/docs/admin/authentication#x509-client-certs) for information on how certificates interact with authentication. diff --git a/docs/tutorials/stateless-application/guestbook.md b/docs/tutorials/stateless-application/guestbook.md index 42775d131d..db3da76fbd 100644 --- a/docs/tutorials/stateless-application/guestbook.md +++ b/docs/tutorials/stateless-application/guestbook.md @@ -39,701 +39,299 @@ import it to the website. --> -This example shows how to build a simple, multi-tier web application using Kubernetes and [Docker](https://www.docker.com/). +{% capture overview %} +This tutorial shows you how to build and deploy a simple, multi-tier web application using Kubernetes and [Docker](https://www.docker.com/). This example consists of the following components: -**Table of Contents** - +* A single-instance [Redis](https://redis.io/) master to store guestbook entries +* Multiple replicated Redis instances to serve reads +* Multiple web frontend instances - - [Guestbook Example](#guestbook-example) - - [Prerequisites](#prerequisites) - - [Quick Start](#quick-start) - - [Step One: Start up the redis master](#step-one-start-up-the-redis-master) - - [Define a Deployment](#define-a-deployment) - - [Define a Service](#define-a-service) - - [Create a Service](#create-a-service) - - [Finding a Service](#finding-a-service) - - [Environment variables](#environment-variables) - - [DNS service](#dns-service) - - [Create a Deployment](#create-a-deployment) - - [Optional Interlude](#optional-interlude) - - [Step Two: Start up the redis slave](#step-two-start-up-the-redis-slave) - - [Step Three: Start up the guestbook frontend](#step-three-start-up-the-guestbook-frontend) - - [Using 'type: LoadBalancer' for the frontend service (cloud-provider-specific)](#using-type-loadbalancer-for-the-frontend-service-cloud-provider-specific) - - [Step Four: Cleanup](#step-four-cleanup) - - [Troubleshooting](#troubleshooting) - - [Appendix: Accessing the guestbook site externally](#appendix-accessing-the-guestbook-site-externally) - - [Google Compute Engine External Load Balancer Specifics](#google-compute-engine-external-load-balancer-specifics) +{% endcapture %} - +{% capture objectives %} +* Start up a Redis master. +* Start up Redis slaves. +* Start up the guestbook frontend. +* Expose and view the Frontend Service. +* Clean up. +{% endcapture %} -The example consists of: +{% capture prerequisites %} -- A web frontend -- A [redis](http://redis.io/) master (for storage), and a replicated set of redis 'slaves'. +{% include task-tutorial-prereqs.md %} +Download the following configuration files: -The web frontend interacts with the redis master via javascript redis API calls. +1. [redis-master-deployment.yaml](https://kubernetes.io/docs/tutorials/docs/tutorials/stateless-application/redis-master-deployment.yaml) +1. [redis-master-service.yaml](https://kubernetes.io/docs/tutorials/docs/tutorials/stateless-application/redis-master-service.yaml) +1. [redis-slave-deployment.yaml](https://kubernetes.io/docs/tutorials/docs/tutorials/stateless-application/redis-slave-deployment.yaml) +1. [redis-slave-service.yaml](https://kubernetes.io/docs/tutorials/docs/tutorials/stateless-application/redis-slave-service.yaml) +1. [frontend-deployment.yaml](https://kubernetes.io/docs/tutorials/docs/tutorials/stateless-application/frontend-deployment.yaml) +1. [frontend-service.yaml](https://kubernetes.io/docs/tutorials/docs/tutorials/stateless-application/frontend-service.yaml) -**Note**: If you are running this example on a [Google Container Engine](https://cloud.google.com/container-engine/) installation, see [this Google Container Engine guestbook walkthrough](https://cloud.google.com/container-engine/docs/tutorials/guestbook) instead. The basic concepts are the same, but the walkthrough is tailored to a Container Engine setup. +{% endcapture %} -### Prerequisites +{% capture lessoncontent %} -This example requires a running Kubernetes cluster. First, check that kubectl is properly configured by getting the cluster state: - -```console -$ kubectl cluster-info -``` - -If you see a url response, you are ready to go. If not, read the [Getting Started guides](http://kubernetes.io/docs/getting-started-guides/) for how to get started, and follow the [prerequisites](http://kubernetes.io/docs/user-guide/prereqs/) to install and configure `kubectl`. As noted above, if you have a Google Container Engine cluster set up, read [this example](https://cloud.google.com/container-engine/docs/tutorials/guestbook) instead. - -All the files referenced in this example can be downloaded [from GitHub](https://git.k8s.io/examples/guestbook). - -### Quick Start - -This section shows the simplest way to get the example work. If you want to know the details, you should skip this and read [the rest of the example](#step-one-start-up-the-redis-master). - -Start the guestbook with one command: - -```console -$ kubectl create -f guestbook/all-in-one/guestbook-all-in-one.yaml -service "redis-master" created -deployment "redis-master" created -service "redis-slave" created -deployment "redis-slave" created -service "frontend" created -deployment "frontend" created -``` +## Start up the Redis Master -Alternatively, you can start the guestbook by running: +The guestbook application uses Redis to store its data. It writes its data to a Redis master instance and reads data from multiple Redis slave instances. -```console -$ kubectl create -f guestbook/ -``` - -Then, list all your Services: - -```console -$ kubectl get services -NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE -frontend 10.0.0.117 80/TCP 20s -redis-master 10.0.0.170 6379/TCP 20s -redis-slave 10.0.0.201 6379/TCP 20s -``` - -Now you can access the guestbook on each node with frontend Service's `:`, e.g. `10.0.0.117:80` in this guide. `` is a cluster-internal IP. If you want to access the guestbook from outside of the cluster, add `type: NodePort` to the frontend Service `spec` field. Then you can access the guestbook with `:NodePort` from outside of the cluster. On cloud providers which support external load balancers, adding `type: LoadBalancer` to the frontend Service `spec` field will provision a load balancer for your Service. There are several ways for you to access the guestbook. You may learn from [Accessing services running on the cluster](https://kubernetes.io/docs/concepts/cluster-administration/access-cluster/#accessing-services-running-on-the-cluster). - -Clean up the guestbook: - -```console -$ kubectl delete -f guestbook/all-in-one/guestbook-all-in-one.yaml -``` - -or - -```console -$ kubectl delete -f guestbook/ -``` - - -### Step One: Start up the redis master - -Before continuing to the gory details, we also recommend you to read Kubernetes [concepts and user guide](http://kubernetes.io/docs/user-guide/). -**Note**: The redis master in this example is *not* highly available. Making it highly available would be an interesting, but intricate exercise — redis doesn't actually support multi-master Deployments at this point in time, so high availability would be a somewhat tricky thing to implement, and might involve periodic serialization to disk, and so on. - -#### Define a Deployment - -To start the redis master, use the file [redis-master-deployment.yaml](https://git.k8s.io/examples/guestbook/redis-master-deployment.yaml), which describes a single [pod](http://kubernetes.io/docs/user-guide/pods/) running a redis key-value server in a container. - -Although we have a single instance of our redis master, we are using a [Deployment](http://kubernetes.io/docs/user-guide/deployments/) to enforce that exactly one pod keeps running. E.g., if the node were to go down, the Deployment will ensure that the redis master gets restarted on a healthy node. (In our simplified example, this could result in data loss.) - -The file [redis-master-deployment.yaml](https://git.k8s.io/examples/guestbook/redis-master-deployment.yaml) defines the redis master Deployment: - - - -```yaml -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: redis-master - # these labels can be applied automatically - # from the labels in the pod template if not set - # labels: - # app: redis - # role: master - # tier: backend -spec: - # this replicas value is default - # modify it according to your case - replicas: 1 - # selector can be applied automatically - # from the labels in the pod template if not set - # selector: - # matchLabels: - # app: guestbook - # role: master - # tier: backend - template: - metadata: - labels: - app: redis - role: master - tier: backend - spec: - containers: - - name: master - image: gcr.io/google_containers/redis:e2e - resources: - requests: - cpu: 100m - memory: 100Mi - ports: - - containerPort: 6379 -``` +### Creating the Redis Master Deployment -[Download example](https://raw.githubusercontent.com/kubernetes/examples/master/guestbook/redis-master-deployment.yaml) - +The manifest file, included below, specifies a Deployment controller that runs a single replica Redis master Pod. -#### Define a Service +1. Launch a terminal window in the directory you downloaded the manifest files. +2. Apply the Redis Master Deployment from the `redis-master-deployment.yaml` file: -A Kubernetes [Service](http://kubernetes.io/docs/user-guide/services/) is a named load balancer that proxies traffic to one or more containers. This is done using the [labels](http://kubernetes.io/docs/user-guide/labels/) metadata that we defined in the `redis-master` pod above. As mentioned, we have only one redis master, but we nevertheless want to create a Service for it. Why? Because it gives us a deterministic way to route to the single master using an elastic IP. + kubectl apply -f redis-master-deployment.yaml + + {% include code.html language="yaml" file="guestbook/redis-master-deployment.yaml" ghlink="/docs/tutorials/stateless-application/guestbook/redis-master-deployment.yaml" %} -Services find the pods to load balance based on the pods' labels. -The selector field of the Service description determines which pods will receive the traffic sent to the Service, and the `port` and `targetPort` information defines what port the Service proxy will run at. +3. Query the list of Pods to verify that the Redis Master Pod is running: -The file [redis-master-service.yaml](https://git.k8s.io/examples/guestbook/redis-master-service.yaml) defines the redis master Service: + kubectl get pods - + The response should be similar to this: -```yaml -apiVersion: v1 -kind: Service -metadata: - name: redis-master - labels: - app: redis - role: master - tier: backend -spec: - ports: - # the port that this service should serve on - - port: 6379 - targetPort: 6379 - selector: - app: redis - role: master - tier: backend -``` + NAME READY STATUS RESTARTS AGE + redis-master-1068406935-3lswp 1/1 Running 0 28s -[Download example](https://raw.githubusercontent.com/kubernetes/examples/master/guestbook/redis-master-service.yaml) - +4. Run the following command to view the logs from the Redis Master Pod: -#### Create a Service + kubectl logs -f POD-NAME -According to the [config best practices](http://kubernetes.io/docs/user-guide/config-best-practices/), create a Service before corresponding Deployments so that the scheduler can spread the pods comprising the Service. So we first create the Service by running: +**Note:** Replace POD-NAME with the name of your Pod. +{: .note} -```console -$ kubectl create -f guestbook/redis-master-service.yaml -service "redis-master" created -``` +### Creating the Redis Master Service -Then check the list of services, which should include the redis-master: - -```console -$ kubectl get services -NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE -redis-master 10.0.76.248 6379/TCP 1s -``` - -This will cause all pods to see the redis master apparently running on `:`. A Service can map an incoming port to any `targetPort` in the backend pod. Once created, the Service proxy on each node is configured to set up a proxy on the specified port (in this case port `6379`). - -`targetPort` will default to `port` if it is omitted in the configuration. `targetPort` is the port the container accepts traffic on, and `port` is the abstracted Service port, which can be any port other pods use to access the Service. For simplicity's sake, we omit it in the following configurations. - -The traffic flow from slaves to masters can be described in two steps: - - - A *redis slave* will connect to `port` on the *redis master Service* - - Traffic will be forwarded from the Service `port` (on the Service node) to the `targetPort` on the pod that the Service listens to. - -For more details, please see [Connecting applications](http://kubernetes.io/docs/user-guide/connecting-applications/). - -#### Finding a Service - -Kubernetes supports two primary modes of finding a Service — environment variables and DNS. +The guestbook applications needs to communicate to the Redis master to write its data. You need to apply a [Service](https://kubernetes.io/docs/concepts/services-networking/service/) to proxy the traffic to the Redis master Pod. A Service defines a policy to access the Pods. +1. Apply the Redis Master Service from the following `redis-master-service.yaml` file: -##### Environment variables + kubectl apply -f redis-master-service.yaml -The services in a Kubernetes cluster are discoverable inside other containers via [environment variables](https://kubernetes.io/docs/concepts/services-networking/service/#environment-variables). + {% include code.html language="yaml" file="guestbook/redis-master-service.yaml" ghlink="/docs/tutorials/stateless-application/guestbook/redis-master-service.yaml" %} -##### DNS service +**Note:** This manifest file creates a Service named `redis-master` with a set of labels that match the labels previously defined, so the Service routes network traffic to the Redis master Pod. +{: .note} -An alternative is to use the [cluster's DNS service](https://kubernetes.io/docs/concepts/services-networking/service/#dns), if it has been enabled for the cluster. This lets all pods do name resolution of services automatically, based on the Service name. +2. Query the list of Services to verify that the Redis Master Service is running: -This example has been configured to use the DNS service by default. + kubectl get service -If your cluster does not have the DNS service enabled, then you can use environment variables by setting the -`GET_HOSTS_FROM` env value in both -[redis-slave-deployment.yaml](https://git.k8s.io/examples/guestbook/redis-slave-deployment.yaml) and [frontend-deployment.yaml](https://git.k8s.io/examples/guestbook/frontend-deployment.yaml) -from `dns` to `env` before you start up the app. -(However, this is unlikely to be necessary. You can check for the DNS service in the list of the cluster's services by -running `kubectl --namespace=kube-system get rc -l k8s-app=kube-dns`.) -Note that switching to env causes creation-order dependencies, since Services need to be created before their clients that require env vars. + The response should be similar to this: -#### Create a Deployment + NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE + kubernetes 10.0.0.1 443/TCP 1m + redis-master 10.0.0.151 6379/TCP 8s -Second, create the redis master pod in your Kubernetes cluster by running: +## Start up the Redis Slaves -```console -$ kubectl create -f guestbook/redis-master-deployment.yaml -deployment "redis-master" created -``` +Although the Redis master is a single pod, you can make it highly available to meet traffic demands by adding replica Redis slaves. -You can see the Deployment for your cluster by running: +### Creating the Redis Slave Deployment -```console -$ kubectl get deployments -NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE -redis-master 1 1 1 1 27s -``` +Deployments scale based off of the configurations set in the manifest file. In this case, the Deployment object specifies two replicas. -Then, you can list the pods in the cluster, to verify that the master is running: +If there are not any replicas running, this Deployment would start the two replicas on your container cluster. Conversely, if there are more than two replicas are running, it would scale down until two replicas are running. -```console -$ kubectl get pods -``` +1. Apply the Redis Slave Deployment from the `redis-slave-deployment.yaml` file: -You'll see all pods in the cluster, including the redis master pod, and the status of each pod. -The name of the redis master will look similar to that in the following list: + kubectl apply -f redis-slave-deployment.yaml -```console -NAME READY STATUS RESTARTS AGE -redis-master-2353460263-1ecey 1/1 Running 0 1m -... -``` + {% include code.html language="yaml" file="guestbook/redis-slave-deployment.yaml" ghlink="/docs/tutorials/stateless-application/guestbook/redis-slave-deployment.yaml" %} -(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.) +2. Query the list of Pods to verify that the Redis Slave Pods are running: -`kubectl get pods` will show only the pods in the default [namespace](http://kubernetes.io/docs/user-guide/namespaces/). To see pods in all namespaces, run: + kubectl get pods -``` -kubectl get pods --all-namespaces -``` + The response should be similar to this: -For more details, please see [Configuring containers](http://kubernetes.io/docs/user-guide/configuring-containers/) and [Deploying applications](http://kubernetes.io/docs/user-guide/deploying-applications/). + NAME READY STATUS RESTARTS AGE + redis-master-1068406935-3lswp 1/1 Running 0 1m + redis-slave-2005841000-fpvqc 0/1 ContainerCreating 0 6s + redis-slave-2005841000-phfv9 0/1 ContainerCreating 0 6s + +### Creating the Redis Slave Service -#### Optional Interlude +The guestbook application needs to communicate to Redis slaves to read data. To make the Redis slaves discoverable, you need to set up a Service. A Service provides transparent load balancing to a set of Pods. -You can get information about a pod, including the machine that it is running on, via `kubectl describe pods/`. E.g., for the redis master, you should see something like the following (your pod name will be different): +1. Apply the Redis Slave Service from the following `redis-slave-service.yaml` file: -```console -$ kubectl describe pods redis-master-2353460263-1ecey -Name: redis-master-2353460263-1ecey -Node: kubernetes-node-m0k7/10.240.0.5 -... -Labels: app=redis,pod-template-hash=2353460263,role=master,tier=backend -Status: Running -IP: 10.244.2.3 -Controllers: ReplicaSet/redis-master-2353460263 -Containers: - master: - Container ID: docker://76cf8115485966131587958ea3cbe363e2e1dcce129e2e624883f393ce256f6c - Image: gcr.io/google_containers/redis:e2e - Image ID: docker://e5f6c5a2b5646828f51e8e0d30a2987df7e8183ab2c3ed0ca19eaa03cc5db08c - Port: 6379/TCP -... -``` - -The `Node` is the name and IP of the machine, e.g. `kubernetes-node-m0k7` in the example above. You can find more details about this node with `kubectl describe nodes kubernetes-node-m0k7`. - -If you want to view the container logs for a given pod, you can run: - -```console -$ kubectl logs -``` - -These logs will usually give you enough information to troubleshoot. - -However, if you should want to SSH to the listed host machine, you can inspect various logs there directly as well. For example, with Google Compute Engine, using `gcloud`, you can SSH like this: - -```console -me@workstation$ gcloud compute ssh -``` - -Then, you can look at the Docker containers on the remote machine. You should see something like this (the specifics of the IDs will be different): - -```console -me@kubernetes-node-krxw:~$ sudo docker ps -CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES -... -0ffef9649265 redis:latest "/entrypoint.sh redi" About a minute ago Up About a minute k8s_master.869d22f3_redis-master-dz33o_default_1449a58a-5ead-11e5-a104-688f84ef8ef6_d74cb2b5 -``` - -If you want to see the logs for a given container, you can run: - -```console -$ docker logs -``` - -### Step Two: Start up the redis slave - -Now that the redis master is running, we can start up its 'read slaves'. - -We'll define these as replicated pods as well, though this time — unlike for the redis master — we'll define the number of replicas to be 2. -In Kubernetes, a Deployment is responsible for managing multiple instances of a replicated pod. The Deployment will automatically launch new pods if the number of replicas falls below the specified number. -(This particular replicated pod is a great one to test this with -- you can try killing the Docker processes for your pods directly, then watch them come back online on a new node shortly thereafter.) - -Just like the master, we want to have a Service to proxy connections to the redis slaves. In this case, in addition to discovery, the slave Service will provide transparent load balancing to web app clients. - -This time we put the Service and Deployment into one [file](http://kubernetes.io/docs/user-guide/managing-deployments/#organizing-resource-configurations). Grouping related objects together in a single file is often better than having separate files. -The specification for the slaves is in [all-in-one/redis-slave.yaml](https://git.k8s.io/examples/guestbook/all-in-one/redis-slave.yaml): - - - -```yaml -apiVersion: v1 -kind: Service -metadata: - name: redis-slave - labels: - app: redis - role: slave - tier: backend -spec: - ports: - # the port that this service should serve on - - port: 6379 - selector: - app: redis - role: slave - tier: backend ---- -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: redis-slave - # these labels can be applied automatically - # from the labels in the pod template if not set - # labels: - # app: redis - # role: slave - # tier: backend -spec: - # this replicas value is default - # modify it according to your case - replicas: 2 - # selector can be applied automatically - # from the labels in the pod template if not set - # selector: - # matchLabels: - # app: guestbook - # role: slave - # tier: backend - template: - metadata: - labels: - app: redis - role: slave - tier: backend - spec: - containers: - - name: slave - image: gcr.io/google_samples/gb-redisslave:v1 - resources: - requests: - cpu: 100m - memory: 100Mi - env: - - name: GET_HOSTS_FROM - value: dns - # If your cluster config does not include a dns service, then to - # instead access an environment variable to find the master - # service's host, comment out the 'value: dns' line above, and - # uncomment the line below. - # value: env - ports: - - containerPort: 6379 -``` - -[Download example](https://raw.githubusercontent.com/kubernetes/examples/master/guestbook/all-in-one/redis-slave.yaml) - - -This time the selector for the Service is `app=redis,role=slave,tier=backend`, because that identifies the pods running redis slaves. It is generally helpful to set labels on your Service itself as we've done here to make it easy to locate them with the `kubectl get services -l "app=redis,role=slave,tier=backend"` command. For more information on the usage of labels, see [using-labels-effectively](http://kubernetes.io/docs/user-guide/managing-deployments/#using-labels-effectively). - -Now that you have created the specification, create the Service in your cluster by running: - -```console -$ kubectl create -f guestbook/all-in-one/redis-slave.yaml -service "redis-slave" created -deployment "redis-slave" created - -$ kubectl get services -NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE -redis-master 10.0.76.248 6379/TCP 20m -redis-slave 10.0.112.188 6379/TCP 16s - -$ kubectl get deployments -NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE -redis-master 1 1 1 1 22m -redis-slave 2 2 2 2 2m -``` - -Once the Deployment is up, you can list the pods in the cluster, to verify that the master and slaves are running. You should see a list that includes something like the following: - -```console -$ kubectl get pods -NAME READY STATUS RESTARTS AGE -redis-master-2353460263-1ecey 1/1 Running 0 35m -redis-slave-1691881626-dlf5f 1/1 Running 0 15m -redis-slave-1691881626-sfn8t 1/1 Running 0 15m -``` - -You should see a single redis master pod and two redis slave pods. As mentioned above, you can get more information about any pod with: `kubectl describe pods/`. And also can view the resources on [kube-ui](http://kubernetes.io/docs/user-guide/ui/). - -### Step Three: Start up the guestbook frontend - -A frontend pod is a simple PHP server that is configured to talk to either the slave or master services, depending on whether the client request is a read or a write. It exposes a simple AJAX interface, and serves an Angular-based UX. -Again we'll create a set of replicated frontend pods instantiated by a Deployment — this time, with three replicas. - -As with the other pods, we now want to create a Service to group the frontend pods. -The Deployment and Service are described in the file [all-in-one/frontend.yaml](https://git.k8s.io/examples/guestbook/all-in-one/frontend.yaml): - - - -```yaml -apiVersion: v1 -kind: Service -metadata: - name: frontend - labels: - app: guestbook - tier: frontend -spec: - # if your cluster supports it, uncomment the following to automatically create - # an external load-balanced IP for the frontend service. - # type: LoadBalancer - ports: - # the port that this service should serve on - - port: 80 - selector: - app: guestbook - tier: frontend ---- -apiVersion: extensions/v1beta1 -kind: Deployment -metadata: - name: frontend - # these labels can be applied automatically - # from the labels in the pod template if not set - # labels: - # app: guestbook - # tier: frontend -spec: - # this replicas value is default - # modify it according to your case - replicas: 3 - # selector can be applied automatically - # from the labels in the pod template if not set - # selector: - # matchLabels: - # app: guestbook - # tier: frontend - template: - metadata: - labels: - app: guestbook - tier: frontend - spec: - containers: - - name: php-redis - image: gcr.io/google-samples/gb-frontend:v4 - resources: - requests: - cpu: 100m - memory: 100Mi - env: - - name: GET_HOSTS_FROM - value: dns - # If your cluster config does not include a dns service, then to - # instead access environment variables to find service host - # info, comment out the 'value: dns' line above, and uncomment the - # line below. - # value: env - ports: - - containerPort: 80 -``` - -[Download example](https://raw.githubusercontent.com/kubernetes/examples/master/guestbook/all-in-one/frontend.yaml) - - -#### Using 'type: LoadBalancer' for the frontend service (cloud-provider-specific) - -For supported cloud providers, such as Google Compute Engine or Google Container Engine, you can specify to use an external load balancer -in the service `spec`, to expose the service onto an external load balancer IP. -To do this, uncomment the `type: LoadBalancer` line in the [all-in-one/frontend.yaml](https://git.k8s.io/examples/guestbook/all-in-one/frontend.yaml) file before you start the service. - -[See the appendix below](#appendix-accessing-the-guestbook-site-externally) on accessing the guestbook site externally for more details. - -Create the service and Deployment like this: - -```console -$ kubectl create -f guestbook/all-in-one/frontend.yaml -service "frontend" created -deployment "frontend" created -``` - -Then, list all your services again: - -```console -$ kubectl get services -NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE -frontend 10.0.63.63 80/TCP 1m -redis-master 10.0.76.248 6379/TCP 39m -redis-slave 10.0.112.188 6379/TCP 19m -``` - -Also list all your Deployments: - -```console -$ kubectl get deployments -NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE -frontend 3 3 3 3 2m -redis-master 1 1 1 1 39m -redis-slave 2 2 2 2 20m -``` - -Once it's up, i.e. when desired replicas match current replicas (again, it may take up to thirty seconds to create the pods), you can list the pods with specified labels in the cluster, to verify that the master, slaves and frontends are all running. You should see a list containing pods with label 'tier' like the following: - -```console -$ kubectl get pods -L tier -NAME READY STATUS RESTARTS AGE TIER -frontend-1211764471-4e1j2 1/1 Running 0 4m frontend -frontend-1211764471-gkbkv 1/1 Running 0 4m frontend -frontend-1211764471-rk1cf 1/1 Running 0 4m frontend -redis-master-2353460263-1ecey 1/1 Running 0 42m backend -redis-slave-1691881626-dlf5f 1/1 Running 0 22m backend -redis-slave-1691881626-sfn8t 1/1 Running 0 22m backend -``` - -You should see a single redis master pod, two redis slaves, and three frontend pods. - -The code for the PHP server that the frontends are running is in `examples/guestbook/php-redis/guestbook.php`. It looks like this: - -```php - 'tcp', - 'host' => $host, - 'port' => 6379, - ]); + kubectl apply -f redis-slave-service.yaml - $client->set($_GET['key'], $_GET['value']); - print('{"message": "Updated"}'); - } else { - $host = 'redis-slave'; - if (getenv('GET_HOSTS_FROM') == 'env') { - $host = getenv('REDIS_SLAVE_SERVICE_HOST'); - } - $client = new Predis\Client([ - 'scheme' => 'tcp', - 'host' => $host, - 'port' => 6379, - ]); + {% include code.html language="yaml" file="guestbook/redis-slave-service.yaml" ghlink="/docs/tutorials/stateless-application/guestbook/redis-slave-service.yaml" %} - $value = $client->get($_GET['key']); - print('{"data": "' . $value . '"}'); - } -} else { - phpinfo(); -} ?> -``` +2. Query the list of Services to verify that the Redis Slave Service is running: -Note the use of the `redis-master` and `redis-slave` host names -- we're finding those Services via the Kubernetes cluster's DNS service, as discussed above. All the frontend replicas will write to the load-balancing redis-slaves service, which can be highly replicated as well. + kubectl get services -### Step Four: Cleanup + The response should be similar to this: -If you are in a live Kubernetes cluster, you can just kill the pods by deleting the Deployments and Services. Using labels to select the resources to delete is an easy way to do this in one command. + NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE + kubernetes 10.0.0.1 443/TCP 2m + redis-master 10.0.0.151 6379/TCP 1m + redis-slave 10.0.0.223 6379/TCP 6s -```console -$ kubectl delete deployments,services -l "app in (redis, guestbook)" -``` +## Set up and Expose the Guestbook Frontend -To completely tear down a Kubernetes cluster, if you ran this from source, you can use: +The guestbook application has a web frontend serving the HTTP requests written in PHP. It is configured to connect to the `redis-master` Service for write requests and the `redis-slave` service for Read requests. -```console -$ /cluster/kube-down.sh -``` +### Creating the Guestbook Frontend Deployment -### Troubleshooting +1. Apply the frontend Deployment from the following `frontend-deployment.yaml` file: -If you are having trouble bringing up your guestbook app, double check that your external IP is properly defined for your frontend Service, and that the firewall for your cluster nodes is open to port 80. + kubectl apply -f frontend-deployment.yaml -Then, see the [troubleshooting documentation](http://kubernetes.io/docs/troubleshooting/) for a further list of common issues and how you can diagnose them. + {% include code.html language="yaml" file="guestbook/frontend-deployment.yaml" ghlink="/docs/tutorials/stateless-application/guestbook/frontend-deployment.yaml" %} +2. Query the list of Pods to verify that the three frontend replicas are running: + kubectl get pods -l app=guestbook -l tier=frontend -### Appendix: Accessing the guestbook site externally + The response should be similar to this: -You'll want to set up your guestbook Service so that it can be accessed from outside of the internal Kubernetes network. Above, we introduced one way to do that, by setting `type: LoadBalancer` to Service `spec`. + NAME READY STATUS RESTARTS AGE + frontend-3823415956-dsvc5 1/1 Running 0 54s + frontend-3823415956-k22zn 1/1 Running 0 54s + frontend-3823415956-w9gbt 1/1 Running 0 54s -More generally, Kubernetes supports two ways of exposing a Service onto an external IP address: `NodePort`s and `LoadBalancer`s , as described [here](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services---service-types). +### Creating the Frontend Service -If the `LoadBalancer` specification is used, it can take a short period for an external IP to show up in `kubectl get services` output, but you should then see it listed as well, e.g. like this: +The `redis-slave` and `redis-master` Services you applied are only accessible within the container cluster because the default type for a Service is [ClusterIP](https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services---service-types). `ClusterIP` provides a single IP address for the set of Pods the Service is pointing to. This IP address is accessible only within the cluster. -```console -$ kubectl get services -NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE -frontend 10.0.63.63 23.236.59.54 80/TCP 1m -redis-master 10.0.76.248 6379/TCP 39m -redis-slave 10.0.112.188 6379/TCP 19m -``` +If you want guests to be able to access your guestbook, you must configure the frontend Service to be externally visible, so a client can request the Service from outside the container cluster. Minikube can only expose Services through `NodePort`. -Once you've exposed the service to an external IP, visit the IP to see your guestbook in action, i.e. `http://:`. +**Note:** Some cloud providers, like Google Compute Engine or Google Container Engine, support external load balancers. If your cloud provider supports load balancers and you want to use it, simply delete or comment out `type: NodePort`, and uncomment `type: LoadBalancer`. +{: .note} -You should see a web page that looks something like this (without the messages). Try adding some entries to it! +1. Apply the frontend Service from the following `frontend-service.yaml` file: - + kubectl apply -f frontend-service.yaml + + {% include code.html language="yaml" file="guestbook/frontend-service.yaml" ghlink="/docs/tutorials/stateless-application/guestbook/frontend-service.yaml" %} -If you are more advanced in the ops arena, you can also manually get the service IP from looking at the output of `kubectl get pods,services`, and modify your firewall using standard tools and services (firewalld, iptables, selinux) which you are already familiar with. +2. Query the list of Services to verify that the frontend Service is running: -#### Google Compute Engine External Load Balancer Specifics + kubectl get services -In Google Compute Engine, Kubernetes automatically creates forwarding rules for services with `LoadBalancer`. + The response should be similar to this: -You can list the forwarding rules like this (the forwarding rule also indicates the external IP): + NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE + frontend 10.0.0.112 80:31323/TCP 6s + kubernetes 10.0.0.1 443/TCP 4m + redis-master 10.0.0.151 6379/TCP 2m + redis-slave 10.0.0.223 6379/TCP 1m -```console -$ gcloud compute forwarding-rules list -NAME REGION IP_ADDRESS IP_PROTOCOL TARGET -frontend us-central1 130.211.188.51 TCP us-central1/targetPools/frontend -``` +### Viewing the Frontend Service via `NodePort` -In Google Compute Engine, you also may need to open the firewall for port 80 using the [console][cloud-console] or the `gcloud` tool. The following command will allow traffic from any source to instances tagged `kubernetes-node` (replace with your tags as appropriate): +If you deployed this application to Minikube or a local cluster, you need to find the IP address to view your Guestbook. -```console -$ gcloud compute firewall-rules create --allow=tcp:80 --target-tags=kubernetes-node kubernetes-node-80 -``` +1. Run the following command to get the IP address for the frontend Service. -For GCE Kubernetes startup details, see the [Getting started on Google Compute Engine](http://kubernetes.io/docs/getting-started-guides/gce/) + minikube service frontend --url -For Google Compute Engine details about limiting traffic to specific sources, see the [Google Compute Engine firewall documentation][gce-firewall-docs]. + The response should be similar to this: -[cloud-console]: https://console.developer.google.com -[gce-firewall-docs]: https://cloud.google.com/compute/docs/networking#firewalls + http://192.168.99.100:31323 + +2. Copy the IP address, and load the page in your browser to view your guestbook. + +### Viewing the Frontend Service via `LoadBalancer` + +If you deployed the `frontend-service.yaml` manifest with type: `LoadBalancer` you need to find the IP address to view your Guestbook. + +1. Run the following command to get the IP address for the frontend Service. + + kubectl get service frontend + + The response should be similar to this: + + NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE + frontend 10.51.242.136 109.197.92.229 80:32372/TCP 1m + +2. Copy the External IP address, and load the page in your browser to view your guestbook. + +## Scale the Web Frontend + +Scaling up or down is easy because your servers are defined as a Service that uses a Deployment controller. + +1. Run the following command to scale up the number of frontend Pods: + + kubectl scale deployment frontend --replicas=5 + +2. Query the list of Pods to verify the number of frontend Pods running: + + kubectl get pods + + The response should look similar to this: + + NAME READY STATUS RESTARTS AGE + frontend-3823415956-70qj5 1/1 Running 0 5s + frontend-3823415956-dsvc5 1/1 Running 0 54m + frontend-3823415956-k22zn 1/1 Running 0 54m + frontend-3823415956-w9gbt 1/1 Running 0 54m + frontend-3823415956-x2pld 1/1 Running 0 5s + redis-master-1068406935-3lswp 1/1 Running 0 56m + redis-slave-2005841000-fpvqc 1/1 Running 0 55m + redis-slave-2005841000-phfv9 1/1 Running 0 55m + +3. Run the following command to scale down the number of frontend Pods: + + kubectl scale deployment frontend --replicas=2 + +4. Query the list of Pods to verify the number of frontend Pods running: + + kubectl get pods + + The response should look similar to this: + + NAME READY STATUS RESTARTS AGE + frontend-3823415956-k22zn 1/1 Running 0 1h + frontend-3823415956-w9gbt 1/1 Running 0 1h + redis-master-1068406935-3lswp 1/1 Running 0 1h + redis-slave-2005841000-fpvqc 1/1 Running 0 1h + redis-slave-2005841000-phfv9 1/1 Running 0 1h + +{% endcapture %} + +{% capture cleanup %} +Deleting the Deployments and Services also deletes any running Pods. Use labels to delete multiple resources with one command. + +1. Run the following commands to delete all Pods, Deployments, and Services. + + kubectl delete deployment -l app=redis + kubectl delete service -l app=redis + kubectl delete deployment -l app=guestbook + kubectl delete service -l app=guestbook + + The responses should be: + + deployment "redis-master" deleted + deployment "redis-slave" deleted + service "redis-master" deleted + service "redis-slave" deleted + deployment "frontend" deleted + service "frontend" deleted + +2. Query the list of Pods to verify that no Pods are running: + + kubectl get pods + + The response should be this: + + No resources found. + +{% endcapture %} + +{% capture whatsnext %} +* Complete the [Kubernetes Basics](https://kubernetes.io//docs/tutorials/kubernetes-basics/) Interactive Tutorials +* Use Kubernetes to create a blog using [Persistant Volumes for MySQL and Wordpress](https://kubernetes.io/docs/tutorials/stateful-application/mysql-wordpress-persistent-volume/#visit-your-new-wordpress-blog) +* Read more about [connecting applications](https://kubernetes.io/docs/concepts/services-networking/connect-applications-service/) +* Read more about [Managing Resources](https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#using-labels-effectively) +{% endcapture %} +{% include templates/tutorial.md %} [![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/examples/guestbook/README.md?pixel)]() diff --git a/docs/tutorials/stateless-application/guestbook/frontend-deployment.yaml b/docs/tutorials/stateless-application/guestbook/frontend-deployment.yaml new file mode 100644 index 0000000000..1888836b3c --- /dev/null +++ b/docs/tutorials/stateless-application/guestbook/frontend-deployment.yaml @@ -0,0 +1,29 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: frontend +spec: + replicas: 3 + template: + metadata: + labels: + app: guestbook + tier: frontend + spec: + containers: + - name: php-redis + image: gcr.io/google-samples/gb-frontend:v4 + resources: + requests: + cpu: 100m + memory: 100Mi + env: + - name: GET_HOSTS_FROM + value: dns + # If your cluster config does not include a dns service, then to + # instead access environment variables to find service host + # info, comment out the 'value: dns' line above, and uncomment the + # line below: + # value: env + ports: + - containerPort: 80 diff --git a/docs/tutorials/stateless-application/guestbook/frontend-service.yaml b/docs/tutorials/stateless-application/guestbook/frontend-service.yaml new file mode 100644 index 0000000000..6f283f347b --- /dev/null +++ b/docs/tutorials/stateless-application/guestbook/frontend-service.yaml @@ -0,0 +1,18 @@ +apiVersion: v1 +kind: Service +metadata: + name: frontend + labels: + app: guestbook + tier: frontend +spec: + # comment or delete the following line if you want to use a LoadBalancer + type: NodePort + # if your cluster supports it, uncomment the following to automatically create + # an external load-balanced IP for the frontend service. + # type: LoadBalancer + ports: + - port: 80 + selector: + app: guestbook + tier: frontend diff --git a/docs/tutorials/stateless-application/guestbook/redis-master-deployment.yaml b/docs/tutorials/stateless-application/guestbook/redis-master-deployment.yaml new file mode 100644 index 0000000000..3fbcc0f01c --- /dev/null +++ b/docs/tutorials/stateless-application/guestbook/redis-master-deployment.yaml @@ -0,0 +1,22 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: redis-master +spec: + replicas: 1 + template: + metadata: + labels: + app: redis + role: master + tier: backend + spec: + containers: + - name: master + image: gcr.io/google_containers/redis:e2e # or just image: redis + resources: + requests: + cpu: 100m + memory: 100Mi + ports: + - containerPort: 6379 diff --git a/docs/tutorials/stateless-application/guestbook/redis-master-service.yaml b/docs/tutorials/stateless-application/guestbook/redis-master-service.yaml new file mode 100644 index 0000000000..a484014f1f --- /dev/null +++ b/docs/tutorials/stateless-application/guestbook/redis-master-service.yaml @@ -0,0 +1,16 @@ +apiVersion: v1 +kind: Service +metadata: + name: redis-master + labels: + app: redis + role: master + tier: backend +spec: + ports: + - port: 6379 + targetPort: 6379 + selector: + app: redis + role: master + tier: backend diff --git a/docs/tutorials/stateless-application/guestbook/redis-slave-deployment.yaml b/docs/tutorials/stateless-application/guestbook/redis-slave-deployment.yaml new file mode 100644 index 0000000000..2bea4a5134 --- /dev/null +++ b/docs/tutorials/stateless-application/guestbook/redis-slave-deployment.yaml @@ -0,0 +1,30 @@ +apiVersion: extensions/v1beta1 +kind: Deployment +metadata: + name: redis-slave +spec: + replicas: 2 + template: + metadata: + labels: + app: redis + role: slave + tier: backend + spec: + containers: + - name: slave + image: gcr.io/google_samples/gb-redisslave:v1 + resources: + requests: + cpu: 100m + memory: 100Mi + env: + - name: GET_HOSTS_FROM + value: dns + # If your cluster config does not include a dns service, then to + # instead access an environment variable to find the master + # service's host, comment out the 'value: dns' line above, and + # uncomment the line below: + # value: env + ports: + - containerPort: 6379 diff --git a/docs/tutorials/stateless-application/guestbook/redis-slave-service.yaml b/docs/tutorials/stateless-application/guestbook/redis-slave-service.yaml new file mode 100644 index 0000000000..238fd63fb6 --- /dev/null +++ b/docs/tutorials/stateless-application/guestbook/redis-slave-service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: redis-slave + labels: + app: redis + role: slave + tier: backend +spec: + ports: + - port: 6379 + selector: + app: redis + role: slave + tier: backend diff --git a/images/square-logos/jetstack.png b/images/square-logos/jetstack.png index 90d0201591..f7b5a140a0 100644 Binary files a/images/square-logos/jetstack.png and b/images/square-logos/jetstack.png differ diff --git a/js/redirects.js b/js/redirects.js index f7aae1ed62..ec664a238d 100644 --- a/js/redirects.js +++ b/js/redirects.js @@ -15,25 +15,7 @@ $( document ).ready(function() { * "postfix": "/#" //[optional] append this to base URL w/ found by "pattern" * } */ - var forwardingRules = [{ - "from":"/docs/api-reference/v1/definitions", - "pattern":"#_v1_(\\w+)", - "to":"/docs/api-reference/v1.7", - "postfix":"/#-v1-core" - }, - { - "from":"/docs/user-guide/kubectl/kubectl_", - "pattern":"kubectl_(\\w+)", - "to":"/docs/user-guide/kubectl/v1.7", - "postfix":"/#" - }, - { - "from":"/docs/contribute/", - "pattern":"\/contribute\/([0-9a-zA-Z\-\_]+)", - "to":"/docs/home/contribute", - "postfix":"/" - } - ]; + var forwardingRules = []; forwardingRules.forEach(function(rule) { if (forwardingURL.indexOf(rule.from) > -1) { diff --git a/quota-pod-deployment.yaml b/quota-pod-deployment.yaml new file mode 100644 index 0000000000..e9f021e7cd --- /dev/null +++ b/quota-pod-deployment.yaml @@ -0,0 +1,14 @@ +apiVersion: apps/v1beta1 +kind: Deployment +metadata: + name: pod-quota-demo +spec: + replicas: 3 + template: + metadata: + labels: + app: pod-quota-demo + spec: + containers: + - name: pod-quota-demo + image: nginx diff --git a/update-imported-tutorials.py b/update-imported-tutorials.py index 6607934954..ba235d1ce5 100755 --- a/update-imported-tutorials.py +++ b/update-imported-tutorials.py @@ -24,14 +24,22 @@ import os.path import shutil import urllib.request -SRC_TREE = 'master' # Revision for kubernetes/examples used +SRC_REPO = 'kubernetes/examples' +SRC_TREE = 'master' # mapping of tutorials in kubernetes/examples to their # equivalent files here: (examples-path, docs-path, new-title, imports-map) TUTORIALS = [ ('guestbook/README.md', './docs/tutorials/stateless-application/guestbook.md', - "Example: Deploying PHP Guestbook application with Redis", {}), + "Example: Deploying PHP Guestbook application with Redis", { + "guestbook/redis-master-deployment.yaml" : "./docs/tutorials/stateless-application/guestbook/redis-master-deployment.yaml", + "guestbook/redis-master-service.yaml" : "./docs/tutorials/stateless-application/guestbook/redis-master-service.yaml", + "guestbook/redis-slave-deployment.yaml" : "./docs/tutorials/stateless-application/guestbook/redis-slave-deployment.yaml", + "guestbook/redis-slave-service.yaml" : "./docs/tutorials/stateless-application/guestbook/redis-slave-service.yaml", + "guestbook/frontend-deployment.yaml" : "./docs/tutorials/stateless-application/guestbook/frontend-deployment.yaml", + "guestbook/frontend-service.yaml" : "./docs/tutorials/stateless-application/guestbook/frontend-service.yaml", + }), ('mysql-wordpress-pd/README.md', './docs/tutorials/stateful-application/mysql-wordpress-persistent-volume.md', "Example: WordPress and MySQL with Persistent Volumes", {}), @@ -48,16 +56,16 @@ TUTORIALS = [ def main(): for (src_path, dst_path, new_title, imports) in TUTORIALS: print('Processing {0}'.format(src_path)) - dst_dir = os.path.dirname(dst_path) - if not os.path.exists(dst_dir): - print('Ensuring destination directory exists.') - os.makedirs(dst_dir) - if os.path.exists(dst_path): - os.remove(dst_path) imports[src_path] = dst_path # add source itself as import file for src_path, dst_path in imports.items(): - src_url = 'https://github.com/kubernetes/examples/raw/{0}/{1}'.format(SRC_TREE, src_path) + src_url = 'https://github.com/{0}/raw/{1}/{2}'.format(SRC_REPO, + SRC_TREE, src_path) + dst_dir = os.path.dirname(dst_path) + if not os.path.exists(dst_dir): + print('Creating directory {0}.'.format(dst_dir)) + os.makedirs(dst_dir) + print('Downloading {0}'.format(src_url)) with urllib.request.urlopen(src_url) as resp, \ open(dst_path, 'wb') as out_file: