Skip to content

Commit e3655bb

Browse files
committed
Trigger deployment as success when new replicaSet has reached minimum you need which is number of replicas minus maxUnavailable
1 parent 15576ab commit e3655bb

File tree

5 files changed

+46
-11
lines changed

5 files changed

+46
-11
lines changed

cmd/helm/install.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ func newInstallCmd(c helm.Interface, out io.Writer) *cobra.Command {
172172
f.StringVar(&inst.keyring, "keyring", defaultKeyring(), "location of public keys used for verification")
173173
f.StringVar(&inst.version, "version", "", "specify the exact chart version to install. If this is not specified, the latest version is installed")
174174
f.Int64Var(&inst.timeout, "timeout", 300, "time in seconds to wait for any individual kubernetes operation (like Jobs for hooks)")
175-
f.BoolVar(&inst.wait, "wait", false, "if set, will wait until all Pods, PVCs, and Services are in a ready state before marking the release as successful. It will wait for as long as --timeout")
175+
f.BoolVar(&inst.wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout")
176176

177177
return cmd
178178
}

cmd/helm/rollback.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ func newRollbackCmd(c helm.Interface, out io.Writer) *cobra.Command {
8080
f.BoolVar(&rollback.recreate, "recreate-pods", false, "performs pods restart for the resource if applicable")
8181
f.BoolVar(&rollback.disableHooks, "no-hooks", false, "prevent hooks from running during rollback")
8282
f.Int64Var(&rollback.timeout, "timeout", 300, "time in seconds to wait for any individual kubernetes operation (like Jobs for hooks)")
83-
f.BoolVar(&rollback.wait, "wait", false, "if set, will wait until all Pods, PVCs, and Services are in a ready state before marking the release as successful. It will wait for as long as --timeout")
83+
f.BoolVar(&rollback.wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout")
8484

8585
return cmd
8686
}

cmd/helm/upgrade.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ func newUpgradeCmd(client helm.Interface, out io.Writer) *cobra.Command {
114114
f.StringVar(&upgrade.version, "version", "", "specify the exact chart version to use. If this is not specified, the latest version is used")
115115
f.Int64Var(&upgrade.timeout, "timeout", 300, "time in seconds to wait for any individual kubernetes operation (like Jobs for hooks)")
116116
f.BoolVar(&upgrade.resetValues, "reset-values", false, "when upgrading, reset the values to the ones built into the chart")
117-
f.BoolVar(&upgrade.wait, "wait", false, "if set, will wait until all Pods, PVCs, and Services are in a ready state before marking the release as successful. It will wait for as long as --timeout")
117+
f.BoolVar(&upgrade.wait, "wait", false, "if set, will wait until all Pods, PVCs, Services, and minimum number of Pods of a Deployment are in a ready state before marking the release as successful. It will wait for as long as --timeout")
118118

119119
f.MarkDeprecated("disable-hooks", "use --no-hooks instead")
120120

docs/using_helm.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,11 +353,15 @@ is not a full list of cli flags. To see a description of all flags, just run
353353

354354
- `--timeout`: A value in seconds to wait for Kubernetes commands to complete
355355
This defaults to 300 (5 minutes)
356-
- `--wait`: Waits until all Pods are in a ready state, PVCs are bound, and
356+
- `--wait`: Waits until all Pods are in a ready state, PVCs are bound, Deployments
357+
have minimum (`Desired` minus `maxUnavailable`) Pods in ready state and
357358
Services have and IP address (and Ingress if a `LoadBalancer`) before
358359
marking the release as successful. It will wait for as long as the
359360
`--timeout` value. If timeout is reached, the release will be marked as
360361
`FAILED`.
362+
363+
Note: In scenario where Deployment has `replicas` set to 1 and `maxUnavailable` is not set to 0 as part of rolling
364+
update strategy, `--wait` will return as ready as it has satisfied the minimum Pod in ready condition.
361365
- `--no-hooks`: This skips running hooks for the command
362366
- `--recreate-pods` (only available for `upgrade` and `rollback`): This flag
363367
will cause all pods to be recreated (with the exception of pods belonging to

pkg/kube/client.go

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@ import (
3434
apps "k8s.io/kubernetes/pkg/apis/apps/v1beta1"
3535
batchinternal "k8s.io/kubernetes/pkg/apis/batch"
3636
batch "k8s.io/kubernetes/pkg/apis/batch/v1"
37+
ext "k8s.io/kubernetes/pkg/apis/extensions"
3738
extensions "k8s.io/kubernetes/pkg/apis/extensions/v1beta1"
3839
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
3940
conditions "k8s.io/kubernetes/pkg/client/unversioned"
4041
"k8s.io/kubernetes/pkg/client/unversioned/clientcmd"
42+
deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util"
4143
"k8s.io/kubernetes/pkg/fields"
4244
"k8s.io/kubernetes/pkg/kubectl"
4345
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
@@ -59,6 +61,12 @@ type Client struct {
5961
SchemaCacheDir string
6062
}
6163

64+
// deployment holds associated replicaSets for a deployment
65+
type deployment struct {
66+
replicaSets *ext.ReplicaSet
67+
deployment *ext.Deployment
68+
}
69+
6270
// New create a new Client
6371
func New(config clientcmd.ClientConfig) *Client {
6472
return &Client{
@@ -541,6 +549,15 @@ func volumesReady(vols []api.PersistentVolumeClaim) bool {
541549
return true
542550
}
543551

552+
func deploymentsReady(deployments []deployment) bool {
553+
for _, v := range deployments {
554+
if !(v.replicaSets.Status.ReadyReplicas >= v.deployment.Spec.Replicas-deploymentutil.MaxUnavailable(*v.deployment)) {
555+
return false
556+
}
557+
}
558+
return true
559+
}
560+
544561
func getPods(client *internalclientset.Clientset, namespace string, selector map[string]string) ([]api.Pod, error) {
545562
list, err := client.Pods(namespace).List(api.ListOptions{
546563
FieldSelector: fields.Everything(),
@@ -569,6 +586,8 @@ func (c *Client) waitForResources(timeout time.Duration, created Result) error {
569586
pods := []api.Pod{}
570587
services := []api.Service{}
571588
pvc := []api.PersistentVolumeClaim{}
589+
replicaSets := []*ext.ReplicaSet{}
590+
deployments := []deployment{}
572591
for _, v := range created {
573592
obj, err := c.AsVersionedObject(v.Object)
574593
if err != nil && !runtime.IsNotRegisteredError(err) {
@@ -596,13 +615,25 @@ func (c *Client) waitForResources(timeout time.Duration, created Result) error {
596615
if err != nil {
597616
return false, err
598617
}
599-
for _, r := range rs.Items {
600-
list, err := getPods(client, value.Namespace, r.Spec.Selector.MatchLabels)
601-
if err != nil {
602-
return false, err
603-
}
604-
pods = append(pods, list...)
618+
619+
for i := range rs.Items {
620+
replicaSets = append(replicaSets, &rs.Items[i])
621+
}
622+
623+
currentDeployment, err := client.Deployments(value.Namespace).Get(value.Name)
624+
if err != nil {
625+
return false, err
626+
}
627+
// Find RS associated with deployment
628+
newReplicaSet, err := deploymentutil.FindNewReplicaSet(currentDeployment, replicaSets)
629+
if err != nil {
630+
return false, err
631+
}
632+
newDeployment := deployment{
633+
newReplicaSet,
634+
currentDeployment,
605635
}
636+
deployments = append(deployments, newDeployment)
606637
case (*extensions.DaemonSet):
607638
list, err := getPods(client, value.Namespace, value.Spec.Selector.MatchLabels)
608639
if err != nil {
@@ -635,7 +666,7 @@ func (c *Client) waitForResources(timeout time.Duration, created Result) error {
635666
services = append(services, *svc)
636667
}
637668
}
638-
return podsReady(pods) && servicesReady(services) && volumesReady(pvc), nil
669+
return podsReady(pods) && servicesReady(services) && volumesReady(pvc) && deploymentsReady(deployments), nil
639670
})
640671
}
641672

0 commit comments

Comments
 (0)