From 2f252e95242849123fa7826748cbfd050fde870c Mon Sep 17 00:00:00 2001 From: Yaroslav Molochko Date: Tue, 6 Mar 2018 02:21:17 +0200 Subject: [PATCH] Add --replicas option for HA fixes #2334 --- cmd/helm/init.go | 3 +++ cmd/helm/installer/install.go | 1 + cmd/helm/installer/install_test.go | 27 +++++++++++++++++++++++++++ cmd/helm/installer/options.go | 13 +++++++++++++ docs/helm/helm_init.md | 3 ++- 5 files changed, 46 insertions(+), 1 deletion(-) diff --git a/cmd/helm/init.go b/cmd/helm/init.go index cccd8a83d..49adfc2c3 100644 --- a/cmd/helm/init.go +++ b/cmd/helm/init.go @@ -86,6 +86,7 @@ type initCmd struct { kubeClient kubernetes.Interface serviceAccount string maxHistory int + replicas int wait bool } @@ -130,6 +131,7 @@ func newInitCmd(out io.Writer) *cobra.Command { f.BoolVar(&i.opts.EnableHostNetwork, "net-host", false, "install Tiller with net=host") f.StringVar(&i.serviceAccount, "service-account", "", "name of service account") f.IntVar(&i.maxHistory, "history-max", 0, "limit the maximum number of revisions saved per release. Use 0 for no limit.") + f.IntVar(&i.replicas, "replicas", 1, "amount of tiller instances to run on the cluster") f.StringVar(&i.opts.NodeSelectors, "node-selectors", "", "labels to specify the node on which Tiller is installed (app=tiller,helm=rocks)") f.VarP(&i.opts.Output, "output", "o", "skip installation and output Tiller's manifest in specified format (json or yaml)") @@ -175,6 +177,7 @@ func (i *initCmd) run() error { i.opts.ForceUpgrade = i.forceUpgrade i.opts.ServiceAccount = i.serviceAccount i.opts.MaxHistory = i.maxHistory + i.opts.Replicas = i.replicas writeYAMLManifest := func(apiVersion, kind, body string, first, last bool) error { w := i.out diff --git a/cmd/helm/installer/install.go b/cmd/helm/installer/install.go index 230c7b39b..fc81fa26b 100644 --- a/cmd/helm/installer/install.go +++ b/cmd/helm/installer/install.go @@ -183,6 +183,7 @@ func generateDeployment(opts *Options) (*v1beta1.Deployment, error) { Labels: labels, }, Spec: v1beta1.DeploymentSpec{ + Replicas: opts.getReplicas(), Template: v1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: labels, diff --git a/cmd/helm/installer/install_test.go b/cmd/helm/installer/install_test.go index eaea05870..dbb7143e3 100644 --- a/cmd/helm/installer/install_test.go +++ b/cmd/helm/installer/install_test.go @@ -211,6 +211,10 @@ func TestInstall(t *testing.T) { if ports != 2 { t.Errorf("expected ports = 2, got '%d'", ports) } + replicas := obj.Spec.Replicas + if int(*replicas) != 1 { + t.Errorf("expected replicas = 1, got '%d'", replicas) + } return true, obj, nil }) fc.AddReactor("create", "services", func(action testcore.Action) (bool, runtime.Object, error) { @@ -236,6 +240,29 @@ func TestInstall(t *testing.T) { } } +func TestInstallHA(t *testing.T) { + image := "gcr.io/kubernetes-helm/tiller:v2.0.0" + + fc := &fake.Clientset{} + fc.AddReactor("create", "deployments", func(action testcore.Action) (bool, runtime.Object, error) { + obj := action.(testcore.CreateAction).GetObject().(*v1beta1.Deployment) + replicas := obj.Spec.Replicas + if int(*replicas) != 2 { + t.Errorf("expected replicas = 2, got '%d'", replicas) + } + return true, obj, nil + }) + + opts := &Options{ + Namespace: v1.NamespaceDefault, + ImageSpec: image, + Replicas: 2, + } + if err := Install(fc, opts); err != nil { + t.Errorf("unexpected error: %#+v", err) + } +} + func TestInstall_WithTLS(t *testing.T) { image := "gcr.io/kubernetes-helm/tiller:v2.0.0" name := "tiller-secret" diff --git a/cmd/helm/installer/options.go b/cmd/helm/installer/options.go index edff2740f..13cf43dcc 100644 --- a/cmd/helm/installer/options.go +++ b/cmd/helm/installer/options.go @@ -81,6 +81,11 @@ type Options struct { // Less than or equal to zero means no limit. MaxHistory int + // Replicas sets the amount of Tiller replicas to start + // + // Less than or equals to 1 means 1. + Replicas int + // NodeSelectors determine which nodes Tiller can land on. NodeSelectors string @@ -109,6 +114,14 @@ func (opts *Options) pullPolicy() v1.PullPolicy { return v1.PullIfNotPresent } +func (opts *Options) getReplicas() *int32 { + replicas := int32(1) + if opts.Replicas > 1 { + replicas = int32(opts.Replicas) + } + return &replicas +} + func (opts *Options) tls() bool { return opts.EnableTLS || opts.VerifyTLS } // valuesMap returns user set values in map format diff --git a/docs/helm/helm_init.md b/docs/helm/helm_init.md index 856e9b565..5ed24e60d 100644 --- a/docs/helm/helm_init.md +++ b/docs/helm/helm_init.md @@ -43,6 +43,7 @@ helm init --node-selectors string labels to specify the node on which Tiller is installed (app=tiller,helm=rocks) -o, --output OutputFormat skip installation and output Tiller's manifest in specified format (json or yaml) --override stringArray override values for the Tiller Deployment manifest (can specify multiple or separate values with commas: key1=val1,key2=val2) + --replicas int amount of tiller instances to run on the cluster (default 1) --service-account string name of service account --skip-refresh do not refresh (download) the local repository cache --stable-repo-url string URL for stable repository (default "https://kubernetes-charts.storage.googleapis.com") @@ -69,4 +70,4 @@ helm init ### SEE ALSO * [helm](helm.md) - The Helm package manager for Kubernetes. -###### Auto generated by spf13/cobra on 25-Jan-2018 +###### Auto generated by spf13/cobra on 6-Mar-2018