Code and debug an application locally
Local Development Methods
Telepresence offers three powerful ways to develop your services locally:
Replace
- How it Works:
- Replaces an existing container within your Kubernetes cluster with a Traffic Agent.
- Reroutes traffic intended for the replaced container to your local workstation.
- Makes the remote environment of the replaced container available to the local workstation.
- Provides read-write access to the volumes mounted by replaced container.
- Impact:
- A Traffic Agent is injected into the pods of the targeted workload.
- The replaced container is removed from the pods of the targeted workload.
- The replaced container is restored when the replace operation ends.
- Use-cases:
- You're working with message queue consumers and must stop the remote container.
- You're working with remote containers configured without incoming traffic.
Intercept
- How it Works:
- Intercepts requests destined for a specific service port (or ports) and reroutes them to the local workstation.
- Makes the remote environment of the targeted container available to the local workstation.
- Provides read-write access to the volumes mounted by the targeted container.
- Impact:
- A Traffic Agent is injected into the pods of the targeted workload.
- Intercepted traffic is rerouted to the local workstation and will no longer reach the remote service.
- All containers keep on running.
- Use-cases:
- Your main focus is the service API rather than the cluster's pods and containers.
- You want your local service to only receive specific ingress traffic, while other traffic must be untouched.
- You want your remote container to continue processing other requests or background tasks.
Ingest
- How it Works:
- Makes the remote environment of the ingested container available to the local workstation.
- Provides read-only access to the volumes mounted by replaced container.
- Impact:
- A Traffic Agent is injected into the pods of the targeted workload.
- No traffic is rerouted and all containers keep on running.
- Use-cases:
- You want to keep the impact of your local development to a minimum.
- You have don't need traffic being routed from the cluster, and read-only access to the container's volumes is ok.
Prerequisites
Before you begin, you need to have Telepresence installed. This document uses the Kubernetes command-line tool, kubectl
in several examples. OpenShift users can substitute oc commands instead.
This guide assumes you have an application represented by a Kubernetes deployment and service accessible publicly by an ingress controller, and that you can run a copy of that application on your laptop.
Replace your Container
This approach offers the benefit of direct cluster connectivity from your workstation, simplifying debugging and modification of your application within its familiar environment. However, it requires root access to configure network telepresence, and remote mounts must be made relative to a specific mount point, which can add complexity.
-
Connect to your cluster with
telepresence connect
and try to curl to the Kubernetes API server. A 401 or 403 response code is expected and indicates that the service could be reached:Terminal$ curl -ik https://kubernetes.defaultHTTP/1.1 401 UnauthorizedCache-Control: no-cache, privateContent-Type: application/json...You now have access to your remote Kubernetes API server as if you were on the same network. You can now use any local tools to connect to any service in the cluster.
-
Enter
telepresence list
and make sure the workload (deployment in this case) you want to intercept is listed. For example:Terminal$ telepresence list...deolpoyment example-app: ready to engage (traffic-agent not yet installed)... -
Get the name of the container you want to replace (output truncated for brewity)
Terminal$ kubectl describe deploy example-appName: example-appNamespace: defaultCreationTimestamp: Tue, 14 Jan 2025 03:49:29 +0100Labels: app=example-appAnnotations: deployment.kubernetes.io/revision: 1Selector: app=example-appReplicas: 1 desired | 1 updated | 1 total | 0 available | 1 unavailableStrategyType: RollingUpdateMinReadySeconds: 0RollingUpdateStrategy: 25% max unavailable, 25% max surgePod Template:Labels: app=example-appContainers:echo-server:Image: ghcr.io/telepresencio/echo-serverPort: 8080/TCP -
Replace the container. Please note that the
--container echo-server
flag here is optional. It's only needed when the workload has more than one container:Terminal$ telepresence replace example-app --container echo-server --env-file /tmp/example-app.env --mount /tmp/example-app-mountsUsing Deployment example-appContainer name : echo-serverState : ACTIVEWorkload kind : DeploymentPort forwards : 10.1.4.106 -> 127.0.0.18080 -> 8080 TCPVolume Mount Point: /tmp/example-app-mountsYour workstation is now ready. You can run the application using the environment in the
/tmp/example-app.env
file and the mounts under/tmp/example-app-mounts
. The application can listen tolocalhost:8080
to receive traffic intended for the replaced container. On the cluster side of things, a Traffic Agent container has replaced theecho-server
.Telepresence assumes that you want all declared container ports to be mapped to their corresponding port on
localhost
. You can change this with the--port
flag. For example,--port 1080:8080
will map the replaced containers port number8080
tolocalhost:1080
. The--port
can also be used when the container is known to listen to ports that are not declared in the manifest. -
Query the cluster in which you replaced your application and verify your local instance being invoked. All the traffic previously routed to your Kubernetes Service is now routed to your local environment
You can now:
- Make changes on the fly and see them reflected when interacting with your Kubernetes environment.
- Query services only exposed in your cluster's network.
- Set breakpoints in your IDE to investigate bugs.
- You end the replace operation with the command
telepresence leave example-app --container echo-server
Ingest your Container
In some situations, you want to work and debug the code locally, and you want it to be able to access other services in the cluster,
but you don't wish to interfere with the targeted workload. This is where the telepresence ingest
command comes into play. Just
like replace
command, it will make the environment and mounted containers of the targeted container available locally, but it will
not replace the container nor will it intercept any of its traffic.
This example assumes that you have the example-app
deployment.
-
Connect and run and start an ingest from
example-app
:Terminal$ telepresence connectLaunching Telepresence User DaemonLaunching Telepresence Root DaemonConnected to context xxx, namespace default (https://<some url>)$ telepresence ingest example-app --container echo-server --env-file /tmp/example-app.env --mount /tmp/example-app-mountsUsing Deployment example-appContainer name : echo-serverWorkload kind : DeploymentVolume Mount Point: /tmp/example-app-mounts -
Start your local application using the environment variables retrieved and the volumes that were mounted in the previous step.
You can now:
- Code and debug your local app while it interacts with other services in your cluster.
- Query services only exposed in your cluster's network.
- Set breakpoints in your IDE to investigate bugs.
Intercept your application
You can use the telepresence intercept
command when you want to intercept the traffic for a specific service and route that
traffic to your workstation. The intercept
is less intrusive than the replace
, because it allows the original receiver of the
intercepted traffic to continue to run and deal with tasks that aren't directly related to that traffic.
-
Connect to your cluster with
telepresence connect
. -
Intercept all traffic going to the application's http port in your cluster and redirect to port 8080 on your workstation.
Terminal$ telepresence intercept example-app --port 8080:http --env-file ~/example-app-intercept.env --mount /tmp/example-app-mountsUsing Deployment example-appinterceptedIntercept name: example-appState : ACTIVEWorkload kind : DeploymentDestination : 127.0.0.1:8080Intercepting : all TCP connections-
For
--port
: specify the port the local instance of your application is running on, and optionally the remote port that you want to intercept. Telepresence will select the remote port automatically when there's only one service port available to access the workload. You must specify the port to intercept when the workload exposes multiple ports. You can do this by specifying the port you want to intercept after a colon in the--port
argument (like in the example), and/or by specifying the service you want to intercept using the--service
flag. -
For
--env-file
: specify a file path for Telepresence to write the environment variables that are set for the targeted container.
-
-
Start your local application using the environment variables retrieved and the volumes that were mounted in the previous step.
You can now:
- Make changes on the fly and see them reflected when interacting with your Kubernetes environment.
- Query services only exposed in your cluster's network.
- Set breakpoints in your IDE to investigate bugs.
Running everything using Docker
This approach eliminates the need for root access and confines the Telepresence network interface and remote mounts to a container. Additionally, it allows for precise replication of the target container's volume mounts, using identical mount points. However, this method will require docker to get cluster connectivity, and the containerized environment can present challenges in terms of toolchain integration, debugging, and the overall development workflow.
-
Connect to your cluster with
telepresence connect --docker
. This starts the Telepresence daemon in a docker container and ensures that this container has access to the cluster network. -
Use
telepresence curl
to access the Kubernetes API server from a container. A 401 or 403 response code is expected and indicates that the service could be reached. Thetelepresence curl
command used will execute a standardcurl
command from a container that shares the network created by theconnect
call:Terminal$ telepresence curl -ik https://kubernetes.defaultHTTP/1.1 401 UnauthorizedCache-Control: no-cache, privateContent-Type: application/json...You now have access to your remote Kubernetes API server as if you were on the same network.
-
Enter
telepresence list
and make sure the workload you want to engage is listed. For example:Terminal$ telepresence list...deployment example-app: ready to engage (traffic-agent not yet installed)... -
Use
replace
,inject
, orintercept
to engage the container in combination with the--docker-run
flag. Example usingtelepresence replace
Terminal$ telepresence replace example-app --container echo-server --docker-run -- <your local container>Using Deployment example-appinterceptedIntercept name: example-appState : ACTIVEWorkload kind : DeploymentDestination : 127.0.0.1:8080Intercepting : all TCP connections<output from your local container>
You can now:
- Make changes on the fly and see them reflected when interacting with your Kubernetes environment; although depending on how your local container is configured, this might require that it is rebuilt.
- Query services only exposed in your cluster's network using
telepresence curl
. - Set breakpoints in a Remote Debug configuration in your IDE to investigate bugs.