1"use strict";(globalThis.webpackChunktelepresence=globalThis.webpackChunktelepresence||[]).push([[15500],{35259(e,n,t){t.r(n),t.d(n,{assets:()=>o,contentTitle:()=>c,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>l});const a=JSON.parse('{"id":"reference/attachments/cli","title":"Configure workload attachments using CLI","description":"Specifying a namespace for an attachment","source":"@site/versioned_docs/version-2.30/reference/attachments/cli.md","sourceDirName":"reference/attachments","slug":"/reference/attachments/cli","permalink":"/docs/2.30/reference/attachments/cli","draft":false,"unlisted":false,"editUrl":"https://github.com/telepresenceio/telepresence/tree/release/v2/docs/reference/attachments/cli.md","tags":[],"version":"2.30","frontMatter":{"title":"Configure workload attachments using CLI"},"sidebar":"defaultSidebar","previous":{"title":"Environment variables","permalink":"/docs/2.30/reference/environment"},"next":{"title":"Traffic Agent Sidecar","permalink":"/docs/2.30/reference/attachments/sidecar"}}');var r=t(74848),i=t(28453);const s={title:"Configure workload attachments using CLI"},c="Configuring workload attachments using CLI",o={},l=[{value:"Specifying a namespace for an attachment",id:"specifying-a-namespace-for-an-attachment",level:2},{value:"Importing environment variables",id:"importing-environment-variables",level:2},{value:"Creating an intercept when multiple services match your workload",id:"creating-an-intercept-when-multiple-services-match-your-workload",level:2},{value:"Intercepting multiple ports",id:"intercepting-multiple-ports",level:2},{value:"Port-forwarding an intercepted container's sidecars",id:"port-forwarding-an-intercepted-containers-sidecars",level:2},{value:"Intercepting headless services",id:"intercepting-headless-services",level:2},{value:"Intercepting without a service",id:"intercepting-without-a-service",level:2},{value:"Specifying the attachment traffic target",id:"specifying-the-attachment-traffic-target",level:2},{value:"Replacing a running workload",id:"replacing-a-running-workload",level:2}];function d(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",header:"header",p:"p",pre:"pre",...(0,i.R)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.header,{children:(0,r.jsx)(n.h1,{id:"configuring-workload-attachments-using-cli",children:"Configuring workload attachments using CLI"})}),"\n",(0,r.jsx)(n.h2,{id:"specifying-a-namespace-for-an-attachment",children:"Specifying a namespace for an attachment"}),"\n",(0,r.jsxs)(n.p,{children:["By default, an attachment targets the namespace selected by ",(0,r.jsx)(n.code,{children:"telepresence connect --namespace"}),".\nThe ",(0,r.jsx)(n.code,{children:"intercept"}),", ",(0,r.jsx)(n.code,{children:"wiretap"}),", and ",(0,r.jsx)(n.code,{children:"replace"})," commands also accept ",(0,r.jsx)(n.code,{children:"--namespace"})," when the workload\nto attach to is in a different mapped namespace. ",(0,r.jsx)(n.code,{children:"ingest"})," continues to use the connected namespace."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"telepresence connect --namespace myns\ntelepresence replace/ingest/intercept/wiretap hello\n"})}),"\n",(0,r.jsxs)(n.p,{children:["To attach to a workload in another mapped namespace without reconnecting, pass ",(0,r.jsx)(n.code,{children:"--namespace"}),"\nto the attachment command:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",children:"telepresence connect --namespace alpha --mapped-namespaces alpha,beta\ntelepresence intercept beta-local --workload hello --namespace beta --http-header x-user=susan --port 8080:80\n"})}),"\n",(0,r.jsxs)(n.p,{children:["Single-label DNS names continue to resolve in the connected namespace. When an attachment\ntargets another namespace, use a namespace-qualified name such as ",(0,r.jsx)(n.code,{children:"hello.beta"}),"."]}),"\n",(0,r.jsx)(n.h2,{id:"importing-environment-variables",children:"Importing environment variables"}),"\n",(0,r.jsxs)(n.p,{children:["Telepresence can import the environment variables from the pod that is\nattached to, see ",(0,r.jsx)(n.a,{href:"/docs/2.30/reference/environment",children:"this doc"})," for more details."]}),"\n",(0,r.jsx)(n.h2,{id:"creating-an-intercept-when-multiple-services-match-your-workload",children:"Creating an intercept when multiple services match your workload"}),"\n",(0,r.jsxs)(n.p,{children:["Oftentimes, there's a 1-to-1 relationship between a service and a\nworkload, so telepresence is able to auto-detect which service it\nshould intercept based on the workload you are trying to intercept.\nBut if you use something like\n",(0,r.jsx)(n.a,{href:"https://argoproj.github.io/argo-rollouts/",children:"Argo Rollouts"}),", there may be\ntwo services (that use the same labels) to manage traffic between a\ncanary and a stable service."]}
1),"\n",(0,r.jsxs)(n.p,{children:["Fortunately, if you know which service you want to use when\nintercepting a workload, you can use the ",(0,r.jsx)(n.code,{children:"--service"})," flag. So in the\naforementioned example, if you wanted to use the ",(0,r.jsx)(n.code,{children:"echo-stable"})," service\nwhen intercepting your workload, your command would look like this:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-console",children:"$ telepresence intercept echo-rollout-<generatedHash> --port <local TCP port> --service echo-stable\nUsing ReplicaSet echo-rollout-<generatedHash>\nintercepted\n Intercept name : echo-rollout-<generatedHash>\n State : ACTIVE\n Workload kind : ReplicaSet\n Destination : 127.0.0.1:3000\n Volume Mount Point: /var/folders/cp/2r22shfd50d9ymgrw14fd23r0000gp/T/telfs-921196036\n Intercepting : all TCP connections\n"})}),"\n",(0,r.jsx)(n.h2,{id:"intercepting-multiple-ports",children:"Intercepting multiple ports"}),"\n",(0,r.jsxs)(n.p,{children:["It is possible to intercept more than one service and/or service port that are using the same workload. You do this\nby repeating the ",(0,r.jsx)(n.code,{children:"--port"})," flag."]}),"\n",(0,r.jsxs)(n.p,{children:["Let's assume that we have a service ",(0,r.jsx)(n.code,{children:"multi-echo"})," with the two ports ",(0,r.jsx)(n.code,{children:"http"})," and ",(0,r.jsx)(n.code,{children:"grpc"}),". They are both\ntargeting the same ",(0,r.jsx)(n.code,{children:"multi-echo"})," deployment."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-console",children:"$ telepresence intercept multi-echo-http --workload multi-echo --port 8080:http --port 8443:grpc\nUsing Deployment multi-echo\nintercepted\n Intercept name : multi-echo-http\n State : ACTIVE\n Workload kind : Deployment\n Intercepting : 10.1.54.120 -> 127.0.0.1\n 8080 -> 8080 TCP\n 8443 -> 8443 TCP\n Volume Mount Point : /tmp/telfs-893700837\n"})}),"\n",(0,r.jsx)(n.h2,{id:"port-forwarding-an-intercepted-containers-sidecars",children:"Port-forwarding an intercepted container's sidecars"}),"\n",(0,r.jsxs)(n.p,{children:["Sidecars are containers that sit in the same pod as an application\ncontainer; they usually provide auxiliary functionality to an\napplication, and can usually be reached at\n",(0,r.jsx)(n.code,{children:"localhost:${SIDECAR_PORT}"}),". For example, a common use case for a\nsidecar is to proxy requests to a database, your application would\nconnect to ",(0,r.jsx)(n.code,{children:"localhost:${SIDECAR_PORT}"}),", and the sidecar would then\nconnect to the database, perhaps augmenting the connection with TLS or\nauthentication."]}),"\n",(0,r.jsxs)(n.p,{children:["When intercepting a container that uses sidecars, you might want those\nsidecars' ports to be available to your local application at\n",(0,r.jsx)(n.code,{children:"localhost:${SIDECAR_PORT}"}),", exactly as they would be if running\nin-cluster. Telepresence's ",(0,r.jsx)(n.code,{children:"--to-pod ${PORT}"})," flag implements this\nbehavior, adding port-forwards for the port given."]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-console",children:"$ telepresence intercept <base name of intercept> --port=<local TCP port>:<servicePortIdentifier> --to-pod=<sidecarPort>\nUsing Deployment <name of deployment>\nintercepted\n Intercept name : <full name of intercept>\n State : ACTIVE\n Workload kind : Deployment\n Destination : 127.0.0.1:<local TCP port>\n Service Port Identifier: <servicePortIdentifier>\n Intercepting : all TCP connections\n"})}),"\n",(0,r.jsxs)(n.p,{children:["If there are multiple ports that you need forwarded, simply repeat the\nflag (",(0,r.jsx)(n.code,{children:"--to-pod=<sidecarPort0> --to-pod=<sidecarPort1>"}),")."]}),"\n",(0,r.jsx)(n.h2,{id:"intercepting-headless-services",children:"Intercepting headless services"}),"\n",(0,r.jsxs)(n.p,{children:["Kubernetes supports creating ",(0,r.jsx)(n.a,{href:"https://kubernetes.io/docs/concepts/services-networking/service/#headless-services",children:"services without a ClusterIP"}),",\nwhich, when they have a pod selector, serve to provide a DNS re
1cord that will directly point to the service's backing pods.\nTelepresence supports intercepting these ",(0,r.jsx)(n.code,{children:"headless"})," services as it would a regular service with a ClusterIP.\nSo, for example, if you have the following service:"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-yaml",children:"---\napiVersion: v1\nkind: Service\nmetadata:\n name: my-headless\nspec:\n type: ClusterIP\n clusterIP: None\n selector:\n service: my-headless\n ports:\n - port: 8080\n targetPort: 8080\n---\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n name: my-headless\n labels:\n service: my-headless\nspec:\n replicas: 1\n serviceName: my-headless\n selector:\n matchLabels:\n service: my-headless\n template:\n metadata:\n labels:\n service: my-headless\n spec:\n containers:\n - name: my-headless\n image: ghcr.io/telepresenceio/echo-server:latest\n ports:\n - containerPort: 8080\n resources: {}\n"})}),"\n",(0,r.jsx)(n.p,{children:"You can intercept it like any other:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-console",children:"$ telepresence intercept my-headless --port 8080\nUsing StatefulSet my-headless\nintercepted\n Intercept name : my-headless\n State : ACTIVE\n Workload kind : StatefulSet\n Destination : 127.0.0.1:8080\n Volume Mount Point: /var/folders/j8/kzkn41mx2wsd_ny9hrgd66fc0000gp/T/telfs-524189712\n Intercepting : all TCP connections\n"})}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["This utilizes an ",(0,r.jsx)(n.code,{children:"initContainer"})," that requires ",(0,r.jsx)(n.code,{children:"NET_ADMIN"})," capabilities.\nIf your cluster administrator has disabled them, you will be unable to use numeric ports with the agent injector."]})}),"\n",(0,r.jsx)(n.h2,{id:"intercepting-without-a-service",children:"Intercepting without a service"}),"\n",(0,r.jsx)(n.p,{children:"You can intercept a workload without a service by adding an annotation that informs Telepresence what container\nports that are eligable for intercepts. Telepresence will then inject a traffic-agent when the workload is\ndeployed, and you will be able to intercept the given ports as if they were service ports. The annotation is:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-yaml",children:" annotations:\n telepresence.io/inject-container-ports: http\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The annotation value is a comma separated list of port identifiers consisting of either the name or the port number of a container\nport, optionally suffixed with ",(0,r.jsx)(n.code,{children:"/TCP"})," or ",(0,r.jsx)(n.code,{children:"/UDP"})]}),"\n",(0,r.jsx)(n.p,{children:"An example deployment with the annotation:"}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-yaml",children:"apiVersion: apps/v1\nkind: Deployment\nmetadata:\n name: echo-no-svc\n labels:\n app: echo-no-svc\nspec:\n replicas: 1\n selector:\n matchLabels:\n app: echo-no-svc\n template:\n metadata:\n labels:\n app: echo-no-svc\n annotations:\n telepresence.io/inject-container-ports: http\n spec:\n automountServiceAccountToken: false\n containers:\n - name: echo-server\n image: ghcr.io/telepresenceio/echo-server:latest\n ports:\n - name: http\n containerPort: 8080\n"})}),"\n",(0,r.jsxs)(n.p,{children:["The workload shows up in ",(0,r.jsx)(n.code,{children:"telepresence list"}),' and can be intercepted like any other. Since no\nservice exists, there is no DNS entry either; the output of the intercept command contains an\n"Address" field with the pod address that reaches the intercepted workload:']}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-console",children:"$ telepresence intercept echo-no-svc\nUsing Deployment echo-no-svc\n Intercept name : echo-no-svc\n State : ACTIVE\n Workload kind : Deployment\n Destination : 127.0.0.1:8080\n Volume Mount Point: /tmp/telfs-3306285526\n Intercepting : all TCP connections\n Address : 10.244.0.13:8080\n"})}),"\n",(0,r.jsx)(n.admonition,{type:"info",children:(0,r.jsxs)(n.p,{children:["A service-less intercept utilizes an ",(0,r.jsx)(n.code,{children:"initContainer"})," that requires ",(0,r.jsx)(n.code,{children:"NET_ADMIN"})," capabilities.\nIf your cluster administrator has disabled them, you will only be able to intercept services using symbolic target ports."]})}),"\n",(0,r.jsx)(n.h2,{id:"specifying-the-attachment-traffic-target",children:"Specifying the attachment traffic target"}),"\n",(0,r.jsxs)(n.p,{children:["By default, it's assumed that your local app is reachable on ",(0,r.jsx)(n.code,{children:"127.0.0.1"})," or on the IP of the local container that is\nrunning that app, and intercepted traffic will be sent to that address at the port given by ",(0,r.jsx)(n.code,{children:"--port"}),". If you wish to\nchange this behavior and send traffic to a different address, you can use the ",(0,r.jsx)(n.code,{children:"--address"})," parameter to\n",(0,r.jsx)(n.code,{children:"telepresence intercept/replace/wiretap"}),'. Say your machine is configured to respond to HTTP requests for an intercept\non a container named "stoic_galois". You would run this as:']}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-console",children:"$ telepresence intercept my-service --address stoic-galois --port 8080\nUsing Deployment my-service\n Intercept name: my-service\n State : ACTIVE\n Workload kind : Deployment\n Intercepting : 127.0.0.1 -> stoic-galois\n 8080 -> 8080 TCP\n"})}),"\n",(0,r.jsx)(n.h2,{id:"replacing-a-running-workload",children:"Replacing a running workload"}),"\n",(0,r.jsxs)(n.p,{children:["By default, your application container continues to run while Telepresence intercepts its traffic. This can cause issues\nfor applications with ongoing background activities, such as consuming from a message queue. To address this, use the\n",(0,r.jsx)(n.code,{children:"telepresence replace"})," command instead of ",(0,r.jsx)(n.code,{children:"telepresence intercept"}),": the Traffic Agent then replaces the application\ncontainer within the pod, and the original container is automatically restored once the attachment ends. See\n",(0,r.jsx)(n.a,{href:"/docs/2.30/concepts/attachments",children:"Attachments"})," for how the modes compare."]}),"\n",(0,r.jsx)(n.admonition,{type:"note",children:(0,r.jsx)(n.p,{children:"Sidecars will not be stopped. Only the targeted container will be removed from the pod."})}),"\n",(0,r.jsx)(n.admonition,{type:"note",children:(0,r.jsxs)(n.p,{children:["The ",(0,r.jsx)(n.code,{children:"--replace"})," flag of ",(0,r.jsx)(n.code,{children:"telepresence intercept"})," is deprecated; use the ",(0,r.jsx)(n.code,{children:"telepresence replace"})," command."]})})]})}function h(e={}){const{wrapper:n}={...(0,i.R)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(d,{...e})}):d(e)}},28453(e,n,t){t.d(n,{R:()=>s,x:()=>c});var a=t(96540);const r={},i=a.createContext(r);function s(e){const n=a.useContext(i);return a.useMemo(function(){return"function"==typeof e?e(n):{...n,...e}},[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:s(e.components),a.createElement(i.Provider,{value:n},e.children)}}}]);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.