Merge pull request #46699 from wanghaoran1988/issue_43325

Automatic merge from submit-queue (batch tested with PRs 47144, 46699)

Update statefulset reaper use StatefulSetHasDesiredReplicas

**What this PR does / why we need it**:
StatefulSetHasDesiredReplicas condition should check ObservedGeneration and update statefulset reaper use StatefulSetHasDesiredReplicas
**Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes #43325

**Special notes for your reviewer**:

**Release note**:
```
None
```
This commit is contained in:
Kubernetes Submit Queue 2017-06-09 12:19:41 -07:00 committed by GitHub
commit 2be7a18ead
3 changed files with 119 additions and 144 deletions

View File

@ -79,15 +79,23 @@ func ReplicaSetHasDesiredReplicas(rsClient extensionsclient.ReplicaSetsGetter, r
}
}
// StatefulSetHasDesiredReplicas returns a conditon that checks the number of statefulset replicas
// StatefulSetHasDesiredReplicas returns a condition that checks the number of StatefulSet replicas
func StatefulSetHasDesiredReplicas(ssClient appsclient.StatefulSetsGetter, ss *apps.StatefulSet) wait.ConditionFunc {
// TODO: Differentiate between 0 statefulset pods and a really quick scale down using generation.
// If we're given a StatefulSet where the status lags the spec, it either means that the
// StatefulSet is stale, or that the StatefulSet manager hasn't noticed the update yet.
// Polling status.Replicas is not safe in the latter case.
desiredGeneration := ss.Generation
return func() (bool, error) {
ss, err := ssClient.StatefulSets(ss.Namespace).Get(ss.Name, metav1.GetOptions{})
if err != nil {
return false, err
}
return ss.Status.Replicas == ss.Spec.Replicas, nil
// There's a chance a concurrent update modifies the Spec.Replicas causing this check to
// pass, or, after this check has passed, a modification causes the StatefulSet manager to
// create more pods. This will not be an issue once we've implemented graceful delete for
// StatefulSet, but till then concurrent stop operations on the same StatefulSet might have
// unintended side effects.
return ss.Status.ObservedGeneration != nil && *ss.Status.ObservedGeneration >= desiredGeneration && ss.Status.Replicas == ss.Spec.Replicas, nil
}
}

View File

