Support to set imagePullSecret when creating environment (#1429)

This commit is contained in:
Ta-Ching Chen
2019-11-22 18:19:57 +08:00
committed by GitHub
parent af73d0ce1a
commit a66de4c601
10 changed files with 104 additions and 38 deletions
+4
View File
@@ -528,6 +528,10 @@ type (
// or unarchived file should be placed, which is then used by specialize handler. // or unarchived file should be placed, which is then used by specialize handler.
// (This is mainly for the JVM environment because .jar is one kind of zip archive.) // (This is mainly for the JVM environment because .jar is one kind of zip archive.)
KeepArchive bool `json:"keeparchive"` KeepArchive bool `json:"keeparchive"`
// ImagePullSecret is the secret for Kubernetes to pull an image from a
// private registry.
ImagePullSecret string `json:"imagepullsecret"`
} }
AllowedFunctionsPerContainer string AllowedFunctionsPerContainer string
+22 -14
View File
@@ -17,11 +17,11 @@ limitations under the License.
package newdeploy package newdeploy
import ( import (
"errors"
"fmt" "fmt"
"time" "time"
multierror "github.com/hashicorp/go-multierror" multierror "github.com/hashicorp/go-multierror"
"github.com/pkg/errors"
"go.uber.org/zap" "go.uber.org/zap"
appsv1 "k8s.io/api/apps/v1" appsv1 "k8s.io/api/apps/v1"
asv1 "k8s.io/api/autoscaling/v1" asv1 "k8s.io/api/autoscaling/v1"
@@ -76,7 +76,7 @@ func (deploy *NewDeploy) createOrGetDeployment(fn *fv1.Function, env *fv1.Enviro
return nil, err return nil, err
} }
deployment, err := deploy.getDeploymentSpec(fn, env, deployName, deployLabels) deployment, err := deploy.getDeploymentSpec(fn, env, deployName, deployNamespace, deployLabels)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -158,7 +158,7 @@ func (deploy *NewDeploy) deleteDeployment(ns string, name string) error {
} }
func (deploy *NewDeploy) getDeploymentSpec(fn *fv1.Function, env *fv1.Environment, func (deploy *NewDeploy) getDeploymentSpec(fn *fv1.Function, env *fv1.Environment,
deployName string, deployLabels map[string]string) (*appsv1.Deployment, error) { deployName string, deployNamespace string, deployLabels map[string]string) (*appsv1.Deployment, error) {
replicas := int32(fn.Spec.InvokeStrategy.ExecutionStrategy.MinScale) replicas := int32(fn.Spec.InvokeStrategy.ExecutionStrategy.MinScale)
@@ -227,6 +227,24 @@ func (deploy *NewDeploy) getDeploymentSpec(fn *fv1.Function, env *fv1.Environmen
return nil, err return nil, err
} }
pod := apiv1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: deployLabels,
Annotations: podAnnotations,
},
Spec: apiv1.PodSpec{
Containers: []apiv1.Container{*container},
ServiceAccountName: "fission-fetcher",
TerminationGracePeriodSeconds: &gracePeriodSeconds,
},
}
podspec, err := util.ApplyImagePullSecret(deploy.kubernetesClient, env.Spec.ImagePullSecret, deployNamespace, pod.Spec)
if err != nil {
return nil, errors.Wrapf(err, "failed to apply image pull secret for env '%v'", env.Metadata.Name)
}
pod.Spec = *podspec
deployment := &appsv1.Deployment{ deployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: deployName, Name: deployName,
@@ -237,17 +255,7 @@ func (deploy *NewDeploy) getDeploymentSpec(fn *fv1.Function, env *fv1.Environmen
Selector: &metav1.LabelSelector{ Selector: &metav1.LabelSelector{
MatchLabels: deployLabels, MatchLabels: deployLabels,
}, },
Template: apiv1.PodTemplateSpec{ Template: pod,
ObjectMeta: metav1.ObjectMeta{
Labels: deployLabels,
Annotations: podAnnotations,
},
Spec: apiv1.PodSpec{
Containers: []apiv1.Container{*container},
ServiceAccountName: "fission-fetcher",
TerminationGracePeriodSeconds: &gracePeriodSeconds,
},
},
Strategy: appsv1.DeploymentStrategy{ Strategy: appsv1.DeploymentStrategy{
Type: appsv1.RollingUpdateDeploymentStrategyType, Type: appsv1.RollingUpdateDeploymentStrategyType,
RollingUpdate: &appsv1.RollingUpdateDeployment{ RollingUpdate: &appsv1.RollingUpdateDeployment{
+6 -6
View File
@@ -535,12 +535,6 @@ func (deploy *NewDeploy) updateFuncDeployment(fn *fv1.Function, env *fv1.Environ
deploy.logger.Info("updating deployment due to function/environment update", deploy.logger.Info("updating deployment due to function/environment update",
zap.String("deployment", fnObjName), zap.Any("function", fn.Metadata.Name)) zap.String("deployment", fnObjName), zap.Any("function", fn.Metadata.Name))
newDeployment, err := deploy.getDeploymentSpec(fn, env, fnObjName, deployLabels)
if err != nil {
deploy.updateStatus(fn, err, "failed to get new deployment spec while updating function")
return err
}
// to support backward compatibility, if the function was created in default ns, we fall back to creating the // 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 // deployment of the function in fission-function ns
ns := deploy.namespace ns := deploy.namespace
@@ -548,6 +542,12 @@ func (deploy *NewDeploy) updateFuncDeployment(fn *fv1.Function, env *fv1.Environ
ns = fn.Metadata.Namespace ns = fn.Metadata.Namespace
} }
newDeployment, err := deploy.getDeploymentSpec(fn, env, fnObjName, ns, deployLabels)
if err != nil {
deploy.updateStatus(fn, err, "failed to get new deployment spec while updating function")
return err
}
err = deploy.updateDeployment(newDeployment, ns) err = deploy.updateDeployment(newDeployment, ns)
if err != nil { if err != nil {
deploy.updateStatus(fn, err, "failed to update deployment while updating function") deploy.updateStatus(fn, err, "failed to update deployment while updating function")
+22 -14
View File
@@ -389,6 +389,27 @@ func (gp *GenericPool) createPool() error {
return err return err
} }
pod := apiv1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: gp.labelsForPool,
Annotations: podAnnotations,
},
Spec: apiv1.PodSpec{
Containers: []apiv1.Container{*container},
ServiceAccountName: "fission-fetcher",
// TerminationGracePeriodSeconds should be equal to the
// sleep time of preStop to make sure that SIGTERM is sent
// to pod after 6 mins.
TerminationGracePeriodSeconds: &gracePeriodSeconds,
},
}
podspec, err := util.ApplyImagePullSecret(gp.kubernetesClient, gp.env.Spec.ImagePullSecret, gp.namespace, pod.Spec)
if err != nil {
return errors.Wrapf(err, "failed to apply image pull secret for env '%v'", gp.env.Metadata.Name)
}
pod.Spec = *podspec
deployment := &appsv1.Deployment{ deployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{ ObjectMeta: metav1.ObjectMeta{
Name: gp.getPoolName(), Name: gp.getPoolName(),
@@ -399,20 +420,7 @@ func (gp *GenericPool) createPool() error {
Selector: &metav1.LabelSelector{ Selector: &metav1.LabelSelector{
MatchLabels: gp.labelsForPool, MatchLabels: gp.labelsForPool,
}, },
Template: apiv1.PodTemplateSpec{ Template: pod,
ObjectMeta: metav1.ObjectMeta{
Labels: gp.labelsForPool,
Annotations: podAnnotations,
},
Spec: apiv1.PodSpec{
Containers: []apiv1.Container{*container},
ServiceAccountName: "fission-fetcher",
// TerminationGracePeriodSeconds should be equal to the
// sleep time of preStop to make sure that SIGTERM is sent
// to pod after 6 mins.
TerminationGracePeriodSeconds: &gracePeriodSeconds,
},
},
}, },
} }
+38
View File
@@ -0,0 +1,38 @@
/*
Copyright 2019 The Fission Authors.
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.
*/
package util
import (
"github.com/pkg/errors"
apiv1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
)
// ApplyImagePullSecret applies image pull secret to the give pod spec. An error will be returned if failed to get secret.
func ApplyImagePullSecret(client *kubernetes.Clientset, secret string, secretNS string, podspec apiv1.PodSpec) (*apiv1.PodSpec, error) {
if len(secret) > 0 && client != nil {
_, err := client.CoreV1().Secrets(secretNS).Get(secret, metav1.GetOptions{})
if err != nil {
err = errors.Wrapf(err, "unable to get image pull secret '%v' under namespace '%v'",
secret, secretNS)
return nil, err
}
podspec.ImagePullSecrets = []apiv1.LocalObjectReference{{Name: secret}}
}
return &podspec, nil
}
+4 -4
View File
@@ -33,8 +33,8 @@ func Commands() *cobra.Command {
Required: []flag.Flag{flag.EnvName, flag.EnvImage}, Required: []flag.Flag{flag.EnvName, flag.EnvImage},
Optional: []flag.Flag{flag.EnvPoolsize, flag.EnvBuilderImage, flag.EnvBuildCmd, Optional: []flag.Flag{flag.EnvPoolsize, flag.EnvBuilderImage, flag.EnvBuildCmd,
flag.RunTimeMinCPU, flag.RunTimeMaxCPU, flag.RunTimeMinMemory, flag.RunTimeMaxMemory, flag.RunTimeMinCPU, flag.RunTimeMaxCPU, flag.RunTimeMinMemory, flag.RunTimeMaxMemory,
flag.EnvTerminationGracePeriod, flag.EnvVersion, flag.EnvExternalNetwork, flag.EnvKeepArchive, flag.EnvTerminationGracePeriod, flag.EnvVersion, flag.EnvImagePullSecret,
flag.NamespaceEnvironment, flag.SpecSave}, flag.EnvExternalNetwork, flag.EnvKeepArchive, flag.NamespaceEnvironment, flag.SpecSave},
}) })
getCmd := &cobra.Command{ getCmd := &cobra.Command{
@@ -55,8 +55,8 @@ func Commands() *cobra.Command {
wrapper.SetFlags(updateCmd, flag.FlagSet{ wrapper.SetFlags(updateCmd, flag.FlagSet{
Required: []flag.Flag{flag.EnvName}, Required: []flag.Flag{flag.EnvName},
Optional: []flag.Flag{flag.EnvImage, flag.EnvPoolsize, Optional: []flag.Flag{flag.EnvImage, flag.EnvPoolsize,
flag.EnvBuilderImage, flag.EnvBuildCmd, flag.EnvExternalNetwork, flag.EnvBuilderImage, flag.EnvBuildCmd, flag.EnvImagePullSecret, flag.EnvTerminationGracePeriod,
flag.EnvTerminationGracePeriod, flag.EnvKeepArchive, flag.NamespaceEnvironment}, flag.EnvKeepArchive, flag.NamespaceEnvironment, flag.EnvExternalNetwork},
}) })
deleteCmd := &cobra.Command{ deleteCmd := &cobra.Command{
@@ -112,6 +112,7 @@ func createEnvironmentFromCmd(input cli.Input) (*fv1.Environment, error) {
envExternalNetwork := input.Bool(flagkey.EnvExternalNetwork) envExternalNetwork := input.Bool(flagkey.EnvExternalNetwork)
keepArchive := input.Bool(flagkey.EnvKeeparchive) keepArchive := input.Bool(flagkey.EnvKeeparchive)
envGracePeriod := input.Int64(flagkey.EnvGracePeriod) envGracePeriod := input.Int64(flagkey.EnvGracePeriod)
pullSecret := input.String(flagkey.EnvImagePullSecret)
envVersion := input.Int(flagkey.EnvVersion) envVersion := input.Int(flagkey.EnvVersion)
// Environment API interface version is not specified and // Environment API interface version is not specified and
@@ -169,6 +170,7 @@ func createEnvironmentFromCmd(input cli.Input) (*fv1.Environment, error) {
AllowAccessToExternalNetwork: envExternalNetwork, AllowAccessToExternalNetwork: envExternalNetwork,
TerminationGracePeriod: envGracePeriod, TerminationGracePeriod: envGracePeriod,
KeepArchive: keepArchive, KeepArchive: keepArchive,
ImagePullSecret: pullSecret,
}, },
} }
@@ -123,6 +123,10 @@ func updateExistingEnvironmentWithCmd(env *fv1.Environment, input cli.Input) (*f
env.Spec.KeepArchive = input.Bool(flagkey.EnvKeeparchive) env.Spec.KeepArchive = input.Bool(flagkey.EnvKeeparchive)
} }
if input.IsSet(flagkey.EnvImagePullSecret) {
env.Spec.ImagePullSecret = input.String(flagkey.EnvImagePullSecret)
}
env.Spec.AllowAccessToExternalNetwork = envExternalNetwork env.Spec.AllowAccessToExternalNetwork = envExternalNetwork
// TODO: allow to update resource. // TODO: allow to update resource.
+1
View File
@@ -142,6 +142,7 @@ var (
EnvExternalNetwork = Flag{Type: Bool, Name: flagkey.EnvExternalNetwork, Usage: "Allow pod to access external network (only works when istio feature is enabled)"} EnvExternalNetwork = Flag{Type: Bool, Name: flagkey.EnvExternalNetwork, Usage: "Allow pod to access external network (only works when istio feature is enabled)"}
EnvTerminationGracePeriod = Flag{Type: Int, Name: flagkey.EnvGracePeriod, Aliases: []string{"period"}, Usage: "Grace time (in seconds) for pod to perform connection draining before termination", DefaultValue: 360} EnvTerminationGracePeriod = Flag{Type: Int, Name: flagkey.EnvGracePeriod, Aliases: []string{"period"}, Usage: "Grace time (in seconds) for pod to perform connection draining before termination", DefaultValue: 360}
EnvVersion = Flag{Type: Int, Name: flagkey.EnvVersion, Usage: "Environment API version (1 means v1 interface)", DefaultValue: 1} EnvVersion = Flag{Type: Int, Name: flagkey.EnvVersion, Usage: "Environment API version (1 means v1 interface)", DefaultValue: 1}
EnvImagePullSecret = Flag{Type: String, Name: flagkey.EnvImagePullSecret, Usage: "Secret for Kubernetes to pull an image from a private registry"}
KwName = Flag{Type: String, Name: flagkey.KwName, Usage: "Watch name"} KwName = Flag{Type: String, Name: flagkey.KwName, Usage: "Watch name"}
KwFnName = Flag{Type: String, Name: flagkey.KwFnName, Usage: "Function name"} KwFnName = Flag{Type: String, Name: flagkey.KwFnName, Usage: "Function name"}
+1
View File
@@ -96,6 +96,7 @@ const (
EnvExternalNetwork = "externalnetwork" EnvExternalNetwork = "externalnetwork"
EnvGracePeriod = "graceperiod" EnvGracePeriod = "graceperiod"
EnvVersion = "version" EnvVersion = "version"
EnvImagePullSecret = "imagepullsecret"
KwName = resourceName KwName = resourceName
KwFnName = "function" KwFnName = "function"