-
Notifications
You must be signed in to change notification settings - Fork 215
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add kapinger traffic gen tool (#545)
# Description Add Kapinger traffic gen and toolbox image to this repo ## Related Issue If this pull request is related to any issue, please mention it here. Additionally, make sure that the issue is assigned to you before submitting this pull request. ## Checklist - [ ] I have read the [contributing documentation](https://retina.sh/docs/contributing). - [ ] I signed and signed-off the commits (`git commit -S -s ...`). See [this documentation](https://docs.github.com/en/authentication/managing-commit-signature-verification/about-commit-signature-verification) on signing commits. - [ ] I have correctly attributed the author(s) of the code. - [ ] I have tested the changes locally. - [ ] I have followed the project's style guidelines. - [ ] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed Please add any relevant screenshots or GIFs to showcase the changes made. ## Additional Notes Add any additional notes or context about the pull request here. --- Please refer to the [CONTRIBUTING.md](../CONTRIBUTING.md) file for more information on how to contribute to this project.
- Loading branch information
Showing
16 changed files
with
837 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
name: Build and Push Kapinger Image | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- name: Checkout code | ||
uses: actions/checkout@v2 | ||
|
||
- name: Set outputs | ||
id: vars | ||
run: echo "sha_short=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT | ||
- name: Check outputs | ||
run: echo ${{ steps.vars.outputs.sha_short }} | ||
|
||
- name: Set up Docker Buildx | ||
uses: docker/setup-buildx-action@v1 | ||
|
||
# - name: Login to GitHub Container Registry | ||
# uses: docker/login-action@v1 | ||
# with: | ||
# registry: ghcr.io | ||
# username: ${{ github.repository_owner }} | ||
# password: ${{ secrets.GITHUB_TOKEN }} | ||
|
||
- name: Build Windows Kapinger Image | ||
uses: docker/build-push-action@v2 | ||
with: | ||
context: hack/tools/kapinger | ||
file: hack/tools/kapinger/Dockerfile.windows | ||
platforms: windows/amd64 | ||
push: false | ||
provenance: false | ||
tags: ghcr.io/${{ github.repository }}/kapinger:${{ steps.vars.outputs.sha_short }}-windows | ||
|
||
- name: Build Linux Kapinger Image | ||
uses: docker/build-push-action@v2 | ||
with: | ||
context: hack/tools/kapinger | ||
file: hack/tools/kapinger/Dockerfile | ||
platforms: linux/amd64 | ||
push: false | ||
provenance: false | ||
tags: ghcr.io/${{ github.repository }}/kapinger:${{ steps.vars.outputs.sha_short }}-linux | ||
|
||
- name: Build Linux Toolbox Image | ||
uses: docker/build-push-action@v2 | ||
with: | ||
context: hack/tools | ||
file: hack/tools/toolbox/Dockerfile | ||
platforms: linux/amd64 | ||
push: false | ||
provenance: false | ||
tags: ghcr.io/${{ github.repository }}/toolbox:${{ steps.vars.outputs.sha_short }}-linux | ||
# - name: Create and push manifest | ||
# id: docker_manifest | ||
# run: | | ||
# docker manifest create ghcr.io/${{ github.repository }}/kapinger:latest ghcr.io/${{ github.repository }}/kapinger:${{ steps.vars.outputs.sha_short }}-windows ghcr.io/${{ github.repository }}/kapinger:${{ steps.vars.outputs.sha_short }}-linux | ||
# docker manifest push ghcr.io/${{ github.repository }}/kapinger:latest |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
FROM mcr.microsoft.com/oss/go/microsoft/golang:1.22 AS builder | ||
|
||
WORKDIR /build | ||
ADD . . | ||
RUN go mod download | ||
|
||
RUN CGO_ENABLED=0 GOOS=linux go build -o kapinger . | ||
|
||
FROM scratch | ||
WORKDIR /build | ||
COPY --from=builder /build/kapinger . | ||
CMD ["./kapinger"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
FROM --platform=linux/amd64 mcr.microsoft.com/oss/go/microsoft/golang:1.22 AS builder | ||
|
||
WORKDIR /build | ||
COPY . . | ||
ENV GOOS=windows | ||
ENV GOARCH=amd64 | ||
|
||
RUN echo "building kapinger for OS: $GOOS, ARCH: $GOARCH" | ||
RUN go mod download | ||
RUN ls | ||
RUN CGO_ENABLED=0 go build -o kapinger.exe . | ||
|
||
FROM --platform=windows/amd64 mcr.microsoft.com/windows/nanoserver:ltsc2022 | ||
WORKDIR /build | ||
COPY --from=builder /build/kapinger.exe . | ||
CMD ["kapinger.exe"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,161 @@ | ||
package clients | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
"io" | ||
"log" | ||
"net/http" | ||
"os" | ||
"time" | ||
|
||
corev1 "k8s.io/api/core/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/util/wait" | ||
"k8s.io/client-go/kubernetes" | ||
) | ||
|
||
type TargetType string | ||
|
||
const ( | ||
Service TargetType = "service" | ||
Pod TargetType = "pod" | ||
|
||
envTargetType = "TARGET_TYPE" | ||
) | ||
|
||
type KapingerHTTPClient struct { | ||
client http.Client | ||
clientset *kubernetes.Clientset | ||
labelselector string | ||
ips []string | ||
port int | ||
targettype TargetType | ||
} | ||
|
||
func NewKapingerHTTPClient(clientset *kubernetes.Clientset, labelselector string, httpPort int) (*KapingerHTTPClient, error) { | ||
k := KapingerHTTPClient{ | ||
client: http.Client{ | ||
Transport: &http.Transport{ | ||
DisableKeepAlives: true, | ||
}, | ||
Timeout: 3 * time.Second, | ||
}, | ||
labelselector: labelselector, | ||
clientset: clientset, | ||
port: httpPort, | ||
} | ||
|
||
targettype := os.Getenv(envTargetType) | ||
if targettype != "" { | ||
k.targettype = TargetType(targettype) | ||
} else { | ||
k.targettype = Service | ||
} | ||
|
||
err := k.getIPS() | ||
if err != nil { | ||
return nil, fmt.Errorf("error getting IPs: %w", err) | ||
} | ||
|
||
return &k, nil | ||
} | ||
|
||
func (k *KapingerHTTPClient) MakeRequest() error { | ||
for _, ip := range k.ips { | ||
url := fmt.Sprintf("http://%s:%d", ip, k.port) | ||
req, err := http.NewRequest("GET", url, nil) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Set the "Connection" header to "close" | ||
req.Header.Set("Connection", "close") | ||
|
||
// Send the request | ||
resp, err := k.client.Do(req) | ||
if err != nil { | ||
return err | ||
} | ||
defer resp.Body.Close() | ||
|
||
body, err := io.ReadAll(resp.Body) | ||
if err != nil { | ||
log.Fatalf("Error reading response body from %s: %v", url, err) | ||
return err | ||
} | ||
log.Printf("Response from %s: %s\n", url, string(body)) | ||
} | ||
return nil | ||
} | ||
|
||
func (k *KapingerHTTPClient) getIPS() error { | ||
ips := []string{} | ||
|
||
switch k.targettype { | ||
case Service: | ||
services, err := k.clientset.CoreV1().Services(corev1.NamespaceAll).List(context.Background(), metav1.ListOptions{ | ||
LabelSelector: k.labelselector, | ||
}) | ||
if err != nil { | ||
return fmt.Errorf("error getting services: %w", err) | ||
} | ||
|
||
// Extract the Service cluster IP addresses | ||
|
||
for _, svc := range services.Items { | ||
ips = append(ips, svc.Spec.ClusterIP) | ||
} | ||
log.Println("using service IPs:", ips) | ||
|
||
case Pod: | ||
err := waitForPodsRunning(k.clientset, k.labelselector) | ||
if err != nil { | ||
return fmt.Errorf("error waiting for pods to be in Running state: %w", err) | ||
} | ||
|
||
// Get all pods in the cluster with label app=agnhost | ||
pods, err := k.clientset.CoreV1().Pods(corev1.NamespaceAll).List(context.Background(), metav1.ListOptions{ | ||
LabelSelector: k.labelselector, | ||
}) | ||
if err != nil { | ||
return fmt.Errorf("error getting pods: %w", err) | ||
} | ||
|
||
for _, pod := range pods.Items { | ||
ips = append(ips, pod.Status.PodIP) | ||
} | ||
|
||
log.Printf("using pod IPs: %v", ips) | ||
default: | ||
return fmt.Errorf("env TARGET_TYPE must be \"service\" or \"pod\"") | ||
} | ||
|
||
k.ips = ips | ||
return nil | ||
} | ||
|
||
// waitForPodsRunning waits for all pods with the specified label to be in the Running phase | ||
func waitForPodsRunning(clientset *kubernetes.Clientset, labelSelector string) error { | ||
return wait.ExponentialBackoff(wait.Backoff{ | ||
Duration: 5 * time.Second, | ||
Factor: 1.5, | ||
}, func() (bool, error) { | ||
pods, err := clientset.CoreV1().Pods(corev1.NamespaceAll).List(context.Background(), metav1.ListOptions{ | ||
LabelSelector: labelSelector, | ||
}) | ||
if err != nil { | ||
log.Printf("error getting pods: %v", err) | ||
return false, nil | ||
} | ||
|
||
for _, pod := range pods.Items { | ||
if pod.Status.Phase != corev1.PodRunning { | ||
log.Printf("waiting for pod %s to be in Running state (currently %s)", pod.Name, pod.Status.Phase) | ||
return false, nil | ||
} | ||
} | ||
|
||
return true, nil | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
module github.com/microsoft/retina/hack/tools/kapinger | ||
|
||
go 1.22.5 | ||
|
||
require ( | ||
k8s.io/api v0.30.2 | ||
k8s.io/apimachinery v0.30.2 | ||
k8s.io/client-go v0.30.2 | ||
) | ||
|
||
require ( | ||
github.com/davecgh/go-spew v1.1.1 // indirect | ||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect | ||
github.com/go-logr/logr v1.4.1 // indirect | ||
github.com/go-openapi/jsonpointer v0.19.6 // indirect | ||
github.com/go-openapi/jsonreference v0.20.2 // indirect | ||
github.com/go-openapi/swag v0.22.3 // indirect | ||
github.com/gogo/protobuf v1.3.2 // indirect | ||
github.com/golang/protobuf v1.5.4 // indirect | ||
github.com/google/gnostic-models v0.6.8 // indirect | ||
github.com/google/gofuzz v1.2.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/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 | ||
golang.org/x/net v0.23.0 // indirect | ||
golang.org/x/oauth2 v0.10.0 // indirect | ||
golang.org/x/sys v0.18.0 // indirect | ||
golang.org/x/term v0.18.0 // indirect | ||
golang.org/x/text v0.14.0 // indirect | ||
golang.org/x/time v0.3.0 // indirect | ||
google.golang.org/appengine v1.6.7 // indirect | ||
google.golang.org/protobuf v1.33.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/klog/v2 v2.120.1 // indirect | ||
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 // indirect | ||
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect | ||
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect | ||
sigs.k8s.io/structured-merge-diff/v4 v4.4.1 // indirect | ||
sigs.k8s.io/yaml v1.3.0 // indirect | ||
) |
Oops, something went wrong.