Skip to content

Commit

Permalink
feat: rollout tested
Browse files Browse the repository at this point in the history
  • Loading branch information
ramantehlan committed Jul 2, 2024
1 parent b7dc393 commit 23c8926
Show file tree
Hide file tree
Showing 24 changed files with 388 additions and 178 deletions.
9 changes: 3 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,13 @@ helm-chart: ## Create Helm chart for the operator

.PHONY: generate-manifest
generate-manifest: ## Generate deploy manifest
kustomize build operator/config/default > ./operator/install.yaml
kustomize build resolver/config/ > ./resolver/install.yaml
kustomize build . > ./install.yaml

.PHONY: deploy
deploy: ## Deploy the operator and resolver
kubectl apply -f ./resolver/install.yaml
kubectl apply -f ./operator/install.yaml
kubectl apply -f ./install.yaml

.PHONY: undeploy
undeploy: ## Undeploy the operator and resolver
kubectl delete -f ./resolver/install.yaml
kubectl delete -f ./operator/install.yaml
kubectl delete -f ./install.yaml

6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,13 @@ The icon is <a href="https://www.flaticon.com/free-icons/full-screen" title="ful



---

```
Get argo rollout type locally
kubectl apply -f https://github.com/argoproj/argo-rollouts/releases/latest/download/install.yaml
```



Expand Down
2 changes: 1 addition & 1 deletion demo-elastiService.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ metadata:
spec:
queueTimeout: 4
idlePeriod: 20
minTargetReplicas: 1
minTargetReplicas: 2
service: emotion-class-svc
scaleTargetRef:
apiVersion: argoproj.io/v1alpha1
Expand Down
1 change: 1 addition & 0 deletions go.work.sum
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ github.com/fxamacker/cbor/v2 v2.6.0 h1:sU6J2usfADwWlYDAFhZBQ6TnLFBHxgesMrQfQgk1t
github.com/fxamacker/cbor/v2 v2.6.0/go.mod h1:pxXPTn3joSm21Gbwsv0w9OSA2y1HFR9qXEeXQVeNoDQ=
github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I=
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA=
github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3BopGUQ5a5Og=
github.com/go-gorp/gorp/v3 v3.0.5/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw=
github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
Expand Down
86 changes: 83 additions & 3 deletions operator/install.yaml → install.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
apiVersion: v1
kind: Namespace
metadata:
name: elasti
---
apiVersion: v1
kind: Namespace
metadata:
labels:
app.kubernetes.io/managed-by: kustomize
Expand Down Expand Up @@ -292,6 +297,35 @@ rules:
- update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: elasti-resolver-additional-access
rules:
- apiGroups:
- apps
resources:
- deployments
verbs:
- get
- list
- watch
- update
- patch
- apiGroups:
- ""
resources:
- services
- pods
verbs:
- get
- list
- watch
- update
- patch
- delete
- create
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
labels:
Expand Down Expand Up @@ -363,15 +397,15 @@ metadata:
labels:
app.kubernetes.io/managed-by: kustomize
app.kubernetes.io/name: elasti-operator
name: elasti-operator-resolver-additional-access-binding
name: elasti-resolver-additional-access-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: elasti-operator-additional-access
name: elasti-resolver-additional-access
subjects:
- kind: ServiceAccount
name: default
namespace: elasti-operator-system
namespace: elasti
---
apiVersion: v1
kind: Service
Expand Down Expand Up @@ -409,6 +443,20 @@ spec:
selector:
control-plane: controller-manager
---
apiVersion: v1
kind: Service
metadata:
name: resolver-service
namespace: elasti
spec:
ports:
- name: http-playground
port: 8012
protocol: TCP
selector:
app: elasti-resolver
type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
Expand Down Expand Up @@ -472,3 +520,35 @@ spec:
runAsNonRoot: true
serviceAccountName: elasti-operator-controller-manager
terminationGracePeriodSeconds: 10
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: elasti-resolver
namespace: elasti
spec:
replicas: 1
selector:
matchLabels:
app: elasti-resolver
template:
metadata:
labels:
app: elasti-resolver
spec:
containers:
- env:
- name: SYSTEM_NAMESPACE
value: elasti
image: ramantehlan/elasti-resolver:v1alpha1
imagePullPolicy: Always
name: playground
ports:
- containerPort: 8012
resources:
limits:
cpu: 750m
memory: 1Gi
requests:
cpu: 250m
memory: 500Mi
3 changes: 3 additions & 0 deletions kustomization.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
resources:
- operator/config/default
- resolver/config
16 changes: 0 additions & 16 deletions operator/config/rbac/role_additional_binding.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,3 @@ subjects:
- kind: ServiceAccount
name: elasti-operator-controller-manager
namespace: elasti-operator-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
labels:
app.kubernetes.io/name: elasti-operator
app.kubernetes.io/managed-by: kustomize
name: resolver-additional-access-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: additional-access
subjects:
- kind: ServiceAccount
name: default
namespace: elasti
2 changes: 1 addition & 1 deletion operator/config/rbac/service_account.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ metadata:
app.kubernetes.io/name: elasti-operator
app.kubernetes.io/managed-by: kustomize
name: controller-manager
namespace: system
namespace: system
89 changes: 16 additions & 73 deletions operator/internal/controller/elastiservice_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,18 @@ package controller

