2015-10-15 22:15:13 +00:00
/ *
2016-06-03 00:25:58 +00:00
Copyright 2015 The Kubernetes Authors .
2015-10-15 22:15:13 +00:00
Licensed under the Apache License , Version 2.0 ( the "License" ) ;
you may not use this file except in compliance with the License .
You may obtain a copy of the License at
http : //www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing , software
distributed under the License is distributed on an "AS IS" BASIS ,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
See the License for the specific language governing permissions and
limitations under the License .
* /
2018-10-05 11:06:12 +00:00
package autoscale
2015-10-15 22:15:13 +00:00
import (
"fmt"
2018-04-19 00:02:37 +00:00
"github.com/spf13/cobra"
2018-11-09 18:49:10 +00:00
"k8s.io/klog"
2018-04-19 00:02:37 +00:00
2018-04-27 15:38:34 +00:00
autoscalingv1 "k8s.io/api/autoscaling/v1"
2018-04-19 00:02:37 +00:00
"k8s.io/apimachinery/pkg/api/meta"
2018-08-21 10:46:39 +00:00
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/genericclioptions/printers"
"k8s.io/cli-runtime/pkg/genericclioptions/resource"
2018-04-27 15:38:34 +00:00
autoscalingv1client "k8s.io/client-go/kubernetes/typed/autoscaling/v1"
2015-10-15 22:15:13 +00:00
"k8s.io/kubernetes/pkg/kubectl"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
2018-09-09 06:59:55 +00:00
"k8s.io/kubernetes/pkg/kubectl/generate"
generateversioned "k8s.io/kubernetes/pkg/kubectl/generate/versioned"
2018-05-21 20:01:08 +00:00
"k8s.io/kubernetes/pkg/kubectl/polymorphichelpers"
2018-05-16 18:19:21 +00:00
"k8s.io/kubernetes/pkg/kubectl/scheme"
2017-07-07 04:04:11 +00:00
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
2018-10-10 18:29:30 +00:00
"k8s.io/kubernetes/pkg/kubectl/util/templates"
2015-10-15 22:15:13 +00:00
)
2016-05-20 17:49:56 +00:00
var (
2017-03-15 03:49:10 +00:00
autoscaleLong = templates . LongDesc ( i18n . T ( `
2016-05-20 17:49:56 +00:00
Creates an autoscaler that automatically chooses and sets the number of pods that run in a kubernetes cluster .
2015-10-15 22:15:13 +00:00
2018-11-16 02:42:39 +00:00
Looks up a Deployment , ReplicaSet , StatefulSet , or ReplicationController by name and creates an autoscaler that uses the given resource as a reference .
2017-03-15 03:49:10 +00:00
An autoscaler can automatically increase or decrease number of pods deployed within the system as needed . ` ) )
2015-10-15 22:15:13 +00:00
2017-03-15 03:49:10 +00:00
autoscaleExample = templates . Examples ( i18n . T ( `
2017-11-02 09:05:45 +00:00
# Auto scale a deployment "foo" , with the number of pods between 2 and 10 , no target CPU utilization specified so a default autoscaling policy will be used :
2016-05-20 17:49:56 +00:00
kubectl autoscale deployment foo -- min = 2 -- max = 10
2015-10-15 22:15:13 +00:00
2016-08-02 16:51:51 +00:00
# Auto scale a replication controller "foo" , with the number of pods between 1 and 5 , target CPU utilization at 80 % :
2017-03-15 03:49:10 +00:00
kubectl autoscale rc foo -- max = 5 -- cpu - percent = 80 ` ) )
2015-10-15 22:15:13 +00:00
)
2018-04-18 15:20:33 +00:00
type AutoscaleOptions struct {
2018-04-19 00:02:37 +00:00
FilenameOptions * resource . FilenameOptions
RecordFlags * genericclioptions . RecordFlags
Recorder genericclioptions . Recorder
2018-05-02 19:15:47 +00:00
PrintFlags * genericclioptions . PrintFlags
ToPrinter func ( string ) ( printers . ResourcePrinter , error )
2018-04-19 00:02:37 +00:00
2018-04-26 13:30:21 +00:00
Name string
Generator string
Min int32
Max int32
2018-10-30 10:35:24 +00:00
CPUPercent int32
2018-04-26 13:30:21 +00:00
createAnnotation bool
args [ ] string
enforceNamespace bool
namespace string
dryRun bool
builder * resource . Builder
2018-05-21 20:01:08 +00:00
canBeAutoscaled polymorphichelpers . CanBeAutoscaledFunc
2018-09-09 06:59:55 +00:00
generatorFunc func ( string , * meta . RESTMapping ) ( generate . StructuredGenerator , error )
2018-04-19 00:02:37 +00:00
2018-04-27 15:38:34 +00:00
HPAClient autoscalingv1client . HorizontalPodAutoscalersGetter
2018-04-19 00:02:37 +00:00
genericclioptions . IOStreams
2018-04-18 15:20:33 +00:00
}
2018-04-19 00:02:37 +00:00
func NewAutoscaleOptions ( ioStreams genericclioptions . IOStreams ) * AutoscaleOptions {
2018-04-18 15:20:33 +00:00
return & AutoscaleOptions {
2018-05-02 19:15:47 +00:00
PrintFlags : genericclioptions . NewPrintFlags ( "autoscaled" ) . WithTypeSetter ( scheme . Scheme ) ,
2018-04-19 00:02:37 +00:00
FilenameOptions : & resource . FilenameOptions { } ,
2018-04-18 15:20:33 +00:00
RecordFlags : genericclioptions . NewRecordFlags ( ) ,
2018-04-19 12:32:15 +00:00
Recorder : genericclioptions . NoopRecorder { } ,
2018-04-19 00:02:37 +00:00
IOStreams : ioStreams ,
2018-04-18 15:20:33 +00:00
}
}
2018-04-19 00:02:37 +00:00
func NewCmdAutoscale ( f cmdutil . Factory , ioStreams genericclioptions . IOStreams ) * cobra . Command {
o := NewAutoscaleOptions ( ioStreams )
2016-03-28 19:44:21 +00:00
2016-08-22 02:46:50 +00:00
validArgs := [ ] string { "deployment" , "replicaset" , "replicationcontroller" }
2015-10-15 22:15:13 +00:00
cmd := & cobra . Command {
2018-10-05 19:59:38 +00:00
Use : "autoscale (-f FILENAME | TYPE NAME | TYPE/NAME) [--min=MINPODS] --max=MAXPODS [--cpu-percent=CPU]" ,
2017-10-11 06:26:02 +00:00
DisableFlagsInUseLine : true ,
2018-10-05 19:59:38 +00:00
Short : i18n . T ( "Auto-scale a Deployment, ReplicaSet, or ReplicationController" ) ,
Long : autoscaleLong ,
Example : autoscaleExample ,
2015-10-15 22:15:13 +00:00
Run : func ( cmd * cobra . Command , args [ ] string ) {
2018-04-19 00:02:37 +00:00
cmdutil . CheckErr ( o . Complete ( f , cmd , args ) )
2018-04-26 13:30:21 +00:00
cmdutil . CheckErr ( o . Validate ( ) )
2018-04-19 00:02:37 +00:00
cmdutil . CheckErr ( o . Run ( ) )
2015-10-15 22:15:13 +00:00
} ,
2018-05-07 19:25:40 +00:00
ValidArgs : validArgs ,
2015-10-15 22:15:13 +00:00
}
2018-04-18 15:20:33 +00:00
// bind flag structs
o . RecordFlags . AddFlags ( cmd )
2018-04-19 00:02:37 +00:00
o . PrintFlags . AddFlags ( cmd )
2018-04-18 15:20:33 +00:00
2018-09-09 06:59:55 +00:00
cmd . Flags ( ) . StringVar ( & o . Generator , "generator" , generateversioned . HorizontalPodAutoscalerV1GeneratorName , i18n . T ( "The name of the API generator to use. Currently there is only 1 generator." ) )
2018-04-26 13:30:21 +00:00
cmd . Flags ( ) . Int32Var ( & o . Min , "min" , - 1 , "The lower limit for the number of pods that can be set by the autoscaler. If it's not specified or negative, the server will apply a default value." )
cmd . Flags ( ) . Int32Var ( & o . Max , "max" , - 1 , "The upper limit for the number of pods that can be set by the autoscaler. Required." )
2015-10-15 22:15:13 +00:00
cmd . MarkFlagRequired ( "max" )
2018-10-30 10:35:24 +00:00
cmd . Flags ( ) . Int32Var ( & o . CPUPercent , "cpu-percent" , - 1 , fmt . Sprintf ( "The target average CPU utilization (represented as a percent of requested CPU) over all the pods. If it's not specified or negative, a default autoscaling policy will be used." ) )
2018-04-26 13:30:21 +00:00
cmd . Flags ( ) . StringVar ( & o . Name , "name" , "" , i18n . T ( "The name for the newly created object. If not specified, the name of the input resource will be used." ) )
2016-05-11 00:26:39 +00:00
cmdutil . AddDryRunFlag ( cmd )
2018-04-26 13:30:21 +00:00
cmdutil . AddFilenameOptionFlags ( cmd , o . FilenameOptions , "identifying the resource to autoscale." )
2015-11-04 21:47:08 +00:00
cmdutil . AddApplyAnnotationFlags ( cmd )
2015-10-15 22:15:13 +00:00
return cmd
}
2018-04-19 00:02:37 +00:00
func ( o * AutoscaleOptions ) Complete ( f cmdutil . Factory , cmd * cobra . Command , args [ ] string ) error {
2018-04-30 12:04:43 +00:00
var err error
2018-04-26 13:30:21 +00:00
o . dryRun = cmdutil . GetFlagBool ( cmd , "dry-run" )
o . createAnnotation = cmdutil . GetFlagBool ( cmd , cmdutil . ApplyAnnotationsFlag )
o . builder = f . NewBuilder ( )
2018-05-21 20:01:08 +00:00
o . canBeAutoscaled = polymorphichelpers . CanBeAutoscaledFn
2018-04-26 13:30:21 +00:00
o . args = args
2018-05-21 19:27:11 +00:00
o . RecordFlags . Complete ( cmd )
2018-04-19 00:02:37 +00:00
2018-04-18 15:20:33 +00:00
o . Recorder , err = o . RecordFlags . ToRecorder ( )
if err != nil {
return err
}
2018-04-27 15:38:34 +00:00
kubeClient , err := f . KubernetesClientSet ( )
if err != nil {
return err
}
o . HPAClient = kubeClient . AutoscalingV1 ( )
2018-04-19 00:02:37 +00:00
// get the generator
2018-09-09 06:59:55 +00:00
o . generatorFunc = func ( name string , mapping * meta . RESTMapping ) ( generate . StructuredGenerator , error ) {
2018-04-26 13:30:21 +00:00
switch o . Generator {
2018-09-09 06:59:55 +00:00
case generateversioned . HorizontalPodAutoscalerV1GeneratorName :
return & generateversioned . HorizontalPodAutoscalerGeneratorV1 {
2018-04-19 00:02:37 +00:00
Name : name ,
2018-04-26 13:30:21 +00:00
MinReplicas : o . Min ,
MaxReplicas : o . Max ,
2018-10-30 10:35:24 +00:00
CPUPercent : o . CPUPercent ,
2018-04-19 00:02:37 +00:00
ScaleRefName : name ,
ScaleRefKind : mapping . GroupVersionKind . Kind ,
2018-10-30 09:48:27 +00:00
ScaleRefAPIVersion : mapping . GroupVersionKind . GroupVersion ( ) . String ( ) ,
2018-04-26 13:30:21 +00:00
} , nil
2018-04-19 00:02:37 +00:00
default :
2018-04-26 13:30:21 +00:00
return nil , cmdutil . UsageErrorf ( cmd , "Generator %s not supported. " , o . Generator )
2018-04-19 00:02:37 +00:00
}
}
2018-04-18 15:20:33 +00:00
2018-05-24 13:33:36 +00:00
o . namespace , o . enforceNamespace , err = f . ToRawKubeConfigLoader ( ) . Namespace ( )
2015-10-15 22:15:13 +00:00
if err != nil {
return err
}
2018-05-02 19:15:47 +00:00
o . ToPrinter = func ( operation string ) ( printers . ResourcePrinter , error ) {
2018-04-19 00:02:37 +00:00
o . PrintFlags . NamePrintFlags . Operation = operation
2018-04-26 13:30:21 +00:00
if o . dryRun {
2018-04-19 00:02:37 +00:00
o . PrintFlags . Complete ( "%s (dry run)" )
}
2018-05-02 19:15:47 +00:00
return o . PrintFlags . ToPrinter ( )
2018-04-19 00:02:37 +00:00
}
return nil
}
2018-04-26 13:30:21 +00:00
func ( o * AutoscaleOptions ) Validate ( ) error {
if o . Max < 1 {
return fmt . Errorf ( "--max=MAXPODS is required and must be at least 1, max: %d" , o . Max )
}
if o . Max < o . Min {
return fmt . Errorf ( "--max=MAXPODS must be larger or equal to --min=MINPODS, max: %d, min: %d" , o . Max , o . Min )
2015-10-15 22:15:13 +00:00
}
2018-04-19 00:02:37 +00:00
return nil
}
func ( o * AutoscaleOptions ) Run ( ) error {
2018-04-26 13:30:21 +00:00
r := o . builder .
2018-09-14 22:10:26 +00:00
WithScheme ( scheme . Scheme , scheme . Scheme . PrioritizedVersionsAllGroups ( ) ... ) .
2015-10-15 22:15:13 +00:00
ContinueOnError ( ) .
2018-04-26 13:30:21 +00:00
NamespaceParam ( o . namespace ) . DefaultNamespace ( ) .
FilenameParam ( o . enforceNamespace , o . FilenameOptions ) .
ResourceTypeOrNameArgs ( false , o . args ... ) .
2015-10-15 22:15:13 +00:00
Flatten ( ) .
Do ( )
2018-04-19 00:02:37 +00:00
if err := r . Err ( ) ; err != nil {
2015-10-15 22:15:13 +00:00
return err
}
2016-04-14 22:00:40 +00:00
count := 0
2018-04-19 00:02:37 +00:00
err := r . Visit ( func ( info * resource . Info , err error ) error {
2016-04-14 22:00:40 +00:00
if err != nil {
return err
}
2015-10-15 22:15:13 +00:00
2016-04-14 22:00:40 +00:00
mapping := info . ResourceMapping ( )
2018-04-26 13:30:21 +00:00
if err := o . canBeAutoscaled ( mapping . GroupVersionKind . GroupKind ( ) ) ; err != nil {
2016-04-14 22:00:40 +00:00
return err
}
2015-10-15 22:15:13 +00:00
2018-04-26 13:30:21 +00:00
generator , err := o . generatorFunc ( info . Name , mapping )
2018-04-19 00:02:37 +00:00
if err != nil {
return err
2016-01-22 18:33:23 +00:00
}
2015-10-15 22:15:13 +00:00
2016-04-14 22:00:40 +00:00
// Generate new object
2017-11-16 09:29:47 +00:00
object , err := generator . StructuredGenerate ( )
2016-04-14 22:00:40 +00:00
if err != nil {
return err
}
2018-04-27 15:38:34 +00:00
hpa , ok := object . ( * autoscalingv1 . HorizontalPodAutoscaler )
if ! ok {
return fmt . Errorf ( "generator made %T, not autoscalingv1.HorizontalPodAutoscaler" , object )
2016-04-14 22:00:40 +00:00
}
2018-04-27 15:38:34 +00:00
if err := o . Recorder . Record ( hpa ) ; err != nil {
2018-11-09 18:49:10 +00:00
klog . V ( 4 ) . Infof ( "error recording current command: %v" , err )
2016-04-14 22:00:40 +00:00
}
2018-04-19 00:02:37 +00:00
2018-04-26 13:30:21 +00:00
if o . dryRun {
2018-04-19 00:02:37 +00:00
count ++
printer , err := o . ToPrinter ( "created" )
if err != nil {
return err
}
2018-04-27 15:38:34 +00:00
return printer . PrintObj ( hpa , o . Out )
2016-04-14 22:00:40 +00:00
}
2018-09-14 22:10:26 +00:00
if err := kubectl . CreateOrUpdateAnnotation ( o . createAnnotation , hpa , scheme . DefaultJSONEncoder ( ) ) ; err != nil {
2016-04-14 22:00:40 +00:00
return err
}
2018-04-27 15:38:34 +00:00
actualHPA , err := o . HPAClient . HorizontalPodAutoscalers ( o . namespace ) . Create ( hpa )
2016-04-14 22:00:40 +00:00
if err != nil {
return err
}
count ++
2018-04-19 00:02:37 +00:00
printer , err := o . ToPrinter ( "autoscaled" )
if err != nil {
return err
2016-04-14 22:00:40 +00:00
}
2018-04-27 15:38:34 +00:00
return printer . PrintObj ( actualHPA , o . Out )
2016-04-14 22:00:40 +00:00
} )
2015-10-15 22:15:13 +00:00
if err != nil {
return err
}
2016-04-14 22:00:40 +00:00
if count == 0 {
return fmt . Errorf ( "no objects passed to autoscale" )
2015-10-15 22:15:13 +00:00
}
return nil
}