About traffic tapping

A tap server is a simple device that connects directly to your infrastructure and receives copies of actual traffic from your network so that this traffic can be further monitored, analyzed, or tested with.

Considerations

  • Traffic tapping can be applied to a gateway listener by using an HTTPListenerOption resource. As such, traffic tapping is applied to all routes that the gateway listener serves. Tapping traffic for a specific route is not currently supported.

  • You must write your own tap servers. You can find the tap server definitions in the tap-extension-examples repository. To receive tap traces, the tap server must implement the tap service protobuf definitions and be configured to receive data over the gRPC or HTTP protocol.

  • In the current implementation, the data plane buffers all trace data in memory before sending it to the tap server.

  • You cannot tap traffic to a local file.

Before you begin

  1. Follow the Get started guide to install Gloo Gateway, set up a gateway resource, and deploy the httpbin sample app.

  2. Get the external address of the gateway and save it in an environment variable.

Deploy a tap server

  1. Create the deployment, service, and upstream for the tap server in your cluster.

      kubectl apply -f- <<EOF
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      labels:
        app: sample-tap-server-http
      name: sample-tap-server-http
      namespace: gloo-system
    spec:
      selector:
        matchLabels:
          app: sample-tap-server-http
      replicas: 1
      template:
        metadata:
          labels:
            app: sample-tap-server-http
        spec:
          containers:
          - image: gcr.io/solo-test-236622/sample-tap-server-http:0.0.2
            name: sample-tap-server-http
            # args: ["-text='Hello World!'"]
            ports:
            - containerPort: 8080
              name: grpc
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: sample-tap-server-http
      namespace: gloo-system
      labels:
        service: sample-tap-server-http
    spec:
      ports:
      - port: 8080
        protocol: TCP
      selector:
        app: sample-tap-server-http
    ---
    apiVersion: gloo.solo.io/v1
    kind: Upstream
    metadata:
      name: sample-tap-server-http
      namespace: gloo-system
    spec:
      # useHttp2: true
      static:
        hosts:
        - addr: sample-tap-server-http
          port: 8080
    EOF
      
  2. Verify that the tap server is up and running.

      kubectl get pods -n gloo-system | grep tap
      

Set up traffic tapping

  1. Create an HTTPListenerOption resource to configure traffic tapping for the HTTP listener on the gateway. In the following example, you instruct Gloo Gateway to tap all incoming traffic on the gateway and to send it to the tap server that you previously configured by using the HTTP protocol.

      kubectl apply -f- <<EOF
    apiVersion: gateway.solo.io/v1
    kind: HttpListenerOption
    metadata:
      name: tapping
      namespace: gloo-system
    spec:
      targetRefs:
      - group: gateway.networking.k8s.io
        kind: Gateway
        name: http
      options:
        tap:
          sinks:
          - httpService:
              tapServer:
                name: sample-tap-server-http
                namespace: gloo-system
              timeout: '20s'
    EOF
      
  2. In a terminal window, tail the logs of the tap server.

      kubectl -n gloo-system logs deployments/sample-tap-server-http -f
      
  3. In another terminal window, send a request to the httpbin app.

  4. Go back to the logs of the tap server and verify that you can see the request to the httpbin app.

    Example output:

      2024/06/25 03:12:44 got a request on /
    2024/06/25 03:12:45 Message contents were: {
      "trace_data": {
        "Trace": {
          "HttpBufferedTrace": {
            "request": {
              "headers": [
                 {
                   "key": ":authority",
                   "value": "www.example.com:8080"
                 },
                 {
                   "key": ":path",
                   "value": "/status/200"
                 },
                 {
                   "key": ":method",
                   "value": "GET"
                 },
                 {
                   "key": ":scheme",
                   "value": "http"
                 },
                 {
                   "key": "user-agent",
                   "value": "curl/7.77.0"
                 },
                 {
                   "key": "accept",
                   "value": "*/*"
                 },
                 {
                   "key": "x-forwarded-proto",
                   "value": "http"
                 },
                 {
                   "key": "x-request-id",
                   "value": "87409d69-7c6d-4ce0-9d5a-a9050f960a60"
                 },
                 {
                   "key": "x-envoy-expected-rq-timeout-ms",
                   "value": "15000"
                 }
             ]
             },
             "response": {
             "headers": [
                 {
                   "key": ":status",
                   "value": "200"
                 },
                 {
                   "key": "access-control-allow-credentials",
                   "value": "true"
                 },
                 {
                   "key": "access-control-allow-origin",
                   "value": "*"
                 },
                 {
                   "key": "date",
                   "value": "Tue, 25 Jun 2024 03:12:44 GMT"
                 },
                 {
                   "key": "content-length",
                   "value": "0"
                 },
                 {
                   "key": "x-envoy-upstream-service-time",
                   "value": "2"
                 },
                 {
                   "key": "server",
                   "value": "envoy"
                 },
                 {
                   "key": "x-envoy-decorator-operation",
                   "value": "httpbin.httpbin.svc.cluster.local:8000/*"
                 }
             ]
         }
      

Clean up

You can optionally remove the resources that you created as part of this guide.

  kubectl delete deployment sample-tap-server-http -n gloo-system
kubectl delete service sample-tap-server-http -n gloo-system
kubectl delete httplisteneroption tapping -n gloo-system