import (
"context"
"strings"
"sync"

"github.com/truefoundry/elasti/pkg/utils"
"truefoundry.io/elasti/internal/crdDirectory"
"truefoundry.io/elasti/internal/informer"

"k8s.io/apimachinery/pkg/api/errors"
kRuntime "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"

"truefoundry.io/elasti/api/v1alpha1"

"runtime"

"go.uber.org/zap"
)

Expand Down Expand Up @@ -59,23 +53,12 @@ const (
// For more details, check Reconcile and its Result here:
// - https://pkg.go.dev/sigs.k8s.io/controller-runtime@v0.17.3/pkg/reconcile
func (r *ElastiServiceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (res ctrl.Result, err error) {
defer func() {
if rErr := recover(); rErr != nil {
r.Logger.Error("Recovered from panic", zap.Any("recovered", rErr))
buf := make([]byte, 4096)
n := runtime.Stack(buf, false)
r.Logger.Error("Panic stack trace", zap.ByteString("stacktrace", buf[:n]))
}
}()

r.Logger.Debug("- In Reconcile", zap.String("es", req.NamespacedName.String()))
mutex := r.getMutexForReconcile(req.NamespacedName.String())
mutex.Lock()
defer r.Logger.Debug("- Out of Reconcile", zap.String("es", req.NamespacedName.String()))
defer mutex.Unlock()

// First we get the ElastiService object
// No mutex is taken for this, as we are not modifying the object, but if we face issues in future, we can add a mutex
es, esErr := r.getCRD(ctx, req.NamespacedName)
if esErr != nil {
if errors.IsNotFound(esErr) {
Expand All @@ -87,75 +70,35 @@ func (r *ElastiServiceReconciler) Reconcile(ctx context.Context, req ctrl.Reques
}

// If the ElastiService is being deleted, we need to clean up the resources
if !es.ObjectMeta.DeletionTimestamp.IsZero() {
if controllerutil.ContainsFinalizer(es, v1alpha1.ElastiServiceFinalizer) {
// If CRD contains finalizer, we call the finaizer function and remove the finalizer post that
if err := r.finalizeCRD(ctx, es, req); err != nil {
r.Logger.Error("Failed to enable serve mode", zap.String("es", req.String()), zap.Error(err))
return res, err
}
controllerutil.RemoveFinalizer(es, v1alpha1.ElastiServiceFinalizer)
if err := r.Update(ctx, es); err != nil {
return res, err
}
}
return res, nil
if err := r.checkIfCRDIsDeleted(ctx, es, req); err != nil {
r.Logger.Error("Failed to check if CRD is deleted", zap.String("es", req.String()), zap.Error(err))
return res, err
}

// We also check if the CRD has finalizer, and if not, we add the finalizer
if err := r.checkFinalizerCRD(ctx, es, req); err != nil {
if err := r.checkAndAddCRDFinalizer(ctx, es, req); err != nil {
r.Logger.Error("Failed to finalize CRD", zap.String("es", req.String()), zap.Error(err))
return res, err
}

// Check if ScaleTargetRef is present, and has not changed from the values in CRDDirectory
if err := r.checkChangesInScaleTargetRef(ctx, es, req); err != nil {
r.Logger.Error("Failed to check changes in ScaleTargetRef", zap.String("es", req.String()), zap.Error(err))
return res, err
}

// Check if Public Service is present, and has not changed from the values in CRDDirectory
if err := r.checkChangesInPublicService(ctx, es, req); err != nil {
r.Logger.Error("Failed to check changes in public service", zap.String("es", req.String()), zap.Error(err))
return res, err
}

// We add the CRD details to service directory, so when elasti server received a request,
// we can find the right resource to scale up
crdDirectory.CRDDirectory.AddCRD(es.Spec.Service, &crdDirectory.CRDDetails{
CRDName: es.Name,
Spec: es.Spec,
})

// We need to start the informer only once per CRD. This is to avoid multiple informers for the same CRD
// We reset mutex if crd is deleted, so it can be used again if the same CRD is reapplied
r.getMutexForInformerStart(req.NamespacedName.String()).Do(func() {
targetGroup, targetVersion, err := utils.ParseAPIVersion(es.Spec.ScaleTargetRef.APIVersion)
if err != nil {
r.Logger.Error("Failed to parse API version", zap.String("APIVersion", es.Spec.ScaleTargetRef.APIVersion), zap.Error(err))
return
}

// Watch for changes in ScaleTargetRef
r.Informer.Add(&informer.RequestWatch{
Req: req,
ResourceName: es.Spec.ScaleTargetRef.Name,
ResourceNamespace: req.Namespace,
GroupVersionResource: &schema.GroupVersionResource{
Group: targetGroup,
Version: targetVersion,
Resource: strings.ToLower(es.Spec.ScaleTargetRef.Kind),
},
Handlers: r.getScaleTargetRefChangeHandler(ctx, es, req),
})

// Watch for changes in public service
r.Informer.Add(&informer.RequestWatch{
Req: req,
ResourceName: es.Spec.Service,
ResourceNamespace: es.Namespace,
GroupVersionResource: &schema.GroupVersionResource{
Group: "",
Version: "v1",
Resource: "services",
},
Handlers: r.getPublicServiceChangeHandler(ctx, es, req),
})

r.Logger.Info("ScaleTargetRef and Public Service added to informer", zap.String("es", req.String()),
zap.String("scaleTargetRef", es.Spec.ScaleTargetRef.Name),
zap.String("public service", es.Spec.Service),
)
})

return res, nil
}

Expand Down
Loading

0 comments on commit 23c8926

Please sign in to comment.