diff --git a/docs/concepts/workloads/controllers/statefulset.md b/docs/concepts/workloads/controllers/statefulset.md index 2287055d68..fa58f58b77 100644 --- a/docs/concepts/workloads/controllers/statefulset.md +++ b/docs/concepts/workloads/controllers/statefulset.md @@ -1,6 +1,5 @@ --- assignees: -- bprashanth - enisoc - erictune - foxish @@ -14,7 +13,7 @@ redirect_from: --- {% capture overview %} -**StatefulSets are a beta feature in 1.5. This feature replaces the +**StatefulSets are a beta feature in 1.7. This feature replaces the PetSets feature from 1.4. Users of PetSets are referred to the 1.5 [Upgrade Guide](/docs/tasks/manage-stateful-set/upgrade-pet-set-to-stateful-set/) for further information on how to upgrade existing PetSets to StatefulSets.** @@ -34,8 +33,9 @@ following. * Stable, persistent storage. * Ordered, graceful deployment and scaling. * Ordered, graceful deletion and termination. +* Ordered, automated rolling updates. -In the above, stable is synonymous with persistence across Pod (re)schedulings. +In the above, stable is synonymous with persistence across Pod (re)scheduling. If an application doesn't require any stable identifiers or ordered deployment, deletion, or scaling, you should deploy your application with a controller that provides a set of stateless replicas. Controllers such as @@ -48,7 +48,6 @@ provides a set of stateless replicas. Controllers such as * The storage for a given Pod must either be provisioned by a [PersistentVolume Provisioner](http://releases.k8s.io/{{page.githubbranch}}/examples/persistent-volume-provisioning/README.md) based on the requested `storage class`, or pre-provisioned by an admin. * Deleting and/or scaling a StatefulSet down will *not* delete the volumes associated with the StatefulSet. This is done to ensure data safety, which is generally more valuable than an automatic purge of all related StatefulSet resources. * StatefulSets currently require a [Headless Service](/docs/concepts/services-networking/service/#headless-services) to be responsible for the network identity of the Pods. You are responsible for creating this Service. -* Updating an existing StatefulSet is currently a [manual process](/docs/tutorials/stateful-application/basic-stateful-set/#updating-containers). ## Components The example below demonstrates the components of a StatefulSet. @@ -59,7 +58,6 @@ The example below demonstrates the components of a StatefulSet. PersistentVolume Provisioner. ```yaml ---- apiVersion: v1 kind: Service metadata: @@ -154,7 +152,7 @@ PersistentVolume Claims. Note that, the PersistentVolumes associated with the Pods' PersistentVolume Claims are not deleted when the Pods, or StatefulSet are deleted. This must be done manually. -## Deployment and Scaling Guarantee +## Deployment and Scaling Guarantees * For a StatefulSet with N replicas, when Pods are being deployed, they are created sequentially, in order from {0..N-1}. * When Pods are being deleted, they are terminated in reverse order, from {N-1..0}. @@ -175,5 +173,62 @@ If a user were to scale the deployed example by patching the StatefulSet such th is fully shutdown and deleted. If web-0 were to fail after web-2 has been terminated and is completely shutdown, but prior to web-1's termination, web-1 would not be terminated until web-0 is Running and Ready. + +### Pod Management Policies +In Kubernetes 1.7 and later, StatefulSet allows you to relax its ordering guarantees while +preserving its uniqueness and identity guarantees via its `.spec.podManagementPolicy` field. + +#### OrderedReady Pod Management + +`OrderedReady` pod management is the default for StatefulSets. It implements the behavior +described [above](#deployment-and-scaling-guarantees). + +#### Parallel Pod Management + +`Parallel` pod management tells the StatefulSet controller to launch or +terminate all Pods in parallel, and to not wait for Pods to become Running +and Ready or completely terminated prior to launching or terminating another +Pod. + +## Update Strategies + +In Kuberentes 1.7 and later, StatefulSet's `.spec.updateStrategy` field allows you to configure +and disable automated rolling updates for containers, labels, resource request/limits, and +annotations for the Pods in a StatefulSet. + +### On Delete + +The `OnDelete` update strategy implements the legacy (1.6 and prior) behavior. It is the default +strategy when `spec.updateStrategy` is left unspecified. When a StatefulSet's +`.spec.updateStrategy.type` is set to `OnDelete`, the StatefulSet controller will not automatically +update the Pods in a StatefulSet. Users must manually delete Pods to cause the controller to +create new Pods that reflect modifications made to a StatefulSet's `.spec.template`. + +### Rolling Updates + +The `RollingUpdate` update strategy implements automated, rolling update for the Pods in a +StatefulSet. When a StatefulSet's `.spec.updateStrategy.type` is set to `RollingUpdate`, the +StatefulSet controller will delete and recreate each Pod in the StatefulSet. It will proceed +in the same order as Pod termination (from the largest ordinal to the smallest), updating +each Pod one at a time. It will wait until an updated Pod is Running and Ready prior to +updating its predecessor. + +#### Partitions + +The `RollingUpdate` update strategy can be partitioned, by specifying a +`.spec.updateStrategy.rollingUpdate.partition`. If a partition is specified, all Pods with an +ordinal that is greater than or equal to the partition will be updated when the StatefulSet's +`.spec.template` is updated. All Pods with an ordinal that is less than the partition will not +be updated, and, even if they are deleted, they will be recreated at the previous version. If a +StatefulSet's `.spec.updateStrategy.rollingUpdate.partition` is greater than its `.spec.replicas`, +updates to its `.spec.template` will not be propagated to its Pods. +In most cases you will not need to use a partition, but they are useful if you want to stage an +update, roll out a canary, or perform a phased roll out. + +{% endcapture %} +{% capture whatsnext %} + +* Follow an example of [deploying a stateful application](/docs/tutorials/stateful-application/basic-stateful-set). + {% endcapture %} {% include templates/concept.md %} diff --git a/docs/tutorials/stateful-application/basic-stateful-set.md b/docs/tutorials/stateful-application/basic-stateful-set.md index 0bfe1d41c9..f76f70195d 100644 --- a/docs/tutorials/stateful-application/basic-stateful-set.md +++ b/docs/tutorials/stateful-application/basic-stateful-set.md @@ -1,6 +1,5 @@ --- assignees: -- bprashanth - enisoc - erictune - foxish @@ -11,10 +10,9 @@ title: StatefulSet Basics --- {% capture overview %} -This tutorial provides an introduction to manage applications with +This tutorial provides an introduction to managing applications with [StatefulSets](/docs/concepts/abstractions/controllers/statefulsets/). It -demonstrates how to create, delete, scale, and update the container image of a -StatefulSet. +demonstrates how to create, delete, scale, and update the Pods of StatefulSets. {% endcapture %} {% capture prerequisites %} @@ -40,7 +38,7 @@ StatefulSets are intended to be used with stateful applications and distributed systems. However, the administration of stateful applications and distributed systems on Kubernetes is a broad, complex topic. In order to demonstrate the basic features of a StatefulSet, and to not conflate the former -topic with the latter, you will deploy a simple web application using StatefulSets. +topic with the latter, you will deploy a simple web application using a StatefulSet. After this tutorial, you will be familiar with the following. @@ -48,7 +46,7 @@ After this tutorial, you will be familiar with the following. * How a StatefulSet manages its Pods * How to delete a StatefulSet * How to scale a StatefulSet -* How to update the container image of a StatefulSet's Pods +* How to update a StatefulSet's Pods {% endcapture %} {% capture lessoncontent %} @@ -56,9 +54,9 @@ After this tutorial, you will be familiar with the following. Begin by creating a StatefulSet using the example below. It is similar to the example presented in the -[StatefulSets](/docs/concepts/abstractions/controllers/statefulsets/) concept. It creates -a [Headless Service](/docs/user-guide/services/#headless-services), `nginx`, to -control the domain of the StatefulSet, `web`. +[StatefulSets](/docs/concepts/abstractions/controllers/statefulsets/) concept. +It creates a [Headless Service](/docs/user-guide/services/#headless-services), +`nginx`, to publish the IP addresses of Pods in the StatefulSet, `web`. {% include code.html language="yaml" file="web.yaml" ghlink="/docs/tutorials/stateful-application/web.yaml" %} @@ -116,13 +114,12 @@ web-1 0/1 ContainerCreating 0 0s web-1 1/1 Running 0 18s ``` -Notice that the `web-0` Pod is launched and set to Pending prior to -launching `web-1`. In fact, `web-1` is not launched until `web-0` is +Notice that the `web-1` Pod is not launched until the `web-0` Pod is [Running and Ready](/docs/user-guide/pod-states). ## Pods in a StatefulSet -Unlike Pods in other controllers, the Pods in a StatefulSet have a unique -ordinal index and a stable network identity. + +Pods in a StatefulSet have a unique ordinal index and a stable network identity. ### Examining the Pod's Ordinal Index @@ -138,12 +135,13 @@ web-1 1/1 Running 0 1m As mentioned in the [StatefulSets](/docs/concepts/abstractions/controllers/statefulsets/) concept, the Pods in a StatefulSet have a sticky, unique identity. This identity -is based on a unique ordinal index that is assigned to each Pod by the Stateful -Set controller. The Pods' names take the form +is based on a unique ordinal index that is assigned to each Pod by the +StatefulSet controller. The Pods' names take the form `-`. Since the `web` StatefulSet has two replicas, it creates two Pods, `web-0` and `web-1`. ### Using Stable Network Identities + Each Pod has a stable hostname based on its ordinal index. Use [`kubectl exec`](/docs/user-guide/kubectl/v1.6/#exec) to execute the `hostname` command in each Pod. @@ -264,9 +262,9 @@ www-web-0 Bound pvc-15c268c7-b507-11e6-932f-42010a800002 1Gi RWO www-web-1 Bound pvc-15c79307-b507-11e6-932f-42010a800002 1Gi RWO 48s ``` The StatefulSet controller created two PersistentVolumeClaims that are -bound to two [PersistentVolumes](/docs/concepts/storage/volumes/). As the cluster used -in this tutorial is configured to dynamically provision PersistentVolumes, the -PersistentVolumes were created and bound automatically. +bound to two [PersistentVolumes](/docs/concepts/storage/volumes/). As the +cluster used in this tutorial is configured to dynamically provision +PersistentVolumes, the PersistentVolumes were created and bound automatically. The NGINX webservers, by default, will serve an index file at `/usr/share/nginx/html/index.html`. The `volumeMounts` field in the @@ -331,10 +329,10 @@ web-1 ``` Even though `web-0` and `web-1` were rescheduled, they continue to serve their -hostnames because the PersistentVolumes associated with their Persistent -Volume Claims are remounted to their `volumeMount`s. No matter what node `web-0` -and `web-1` are scheduled on, their PersistentVolumes will be mounted to the -appropriate mount points. +hostnames because the PersistentVolumes associated with their +PersistentVolumeClaims are remounted to their `volumeMount`s. No matter what +node `web-0`and `web-1` are scheduled on, their PersistentVolumes will be +mounted to the appropriate mount points. ## Scaling a StatefulSet Scaling a StatefulSet refers to increasing or decreasing the number of replicas. @@ -355,7 +353,7 @@ In another terminal window, use `kubectl scale` to scale the number of replicas to 5. ```shell -kubectl scale statefulset web --replicas=5 +kubectl scale sts web --replicas=5 statefulset "web" scaled ``` @@ -397,10 +395,10 @@ kubectl get pods -w -l app=nginx ``` In another terminal, use `kubectl patch` to scale the StatefulSet back down to -3 replicas. +three replicas. ```shell -kubectl patch statefulset web -p '{"spec":{"replicas":3}}' +kubectl patch sts web -p '{"spec":{"replicas":3}}' "web" patched ``` @@ -424,8 +422,8 @@ web-3 1/1 Terminating 0 42s ### Ordered Pod Termination -The controller deleted one Pod at a time, with respect to its ordinal index, -in reverse order, and it waited for each to be completely shutdown before +The controller deleted one Pod at a time, in reverse order with respect to its +ordinal index, and it waited for each to be completely shutdown before deleting the next. Get the StatefulSet's PersistentVolumeClaims. @@ -445,18 +443,22 @@ There are still five PersistentVolumeClaims and five PersistentVolumes. When exploring a Pod's [stable storage](#stable-storage), we saw that the PersistentVolumes mounted to the Pods of a StatefulSet are not deleted when the StatefulSet's Pods are deleted. This is still true when Pod deletion is -caused by scaling the StatefulSet down. This feature can be used to facilitate -upgrading the container images of Pods in a StatefulSet. +caused by scaling the StatefulSet down. -## Updating Containers -As demonstrated in the [Scaling a StatefulSet](#scaling-a-statefulset) section, -the `replicas` field of a StatefulSet is mutable. The only other field of a -StatefulSet that can be updated is the `spec.template.containers` field. +## Updating StatefulSets -StatefulSet currently *does not* support automated image upgrade. However, you -can update the `image` field of any container in the podTemplate and delete -StatefulSet's Pods one by one, the StatefulSet controller will recreate -each Pod with the new image. +In Kubernetes 1.7, the StatefulSet controller supports automated updates. The +strategy used is determined by the `spec.updateStrategy` field of the +StatefulSet API Object. This feature can be used to upgrade the container +images, resource requests and/or limits, labels, and annotations of the Pods in a +StatefulSet. There are two valid update strategies, `OnDelete` and +`RollingUpdate`. + +### On Delete +The `OnDelete` update strategy implements the legacy (prior to 1.7) behavior, +and it is the default update strategy. When you select this update strategy, +the StatefulSet controller will not automatically update Pods when a +modification is made to the StatefulSet's `.spec.template` field. Patch the container image for the `web` StatefulSet. @@ -472,7 +474,7 @@ kubectl delete pod web-0 pod "web-0" deleted ``` -Watch `web-0`, and wait for the Pod to transition to Running and Ready. +Watch the `web-0` Pod, and wait for it to transition to Running and Ready. ```shell kubectl get pod web-0 -w @@ -488,7 +490,7 @@ web-0 0/1 ContainerCreating 0 0s web-0 1/1 Running 0 3s ``` -Get the Pods to view their container images. +Get the `web` StatefulSet's Pods to view their container images. ```shell{% raw %} kubectl get pod -l app=nginx -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[0].image}{"\n"}{end}' @@ -497,8 +499,8 @@ web-1 gcr.io/google_containers/nginx-slim:0.8 web-2 gcr.io/google_containers/nginx-slim:0.8 {% endraw %}``` -`web-0` has had its image updated. Complete the update by deleting the remaining -Pods. +`web-0` has had its image updated, but `web-0` and `web-1` still have the original +image. Complete the update by deleting the remaining Pods. ```shell kubectl delete pod web-1 web-2 @@ -506,7 +508,7 @@ pod "web-1" deleted pod "web-2" deleted ``` -Watch the Pods, and wait for all of them to transition to Running and Ready. +Watch the StatefulSet's Pods, and wait for all of them to transition to Running and Ready. ``` kubectl get pods -w -l app=nginx @@ -540,6 +542,261 @@ web-2 gcr.io/google_containers/nginx-slim:0.7 All the Pods in the StatefulSet are now running a new container image. +### Rolling Update + +The `RollingUpdate` update strategy will update all Pods in a StatefulSet, in +reverse ordinal order, while respecting the StatefulSet guarantees. + +Patch the `web` StatefulSet to apply the `RollingUpdate` update strategy. + +```shell +kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate"}}} +statefulset "web" patched +``` + +In one terminal window, patch the `web` StatefulSet to change the container +image again. + +```shell +kubectl patch statefulset web --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"gcr.io/google_containers/nginx-slim:0.8"}]' +statefulset "web" patched +``` + +In another terminal, watch the Pods in the StatefulSet. + +```shell +kubectl get po -l app=nginx -w +NAME READY STATUS RESTARTS AGE +web-0 1/1 Running 0 7m +web-1 1/1 Running 0 7m +web-2 1/1 Running 0 8m +web-2 1/1 Terminating 0 8m +web-2 1/1 Terminating 0 8m +web-2 0/1 Terminating 0 8m +web-2 0/1 Terminating 0 8m +web-2 0/1 Terminating 0 8m +web-2 0/1 Terminating 0 8m +web-2 0/1 Pending 0 0s +web-2 0/1 Pending 0 0s +web-2 0/1 ContainerCreating 0 0s +web-2 1/1 Running 0 19s +web-1 1/1 Terminating 0 8m +web-1 0/1 Terminating 0 8m +web-1 0/1 Terminating 0 8m +web-1 0/1 Terminating 0 8m +web-1 0/1 Pending 0 0s +web-1 0/1 Pending 0 0s +web-1 0/1 ContainerCreating 0 0s +web-1 1/1 Running 0 6s +web-0 1/1 Terminating 0 7m +web-0 1/1 Terminating 0 7m +web-0 0/1 Terminating 0 7m +web-0 0/1 Terminating 0 7m +web-0 0/1 Terminating 0 7m +web-0 0/1 Terminating 0 7m +web-0 0/1 Pending 0 0s +web-0 0/1 Pending 0 0s +web-0 0/1 ContainerCreating 0 0s +web-0 1/1 Running 0 10s +``` + +The Pods in the StatefulSet are updated in reverse ordinal order. The +StatefulSet controller terminates each Pod, and waits for it to transition to Running and +Ready prior to updating the next Pod. Note that, even though the StatefulSet +controller will not proceed to update the next Pod until its ordinal successor +is Running and Ready, it will restore any Pod that fails during the update to +its current version. Pods that have already received the update will be +restored to the updated version, and Pods that have not yet received the +update will be restored to the previous version. In this way, the controller +attempts to continue to keep the application healthy and the update consistent +in the presence of intermittent failures. + +Get the Pods to view their container images. + +```shell{% raw %} +for p in 0 1 2; do kubectl get po web-$p --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}'; echo; done +gcr.io/google_containers/nginx-slim:0.8 +gcr.io/google_containers/nginx-slim:0.8 +gcr.io/google_containers/nginx-slim:0.8 +{% endraw %} +``` + +All the Pods in the StatefulSet are now running the previous container image. + +**Tip** You can also use `kubectl rollout status sts/` to view +the status of a rolling update. + +#### Staging an Update +You can stage an update to a StatefulSet by using the `partition` parameter of +the `RollingUpdate` update strategy. A staged update will keep all of the Pods +in the StatefulSet at the current version while allowing mutations to the +StatefulSet's `.spec.template`. + +Patch the `web` StatefulSet to add a partition to the `updateStrategy` field. + +```shell +kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":3}}}}' +statefulset "web" patched +``` + +Patch the StatefulSet again to change the container's image. + +```shell +kubectl patch statefulset web --type='json' -p='[{"op": "replace", "path": "/spec/template/spec/containers/0/image", "value":"gcr.io/google_containers/nginx-slim:0.7"}]' +statefulset "web" patched +``` + +Delete a Pod in the StatefulSet. + +```shell +kubectl delete po web-2 +pod "web-2" deleted +``` + +Wait for the Pod to be Running and Ready. + +```shell +kubectl get po -lapp=nginx -w +NAME READY STATUS RESTARTS AGE +web-0 1/1 Running 0 4m +web-1 1/1 Running 0 4m +web-2 0/1 ContainerCreating 0 11s +web-2 1/1 Running 0 18s +``` + +Get the Pod's container. + +```shell{% raw %} +get po web-2 --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}' +gcr.io/google_containers/nginx-slim:0.8 +{% endraw %} +``` + +Notice that, even though the update strategy is `RollingUpdate` the StatefulSet +controller restored the Pod with its original container. This is because the +ordinal of the Pod is less than the `partition` specified by the +`updateStrategy`. + +#### Rolling Out a Canary +You can roll out a canary to test a modification by decrementing the `partition` +you specified [above](#staging-an-update). + +Patch the StatefulSet to decrement the partition. + +```shell +kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":2}}}}' +statefulset "web" patched +``` + +Wait for `web-2` to be Running and Ready. + +```shell +kubectl get po -lapp=nginx -w +NAME READY STATUS RESTARTS AGE +web-0 1/1 Running 0 4m +web-1 1/1 Running 0 4m +web-2 0/1 ContainerCreating 0 11s +web-2 1/1 Running 0 18s +``` + +Get the Pod's container. + +```shell{% raw %} +kubectl get po web-2 --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}' +gcr.io/google_containers/nginx-slim:0.7 +{% endraw %} +``` + +When you changed the `partition`, the StatefulSet controller automatically +updated the `web-2` Pod because the Pod's ordinal was less than or equal to +the `partition`. + +Delete the `web-1` Pod. + +```shell +kubectl delete po web-1 +pod "web-1" deleted +``` + +Wait for the `web-1` Pod to be Running and Ready. + +```shell +kubectl get po -lapp=nginx -w +NAME READY STATUS RESTARTS AGE +web-0 1/1 Running 0 6m +web-1 0/1 Terminating 0 6m +web-2 1/1 Running 0 2m +web-1 0/1 Terminating 0 6m +web-1 0/1 Terminating 0 6m +web-1 0/1 Terminating 0 6m +web-1 0/1 Pending 0 0s +web-1 0/1 Pending 0 0s +web-1 0/1 ContainerCreating 0 0s +web-1 1/1 Running 0 18s +``` + +Get the `web-1` Pods container. + +```shell{% raw %} +get po web-1 --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}' +gcr.io/google_containers/nginx-slim:0.8 +{% endraw %} +``` +`web-1` was restored to its original configuration because the Pod's ordinal +was less than the partition. When a partition is specified, all Pods with an +ordinal that is greater than or equal to the partition will be updated when the +StatefulSet's `.spec.template` is updated. If a Pod that has an ordinal less +than the partition is deleted or otherwise terminated, it will be restored to +its original configuration. + +#### Phased Roll Outs +You can perform a phased roll out (e.g. a linear, geometric, or exponential +roll out) using a partitioned rolling update in a similar manner to how you +rolled out a [canary](#rolling-out-a-canary). To perform a phased roll out, set +the `partition` to the ordinal at which you want the controller to pause the +update. + +The partition is currently set to `2`. Set the partition to `0`. + +```shell +kubectl patch statefulset web -p '{"spec":{"updateStrategy":{"type":"RollingUpdate","rollingUpdate":{"partition":0}}}}' +statefulset "web" patched +``` + +Wait for all of the Pods in the StatefulSet to become Running and Ready. + +```shell +kubectl get po -lapp=nginx -w +NAME READY STATUS RESTARTS AGE +web-0 1/1 Running 0 3m +web-1 0/1 ContainerCreating 0 11s +web-2 1/1 Running 0 2m +web-1 1/1 Running 0 18s +web-0 1/1 Terminating 0 3m +web-0 1/1 Terminating 0 3m +web-0 0/1 Terminating 0 3m +web-0 0/1 Terminating 0 3m +web-0 0/1 Terminating 0 3m +web-0 0/1 Terminating 0 3m +web-0 0/1 Pending 0 0s +web-0 0/1 Pending 0 0s +web-0 0/1 ContainerCreating 0 0s +web-0 1/1 Running 0 3s +``` + +Get the Pod's containers. + +```shell{% raw %} +for p in 0 1 2; do kubectl get po web-$p --template '{{range $i, $c := .spec.containers}}{{$c.image}}{{end}}'; echo; done +gcr.io/google_containers/nginx-slim:0.7 +gcr.io/google_containers/nginx-slim:0.7 +gcr.io/google_containers/nginx-slim:0.7 +{% endraw %} +``` + +By moving the `partition` to `0`, you allowed the StatefulSet controller to +continue the update process. + ## Deleting StatefulSets StatefulSet supports both Non-Cascading and Cascading deletion. In a @@ -596,7 +853,7 @@ As the `web` StatefulSet has been deleted, `web-0` has not been relaunched. In one terminal, watch the StatefulSet's Pods. -``` +```shell kubectl get pods -w -l app=nginx ``` @@ -733,6 +990,131 @@ kubectl delete statefulset web statefulset "web" deleted ``` +## Pod Management Policy + +For some distributed systems, the StatefulSet ordering guarantees are +unnecessary and/or undesirable. These systems require only uniqueness and +identity. To address this, in Kubernetes 1.7, we introduced +`.spec.podManagementPolicy` to the StatefulSet API Object. + +### OrderedReady Pod Management + +`OrderedReady` pod management is the default for StatefulSets. It tells the +StatefulSet controller to respect the ordering guarantees demonstrated +above. + +### Parallel Pod Management + +`Parallel` pod management tells the StatefulSet controller to launch or +terminate all Pods in parallel, and to not wait for Pods to becoming Running +and Ready or completely terminated prior to launching or terminating another +Pod. + +{% include code.html language="yaml" file="webp.yaml" ghlink="/docs/tutorials/stateful-application/webp.yaml" %} + +Download the example above, and save it to a file named `webp.yaml` + +This manifest is identical to the one you +[downloaded above](creating-a-statefulset) except that the `.spec.podManagementPolicy` +of the `web` StatefulSet is set to `Parallel`. + +In one terminal, watch the Pods in the StatefulSet. + +```shell +kubectl get po -lapp=nginx -w +``` + +In another terminal, create the StatefulSet and Service in the manifest. + +```shell +kubectl create -f webp.yaml +service "nginx" created +statefulset "web" created +``` + +Examine the output of the `kubectl get` command that you executed in the first terminal. + +```shell +kubectl get po -lapp=nginx -w +NAME READY STATUS RESTARTS AGE +web-0 0/1 Pending 0 0s +web-0 0/1 Pending 0 0s +web-1 0/1 Pending 0 0s +web-1 0/1 Pending 0 0s +web-0 0/1 ContainerCreating 0 0s +web-1 0/1 ContainerCreating 0 0s +web-0 1/1 Running 0 10s +web-1 1/1 Running 0 10s +``` + +The StatefulSet controller launched both `web-0` and `web-1` at the same time. + +Keep the second terminal open, and, in another terminal window scale the +StatefulSet. + +```shell +kubectl scale statefulset/web --replicas=4 +statefulset "web" scaled +``` + +Examine the output of the terminal where the `kubectl get` command is running. + +```shell +web-3 0/1 Pending 0 0s +web-3 0/1 Pending 0 0s +web-3 0/1 Pending 0 7s +web-3 0/1 ContainerCreating 0 7s +web-2 1/1 Running 0 10s +web-3 1/1 Running 0 26s +``` + + +The StatefulSet controller launched two new Pods, and it did not wait for +the first to become Running and Ready prior to launching the second. + +Keep this terminal open, and in another terminal delete the `web` StatefulSet. + +```shell +kubectl delete sts web +``` + +Again, examine the output of the `kubectl get` command running in the other terminal. + +```shell +web-3 1/1 Terminating 0 9m +web-2 1/1 Terminating 0 9m +web-3 1/1 Terminating 0 9m +web-2 1/1 Terminating 0 9m +web-1 1/1 Terminating 0 44m +web-0 1/1 Terminating 0 44m +web-0 0/1 Terminating 0 44m +web-3 0/1 Terminating 0 9m +web-2 0/1 Terminating 0 9m +web-1 0/1 Terminating 0 44m +web-0 0/1 Terminating 0 44m +web-2 0/1 Terminating 0 9m +web-2 0/1 Terminating 0 9m +web-2 0/1 Terminating 0 9m +web-1 0/1 Terminating 0 44m +web-1 0/1 Terminating 0 44m +web-1 0/1 Terminating 0 44m +web-0 0/1 Terminating 0 44m +web-0 0/1 Terminating 0 44m +web-0 0/1 Terminating 0 44m +web-3 0/1 Terminating 0 9m +web-3 0/1 Terminating 0 9m +web-3 0/1 Terminating 0 9m +``` + +The StatefulSet controller deletes all Pods concurrently, it does not wait for +a Pod's ordinal successor to terminate prior to deleting that Pod. + +Close the terminal where the `kubectl get` command is running and delete the `nginx` +Service. + +```shell +kubectl delete svc nginx +``` {% endcapture %} {% capture cleanup %} diff --git a/docs/tutorials/stateful-application/webp.yaml b/docs/tutorials/stateful-application/webp.yaml new file mode 100644 index 0000000000..0a56f234e0 --- /dev/null +++ b/docs/tutorials/stateful-application/webp.yaml @@ -0,0 +1,45 @@ +--- +apiVersion: v1 +kind: Service +metadata: + name: nginx + labels: + app: nginx +spec: + ports: + - port: 80 + name: web + clusterIP: None + selector: + app: nginx +--- +apiVersion: apps/v1beta1 +kind: StatefulSet +metadata: + name: web +spec: + serviceName: "nginx" + podManagementPolicy: "Parallel" + replicas: 2 + template: + metadata: + labels: + app: nginx + spec: + containers: + - name: nginx + image: gcr.io/google_containers/nginx-slim:0.8 + ports: + - containerPort: 80 + name: web + volumeMounts: + - name: www + mountPath: /usr/share/nginx/html + volumeClaimTemplates: + - metadata: + name: www + spec: + accessModes: [ "ReadWriteOnce" ] + resources: + requests: + storage: 1Gi \ No newline at end of file diff --git a/test/examples_test.go b/test/examples_test.go index f923547032..9e58ff0ad4 100644 --- a/test/examples_test.go +++ b/test/examples_test.go @@ -332,6 +332,7 @@ func TestExampleObjectSchemas(t *testing.T) { "mysql-configmap": {&api.ConfigMap{}}, "mysql-statefulset": {&apps.StatefulSet{}}, "web": {&api.Service{}, &apps.StatefulSet{}}, + "webp": {&api.Service{}, &apps.StatefulSet{}}, "zookeeper": {&api.Service{}, &api.ConfigMap{}, &policy.PodDisruptionBudget{}, &apps.StatefulSet{}}, }, }