Skip to content

Commit

Permalink
Add new flag --docker-address, --containerd-address, `--cri-runti…
Browse files Browse the repository at this point in the history
…me-address` (#74)
  • Loading branch information
mozillazg authored Jun 16, 2024
1 parent c7f09bd commit f844a9e
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 29 deletions.
38 changes: 21 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,23 +150,27 @@ Examples:
Expression: see "man 7 pcap-filter"
Flags:
--container-id string Filter by container id (only TCP and UDP packets are supported)
--container-name string Filter by container name (only TCP and UDP packets are supported)
-Q, --direction string Choose send/receive direction for which packets should be captured. Possible values are 'in', 'out' and 'inout' (default "inout")
-f, --follow-forks Trace child processes as they are created by currently traced processes when filter by process
-h, --help help for ptcpdump
-i, --interface strings Interfaces to capture (default [lo])
--list-interfaces Print the list of the network interfaces available on the system
--log-level string Set the logging level ("debug", "info", "warn", "error", "fatal") (default "warn")
--oneline Print parsed packet output in a single line
--pid uint Filter by process ID (only TCP and UDP packets are supported)
--pname string Filter by process name (only TCP and UDP packets are supported)
--print Print parsed packet output, even if the raw packets are being saved to a file with the -w flag
-r, --read-file string Read packets from file (which was created with the -w option). e.g. ptcpdump.pcapng
-c, --receive-count uint Exit after receiving count packets
-v, --verbose count When parsing and printing, produce (slightly more) verbose output
--version Print the ptcpdump and libpcap version strings and exit
-w, --write-file string Write the raw packets to file rather than parsing and printing them out. They can later be printed with the -r option. Standard output is used if file is '-'. e.g. ptcpdump.pcapng
--container-id string Filter by container id (only TCP and UDP packets are supported)
--container-name string Filter by container name (only TCP and UDP packets are supported)
--containerd-address string Address of containerd service (default "/run/containerd/containerd.sock")
--count Print only on stdout the packet count when reading capture file instead of parsing/printing the packets
--cri-runtime-address string Address of CRI container runtime service (default: uses in order the first successful one of [/run/containerd/containerd.sock, /run/crio/crio.sock, /var/run/cri-dockerd.sock, /var/run/dockershim.sock])
-Q, --direction string Choose send/receive direction for which packets should be captured. Possible values are 'in', 'out' and 'inout' (default "inout")
--docker-address string Address of Docker Engine service (default "/var/run/docker.sock")
-f, --follow-forks Trace child processes as they are created by currently traced processes when filter by process
-h, --help help for ptcpdump
-i, --interface strings Interfaces to capture (default [lo])
--list-interfaces Print the list of the network interfaces available on the system
--log-level string Set the logging level ("debug", "info", "warn", "error", "fatal") (default "warn")
--oneline Print parsed packet output in a single line
--pid uint Filter by process ID (only TCP and UDP packets are supported)
--pname string Filter by process name (only TCP and UDP packets are supported)
--print Print parsed packet output, even if the raw packets are being saved to a file with the -w flag
-r, --read-file string Read packets from file (which was created with the -w option). e.g. ptcpdump.pcapng
-c, --receive-count uint Exit after receiving count packets
-v, --verbose count When parsing and printing, produce (slightly more) verbose output
--version Print the ptcpdump and libpcap version strings and exit
-w, --write-file string Write the raw packets to file rather than parsing and printing them out. They can later be printed with the -r option. Standard output is used if file is '-'. e.g. ptcpdump.pcapng
```

<p align="right"><a href="#top">🔝</a></p>
Expand Down
3 changes: 2 additions & 1 deletion cmd/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import (
)

func applyContainerFilter(ctx context.Context, opts *Options) (*metadata.ContainerCache, error) {
cc, err := metadata.NewContainerCache(ctx)
cc, err := metadata.NewContainerCache(ctx, opts.dockerEndpoint,
opts.containerdEndpoint, opts.criRuntimeEndpoint)
if err != nil {
if opts.filterByContainer() {
log.Fatalf("find container failed: %s", err)
Expand Down
35 changes: 35 additions & 0 deletions cmd/options.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package cmd

import (
"fmt"
"strings"
"time"

"github.com/mozillazg/ptcpdump/internal/metadata/k8s"
)

const (
Expand Down Expand Up @@ -38,6 +41,10 @@ type Options struct {
execEventsWorkerNumber uint
logLevel string

dockerEndpoint string
containerdEndpoint string
criRuntimeEndpoint string

subProgArgs []string

mntns_id uint32
Expand Down Expand Up @@ -76,4 +83,32 @@ func prepareOptions(opts *Options, rawArgs []string, args []string) {
opts.pcapFilter = strings.TrimSuffix(opts.pcapFilter, strings.Join(subProgArgs, " "))
}
opts.pcapFilter = strings.TrimSpace(opts.pcapFilter)

if opts.dockerEndpoint != "" {
opts.dockerEndpoint = getEndpoint(opts.dockerEndpoint)
}
// if opts.containerdEndpoint != "" {
// opts.containerdEndpoint = getEndpoint(opts.containerdEndpoint)
// }
if opts.criRuntimeEndpoint != "" {
opts.criRuntimeEndpoint = getEndpoint(opts.criRuntimeEndpoint)
}
}

func getEndpoint(raw string) string {
if strings.HasPrefix(raw, "http") {
return raw
}
if strings.HasPrefix(raw, "unix://") {
return raw
}
return fmt.Sprintf("unix://%s", raw)
}

func getDefaultCriRuntimeEndpoint() []string {
var rs []string
for _, end := range k8s.DefaultRuntimeEndpoints {
rs = append(rs, strings.TrimPrefix(end, "unix://"))
}
return rs
}
10 changes: 10 additions & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ package cmd

import (
"context"
"fmt"
"os"
"os/signal"
"strings"
"syscall"

"github.com/mozillazg/ptcpdump/internal/utils"
Expand Down Expand Up @@ -85,6 +87,14 @@ func init() {
rootCmd.Flags().StringVar(&opts.containerId, "container-id", "", "Filter by container id (only TCP and UDP packets are supported)")
rootCmd.Flags().StringVar(&opts.containerName, "container-name", "", "Filter by container name (only TCP and UDP packets are supported)")
rootCmd.Flags().StringVar(&opts.logLevel, "log-level", "warn", `Set the logging level ("debug", "info", "warn", "error", "fatal")`)
rootCmd.Flags().StringVar(&opts.dockerEndpoint, "docker-address", "/var/run/docker.sock",
`Address of Docker Engine service`)
rootCmd.Flags().StringVar(&opts.containerdEndpoint, "containerd-address", "/run/containerd/containerd.sock",
`Address of containerd service`)
rootCmd.Flags().StringVar(&opts.criRuntimeEndpoint, "cri-runtime-address", "",
"Address of CRI container runtime service "+
fmt.Sprintf("(default: uses in order the first successful one of [%s])",
strings.Join(getDefaultCriRuntimeEndpoint(), ", ")))

}

Expand Down
7 changes: 4 additions & 3 deletions internal/metadata/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@ type ContainerCache struct {
k8s *k8s.MetaData
}

func NewContainerCache(ctx context.Context) (*ContainerCache, error) {
d := container.NewMultipleEngineMetaData()
func NewContainerCache(ctx context.Context,
dockerEndpoint, containerdEndpoint, criRuntimeEndpoint string) (*ContainerCache, error) {
d := container.NewMultipleEngineMetaData(dockerEndpoint, containerdEndpoint)

if err := d.Start(ctx); err != nil {
return nil, err
}
k8sd, err := k8s.NewMetaData()
k8sd, err := k8s.NewMetaData(criRuntimeEndpoint)
if err != nil {
log.Warnf("skip k8s integration: %s", err)
}
Expand Down
6 changes: 3 additions & 3 deletions internal/metadata/container/multiple.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ type MultipleEngineMetaData struct {
engines []MetaData
}

func NewMultipleEngineMetaData() *MultipleEngineMetaData {
func NewMultipleEngineMetaData(dockerEndpoint, containerdEndpoint string) *MultipleEngineMetaData {
var m MultipleEngineMetaData

dr, err := docker.NewMetaData("")
dr, err := docker.NewMetaData(dockerEndpoint)
if err != nil {
log.Infof(err.Error())
log.Warn("skip Docker Engine integration")
} else {
m.engines = append(m.engines, dr)
}

cd, err := containerd.NewMultipleNamespacesMetaData("", "")
cd, err := containerd.NewMultipleNamespacesMetaData(containerdEndpoint, "")
if err != nil {
log.Infof(err.Error())
log.Warn("skip containerd integration")
Expand Down
15 changes: 10 additions & 5 deletions internal/metadata/k8s/cri.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ import (
"k8s.io/klog/v2"
)

var defaultRuntimeEndpoints = []string{
var DefaultRuntimeEndpoints = []string{
"unix:///run/containerd/containerd.sock",
"unix:///run/crio/crio.sock",
"unix:///var/run/cri-dockerd.sock",
"unix:///var/run/dockershim.sock",
}

const defaultTimeout = 2 * time.Second
Expand All @@ -25,8 +26,8 @@ type MetaData struct {
res cri.RuntimeService
}

func NewMetaData() (*MetaData, error) {
res, err := getRuntimeService()
func NewMetaData(criRuntimeEndpoint string) (*MetaData, error) {
res, err := getRuntimeService(criRuntimeEndpoint)
if err != nil {
log.Warn("skip kubernetes integration")
}
Expand Down Expand Up @@ -79,12 +80,16 @@ func tidyLabels(raw map[string]string) map[string]string {
return newLabels
}

func getRuntimeService() (res cri.RuntimeService, err error) {
func getRuntimeService(criRuntimeEndpoint string) (res cri.RuntimeService, err error) {
logger := klog.Background()
t := defaultTimeout
endpoints := DefaultRuntimeEndpoints
var tp trace.TracerProvider = noop.NewTracerProvider()
if criRuntimeEndpoint != "" {
endpoints = []string{criRuntimeEndpoint}
}

for _, endPoint := range defaultRuntimeEndpoints {
for _, endPoint := range endpoints {
log.Debugf("Connect using endpoint %q with %q timeout", endPoint, t)
res, err = remote.NewRemoteRuntimeService(endPoint, t, tp, &logger)
if err != nil {
Expand Down

0 comments on commit f844a9e

Please sign in to comment.