<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Peter ONeill</title>
    <description>The latest articles on DEV Community by Peter ONeill (@peteroneilljr).</description>
    <link>https://dev.to/peteroneilljr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F410424%2Fe22eb52d-4702-43b9-a771-f7edff3fbe6c.png</url>
      <title>DEV Community: Peter ONeill</title>
      <link>https://dev.to/peteroneilljr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/peteroneilljr"/>
    <language>en</language>
    <item>
      <title>Debugging Go Microservices in Kubernetes with VScode</title>
      <dc:creator>Peter ONeill</dc:creator>
      <pubDate>Fri, 09 Apr 2021 14:04:58 +0000</pubDate>
      <link>https://dev.to/ambassadorlabs/debugging-go-microservices-in-kubernetes-with-vscode-kli</link>
      <guid>https://dev.to/ambassadorlabs/debugging-go-microservices-in-kubernetes-with-vscode-kli</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Tutorial: Learn to debug Go microservices locally while testing against dependencies in a remote Kubernetes cluster&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F11668%2F1%2AkFNAnhDkPcDDqPAXVWyafg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F11668%2F1%2AkFNAnhDkPcDDqPAXVWyafg.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Many organizations adopt cloud native development practices with the dream of shipping features faster. Although the technologies and architectures may change when moving to the cloud, the fact that we all still add the occasional bug to our code remains constant. The snag is that many of your existing local debugging tools and practices can’t be used when everything is running in a container or on the cloud.&lt;/p&gt;

&lt;p&gt;Easy and efficient debugging is essential to being a productive engineer, but when you have a large number of microservices running in Kubernetes the approach you take to debugging has to change. For one, you typically can’t run all of your dependent services on your local machine. This then opens up the challenges of remote debugging (and the associated fiddling with debug modes and exposing ports correctly). However, there is another way. And the &lt;a href="https://www.getambassador.io/products/telepresence" rel="noopener noreferrer"&gt;CNCF Telepresence tool&lt;/a&gt; enables this path.&lt;/p&gt;

&lt;p&gt;This article walks you through using &lt;a href="https://www.getambassador.io/products/telepresence/" rel="noopener noreferrer"&gt;Telepresence&lt;/a&gt; to seamlessly connect your local development machine to a remote Kubernetes cluster, allowing you to use your favorite debugging tools with all of your microservices. Giving you the ability to comfortably debug your remote apps with your existing skills.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Difficulty with Debugging Applications Running in Kubernetes
&lt;/h2&gt;

&lt;p&gt;Splitting your application into microservices introduces a number of challenges. Particularly with debugging. Splitting an application into several, if not dozens, of microservices creates a complex dependency tree that becomes nearly impossible to replicate in staging.&lt;/p&gt;

&lt;p&gt;Sure, you can use unit tests with tools like &lt;a href="https://github.com/golang/mock" rel="noopener noreferrer"&gt;GoMock&lt;/a&gt; and &lt;a href="https://github.com/prashantv/gostub" rel="noopener noreferrer"&gt;GoStub&lt;/a&gt; to simulate external dependencies or introduce synthetic data into the mix, but it still leaves you unsure if it will work with data from your actual services.&lt;/p&gt;

&lt;p&gt;And after you have deployed your service into your cluster, running a remote debugging session can be tricky to get right, due to the complicated configuration of ports and protocols that need to be set via your Kubernetes service YAML. You often lose the ability to use your favorite debugging tools and strategies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Deploy a Sample Microservice Application
&lt;/h2&gt;

&lt;p&gt;In this article, we’re going to be working with the sample Edgey Corp application written in Go. There are detailed instructions for deploying this application in my &lt;a href="https://blog.getambassador.io/go-kubernetes-rapidly-developing-golang-microservices-bfe36cfb5893" rel="noopener noreferrer"&gt;previous blog post&lt;/a&gt;. Or just apply the YAML from the URL to your Kubernetes cluster, clone the repository, and jump right into the action.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Apply the manifest for the Edgey Corp app to your K8s cluster&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;https://raw.githubusercontent.com/datawire/edgey-corp-go/main/k8s-config/edgey-corp-web-app-no-mapping.yaml]&lt;span class="o"&gt;(&lt;/span&gt;https://raw.githubusercontent.com/datawire/edgey-corp-go/main/k8s-config/edgey-corp-web-app-no-mapping.yaml&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Git clone the code for the Edgey Corp app to your machine&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="o"&gt;[&lt;/span&gt;https://github.com/datawire/edgey-corp-go.git]&lt;span class="o"&gt;(&lt;/span&gt;https://github.com/datawire/edgey-corp-go.git&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now that we have the Edgey Corp app running in our Kubernetes cluster, and we have the code on our local machine let’s pop it open with VSCode.&lt;/p&gt;

&lt;p&gt;Let’s check the application is running successfully. Run a kubectl get pods to see the pods are up and running for the 3 microservices. verylargedatastore, verylargejavaservice and dataprocessingservice.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl get pods
NAME READY STATUS RESTARTS AGE
verylargedatastore-cd998dfc6-k5bkw 1/1 Running 0 19s
verylargejavaservice-77748f79d6-dx4kj 1/1 Running 0 20s
dataprocessingservice-f5b644d95-s98hp 1/1 Running 0 20s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;With the sample application up and running we can configure VScode to start debugging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Configure VScode and Delve
&lt;/h2&gt;

&lt;p&gt;VScode is a great all-purpose IDE with countless extensions to get you up and running quickly. We are going to use the Go extension made by the Google team with the Go debugger tool called Delve. Here are links to each tool:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://code.visualstudio.com/Download" rel="noopener noreferrer"&gt;Visual Studio Code&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.visualstudio.com/items?itemName=golang.Go" rel="noopener noreferrer"&gt;Go for Visual Studio Code Extension&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/go-delve/delve/tree/master/Documentation/installation" rel="noopener noreferrer"&gt;Delve the Go debugger&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You’ll want to make sure that Delve is both installed to your local system and connected to VScode through the Go extension.&lt;/p&gt;

&lt;h3&gt;
  
  
  Install Delve to your local system
&lt;/h3&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go install github.com/go-delve/delve/cmd/dlv@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  Connect Delve to VScode
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open VScode now&lt;/li&gt;
&lt;li&gt;Access the command palette with (command+shift+p)&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Select Go: install/update tools&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2Ama0Vk4VyFLwuJATL" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2Ama0Vk4VyFLwuJATL"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Check the box for DLV and any other options you might find useful&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Click Ok&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AYSYFL3PxFcXN0Oif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AYSYFL3PxFcXN0Oif"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Run your Go code in debugging mode
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open the project directory for the Edgy Corp Go App in VScode&lt;/li&gt;
&lt;li&gt;Open up the file dataprocessingservice/main.go&lt;/li&gt;
&lt;li&gt;Click the debug icon on the right side.&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Lastly, click “Run and Debug”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AQpM5RjnbTP234HbO" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AQpM5RjnbTP234HbO"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You should now see the debug console starting to log output.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;API server listening at: 127.0.0.1:48808
Welcome to the DataProcessingGoService!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Let’s check that it’s working by navigating to &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;localhost:3000&lt;/a&gt; in your browser. You can also navigate to &lt;a href="http://localhost:3000/color" rel="noopener noreferrer"&gt;localhost:3000/color&lt;/a&gt; to see how the Go application response to the color endpoint.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2420%2F0%2AThpJxNqjmgEFwBWk" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2420%2F0%2AThpJxNqjmgEFwBWk"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Intercept Your Service with Telepresence
&lt;/h2&gt;

