diff --git a/command/troubleshoot/proxy/troubleshoot_proxy.go b/command/troubleshoot/proxy/troubleshoot_proxy.go index 6601bcea0..d72983065 100644 --- a/command/troubleshoot/proxy/troubleshoot_proxy.go +++ b/command/troubleshoot/proxy/troubleshoot_proxy.go @@ -24,20 +24,22 @@ type cmd struct { help string // flags - upstream string - adminBind string + upstreamEnvoyID string + upstreamIP string + envoyAdminEndpoint string } func (c *cmd) init() { c.flags = flag.NewFlagSet("", flag.ContinueOnError) - c.flags.StringVar(&c.upstream, "upstream", os.Getenv("TROUBLESHOOT_UPSTREAM"), "The upstream service that receives the communication. ") + c.flags.StringVar(&c.upstreamEnvoyID, "upstream-envoy-id", os.Getenv("UPSTREAM_ENVOY_ID"), "The envoy identifier of the upstream service that receives the communication. (explicit upstreams only)") + c.flags.StringVar(&c.upstreamIP, "upstream-ip", os.Getenv("UPSTREAM_IP"), "The IP address of the upstream service that receives the communication. (transparent proxy only) ") - defaultAdminBind := "localhost:19000" - if adminBind := os.Getenv("ADMIN_BIND"); adminBind != "" { - defaultAdminBind = adminBind + defaultEnvoyAdminEndpoint := "localhost:19000" + if envoyAdminEndpoint := os.Getenv("ENVOY_ADMIN_ENDPOINT"); envoyAdminEndpoint != "" { + defaultEnvoyAdminEndpoint = envoyAdminEndpoint } - c.flags.StringVar(&c.adminBind, "admin-bind", defaultAdminBind, "The address:port that envoy's admin endpoint is on.") + c.flags.StringVar(&c.envoyAdminEndpoint, "envoy-admin-endpoint", defaultEnvoyAdminEndpoint, "The address:port that envoy's admin endpoint is on.") c.http = &flags.HTTPFlags{} flags.Merge(c.flags, c.http.ClientFlags()) @@ -52,12 +54,13 @@ func (c *cmd) Run(args []string) int { return 1 } - if c.upstream == "" { - c.UI.Error("-upstream envoy identifier is required") + if c.upstreamEnvoyID == "" && c.upstreamIP == "" { + c.UI.Error("-upstream-envoy-id OR -upstream-ip is required.") + c.UI.Error("Please run `consul troubleshoot upstreams` to find the corresponding upstream.") return 1 } - adminAddr, adminPort, err := net.SplitHostPort(c.adminBind) + adminAddr, adminPort, err := net.SplitHostPort(c.envoyAdminEndpoint) if err != nil { c.UI.Error("Invalid Envoy Admin endpoint: " + err.Error()) return 1 @@ -67,7 +70,8 @@ func (c *cmd) Run(args []string) int { // localhost here. adminBindIP, err := net.ResolveIPAddr("ip", adminAddr) if err != nil { - c.UI.Error("Failed to resolve admin bind address: " + err.Error()) + c.UI.Error("Failed to resolve Envoy admin endpoint: " + err.Error()) + c.UI.Error("Please make sure Envoy's Admin API is enabled.") return 1 } @@ -76,7 +80,7 @@ func (c *cmd) Run(args []string) int { c.UI.Error("error generating troubleshoot client: " + err.Error()) return 1 } - messages, err := t.RunAllTests(c.upstream) + messages, err := t.RunAllTests(c.upstreamEnvoyID, c.upstreamIP) if err != nil { c.UI.Error("error running the tests: " + err.Error()) return 1 @@ -111,9 +115,12 @@ Usage: consul troubleshoot proxy [options] Connects to local envoy proxy and troubleshoots service mesh communication issues. Requires an upstream service envoy identifier. Examples: - $ consul troubleshoot proxy -upstream foo + (explicit upstreams only) + $ consul troubleshoot proxy -upstream-envoy-id foo + (transparent proxy only) + $ consul troubleshoot proxy -upstream-ip - where 'foo' is the upstream envoy ID which + where 'foo' is the upstream envoy identifier which can be obtained by running: $ consul troubleshoot upstreams [options] ` diff --git a/command/troubleshoot/upstreams/troubleshoot_upstreams.go b/command/troubleshoot/upstreams/troubleshoot_upstreams.go index 1bf34d0e7..116952bf5 100644 --- a/command/troubleshoot/upstreams/troubleshoot_upstreams.go +++ b/command/troubleshoot/upstreams/troubleshoot_upstreams.go @@ -24,17 +24,17 @@ type cmd struct { help string // flags - adminBind string + envoyAdminEndpoint string } func (c *cmd) init() { c.flags = flag.NewFlagSet("", flag.ContinueOnError) - defaultAdminBind := "localhost:19000" - if adminBind := os.Getenv("ADMIN_BIND"); adminBind != "" { - defaultAdminBind = adminBind + defaultEnvoyAdminEndpoint := "localhost:19000" + if envoyAdminEndpoint := os.Getenv("ENVOY_ADMIN_ENDPOINT"); envoyAdminEndpoint != "" { + defaultEnvoyAdminEndpoint = envoyAdminEndpoint } - c.flags.StringVar(&c.adminBind, "admin-bind", defaultAdminBind, "The address:port that envoy's admin endpoint is on.") + c.flags.StringVar(&c.envoyAdminEndpoint, "envoy-admin-endpoint", defaultEnvoyAdminEndpoint, "The address:port that envoy's admin endpoint is on.") c.http = &flags.HTTPFlags{} flags.Merge(c.flags, c.http.ClientFlags()) @@ -49,7 +49,7 @@ func (c *cmd) Run(args []string) int { return 1 } - adminAddr, adminPort, err := net.SplitHostPort(c.adminBind) + adminAddr, adminPort, err := net.SplitHostPort(c.envoyAdminEndpoint) if err != nil { c.UI.Error("Invalid Envoy Admin endpoint: " + err.Error()) return 1 @@ -59,7 +59,8 @@ func (c *cmd) Run(args []string) int { // localhost here. adminBindIP, err := net.ResolveIPAddr("ip", adminAddr) if err != nil { - c.UI.Error("Failed to resolve admin bind address: " + err.Error()) + c.UI.Error("Failed to resolve envoy admin endpoint: " + err.Error()) + c.UI.Error("Please make sure Envoy's Admin API is enabled.") return 1 } @@ -74,14 +75,22 @@ func (c *cmd) Run(args []string) int { return 1 } + c.UI.Output(fmt.Sprintf("==> Upstreams (explicit upstreams only) (%v)", len(envoyIDs))) for _, u := range envoyIDs { c.UI.Output(u) } + c.UI.Output(fmt.Sprintf("\n==> Upstream IPs (transparent proxy only) (%v)", len(upstreamIPs))) for _, u := range upstreamIPs { c.UI.Output(fmt.Sprintf("%+v %v %+v", u.IPs, u.IsVirtual, u.ClusterNames)) } + c.UI.Output("\nIf you don't see your upstream address or cluster for a transparent proxy upstream:") + c.UI.Output("- Check intentions: Tproxy upstreams are configured based on intentions, make sure you " + + "have configured intentions to allow traffic to your upstream.") + c.UI.Output("- You can also check that the right cluster is being dialed by running a DNS lookup " + + "for the upstream you are dialing (i.e dig backend.svc.consul). If the address you get from that is missing " + + "from the Upstream IPs your proxy may be misconfigured.") return 0 } diff --git a/troubleshoot/proxy/troubleshoot_proxy.go b/troubleshoot/proxy/troubleshoot_proxy.go index 7b7502609..4b74012c9 100644 --- a/troubleshoot/proxy/troubleshoot_proxy.go +++ b/troubleshoot/proxy/troubleshoot_proxy.go @@ -52,7 +52,7 @@ func NewTroubleshoot(envoyIP *net.IPAddr, envoyPort string) (*Troubleshoot, erro }, nil } -func (t *Troubleshoot) RunAllTests(envoyID string) (validate.Messages, error) { +func (t *Troubleshoot) RunAllTests(upstreamEnvoyID, upstreamIP string) (validate.Messages, error) { var allTestMessages validate.Messages // Get all info from proxy to set up validations. @@ -91,7 +91,7 @@ func (t *Troubleshoot) RunAllTests(envoyID string) (validate.Messages, error) { // } // Validate listeners, routes, clusters, endpoints. - messages = Validate(indexedResources, envoyID, "", true, t.envoyClusters) + messages = Validate(indexedResources, upstreamEnvoyID, upstreamIP, true, t.envoyClusters) allTestMessages = append(allTestMessages, messages...) if errors := messages.Errors(); len(errors) == 0 { msg := validate.Message{