New API Development Platform, join Blackbird Beta and try it now Learn More

Back to blog
TELEPRESENCE

Unlocking the Power of Telepresence’s Intercept Specification

Kay James
January 26, 2024 | 7 min read

Personal intercepts, multiple connections, multiple ports, and more!


TLDR: The Telepresence Intercept Specification now allows for multiple connection definitions that specify which one to use for each intercepted workload. Multiple namespaces can be intercepted simultaneously, and/or colliding ports on localhost can be routed using separate networks.

Many users are now familiar with Telepresence, the Kubernetes development and debugging tool that ‘puts your local workstation into the cluster’ so you can work faster, more efficiently, and with more predictable results. But, in our experience, not every dev uses Telepresence to its full capacity. With some powerful untapped capabilities, Telepresence goes far beyond mere connectivity to your cluster and lets you fully interact with your deployed services using Telepresence intercepts and your personalized go-to Intercept Specification.

What is a Telepresence Intercept?

As background, Telepresence Intercepts are an extremely useful feature and one every Kubernetes developer should have in their toolkit. Running an intercept lets you direct traffic on your deployed Kubernetes service to your local machine where, using your preferred IDE, you can employ all your local testing and debugging tools to quickly attack problems and iterate on solutions.

How does it work?

When intercepting a service, the Telepresence Traffic Manager ensures that a Traffic Agent has been injected into the intercepted workload. The injection is triggered by a Kubernetes Mutating Webhook. The Traffic Agent is responsible for redirecting intercepted traffic to the developer's workstation and for propagating the intercepted container's environment and volume mounts.

There are two types of intercepts available, Global and Personal intercepts. A global intercept targets all TCP and/or UDP traffic sent to the intercepted service and sends all of that traffic down to the developer's workstation. This means that a global intercept will affect all users of the intercepted service. Obviously, this is a blocker when multiple devs need to work on a service simultaneously.

The Advantage of Personal Intercepts

Telepresence Enterprise, the licensed solution, gives the option of using Personal intercepts. A personal intercept targets only specific HTTP requests while allowing other HTTP requests through to the regular service. The selection is based on HTTP headers or paths, which act as a ‘tag’ for a given developer, ensuring separation for multiple devs working on the same service.

Personal intercepts add a lot of power and selectively to your Telepresence workflow, and they can be configured either from the CLI directly or using the Intercept Specification. If you’re just trying a quick intercept, the CLI is the way to go. But what if you often use a more complex intercept for a repeated task or if the intercept requires multiple specs to achieve the needed behavior? That’s where the Intercept Specification comes in handy to manage those details.

Intercept Specification

Introduced in v2.11, the Intercept Spec lets you template a file that defines how an intercept should work. It’s where you can create a go-to, standard configuration to execute pre and post-tasks, start an intercept, and start your local application to handle the intercepted traffic. It is now possible to leverage the intercept specification to spin up your environment without extra tools.

The Intercept Spec’s schema provides a wide range of options such as connection properties, process handlers, prerequisites to be set up first, remote workloads to be intercepted, and more. You can also use environment variables to provide the header value needed for personal intercepts. Let’s look at a sample schema:

kubectl apply -f - <<EOF
---
apiVersion: getambassador.io/v1alpha4
kind: InterceptSpecification
metadata:
name: echo-server-spec
namespace: my-crd-namespace
spec:
connection:
context: "my-context"
workloads:
- name: echo-easy
namespace: default
intercepts:
- headers:
- name: test-{{ .Telepresence.Username }}
value: "{{ .Telepresence.Username }}"
localPort: 9090
port: proxied
handler: echo-easy
service: echo-easy
previewURL:
enable: false
handlers:
- name: echo-easy
environment:
- name: PORT
value: "9090"
docker:
image: jmalloc/echo-server
EOF

With this flexible format, it's easy to declare connections, intercept headers, handlers, port variables, and other specs to dial in the desired intercept behavior. A handler, for example, can be a Docker container or an application running natively - just provide the correct specs.

New - Multiple Connection support

Released in v2.18, an exciting and much-anticipated feature of the Intercept Spec is the ability to use it to define multiple connections. Actually, multiple connections using Docker have been available for some time, but now multiple connections can be declared in an Intercept Specification, and the intercept handlers therein can declare which connection they use. And it is now possible to have simultaneous intercepts spanning more than one cluster. Let’s look at an example:

connections:
- name: a
namespace: {{env “NAMESPACE_A”}}
hostname: alpha
- name: b
namespace: {{env “NAMESPACE_B”}}
hostname: bravo
workloads:
- name: a/echo
intercepts:
- handler: echo
localPort: 8088
port: 80
name: a
- name: b/echo
intercepts:
- handler: echo
localPort: 8089
port: 80
name: b
handlers:
- name: echo
docker:
compose:
Services:
- name: echo-a
behavior: interceptHandler
connection: a
- name: echo-b
behavior: interceptHandler
connection: b

Currently, when you connect Telepresence to a cluster, it connects your host (workstation) to a namespace in that cluster. This lets you resolve a service using single label names but, on the downside, it also confines you to that namespace. You can’t connect to another namespace because if you do, the single-label name resolution gets confused and stops working.

The solution to being able to intercept things in more than one namespace simultaneously relies on Docker containers. Instead of connecting your host to a namespace, the user will now connect a docker container to a namespace. That container will have a network that permits the resolution of single-label names. The host (that runs this docker container) keeps its own network unaffected because it’s not connected to the cluster.

Under the hood, we’ve enhanced Telepresence’s ability to create and use multiple containerized daemons, each with its own isolated VIF (Virtual Network Interface) when running an intercept specification. Similarly, it enables simultaneous intercepts of containers that use the same port number (while retaining the container configuration for the container that handles the intercept locally).

The new feature also plays nicely with ispec’s Docker Compose integration, which means that services in one Docker Compose spec can act as intercept handlers for services that live in different namespaces in the cluster.

The intercept specification also supports template expansion in all properties except names that reference other objects within the specification and makes all functions from the Masterminds/sprig package available. As you can see, the Intercept Specification provides a plethora of options, so reading through the detailed documentation will help ensure you’re getting the most out of this advanced feature.

Try out Telepresence today