...

Source file src/github.com/linkerd/linkerd2/web/main.go

Documentation: github.com/linkerd/linkerd2/web

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"flag"
     6  	"net"
     7  	"os"
     8  	"os/signal"
     9  	"regexp"
    10  	"syscall"
    11  	"time"
    12  
    13  	"github.com/linkerd/linkerd2/pkg/config"
    14  
    15  	"github.com/linkerd/linkerd2/pkg/admin"
    16  	"github.com/linkerd/linkerd2/pkg/charts/linkerd2"
    17  	"github.com/linkerd/linkerd2/pkg/flags"
    18  	"github.com/linkerd/linkerd2/pkg/healthcheck"
    19  	"github.com/linkerd/linkerd2/pkg/k8s"
    20  	"github.com/linkerd/linkerd2/pkg/trace"
    21  	"github.com/linkerd/linkerd2/viz/metrics-api/client"
    22  	"github.com/linkerd/linkerd2/web/srv"
    23  	log "github.com/sirupsen/logrus"
    24  )
    25  
    26  func main() {
    27  	cmd := flag.NewFlagSet("public-api", flag.ExitOnError)
    28  
    29  	addr := cmd.String("addr", ":8084", "address to serve on")
    30  	metricsAddr := cmd.String("metrics-addr", ":9994", "address to serve scrapable metrics on")
    31  	vizAPIAddr := cmd.String("linkerd-metrics-api-addr", "127.0.0.1:8085", "address of the linkerd-metrics-api service")
    32  	grafanaAddr := cmd.String("grafana-addr", "", "address of the linkerd-grafana service")
    33  	grafanaExternalAddr := cmd.String("grafana-external-addr", "", "address of the external grafana service")
    34  	grafanaPrefix := cmd.String("grafana-prefix", "", "prefix for Grafana dashboard UID's")
    35  	jaegerAddr := cmd.String("jaeger-addr", "", "address of the jaeger service")
    36  	templateDir := cmd.String("template-dir", "templates", "directory to search for template files")
    37  	staticDir := cmd.String("static-dir", "app/dist", "directory to search for static files")
    38  	reload := cmd.Bool("reload", true, "reloading set to true or false")
    39  	controllerNamespace := cmd.String("controller-namespace", "linkerd", "namespace in which Linkerd is installed")
    40  	enforcedHost := cmd.String("enforced-host", "", "regexp describing the allowed values for the Host header; protects from DNS-rebinding attacks")
    41  	kubeConfigPath := cmd.String("kubeconfig", "", "path to kube config")
    42  	clusterDomain := cmd.String("cluster-domain", "", "kubernetes cluster domain")
    43  	enablePprof := cmd.Bool("enable-pprof", false, "Enable pprof endpoints on the admin server")
    44  
    45  	traceCollector := flags.AddTraceFlags(cmd)
    46  
    47  	flags.ConfigureAndParse(cmd, os.Args[1:])
    48  
    49  	ready := false
    50  	adminServer := admin.NewServer(*metricsAddr, *enablePprof, &ready)
    51  
    52  	go func() {
    53  		log.Infof("starting admin server on %s", *metricsAddr)
    54  		if err := adminServer.ListenAndServe(); err != nil {
    55  			log.Errorf("failed to start web admin server: %s", err)
    56  		}
    57  	}()
    58  
    59  	ctx := context.Background()
    60  
    61  	_, _, err := net.SplitHostPort(*vizAPIAddr) // Verify vizAPIAddr is of the form host:port.
    62  	if err != nil {
    63  		log.Fatalf("failed to parse metrics API server address: %s", *vizAPIAddr)
    64  	}
    65  	client, err := client.NewInternalClient(*vizAPIAddr)
    66  	if err != nil {
    67  		log.Fatalf("failed to construct client for viz API server URL %s", *vizAPIAddr)
    68  	}
    69  
    70  	if *clusterDomain == "" {
    71  		*clusterDomain = "cluster.local"
    72  		log.Warnf("expected cluster domain through args (falling back to %s)", *clusterDomain)
    73  	}
    74  
    75  	k8sAPI, err := k8s.NewAPI(*kubeConfigPath, "", "", []string{}, 0)
    76  	if err != nil {
    77  		log.Fatalf("failed to construct Kubernetes API client: [%s]", err)
    78  	}
    79  
    80  	// Setup health checker
    81  	checks := []healthcheck.CategoryID{
    82  		healthcheck.KubernetesAPIChecks,
    83  		healthcheck.KubernetesVersionChecks,
    84  		healthcheck.LinkerdConfigChecks,
    85  		healthcheck.LinkerdControlPlaneExistenceChecks,
    86  		healthcheck.LinkerdVersionChecks,
    87  		healthcheck.LinkerdControlPlaneVersionChecks,
    88  	}
    89  	hc := healthcheck.NewHealthChecker(checks, &healthcheck.Options{
    90  		ControlPlaneNamespace: *controllerNamespace,
    91  		KubeConfig:            *kubeConfigPath,
    92  	})
    93  
    94  	uuid, version := getUUIDAndVersion(ctx, k8sAPI, *controllerNamespace)
    95  
    96  	stop := make(chan os.Signal, 1)
    97  	signal.Notify(stop, os.Interrupt, syscall.SIGTERM)
    98  
    99  	if *traceCollector != "" {
   100  		if err := trace.InitializeTracing("web", *traceCollector); err != nil {
   101  			log.Warnf("failed to initialize tracing: %s", err)
   102  		}
   103  	}
   104  
   105  	reHost, err := regexp.Compile(*enforcedHost)
   106  	if err != nil {
   107  		log.Fatalf("invalid --enforced-host parameter: %s", err)
   108  	}
   109  
   110  	server := srv.NewServer(*addr, *grafanaAddr, *grafanaExternalAddr, *grafanaPrefix, *jaegerAddr, *templateDir, *staticDir, uuid, version,
   111  		*controllerNamespace, *clusterDomain, *reload, reHost, client, k8sAPI, hc)
   112  
   113  	go func() {
   114  		log.Infof("starting HTTP server on %+v", *addr)
   115  		if err := server.ListenAndServe(); err != nil {
   116  			log.Errorf("failed to start web HTTP server: %s", err)
   117  		}
   118  	}()
   119  
   120  	ready = true
   121  
   122  	<-stop
   123  
   124  	log.Infof("shutting down HTTP server on %+v", *addr)
   125  	ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
   126  	defer cancel()
   127  	server.Shutdown(ctx)
   128  	adminServer.Shutdown(ctx)
   129  }
   130  
   131  func getUUIDAndVersion(ctx context.Context, k8sAPI *k8s.KubernetesAPI, controllerNamespace string) (string, string) {
   132  	var uuid string
   133  	var version string
   134  
   135  	cm, err := config.FetchLinkerdConfigMap(ctx, k8sAPI, controllerNamespace)
   136  	if err != nil {
   137  		log.Errorf("Failed to fetch linkerd-config: %s", err)
   138  	} else {
   139  		uuid = string(cm.GetUID())
   140  
   141  		values, err := linkerd2.ValuesFromConfigMap(cm)
   142  		if err != nil {
   143  			log.Errorf("failed to load values from linkerd-config: %s", err)
   144  		} else {
   145  			version = values.LinkerdVersion
   146  		}
   147  	}
   148  
   149  	return uuid, version
   150  }
   151  

View as plain text