@ -1,3 +1,5 @@
package(default_visibility = ["//visibility:public"])
licenses(["notice"])
load(
@ -6,115 +8,6 @@ load(
"go_test",
)
go_library(
name = "go_default_library",
srcs = [
"apply.go",
"autoscale.go",
"bash_comp_utils.go",
"cluster.go",
"clusterrolebinding.go",
"configmap.go",
"deployment.go",
"doc.go",
"env_file.go",
"explain.go",
"generate.go",
"history.go",
"interfaces.go",
"kubectl.go",
"namespace.go",
"pdb.go",
"proxy_server.go",
"quota.go",
"resource_filter.go",
"rolebinding.go",
"rollback.go",
"rolling_updater.go",
"rollout_status.go",
"run.go",
"scale.go",
"secret.go",
"secret_for_docker_registry.go",
"secret_for_tls.go",
"service.go",
"service_basic.go",
"serviceaccount.go",
"sorting_printer.go",
"stop.go",
"versioned_client.go",
],
tags = ["automanaged"],
visibility = [
"//build/visible_to:COMMON_testing",
"//build/visible_to:pkg_kubectl_CONSUMERS",
],
deps = [
"//federation/apis/federation/v1beta1:go_default_library",
"//pkg/api:go_default_library",
"//pkg/api/util:go_default_library",
"//pkg/api/v1:go_default_library",
"//pkg/api/v1/pod:go_default_library",
"//pkg/apis/apps:go_default_library",
"//pkg/apis/apps/v1beta1:go_default_library",
"//pkg/apis/autoscaling:go_default_library",
"//pkg/apis/batch:go_default_library",
"//pkg/apis/batch/v1:go_default_library",
"//pkg/apis/batch/v2alpha1:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/apis/extensions/v1beta1:go_default_library",
"//pkg/apis/policy:go_default_library",
"//pkg/apis/rbac:go_default_library",
"//pkg/client/clientset_generated/clientset:go_default_library",
"//pkg/client/clientset_generated/clientset/typed/apps/v1beta1:go_default_library",
"//pkg/client/clientset_generated/clientset/typed/core/v1:go_default_library",
"//pkg/client/clientset_generated/clientset/typed/extensions/v1beta1:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/apps/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/batch/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion:go_default_library",
"//pkg/client/retry:go_default_library",
"//pkg/client/unversioned:go_default_library",
"//pkg/controller:go_default_library",
"//pkg/controller/daemon:go_default_library",
"//pkg/controller/deployment/util:go_default_library",
"//pkg/credentialprovider:go_default_library",
"//pkg/kubectl/resource:go_default_library",
"//pkg/kubectl/util:go_default_library",
"//pkg/printers:go_default_library",
"//pkg/printers/internalversion:go_default_library",
"//pkg/util:go_default_library",
"//pkg/util/slice:go_default_library",
"//vendor/github.com/emicklei/go-restful-swagger12:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
"//vendor/k8s.io/client-go/rest:go_default_library",
"//vendor/k8s.io/client-go/util/integer:go_default_library",
"//vendor/k8s.io/client-go/util/jsonpath:go_default_library",
"//vendor/vbom.ml/util/sortorder:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = [
@ -181,10 +74,116 @@ go_test(
],
)
go_library(
name = "go_default_library",
srcs = [
"apply.go",
"autoscale.go",
"bash_comp_utils.go",
"cluster.go",
"clusterrolebinding.go",
"configmap.go",
"deployment.go",
"doc.go",
"env_file.go",
"explain.go",
"generate.go",
"history.go",
"interfaces.go",
"kubectl.go",
"namespace.go",
"pdb.go",
"proxy_server.go",
"quota.go",
"resource_filter.go",
"rolebinding.go",
"rollback.go",
"rolling_updater.go",
"rollout_status.go",
"run.go",
"scale.go",
"secret.go",
"secret_for_docker_registry.go",
"secret_for_tls.go",
"service.go",
"service_basic.go",
"serviceaccount.go",
"sorting_printer.go",
"stop.go",
"versioned_client.go",
],
tags = ["automanaged"],
deps = [
"//federation/apis/federation/v1beta1:go_default_library",
"//pkg/api:go_default_library",
"//pkg/api/util:go_default_library",
"//pkg/api/v1:go_default_library",
"//pkg/api/v1/pod:go_default_library",
"//pkg/apis/apps:go_default_library",
"//pkg/apis/apps/v1beta1:go_default_library",
"//pkg/apis/autoscaling:go_default_library",
"//pkg/apis/batch:go_default_library",
"//pkg/apis/batch/v1:go_default_library",
"//pkg/apis/batch/v2alpha1:go_default_library",
"//pkg/apis/extensions:go_default_library",
"//pkg/apis/extensions/v1beta1:go_default_library",
"//pkg/apis/policy:go_default_library",
"//pkg/apis/rbac:go_default_library",
"//pkg/client/clientset_generated/clientset:go_default_library",
"//pkg/client/clientset_generated/clientset/typed/apps/v1beta1:go_default_library",
"//pkg/client/clientset_generated/clientset/typed/core/v1:go_default_library",
"//pkg/client/clientset_generated/clientset/typed/extensions/v1beta1:go_default_library",
"//pkg/client/clientset_generated/internalclientset:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/apps/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/batch/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library",
"//pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion:go_default_library",
"//pkg/client/retry:go_default_library",
"//pkg/client/unversioned:go_default_library",
"//pkg/controller:go_default_library",
"//pkg/controller/daemon:go_default_library",
"//pkg/controller/deployment/util:go_default_library",
"//pkg/credentialprovider:go_default_library",
"//pkg/kubectl/resource:go_default_library",
"//pkg/kubectl/util:go_default_library",
"//pkg/printers:go_default_library",
"//pkg/printers/internalversion:go_default_library",
"//pkg/util:go_default_library",
"//pkg/util/slice:go_default_library",
"//vendor/github.com/emicklei/go-restful-swagger12:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library",
"//vendor/github.com/spf13/pflag:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1/unstructured:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/sets:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/uuid:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/validation:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
"//vendor/k8s.io/client-go/rest:go_default_library",
"//vendor/k8s.io/client-go/util/integer:go_default_library",
"//vendor/k8s.io/client-go/util/jsonpath:go_default_library",
"//vendor/vbom.ml/util/sortorder:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
@ -199,7 +198,4 @@ filegroup(
"//pkg/kubectl/util:all-srcs",
],
tags = ["automanaged"],
visibility = [
"//build/visible_to:pkg_kubectl_CONSUMERS",
],
)

View File

@ -37,7 +37,6 @@ import (
batchclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/batch/internalversion"
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
extensionsclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion"
"k8s.io/kubernetes/pkg/controller"
deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util"
"k8s.io/kubernetes/pkg/util"
)
@ -345,34 +344,6 @@ func (reaper *StatefulSetReaper) Stop(namespace, name string, timeout time.Durat
return err
}
// TODO: This shouldn't be needed, see corresponding TODO in StatefulSetHasDesiredReplicas.
// StatefulSet should track generation number.
pods := reaper.podClient.Pods(namespace)
selector, _ := metav1.LabelSelectorAsSelector(ss.Spec.Selector)
options := metav1.ListOptions{LabelSelector: selector.String()}
podList, err := pods.List(options)
if err != nil {
return err
}
errList := []error{}
for i := range podList.Items {
pod := &podList.Items[i]
controllerRef := controller.GetControllerOf(pod)
// Ignore Pod if it's an orphan or owned by someone else.
if controllerRef == nil || controllerRef.UID != ss.UID {
continue
}
if err := pods.Delete(pod.Name, gracePeriod); err != nil {
if !errors.IsNotFound(err) {
errList = append(errList, err)
}
}
}
if len(errList) > 0 {
return utilerrors.NewAggregate(errList)
}
// TODO: Cleanup volumes? We don't want to accidentally delete volumes from
// stop, so just leave this up to the statefulset.
falseVar := false