Skip to content

Commit

Permalink
feat: map IP address to pod name (#42)
Browse files Browse the repository at this point in the history
## βœ… Which problem is this PR solving?

- Closes #40 

## πŸ“ Short description of the changes
- Use k8s sdk to get pod metadata
- Map source / dest IPs to pod names

## 🀯 Janky stuff
- Source IP mapping doesn't work at the moment because source IPs are
janky 😬

## πŸ§ͺ  How to verify that this has the expected result
- Build and run the agent in a kube cluster 
- Configure Honeycomb API key
- Should see destination IP addresses mapped to destination pod names
  • Loading branch information
pkanal committed Jul 27, 2023
1 parent 9ba6b39 commit 736a2d4
Show file tree
Hide file tree
Showing 5 changed files with 596 additions and 21 deletions.
75 changes: 60 additions & 15 deletions bpf/probes/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package probes

import (
"bytes"
"context"
"encoding/binary"
"errors"
"fmt"
Expand All @@ -12,6 +13,10 @@ import (
"github.com/cilium/ebpf/link"
"github.com/cilium/ebpf/perf"
"github.com/honeycombio/libhoney-go"
v1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/rest"
)

//go:generate go run github.com/cilium/ebpf/cmd/bpf2go -target amd64,arm64 -cc clang -cflags $CFLAGS bpf tcp_probe.c
Expand All @@ -20,11 +25,11 @@ const mapKey uint32 = 0

type Event struct {
StartTime uint64
EndTime uint64
Daddr uint32
Dport uint16
Saddr uint32
Sport uint16
EndTime uint64
Daddr uint32
Dport uint16
Saddr uint32
Sport uint16
BytesSent uint64
}

Expand Down Expand Up @@ -85,22 +90,62 @@ func Setup() {

// log.Printf("event: %+v\n", event)

ev := libhoney.NewEvent()
ev.AddField("name", "tcp_event")
ev.AddField("duration_ms", (event.EndTime - event.StartTime) / 1_000_000) // convert ns to ms
ev.AddField("source", fmt.Sprintf("%s:%d", intToIP(event.Saddr), event.Sport))
ev.AddField("dest", fmt.Sprintf("%s:%d", intToIP(event.Daddr), event.Dport))
ev.AddField("num_bytes", event.BytesSent)
err = ev.Send()
if err != nil {
log.Printf("error sending event: %v\n", err)
sendEvent(event)
}
}

func getPodByIPAddr(ipAddr string) v1.Pod {
// creates the in-cluster config
config, err := rest.InClusterConfig()
if err != nil {
panic(err.Error())
}
// creates the clientset
client, err := kubernetes.NewForConfig(config)
if err != nil {
panic(err.Error())
}

pods, _ := client.CoreV1().Pods(v1.NamespaceAll).List(context.TODO(), metav1.ListOptions{})

var matchedPod v1.Pod

for _, pod := range pods.Items {
if ipAddr == pod.Status.PodIP {
matchedPod = pod
}
}

return matchedPod
}

// Send event to Honeycomb
func sendEvent(event Event) {

sourceIpAddr := intToIP(event.Saddr).String()
destIpAddr := intToIP(event.Daddr).String()

destPod := getPodByIPAddr(destIpAddr)
sourcePod := getPodByIPAddr(sourceIpAddr)

ev := libhoney.NewEvent()
ev.AddField("name", "tcp_event")
ev.AddField("duration_ms", (event.EndTime-event.StartTime)/1_000_000) // convert ns to ms
ev.AddField("source", fmt.Sprintf("%s:%d", sourceIpAddr, event.Sport))
ev.AddField("dest", fmt.Sprintf("%s:%d", destIpAddr, event.Dport))
ev.AddField("num_bytes", event.BytesSent)
ev.AddField("k8s.pod.dest.name", destPod.Name)
ev.AddField("k8s.pod.source.name", sourcePod.Name)

err := ev.Send()
if err != nil {
log.Printf("error sending event: %v\n", err)
}
}

// intToIP converts IPv4 number to net.IP
func intToIP(ipNum uint32) net.IP {
ip := make(net.IP, 4)
binary.LittleEndian.PutUint32(ip, ipNum)
return ip
}
}
36 changes: 34 additions & 2 deletions deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,37 @@ stringData:
# export GITHUB_TOKEN env var as 'github_username:github_token'
# export BASE64_TOKEN=$(echo -n $GITHUB_TOKEN | base64)
.dockerconfigjson: "{\"auths\":{\"ghcr.io\":{\"auth\":\"$BASE64_TOKEN\"}}}"

## Permissions to access pod metadata
---
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: null
name: honeycomb-sa
namespace: honeycomb
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: honeycomb
rules:
- apiGroups: ["", "metrics.k8s.io","apps"]
resources: ["*"]
verbs: ["get","watch","list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: honeycomb
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: honeycomb
subjects:
- kind: ServiceAccount
namespace: honeycomb
name: honeycomb-sa
---
apiVersion: apps/v1
kind: DaemonSet
Expand All @@ -42,6 +73,7 @@ spec:
labels:
name: hny-ebpf-agent
spec:
serviceAccountName: honeycomb-sa
containers:
- name: hny-ebpf-agent
image: hny/ebpf-agent:local
Expand All @@ -56,8 +88,8 @@ spec:
- name: HONEYCOMB_DATASET
value: ebpf-agent-go
# set to another endpoint if desired
# - name: HONEYCOMB_API_ENDPOINT
# value: $HONEYCOMB_API_ENDPOINT
- name: HONEYCOMB_API_ENDPOINT
value: $HONEYCOMB_API_ENDPOINT
securityContext:
capabilities:
add:
Expand Down
39 changes: 38 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,52 @@ go 1.20
require (
github.com/cilium/ebpf v0.10.0
github.com/honeycombio/libhoney-go v1.20.0
k8s.io/apimachinery v0.27.4
k8s.io/client-go v0.27.4
)

require (
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a // indirect
github.com/facebookgo/limitgroup v0.0.0-20150612190941-6abd8d71ec01 // indirect
github.com/facebookgo/muster v0.0.0-20150708232844-fd3d7953fd52 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.1 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gnostic v0.5.7-v3refs // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/compress v1.16.6 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
golang.org/x/sys v0.2.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/term v0.6.0 // indirect
golang.org/x/text v0.8.0 // indirect
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/alexcesaro/statsd.v2 v2.0.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
k8s.io/api v0.27.4 // indirect
k8s.io/klog/v2 v2.90.1 // indirect
k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f // indirect
k8s.io/utils v0.0.0-20230209194617-a36077c30491 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)
Loading

0 comments on commit 736a2d4

Please sign in to comment.