123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112 |
- package render
- import (
- "net"
- "regexp"
- "strings"
- "camlistore.org/pkg/lru"
- "github.com/weaveworks/scope/report"
- )
- var (
- // ServiceNodeIDPrefix is how the ID of all service pseudo nodes begin
- ServiceNodeIDPrefix = "service-"
- knownServiceMatcher = regexp.MustCompile(`^.+\.(` + strings.Join([]string{
- // See http://docs.aws.amazon.com/general/latest/gr/rande.html
- // for finer grained details
- `amazonaws\.com`,
- `googleapis\.com`,
- `weave\.works`, // Weave Cloud
- `core\.windows\.net`, // Azure Storage - Blob, Tables, Files & Queues
- `servicebus\.windows\.net`, // Azure Service Bus
- `azure-api\.net`, // Azure API Management
- `onmicrosoft\.com`, // Azure Active Directory
- `cloudapp\.azure\.com`, // Azure IaaS
- `database\.windows\.net`, // Azure SQL DB
- `documents\.azure\.com`, // Azure DocumentDB/CosmosDB
- }, `|`) + `)$`)
- knownServiceExcluder = regexp.MustCompile(`^(` + strings.Join([]string{
- // We exclude ec2 machines because they are too generic
- // and having separate nodes for them makes visualizations worse
- `ec2.*\.amazonaws\.com`,
- }, `|`) + `)$`)
- // Memoization for isKnownService.
- //
- // The 10000 comes from the observation that large reports contain
- // hundreds of names, and in a multi-tenant context we want to be
- // able to render a few dozen reports concurrently. Also, unlike
- // memoization in the reducers, which is keyed on reports, this
- // cache is effective when rendering multiple reports from the
- // same cluster of probes, e.g. from different points in time,
- // since names tend to change infrequently.
- //
- // Since names are generally <50 bytes, this shouldn't weight in
- // at more than a few MB of memory.
- knownServiceCache = lru.New(10000)
- )
- func purgeKnownServiceCache() {
- knownServiceCache = lru.New(10000)
- }
- // TODO: Make it user-customizable https://github.com/weaveworks/scope/issues/1876
- // NB: this is a hotspot in rendering performance.
- func isKnownService(hostname string) bool {
- if v, ok := knownServiceCache.Get(hostname); ok {
- return v.(bool)
- }
- known := knownServiceMatcher.MatchString(hostname) && !knownServiceExcluder.MatchString(hostname)
- knownServiceCache.Add(hostname, known)
- return known
- }
- // LocalNetworks returns a superset of the networks (think: CIDRs) that are
- // "local" from the perspective of each host represented in the report. It's
- // used to determine which nodes in the report are "remote", i.e. outside of
- // our infrastructure.
- func LocalNetworks(r report.Report) report.Networks {
- networks := report.MakeNetworks()
- for _, topology := range []report.Topology{r.Host, r.Overlay} {
- for _, md := range topology.Nodes {
- nets, _ := md.Sets.Lookup(report.HostLocalNetworks)
- for _, s := range nets {
- networks.AddCIDR(s)
- }
- }
- }
- if extra := kubeServiceNetwork(r.Service); extra != nil {
- networks.Add(extra)
- }
- return networks
- }
- // FIXME: Hideous hack to remove persistent-connection edges to
- // virtual service IPs attributed to the internet. The global
- // service-cluster-ip-range is not exposed by the API server (see
- // https://github.com/kubernetes/kubernetes/issues/25533), so instead
- // we synthesise it by computing the smallest network that contains
- // all service IPs. That network may be smaller than the actual range
- // but that is ok, since in the end all we care about is that it
- // contains all the service IPs.
- //
- // The right way of fixing this is performing DNAT mapping on
- // persistent connections for which we don't have a robust solution
- // (see https://github.com/weaveworks/scope/issues/1491).
- func kubeServiceNetwork(services report.Topology) *net.IPNet {
- serviceIPs := make([]net.IP, 0, len(services.Nodes))
- for _, md := range services.Nodes {
- serviceIP, _ := md.Latest.Lookup(report.KubernetesIP)
- if ip := net.ParseIP(serviceIP).To4(); ip != nil {
- serviceIPs = append(serviceIPs, ip)
- }
- }
- return report.ContainingIPv4Network(serviceIPs)
- }
|