OpenTracing for Fission (#1079)

Added Opentracing integration using opencensus libraries for all Fission components.
This commit is contained in:
Vishal
2019-02-07 11:56:41 +05:30
committed by GitHub
parent 8b0a201f69
commit 5d2abdd95b
29 changed files with 400 additions and 121 deletions
+9 -3
View File
@@ -26,6 +26,7 @@ import (
"strings"
"github.com/gorilla/mux"
"go.opencensus.io/plugin/ochttp"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/fission/fission"
@@ -46,7 +47,7 @@ func (executor *Executor) getServiceForFunctionApi(w http.ResponseWriter, r *htt
return
}
serviceName, err := executor.getServiceForFunction(&m)
serviceName, err := executor.getServiceForFunction(r.Context(), &m)
if err != nil {
code, msg := fission.GetHTTPError(err)
log.Printf("Error: %v: %v", code, msg)
@@ -66,7 +67,7 @@ func (executor *Executor) getServiceForFunctionApi(w http.ResponseWriter, r *htt
// stale addresses are not returned to the router.
// To make it optimal, plan is to add an eager cache invalidator function that watches for pod deletion events and
// invalidates the cache entry if the pod address was cached.
func (executor *Executor) getServiceForFunction(m *metav1.ObjectMeta) (string, error) {
func (executor *Executor) getServiceForFunction(ctx context.Context, m *metav1.ObjectMeta) (string, error) {
// Check function -> svc cache
log.Printf("[%v] Checking for cached function service", m.Name)
fsvc, err := executor.fsCache.GetByFunction(m)
@@ -82,6 +83,7 @@ func (executor *Executor) getServiceForFunction(m *metav1.ObjectMeta) (string, e
respChan := make(chan *createFuncServiceResponse)
executor.requestChan <- &createFuncServiceRequest{
ctx: ctx,
funcMeta: m,
respChan: respChan,
}
@@ -127,5 +129,9 @@ func (executor *Executor) Serve(port int) {
executor.ndm.Run(ctx)
executor.gpm.Run(ctx)
r.Use(fission.LoggingMiddleware)
log.Fatal(http.ListenAndServe(address, r))
err := http.ListenAndServe(address, &ochttp.Handler{
Handler: r,
// Propagation: &b3.HTTPFormat{},
})
log.Fatal(err)
}
+9 -2
View File
@@ -18,6 +18,7 @@ package client
import (
"bytes"
"context"
"encoding/json"
"io/ioutil"
"log"
@@ -26,6 +27,8 @@ import (
"strings"
"time"
"go.opencensus.io/plugin/ochttp"
"golang.org/x/net/context/ctxhttp"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/fission/fission"
@@ -35,6 +38,7 @@ type Client struct {
executorUrl string
tappedByUrl map[string]bool
requestChan chan string
httpClient *http.Client
}
func MakeClient(executorUrl string) *Client {
@@ -42,12 +46,15 @@ func MakeClient(executorUrl string) *Client {
executorUrl: strings.TrimSuffix(executorUrl, "/"),
tappedByUrl: make(map[string]bool),
requestChan: make(chan string),
httpClient: &http.Client{
Transport: &ochttp.Transport{},
},
}
go c.service()
return c
}
func (c *Client) GetServiceForFunction(metadata *metav1.ObjectMeta) (string, error) {
func (c *Client) GetServiceForFunction(ctx context.Context, metadata *metav1.ObjectMeta) (string, error) {
executorUrl := c.executorUrl + "/v2/getServiceForFunction"
body, err := json.Marshal(metadata)
@@ -55,7 +62,7 @@ func (c *Client) GetServiceForFunction(metadata *metav1.ObjectMeta) (string, err
return "", err
}
resp, err := http.Post(executorUrl, "application/json", bytes.NewReader(body))
resp, err := ctxhttp.Post(ctx, c.httpClient, executorUrl, "application/json", bytes.NewReader(body))
if err != nil {
return "", err
}
+6 -4
View File
@@ -17,6 +17,7 @@ limitations under the License.
package executor
import (
"context"
"fmt"
"log"
"net/http"
@@ -50,6 +51,7 @@ type (
fsCreateWg map[string]*sync.WaitGroup
}
createFuncServiceRequest struct {
ctx context.Context
funcMeta *metav1.ObjectMeta
respChan chan *createFuncServiceResponse
}
@@ -98,7 +100,7 @@ func (executor *Executor) serveCreateFuncServices() {
// launch a goroutine for each request, to parallelize
// the specialization of different functions
go func() {
fsvc, err := executor.createServiceForFunction(m)
fsvc, err := executor.createServiceForFunction(req.ctx, m)
req.respChan <- &createFuncServiceResponse{
funcSvc: fsvc,
err: err,
@@ -137,7 +139,7 @@ func (executor *Executor) getFunctionExecutorType(meta *metav1.ObjectMeta) (fiss
return fn.Spec.InvokeStrategy.ExecutionStrategy.ExecutorType, nil
}
func (executor *Executor) createServiceForFunction(meta *metav1.ObjectMeta) (*fscache.FuncSvc, error) {
func (executor *Executor) createServiceForFunction(ctx context.Context, meta *metav1.ObjectMeta) (*fscache.FuncSvc, error) {
log.Printf("[%v] No cached function service found, creating one", meta.Name)
executorType, err := executor.getFunctionExecutorType(meta)
@@ -150,9 +152,9 @@ func (executor *Executor) createServiceForFunction(meta *metav1.ObjectMeta) (*fs
switch executorType {
case fission.ExecutorTypeNewdeploy:
fsvc, fsvcErr = executor.ndm.GetFuncSvc(meta)
fsvc, fsvcErr = executor.ndm.GetFuncSvc(ctx, meta)
default:
fsvc, fsvcErr = executor.gpm.GetFuncSvc(meta)
fsvc, fsvcErr = executor.gpm.GetFuncSvc(ctx, meta)
}
if fsvcErr != nil {
+2 -1
View File
@@ -23,6 +23,7 @@
package executor
import (
"context"
"fmt"
"io/ioutil"
"log"
@@ -237,7 +238,7 @@ func TestExecutor(t *testing.T) {
// the main test: get a service for a given function
t1 := time.Now()
svc, err := poolmgrClient.GetServiceForFunction(&f.Metadata)
svc, err := poolmgrClient.GetServiceForFunction(context.Background(), &f.Metadata)
if err != nil {
log.Panicf("failed to get func svc: %v", err)
}
+1
View File
@@ -292,6 +292,7 @@ func (deploy *NewDeploy) getDeploymentSpec(fn *crd.Function, env *crd.Environmen
"-specialize-request", string(specializePayload),
"-secret-dir", deploy.sharedSecretPath,
"-cfgmap-dir", deploy.sharedCfgMapPath,
"-jaeger-collector-endpoint", deploy.collectorEndpoint,
deploy.sharedMountPath},
Lifecycle: &apiv1.Lifecycle{
PreStop: &apiv1.Handler{
+5 -1
View File
@@ -59,6 +59,7 @@ type (
sharedSecretPath string
sharedCfgMapPath string
useIstio bool
collectorEndpoint string
fsCache *fscache.FunctionServiceCache // cache funcSvc's by function, address and pod name
@@ -85,6 +86,8 @@ func MakeNewDeploy(
fetcherImg = "fission/fetcher"
}
collectorEndpoint := os.Getenv("TRACE_JAEGER_COLLECTOR_ENDPOINT")
enableIstio := false
if len(os.Getenv("ENABLE_ISTIO")) > 0 {
istio, err := strconv.ParseBool(os.Getenv("ENABLE_ISTIO"))
@@ -110,6 +113,7 @@ func MakeNewDeploy(
sharedMountPath: "/userfunc",
sharedSecretPath: "/secrets",
sharedCfgMapPath: "/configs",
collectorEndpoint: collectorEndpoint,
useIstio: enableIstio,
idlePodReapTime: 2 * time.Minute,
@@ -160,7 +164,7 @@ func (deploy *NewDeploy) initFuncController() (k8sCache.Store, k8sCache.Controll
return store, controller
}
func (deploy *NewDeploy) GetFuncSvc(metadata *metav1.ObjectMeta) (*fscache.FuncSvc, error) {
func (deploy *NewDeploy) GetFuncSvc(ctx context.Context, metadata *metav1.ObjectMeta) (*fscache.FuncSvc, error) {
fn, err := deploy.fissionClient.Functions(metadata.Namespace).Get(metadata.Name)
if err != nil {
return nil, err
+10 -5
View File
@@ -17,6 +17,7 @@ limitations under the License.
package poolmgr
import (
"context"
"fmt"
"log"
"math/rand"
@@ -67,6 +68,7 @@ type (
sharedMountPath string // used by generic pool when creating env deployment to specify the share volume path for fetcher & env
sharedSecretPath string
sharedCfgMapPath string
collectorEndpoint string
}
// serialize the choosing of pods so that choices don't conflict
@@ -89,7 +91,8 @@ func MakeGenericPool(
functionNamespace string,
fsCache *fscache.FunctionServiceCache,
instanceId string,
enableIstio bool) (*GenericPool, error) {
enableIstio bool,
collectorEndpoint string) (*GenericPool, error) {
log.Printf("Creating pool for environment %v", env.Metadata)
@@ -119,6 +122,7 @@ func MakeGenericPool(
sharedMountPath: "/userfunc", // change this may break v1 compatibility, since most of the v1 environments have hard-coded "/userfunc" in loading path
sharedSecretPath: "/secrets",
sharedCfgMapPath: "/configs",
collectorEndpoint: collectorEndpoint,
}
gp.runtimeImagePullPolicy = fission.GetImagePullPolicy(os.Getenv("RUNTIME_IMAGE_PULL_POLICY"))
@@ -301,7 +305,7 @@ func (gp *GenericPool) getSpecializeUrl(podIP string) string {
// specializePod chooses a pod, copies the required user-defined function to that pod
// (via fetcher), and calls the function-run container to load it, resulting in a
// specialized pod.
func (gp *GenericPool) specializePod(pod *apiv1.Pod, metadata *metav1.ObjectMeta) error {
func (gp *GenericPool) specializePod(ctx context.Context, pod *apiv1.Pod, metadata *metav1.ObjectMeta) error {
// for fetcher we don't need to create a service, just talk to the pod directly
podIP := pod.Status.PodIP
if len(podIP) == 0 {
@@ -354,7 +358,7 @@ func (gp *GenericPool) specializePod(pod *apiv1.Pod, metadata *metav1.ObjectMeta
log.Printf("[%v] specializing pod", metadata.Name)
err = fetcherClient.MakeClient(fetcherUrl).Specialize(&specializeReq)
err = fetcherClient.MakeClient(fetcherUrl).Specialize(ctx, &specializeReq)
if err != nil {
return err
}
@@ -487,6 +491,7 @@ func (gp *GenericPool) createPool() error {
Command: []string{"/fetcher",
"-secret-dir", gp.sharedSecretPath,
"-cfgmap-dir", gp.sharedCfgMapPath,
"-jaeger-collector-endpoint", gp.collectorEndpoint,
gp.sharedMountPath},
// Pod is removed from endpoints list for service when it's
// state became "Termination". We used preStop hook as the
@@ -617,7 +622,7 @@ func (gp *GenericPool) createSvc(name string, labels map[string]string) (*apiv1.
return svc, err
}
func (gp *GenericPool) GetFuncSvc(m *metav1.ObjectMeta) (*fscache.FuncSvc, error) {
func (gp *GenericPool) GetFuncSvc(ctx context.Context, m *metav1.ObjectMeta) (*fscache.FuncSvc, error) {
log.Printf("[%v] Choosing pod from pool", m.Name)
newLabels := gp.labelsForFunction(m)
@@ -667,7 +672,7 @@ func (gp *GenericPool) GetFuncSvc(m *metav1.ObjectMeta) (*fscache.FuncSvc, error
return nil, err
}
err = gp.specializePod(pod, m)
err = gp.specializePod(ctx, pod, m)
if err != nil {
gp.scheduleDeletePod(pod.ObjectMeta.Name)
return nil, err
+17 -13
View File
@@ -55,7 +55,9 @@ type (
instanceId string
requestChannel chan *request
enableIstio bool
enableIstio bool
collectorEndpoint string
funcStore k8sCache.Store
funcController k8sCache.Controller
pkgStore k8sCache.Store
@@ -82,15 +84,16 @@ func MakeGenericPoolManager(
instanceId string) *GenericPoolManager {
gpm := &GenericPoolManager{
pools: make(map[string]*GenericPool),
kubernetesClient: kubernetesClient,
namespace: functionNamespace,
fissionClient: fissionClient,
functionEnv: cache.MakeCache(10*time.Second, 0),
fsCache: fscache.MakeFunctionServiceCache(),
instanceId: instanceId,
requestChannel: make(chan *request),
idlePodReapTime: 2 * time.Minute,
pools: make(map[string]*GenericPool),
kubernetesClient: kubernetesClient,
namespace: functionNamespace,
fissionClient: fissionClient,
functionEnv: cache.MakeCache(10*time.Second, 0),
fsCache: fscache.MakeFunctionServiceCache(),
instanceId: instanceId,
requestChannel: make(chan *request),
idlePodReapTime: 2 * time.Minute,
collectorEndpoint: os.Getenv("TRACE_JAEGER_COLLECTOR_ENDPOINT"),
}
go gpm.service()
go gpm.eagerPoolCreator()
@@ -141,7 +144,8 @@ func (gpm *GenericPoolManager) service() {
pool, err = MakeGenericPool(
gpm.fissionClient, gpm.kubernetesClient, req.env, poolsize,
ns, gpm.namespace, gpm.fsCache, gpm.instanceId, gpm.enableIstio)
ns, gpm.namespace, gpm.fsCache, gpm.instanceId, gpm.enableIstio,
gpm.collectorEndpoint)
if err != nil {
req.responseChannel <- &response{error: err}
continue
@@ -189,7 +193,7 @@ func (gpm *GenericPoolManager) CleanupPools(envs []crd.Environment) {
}
}
func (gpm *GenericPoolManager) GetFuncSvc(metadata *metav1.ObjectMeta) (*fscache.FuncSvc, error) {
func (gpm *GenericPoolManager) GetFuncSvc(ctx context.Context, metadata *metav1.ObjectMeta) (*fscache.FuncSvc, error) {
// from Func -> get Env
log.Printf("[%v] getting environment for function", metadata.Name)
env, err := gpm.getFunctionEnv(metadata)
@@ -204,7 +208,7 @@ func (gpm *GenericPoolManager) GetFuncSvc(metadata *metav1.ObjectMeta) (*fscache
// from GenericPool -> get one function container
// (this also adds to the cache)
log.Printf("[%v] getting function service from pool", metadata.Name)
return pool.GetFuncSvc(metadata)
return pool.GetFuncSvc(ctx, metadata)
}
func (gpm *GenericPoolManager) getFunctionEnv(m *metav1.ObjectMeta) (*crd.Environment, error) {