Skip to content

Commit

Permalink
ScaledObject scales any resource with /scale subresource
Browse files Browse the repository at this point in the history
Signed-off-by: Zbynek Roubalik <zroubali@redhat.com>
  • Loading branch information
Zbynek Roubalik committed Aug 6, 2020
1 parent 6385884 commit ea77878
Show file tree
Hide file tree
Showing 22 changed files with 875 additions and 533 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ To be KEDA to be fully operational we need to deploy Metrics Server first.
1. Deploy CRDs and KEDA into `keda` namespace
```bash
kubectl apply -f deploy/crds/keda.sh_scaledobjects_crd.yaml
kubectl apply -f deploy/crds/keda.sh_scaledjob_crd.yaml
kubectl apply -f deploy/crds/keda.sh_triggerauthentications_crd.yaml
kubectl apply -f deploy/
```
Expand Down
2 changes: 1 addition & 1 deletion cmd/adapter/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func (a *Adapter) makeProviderOrDie() provider.MetricsProvider {
os.Exit(1)
}

handler := handler.NewScaleHandler(kubeclient, scheme)
handler := handler.NewScaleHandler(kubeclient, nil, scheme)

namespace, err := k8sutil.GetWatchNamespace()
if err != nil {
Expand Down
20 changes: 20 additions & 0 deletions deploy/crds/keda.sh_scaledobjects_crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,28 @@ spec:
lastActiveTime:
format: date-time
type: string
scaleTargetGVKR:
description: GroupVersionKindResource provides unified structure for
schema.GroupVersionKind and Resource
properties:
group:
type: string
kind:
type: string
resource:
type: string
version:
type: string
required:
- group
- kind
- resource
- version
type: object
scaleTargetKind:
type: string
required:
- scaleTargetGVKR
type: object
required:
- spec
Expand Down
2 changes: 1 addition & 1 deletion deploy/crds/keda.sh_triggerauthentications_crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ spec:
env:
items:
description: AuthEnvironment is used to authenticate using environment
variables in the destination deployment spec
variables in the destination ScaleTarget spec
properties:
containerName:
type: string
Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ require (
k8s.io/klog v1.0.0
k8s.io/kube-openapi v0.0.0-20191107075043-30be4d16710a
k8s.io/metrics v0.17.4
knative.dev/pkg v0.0.0-20200404181734-92cdec5b3593
pack.ag/amqp v0.12.5 // indirect
sigs.k8s.io/controller-runtime v0.5.2
)
Expand Down
4 changes: 4 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1058,6 +1058,7 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
Expand Down Expand Up @@ -1245,6 +1246,7 @@ k8s.io/api v0.17.2/go.mod h1:BS9fjjLc4CMuqfSO8vgbHPKMt5+SF0ET6u/RVDihTo4=
k8s.io/api v0.17.3/go.mod h1:YZ0OTkuw7ipbe305fMpIdf3GLXZKRigjtZaV5gzC2J0=
k8s.io/api v0.17.4 h1:HbwOhDapkguO8lTAE8OX3hdF2qp8GtpC9CW/MQATXXo=
k8s.io/api v0.17.4/go.mod h1:5qxx6vjmwUVG2nHQTKGlLts8Tbok8PzHl4vHtVFuZCA=
k8s.io/api v0.18.0 h1:lwYk8Vt7rsVTwjRU6pzEsa9YNhThbmbocQlKvNBB4EQ=
k8s.io/apiextensions-apiserver v0.0.0-20190918161926-8f644eb6e783/go.mod h1:xvae1SZB3E17UpV59AWc271W/Ph25N+bjPyR63X6tPY=
k8s.io/apiextensions-apiserver v0.16.7/go.mod h1:6xYRp4trGp6eT5WZ6tPi/TB2nfWQCzwUvBlpg8iswe0=
k8s.io/apiextensions-apiserver v0.17.0/go.mod h1:XiIFUakZywkUl54fVXa7QTEHcqQz9HG55nHd1DCoHj8=
Expand Down Expand Up @@ -1318,6 +1320,8 @@ k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl
k8s.io/utils v0.0.0-20191114184206-e782cd3c129f/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
k8s.io/utils v0.0.0-20191114200735-6ca3b61696b6 h1:p0Ai3qVtkbCG/Af26dBmU0E1W58NID3hSSh7cMyylpM=
k8s.io/utils v0.0.0-20191114200735-6ca3b61696b6/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
knative.dev/pkg v0.0.0-20200404181734-92cdec5b3593 h1:ubDiFWWncTD4TkA3hDH/JgGOYJlp3qyUjXf2rEIRLiM=
knative.dev/pkg v0.0.0-20200404181734-92cdec5b3593/go.mod h1:pgODObA1dTyhNoFxPZTTjNWfx6F0aKsKzn+vaT9XO/Q=
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
Expand Down
16 changes: 10 additions & 6 deletions pkg/apis/keda/v1alpha1/scaledobject_types.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package v1alpha1

import (
kedautil "github.com/kedacore/keda/pkg/util"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand Down Expand Up @@ -34,24 +36,23 @@ type ScaledObjectSpec struct {
// +optional
MinReplicaCount *int32 `json:"minReplicaCount,omitempty"`
// +optional
MaxReplicaCount *int32 `json:"maxReplicaCount,omitempty"`
Triggers []ScaleTriggers `json:"triggers"`
MaxReplicaCount *int32 `json:"maxReplicaCount,omitempty"`
Triggers []ScaleTriggers `json:"triggers"`
}

//ScaleTarget holds the a reference to the scale target Object
// +k8s:openapi-gen=true
type ScaleTarget struct {
Name string `json:"name"`
// +optional
ApiVersion string `json:"apiVersion,omitempty"`
ApiVersion string `json:"apiVersion,omitempty"`
// +optional
Kind string `json:"kind,omitempty"`

// +optional
ContainerName string `json:"containerName,omitempty"`
}


// ScaleTriggers reference the scaler that will be used
// +k8s:openapi-gen=true
type ScaleTriggers struct {
Expand All @@ -67,8 +68,11 @@ type ScaleTriggers struct {
// +k8s:openapi-gen=true
// +optional
type ScaledObjectStatus struct {
// +optionl
ScaleTargetKind string `json:"scaleTargetKind,omitempty"`
// +optional
ScaleTargetKind string `json:"scaleTargetKind,omitempty"`

ScaleTargetGVKR *kedautil.GroupVersionKindResource `json:"scaleTargetGVKR"`

// +optional
LastActiveTime *metav1.Time `json:"lastActiveTime,omitempty"`
// +optional
Expand Down
2 changes: 1 addition & 1 deletion pkg/apis/keda/v1alpha1/triggerauthentication_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ type AuthSecretTargetRef struct {
}

// AuthEnvironment is used to authenticate using environment variables
// in the destination deployment spec
// in the destination ScaleTarget spec
// +k8s:openapi-gen=true
type AuthEnvironment struct {
Parameter string `json:"parameter"`
Expand Down
6 changes: 6 additions & 0 deletions pkg/apis/keda/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

144 changes: 144 additions & 0 deletions pkg/controller/scaledjob/scaledjob_controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
package scaledjob

import (
"context"

kedav1alpha1 "github.com/kedacore/keda/pkg/apis/keda/v1alpha1"

"k8s.io/apimachinery/pkg/api/errors"
//metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
//"k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller"
//"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/handler"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
"sigs.k8s.io/controller-runtime/pkg/source"
)

var log = logf.Log.WithName("controller_scaledjob")

/**
* USER ACTION REQUIRED: This is a scaffold file intended for the user to modify with their own Controller
* business logic. Delete these comments after modifying this file.*
*/

// Add creates a new ScaledJob Controller and adds it to the Manager. The Manager will set fields on the Controller
// and Start it when the Manager is Started.
func Add(mgr manager.Manager) error {
return add(mgr, newReconciler(mgr))
}

// newReconciler returns a new reconcile.Reconciler
func newReconciler(mgr manager.Manager) reconcile.Reconciler {
return &ReconcileScaledJob{client: mgr.GetClient(), scheme: mgr.GetScheme()}
}

// add adds a new Controller to mgr with r as the reconcile.Reconciler
func add(mgr manager.Manager, r reconcile.Reconciler) error {
// Create a new controller
c, err := controller.New("scaledjob-controller", mgr, controller.Options{Reconciler: r})
if err != nil {
return err
}

// Watch for changes to primary resource ScaledJob
err = c.Watch(&source.Kind{Type: &kedav1alpha1.ScaledJob{}}, &handler.EnqueueRequestForObject{})
if err != nil {
return err
}

// TODO(user): Modify this to be the types you create that are owned by the primary resource
// Watch for changes to secondary resource Pods and requeue the owner ScaledJob
// err = c.Watch(&source.Kind{Type: &corev1.Pod{}}, &handler.EnqueueRequestForOwner{
// IsController: true,
// OwnerType: &kedav1alpha1.ScaledJob{},
// })
if err != nil {
return err
}

return nil
}

// blank assignment to verify that ReconcileScaledJob implements reconcile.Reconciler
var _ reconcile.Reconciler = &ReconcileScaledJob{}

// ReconcileScaledJob reconciles a ScaledJob object
type ReconcileScaledJob struct {
// This client, initialized using mgr.Client() above, is a split client
// that reads objects from the cache and writes to the apiserver
client client.Client
scheme *runtime.Scheme
}

// Reconcile reads that state of the cluster for a ScaledJob object and makes changes based on the state read
// and what is in the ScaledJob.Spec
// TODO(user): Modify this Reconcile function to implement your Controller logic. This example creates
// a Pod as an example
// Note:
// The Controller will requeue the Request to be processed again if the returned error is non-nil or
// Result.Requeue is true, otherwise upon completion it will remove the work from the queue.
func (r *ReconcileScaledJob) Reconcile(request reconcile.Request) (reconcile.Result, error) {
reqLogger := log.WithValues("Request.Namespace", request.Namespace, "Request.Name", request.Name)
reqLogger.Info("Reconciling ScaledJob")

// Fetch the ScaledJob instance
instance := &kedav1alpha1.ScaledJob{}
err := r.client.Get(context.TODO(), request.NamespacedName, instance)
if err != nil {
if errors.IsNotFound(err) {
// Request object not found, could have been deleted after reconcile request.
// Owned objects are automatically garbage collected. For additional cleanup logic use finalizers.
// Return and don't requeue
return reconcile.Result{}, nil
}
// Error reading the object - requeue the request.
return reconcile.Result{}, err
}

reqLogger.Info("Reconciling ScaledJob is NOT IMPLEMENTED yet")

return reconcile.Result{}, nil
}

// FIXME use ScaledJob
// reconcileJobType implemets reconciler logic for K8s Jobs based ScaleObject
// func (r *ReconcileScaledObject) reconcileJobType(logger logr.Logger, scaledObject *kedav1alpha1.ScaledObject) ( error) {
// // scaledObject.Spec.ScaleType = kedav1alpha1.ScaleTypeJob

// // Delete Jobs owned by the previous version of the ScaledObject
// opts := []client.ListOption{
// client.InNamespace(scaledObject.GetNamespace()),
// client.MatchingLabels(map[string]string{"scaledobject": scaledObject.GetName()}),
// }
// jobs := &batchv1.JobList{}
// err := r.client.List(context.TODO(), jobs, opts...)
// if err != nil {
// logger.Error(err, "Cannot get list of Jobs owned by this ScaledObject")
// return err
// }

// if jobs.Size() > 0 {
// logger.Info("Deleting jobs owned by the previous version of the ScaledObject", "Number of jobs to delete", jobs.Size())
// }
// for _, job := range jobs.Items {
// err = r.client.Delete(context.TODO(), &job, client.PropagationPolicy(metav1.DeletePropagationBackground))
// if err != nil {
// logger.Error(err, "Not able to delete job", "Job", job.Name)
// return err
// }
// }

// // ScaledObject was created or modified - let's start a new ScaleLoop
// err = r.startScaleLoop(logger, scaledObject)
// if err != nil {
// logger.Error(err, "Failed to start a new ScaleLoop")
// return err
// }

// return nil
// }
Loading

0 comments on commit ea77878

Please sign in to comment.