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