Contributing

    Here you can learn how you can contribute to Inspektor Gadget.

    Getting started

    To better understand how the pieces fit together, we recommend reading the architecture documentation before starting to play with Inspektor Gadget.

    Setup developer environment

    • Fork and clone this repo:
      • git clone git@github.com:your_account/inspektor-gadget.git.
    • Install Docker , Docker Buildx and Golang .
    • To be able to cross build our different container images, you will also need qemu-user-static .

    Building the code

    Inspektor Gadget is composed of a client executable that runs on the operator’s machine, and a container image that runs in the Kubernetes cluster. They can be built together or independently.

    Building the client executable

    You can compile the client executable for your platform by running make kubectl-gadget.

    To cross compile for all supported platforms, you can run make kubectl-gadget-all or select a specific one with make kubectl-gadget-linux-amd64 or make kubectl-gadget-darwin-amd64.

    Building the gadget container image

    Inspektor Gadget provides two different container images:

    • gadget-default: Contains CO-RE and BCC gadgets
    • gadget-core: Containes only CO-RE gadgets that are integrated with the gadget tracer manager
      • traceloop gadget is not included, it will be included once #371 is fixed.

    You can build and push the container gadget image by running the following commands:

    $ make gadget-default-container # or make gadget-core-container
    $ make push-gadget-default-container
    

    The eBPF code is built using a Docker container, so you don’t have to worry installing the compilers to build it.

    If you push the container images to another registry, you can use the --image argument when deploying to the Kubernetes cluster.

    Notes

    • Using a locally built container image requires pushing it to a container registry, either local or remote. The default registry can be overridden by changing the value of the CONTAINER_REPO env variable, which defaults to ghcr.io/inspektor-gadget/inspektor-gadget if not defined.
    • The compilation uses tools/image-tag to choose the tag of the container image to use according to the branch that you are compiling.
    • If you wish to make changes to traceloop program, update gadget-default.Dockerfile to pick your own image of traceloop.
    • As for traceloop, it is also possible to change the BCC to be used as described in BCC section.
    • You can generate the required BTF information for some well known kernel versions by setting ENABLE_BTFGEN=true

    Building the eBPF object files

    If you need to compile the eBPF code of the gadgets, the ebpf-objects target will help you in this task:

    $ make ebpf-objects
    ...
    go: downloading github.com/giantswarm/crd-docs-generator v0.7.1
    ...
    Wrote /work/pkg/gadgettracermanager/containers-map/containersmap_bpfel.go
    

    Building ig

    Inspektor Gadget also provides the ig tool to trace containers without Kubernetes. It can be built independently from the kubectl-gadget and the gadget container image.

    $ make ig
    

    Testing

    Development environment on minikube

    For faster iteration, it’s possible to make changes to Inspektor Gadget and test them on minikube locally without pushing container images to any registry.

    • Follow the specific installation instructions for minikube or use make minikube-start to start it.
    • Deploy the locally modified version of Inspektor Gadget to an already running minikube cluster with make minikube-deploy.

    Unit tests

    Requirements

    For running unit tests, the following additional requirements need to be installed and configured on your system:

    • gcc compiler
    • pkg-config and libseccomp-dev libraries

    You can run the different unit tests with:

    $ make test
    

    Integration tests

    The integration tests use a Kubernetes cluster to deploy and test Inspektor Gadget. Be sure that you have a valid kubeconfig and run:

    $ export KUBECONFIG=... # not needed if valid config in $HOME/.kube/config
    $ make integration-tests
    

    Integration tests for ig

    Kubernetes

    The integration tests for ig uses minikube for testing different container runtimes. The default minikube driver used for testing is docker. Currently supported container runtimes are docker, containerd and cri-o. You can start minikube using:

    $ make minikube-start-all
    # for single container runtime e.g containerd
    $ make CONTAINER_RUNTIME=containerd minikube-start
    # for minikube driver other than docker e.g kvm2
    $ make MINIKUBE_DRIVER=kvm2 minikube-start
    

    And run the test using:

    $ make -C integration/ig/k8s test-all
    # for single container runtime e.g containerd
    $ make -C integration/ig/k8s CONTAINER_RUNTIME=containerd test
    

    if no CONTAINER_RUNTIME is specified docker will be used as a default runtime.

    Non-Kubernetes

    The ig integration tests for non-Kubernetes containers directly interact with container runtime. The tests assume that you already have the desired container runtime installed. Currently supported runtime is docker only, You can run the test using:

    $ make -C integration/ig/non-k8s test-docker
    

    Benchmarks

    You can run the different benchmark tests with:

    $ make gadgets-benchmarks
    

    Or you can run an individual test with:

    $ go test -exec sudo \
        -bench='BenchmarkAllGadgetsWithContainers/container10$/trace-tcpconnect' \
        -run=Benchmark \
        ./internal/benchmarks/...
    

    Records of previous benchmarks are available here . See details in the CI documentation (benchmarks) .

    Explaining performance improvements in a PR

    If you want to contribute a performance improvement, it is useful to use benchmarks to explain the impact on performances. I will use the example of an improvement on the networking gadgets from #1430 :

    • Run the benchmarks both on the main and the feature branches and saving the output in two files.
    $ git checkout main
    $ go test -exec sudo \
        -bench='^BenchmarkAllGadgetsWithContainers$/^container100$/trace-(dns|sni)' \
        -run=Benchmark \
        ./internal/benchmarks/... \
        -count 10 | tee main.bench
    $ git checkout myfeature
    $ go test -exec sudo \
        -bench='^BenchmarkAllGadgetsWithContainers$/^container100$/trace-(dns|sni)' \
        -run=Benchmark \
        ./internal/benchmarks/... \
        -count 10 | tee patched.bench
    

    Please use -count to gather a statistically significant sample of results. The benchstat’s documentation recommends 10 times.

    • Compare the results with benchstat:
    $ go install golang.org/x/perf/cmd/benchstat@latest # if not already installed
    $ benchstat main.bench patched.bench
    goos: linux
    goarch: amd64
    pkg: github.com/inspektor-gadget/inspektor-gadget/internal/benchmarks
    cpu: Intel(R) Core(TM) i7-6500U CPU @ 2.50GHz
                                                      │ main.bench  │           patched.bench            │
                                                      │   sec/op    │   sec/op    vs base                │
    AllGadgetsWithContainers/container100/trace-dns-4   2.941 ±  3%   1.489 ± 4%  -49.38% (p=0.000 n=10)
    AllGadgetsWithContainers/container100/trace-sni-4   4.440 ± 19%   1.495 ± 6%  -66.34% (p=0.000 n=10)
    geomean                                             3.613         1.492       -58.72%
    
    • Include the commands used and the output of benchstat in your pull request description

    Continuous Integration

    Inspektor Gadget uses GitHub Actions as CI. Please check dedicated CI documentation for details.

    Contribution Guidelines

    Code of Conduct

    Please refer to the Kinvolk Code of Conduct .

    Authoring PRs

    For making PRs/commits consistent and easier to review, please check out Kinvolk’s contribution guidelines on git .

    Good first issues

    If you’re looking where to start, you can check the issues with the good first issue label on Inspektor Gadget or traceloop . Don’t hesitate to talk to us if you need further help.

    Proposing new features

    If you want to propose a new feature or do a big change in the architecture it’s highly recommended to open an issue first to discuss it with the team.

    Writing tests

    We use github.com/stretchr/testify to make tests less verbose.

    Planning

    Our planning is published through two different project boards:

    BCC

    Porting BCC gadgets

    This project uses some gadgets from BCC . Instead of keeping our patched versions, we prefer to make those gadgets suitable to be used with Inspektor Gadget by contributing to the upstream project.

    A BCC gadget has to provide a filtering mechanism by cgroup id and mount namespace id in order to be compatible with Inspektor Gadget. You can get some inspiration from the opensnoop and execsnoop implementations to port a different BCC gadget.

    Once the gadget has been updated in the BCC repo, it can be added to Inspektor Gadget by filling a PR adding the gadget to cmd/kubectl-gadget/bcck8s.go . The add gadget bindsnoop PR is an example of it.

    The adding new BCC-based gadgets in Inspektor Gadget blogpost presents some more details about this process.

    Updating BCC from upstream

    As you can see in gadget-default.Dockerfile, the gadget container image uses the BCC container image as its parent image. Given that there is not an official container repository to get that BCC image, we keep a synchronised Kinvolk BCC fork that is configured to publish the images on Kinvolk container registries Quay and Docker Hub , by using the Github actions already available in BCC upstream .

    Given that, if you want to update the BCC version used by Inspektor Gadget, it is necessary to first update the Kinvolk BCC fork so that the Github actions are triggered, and a new image is published. Once the image is available in registries, you have to update gadget-default.Dockerfile so that it uses the just created image, same goes for local compilation with gadget-local.Dockerfile. The Update BCC container image PR is an example of it.

    Currently, we use Docker Hub to pull the BCC image when building the gadget container image. Notice we do not use the latest tag because it is overwritten after each push on master branch. Instead, we use the stable unique tags that are named with format: <Timestamp><Commit-SHA>. For instance, tag 202107061407494e8e8c describes that it was created in 2021-07-06 at 14:07:49 from commit SHA starting with 4e8e8c.