github.com/werf/3p-helm@v2.8.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  	"strconv"
    30  	"strings"
    31  	"time"
    32  
    33  	goprom "github.com/grpc-ecosystem/go-grpc-prometheus"
    34  	"google.golang.org/grpc"
    35  	"google.golang.org/grpc/credentials"
    36  	"google.golang.org/grpc/keepalive"
    37  
    38  	"k8s.io/helm/pkg/kube"
    39  	"k8s.io/helm/pkg/proto/hapi/services"
    40  	"k8s.io/helm/pkg/storage"
    41  	"k8s.io/helm/pkg/storage/driver"
    42  	"k8s.io/helm/pkg/tiller"
    43  	"k8s.io/helm/pkg/tiller/environment"
    44  	"k8s.io/helm/pkg/tlsutil"
    45  	"k8s.io/helm/pkg/version"
    46  )
    47  
    48  const (
    49  	// tlsEnableEnvVar names the environment variable that enables TLS.
    50  	tlsEnableEnvVar = "TILLER_TLS_ENABLE"
    51  	// tlsVerifyEnvVar names the environment variable that enables
    52  	// TLS, as well as certificate verification of the remote.
    53  	tlsVerifyEnvVar = "TILLER_TLS_VERIFY"
    54  	// tlsCertsEnvVar names the environment variable that points to
    55  	// the directory where Tiller's TLS certificates are located.
    56  	tlsCertsEnvVar = "TILLER_TLS_CERTS"
    57  	// historyMaxEnvVar is the name of the env var for setting max history.
    58  	historyMaxEnvVar = "TILLER_HISTORY_MAX"
    59  
    60  	storageMemory    = "memory"
    61  	storageConfigMap = "configmap"
    62  	storageSecret    = "secret"
    63  
    64  	probeAddr = ":44135"
    65  	traceAddr = ":44136"
    66  
    67  	// defaultMaxHistory sets the maximum number of releases to 0: unlimited
    68  	defaultMaxHistory = 0
    69  )
    70  
    71  var (
    72  	grpcAddr             = flag.String("listen", ":44134", "address:port to listen on")
    73  	enableTracing        = flag.Bool("trace", false, "enable rpc tracing")
    74  	store                = flag.String("storage", storageConfigMap, "storage driver to use. One of 'configmap', 'memory', or 'secret'")
    75  	remoteReleaseModules = flag.Bool("experimental-release", false, "enable experimental release modules")
    76  	tlsEnable            = flag.Bool("tls", tlsEnableEnvVarDefault(), "enable TLS")
    77  	tlsVerify            = flag.Bool("tls-verify", tlsVerifyEnvVarDefault(), "enable TLS and verify remote certificate")
    78  	keyFile              = flag.String("tls-key", tlsDefaultsFromEnv("tls-key"), "path to TLS private key file")
    79  	certFile             = flag.String("tls-cert", tlsDefaultsFromEnv("tls-cert"), "path to TLS certificate file")
    80  	caCertFile           = flag.String("tls-ca-cert", tlsDefaultsFromEnv("tls-ca-cert"), "trust certificates signed by this CA")
    81  	maxHistory           = flag.Int("history-max", historyMaxFromEnv(), "maximum number of releases kept in release history, with 0 meaning no limit")
    82  	printVersion         = flag.Bool("version", false, "print the version number")
    83  
    84  	// rootServer is the root gRPC server.
    85  	//
    86  	// Each gRPC service registers itself to this server during init().
    87  	rootServer *grpc.Server
    88  
    89  	// env is the default environment.
    90  	//
    91  	// Any changes to env should be done before rootServer.Serve() is called.
    92  	env = environment.New()
    93  
    94  	logger *log.Logger
    95  )
    96  
    97  func main() {
    98  	// TODO: use spf13/cobra for tiller instead of flags
    99  	flag.Parse()
   100  
   101  	if *printVersion {
   102  		fmt.Println(version.GetVersion())
   103  		os.Exit(0)
   104  	}
   105  
   106  	if *enableTracing {
   107  		log.SetFlags(log.Lshortfile)
   108  	}
   109  	logger = newLogger("main")
   110  
   111  	start()
   112  }
   113  
   114  func start() {
   115  
   116  	clientset, err := kube.New(nil).ClientSet()
   117  	if err != nil {
   118  		logger.Fatalf("Cannot initialize Kubernetes connection: %s", err)
   119  	}
   120  
   121  	switch *store {
   122  	case storageMemory:
   123  		env.Releases = storage.Init(driver.NewMemory())
   124  	case storageConfigMap:
   125  		cfgmaps := driver.NewConfigMaps(clientset.Core().ConfigMaps(namespace()))
   126  		cfgmaps.Log = newLogger("storage/driver").Printf
   127  
   128  		env.Releases = storage.Init(cfgmaps)
   129  		env.Releases.Log = newLogger("storage").Printf
   130  	case storageSecret:
   131  		secrets := driver.NewSecrets(clientset.Core().Secrets(namespace()))
   132  		secrets.Log = newLogger("storage/driver").Printf
   133  
   134  		env.Releases = storage.Init(secrets)
   135  		env.Releases.Log = newLogger("storage").Printf
   136  	}
   137  
   138  	if *maxHistory > 0 {
   139  		env.Releases.MaxHistory = *maxHistory
   140  	}
   141  
   142  	kubeClient := kube.New(nil)
   143  	kubeClient.Log = newLogger("kube").Printf
   144  	env.KubeClient = kubeClient
   145  
   146  	if *tlsEnable || *tlsVerify {
   147  		opts := tlsutil.Options{CertFile: *certFile, KeyFile: *keyFile}
   148  		if *tlsVerify {
   149  			opts.CaCertFile = *caCertFile
   150  		}
   151  	}
   152  
   153  	var opts []grpc.ServerOption
   154  	if *tlsEnable || *tlsVerify {
   155  		cfg, err := tlsutil.ServerConfig(tlsOptions())
   156  		if err != nil {
   157  			logger.Fatalf("Could not create server TLS configuration: %v", err)
   158  		}
   159  		opts = append(opts, grpc.Creds(credentials.NewTLS(cfg)))
   160  		opts = append(opts, grpc.KeepaliveParams(keepalive.ServerParameters{
   161  			MaxConnectionIdle: 10 * time.Minute,
   162  			// If needed, we can configure the max connection age
   163  		}))
   164  	}
   165  
   166  	rootServer = tiller.NewServer(opts...)
   167  
   168  	lstn, err := net.Listen("tcp", *grpcAddr)
   169  	if err != nil {
   170  		logger.Fatalf("Server died: %s", err)
   171  	}
   172  
   173  	logger.Printf("Starting Tiller %s (tls=%t)", version.GetVersion(), *tlsEnable || *tlsVerify)
   174  	logger.Printf("GRPC listening on %s", *grpcAddr)
   175  	logger.Printf("Probes listening on %s", probeAddr)
   176  	logger.Printf("Storage driver is %s", env.Releases.Name())
   177  	logger.Printf("Max history per release is %d", *maxHistory)
   178  
   179  	if *enableTracing {
   180  		startTracing(traceAddr)
   181  	}
   182  
   183  	srvErrCh := make(chan error)
   184  	probeErrCh := make(chan error)
   185  	go func() {
   186  		svc := tiller.NewReleaseServer(env, clientset, *remoteReleaseModules)
   187  		svc.Log = newLogger("tiller").Printf
   188  		services.RegisterReleaseServiceServer(rootServer, svc)
   189  		if err := rootServer.Serve(lstn); err != nil {
   190  			srvErrCh <- err
   191  		}
   192  	}()
   193  
   194  	go func() {
   195  		mux := newProbesMux()
   196  
   197  		// Register gRPC server to prometheus to initialized matrix
   198  		goprom.Register(rootServer)
   199  		addPrometheusHandler(mux)
   200  
   201  		if err := http.ListenAndServe(probeAddr, mux); err != nil {
   202  			probeErrCh <- err
   203  		}
   204  	}()
   205  
   206  	select {
   207  	case err := <-srvErrCh:
   208  		logger.Fatalf("Server died: %s", err)
   209  	case err := <-probeErrCh:
   210  		logger.Printf("Probes server died: %s", err)
   211  	}
   212  }
   213  
   214  func newLogger(prefix string) *log.Logger {
   215  	if len(prefix) > 0 {
   216  		prefix = fmt.Sprintf("[%s] ", prefix)
   217  	}
   218  	return log.New(os.Stderr, prefix, log.Flags())
   219  }
   220  
   221  // namespace returns the namespace of tiller
   222  func namespace() string {
   223  	if ns := os.Getenv("TILLER_NAMESPACE"); ns != "" {
   224  		return ns
   225  	}
   226  
   227  	// Fall back to the namespace associated with the service account token, if available
   228  	if data, err := ioutil.ReadFile("/var/run/secrets/kubernetes.io/serviceaccount/namespace"); err == nil {
   229  		if ns := strings.TrimSpace(string(data)); len(ns) > 0 {
   230  			return ns
   231  		}
   232  	}
   233  
   234  	return environment.DefaultTillerNamespace
   235  }
   236  
   237  func tlsOptions() tlsutil.Options {
   238  	opts := tlsutil.Options{CertFile: *certFile, KeyFile: *keyFile}
   239  	if *tlsVerify {
   240  		opts.CaCertFile = *caCertFile
   241  
   242  		// We want to force the client to not only provide a cert, but to
   243  		// provide a cert that we can validate.
   244  		// http://www.bite-code.com/2015/06/25/tls-mutual-auth-in-golang/
   245  		opts.ClientAuth = tls.RequireAndVerifyClientCert
   246  	}
   247  	return opts
   248  }
   249  
   250  func tlsDefaultsFromEnv(name string) (value string) {
   251  	switch certsDir := os.Getenv(tlsCertsEnvVar); name {
   252  	case "tls-key":
   253  		return filepath.Join(certsDir, "tls.key")
   254  	case "tls-cert":
   255  		return filepath.Join(certsDir, "tls.crt")
   256  	case "tls-ca-cert":
   257  		return filepath.Join(certsDir, "ca.crt")
   258  	}
   259  	return ""
   260  }
   261  
   262  func historyMaxFromEnv() int {
   263  	val := os.Getenv(historyMaxEnvVar)
   264  	if val == "" {
   265  		return defaultMaxHistory
   266  	}
   267  	ret, err := strconv.Atoi(val)
   268  	if err != nil {
   269  		log.Printf("Invalid max history %q. Defaulting to 0.", val)
   270  		return defaultMaxHistory
   271  	}
   272  	return ret
   273  }
   274  
   275  func tlsEnableEnvVarDefault() bool { return os.Getenv(tlsEnableEnvVar) != "" }
   276  func tlsVerifyEnvVarDefault() bool { return os.Getenv(tlsVerifyEnvVar) != "" }