diff --git a/tap/source/discoverer_util.go b/tap/source/discoverer_util.go new file mode 100644 index 000000000..7c9640d4f --- /dev/null +++ b/tap/source/discoverer_util.go @@ -0,0 +1,38 @@ +package source + +import ( + "io/ioutil" + "regexp" + "strings" + + "github.com/up9inc/mizu/shared/logger" +) + +var numberRegex = regexp.MustCompile("[0-9]+") + +func getSingleValueFromEnvironmentVariableFile(filePath string, variableName string) (string, error) { + bytes, err := ioutil.ReadFile(filePath) + + if err != nil { + logger.Log.Warningf("Error reading environment file %v - %v", filePath, err) + return "", err + } + + envs := strings.Split(string(bytes), string([]byte{0})) + + for _, env := range envs { + if !strings.Contains(env, "=") { + continue + } + + parts := strings.Split(env, "=") + varName := parts[0] + value := parts[1] + + if variableName == varName { + return value, nil + } + } + + return "", nil +} diff --git a/tap/source/envoy_discoverer.go b/tap/source/envoy_discoverer.go index 0230b1273..d90f96943 100644 --- a/tap/source/envoy_discoverer.go +++ b/tap/source/envoy_discoverer.go @@ -4,7 +4,6 @@ import ( "fmt" "io/ioutil" "os" - "regexp" "strings" "github.com/up9inc/mizu/shared/logger" @@ -13,8 +12,6 @@ import ( const envoyBinary = "/envoy" -var numberRegex = regexp.MustCompile("[0-9]+") - func discoverRelevantEnvoyPids(procfs string, pods []v1.Pod) ([]string, error) { result := make([]string, 0) @@ -36,7 +33,7 @@ func discoverRelevantEnvoyPids(procfs string, pods []v1.Pod) ([]string, error) { continue } - if checkPid(procfs, pid.Name(), pods) { + if checkEnvoyPid(procfs, pid.Name(), pods) { result = append(result, pid.Name()) } } @@ -46,7 +43,7 @@ func discoverRelevantEnvoyPids(procfs string, pods []v1.Pod) ([]string, error) { return result, nil } -func checkPid(procfs string, pid string, pods []v1.Pod) bool { +func checkEnvoyPid(procfs string, pid string, pods []v1.Pod) bool { execLink := fmt.Sprintf("%v/%v/exe", procfs, pid) exec, err := os.Readlink(execLink) @@ -63,7 +60,7 @@ func checkPid(procfs string, pid string, pods []v1.Pod) bool { } environmentFile := fmt.Sprintf("%v/%v/environ", procfs, pid) - podIp, err := readEnvironmentVariable(environmentFile, "INSTANCE_IP") + podIp, err := getSingleValueFromEnvironmentVariableFile(environmentFile, "INSTANCE_IP") if err != nil { return false @@ -84,30 +81,3 @@ func checkPid(procfs string, pid string, pods []v1.Pod) bool { return false } - -func readEnvironmentVariable(file string, name string) (string, error) { - bytes, err := ioutil.ReadFile(file) - - if err != nil { - logger.Log.Warningf("Error reading environment file %v - %v", file, err) - return "", err - } - - envs := strings.Split(string(bytes), string([]byte{0})) - - for _, env := range envs { - if !strings.Contains(env, "=") { - continue - } - - parts := strings.Split(env, "=") - varName := parts[0] - value := parts[1] - - if name == varName { - return value, nil - } - } - - return "", nil -} diff --git a/tap/source/linkerd_discoverer.go b/tap/source/linkerd_discoverer.go new file mode 100644 index 000000000..808fc8036 --- /dev/null +++ b/tap/source/linkerd_discoverer.go @@ -0,0 +1,83 @@ +package source + +import ( + "fmt" + "io/ioutil" + "os" + "strings" + + "github.com/up9inc/mizu/shared/logger" + v1 "k8s.io/api/core/v1" +) + +const linkerdBinary = "/linkerd2-proxy" + +func discoverRelevantLinkerdPids(procfs string, pods []v1.Pod) ([]string, error) { + result := make([]string, 0) + + pids, err := ioutil.ReadDir(procfs) + + if err != nil { + return result, err + } + + logger.Log.Infof("Starting linkerd auto discoverer %v %v - scanning %v potential pids", + procfs, pods, len(pids)) + + for _, pid := range pids { + if !pid.IsDir() { + continue + } + + if !numberRegex.MatchString(pid.Name()) { + continue + } + + if checkLinkerdPid(procfs, pid.Name(), pods) { + result = append(result, pid.Name()) + } + } + + logger.Log.Infof("Found %v relevant linkerd processes - %v", len(result), result) + + return result, nil +} + +func checkLinkerdPid(procfs string, pid string, pods []v1.Pod) bool { + execLink := fmt.Sprintf("%v/%v/exe", procfs, pid) + exec, err := os.Readlink(execLink) + + if err != nil { + // Debug on purpose - it may happen due to many reasons and we only care + // for it during troubleshooting + // + logger.Log.Debugf("Unable to read link %v - %v\n", execLink, err) + return false + } + + if !strings.HasSuffix(exec, linkerdBinary) { + return false + } + + environmentFile := fmt.Sprintf("%v/%v/environ", procfs, pid) + podName, err := getSingleValueFromEnvironmentVariableFile(environmentFile, "_pod_name") + + if err != nil { + return false + } + + if podName == "" { + logger.Log.Debugf("Found a linkerd process without _pod_name variable %v\n", pid) + return false + } + + logger.Log.Infof("Found linkerd pid %v with pod name %v", pid, podName) + + for _, pod := range pods { + if pod.Name == podName { + return true + } + } + + return false +} diff --git a/tap/source/packet_source_manager.go b/tap/source/packet_source_manager.go index af88554ea..912d03c9a 100644 --- a/tap/source/packet_source_manager.go +++ b/tap/source/packet_source_manager.go @@ -16,7 +16,7 @@ type PacketSourceManager struct { } func NewPacketSourceManager(procfs string, pids string, filename string, interfaceName string, - istio bool, pods []v1.Pod, behaviour TcpPacketSourceBehaviour) (*PacketSourceManager, error) { + mtls bool, pods []v1.Pod, behaviour TcpPacketSourceBehaviour) (*PacketSourceManager, error) { sources := make([]*tcpPacketSource, 0) sources, err := createHostSource(sources, filename, interfaceName, behaviour) @@ -25,7 +25,8 @@ func NewPacketSourceManager(procfs string, pids string, filename string, interfa } sources = createSourcesFromPids(sources, procfs, pids, interfaceName, behaviour) - sources = createSourcesFromEnvoy(sources, istio, procfs, pods, interfaceName, behaviour) + sources = createSourcesFromEnvoy(sources, mtls, procfs, pods, interfaceName, behaviour) + sources = createSourcesFromLinkerd(sources, mtls, procfs, pods, interfaceName, behaviour) return &PacketSourceManager{ sources: sources, @@ -54,13 +55,13 @@ func createSourcesFromPids(sources []*tcpPacketSource, procfs string, pids strin return sources } -func createSourcesFromEnvoy(sources []*tcpPacketSource, istio bool, procfs string, clusterIps []v1.Pod, +func createSourcesFromEnvoy(sources []*tcpPacketSource, mtls bool, procfs string, pods []v1.Pod, interfaceName string, behaviour TcpPacketSourceBehaviour) []*tcpPacketSource { - if !istio { + if !mtls { return sources } - envoyPids, err := discoverRelevantEnvoyPids(procfs, clusterIps) + envoyPids, err := discoverRelevantEnvoyPids(procfs, pods) if err != nil { logger.Log.Warningf("Unable to discover envoy pids - %v", err) @@ -73,6 +74,25 @@ func createSourcesFromEnvoy(sources []*tcpPacketSource, istio bool, procfs strin return sources } +func createSourcesFromLinkerd(sources []*tcpPacketSource, mtls bool, procfs string, pods []v1.Pod, + interfaceName string, behaviour TcpPacketSourceBehaviour) []*tcpPacketSource { + if !mtls { + return sources + } + + linkerdPids, err := discoverRelevantLinkerdPids(procfs, pods) + + if err != nil { + logger.Log.Warningf("Unable to discover linkerd pids - %v", err) + return sources + } + + netnsSources := newNetnsPacketSources(procfs, linkerdPids, interfaceName, behaviour) + sources = append(sources, netnsSources...) + + return sources +} + func newHostPacketSource(filename string, interfaceName string, behaviour TcpPacketSourceBehaviour) (*tcpPacketSource, error) { var name string