1// Copyright 2017 Istio Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15package main
16
17import (
18	"fmt"
19	"os"
20	"time"
21
22	"github.com/spf13/cobra"
23	"github.com/spf13/cobra/doc"
24	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
25
26	"istio.io/pkg/collateral"
27	"istio.io/pkg/ctrlz"
28	"istio.io/pkg/log"
29	"istio.io/pkg/version"
30
31	"istio.io/istio/pilot/pkg/bootstrap"
32	"istio.io/istio/pilot/pkg/features"
33	"istio.io/istio/pilot/pkg/serviceregistry"
34	"istio.io/istio/pkg/cmd"
35	"istio.io/istio/pkg/spiffe"
36)
37
38const (
39	defaultMCPMaxMessageSize        = 1024 * 1024 * 4 // default grpc maximum message size
40	defaultMCPInitialConnWindowSize = 1024 * 1024     // default grpc InitialWindowSize
41	defaultMCPInitialWindowSize     = 1024 * 1024     // default grpc ConnWindowSize
42)
43
44var (
45	serverArgs *bootstrap.PilotArgs
46
47	loggingOptions = log.DefaultOptions()
48
49	rootCmd = &cobra.Command{
50		Use:          "pilot-discovery",
51		Short:        "Istio Pilot.",
52		Long:         "Istio Pilot provides fleet-wide traffic management capabilities in the Istio Service Mesh.",
53		SilenceUsage: true,
54	}
55
56	discoveryCmd = &cobra.Command{
57		Use:   "discovery",
58		Short: "Start Istio proxy discovery service.",
59		Args:  cobra.ExactArgs(0),
60		RunE: func(c *cobra.Command, args []string) error {
61			cmd.PrintFlags(c.Flags())
62			if err := log.Configure(loggingOptions); err != nil {
63				return err
64			}
65
66			spiffe.SetTrustDomain(spiffe.DetermineTrustDomain(serverArgs.Config.ControllerOptions.TrustDomain, hasKubeRegistry()))
67
68			// Create the stop channel for all of the servers.
69			stop := make(chan struct{})
70
71			// Create the server for the discovery service.
72			discoveryServer, err := bootstrap.NewServer(serverArgs)
73			if err != nil {
74				return fmt.Errorf("failed to create discovery service: %v", err)
75			}
76
77			// Start the server
78			if err := discoveryServer.Start(stop); err != nil {
79				return fmt.Errorf("failed to start discovery service: %v", err)
80			}
81
82			cmd.WaitSignal(stop)
83			// Wait until we shut down. In theory this could block forever; in practice we will get
84			// forcibly shut down after 30s in Kubernetes.
85			discoveryServer.WaitUntilCompletion()
86			return nil
87		},
88	}
89)
90
91// when we run on k8s, the default trust domain is 'cluster.local', otherwise it is the empty string
92func hasKubeRegistry() bool {
93	for _, r := range serverArgs.Service.Registries {
94		if serviceregistry.ProviderID(r) == serviceregistry.Kubernetes {
95			return true
96		}
97	}
98	return false
99}
100
101func init() {
102
103	serverArgs = bootstrap.NewPilotArgs(func(p *bootstrap.PilotArgs) {
104		// Set Defaults
105		p.CtrlZOptions = ctrlz.DefaultOptions()
106		// TODO replace with mesh config?
107		p.InjectionOptions = bootstrap.InjectionOptions{
108			InjectionDirectory: "./var/lib/istio/inject",
109		}
110	})
111
112	// Process commandline args.
113	discoveryCmd.PersistentFlags().StringSliceVar(&serverArgs.Service.Registries, "registries",
114		[]string{string(serviceregistry.Kubernetes)},
115		fmt.Sprintf("Comma separated list of platform service registries to read from (choose one or more from {%s, %s, %s})",
116			serviceregistry.Kubernetes, serviceregistry.Consul, serviceregistry.Mock))
117	discoveryCmd.PersistentFlags().StringVar(&serverArgs.Config.ClusterRegistriesNamespace, "clusterRegistriesNamespace",
118		serverArgs.Config.ClusterRegistriesNamespace, "Namespace for ConfigMap which stores clusters configs")
119	discoveryCmd.PersistentFlags().StringVar(&serverArgs.Config.KubeConfig, "kubeconfig", "",
120		"Use a Kubernetes configuration file instead of in-cluster configuration")
121	discoveryCmd.PersistentFlags().StringVar(&serverArgs.Mesh.ConfigFile, "meshConfig", "/etc/istio/config/mesh",
122		"File name for Istio mesh configuration. If not specified, a default mesh will be used.")
123	discoveryCmd.PersistentFlags().StringVar(&serverArgs.NetworksConfigFile, "networksConfig", "/etc/istio/config/meshNetworks",
124		"File name for Istio mesh networks configuration. If not specified, a default mesh networks will be used.")
125	discoveryCmd.PersistentFlags().StringVarP(&serverArgs.Namespace, "namespace", "n", bootstrap.PodNamespaceVar.Get(),
126		"Select a namespace where the controller resides. If not set, uses ${POD_NAMESPACE} environment variable")
127	discoveryCmd.PersistentFlags().StringSliceVar(&serverArgs.Plugins, "plugins", bootstrap.DefaultPlugins,
128		"comma separated list of networking plugins to enable")
129
130	// MCP client flags
131	discoveryCmd.PersistentFlags().IntVar(&serverArgs.MCPOptions.MaxMessageSize, "mcpMaxMsgSize", defaultMCPMaxMessageSize,
132		"Max message size received by MCP's grpc client")
133	discoveryCmd.PersistentFlags().IntVar(&serverArgs.MCPOptions.InitialWindowSize, "mcpInitialWindowSize", defaultMCPInitialWindowSize,
134		"Initial window size for MCP's gRPC connection")
135	discoveryCmd.PersistentFlags().IntVar(&serverArgs.MCPOptions.InitialConnWindowSize, "mcpInitialConnWindowSize", defaultMCPInitialConnWindowSize,
136		"Initial connection window size for MCP's gRPC connection")
137
138	// Config Controller options
139	discoveryCmd.PersistentFlags().BoolVar(&serverArgs.Config.DisableInstallCRDs, "disable-install-crds", true,
140		"Disable discovery service from verifying the existence of CRDs at startup and then installing if not detected.  "+
141			"It is recommended to be disable for highly available setups.")
142	_ = discoveryCmd.PersistentFlags().MarkDeprecated("disable-install-crds",
143		"Setting this flag has no effect. Install CRD definitions directly or with the operator")
144	discoveryCmd.PersistentFlags().StringVar(&serverArgs.Config.FileDir, "configDir", "",
145		"Directory to watch for updates to config yaml files. If specified, the files will be used as the source of config, rather than a CRD client.")
146	discoveryCmd.PersistentFlags().StringVarP(&serverArgs.Config.ControllerOptions.WatchedNamespace, "appNamespace",
147		"a", metav1.NamespaceAll,
148		"Restrict the applications namespace the controller manages; if not set, controller watches all namespaces")
149	discoveryCmd.PersistentFlags().DurationVar(&serverArgs.Config.ControllerOptions.ResyncPeriod, "resync", 60*time.Second,
150		"Controller resync interval")
151	discoveryCmd.PersistentFlags().StringVar(&serverArgs.Config.ControllerOptions.DomainSuffix, "domain", "cluster.local",
152		"DNS domain suffix")
153	discoveryCmd.PersistentFlags().StringVar(&serverArgs.Config.ControllerOptions.ClusterID, "clusterID", features.ClusterName.Get(),
154		"The ID of the cluster that this Istiod instance resides")
155	discoveryCmd.PersistentFlags().StringVar(&serverArgs.Config.ControllerOptions.TrustDomain, "trust-domain", "",
156		"The domain serves to identify the system with spiffe")
157	discoveryCmd.PersistentFlags().StringVar(&serverArgs.Service.Consul.ServerURL, "consulserverURL", "",
158		"URL for the Consul server")
159
160	// using address, so it can be configured as localhost:.. (possibly UDS in future)
161	discoveryCmd.PersistentFlags().StringVar(&serverArgs.DiscoveryOptions.HTTPAddr, "httpAddr", ":8080",
162		"Discovery service HTTP address")
163	discoveryCmd.PersistentFlags().StringVar(&serverArgs.DiscoveryOptions.HTTPSAddr, "httpsAddr", ":15017",
164		"Injection and validation service HTTPS address")
165	discoveryCmd.PersistentFlags().StringVar(&serverArgs.DiscoveryOptions.GrpcAddr, "grpcAddr", ":15010",
166		"Discovery service grpc address")
167	discoveryCmd.PersistentFlags().StringVar(&serverArgs.DiscoveryOptions.MonitoringAddr, "monitoringAddr", ":15014",
168		"HTTP address to use for pilot's self-monitoring information")
169	discoveryCmd.PersistentFlags().BoolVar(&serverArgs.DiscoveryOptions.EnableProfiling, "profile", true,
170		"Enable profiling via web interface host:port/debug/pprof")
171
172	// Use TLS certificates if provided.
173	discoveryCmd.PersistentFlags().StringVar(&serverArgs.TLSOptions.CaCertFile, "caCertFile", "",
174		"File containing the x509 Server CA Certificate")
175	discoveryCmd.PersistentFlags().StringVar(&serverArgs.TLSOptions.CertFile, "tlsCertFile", "",
176		"File containing the x509 Server Certificate")
177	discoveryCmd.PersistentFlags().StringVar(&serverArgs.TLSOptions.KeyFile, "tlsKeyFile", "",
178		"File containing the x509 private key matching --tlsCertFile")
179
180	// Attach the Istio logging options to the command.
181	loggingOptions.AttachCobraFlags(rootCmd)
182
183	// Attach the Istio Ctrlz options to the command.
184	serverArgs.CtrlZOptions.AttachCobraFlags(rootCmd)
185
186	// Attach the Istio Keepalive options to the command.
187	serverArgs.KeepaliveOptions.AttachCobraFlags(rootCmd)
188
189	cmd.AddFlags(rootCmd)
190
191	rootCmd.AddCommand(discoveryCmd)
192	rootCmd.AddCommand(version.CobraCommand())
193	rootCmd.AddCommand(collateral.CobraCommand(rootCmd, &doc.GenManHeader{
194		Title:   "Istio Pilot Discovery",
195		Section: "pilot-discovery CLI",
196		Manual:  "Istio Pilot Discovery",
197	}))
198
199}
200
201func main() {
202	if err := rootCmd.Execute(); err != nil {
203		log.Errora(err)
204		os.Exit(-1)
205	}
206}
207