Skip to content

Commit 8cbe374

Browse files
committed
Enable safe handling of range limits for replicas
Correct drift within limits available for community (hobbyist) users. Signed-off-by: Alex Ellis (OpenFaaS Ltd) <[email protected]>
1 parent 9874b8a commit 8cbe374

File tree

5 files changed

+90
-2
lines changed

5 files changed

+90
-2
lines changed

Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ RUN GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build \
2727
--ldflags "-s -w \
2828
-X github.com/openfaas/faas-netes/version.GitCommit=${GIT_COMMIT}\
2929
-X github.com/openfaas/faas-netes/version.Version=${VERSION}" \
30-
-a -installsuffix cgo -o faas-netes .
30+
-o faas-netes .
3131

3232
FROM --platform=${TARGETPLATFORM:-linux/amd64} alpine:3.17 as ship
3333
LABEL org.label-schema.license="MIT" \

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ ${CODEGEN_PKG}: $(TOOLS_DIR)/code-generator.mod
2929
@cd $(TOOLS_DIR) && go mod download -modfile=code-generator.mod
3030

3131
local:
32-
CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o faas-netes
32+
CGO_ENABLED=0 GOOS=linux go build -o faas-netes
3333

3434
build-docker:
3535
docker build \

main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
informers "github.com/openfaas/faas-netes/pkg/client/informers/externalversions"
1616
v1 "github.com/openfaas/faas-netes/pkg/client/informers/externalversions/openfaas/v1"
1717
"github.com/openfaas/faas-netes/pkg/config"
18+
"github.com/openfaas/faas-netes/pkg/controller"
1819
"github.com/openfaas/faas-netes/pkg/handlers"
1920
"github.com/openfaas/faas-netes/pkg/k8s"
2021
"github.com/openfaas/faas-netes/pkg/signals"
@@ -197,6 +198,7 @@ func runController(setup serverSetup) {
197198
stopCh := signals.SetupSignalHandler()
198199
operator := false
199200
listers := startInformers(setup, stopCh, operator)
201+
controller.RegisterEventHandlers(listers.DeploymentInformer, kubeClient, config.DefaultFunctionNamespace)
200202

201203
functionLookup := k8s.NewFunctionLookup(config.DefaultFunctionNamespace, listers.EndpointsInformer.Lister())
202204

pkg/controller/controller.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ func (c *Controller) handleObject(obj interface{}) {
368368
}
369369
glog.V(4).Infof("Recovered deleted object '%s' from tombstone", object.GetName())
370370
}
371+
371372
glog.V(4).Infof("Processing object: %s", object.GetName())
372373
if ownerRef := metav1.GetControllerOf(object); ownerRef != nil {
373374
// If this object is not owned by a function, we should not do anything more

pkg/controller/informers.go

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
package controller
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/openfaas/faas-netes/pkg/handlers"
8+
appsv1 "k8s.io/api/apps/v1"
9+
"k8s.io/apimachinery/pkg/api/errors"
10+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
11+
"k8s.io/apimachinery/pkg/labels"
12+
v1apps "k8s.io/client-go/informers/apps/v1"
13+
"k8s.io/client-go/kubernetes"
14+
"k8s.io/client-go/tools/cache"
15+
"k8s.io/klog"
16+
)
17+
18+
func RegisterEventHandlers(deploymentInformer v1apps.DeploymentInformer, kubeClient *kubernetes.Clientset, namespace string) {
19+
deploymentInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
20+
AddFunc: func(obj interface{}) {
21+
deployment, ok := obj.(*appsv1.Deployment)
22+
if !ok || deployment == nil {
23+
return
24+
}
25+
if err := applyValidation(deployment, kubeClient); err != nil {
26+
klog.Info(err)
27+
}
28+
},
29+
UpdateFunc: func(oldObj, newObj interface{}) {
30+
deployment, ok := newObj.(*appsv1.Deployment)
31+
if !ok || deployment == nil {
32+
return
33+
}
34+
if err := applyValidation(deployment, kubeClient); err != nil {
35+
klog.Info(err)
36+
}
37+
},
38+
})
39+
40+
list, err := deploymentInformer.Lister().Deployments(namespace).List(labels.Everything())
41+
if err != nil {
42+
klog.Info(err)
43+
return
44+
}
45+
46+
for _, deployment := range list {
47+
if err := applyValidation(deployment, kubeClient); err != nil {
48+
klog.Info(err)
49+
}
50+
}
51+
}
52+
53+
func applyValidation(deployment *appsv1.Deployment, kubeClient *kubernetes.Clientset) error {
54+
if deployment.Spec.Replicas == nil {
55+
return nil
56+
}
57+
58+
if _, ok := deployment.Spec.Template.Labels["faas_function"]; !ok {
59+
return nil
60+
}
61+
62+
current := *deployment.Spec.Replicas
63+
var target int
64+
if current == 0 {
65+
target = 1
66+
} else if current > handlers.MaxReplicas {
67+
target = handlers.MaxReplicas
68+
} else {
69+
return nil
70+
}
71+
clone := deployment.DeepCopy()
72+
73+
value := int32(target)
74+
clone.Spec.Replicas = &value
75+
76+
if _, err := kubeClient.AppsV1().Deployments(deployment.Namespace).
77+
Update(context.Background(), clone, metav1.UpdateOptions{}); err != nil {
78+
if errors.IsConflict(err) {
79+
return nil
80+
}
81+
return fmt.Errorf("error scaling %s to %d replicas: %w", deployment.Name, value, err)
82+
}
83+
84+
return nil
85+
}

0 commit comments

Comments
 (0)