Feature flag to enable/disable canary + optional prometheus install (#937)

This commit is contained in:
smruthi2187
2018-10-22 15:24:43 -07:00
committed by GitHub
parent e7f1d4564a
commit 0a8c6e97a6
20 changed files with 304 additions and 28 deletions
+16 -2
View File
@@ -19,9 +19,11 @@ package canaryconfigmgr
import (
"context"
"fmt"
log "github.com/sirupsen/logrus"
"os"
"strings"
"time"
log "github.com/sirupsen/logrus"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
@@ -45,7 +47,19 @@ type canaryConfigMgr struct {
func MakeCanaryConfigMgr(fissionClient *crd.FissionClient, kubeClient *kubernetes.Clientset, crdClient *rest.RESTClient, prometheusSvc string) (*canaryConfigMgr, error) {
if prometheusSvc == "" {
return nil, fmt.Errorf("prometheus service not found, cant create canary config manager")
// handle a case where there is a prometheus server is already installed, try to find the service from env variable
envVars := os.Environ()
for _, envVar := range envVars {
if strings.Contains(envVar, "PROMETHEUS_SERVER_SERVICE_HOST") {
envVarSplit := strings.Split(envVar, "=")
prometheusSvc = envVarSplit[1]
break
}
}
if prometheusSvc == "" {
return nil, fmt.Errorf("prometheus service not found, cant create canary config manager")
}
}
configMgr := &canaryConfigMgr{
+2 -1
View File
@@ -1,4 +1,5 @@
dependencies:
- name: prometheus
version: 7.1.0
repository: https://kubernetes-charts.storage.googleapis.com
repository: https://kubernetes-charts.storage.googleapis.com
condition: prometheusDeploy
+17
View File
@@ -14,3 +14,20 @@ We truncate at 24 chars because some Kubernetes name fields are limited to this
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- printf "%s-%s" .Release.Name $name | trunc 24 | trimSuffix "-" -}}
{{- end -}}
{{/*
This is a template with config parameters for optional features in fission. This gets mounted on to the controller pod
as a config map.
To add new features with config parameters, create a yaml block below with the feature name and define a corresponding struct in
controller/config.go
*/}}
{{- define "config" -}}
canary:
enabled: {{ .Values.canaryDeployment.enabled }}
{{- if .Values.prometheusDeploy }}
prometheusSvc: "http://{{ .Release.Name }}-prometheus-server.{{ .Release.Namespace }}"
{{- end }}
{{- printf "\n" -}}
{{- end -}}
+18 -2
View File
@@ -103,6 +103,15 @@ metadata:
name: fission-builder
namespace: {{ .Values.builderNamespace }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: feature-config
namespace: {{ .Release.Namespace }}
data:
"config.yaml": {{ include "config" . | b64enc }}
---
apiVersion: extensions/v1beta1
kind: Deployment
@@ -123,7 +132,7 @@ spec:
image: "{{ .Values.repository }}/{{ .Values.image }}:{{ .Values.imageTag }}"
imagePullPolicy: {{ .Values.pullPolicy }}
command: ["/fission-bundle"]
args: ["--controllerPort", "8888", "--prometheusSvc", "http://{{ .Release.Name }}-prometheus-server.{{ .Release.Namespace }}"]
args: ["--controllerPort", "8888"]
env:
- name: FISSION_FUNCTION_NAMESPACE
value: "{{ .Values.functionNamespace }}"
@@ -144,8 +153,15 @@ spec:
port: 8888
initialDelaySeconds: 35
periodSeconds: 5
volumeMounts:
- name: config-volume
mountPath: /etc/config/config.yaml
subPath: config.yaml
serviceAccount: fission-svc
volumes:
- name: config-volume
configMap:
name: feature-config
---
apiVersion: extensions/v1beta1
kind: Deployment
+7
View File
@@ -106,3 +106,10 @@ preUpgradeChecksImage: fission/pre-upgrade-checks
## if there are any pod specialization errors when a function is triggered and this flag is set to true, the error
## summary is returned as part of http response
debugEnv: true
## set this flag to true if prometheus needs to be deployed along with fission
prometheusDeploy: true
## set this flag to false if you dont need canary deployment feature
canaryDeployment:
enabled: true
+2 -1
View File
@@ -1,4 +1,5 @@
dependencies:
- name: prometheus
version: 7.1.0
repository: https://kubernetes-charts.storage.googleapis.com
repository: https://kubernetes-charts.storage.googleapis.com
condition: prometheusDeploy
@@ -14,3 +14,18 @@ We truncate at 24 chars because some Kubernetes name fields are limited to this
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- printf "%s-%s" .Release.Name $name | trunc 24 | trimSuffix "-" -}}
{{- end -}}
{{/*
This is a template with config parameters for optional features in fission. This gets mounted on to the controller pod
as a config map.
To add new features with config parameters, create a yaml block below with the feature name and define a corresponding struct in
controller/config.go
*/}}
{{- define "config" -}}
canary:
enabled: {{ .Values.canaryDeployment.enabled }}
{{- if .Values.prometheusDeploy }}
prometheusSvc: "http://{{ .Release.Name }}-prometheus-server.{{ .Release.Namespace }}"
{{- end }}
{{- printf "\n" -}}
{{- end -}}
@@ -103,6 +103,15 @@ metadata:
name: fission-builder
namespace: {{ .Values.builderNamespace }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: feature-config
namespace: {{ .Release.Namespace }}
data:
"config.yaml": {{ include "config" . | b64enc }}
---
apiVersion: extensions/v1beta1
kind: Deployment
@@ -144,7 +153,15 @@ spec:
port: 8888
initialDelaySeconds: 35
periodSeconds: 5
volumeMounts:
- name: config-volume
mountPath: /etc/config/config.yaml
subPath: config.yaml
serviceAccount: fission-svc
volumes:
- name: config-volume
configMap:
name: feature-config
---
apiVersion: extensions/v1beta1
+8 -1
View File
@@ -71,4 +71,11 @@ preUpgradeChecksImage: fission/pre-upgrade-checks
## if there are any pod specialization errors when a function is triggered and this flag is set to true, the error
## summary is returned as part of http response
debugEnv: true
debugEnv: true
## set this flag to true if prometheus needs to be deployed along with fission
prometheusDeploy: true
## set this flag to false if you dont need canary deployment feature
canaryDeployment:
enabled: true
+2 -2
View File
@@ -28,14 +28,14 @@ import (
"strings"
"syscall"
log "github.com/sirupsen/logrus"
"github.com/gorilla/handlers"
"github.com/imdario/mergo"
"github.com/mholt/archiver"
uuid "github.com/satori/go.uuid"
apiv1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/fission/fission/fission/log"
)
func UrlForFunction(name, namespace string) string {
+5 -1
View File
@@ -32,6 +32,7 @@ import (
"github.com/fission/fission"
"github.com/fission/fission/crd"
config "github.com/fission/fission/featureconfig"
"github.com/fission/fission/fission/logdb"
)
@@ -53,6 +54,7 @@ type (
workflowApiUrl string
functionNamespace string
useIstio bool
featureConfig *config.FeatureConfig
}
logDBConfig struct {
@@ -62,7 +64,7 @@ type (
}
)
func MakeAPI() (*API, error) {
func MakeAPI(featureConfig *config.FeatureConfig) (*API, error) {
api, err := makeCRDBackedAPI()
u := os.Getenv("STORAGE_SERVICE_URL")
@@ -93,6 +95,8 @@ func MakeAPI() (*API, error) {
api.functionNamespace = "fission-function"
}
api.featureConfig = featureConfig
return api, err
}
+1 -1
View File
@@ -344,7 +344,7 @@ func TestMain(m *testing.M) {
return
}
go Start(8888, "http://localhost:9090")
go Start(8888, true)
time.Sleep(5 * time.Second)
g.client = client.MakeClient("http://localhost:8888")
+26
View File
@@ -25,10 +25,16 @@ import (
log "github.com/sirupsen/logrus"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/fission/fission"
"github.com/fission/fission/crd"
)
func (a *API) CanaryConfigApiCreate(w http.ResponseWriter, r *http.Request) {
if !a.featureConfig.CanaryConfig.IsEnabled {
a.respondWithError(w, fission.MakeError(http.StatusBadRequest, "Please enable canary feature while installing fission"))
return
}
body, err := ioutil.ReadAll(r.Body)
if err != nil {
a.respondWithError(w, err)
@@ -60,6 +66,11 @@ func (a *API) CanaryConfigApiCreate(w http.ResponseWriter, r *http.Request) {
}
func (a *API) CanaryConfigApiGet(w http.ResponseWriter, r *http.Request) {
if !a.featureConfig.CanaryConfig.IsEnabled {
a.respondWithError(w, fission.MakeError(http.StatusBadRequest, "Please enable canary feature while installing fission"))
return
}
vars := mux.Vars(r)
name := vars["canaryConfig"]
@@ -84,6 +95,11 @@ func (a *API) CanaryConfigApiGet(w http.ResponseWriter, r *http.Request) {
}
func (a *API) CanaryConfigApiList(w http.ResponseWriter, r *http.Request) {
if !a.featureConfig.CanaryConfig.IsEnabled {
a.respondWithError(w, fission.MakeError(http.StatusBadRequest, "Please enable canary feature while installing fission"))
return
}
ns := a.extractQueryParamFromRequest(r, "namespace")
if len(ns) == 0 {
ns = metav1.NamespaceDefault
@@ -105,6 +121,11 @@ func (a *API) CanaryConfigApiList(w http.ResponseWriter, r *http.Request) {
}
func (a *API) CanaryConfigApiUpdate(w http.ResponseWriter, r *http.Request) {
if !a.featureConfig.CanaryConfig.IsEnabled {
a.respondWithError(w, fission.MakeError(http.StatusBadRequest, "Please enable canary feature while installing fission"))
return
}
body, err := ioutil.ReadAll(r.Body)
if err != nil {
a.respondWithError(w, err)
@@ -134,6 +155,11 @@ func (a *API) CanaryConfigApiUpdate(w http.ResponseWriter, r *http.Request) {
}
func (a *API) CanaryConfigApiDelete(w http.ResponseWriter, r *http.Request) {
if !a.featureConfig.CanaryConfig.IsEnabled {
a.respondWithError(w, fission.MakeError(http.StatusBadRequest, "Please enable canary feature while installing fission"))
return
}
vars := mux.Vars(r)
name := vars["canaryConfig"]
ns := a.extractQueryParamFromRequest(r, "namespace")
+65
View File
@@ -0,0 +1,65 @@
/*
Copyright 2018 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 controller
import (
"context"
"fmt"
log "github.com/sirupsen/logrus"
"k8s.io/client-go/kubernetes"
"github.com/fission/fission/canaryconfigmgr"
"github.com/fission/fission/crd"
config "github.com/fission/fission/featureconfig"
)
func ConfigCanaryFeature(context context.Context, fissionClient *crd.FissionClient, kubeClient *kubernetes.Clientset, featureConfig *config.FeatureConfig) error {
// start the appropriate controller
if featureConfig.CanaryConfig.IsEnabled {
canaryCfgMgr, err := canaryconfigmgr.MakeCanaryConfigMgr(fissionClient, kubeClient, fissionClient.GetCrdClient(),
featureConfig.CanaryConfig.PrometheusSvc)
if err != nil {
return fmt.Errorf("failed to start canary config manager: %v", err)
}
canaryCfgMgr.Run(context)
log.Printf("Started canary config manager")
}
return nil
}
// ConfigureFeatures gets the feature config and configures the features that are enabled
func ConfigureFeatures(context context.Context, unitTestMode bool, fissionClient *crd.FissionClient, kubeClient *kubernetes.Clientset) (*config.FeatureConfig, error) {
// set feature enabled to false if unitTestMode
if unitTestMode {
featureConfig := &config.FeatureConfig{}
return featureConfig, nil
}
// get the featureConfig from config map mounted onto the file system
featureConfig, err := config.GetFeatureConfig()
if err != nil {
log.Printf("Error getting feature config : %v", err)
return featureConfig, err
}
// configure respective features
// in the future when new optional features are added, we need to add corresponding feature handlers and invoke them here
err = ConfigCanaryFeature(context, fissionClient, kubeClient, featureConfig)
return featureConfig, err
}
+8 -9
View File
@@ -21,11 +21,10 @@ import (
"log"
"github.com/fission/fission"
"github.com/fission/fission/canaryconfigmgr"
"github.com/fission/fission/crd"
)
func Start(port int, prometheusSvc string) {
func Start(port int, unitTestFlag bool) {
// setup a signal handler for SIGTERM
fission.SetupStackTraceHandler()
@@ -44,16 +43,16 @@ func Start(port int, prometheusSvc string) {
log.Fatalf("Error waiting for CRDs: %v", err)
}
// create canary config manager
canaryCfgMgr, err := canaryconfigmgr.MakeCanaryConfigMgr(fc, kc, fc.GetCrdClient(), prometheusSvc)
if err != nil {
log.Fatalf("Failed to start canary config manager: %v", err)
}
ctx, cancel := context.WithCancel(context.Background())
featureConfig, err := ConfigureFeatures(ctx, unitTestFlag, fc, kc)
if err != nil {
log.Printf("Error configuring features : %v. Proceeding without optional features", err.Error())
// set all features to false for the MakeApi call below
featureConfig.CanaryConfig.IsEnabled = false
}
defer cancel()
canaryCfgMgr.Run(ctx)
api, err := MakeAPI()
api, err := MakeAPI(featureConfig)
if err != nil {
log.Fatalf("Failed to start controller: %v", err)
}
+49
View File
@@ -0,0 +1,49 @@
/*
Copyright 2018 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 featureconfig
import (
"encoding/base64"
"fmt"
"io/ioutil"
"github.com/ghodss/yaml"
)
// GetFeatureConfig reads the configMap file and unmarshals the config into a feature config struct
func GetFeatureConfig() (*FeatureConfig, error) {
// read the file
b64EncodedContent, err := ioutil.ReadFile(FeatureConfigFile)
if err != nil {
return nil, fmt.Errorf("error reading YAML file %s: %v", FeatureConfigFile, err)
}
// b64 decode file
yamlContent, err := base64.StdEncoding.DecodeString(string(b64EncodedContent))
if err != nil {
return nil, fmt.Errorf("error b64 decoding the config : %v", err)
}
// unmarshal into feature config
featureConfig := &FeatureConfig{}
err = yaml.Unmarshal(yamlContent, featureConfig)
if err != nil {
return nil, fmt.Errorf("error unmarshalling YAML config %v", err)
}
return featureConfig, err
}
+40
View File
@@ -0,0 +1,40 @@
/*
Copyright 2018 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 featureconfig
const (
FeatureConfigFile = "/etc/config/config.yaml"
)
type (
// config.yaml contains config parameters for optional features
// To add new features with config parameters:
// 1. create a yaml block with feature name in charts/_helpers.tpl
// 2. define a corresponding struct with the feature config for the yaml unmarshal below
// 3. start the appropriate controllers needed for this feature
FeatureConfig struct {
// In the future more such feature configs can be added here for each optional feature
CanaryConfig CanaryFeatureConfig `json:"canary"`
}
// specific feature config
CanaryFeatureConfig struct {
IsEnabled bool `json:"enabled"`
PrometheusSvc string `json:"prometheusSvc"`
}
)
+4 -6
View File
@@ -19,8 +19,8 @@ import (
"github.com/fission/fission/timer"
)
func runController(port int, prometheusSvc string) {
controller.Start(port, prometheusSvc)
func runController(port int) {
controller.Start(port, false)
log.Fatalf("Error: Controller exited.")
}
@@ -114,7 +114,7 @@ Use it to start one or more of the fission servers:
backends.
Usage:
fission-bundle --controllerPort=<port> --prometheusSvc=<url>
fission-bundle --controllerPort=<port>
fission-bundle --routerPort=<port> [--executorUrl=<url>]
fission-bundle --executorPort=<port> [--namespace=<namespace>] [--fission-namespace=<namespace>]
fission-bundle --kubewatcher [--routerUrl=<url>]
@@ -125,7 +125,6 @@ Usage:
fission-bundle --version
Options:
--controllerPort=<port> Port that the controller should listen on.
--prometheusSvc=<url> Service endpoint of prometheus server
--routerPort=<port> Port that the router should listen on.
--executorPort=<port> Port that the executor should listen on.
--storageServicePort=<port> Port that the storage service should listen on.
@@ -154,11 +153,10 @@ Options:
executorUrl := getStringArgWithDefault(arguments["--executorUrl"], "http://executor.fission")
routerUrl := getStringArgWithDefault(arguments["--routerUrl"], "http://router.fission")
storageSvcUrl := getStringArgWithDefault(arguments["--storageSvcUrl"], "http://storagesvc.fission")
prometheusSvcUrl := getStringArgWithDefault(arguments["--prometheusSvc"], "")
if arguments["--controllerPort"] != nil {
port := getPort(arguments["--controllerPort"])
runController(port, prometheusSvcUrl)
runController(port)
}
if arguments["--routerPort"] != nil {
-2
View File
@@ -106,8 +106,6 @@ func canaryConfigCreate(c *cli.Context) error {
},
}
fmt.Printf("Canary config name : %s, ns : %s, trigger : %s", canaryConfigName, ns, trigger)
_, err = client.CanaryConfigCreate(canaryCfg)
util.CheckErr(err, "create canary config")
+2
View File
@@ -241,6 +241,8 @@ build_yamls() {
helm template ${c} -n ${c}-${version} --set serviceType=NodePort,routerServiceType=NodePort > ${c}-${version}-minikube.yaml
# for environments support ELB
helm template ${c} -n ${c}-${version} > ${c}-${version}.yaml
# for cases where prometheus installation along with fission is not preferred
helm template ${c} -n ${c}-${version} --set canaryDeployment.prometheusDeploy=false > ${c}-${version}-fission-only.yaml
mv *.yaml ${BUILDDIR}/yamls/
done