github.com/pensu/helm@v2.6.1+incompatible/cmd/tiller/tiller.go (about)

     1  /*
     2  Copyright 2016 The Kubernetes Authors All rights reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package main // import "k8s.io/helm/cmd/tiller"
    18  
    19  import (
    20  	"crypto/tls"
    21  	"flag"
    22  	"fmt"
    23  	"io/ioutil"
    24  	"log"
    25  	"net"
    26  	"net/http"
    27  	"os"
    28  	"path/filepath"
    29  	"strings"
    30  
    31  	goprom "github.com/grpc-ecosystem/go-grpc-prometheus"
    32  	"google.golang.org/grpc"
    33  	"google.golang.org/grpc/credentials"
    34  
    35  	"k8s.io/helm/pkg/kube"
    36  	"k8s.io/helm/pkg/proto/hapi/services"
    37  	"k8s.io/helm/pkg/storage"
    38  	"k8s.io/helm/pkg/storage/driver"
    39  	"k8s.io/helm/pkg/tiller"
    40  	"k8s.io/helm/pkg/tiller/environment"
    41  	"k8s.io/helm/pkg/tlsutil"
    42  	"k8s.io/helm/pkg/version"
    43  )
    44  
    45  const (
    46  	// tlsEnableEnvVar names the environment variable that enables TLS.
    47  	tlsEnableEnvVar = "TILLER_TLS_ENABLE"
    48  	// tlsVerifyEnvVar names the environment variable that enables
    49  	// TLS, as well as certificate verification of the remote.
    50  	tlsVerifyEnvVar = "TILLER_TLS_VERIFY"
    51  	// tlsCertsEnvVar names the environment variable that points to
    52  	// the directory where Tiller's TLS certificates are located.
    53  	tlsCertsEnvVar = "TILLER_TLS_CERTS"
    54  
    55  	storageMemory    = "memory"
    56  	storageConfigMap = "configmap"
    57  
    58  	probeAddr = ":44135"
    59  	traceAddr = ":44136"
    60  )
    61  
    62  var (
    63  	grpcAddr             = flag.String("listen", ":44134", "address:port to listen on")
    64  	enableTracing        = flag.Bool("trace", false, "enable rpc tracing")
    65  	store                = flag.String("storage", storageConfigMap, "storage driver to use. One of 'configmap' or 'memory'")
    66  	remoteReleaseModules = flag.Bool("experimental-release", false, "enable experimental release modules")
    67  	tlsEnable            = flag.Bool("tls", tlsEnableEnvVarDefault(), "enable TLS")
    68  	tlsVerify            = flag.Bool("tls-verify", tlsVerifyEnvVarDefault(), "enable TLS and verify remote certificate")
    69  	keyFile              = flag.String("tls-key", tlsDefaultsFromEnv("tls-key"), "path to TLS private key file")
    70  	certFile             = flag.String("tls-cert", tlsDefaultsFromEnv("tls-cert"), "path to TLS certificate file")
    71  	caCertFile           = flag.String("tls-ca-cert", tlsDefaultsFromEnv("tls-ca-cert"), "trust certificates signed by this CA")
    72  
    73  	// rootServer is the root gRPC server.
    74  	//
    75  	// Each gRPC service registers itself to this server during init().
    76  	rootServer *grpc.Server
    77  
    78  	// env is the default environment.
    79  	//
    80  	// Any changes to env should be done before rootServer.Serve() is called.
    81  	env = environment.New()
    82  
    83  	logger *log.Logger
    84  )
    85  
    86  func main() {
    87  	flag.Parse()
    88  
    89  	if *enableTracing {
    90  		log.SetFlags(log.Lshortfile)
    91  	}
    92  	logger = newLogger("main")
    93  
    94  	start()
    95  }
    96  
    97  func start() {
    98  
    99  	clientset, err := kube.New(nil).ClientSet()
   100  	if err != nil {
   101  		logger.Fatalf("Cannot initialize Kubernetes connection: %s", err)
   102  	}
   103  
   104  	switch *store {
   105  	case storageMemory:
   106  		env.Releases = storage.Init(driver.NewMemory())
   107  	case storageConfigMap:
   108  		cfgmaps := driver.NewConfigMaps(clientset.Core().ConfigMaps(namespace()))
   109  		cfgmaps.Log = newLogger("storage/driver").Printf
   110  
   111  		env.Releases = storage.Init(cfgmaps)
   112  		env.Releases.Log = newLogger("storage").Printf
   113  	}
   114  
   115  	kubeClient := kube.New(nil)
   116  	kubeClient.Log = newLogger("kube").Printf
   117  	env.KubeClient = kubeClient
   118  
   119  	if *tlsEnable || *tlsVerify {
   120  		opts := tlsutil.Options{CertFile: *certFile, KeyFile: *keyFile}
   121  		if *tlsVerify {
   122  			opts.CaCertFile = *caCertFile
   123  		}
   124  	}
   125  
   126  	var opts []grpc.ServerOption
   127  	if *tlsEnable || *tlsVerify {
   128  		cfg, err := tlsutil.ServerConfig(tlsOptions())
   129  		if err != nil {
   130  			logger.Fatalf("Could not create server TLS configuration: %v", err)
   131  		}
   132  		opts = append(opts, grpc.Creds(credentials.NewTLS(cfg)))
   133  	}
   134  
   135  	rootServer = tiller.NewServer(opts...)
   136  
   137  	lstn, err := net.Listen("tcp", *grpcAddr)
   138  	if err != nil {
   139  		logger.Fatalf("Server died: %s", err)
   140  	}
   141  
   142  	logger.Printf("Starting Tiller %s (tls=%t)", version.GetVersion(), *tlsEnable || *tlsVerify)
   143  	logger.Printf("GRPC listening on %s", *grpcAddr)
   144  	logger.Printf("Probes listening on %s", probeAddr)
   145  	logger.Printf("Storage driver is %s", env.Releases.Name())
   146  
   147  	if *enableTracing {
   148  		startTracing(traceAddr)
   149  	}
   150  
   151  	srvErrCh := make(chan error)
   152  	probeErrCh := make(chan error)
   153  	go func() {
   154  		svc := tiller.NewReleaseServer(env, clientset, *remoteReleaseModules)
   155  		svc.Log = newLogger("tiller").Printf
   156  		services.RegisterReleaseServiceServer(rootServer, svc)
   157  		if err := rootServer.Serve(lstn); err != nil {
   158  			srvErrCh <- err
   159  		}
   160  	}()
   161  
   162  	go func() {
   163  		mux := newProbesMux()
   164  
   165  		// Register gRPC server to prometheus to initialized matrix
   166  		goprom.Register(rootServer)
   167  		addPrometheusHandler(mux)
   168  
   169  		if err := http.ListenAndServe(probeAddr, mux); err != nil {
   170  			probeErrCh <- err
   171  		}
   172  	}()
   173  
   174  	select {
   175  	case err := <-srvErrCh:
   176  		logger.Fatalf("Server died: %s", err)
   177  	case err := <-probeErrCh:
   178  		logger.Printf("Probes server died: %s", err)
   179  	}
   180  }
   181  
   182  func newLogger(prefix string) *log.Logger {
   183  	if len(prefix) > 0 {
   184  		prefix = fmt.Sprintf("[%s] ", prefix)
   185  	}
   186  	return log.New(os.Stderr, prefix, log.Flags())
   187  }
   188  
   189  // namespace returns the namespace of tiller
   190  func namespace() string {
   191  	if ns := os.Getenv("TILLER_NAMESPACE"); ns != "" {
   192  		return ns
   193  	}
   194  
   195  	// Fall back to the namespace associated with the service account token, if available
   196  	if data, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace"); err == nil {
   197  		if ns := strings.TrimSpace(string(data)); len(ns) > 0 {
   198  			return ns
   199  		}
   200  	}
   201  
   202  	return environment.DefaultTillerNamespace
   203  }
   204  
   205  func tlsOptions() tlsutil.Options {
   206  	opts := tlsutil.Options{CertFile: *certFile, KeyFile: *keyFile}
   207  	if *tlsVerify {
   208  		opts.CaCertFile = *caCertFile
   209  		opts.ClientAuth = tls.VerifyClientCertIfGiven
   210  	}
   211  	return opts
   212  }
   213  
   214  func tlsDefaultsFromEnv(name string) (value string) {
   215  	switch certsDir := os.Getenv(tlsCertsEnvVar); name {
   216  	case "tls-key":
   217  		return filepath.Join(certsDir, "tls.key")
   218  	case "tls-cert":
   219  		return filepath.Join(certsDir, "tls.crt")
   220  	case "tls-ca-cert":
   221  		return filepath.Join(certsDir, "ca.crt")
   222  	}
   223  	return ""
   224  }
   225  
   226  func tlsEnableEnvVarDefault() bool { return os.Getenv(tlsEnableEnvVar) != "" }
   227  func tlsVerifyEnvVarDefault() bool { return os.Getenv(tlsVerifyEnvVar) != "" }