Function Update if config/secret changes (#1224)
* Config and secret change to invoke function update * Added recycle function for pool manager as well - where it recycles the specialized pods * Switched to rolling update of pods and env variable based change instead of deleting pods in new deploy executor
This commit is contained in:
@@ -185,6 +185,9 @@ func (deploy *NewDeploy) getDeploymentSpec(fn *fv1.Function, env *fv1.Environmen
|
||||
}
|
||||
resources := deploy.getResources(env, fn)
|
||||
|
||||
maxUnavailable := intstr.FromString("20%")
|
||||
maxSurge := intstr.FromString("100%")
|
||||
|
||||
deployment := &v1beta1.Deployment{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: deployName,
|
||||
@@ -217,6 +220,12 @@ func (deploy *NewDeploy) getDeploymentSpec(fn *fv1.Function, env *fv1.Environmen
|
||||
},
|
||||
},
|
||||
},
|
||||
Env: []apiv1.EnvVar{
|
||||
{
|
||||
Name: fv1.LastUpdateTimestamp,
|
||||
Value: time.Now().String(),
|
||||
},
|
||||
},
|
||||
// https://istio.io/docs/setup/kubernetes/additional-setup/requirements/
|
||||
Ports: []apiv1.ContainerPort{
|
||||
{
|
||||
@@ -231,6 +240,13 @@ func (deploy *NewDeploy) getDeploymentSpec(fn *fv1.Function, env *fv1.Environmen
|
||||
TerminationGracePeriodSeconds: &gracePeriodSeconds,
|
||||
},
|
||||
},
|
||||
Strategy: v1beta1.DeploymentStrategy{
|
||||
Type: v1beta1.RollingUpdateDeploymentStrategyType,
|
||||
RollingUpdate: &v1beta1.RollingUpdateDeployment{
|
||||
MaxUnavailable: &maxUnavailable,
|
||||
MaxSurge: &maxSurge,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ import (
|
||||
k8sErrs "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
k8sTypes "k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
@@ -220,6 +221,45 @@ func (deploy *NewDeploy) GetFuncSvc(ctx context.Context, metadata *metav1.Object
|
||||
return deploy.createFunction(fn, false)
|
||||
}
|
||||
|
||||
// RefreshFuncPods deleted pods related to the function so that new pods are replenished
|
||||
func (deploy *NewDeploy) RefreshFuncPods(logger *zap.Logger, f fv1.Function) error {
|
||||
|
||||
env, err := deploy.fissionClient.Environments(f.Spec.Environment.Namespace).Get(f.Spec.Environment.Name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
funcLabels := deploy.getDeployLabels(f.Metadata, metav1.ObjectMeta{
|
||||
Name: f.Spec.Environment.Name,
|
||||
Namespace: f.Spec.Environment.Namespace,
|
||||
UID: env.Metadata.UID,
|
||||
})
|
||||
|
||||
dep, err := deploy.kubernetesClient.ExtensionsV1beta1().Deployments(metav1.NamespaceAll).List(metav1.ListOptions{
|
||||
LabelSelector: labels.Set(funcLabels).AsSelector().String(),
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
patch := fmt.Sprintf(`{"spec" : {"template": {"spec":{"containers":[{"name": "%s", "env":[{"name": "%s", "value": "%s"}]}]}}}}`,
|
||||
f.Metadata.Name,
|
||||
fv1.LastUpdateTimestamp,
|
||||
time.Now().String())
|
||||
|
||||
// Ideally there should be only one deployment but for now we rely on label/selector to ensure that condition
|
||||
for _, deployment := range dep.Items {
|
||||
_, err := deploy.kubernetesClient.ExtensionsV1beta1().Deployments(deployment.ObjectMeta.Namespace).Patch(deployment.ObjectMeta.Name,
|
||||
k8sTypes.StrategicMergePatchType,
|
||||
[]byte(patch))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (deploy *NewDeploy) createFunction(fn *fv1.Function, firstcreate bool) (*fscache.FuncSvc, error) {
|
||||
if fn.Spec.InvokeStrategy.ExecutionStrategy.ExecutorType != fv1.ExecutorTypeNewdeploy {
|
||||
return nil, nil
|
||||
@@ -276,7 +316,7 @@ func (deploy *NewDeploy) fnCreate(fn *fv1.Function, firstcreate bool) (*fscache.
|
||||
objName = fsvc.Name
|
||||
}
|
||||
}
|
||||
deployLabels := deploy.getDeployLabels(fn, env)
|
||||
deployLabels := deploy.getDeployLabels(fn.Metadata, env.Metadata)
|
||||
|
||||
// to support backward compatibility, if the function was created in default ns, we fall back to creating the
|
||||
// deployment of the function in fission-function ns
|
||||
@@ -491,7 +531,7 @@ func (deploy *NewDeploy) updateFuncDeployment(fn *fv1.Function, env *fv1.Environ
|
||||
}
|
||||
fnObjName := fsvc.Name
|
||||
|
||||
deployLabels := deploy.getDeployLabels(fn, env)
|
||||
deployLabels := deploy.getDeployLabels(fn.Metadata, env.Metadata)
|
||||
deploy.logger.Info("updating deployment due to function/environment update",
|
||||
zap.String("deployment", fnObjName), zap.Any("function", fn.Metadata.Name))
|
||||
|
||||
@@ -557,16 +597,16 @@ func (deploy *NewDeploy) getObjName(fn *fv1.Function) string {
|
||||
return strings.ToLower(fmt.Sprintf("newdeploy-%v-%v-%v", fn.Metadata.Name, fn.Metadata.Namespace, uniuri.NewLen(8)))
|
||||
}
|
||||
|
||||
func (deploy *NewDeploy) getDeployLabels(fn *fv1.Function, env *fv1.Environment) map[string]string {
|
||||
func (deploy *NewDeploy) getDeployLabels(fnMeta metav1.ObjectMeta, envMeta metav1.ObjectMeta) map[string]string {
|
||||
return map[string]string{
|
||||
types.EXECUTOR_INSTANCEID_LABEL: deploy.instanceID,
|
||||
types.EXECUTOR_TYPE: fv1.ExecutorTypeNewdeploy,
|
||||
types.ENVIRONMENT_NAME: env.Metadata.Name,
|
||||
types.ENVIRONMENT_NAMESPACE: env.Metadata.Namespace,
|
||||
types.ENVIRONMENT_UID: string(env.Metadata.UID),
|
||||
types.FUNCTION_NAME: fn.Metadata.Name,
|
||||
types.FUNCTION_NAMESPACE: fn.Metadata.Namespace,
|
||||
types.FUNCTION_UID: string(fn.Metadata.UID),
|
||||
types.ENVIRONMENT_NAME: envMeta.Name,
|
||||
types.ENVIRONMENT_NAMESPACE: envMeta.Namespace,
|
||||
types.ENVIRONMENT_UID: string(envMeta.UID),
|
||||
types.FUNCTION_NAME: fnMeta.Name,
|
||||
types.FUNCTION_NAMESPACE: fnMeta.Namespace,
|
||||
types.FUNCTION_UID: string(fnMeta.UID),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user