&lt;p&gt;So debugging one microservice in isolation is fine, but it still leaves us assuming what is going to happen when it is connected to the rest of the microservice in our application. Let’s introduce Telepresence here to debug our local Go microservice as part of the larger application.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install telepresence CLI&lt;/p&gt;

&lt;p&gt;macOS&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo curl -fL [https://app.getambassador.io/download/tel2/darwin/amd64/latest/telepresence](https://app.getambassador.io/download/tel2/darwin/amd64/latest/telepresence) -o /usr/local/bin/telepresence
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Linux&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo curl -fL [https://app.getambassador.io/download/tel2/linux/amd64/latest/telepresence](https://app.getambassador.io/download/tel2/linux/amd64/latest/telepresence) -o /usr/local/bin/telepresence
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Make the binary executable&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo chmod a+x /usr/local/bin/telepresence
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Connect your local machine to your Kubernetes cluster.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ telepresence connect
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Test the connection by cURL-ling our front-end service via its Kubernetes service name.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ curl [http://verylargejavaservice.default:8080/color](http://verylargejavaservice.default:8080/color)
“green”
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Notice two things here:&lt;/p&gt;

&lt;p&gt;A) You are able to refer to the remote Service directly via its internal cluster name as if your development machine is inside the cluster&lt;/p&gt;

&lt;p&gt;B) The color returned by the remote DataProcessingService is “green”, versus the local result you saw above of “blue”&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Let’s take our connecting to the cluster a step further now by initiating an intercept from our remote dataprocessingservice to our local debug session running on &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;http://localhost:3000&lt;/a&gt;. This will send any traffic destined for the remote service down to our debugger&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;telepresence intercept dataprocessingservice &lt;span class="nt"&gt;--port&lt;/span&gt; 3000
Launching Telepresence Daemon v2.1.2 &lt;span class="o"&gt;(&lt;/span&gt;api v3&lt;span class="o"&gt;)&lt;/span&gt;
Connecting to traffic manager…
Connected to context peteroneilljr-office-hours &lt;span class="o"&gt;([&lt;/span&gt;https://34.67.161.22]&lt;span class="o"&gt;(&lt;/span&gt;https://34.67.161.22&lt;span class="o"&gt;))&lt;/span&gt;
Using deployment dataprocessingservice
intercepted
Intercept name: dataprocessingservice
State : ACTIVE
Destination : 127.0.0.1:3000
Intercepting : all TCP connections
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Let’s try to cURL our front-end service once again. This time we should see our local debugger logging the interaction between the front-end service and our local dataprocessingservice.&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="o"&gt;[&lt;/span&gt;http://verylargejavaservice.default:8080/]&lt;span class="o"&gt;(&lt;/span&gt;http://verylargejavaservice.default:8080/&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;Awesome! Now that our local debugger is hooked up to the remote cluster we should be all set to start debugging!&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 4: Step Through Your Breakpoints
&lt;/h2&gt;

&lt;p&gt;Let’s set a breakpoint on the getColor function. Hover over just to the left of the line number and click on the red dot. Once it’s set, visit &lt;a href="http://localhost:3000" rel="noopener noreferrer"&gt;localhost:3000&lt;/a&gt; in your browser, VScode should pop to the foreground. Click the play button to close the request and the webpage should finish loading.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AqAb8oiaF11niS3BX" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AqAb8oiaF11niS3BX"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now your IDE is processing traffic directly from the cluster, let’s open up our sample application in a web browser:&lt;/p&gt;

&lt;p&gt;&lt;a href="http://verylargejavaservice.default:8080" rel="noopener noreferrer"&gt;http://verylargejavaservice.default:8080&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;VScode will pop open on the breakpoint again. This time let’s click the step button (the one with the clockwise rotating arrow) until the breakpoint reaches the fmt.Println and you see the c: “green” in the variables window. If you try to adjust the variable directly in the IDE variables pane you will receive the following error.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Failed to set variable — literal string can not be allocated because function calls are not allowed without using ‘call’
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;blockquote&gt;
&lt;p&gt;More details about the bug here: &lt;a href="https://github.com/golang/vscode-go/issues/1173" rel="noopener noreferrer"&gt;https://github.com/golang/vscode-go/issues/1173&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To work around this issue we can adjust the variable in the debug terminal with the command call c = “orange”&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AfzzykE46ruEa51u0" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AfzzykE46ruEa51u0"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now let’s end the breakpoint and send the info back to the web browser. Click the play button in the top command bar.&lt;/p&gt;

&lt;p&gt;Awesome! You should see the verylargejavaservice loading with the orange background colors. We’ve successfully made a request to our front-end service running in our remote cluster, where Telepresence intercepted the traffic sending it through our local debugging session, where we inspected and updated the data to send back the orange color variable.&lt;/p&gt;

&lt;p&gt;Introducing Telepresence into the development flow gives us a bridge from our local development environment to our remote Kubernetes cluster. Allowing us to test and debug traffic from the remote cluster as if it was on our local machine, in other words, giving us feedback from our local service to see how it will perform when running in the remote cluster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5: (Bonus) Clone your Pod’s environment variables to your debug session
&lt;/h2&gt;

&lt;p&gt;In some scenarios, a service can inherit environment variables from the cluster or configuration. In cases like this, cloning the remote deployments environment variables to our local service will be necessary to ensure closer parity between the two environments. To do this we will leverage Telepresence to copy the environment variables from the remote service and save them to a .env file. Then we will tell VScode to add these variables to the debug environment.&lt;/p&gt;

&lt;p&gt;To let VScode know that we want to include an environment file, we need to create a launch configuration specifying where the file is going to be.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Stop your last debugging session if it is still running.&lt;/li&gt;
&lt;li&gt;Click the Gear Icon in the top right corner to open the launch.json file.&lt;/li&gt;
&lt;li&gt;From here click the Add Configuration button.&lt;/li&gt;
&lt;li&gt;Select Go: Launch File from the dropdown menu.&lt;/li&gt;
&lt;li&gt;Add the line &lt;code&gt;"envFile": "${workspaceFolder}/go-debug.env"&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AUVJa0F7EJnPuaWPS" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AUVJa0F7EJnPuaWPS"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Launch with env file"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"go"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"launch"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"mode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"debug"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"program"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${file}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
     &lt;/span&gt;&lt;span class="nl"&gt;"envFile"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"${workspaceFolder}/go-debug.env"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now that VScode knows where the file is going to be located let’s generate the file with Telepresence. This time run the intercept from the terminal window within VScode to ensure the file is created in the project directory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;telepresence intercept dataprocessingservice &lt;span class="nt"&gt;--port&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3000 &lt;span class="nt"&gt;--env-file&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;go-debug.env
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AoqM3wW4uiFddwjM6" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2AoqM3wW4uiFddwjM6"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, start the debug session. Click the debug icon on the right side and click the launch session button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AoxEFynFBcBO9nQZy" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F2000%2F0%2AoxEFynFBcBO9nQZy"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now your local process is running with all the same variables as if it was running in the remote cluster.&lt;/p&gt;

&lt;p&gt;You can also &lt;a href="https://www.getambassador.io/docs/latest/telepresence/reference/volume/" rel="noopener noreferrer"&gt;locally access volumes mounted&lt;/a&gt; into your remote Services. This is useful if you are storing configuration, tokens, or other state required for the proper execution of the service. We’ll cover this in more detail in a future tutorial.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn More About Telepresence
&lt;/h2&gt;

&lt;p&gt;Today, we’ve learned how to use Telepresence to easily debug a Go microservice running in Kubernetes. Now, instead of trying to mock out dependencies or fiddle around with remote debugging, we can iterate quickly with an instant feedback loop when locally debugging using our favorite IDE and tools.&lt;/p&gt;

&lt;p&gt;If you want to learn more about Telepresence, check out the following resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.getambassador.io/docs/latest/telepresence/quick-start/qs-go/" rel="noopener noreferrer"&gt;Read the docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Watch the &lt;a href="https://www.youtube.com/watch?v=W_a3aErN3NU" rel="noopener noreferrer"&gt;demo video&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Read more about &lt;a href="https://www.getambassador.io/docs/latest/telepresence/howtos/intercepts/#intercepts" rel="noopener noreferrer"&gt;Intercepts&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Learn about &lt;a href="https://www.getambassador.io/docs/pre-release/telepresence/howtos/preview-urls/#collaboration-with-preview-urls" rel="noopener noreferrer"&gt;Preview URLs&lt;/a&gt; for easy collaboration with teammates&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://a8r.io/Slack" rel="noopener noreferrer"&gt;Join our Slack channel&lt;/a&gt; to connect with the Telepresence community&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>vscode</category>
      <category>telepresence</category>
      <category>go</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>Go &amp; Kubernetes: Rapidly Developing Golang Microservices</title>
      <dc:creator>Peter ONeill</dc:creator>
      <pubDate>Wed, 03 Mar 2021 19:06:55 +0000</pubDate>
      <link>https://dev.to/ambassadorlabs/go-kubernetes-rapidly-developing-golang-microservices-3nlf</link>
      <guid>https://dev.to/ambassadorlabs/go-kubernetes-rapidly-developing-golang-microservices-3nlf</guid>
      <description>&lt;h3&gt;
  
  
  Build a cloud development environment with Telepresence &amp;amp; Golang
&lt;/h3&gt;

&lt;p&gt;Kubernetes is a container orchestration platform that enables its users to deploy and scale their microservice applications at any scale: from one service to thousands of services. Unleashing the power of Kubernetes is often more complicated than it may initially seem — the learning curve for application developers is particularly steep. Knowing what to do is just half the battle, then you have to choose the best tools to do the job. So how do Go developers create a development workflow on Kubernetes that is fast and effective?&lt;/p&gt;

&lt;p&gt;Application developers face two unique challenges when trying to create productive development workflows on Kubernetes.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Most development workflows are optimized for local development, and Kubernetes applications are designed to be native to the cloud.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;As Kubernetes applications evolve into complex microservice architectures, the development environments also become more complex as every microservice adds additional dependencies. These services quickly start to need more resources than are available in your typical local development environment.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In this tutorial, we’ll set up a development environment for Kubernetes and make a change to a Golang microservice. Normally to develop locally, we’d have to wait for a container build, push to registry and deploy to see the effect of our code change. Instead, we’ll use &lt;a href="http://www.getambassador.io/products/telepresence/" rel="noopener noreferrer"&gt;Telepresence&lt;/a&gt; to see the results of our change instantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Deploy a Sample Microservices Application
&lt;/h2&gt;

&lt;p&gt;For our example, we’ll make code changes to a Go service running between a resource-intensive Java service and a large datastore. We’ll start by deploying a sample microservice application consisting of 3 services:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;VeryLargeJavaService&lt;/strong&gt;: A memory-intensive service written in Java that generates the front-end graphics and web pages for our application&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;DataProcessingService&lt;/strong&gt;: A Golang service that manages requests for information between the two services.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;VeryLargeDataStore&lt;/strong&gt;: A large datastore service that contains the sample data for our Edgey Corp store.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Note: We’ve called these VeryLarge services to emphasize the fact that your local environment may not have enough CPU and RAM, or you may just not want to pay for all that extra overhead for every developer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2A7J_48_5o8juPX5E6" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fcdn-images-1.medium.com%2Fmax%2F3200%2F0%2A7J_48_5o8juPX5E6"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In this architecture diagram, you’ll notice that requests from users are routed through an ingress controller to our services. For simplicity’s sake, we’ll skip the step of &lt;a href="https://www.getambassador.io/docs/latest/topics/install/install-ambassador-oss/#kubernetes-yaml" rel="noopener noreferrer"&gt;deploying an ingress controller&lt;/a&gt; in this tutorial. If you’re ready to use Telepresence in your own setup and need a simple way to set up an ingress controller, we recommend checking out the &lt;a href="https://www.getambassador.io/products/edge-stack/" rel="noopener noreferrer"&gt;Ambassador Edge Stack&lt;/a&gt; which can be easily configured with the &lt;a href="https://app.getambassador.io/initializer" rel="noopener noreferrer"&gt;K8s Initializer&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s deploy the sample application to your Kubernetes cluster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    kubectl apply &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;https://raw.githubusercontent.com/datawire/edgey-corp-go/main/k8s-config/edgey-corp-web-app-no-mapping.yaml]&lt;span class="o"&gt;(&lt;/span&gt;https://raw.githubusercontent.com/datawire/edgey-corp-go/main/k8s-config/edgey-corp-web-app-no-mapping.yaml&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2: Set up your local Go development environment
&lt;/h2&gt;

&lt;p&gt;We’ll need a local development environment so that we can edit the &lt;code&gt;DataProcessingService&lt;/code&gt; service. As you can see in the architecture diagram above, the &lt;code&gt;DataProcessingService&lt;/code&gt; is dependent on both the &lt;code&gt;VeryLargeJavaService&lt;/code&gt; and the &lt;code&gt;VeryLargeDataStore&lt;/code&gt;, so in order to make a change to this service, we’ll have to interact with these other services as well. Let’s get started!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Clone the repository for this application from GitHub.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    git clone &lt;span class="o"&gt;[&lt;/span&gt;https://github.com/datawire/edgey-corp-go.git]&lt;span class="o"&gt;(&lt;/span&gt;https://github.com/datawire/edgey-corp-go.git&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Change directories into the DataProcessingService
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="nb"&gt;cd &lt;/span&gt;edgey-corp-go/DataProcessingService
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Start the Go server:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    go build main.go &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; ./main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;See your service running!
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    10:23:41 app | Welcome to the DataProcessingGoService!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;In another terminal window, curl localhost:3000/color to see that the service is returning blue.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="nv"&gt;$ &lt;/span&gt;curl localhost:3000/color

    “blue”
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3: Rapid Development with Telepresence
&lt;/h2&gt;

&lt;p&gt;Instead of waiting for a container image to build, pushed to a repository, and deployed to our Kubernetes cluster we are going to use Telepresence, an open source Cloud Native Computing Foundation project. Telepresence creates a bidirectional network connection between your local development and the Kubernetes cluster to enable &lt;a href="https://www.getambassador.io/use-case/local-kubernetes-development/" rel="noopener noreferrer"&gt;fast, efficient Kubernetes development&lt;/a&gt;.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Download Telepresence (~60MB):
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="c"&gt;# Mac OS X&lt;/span&gt;
    &lt;span class="nb"&gt;sudo &lt;/span&gt;curl &lt;span class="nt"&gt;-fL&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;https://app.getambassador.io/download/tel2/darwin/amd64/latest/telepresence]&lt;span class="o"&gt;(&lt;/span&gt;https://app.getambassador.io/download/tel2/darwin/amd64/latest/telepresence&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; /usr/local/bin/telepresence

    &lt;span class="c"&gt;#Linux&lt;/span&gt;
    &lt;span class="nb"&gt;sudo &lt;/span&gt;curl &lt;span class="nt"&gt;-fL&lt;/span&gt; https://app.getambassador.io/download/tel2/linux/amd64/latest/telepresence &lt;span class="nt"&gt;-o&lt;/span&gt; /usr/local/bin/telepresence
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Make the binary executable
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="nv"&gt;$ &lt;/span&gt;&lt;span class="nb"&gt;sudo chmod &lt;/span&gt;a+x /usr/local/bin/telepresence
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Test Telepresence by connecting to the remote cluster
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="nv"&gt;$ &lt;/span&gt;telepresence connect
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Send a request to the Kubernetes API server:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    &lt;span class="nv"&gt;$ &lt;/span&gt;curl &lt;span class="nt"&gt;-ik&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt;https://kubernetes.default.svc.cluster.local]&lt;span class="o"&gt;(&lt;/span&gt;https://kubernetes.default.svc.cluster.local&lt;span class="o"&gt;)&lt;/span&gt;

    HTTP/1.1 401 Unauthorized
    Cache-Control: no-cache, private
    Content-Type: application/json
    Www-Authenticate: Basic &lt;span class="nv"&gt;realm&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"kubernetes-master"&lt;/span&gt;
    Date: Tue, 09 Feb 2021 23:21:51 GMT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Great! You’ve successfully configured Telepresence. Right now, Telepresence is intercepting the request you’re making to the Kubernetes API server, and routing over its direct connection to the cluster instead of over the Internet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Intercept Your Golang Service
&lt;/h2&gt;

&lt;p&gt;An intercept is a routing rule for Telepresence. We can create an intercept to route traffic intended for the &lt;code&gt;DataProcessingService&lt;/code&gt; in the cluster and instead route all of the traffic to the &lt;em&gt;local&lt;/em&gt; version of the &lt;code&gt;DataProcessingService&lt;/code&gt; running on port 3000.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create the intercept
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;    telepresence intercept dataprocessingservice — port 3000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Access the application directly with Telepresence. Visit &lt;a href="http://verylargejavaservice:8080" rel="noopener noreferrer"&gt;http://verylargejavaservice:8080&lt;/a&gt;. Again, Telepresence is intercepting requests from your browser and routing them directly to the Kubernetes cluster.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Now, we’ll make a code change. Open edgey-corp-go/DataProcessingService/main.go and change the value of the color variable from blue to orange. Save the file, stop the previous server instance and start it again with go build main.go &amp;amp;&amp;amp; ./main.&lt;/li&gt;
&lt;li&gt;Reload the page in your browser and see how the color has changed from blue to orange!&lt;/li&gt;
&lt;/ol&gt;


&lt;/li&gt;

&lt;/ol&gt;

&lt;p&gt;That’s it! With Telepresence we saw how quickly we can go from editing a local service to seeing how these changes will look when deployed with the larger application. When you compare it to our original process of building and deploying a container after every change, it’s very easy to see how much time you can save especially as we make more complex changes or run even larger services.&lt;/p&gt;

&lt;h2&gt;
  
  
  Learn More about Telepresence
&lt;/h2&gt;

&lt;p&gt;Today, we’ve learned how to use Telepresence to rapidly iterate on a Golang microservice running in Kubernetes. Now, instead of waiting for slow local development processes, we can iterate quickly with an instant feedback loop and a productive cloud native development environment.&lt;/p&gt;

&lt;p&gt;If you want to learn more about Telepresence, check out the following resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.getambassador.io/docs/latest/telepresence/quick-start/qs-go/" rel="noopener noreferrer"&gt;Read the docs&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Watch the &lt;a href="https://www.youtube.com/watch?v=W_a3aErN3NU" rel="noopener noreferrer"&gt;demo video&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Read more about &lt;a href="https://www.getambassador.io/docs/latest/telepresence/howtos/intercepts/#intercepts" rel="noopener noreferrer"&gt;Intercepts&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Learn about &lt;a href="https://www.getambassador.io/docs/pre-release/telepresence/howtos/preview-urls/#collaboration-with-preview-urls" rel="noopener noreferrer"&gt;Preview URLs&lt;/a&gt; for easy collaboration with teammates&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://d6e.co/slack" rel="noopener noreferrer"&gt;Join our Slack channel&lt;/a&gt; to connect with the Telepresence community&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In our next tutorial, we’ll use Telepresence to set up a local Kubernetes development environment and then use Delve to set breakpoints and debug a broken service. To be notified when more tutorials are available, make sure to &lt;a href="http://www.getambassador.io" rel="noopener noreferrer"&gt;check out our website&lt;/a&gt; or &lt;a href="http://www.twitter.com/ambassadorlabs" rel="noopener noreferrer"&gt;follow us on Twitter&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>go</category>
      <category>kubernetes</category>
      <category>microservices</category>
      <category>telepresence</category>
    </item>
    <item>
      <title>Cloud Development Environments: Using Skaffold and Telepresence on Kubernetes for fast dev loops</title>
      <dc:creator>Peter ONeill</dc:creator>
      <pubDate>Thu, 11 Feb 2021 15:59:04 +0000</pubDate>
      <link>https://dev.to/peteroneilljr/cloud-development-environments-using-skaffold-and-telepresence-on-kubernetes-for-fast-dev-loops-3038</link>
      <guid>https://dev.to/peteroneilljr/cloud-development-environments-using-skaffold-and-telepresence-on-kubernetes-for-fast-dev-loops-3038</guid>
      <description>&lt;h2&gt;
  
  
  Build and deploy microservices with Skaffold; Test against remote dependencies with Telepresence
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://skaffold.dev/"&gt;Skaffold&lt;/a&gt; is an open source project created by Google. It provides a development framework for Kubernetes based applications. This framework creates a fast, repeatable, and simple local Kubernetes workflow. Put simply, this means that it handles all the hard bits of managing a cloud native local development environment, such as building images and deploying to Kubernetes. With Skaffold handling the hard bits, you save time with every iteration you make in development.&lt;/p&gt;

&lt;p&gt;Telepresence is an open source tool created by Ambassador Labs. Telepresence makes Kubernetes developers super productive by letting them code as if their laptop is in their Kubernetes cluster. This way you can query cluster resources and experiment rapidly with other services in realtime.&lt;/p&gt;

&lt;p&gt;Together, Skaffold and Telepresence give developers a supercharged development workflow for Kubernetes, where Skaffold handles building and deploying your local service and Telepresence allows you to test it against services in your remote cluster.&lt;/p&gt;

&lt;p&gt;In this tutorial, we’ll use Skaffold to build and deploy our local environment. Then, we’ll spin up Telepresence to do some iterations while projecting the local service we are building to a remote cluster. Using Telepresence as part of Ambassador Cloud gives us some additional benefits, like being able to share preview URLs with teammates, so they can view the services running on your local machine as if they were in production. We’ll talk more about this in future blog posts.&lt;/p&gt;

&lt;h2&gt;
  
  
  CI/CD and the Inner Dev Loop
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--XPYl6rKV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3200/0%2AyFtztj6omeqIuee4" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--XPYl6rKV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3200/0%2AyFtztj6omeqIuee4" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Continuous integration and continuous deployment — commonly referred to as CI/CD — is the de-facto method used to develop and deploy cloud native applications. On the right side of the diagram above, we have the continuous deployment workflow or outer loop. On the left-side of the diagram we have the development workflow, typically called the inner-dev-loop. This inner-dev-loop is where you write and test code before committing it to a version control system. Because you’re in the midst of the creative process of writing and testing code, you want this feedback loop to be as fast as possible. The faster this loop performs the faster you can refactor your code and test again.&lt;/p&gt;

&lt;p&gt;The desire to make the loop faster is why tools like Skaffold and Telepresence, which are designed to save you time in this inner-dev-loop, are a great addition to Cloud Native workflows. With Skaffold managing your local deployments and watching your project directory as you make changes, you get a snappy feedback loop where your code appears in your local-dev-environment every time you save a file.&lt;/p&gt;

&lt;p&gt;To make your inner-dev-loop even faster, Skaffold can be paired with Telepresence. With Skaffold managing your local service, and Telepresence safely intercepting traffic from your production cluster, you are able to test your code with nearly instantaneous feedback. On top of that, your code has been tested against real traffic saving you time later from debugging minor differences between dev and prod.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Skaffold dev workflow
&lt;/h2&gt;

&lt;p&gt;When using Skaffold to help manage your local environment you will find yourself in the Skaffold dev mode quite a bit. At the core of Skaffold dev there is a skaffold.yaml file. Sitting at the root directory of your project, this file contains all the info Skaffold needs to turn your code into containers and those containers into an application on your development cluster. Skaffold doesn’t do this alone though, Skaffold takes advantage of the popular tools you probably already use. Such as Dockerfiles or Webpacks to help build the containers, then Kubectl and Helm to deploy them. Because there are so many tooling options for Cloud Native applications, Skaffold has been designed to be highly modular to allow you to mix-and-match with tools you already use.&lt;/p&gt;

&lt;p&gt;You can think of the Skaffold dev mode as a fully automated CI/CD pipeline for your development cluster. It takes all the tools you already use to deploy your application and does it automatically every time you make a change. This pipeline can get complex if needed, but at its primary levels it has 2 main stages: build and deploy. Let’s take a look at how this looks with the ‘react-reload’ example provided in the &lt;a href="https://github.com/GoogleContainerTools/skaffold/tree/master/examples/react-reload"&gt;Skaffold repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build
&lt;/h2&gt;

&lt;p&gt;For those familiar with Docker, the default behaviour is to build a docker image using the provided Dockerfile. While this build stage can use other tools like JIB or Webpacks, the primary goal is to get your code packaged into a container so it is ready to be deployed.&lt;/p&gt;

&lt;p&gt;From the example’s Dockerfile we see that it is creating a Node container with the port 8080 exposed. No special instructions are added for Skaffold, it is just a simple Dockerfile.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FROM node:12.16.0-alpine3.10
WORKDIR /app
EXPOSE 8080
CMD [“npm”, “run”, “dev”]
COPY package* ./
# examples don’t use package-lock.json to minimize updates
RUN npm install — no-package-lock
COPY . .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;One of the most annoying things about managing containers is when you need to rebuild your images every time a file changes, even if the file doesn’t affect the state of the container. This is one area Skaffold really shines, because Skaffold dev manages the deployment, it can update files used by the container without having to rebuild the image.&lt;/p&gt;

&lt;p&gt;However, if you make a change that does affect the container directly, Skaffold will pick up on the change and rebuild the necessary images. Then these newly created images are handed off to the deploy stage, where they are seamlessly integrated into your local dev environment. This seamless integration gives you a very fast turnaround time from code change to code tested.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deploy
&lt;/h2&gt;

&lt;p&gt;Now on to the Kubernetes bits! Skaffold is such a powerful tool because it allows Developers to focus on writing code and managing kubernetes. Switching between writing code and deploying it to your cluster causes an unnecessary context switch from Dev to Ops. In the deploy stage of the pipeline, Skaffold acts like your personal operations engineer. With all the code neatly packaged up from the build stage, Skaffold creates the deployments and services in your development cluster.&lt;/p&gt;

&lt;p&gt;Still working with the ‘react-reload’ example, the deployment and service configurations for the sample application are defined in the manifest files located in k8s folder. Here we can see the react-reload image created in the build stage and service exposing port 8080. Skaffold also supports Helm and Kustomize manifest files.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: v1
kind: Service
metadata:
  name: node
spec:
  ports:
  - port: 8080
  type: LoadBalancer
  selector:
    app: node
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: node
spec:
  selector:
    matchLabels:
      app: node
  template:
    metadata:
      labels:
        app: node
    spec:
      containers:
      - name: react
        image: react-reload
        ports:
        - containerPort: 8080
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;With these manifest files and some of the info in the skaffold.yaml file, Skaffold understands how to apply this configuration. With the default behaviour Skaffold will use kubectl as it is currently configured on your machine. Now that the sample application is up and running, Skaffold switches into watcher mode. Keeping the deployment and services up to date with the code in the project directory automagically. So now, as a developer you can go from writing code to testing code deployed to kubernetes without putting on your hat to be an operations engineer, saving you time and the mental tax from these context switches.&lt;/p&gt;

&lt;h2&gt;
  
  
  React-Reload with Skaffold Dev for fast build and deploy
&lt;/h2&gt;

&lt;p&gt;Now to put all the pieces together and practice using Skaffold dev mode. I’ll walk you through deploying the ‘react-reload’ example to a local cluster running in Docker. Let’s start off by going through the prerequisites.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Docker&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Docker hub account (Necessary for Skaffold + Telepresence Demo)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Kubectl and Kubernetes cluster (running in docker)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Skaffold&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Check requirements
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;docker version&lt;/code&gt; to check that docker is running&lt;/p&gt;

&lt;p&gt;$ docker version&lt;br&gt;
Client: Docker Engine — Community&lt;br&gt;
Cloud integration: 1.0.4&lt;br&gt;
===trimmed for brevity===&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Checked that you are logged into docker&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;$ docker login&lt;br&gt;
Authenticating with existing credentials…&lt;br&gt;
Login Succeeded&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;kubectl get nodes&lt;/code&gt; should return docker-desktop&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;$ kubectl get nodes&lt;br&gt;
NAME STATUS ROLES AGE VERSION&lt;br&gt;
docker-desktop Ready master 2d7h v1.19.3&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;code&gt;skaffold version&lt;/code&gt; to check that the Skaffold binary is available&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;$ skaffold version&lt;br&gt;
v1.19.0&lt;/p&gt;


&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Example Steps
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;1. Clone Repo&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you haven’t already done so, clone the react reload example locally and cd into the read-reload directory.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ git clone git@github.com:GoogleContainerTools/skaffold.git
$ cd skaffold/examples/react-reload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;2. Start Skaffold Dev&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Run &lt;code&gt;skaffold dev — default-repo &amp;lt;repository-name&amp;gt;&lt;/code&gt; in the project directory to kick things off. Remember to replace the repository name with your personal repository.&lt;/p&gt;

&lt;p&gt;*Note: We are using an external repository here. When using a local cluster &lt;code&gt;skaffold dev&lt;/code&gt; works without an external repository, but we will be using this repository in a later section of the tutorial.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ skaffold dev — default-repo peteroneilljr
Listing files to watch…
- react-reload
Generating tags…
- react-reload -&amp;gt; peteroneilljr/react-reload:v1.17.1–57-g95092addf-dirty
Checking cache…
- react-reload: Not found. Building
Found [docker-desktop] context, using local docker daemon.
Building [react-reload]…
Sending build context to Docker daemon 11.26kB
Step 1/7 : FROM node:12.16.0-alpine3.10
== trimmed for brevity ===
Step 7/7 : COPY . .
— -&amp;gt; 11fd5f0fcad4
Successfully built 11fd5f0fcad4
Successfully tagged peteroneilljr/react-reload:v1.17.1–57-
95092addf-dirty
Tags used in deployment:
- react-reload -&amp;gt; peteroneilljr/react-reload:11fd5f0fcad4559dbc176cabd46b91a01a82d3dd2b6604f7702f338e6275015e
Starting deploy…
- service/node created
- deployment.apps/node created
Waiting for deployments to stabilize…
- deployment/node is ready.
Deployments stabilized in 2.229471962s
Press Ctrl+C to exit
Watching for changes…
[react]
[react] &amp;gt; react-reload@1.0.0 dev /app
[react] &amp;gt; webpack-dev-server — mode development — hot
[react]
[react] ℹ ｢wds｣: Project is running at [http://0.0.0.0:8080/](http://0.0.0.0:8080/)
[react] ℹ ｢wds｣: webpack output is served from /
== trimmed for brevity ===
[react] [./node_modules/webpack/buildin/module.js] (webpack)/buildin/module.js 497 bytes {0} [built]
[react] ℹ ｢wdm｣: Compiled successfully.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;3. Review output&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;From the output we can see a few of things have happened:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Docker has successfully built the container image&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;1 service was created in the cluster&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;1 deployment was created in the cluster&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Lastly, you will see the logs report the deployment has stabilized and then starts logging the stdout from the container. React is running the container and watching for changes, as changes are detected they will be reported here.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;4. Find project URL&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So let’s navigate to our sample app and check it out. Near the beginning of the react output you will see that react reports where the application is running. This should match up with the port defined in Dockerfile and manifest files.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Project is running at [&amp;lt;http://0.0.0.0:8080/&amp;gt;](&amp;lt;http://0.0.0.0:8080/&amp;gt;)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;5. Open Sample App&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Let’s navigate this to this address in your local web browser. If all went well you should see &lt;code&gt;Hello world!&lt;/code&gt; in large text in the middle of the window.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;6. Modify HelloWorld.js&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now let’s modify some of the configuration files and watch how Skaffold handles it. Using a text editor or IDE open the file: &lt;code&gt;app/src/components/HelloWorld.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Let’s make it a bit more interesting and have it say &lt;code&gt;Hello From Skaffold!&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from ‘react’;
import ‘../styles/HelloWorld.css’;
export const HelloWorld = () =&amp;gt; (
&amp;lt;div&amp;gt;
&amp;lt;h1&amp;gt;Hello From Skaffold!&amp;lt;/h1&amp;gt;
&amp;lt;/div&amp;gt;
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;7. Watch file sync in action&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Remember the entire project folder is being watched by Skaffold. So the second you save the changes to this file, Skaffold will kick off the update process. Looking back at your web browser you should see that the changes should already be displayed. And from the log output we see that Skaffold reports 1 file has been synced with the running container.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Syncing 1 files for react-reload:5212d19febc7b8a0e5b623473c502a339b7222034e64024a3c3c45e3ab0e3281
Watching for changes…
[react] ℹ ｢wdm｣: Hash: f8313748da8d23ab6dc6
[react] Version: webpack 4.46.0
[react] Time: 120ms
[react] Built at: 01/14/2021 9:05:52 PM
[react] Asset Size Chunks Chunk Names
[react] fa444694c556f0f903da.hot-update.json 46 bytes [emitted] [immutable] [hmr]
[react] index.html 295 bytes [emitted]
[react] main.fa444694c556f0f903da.hot-update.js 1.39 KiB main [emitted] [immutable] [hmr] main
[react] main.js 1.36 MiB main [emitted] main
[react] Entrypoint main = main.js main.fa444694c556f0f903da.hot-update.js
[react] [./src/components/HelloWorld.js] 210 bytes {main} [built]
[react] + 52 hidden modules
[react] Child html-webpack-plugin for “index.html”:
[react] 1 asset
[react] Entrypoint undefined = index.html
[react] 4 modules
[react] ℹ ｢wdm｣: Compiled successfully.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;8. Update dependencies&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now let’s make a change that will cause a bit of a bigger splash; let’s modify the package.json file in the app folder. We can pretend that we need an older version of React. Downgrade the react dependency from &lt;code&gt;16.13.1&lt;/code&gt; to &lt;code&gt;16.13.0&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;“dependencies”: {
    “react”: “¹⁶.13.0”,
    “react-dom”: “¹⁶.13.1”
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;9. Watch automatic redeploy&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Unlike the change earlier which did a hot-swap the file javascript file, Skaffold detected the change in dependencies and kicked off a new build for the container image. But we can see docker was able to rebuild the first 4 layers from the cache before copying in the modified package.json file and building the new layer with npm install. Then Docker hands off this newly made image back off to Skaffold where it updates the running deployment.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Generating tags…
- react-reload -&amp;gt; react-reload:v1.17.1–57-g95092addf-dirty
Checking cache…
- react-reload: Not found. Building
Found [docker-desktop] context, using local docker daemon.
Building [react-reload]…
Sending build context to Docker daemon 11.26kB
Step 1/7 : FROM node:12.16.0-alpine3.10
— -&amp;gt; 48ae9395145d
==trimmed for brevity===
— -&amp;gt; ff4ad02e16bb
Step 7/7 : COPY . .
— -&amp;gt; ae2a7b322a8f
Successfully built ae2a7b322a8f
==trimmed for brevity===
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;10. Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;You should now see your local application running with the updated package dependencies. This alone is a huge time saver, thinking about how often you need to rebuild an image due to a small file change, not to mention redeploying after that. But now let’s look at how we can make this inner-dev-loop even faster; with the addition of Telepresence, we can project our local dev environment into an external cluster.&lt;/p&gt;

&lt;h2&gt;
  
  
  Skaffold dev and Telepresence for fast, realistic testing in dev
&lt;/h2&gt;

&lt;p&gt;Why introduce Telepresence when we already have a perfectly working development environment? Each of these tools saves time for a very specific piece of the inner-dev-loop, this is what makes them a dynamic duo. And to reiterate the inner-dev-loop is to write code, deploy code, test code and repeat.&lt;/p&gt;

&lt;p&gt;Skaffold excels at deploying code to your local development environment, saving you time from running all the operation bits like &lt;code&gt;docker build&lt;/code&gt; and &lt;code&gt;kubectl apply&lt;/code&gt;. Telepresence on other hand saves time testing code. By intercepting traffic from remote clusters, it’s almost like testing your local services directly in staging or production clusters. Together they create an inner-dev-loop that provides nearly instantaneous feedback on how your code will perform in the production environment. Building on top of example Skaffold is running in Docker.&lt;/p&gt;

&lt;p&gt;For today’s example, we’ll be using Telepresence as part of &lt;a href="https://www.getambassador.io/products/telepresence/"&gt;Ambassador Cloud&lt;/a&gt; as Ambassador gives us some additional features we’ll want to take advantage of in later parts of this tutorial and future tutorials. Let’s start by projecting this local service into a remote cluster. While it is possible to complete this with another cluster hosted on your local machine, I highly recommend a cluster that is hosted with a Cloud provider. To use Ambassador Cloud, you’ll be asked to log in with GitHub to create a cloud account. Then, you’ll see the instructions to install and configure Telepresence.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;The react-reload demo running from the previous section&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;A Kubernetes cluster hosted with a Cloud provider&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The Telepresence binary, Install instructions can be found once you login here: &lt;a href="https://app.getambassador.io/cloud/preview/"&gt;https://app.getambassador.io/cloud/preview/&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Check requirements
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Check the demo is still running in your local browser&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a new terminal window with kubectl connected with your cloud-hosted cluster. I’m setting this new terminal to use a new kubeconfig file, but you can also switch context.&lt;/p&gt;

&lt;p&gt;$ export KUBECONFIG=/home/cloud-cluster.yml&lt;br&gt;
$ kubectl get nodes&lt;br&gt;
NAME STATUS ROLES AGE VERSION&lt;br&gt;
cloud-cluster Ready master 10d v1.17.3+k3s1&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Verify telepresence is installed and working&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;$ telepresence version&lt;br&gt;
Client v2.0.0 (api v3)&lt;/p&gt;


&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Example Steps
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Upload container image to Docker hub
&lt;/h3&gt;

&lt;p&gt;For Telepresence to intercept traffic we need our sample application to also be running in our Cloud cluster. To do this we need to first upload the container image created by Skaffold to Dockerhub.&lt;/p&gt;

&lt;p&gt;Let’s find the image id with &lt;code&gt;docker image ls&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
peteroneilljr/react-reload e2a7b322a8f36cf26ff3c12aaa156d8176fb42f26a0ceba3e241b6350c6c01c ae2a7b322a8f 2 hours ago 174MB
peteroneilljr/react-reload v1.17.1–57-g95092addf-dirty ae2a7b322a8f 2 hours ago 174MB
peteroneilljr/react-reload 5212d19febc7b8a0e5b623473c502a339b7222034e64024a3c3c45e3ab0e3281 5212d19febc7 3 hours ago 174MB
=== trimmed for brevity ===
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We see at least a few different react reload images. The first image created is the one we want to upload, the newer images were created by Skaffold when we made modifications. So let’s give the base image a tag of “latest” and push it to Dockerhub&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker image tag 5212d19febc7 peteroneilljr/react-reload:latest
$ docker push peteroneilljr/react-reload
Using default tag: latest
The push refers to repository [docker.io/peteroneilljr/react-reload]
ef61bb2587ca: Pushed
34561a8deb68: Pushed
e2718bad0837: Pushed
3687ae930f2e: Pushed
5947f76477a5: Mounted from library/node
8b86a15dc982: Mounted from library/node
66d69d514191: Mounted from library/node
531743b7098c: Mounted from library/node
latest: digest: sha256:91676ba8810f01b39416f5adaf7cb2c47e82b6a42e58e0735ab6f4f47fb78902 size: 1992
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  2. Run the sample app in the Cloud cluster
&lt;/h3&gt;

&lt;p&gt;Now that our image is hosted in a public repository we can recreate our sample application in the cloud cluster. Remember the kubernetes manifest? We had one deployment and one service. Let’s create these now.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl create deployment node — image=peteroneilljr/react-reload — port=8080
deployment.apps/node created
$ kubectl expose deployment node — type=LoadBalancer — port=8080 — target-port=8080
service/node exposed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h3&gt;
  
  
  3. Check that the sample app is running
&lt;/h3&gt;

&lt;p&gt;Next, let’s find the IP address assigned to our new application.&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
node LoadBalancer 10.43.95.91 35.223.x.x 8080:32708/TCP 2m52s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;And let’s navigate to this address and port in our browser. &lt;a href="http://35.223.x.x:8080"&gt;http://35.223.x.x:8080&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--kwd0f0LV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3200/0%2AfHrxguHdW4iv6nLI" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--kwd0f0LV--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3200/0%2AfHrxguHdW4iv6nLI" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  4. Intercept traffic
&lt;/h3&gt;

&lt;p&gt;Time to start Telepresence! Let’s start with a &lt;code&gt;telepresence list&lt;/code&gt; to verify everything is working as expected.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ telepresence list
Launching Telepresence Daemon v2.0.0 (api v3)
Need root privileges to run “/usr/local/bin/telepresence daemon-foreground ‘’ ‘’”
Password:
Connecting to traffic manager…
Connected to context default (https://34.123.x.x)
node : ready to intercept (traffic-agent not yet installed)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;We should see the node deployment is ready to intercept! So now we are going to intercept the node deployment in the public cluster with the service running on our local port 8080.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ telepresence intercept node — port 8080
Using deployment node
intercepted
State : ACTIVE
Destination : 127.0.0.1:8080
Intercepting: all connections
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now if you navigate back to your web browser and refresh page, you should see your local deployment being displayed on the public IP address from your Cloud cluster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--s7LpDgaT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3200/0%2AaaOQ8VfgUaPgzOBL" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--s7LpDgaT--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3200/0%2AaaOQ8VfgUaPgzOBL" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  5. Testing our inner-dev-loop
&lt;/h3&gt;

&lt;p&gt;With Skaffold and Telepresence working together you’re able to see the changes to our local cluster get populated on the public IP address in real time. Let’s test this out, this time we are going to modify the HelloWorld.css file in the &lt;code&gt;app/src/styles/&lt;/code&gt; folder. Update the h1 color to be ff0000&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;h1 {
  color: #ff0000;
  text-align: center;
  margin-top: 40vh;
  font-size: 120pt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Once you save this file we should see the heading of the page in your browser pointed at your local cluster change to red nearly instantly, and very shortly after you should notice your public ingress change as well.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--jC8WcAcm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3200/0%2AEDl7W9gXIf_73CQ5" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--jC8WcAcm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://cdn-images-1.medium.com/max/3200/0%2AEDl7W9gXIf_73CQ5" alt=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  6. Sharing our intercept with teammates using Ambassador Cloud
&lt;/h3&gt;

&lt;p&gt;Because WebPack has host checking enabled by default we will need to disable it for this next part.&lt;/p&gt;

&lt;p&gt;Open &lt;code&gt;app/webpack.config.js&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Add &lt;code&gt;disableHostChecking: true&lt;/code&gt; to &lt;code&gt;devServer&lt;/code&gt;&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;devServer:{
  host: ‘0.0.0.0’,
  disableHostCheck: true
},
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Save this file and Skaffold will rebuild your local image.&lt;/p&gt;

&lt;p&gt;Tag and push this new image to Dockerhub&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
peteroneilljr/react-reload 82d036eee5887d5660e0a787435f01fddec66c0617c8dc364f45421941aa4f9e 82d036eee588 19 hours ago 173MB
peteroneilljr/react-reload latest 82d036eee588 19 hours ago 173MB
$ docker tag 82d036eee588 peteroneilljr/react-reload
$ docker push peteroneilljr/react-reload
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Delete the current pod so that it can respawn with the new configuration.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl get pods
NAME READY STATUS RESTARTS AGE
node-86dfc695f5–22psv 1/1 Running 0 13s
$ kubectl delete pod node-86dfc695f5–22psv
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now let’s leave the current intercept&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ telepresence leave node
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Login to telepresence, this will take you to GitHub to authenticate.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ telepresence login
Launching browser authentication flow…
Login successful.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Create a new intercept. This time Telepresence will ask a few questions. Follow the prompts shown below.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ telepresence intercept node — port 8080
Confirm the ingress to use for preview URL access
Ingress service.namespace [ambassador.ambassador] ? node.default
Port [80] ? 80
Use TLS y/n [n] ? n
Using deployment node
intercepted
State : ACTIVE
Destination : 127.0.0.1:8080
Intercepting: HTTP requests that match all of:
header(“x-telepresence-intercept-id”) ~= regexp(“6e5b52d3–676a-421d-8223–397fb1146162:node”)
Preview URL : [https://nostalgic-colden-2717.preview.edgestack.me](https://nostalgic-colden-2717.preview.edgestack.me)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Now our intercept can be seen and shared with the preview URL.&lt;/p&gt;

&lt;h3&gt;
  
  
  7. Cleaning up
&lt;/h3&gt;

&lt;p&gt;Just like that we’ve reached the end of our demo, so let’s clean up all the resources we’ve used.&lt;/p&gt;

&lt;p&gt;First Telepresence, either leave the intercept if you plan to use it more or uninstall everything. With either approach you’ll see the display quickly return back to the original prompt and color to show the intercept is not longer applied.&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ telepresence leave node
$ telepresence uninstall — everything
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;Next Skaffold, you can stop &lt;code&gt;skaffold dev&lt;/code&gt; by pressing &lt;code&gt;ctr+c&lt;/code&gt; within the terminal window.&lt;/p&gt;

&lt;p&gt;Lastly, the Cloud cluster. If you’re going to keep using the cluster remove the resources we created, otherwise feel free to delete the whole cluster.&lt;/p&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl delete svc node&lt;br&gt;
service “node” deleted&lt;br&gt;
$ kubectl delete deploy node&lt;br&gt;
deployment.apps “node” deleted&lt;br&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;
&lt;h2&gt;
&lt;br&gt;
  &lt;br&gt;
  &lt;br&gt;
  Conclusion&lt;br&gt;
&lt;/h2&gt;

&lt;p&gt;Now as we can see from this example there are a lot of moving pieces when it comes to writing code for a Cloud Native application. Luckily there are tools like Skaffold that save time managing container images and Kubernetes deployments, and tools like Telepresence &amp;amp; Ambassador to save time debugging by creating a better testing environment.&lt;/p&gt;

&lt;p&gt;If you’re considering using Skaffold or just exploring possible tools to make your development workflow better, I hope this article helped out. Drop a comment and let me know what you liked, what you didn’t like, or what you want to hear more about. You can also Tweet at me to let me know what you think @&lt;a href="https://twitter.com/peteroneilljr/"&gt;peteroneilljr&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here are some additional resources that may help you get started:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://skaffold.dev/docs/"&gt;Skaffold documentation&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Watch the &lt;a href="https://youtu.be/W_a3aErN3NU"&gt;demo video&lt;/a&gt; of Ambassador Cloud and Telepresence&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Learn more about &lt;a href="https://www.getambassador.io/products/telepresence/"&gt;Ambassador Cloud and Telepresence&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Join our &lt;a href="http://d6e.co/slack"&gt;Slack channel&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>kubernetes</category>
      <category>telepresence</category>
      <category>skaffold</category>
      <category>cloudnative</category>
    </item>
  </channel>
</rss>
