<?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: Henrique Cavarsan</title>
    <description>The latest articles on DEV Community by Henrique Cavarsan (@hcavarsan).</description>
    <link>https://dev.to/hcavarsan</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%2F1243406%2F70a23663-0e74-428f-9f28-9e83c6178188.jpeg</url>
      <title>DEV Community: Henrique Cavarsan</title>
      <link>https://dev.to/hcavarsan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/hcavarsan"/>
    <language>en</language>
    <item>
      <title>kftui - A better way to manage kubectl port-forwards</title>
      <dc:creator>Henrique Cavarsan</dc:creator>
      <pubDate>Mon, 25 Aug 2025 13:39:14 +0000</pubDate>
      <link>https://dev.to/hcavarsan/kftui-a-better-way-to-manage-kubectl-port-forwards-3ld8</link>
      <guid>https://dev.to/hcavarsan/kftui-a-better-way-to-manage-kubectl-port-forwards-3ld8</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;First of all - kftray and kftui are independent, cross-platform applications. They help you set up and manage multiple port-forwarding settings easily. Both apps are basically the same tool with different interfaces. kftray is the GUI version with windows and buttons. kftui is the terminal version that runs in your command line. They share the same database and configs. Set up a port-forward in kftray's GUI, and you'll see it in kftui too. Save something in kftui, and it shows up in kftray. You can use whichever one you prefer or switch between them.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So... the kftray/kftui docs are pretty messy right now, and I figured writing this blog post would be easier than fixing everything properly. I'll organize the docs later, but this should cover what kftui does and how to use it.&lt;/p&gt;

&lt;p&gt;kftui has most of the same stuff as kftray, but this guide is just about the terminal version.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0j34os84ltkekmqvqnt1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0j34os84ltkekmqvqnt1.png" alt="Complete Diagram"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Build a Terminal Interface?
&lt;/h2&gt;

&lt;p&gt;I built kftui to address some practical limitations of GUI applications. Terminal interfaces use significantly fewer system resources, which matters in resource-constrained environments. They work well over SSH connections without requiring X11 forwarding or remote desktop setups.&lt;/p&gt;

&lt;p&gt;From a development perspective, maintaining one codebase in Rust is simpler than managing separate frontend and backend projects. This approach reduces complexity and keeps the tool focused on core functionality.&lt;/p&gt;

&lt;p&gt;If you've worked with multiple &lt;code&gt;kubectl port-forward&lt;/code&gt; processes in different terminal windows, you know how quickly it becomes difficult to manage. kftui provides a centralized way to handle these connections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;p&gt;You'll need &lt;code&gt;curl&lt;/code&gt; or &lt;code&gt;wget&lt;/code&gt; installed. Windows users need PowerShell.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Unix-like systems (Linux, macOS, WSL):&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Using cargo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;cargo &lt;span class="nb"&gt;install &lt;/span&gt;kftui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using Homebrew:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;brew tap hcavarsan/kftray
brew install kftui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using curl:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; https://raw.githubusercontent.com/hcavarsan/kftray/main/hacks/kftui_installer.sh&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using wget:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;bash &amp;lt;&lt;span class="o"&gt;(&lt;/span&gt;wget &lt;span class="nt"&gt;-qO-&lt;/span&gt; https://raw.githubusercontent.com/hcavarsan/kftray/main/hacks/kftui_installer.sh&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Windows:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Invoke-Expression&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="n"&gt;New-Object&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;System.Net.WebClient&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;DownloadString&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'https://raw.githubusercontent.com/hcavarsan/kftray/main/hacks/kftui_installer.ps1'&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;After installation, restart your terminal and verify it works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kftui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Basic Usage
&lt;/h2&gt;

&lt;p&gt;Start with a simple configuration file. Create &lt;code&gt;config.json&lt;/code&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="p"&gt;[&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;span class="nl"&gt;"alias"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-api"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"minikube"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"api-service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"local_port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"remote_port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"protocol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"workload_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;"service"&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;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;Launch kftui with this configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kftui &lt;span class="nt"&gt;--configs-path&lt;/span&gt; config.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The interface displays your configuration in the "Stopped" table on the left. Press &lt;code&gt;f&lt;/code&gt; to start the port-forward. The configuration moves to the "Running" table on the right, and your service becomes accessible at &lt;code&gt;localhost:8080&lt;/code&gt;. Press &lt;code&gt;f&lt;/code&gt; again to stop it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Persistent Storage
&lt;/h3&gt;

&lt;p&gt;To avoid specifying the config file path repeatedly, save configurations to kftui's database:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kftui &lt;span class="nt"&gt;--configs-path&lt;/span&gt; config.json &lt;span class="nt"&gt;--save&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After saving, run &lt;code&gt;kftui&lt;/code&gt; without arguments to access your stored configurations. This approach works well for frequently used port-forward setups.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuration Sources
&lt;/h2&gt;

&lt;p&gt;kftui supports several ways to load configurations, each suited to different workflows.&lt;/p&gt;

&lt;h3&gt;
  
  
  Local Files
&lt;/h3&gt;

&lt;p&gt;Load configurations from local JSON files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kftui &lt;span class="nt"&gt;--configs-path&lt;/span&gt; /path/to/config.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  GitHub Repositories
&lt;/h3&gt;

&lt;p&gt;Import configurations from version-controlled repositories:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kftui &lt;span class="nt"&gt;--github-url&lt;/span&gt; https://github.com/your-team/k8s-configs &lt;span class="nt"&gt;--configs-path&lt;/span&gt; environments/dev.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This method works well for teams that maintain environment-specific configurations in version control.&lt;/p&gt;

&lt;h3&gt;
  
  
  Inline JSON
&lt;/h3&gt;

&lt;p&gt;Pass JSON configuration directly for scripting scenarios:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kftui &lt;span class="nt"&gt;--json&lt;/span&gt; &lt;span class="s1"&gt;'[{"alias":"test","namespace":"default","service":"my-service","local_port":8080,"remote_port":80,"protocol":"tcp","workload_type":"service"}]'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Standard Input
&lt;/h3&gt;

&lt;p&gt;Read configurations from stdin for pipeline integration:&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="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'[{"alias":"api",...}]'&lt;/span&gt; | kftui &lt;span class="nt"&gt;--stdin&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Command-Line Options
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;--save&lt;/code&gt;&lt;/strong&gt;: Store configurations in the database for future use&lt;br&gt;
&lt;strong&gt;&lt;code&gt;--flush&lt;/code&gt;&lt;/strong&gt;: Clear existing configurations before importing new ones&lt;br&gt;
&lt;strong&gt;&lt;code&gt;--auto-start&lt;/code&gt;&lt;/strong&gt;: Start all port-forwards immediately after loading&lt;br&gt;
&lt;strong&gt;&lt;code&gt;--non-interactive&lt;/code&gt;&lt;/strong&gt;: Run without the interface for automation scripts&lt;/p&gt;
&lt;h2&gt;
  
  
  Service Auto-Discovery
&lt;/h2&gt;

&lt;p&gt;Rather than manually creating configuration files, kftui can discover services through Kubernetes annotations. This approach keeps port-forward configurations synchronized with service definitions.&lt;/p&gt;

&lt;p&gt;Add annotations to your Kubernetes services:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Service&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;monitoring-stack&lt;/span&gt;
  &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;observability&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;kftray.app/configs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;grafana-3000-3000,prometheus-9090-9090,alertmanager-9093-9093"&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;selector&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;app&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;monitoring&lt;/span&gt;
  &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;grafana&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3000&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;prometheus&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;9090&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;alertmanager&lt;/span&gt;
      &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;9093&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The annotation format is &lt;code&gt;alias-local_port-remote_port&lt;/code&gt;. Multiple configurations are separated by commas.&lt;/p&gt;

&lt;p&gt;To use auto-discovery, navigate to the top menu in kftui and select "Auto Add". Choose your Kubernetes context from the available options, and kftui will create configurations for all annotated services in that context.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0h4q95zgyf7mvhoanbr1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0h4q95zgyf7mvhoanbr1.png" alt="Auto-Discovery"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Interface Organization
&lt;/h2&gt;

&lt;p&gt;The interface consists of four main areas:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Top menu bar&lt;/strong&gt;: Contains Help, Auto Add, Import, Export, Settings, About, and Exit options&lt;br&gt;
&lt;strong&gt;Stopped configurations&lt;/strong&gt; (left): Displays configurations ready to start&lt;br&gt;
&lt;strong&gt;Running configurations&lt;/strong&gt; (right): Shows active port-forwards with status information&lt;br&gt;
&lt;strong&gt;Details panel&lt;/strong&gt; (bottom): Provides information about the selected configuration&lt;/p&gt;
&lt;h3&gt;
  
  
  Menu Navigation
&lt;/h3&gt;

&lt;p&gt;The top menu provides seven functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Help&lt;/strong&gt;: Display usage information and keyboard shortcuts&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Auto Add&lt;/strong&gt;: Discover services from your Kubernetes cluster&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Import&lt;/strong&gt;: Load configuration files through a file browser&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Export&lt;/strong&gt;: Save current configurations to a JSON file&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Settings&lt;/strong&gt;: Configure application behavior&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;About&lt;/strong&gt;: Show version and project information&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Exit&lt;/strong&gt;: Stop all active port-forwards and close the application&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Navigate menu items with &lt;code&gt;←/→&lt;/code&gt; arrow keys and press &lt;code&gt;Enter&lt;/code&gt; to select.&lt;/p&gt;
&lt;h2&gt;
  
  
  Application Settings
&lt;/h2&gt;

&lt;p&gt;Access settings by pressing &lt;code&gt;s&lt;/code&gt; or selecting Settings from the menu.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Disconnect Timeout&lt;/strong&gt;: Configure automatic disconnection after a specified period of inactivity. Set to 0 to disable automatic timeouts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network Monitor&lt;/strong&gt;: Enable or disable network connectivity monitoring. When enabled, kftui monitors network status and attempts to reconnect dropped port-forwards.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Settings persist between application sessions.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fibrt49jtsqfvo2vlhjjn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fibrt49jtsqfvo2vlhjjn.png" alt="Settings"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  HTTP Request Logging
&lt;/h2&gt;

&lt;p&gt;kftui provides HTTP request and response logging for debugging network traffic through port-forwards.&lt;/p&gt;

&lt;p&gt;Enable logging by setting &lt;code&gt;"http_logs_enabled": true&lt;/code&gt; in your configuration file, or toggle it for existing configurations by pressing &lt;code&gt;l&lt;/code&gt; in the interface.&lt;/p&gt;
&lt;h3&gt;
  
  
  HTTP Logs Viewer
&lt;/h3&gt;

&lt;p&gt;Press &lt;code&gt;Shift+V&lt;/code&gt; to open the HTTP logs viewer, which operates in two modes:&lt;/p&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;List Mode&lt;/strong&gt; (default view):
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmhwelxi21alzzvtjjcni.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmhwelxi21alzzvtjjcni.png" alt="HTTP Logs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Displays all HTTP requests with timestamps and status codes&lt;/li&gt;
&lt;li&gt;Navigate requests with &lt;code&gt;↑/↓&lt;/code&gt; arrow keys&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;PageUp/PageDown&lt;/code&gt; to scroll through multiple entries&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;Enter&lt;/code&gt; on any request to view detailed information&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;a&lt;/code&gt; to toggle automatic scrolling for new requests&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  &lt;strong&gt;Detail Mode&lt;/strong&gt; (activated by pressing Enter on a request):
&lt;/h4&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F28kv5wcobvtrgebjnm32.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F28kv5wcobvtrgebjnm32.png" alt="HTTP Logs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Shows complete request and response information including headers and body content&lt;/li&gt;
&lt;li&gt;Scroll through details with &lt;code&gt;↑/↓&lt;/code&gt; arrow keys&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;PageUp/PageDown&lt;/code&gt; for faster navigation&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;r&lt;/code&gt; to replay the selected request&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;Esc&lt;/code&gt; to return to list mode&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  HTTP Logs Configuration
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4vux00gm7egw6hvjy3c9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4vux00gm7egw6hvjy3c9.png" alt="HTTP Logs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Press &lt;code&gt;L&lt;/code&gt; to configure HTTP logging behavior:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enable or disable logging for individual configurations&lt;/li&gt;
&lt;li&gt;Set maximum log file size (1-1000 MB)&lt;/li&gt;
&lt;li&gt;Configure retention period (1-365 days)&lt;/li&gt;
&lt;li&gt;Enable automatic cleanup of old log files&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Complete Keyboard Reference
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Key&lt;/th&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;f&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Start or stop port-forward&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;i&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Import configurations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;e&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Export configurations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;d&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Delete selected configurations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;a&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Select all configurations&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Space&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Toggle individual selection&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Tab&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Switch between interface components&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;←/→&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Navigate menu items&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;s&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Open settings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;h&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Show help information&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;q&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Show about information&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;l&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Toggle HTTP logging&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;L&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Configure HTTP logging&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;V&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;View HTTP logs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;o&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Open HTTP logs in external editor&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;↑/↓&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Navigate within sections&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;PageUp/PageDown&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Scroll through content&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Home/End&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Jump to first/last item&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;Ctrl+C&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Exit application&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;
&lt;h2&gt;
  
  
  Configuration File Structure
&lt;/h2&gt;

&lt;p&gt;Configuration files use JSON format with the following fields:&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="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"alias"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"my-service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;           &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Display&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;interface&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"production"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Kubernetes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;namespace&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(required)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"api-service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;        &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Target&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;service&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;name&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"local_port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;             &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Local&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;binding&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;port&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"remote_port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Remote&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;service&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;port&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"protocol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;              &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Network&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;protocol&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(required)&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"workload_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;"service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;     &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Target&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;type:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"service"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;or&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pod"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prod-cluster"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;      &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Kubernetes&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;context&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"kubeconfig"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/path/to/config"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Kubeconfig&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;file&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;path&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"http_logs_enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;       &lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Enable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;HTTP&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;logging&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;The minimum required fields are &lt;code&gt;namespace&lt;/code&gt; and &lt;code&gt;protocol&lt;/code&gt;. When ports are not specified, kftui attempts to determine appropriate values from the service definition.&lt;/p&gt;

&lt;h2&gt;
  
  
  How kftui Relates to kftray
&lt;/h2&gt;

&lt;h2&gt;
  
  
  What kftui Can Do
&lt;/h2&gt;

&lt;p&gt;kftui handles pretty much everything the kftray GUI does, just through terminal commands and keyboard shortcuts. The auto-discovery stuff saves time by reading your Kubernetes service annotations instead of making you type configs manually. The HTTP logging is useful for debugging API calls and seeing what requests are going through your port-forwards.&lt;/p&gt;

&lt;p&gt;If you work mostly in terminals or need to manage port-forwards over SSH, kftui covers everything without needing a desktop environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo Video
&lt;/h2&gt;

&lt;p&gt;In this quick demo video, I've tested both tools with the same setup - port forwarding to a service while running curl in a loop. Then deleted all pods with kubectl delete pods --all --force to see how each handles recovery.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;kubectl port forward: When pods get deleted, the port forward just dies even though it's forwarding to a service. All requests fail and you have to manually restart it.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;kftray: Loses maybe one request when pods get deleted. The watcher detects changes immediately and reconnects to new pods as they come up. The curl loop keeps going like nothing happened.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/dBzFdejBBpc"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Demo Video HTTP Logs:
&lt;/h2&gt;

&lt;p&gt;Video demonstration on how to inspect HTTP traffic throug requests in port forwarding.&lt;/p&gt;

&lt;p&gt;  &lt;iframe src="https://www.youtube.com/embed/Zvv9gIhLaSM"&gt;
  &lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Additional Resources
&lt;/h2&gt;

&lt;p&gt;For more information:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/hcavarsan/kftray/blob/main/docs/kftui/INSTALL.md" rel="noopener noreferrer"&gt;Installation Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hcavarsan/kftray/blob/main/docs/kftui/USAGE.md" rel="noopener noreferrer"&gt;Usage Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/hcavarsan/kftray/releases" rel="noopener noreferrer"&gt;Latest Release&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you find kftray or kftui useful, consider starring the project on &lt;a href="https://github.com/hcavarsan/kftray" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; ⭐&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>rust</category>
      <category>tui</category>
      <category>devops</category>
    </item>
    <item>
      <title>Design contract infra</title>
      <dc:creator>Henrique Cavarsan</dc:creator>
      <pubDate>Sat, 24 May 2025 23:22:33 +0000</pubDate>
      <link>https://dev.to/hcavarsan/design-contract-infra-4hm1</link>
      <guid>https://dev.to/hcavarsan/design-contract-infra-4hm1</guid>
      <description></description>
      <category>softwaredevelopment</category>
      <category>design</category>
      <category>programming</category>
    </item>
    <item>
      <title>Debugging Kubernetes Services with KFtray's HTTP Logs and VS Code REST Client Extension</title>
      <dc:creator>Henrique Cavarsan</dc:creator>
      <pubDate>Wed, 05 Mar 2025 21:13:22 +0000</pubDate>
      <link>https://dev.to/hcavarsan/debugging-kubernetes-services-with-kftrays-http-logs-and-vs-code-rest-client-extension-kf1</link>
      <guid>https://dev.to/hcavarsan/debugging-kubernetes-services-with-kftrays-http-logs-and-vs-code-rest-client-extension-kf1</guid>
      <description>&lt;p&gt;If you've worked with Kubernetes, you already know the debugging headaches it can cause. But what makes it particularly difficult?&lt;/p&gt;

&lt;p&gt;First, there's the distributed architecture. Your applications run across multiple nodes and namespaces, with traffic flowing through various system layers.&lt;/p&gt;

&lt;p&gt;Second, environments constantly change. Pods start, stop, and reschedule themselves. Configuration changes happen frequently.&lt;/p&gt;

&lt;p&gt;And production environments? They add a whole new level of complexity. Issues often manifest differently in production due to scale, load, or configuration variations. Security policies typically restrict direct access to services.&lt;/p&gt;

&lt;p&gt;Have you ever found a bug in development that behaves completely differently in production? You're not alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Debugging Options for Kubernetes
&lt;/h2&gt;

&lt;p&gt;Most developers rely on a few standard approaches when debugging Kubernetes services. Each has its strengths—and limitations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Manual Request Tools
&lt;/h3&gt;

&lt;p&gt;Tools like Postman, Insomnia, and curl let you test endpoints directly. They're useful for simple tests, but they come with constraints:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each request must be manually created&lt;/li&gt;
&lt;li&gt;They can't capture live traffic patterns&lt;/li&gt;
&lt;li&gt;You often need multiple tools during a debugging session&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tools work well in controlled situations but may fall short when dealing with complex, real-world traffic patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Proxy-Based Solutions
&lt;/h3&gt;

&lt;p&gt;Proxy tools like Charles Proxy and mitmproxy provide deeper traffic visibility. But there's more to it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Certificate management can be complex&lt;/li&gt;
&lt;li&gt;Workflow integration isn't always smooth&lt;/li&gt;
&lt;li&gt;They sometimes capture too much traffic&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While useful, these tools often feel disconnected from your development environment, requiring constant context switching.&lt;/p&gt;

&lt;h3&gt;
  
  
  Network Analysis Tools
&lt;/h3&gt;

&lt;p&gt;Low-level tools like Wireshark offer comprehensive traffic inspection but generally provide more information than needed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;They have a steep learning curve&lt;/li&gt;
&lt;li&gt;The level of detail can be overwhelming&lt;/li&gt;
&lt;li&gt;They lack application context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These tools are great at network-level debugging but can make application-level analysis more complex than necessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  An Alternative Approach with KFtray HTTP Logging
&lt;/h2&gt;

&lt;p&gt;I've found that KFtray offers an approach to Kubernetes debugging by adding HTTP traffic logging capabilities to standard port-forwarding.&lt;/p&gt;

&lt;p&gt;It functions as a proxy layer that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Records HTTP traffic through port-forwards&lt;/li&gt;
&lt;li&gt;Maintains standard port-forward functionality&lt;/li&gt;
&lt;li&gt;Integrates with existing development workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This approach provides additional visibility into service interactions while using familiar port-forwarding mechanics.&lt;/p&gt;

&lt;p&gt;You might be asking yourself: "How does this actually work with VS Code?" That's what i'll explore next.&lt;/p&gt;

&lt;h2&gt;
  
  
  How KFtray's HTTP Logging Works
&lt;/h2&gt;

&lt;p&gt;When you enable HTTP logging for a port-forward configuration in KFtray, a series of events unfolds:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxt3buj7ccdcebugn1gt4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxt3buj7ccdcebugn1gt4.png" alt="diagram" width="715" height="510"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Start a port forward with http logging option enabled&lt;/li&gt;
&lt;li&gt;The app itself captures incoming HTTP requests&lt;/li&gt;
&lt;li&gt;Requests are forwarded to your Kubernetes service&lt;/li&gt;
&lt;li&gt;Responses are captured on their return journey&lt;/li&gt;
&lt;li&gt;Complete request-response pairs are logged with correlation IDs&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This process enables traffic capture without requiring application changes or additional debugging tools.&lt;/p&gt;

&lt;p&gt;And these logs are formatted in a way that works seamlessly with VS Code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Setting Up HTTP Logging in KFtray
&lt;/h2&gt;

&lt;p&gt;Setting up HTTP logging in KFtray is an simple process that begins with downloading and installing KFtray v0.16.1 or later from the &lt;a href="https://github.com/hcavarsan/kftray/releases" rel="noopener noreferrer"&gt;GitHub releases page&lt;/a&gt;. Once you have KFtray installed, you'll need to configure your port-forward settings.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkftray.app%2Fimg%2Fadding-config.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fkftray.app%2Fimg%2Fadding-config.gif" alt="Add Config" width="450" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Start by launching KFtray and creating a new port-forward configuration. You'll need to specify your Kubernetes environment details, including your desired context and the namespace where your service runs. Make sure to enter the correct service name – this is the Kubernetes service you want to monitor.&lt;/p&gt;

&lt;p&gt;Next, configure your port settings. The local port is where you'll access the service on your machine, while the remote port is where the service runs in your Kubernetes cluster. Give your configuration a descriptive name that helps you identify it easily later. This name will be particularly helpful when you're managing multiple port-forwards.&lt;/p&gt;

&lt;p&gt;With your configuration in place, enable the port-forward by toggling the switch in the KFtray interface. Then, click the menu icon next to your port-forward configuration and enable HTTP logging. This simple step activates the logging feature for your selected port-forward.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fln0syfdbfebytd365wly.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fln0syfdbfebytd365wly.gif" alt="Enable HTTP Logging" width="450" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;KFtray will now automatically capture all HTTP traffic flowing through your port-forward. The logs are saved to &lt;code&gt;$HOME/.kftray/http_logs/&lt;/code&gt;, and each log file is named using your configuration ID and local port for easy reference.&lt;/p&gt;

&lt;p&gt;Now that you have logging set up, let's explore what makes these logs particularly valuable for debugging and development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Understanding the HTTP Log Format
&lt;/h2&gt;

&lt;p&gt;The HTTP logs generated by KFtray are structured in a specific format that's compatible with VS Code's REST Client extension. Each entry contains complete details about the HTTP interaction:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;curl '&lt;a href="http://127.0.0.1:8787/gzip" rel="noopener noreferrer"&gt;http://127.0.0.1:8787/gzip&lt;/a&gt;' --compressed -H 'User-Agent: Test'&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk53ic0tx39y9t09xzoxg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fk53ic0tx39y9t09xzoxg.png" alt="HTTP Log Format Example" width="614" height="885"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ----------------------------------------
# Trace ID: 651bc5a5-fb13-46ec-b471-473f08a1f828
# Request at: 2025-03-05T16:56:00.076606+00:00
GET /gzip HTTP/1.1
Host: 127.0.0.1:8787
Accept: */*
Accept-Encoding: deflate, gzip
User-Agent: Test

#&amp;lt;empty body&amp;gt;

###

# ----------------------------------------
# Trace ID: 651bc5a5-fb13-46ec-b471-473f08a1f828
# Response at: 2025-03-05T16:56:00.079206+00:00
# Took: 2 ms
HTTP/1.1 200 OK
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin: *
Content-Encoding: gzip
Content-Length: 150
Content-Type: application/json; encoding=utf-8
Date: Wed, 05 Mar 2025 16:56:00 GMT


{
  "headers": {
    "Accept": [
      "*/*"
    ],
    "Accept-Encoding": [
      "deflate, gzip"
    ],
    "Host": [
      "127.0.0.1:8787"
    ],
    "User-Agent": [
      "Test"
    ]
  },
  "origin": "127.0.0.1:56846",
  "gzipped": true
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The log format includes several key components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Trace ID&lt;/strong&gt;: Each request-response pair shares a unique identifier&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Timestamps and Duration&lt;/strong&gt;: Useful for identifying performance issues&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complete HTTP Details&lt;/strong&gt;: Includes headers, status codes, and body content&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This format is what makes the logs directly usable with VS Code's REST Client.&lt;/p&gt;

&lt;h2&gt;
  
  
  Integrating with VS Code REST Client
&lt;/h2&gt;

&lt;p&gt;The REST Client extension for VS Code is a powerful tool for testing HTTP requests. When combined with KFtray's logs, it creates a workflow for debugging Kubernetes services.&lt;/p&gt;

&lt;p&gt;To use this integration:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Install the REST Client extension from the VS Code marketplace&lt;/li&gt;
&lt;li&gt; Open a KFtray-generated log file in VS Code&lt;/li&gt;
&lt;li&gt; The extension automatically recognizes HTTP requests in the file&lt;/li&gt;
&lt;li&gt; Use the "Send Request" button to replay any captured request&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Note: You can modify parameters, headers, or body content before replaying a request,&lt;br&gt;
making it easy to test different scenarios.&lt;/p&gt;
&lt;/blockquote&gt;




&lt;blockquote&gt;
&lt;p&gt;Note: This approach works alongside existing debugging tools rather than replacing them.&lt;br&gt;
It can complement your current development workflow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This integration allows you to conduct debugging within your code editor, potentially reducing the need to switch between multiple tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  How can it help?
&lt;/h2&gt;

&lt;p&gt;Here are some common scenarios in which these tools can be useful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Diagnosing Intermittent API Errors
&lt;/h3&gt;

&lt;p&gt;Production services sometimes experience sporadic errors that are difficult to reproduce. This approach can help:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; Enable HTTP logging for the service's port-forward&lt;/li&gt;
&lt;li&gt; Monitor the application until the error occurs&lt;/li&gt;
&lt;li&gt; Review the HTTP logs for failing requests:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# ----------------------------------------
# Trace ID: 5525d312-5582-46ad-85d1-0fd3710f824e
# Response at: 2025-03-01T15:34:09.901304+00:00
# Took: 144 ms
HTTP/1.1 500 Internal Server Error
Content-Type: application/json

{
  "error": "Failed to connect to database",
  "code": "DB_CONNECTION_ERROR"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt; Use VS Code REST Client to replay the exact request to verify the error pattern&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This method can help make intermittent failures more reproducible and easier to debug.&lt;/p&gt;

&lt;h3&gt;
  
  
  Tracking Microservice Communication
&lt;/h3&gt;

&lt;p&gt;Microservice architectures create complex communication patterns that can be difficult to visualize. HTTP logging helps by capturing traffic across multiple service port-forwards, recording complete request and response cycles, maintaining trace ID correlation across services, and providing timing data for each interaction. This visibility can help identify communication patterns and potential areas for optimization.&lt;/p&gt;

&lt;h3&gt;
  
  
  Troubleshooting Authentication Flows
&lt;/h3&gt;

&lt;p&gt;Authentication systems typically involve multiple steps of token exchange and validation. With HTTP logging, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Record complete authentication request sequences&lt;/li&gt;
&lt;li&gt;Preserve header information and token data&lt;/li&gt;
&lt;li&gt;Replay requests with modified parameters&lt;/li&gt;
&lt;li&gt;Maintain the full context of authentication flows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All that being said, the real value comes from how these tools fit into your existing development workflow.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Combining KFtray's HTTP logging with VS Code's REST Client extension offers an additional option for debugging Kubernetes services. This approach provides a way to capture and replay HTTP traffic that can simplify some debugging scenarios.&lt;/p&gt;

&lt;p&gt;The format compatibility between KFtray's logs and VS Code REST Client creates a workflow that includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Capturing service interactions with context&lt;/li&gt;
&lt;li&gt;Documenting intermittent issues&lt;/li&gt;
&lt;li&gt;Providing request replay capabilities&lt;/li&gt;
&lt;li&gt;Supplementing existing debugging approaches&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;i believe this combination of tools could be helpful in certain Kubernetes debugging scenarios. i'm curious to see how you might apply this approach to your own debugging challenges.&lt;/p&gt;

&lt;p&gt;If you're interested in exploring this further, you can find more information on the &lt;a href="https://github.com/hcavarsan/kftray" rel="noopener noreferrer"&gt;KFtray GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Feedback and contributions are welcome.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>programming</category>
      <category>opensource</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>A bit about OSS Licenses using LEGO analogy</title>
      <dc:creator>Henrique Cavarsan</dc:creator>
      <pubDate>Fri, 01 Nov 2024 13:04:48 +0000</pubDate>
      <link>https://dev.to/hcavarsan/a-bit-about-oss-licenses-using-lego-analogy-2e33</link>
      <guid>https://dev.to/hcavarsan/a-bit-about-oss-licenses-using-lego-analogy-2e33</guid>
      <description>&lt;p&gt;Link to original article: &lt;a href="https://kftray.app/blog/posts/9-oss-legos" rel="noopener noreferrer"&gt;https://kftray.app/blog/posts/9-oss-legos&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This article was heavily inspired by a video called &lt;a href="https://www.youtube.com/watch?v=a8fHgx9mE5U" rel="noopener noreferrer"&gt;What is Open Source explained in LEGO&lt;/a&gt; from 10 years ago which is very well explained. The video used LEGO to explain open source in a simple way. I wanted to build on that idea by using LEGO to explain the different types of open source licenses.&lt;/p&gt;
&lt;/blockquote&gt;



&lt;p&gt;So, imagine you have a giant box of Lego bricks. You love creating all sorts of things—spaceships, castles, robots—and you often invite your friends over to build together.&lt;br&gt;
Sometimes, you come up with an amazing creation and want others to enjoy it too. But you also want to make sure everyone plays fair and knows how they can use your designs. That's where open source licenses come into play.&lt;/p&gt;

&lt;h3&gt;
  
  
  Permissive vs Copyleft Licenses
&lt;/h3&gt;

&lt;p&gt;Just like you might have different rules for sharing your Lego creations, open source licenses come in two main types: &lt;strong&gt;permissive&lt;/strong&gt; and &lt;strong&gt;copyleft&lt;/strong&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Permissive licenses&lt;/strong&gt; Allow others to use, modify, and distribute your work with minimal restrictions.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Copyleft licenses&lt;/strong&gt;  Ensures that all future versions remain free and open.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Permissive Licenses - The "Do What You Want" and "No Warranty" Rule
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Alex takes your Lego castle and transforms it into a futuristic fortress. He decides to display it at a local event without mentioning you. While you might wish he gave you credit, your "do what you want" rule means he's allowed to do that. Your castle idea has inspired new creations, even if you don't see the direct benefits.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Suppose you tell Alex, &lt;code&gt;Here's my Lego castle. You can do whatever you like with it—even keep it, change it completely, or sell it at the school fair. But if anything goes wrong—like the blocks breaking—it's not my fault.&lt;/code&gt; This gives Alex complete freedom over what he does with your creation while also letting him know that you're not responsible for any problems.&lt;/p&gt;

&lt;p&gt;This is like a permissive license such as the &lt;a href="https://opensource.org/licenses/MIT" rel="noopener noreferrer"&gt;MIT License&lt;/a&gt;. People can use the code in any way they want, even in their own projects that they might sell or keep private. The "no warranty" part is a common clause in these licenses, stating that the software is provided "as is," without any guarantees.&lt;/p&gt;

&lt;p&gt;Another example of a permissive license is the &lt;a href="https://opensource.org/licenses/BSD-3-Clause" rel="noopener noreferrer"&gt;BSD 3-Clause License&lt;/a&gt;. While it allows free use, modification, and distribution like the MIT License, it requires that credit be given to the original author.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Edit Note&lt;/strong&gt;: I have misunderstood about BSD license, before I mentioned that BSD does not require attribution, but after this &lt;a href="https://www.reddit.com/r/programming/comments/1gh4i8t/comment/luv83dl/?context=3" rel="noopener noreferrer"&gt;reddit comment&lt;/a&gt;, I figured out that I was incorrect about BSD as the BSD license is permissive but &lt;a href="https://www.tldrlegal.com/license/bsd-3-clause-license-revised" rel="noopener noreferrer"&gt;requires attribution&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Copyleft Licenses - The "Share Alike" Rule
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Alex takes your Lego spaceship, adds a cool warp drive, and improves the laser cannon. Thanks to your "share alike" rule, Alex shares the enhanced spaceship with you, and now you can both enjoy an even better version. This continuous sharing leads to amazing creations neither of you could have built alone.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Imagine you build an awesome Lego spaceship with unique features—a rotating laser cannon and hidden compartments. You tell Alex, &lt;code&gt;You can add more pieces or change it, but if you do, you have to share your new creation with me too, and make sure you keep the same rules I have.&lt;/code&gt; This way, any improvements Alex makes are shared with you under the same conditions.&lt;/p&gt;

&lt;p&gt;In software, this is similar to a copyleft license like the &lt;a href="https://www.gnu.org/licenses/gpl-3.0.en.html" rel="noopener noreferrer"&gt;GNU General Public License (GPL)&lt;/a&gt;. If someone uses code licensed under the GPL and makes it better, they must also share their improved code with others under the same license. This encourages ongoing sharing and ensures that the software and its enhancements remain available to everyone.&lt;/p&gt;

&lt;p&gt;Some people think that using GPL-licensed code means they can't sell their software, but that's not true (&lt;a href="https://www.gnu.org/licenses/gpl-faq.en.html#DoesTheGPLAllowMoney" rel="noopener noreferrer"&gt;GPL FAQ on selling software&lt;/a&gt;). You can sell your software, but you must also provide the source code under the same GPL license. This approach fosters a community where everyone benefits from each other's contributions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Strong Copyleft for Network Software - The Affero GPL
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Alex takes your online Lego guide, adds new sections, and hosts it on his website. Because of your rule, he shares his improved guide with you, ensuring that you both benefit from the enhancements.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Imagine you create an online guide to building Lego models and say to Alex, &lt;code&gt;You can use and change my guide, but if you make it better and share it with others, even online, you need to share your changes with me.&lt;/code&gt; This ensures that improvements are shared, no matter how they are distributed.&lt;/p&gt;

&lt;p&gt;This is like the &lt;a href="https://www.gnu.org/licenses/agpl-3.0.en.html" rel="noopener noreferrer"&gt;GNU Affero General Public License (AGPL)&lt;/a&gt;. It's similar to the GPL but adds that if you use the software over a network (like a web server), you must make the source code available to users interacting with it.&lt;/p&gt;

&lt;p&gt;Some think the AGPL restricts the use of software in web applications. While it does require sharing modifications when the software is used over a network, it doesn't prevent its use in web services (&lt;a href="https://www.gnu.org/licenses/gpl-faq.en.html#AGPLv3RequireSourceOnline" rel="noopener noreferrer"&gt;AGPL FAQ&lt;/a&gt;). It ensures that all users, even those accessing the software remotely, benefit from improvements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Lesser Copyleft Licenses - Sharing Core Components
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Alex uses your Lego gears in a complex clock he builds. He doesn't have to share the design of his clock, but when he improves the gears to be more efficient, he shares those improvements with you. You both benefit from better gears, while Alex's clock design remains his own.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Suppose you build a special set of Lego gears and say to Alex,&lt;br&gt;
&lt;code&gt;You can use my gears in your creations, and if you improve the gears themselves, please share those improvements. But you don't have to share your entire creation.&lt;/code&gt; This encourages Alex to use and enhance the gears while allowing him to keep his own designs private.&lt;/p&gt;

&lt;p&gt;This is like the &lt;a href="https://www.gnu.org/licenses/lgpl-3.0.html" rel="noopener noreferrer"&gt;GNU Lesser General Public License (LGPL)&lt;/a&gt;. It's often used for software libraries. If someone modifies the library, they must share those changes under the LGPL, but they can use the library in their own software without having to release their entire program's source code.&lt;/p&gt;

&lt;p&gt;People sometimes think the LGPL allows them to ignore copyleft requirements entirely. However, any modifications to the LGPL-licensed components must still be shared under the same license (&lt;a href="https://www.gnu.org/licenses/gpl-faq.en.html#WhatDoesLGPLPermit" rel="noopener noreferrer"&gt;LGPL FAQ&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Middle Ground Licenses - Balancing Sharing and Privacy
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Alex uses your Lego engine in his custom car model. He tweaks the engine for better performance and shares those improvements with you. However, he keeps his car design private. This way, the core engine gets better for both of you, while Alex's unique work remains his.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Consider if you say to Alex, &lt;code&gt;You can use my special Lego engine in your own creations, but if you change the engine itself, you need to share those changes with me. However, you can keep the rest of your creation to yourself.&lt;/code&gt; This way, the core part stays open, but Alex can keep his own creations private.&lt;/p&gt;

&lt;p&gt;This is like the &lt;a href="https://www.mozilla.org/en-US/MPL/2.0/" rel="noopener noreferrer"&gt;Mozilla Public License (MPL)&lt;/a&gt;. It's a compromise between copyleft and permissive licenses. It requires that any changes to the original code are shared under the same license but allows new code that is added to remain under a different license.&lt;/p&gt;

&lt;p&gt;Some think the MPL forces them to open source their entire project. In fact, only modifications to MPL-licensed code need to be shared, not your entire codebase (&lt;a href="https://www.mozilla.org/en-US/MPL/2.0/FAQ/" rel="noopener noreferrer"&gt;MPL FAQ&lt;/a&gt;). This allows for collaboration on core components while protecting proprietary elements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Licenses Focusing on Collaboration and Protection
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;Alex enhances your Lego robot with voice control. He shares his improvements and includes a note about his changes. Because of your agreement, you both feel safe using and modifying the robot without fear of legal issues, leading to more innovation.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Imagine you say to Alex, &lt;code&gt;You can use my Lego robot and change it if you like, but let's agree not to argue over who built which part. Also, please tell me about any big changes you make, and don't sue me over ideas used in this robot.&lt;/code&gt; This helps prevent disagreements and encourages transparency and cooperation.&lt;/p&gt;

&lt;p&gt;This is similar to the &lt;a href="https://www.apache.org/licenses/LICENSE-2.0" rel="noopener noreferrer"&gt;Apache License 2.0&lt;/a&gt;. Others can use and modify the code, but there are rules to prevent disputes, like not suing each other over patents (which are like ideas or inventions).&lt;/p&gt;

&lt;p&gt;Some believe the Apache License is too restrictive because of its patent clauses. In reality, these clauses are there to protect users from patent litigation, making it safer to use the software (&lt;a href="https://www.apache.org/foundation/license-faq.html" rel="noopener noreferrer"&gt;Apache License FAQ&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding Some Fun
&lt;/h3&gt;

&lt;p&gt;Sometimes, people create licenses that are a bit humorous to make a point or just for fun. Imagine you just tell Alex, &lt;code&gt;Do whatever you want with my Lego&lt;/code&gt; That's it—no rules at all.&lt;/p&gt;

&lt;p&gt;This is like the &lt;strong&gt;Do What the Fuck You Want to Public License&lt;/strong&gt; (&lt;a href="http://www.wtfpl.net/about/" rel="noopener noreferrer"&gt;WTFPL&lt;/a&gt;). It's a very permissive license that allows anyone to do anything with the code. While it's humorous, it's important to note that such licenses may not be legally robust in all jurisdictions. Because it's so informal, some think the WTFPL isn't a real license. However, it is recognized by the Open Source Initiative, though its legal enforceability can be questionable.&lt;/p&gt;

&lt;h3&gt;
  
  
  What Happens If You Switch Licenses Mid-Game
&lt;/h3&gt;

&lt;p&gt;Imagine you've been sharing your Lego creations with Alex under one set of rules, and partway through, you decide to change them. Perhaps you initially said to Alex, &lt;code&gt;Do whatever you want&lt;/code&gt; but now you want him to share his improvements. After seeing amazing things Alex has done with your Lego creations without sharing back, you decide to change your rules to require sharing improvements. For future creations, Alex now knows he needs to share changes. But for the creations already shared, the old rules still apply, and he can keep his modifications private if he wishes.&lt;/p&gt;

&lt;p&gt;I actually went through this experience with my open-source project, &lt;a href="https://github.com/hcavarsan/kftray" rel="noopener noreferrer"&gt;KFTray&lt;/a&gt;. When I first started building it, I was like someone who just wanted to share their Lego creation with friends—I chose the MIT license because it was simple and permissive. It was like saying, "Here's my Lego set, do whatever you want with it!"&lt;/p&gt;

&lt;p&gt;But as the project grew and I saw how others were using it, I realized I wanted to ensure that improvements would be shared back with the community. It's like noticing that while Alex was making amazing modifications to your Lego creation, those improvements weren't being shared with you who might benefit from them. So, I decided to switch to the GPL 3.0 license through &lt;a href="https://github.com/hcavarsan/kftray/pull/322" rel="noopener noreferrer"&gt;this pull request&lt;/a&gt; — essentially changing the rules to say, "You can still play with and modify these Lego pieces, but now you need to share your improvements with me."&lt;/p&gt;

&lt;p&gt;In software, changing the license of your project is possible but can be complicated. If you're the sole owner of the code, you can relicense it as you wish. However, if others have contributed, you'll need their permission to change the license on their contributions.&lt;/p&gt;

&lt;p&gt;Some think they can unilaterally change the license without affecting existing users. While you can change the license for future versions, the old versions remain under the original license, and users can continue to use them under those terms (&lt;a href="https://opensource.stackexchange.com/questions/1435/can-i-change-the-license-of-a-project-after-its-been-released" rel="noopener noreferrer"&gt;Changing a License&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Mixing and Matching - License Compatibility
&lt;/h3&gt;

&lt;p&gt;Sometimes, you want to combine your Lego spaceship with Alex's Lego castle to make an even bigger creation. But if you have different rules for sharing, it might get complicated. You want to merge your GPL-licensed Lego spaceship with Alex's permissively licensed castle. To share the combined creation, you both need to agree on a license that respects both sets of rules. Otherwise, you might not be able to share the new creation with others.&lt;/p&gt;

&lt;p&gt;In software, combining code with different licenses can be tricky. Some licenses are compatible, meaning the code can be combined without issues. Others are incompatible, and combining them could lead to legal problems.&lt;/p&gt;

&lt;p&gt;Many think that all open source licenses are compatible. In reality, licenses like the GPL are not compatible with some permissive licenses when it comes to distributing combined works (&lt;a href="https://www.gnu.org/licenses/gpl-faq.en.html#WhatIsCompatible" rel="noopener noreferrer"&gt;GPL Compatibility&lt;/a&gt;). It's important to understand the licenses involved to avoid accidental misuse.&lt;/p&gt;

&lt;h3&gt;
  
  
  Why Licenses Matter - Fair Play and Collaboration
&lt;/h3&gt;

&lt;p&gt;Licenses help protect creators and guide users. They set clear expectations, fostering an environment where everyone knows how they can use, modify, and share creations.&lt;/p&gt;

&lt;p&gt;Some people think licenses are unnecessary or just legal jargon. But without clear licenses, users might unknowingly break laws, and creators might not have their rights respected (&lt;a href="https://opensource.guide/legal/" rel="noopener noreferrer"&gt;The Importance of Open Source Licenses&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;By understanding these licenses, we can choose how we want to share our work and collaborate with others. Whether we're like Alex, deciding how to share our Lego spaceship, or someone using others' creations, knowing the rules helps us contribute to a community where everyone can create, improve, and enjoy together.&lt;/p&gt;

&lt;h3&gt;
  
  
  Both Lego and Code
&lt;/h3&gt;

&lt;p&gt;Licenses are like the rules we agree on when sharing our Lego creations. They help us play fairly, encourage sharing, and protect each other. Remember, just like sharing your Lego creations can lead to new and exciting builds you might not have imagined, sharing software under open source licenses can lead to amazing collaborations that benefit everyone.&lt;/p&gt;

&lt;h3&gt;
  
  
  Building Together
&lt;/h3&gt;

&lt;p&gt;Open source is all about collaboration and shared growth. By respecting the licenses and the intentions behind them, we foster an environment where creativity thrives. It's like a big playground where everyone brings their toys, and together, we build something greater than any one of us could alone.&lt;/p&gt;

&lt;p&gt;So next time you're using or creating open source software, think of it as sharing your Lego creations. Set the rules that feel right to you, understand others' rules, and enjoy the process of building something amazing together.&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>programming</category>
      <category>devops</category>
      <category>github</category>
    </item>
    <item>
      <title>Local Kubernetes Cluster - External traffic without Ingress Using Kftray</title>
      <dc:creator>Henrique Cavarsan</dc:creator>
      <pubDate>Tue, 01 Oct 2024 01:42:01 +0000</pubDate>
      <link>https://dev.to/hcavarsan/local-kubernetes-cluster-external-traffic-without-ingress-using-kftray-2n66</link>
      <guid>https://dev.to/hcavarsan/local-kubernetes-cluster-external-traffic-without-ingress-using-kftray-2n66</guid>
      <description>&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F80q29sttnf030xh5r561.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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F80q29sttnf030xh5r561.png" alt="Kftray Banner"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Hello. In this post, I'll show you how to set up a local Kubernetes cluster using Kind, Terraform, and Kftray. We'll keep all services inside the cluster, avoiding the need for ingress controllers or exposing services like NodePort or LoadBalancer. I'll also walk you through the Terraform code used in this setup.&lt;/p&gt;

&lt;p&gt;Terraform code used in this Blog Post: &lt;a href="https://github.com/hcavarsan/kftray-k8s-tf-example" rel="noopener noreferrer"&gt;https://github.com/hcavarsan/kftray-k8s-tf-example&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Keep Services Inside the Cluster?
&lt;/h2&gt;

&lt;p&gt;Exposing services externally can add complexity and potential security risks. For local development or secure environments, it's often better to keep everything internal. By using &lt;code&gt;kubectl port-forward&lt;/code&gt; and automating it with Kftray, we can access services running inside the cluster without exposing them to the outside world.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tools You'll Need
&lt;/h2&gt;

&lt;p&gt;Before starting, make sure you have the following installed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.docker.com/get-started" rel="noopener noreferrer"&gt;Docker&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.terraform.io/downloads.html" rel="noopener noreferrer"&gt;Terraform (v1.9.5)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/hcavarsan/kftray" rel="noopener noreferrer"&gt;Kftray&lt;/a&gt; (you can choose between the GUI or TUI version)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cloning the Repository
&lt;/h2&gt;

&lt;p&gt;First, clone the repository that contains the Terraform code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone https://github.com/hcavarsan/kftray-k8s-tf-example
&lt;span class="nb"&gt;cd &lt;/span&gt;kftray-k8s-tf-example/terraform
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Understanding the Terraform Code
&lt;/h2&gt;

&lt;p&gt;The Terraform code in this repository automates the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Creates a Kind Kubernetes cluster.&lt;/li&gt;
&lt;li&gt;Deploys Helm charts for Argo CD, Prometheus, Alertmanager, Grafana, and Jaeger.&lt;/li&gt;
&lt;li&gt;Sets up service annotations for Kftray to auto-import port-forward configurations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Project Structure
&lt;/h3&gt;

&lt;p&gt;Here's how the project is organized:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kftray-k8s-tf-example
├── terraform
│   ├── helm.tf
│   ├── outputs.tf
│   ├── locals.tf
│   ├── providers.tf
│   ├── variables.tf
│   ├── templates
│   │   ├── argocd-values.yaml.tpl
│   │   ├── grafana-values.yaml.tpl
│   │   ├── jaeger-values.yaml.tpl
│   │   └── prometheus-values.yaml.tpl
│   └── kind.tf
├── Makefile
├── docs
│   ├── kftray.gif
│   └── kftui.gif
└── README.md
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  providers.tf
&lt;/h3&gt;

&lt;p&gt;This file specifies the Terraform providers we'll use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;terraform&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;required_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 1.0.0"&lt;/span&gt;

  &lt;span class="nx"&gt;required_providers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;kind&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"tehcyx/kind"&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"0.4.0"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;helm&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/helm"&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 2.0.0"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;kubernetes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/kubernetes"&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 2.0.0"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;template&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;source&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"hashicorp/template"&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&amp;gt;= 2.0.0"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"kind"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"kubernetes"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;config_path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;kind_cluster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kubeconfig_path&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;provider&lt;/span&gt; &lt;span class="s2"&gt;"helm"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;kubernetes&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;config_path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;kind_cluster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kubeconfig_path&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;kind&lt;/strong&gt;: Manages Kind clusters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;kubernetes&lt;/strong&gt;: Interacts with the Kubernetes cluster.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;helm&lt;/strong&gt;: Deploys Helm charts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;template&lt;/strong&gt;: Processes template files.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  variables.tf
&lt;/h3&gt;

&lt;p&gt;Defines variables used in the Terraform configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"cluster_name"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Name of the Kind cluster"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"kftray-cluster"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"kubernetes_version"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Version of the Kind node image"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"v1.30.4"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"kubeconfig_dir"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Directory to store the kubeconfig file"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"~/.kube"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;# Chart versions&lt;/span&gt;
&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"argocd_chart_version"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Version of the Argo CD Helm chart"&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"5.19.12"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"prometheus_chart_version"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The version of the Prometheus chart to deploy."&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"25.27.0"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"grafana_chart_version"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The version of the Grafana chart to deploy."&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"8.5.0"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;variable&lt;/span&gt; &lt;span class="s2"&gt;"jaeger_chart_version"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"The version of the Jaeger chart to deploy."&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;string&lt;/span&gt;
  &lt;span class="nx"&gt;default&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"3.3.1"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  kind.tf
&lt;/h3&gt;

&lt;p&gt;Creates the Kind cluster:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"kind_cluster"&lt;/span&gt; &lt;span class="s2"&gt;"default"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cluster_name&lt;/span&gt;
  &lt;span class="nx"&gt;node_image&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"kindest/node:${var.kubernetes_version}"&lt;/span&gt;
  &lt;span class="nx"&gt;kubeconfig_path&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;pathexpand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"${var.kubeconfig_dir}/kind-config-${var.cluster_name}"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="nx"&gt;wait_for_ready&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;

  &lt;span class="nx"&gt;kind_config&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;kind&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Cluster"&lt;/span&gt;
    &lt;span class="nx"&gt;api_version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"kind.x-k8s.io/v1alpha4"&lt;/span&gt;

    &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"control-plane"&lt;/span&gt;

      &lt;span class="nx"&gt;extra_port_mappings&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;container_port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
        &lt;span class="nx"&gt;host_port&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;
        &lt;span class="nx"&gt;protocol&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"TCP"&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="nx"&gt;node&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;role&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"worker"&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;name&lt;/strong&gt;: Cluster name.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;node_image&lt;/strong&gt;: Kubernetes version.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;kubeconfig_path&lt;/strong&gt;: Where to store the kubeconfig file.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;wait_for_ready&lt;/strong&gt;: Wait until the cluster is ready.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;kind_config&lt;/strong&gt;: Custom Kind configuration.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  locals.tf
&lt;/h3&gt;

&lt;p&gt;Defines local variables and service configurations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;locals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;services&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;argocd&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;namespace&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"argocd"&lt;/span&gt;
      &lt;span class="nx"&gt;repository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"https://argoproj.github.io/argo-helm"&lt;/span&gt;
      &lt;span class="nx"&gt;chart&lt;/span&gt;      &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"argo-cd"&lt;/span&gt;
      &lt;span class="nx"&gt;version&lt;/span&gt;    &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;var&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;argocd_chart_version&lt;/span&gt;
      &lt;span class="nx"&gt;kftray&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;alias&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"argocd"&lt;/span&gt;
          &lt;span class="nx"&gt;local_port&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"16080"&lt;/span&gt;
          &lt;span class="nx"&gt;target_port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"http"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;# ... other services ...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="nx"&gt;services_values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;service_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt; &lt;span class="nx"&gt;in&lt;/span&gt; &lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;services&lt;/span&gt; &lt;span class="err"&gt;:&lt;/span&gt;
    &lt;span class="nx"&gt;service_name&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;templatefile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"${path.module}/templates/${service_name}-values.yaml.tpl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;kftray&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;service&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kftray&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;services&lt;/strong&gt;: A map of services to deploy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;kftray&lt;/strong&gt;: Port-forward configurations for Kftray.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;services_values&lt;/strong&gt;: Processes Helm values templates for each service.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  helm.tf
&lt;/h3&gt;

&lt;p&gt;Deploys the services using Helm:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"helm_release"&lt;/span&gt; &lt;span class="s2"&gt;"services"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;depends_on&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;kind_cluster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;default&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="nx"&gt;for_each&lt;/span&gt;         &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;services&lt;/span&gt;
  &lt;span class="nx"&gt;name&lt;/span&gt;             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;
  &lt;span class="nx"&gt;namespace&lt;/span&gt;        &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;namespace&lt;/span&gt;
  &lt;span class="nx"&gt;create_namespace&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
  &lt;span class="nx"&gt;repository&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;repository&lt;/span&gt;
  &lt;span class="nx"&gt;chart&lt;/span&gt;            &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;chart&lt;/span&gt;
  &lt;span class="nx"&gt;version&lt;/span&gt;          &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;version&lt;/span&gt;

  &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;local&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;services_values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;each&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
  &lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;for_each&lt;/strong&gt;: Iterates over each service.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;name&lt;/strong&gt;: Release name.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;namespace&lt;/strong&gt;: Kubernetes namespace.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;repository&lt;/strong&gt;: Helm chart repository.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;chart&lt;/strong&gt;: Helm chart name.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;version&lt;/strong&gt;: Chart version.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;values&lt;/strong&gt;: Custom values for the Helm chart.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  templates/
&lt;/h3&gt;

&lt;p&gt;Contains Helm values templates for each service (e.g., &lt;code&gt;argocd-values.yaml.tpl&lt;/code&gt;). These templates inject the Kftray annotations into the service definitions.&lt;/p&gt;

&lt;h3&gt;
  
  
  outputs.tf
&lt;/h3&gt;

&lt;p&gt;Defines outputs for the Terraform run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"endpoint"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"API endpoint for the Kind cluster."&lt;/span&gt;
  &lt;span class="nx"&gt;value&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;kind_cluster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;endpoint&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"kubeconfig"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Kubeconfig file for the Kind cluster."&lt;/span&gt;
  &lt;span class="nx"&gt;value&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;kind_cluster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;kubeconfig&lt;/span&gt;
  &lt;span class="nx"&gt;sensitive&lt;/span&gt;   &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;output&lt;/span&gt; &lt;span class="s2"&gt;"credentials"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"Credentials for authenticating with the Kind cluster."&lt;/span&gt;
  &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;client_certificate&lt;/span&gt;     &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;kind_cluster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client_certificate&lt;/span&gt;
    &lt;span class="nx"&gt;client_key&lt;/span&gt;             &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;kind_cluster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;client_key&lt;/span&gt;
    &lt;span class="nx"&gt;cluster_ca_certificate&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;kind_cluster&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;cluster_ca_certificate&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="nx"&gt;sensitive&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Applying the Terraform Configuration
&lt;/h2&gt;

&lt;p&gt;To apply the Terraform configuration and set up the cluster, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make apply
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initialize Terraform.&lt;/li&gt;
&lt;li&gt;Create the Kind cluster.&lt;/li&gt;
&lt;li&gt;Deploy the Helm charts.&lt;/li&gt;
&lt;li&gt;Set up the service annotations.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Installing Kftray
&lt;/h2&gt;

&lt;p&gt;Go to the &lt;a href="https://github.com/hcavarsan/kftray" rel="noopener noreferrer"&gt;Kftray GitHub page&lt;/a&gt; and follow the installation instructions for your operating system.&lt;/p&gt;

&lt;h2&gt;
  
  
  Importing Port-Forward Configurations into Kftray
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Using Kftray GUI
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open Kftray and click the tray icon to open the main window.&lt;/li&gt;
&lt;li&gt;Click the menu icon at the bottom left corner.&lt;/li&gt;
&lt;li&gt;Select "Auto Import."&lt;/li&gt;
&lt;li&gt;Click "Set kubeconfig" and choose the kubeconfig file created by Terraform (usually &lt;code&gt;~/.kube/kind-config-kftray-cluster&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Select the context &lt;code&gt;kftray-cluster&lt;/code&gt; from the dropdown menu.&lt;/li&gt;
&lt;li&gt;Click "Import" to load the port-forward settings.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgkrvd71jre34vge7f7la.gif" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgkrvd71jre34vge7f7la.gif" alt="Kftray Banner"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After importing, you can start port forwarding by toggling the switch next to each service or by clicking "Start All."&lt;/p&gt;

&lt;h3&gt;
  
  
  Using Kftui (Terminal Interface)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Set the &lt;code&gt;KUBECONFIG&lt;/code&gt; environment variable:
&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;export &lt;/span&gt;&lt;span class="nv"&gt;KUBECONFIG&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"~/.kube/kind-config-kftray-cluster"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Start Kftui:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   kftui
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Press &lt;code&gt;Tab&lt;/code&gt; to access the top menu and select "Auto Import."&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;Ctrl+A&lt;/code&gt; to select all configurations.&lt;/li&gt;
&lt;li&gt;Press &lt;code&gt;F&lt;/code&gt; to start all port forwards.&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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpj66296vgfaalg960mkk.gif" 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%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpj66296vgfaalg960mkk.gif" alt="kftui"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Accessing Your Services Locally
&lt;/h2&gt;

&lt;p&gt;With port forwarding set up, you can access your services on your local machine:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Argo CD&lt;/strong&gt;: &lt;a href="http://localhost:16080" rel="noopener noreferrer"&gt;http://localhost:16080&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prometheus&lt;/strong&gt;: &lt;a href="http://localhost:19090" rel="noopener noreferrer"&gt;http://localhost:19090&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alertmanager&lt;/strong&gt;: &lt;a href="http://localhost:19093" rel="noopener noreferrer"&gt;http://localhost:19093&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Grafana&lt;/strong&gt;: &lt;a href="http://localhost:13080" rel="noopener noreferrer"&gt;http://localhost:13080&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Jaeger&lt;/strong&gt;: &lt;a href="http://localhost:15090" rel="noopener noreferrer"&gt;http://localhost:15090&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Custom Kftray Settings
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Adjusting Kftray Port Forwarding Settings
&lt;/h3&gt;

&lt;p&gt;To customize how Kftray forwards ports, edit the &lt;code&gt;locals.tf&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;locals&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;services&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;argocd&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;kftray&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="nx"&gt;alias&lt;/span&gt;       &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"argocd"&lt;/span&gt;
          &lt;span class="nx"&gt;local_port&lt;/span&gt;  &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"16080"&lt;/span&gt;
          &lt;span class="nx"&gt;target_port&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"http"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="c1"&gt;# Other services...&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;alias&lt;/strong&gt;: The name displayed in Kftray.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;local_port&lt;/strong&gt;: The port on your machine to access the service.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;target_port&lt;/strong&gt;: The service's port or port name inside the cluster.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Cleaning Up
&lt;/h2&gt;

&lt;p&gt;If you want to destroy the cluster and remove all resources, run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;make destroy
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will tear down the cluster and delete all the resources created by Terraform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By keeping all services inside the cluster and using Kftray for port forwarding, we create a simpler and more secure environment. This setup is useful for local development and situations where you want to avoid exposing services externally.&lt;/p&gt;

&lt;p&gt;Feel free to explore and modify the Terraform code to suit your needs. If you have any questions or need help, feel free to reach out.&lt;/p&gt;

&lt;p&gt;Thanks for reading. You can find more of my work or get in touch on &lt;a href="https://github.com/hcavarsan" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>rust</category>
      <category>devops</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Debugging HTTP Traffic in kubectl port-forward with KFtray v0.11.7</title>
      <dc:creator>Henrique Cavarsan</dc:creator>
      <pubDate>Fri, 14 Jun 2024 15:01:40 +0000</pubDate>
      <link>https://dev.to/hcavarsan/debugging-http-traffic-in-kubectl-port-forward-with-kftray-v0117-2p1d</link>
      <guid>https://dev.to/hcavarsan/debugging-http-traffic-in-kubectl-port-forward-with-kftray-v0117-2p1d</guid>
      <description>&lt;p&gt;KFtray is a  application that can be integrated into the system tray for easy interaction with kubectl port-forward commands. A additional feature has joined recently in new version 0.11.7, one that can make HTTP traffic traces logs; this is an new method that simplifies debugging. This article provides a short guide on how to get started with the new feature.&lt;/p&gt;

&lt;h2&gt;
  
  
  New in v0.11.7
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Toggle HTTP Logs:&lt;/strong&gt; Easily enable/disable HTTP logs for configurations, saved in &lt;code&gt;$HOME/.kftray/http_logs/{config_id}_{local_port}&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Clean Logs Folder:&lt;/strong&gt; New button to tidy up the logs folder.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Logging Controls:&lt;/strong&gt; Buttons to turn HTTP logging on or off for each configuration.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open Logs with Default Editor:&lt;/strong&gt; Icon button to open HTTP logs with your default OS text editor.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trace IDs for Requests and Responses:&lt;/strong&gt; Each request and response in the log has the same trace ID to help identify linked requests and responses when handling multiple parallel requests.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Better Connection Reliability:&lt;/strong&gt; Improvements in the KFtray server and desktop client.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smaller Bundle Sizes:&lt;/strong&gt; More efficient installation.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Using the New Feature - HTTP Traffic Logging
&lt;/h2&gt;

&lt;p&gt;To utilize the new HTTP traffic logging feature, ensure you have the latest version of KFtray installed. Visit the &lt;a href="https://github.com/hcavarsan/kftray/releases" rel="noopener noreferrer"&gt;GitHub releases page&lt;/a&gt; and download the latest version of KFtray for your operating system. Follow the installation instructions specific to your OS to complete the setup.&lt;/p&gt;

&lt;p&gt;Once installed, Ensure the version number displayed in the logo icon tooltip matches the latest release &lt;code&gt;v0.11.7&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Open KFtray
&lt;/h3&gt;

&lt;p&gt;Launch KFtray by clicking its icon or typing &lt;code&gt;kftray&lt;/code&gt; in the terminal if you installed it using Homebrew..This will open the main interface when you click the system tray icon, where you can manage your configurations.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Turn On HTTP Logging
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Open Settings:&lt;/strong&gt; Click the KFtray icon in your system tray and select the configuration panel from the menu.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Start Port Forward&lt;/strong&gt;: Toggle the switch button to enable the configured port forwarding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pick a Configuration:&lt;/strong&gt; In the same row of the switch button, click the hamburger icon to open the configurations from the forwarded port.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Enable Logging:&lt;/strong&gt; Locate the "Enable HTTP Logging"  and click it to turn on HTTP logging for that configuration.&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%2Fkftray.app%2Fimg%2Fhttptraffic1.gif" 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%2Fkftray.app%2Fimg%2Fhttptraffic1.gif" alt="Enable HTTP Logging"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: View HTTP Logs
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Find Logs:&lt;/strong&gt; HTTP logs are automatically saved in the directory &lt;code&gt;$HOME/.kftray/http_logs/{config_id}_{local_port}&lt;/code&gt;. Each log file is named based on the configuration ID and local port for easy identification.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Open Logs:&lt;/strong&gt; To view the logs, click the log icon button next to your configuration. This will open the log file in your default text editor, allowing you to inspect the HTTP requests and responses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Trace IDs:&lt;/strong&gt; Each request and response in the log has the same trace ID, making it easier to identify linked requests and responses when handling multiple parallel requests.&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%2Fkftray.app%2Fimg%2Fhttptraffic2.gif" 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%2Fkftray.app%2Fimg%2Fhttptraffic2.gif" alt="Access HTTP Logs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  HTTP Logs Sample
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="nv"&gt;$HOME&lt;/span&gt;/.kftray/http_sniff/1_8080.log

  &lt;span class="nt"&gt;----------------------------------------&lt;/span&gt;
  Trace ID: 5525d312-5582-46ad-85d1-0fd3710f824e
  Request at: 2024-06-13T15:34:09.756706+00:00
  Method: GET
  Path: /json
  Version: 1

  Headers:
  Host: 127.0.0.1:8081
  Connection: keep-alive
  sec-ch-ua: &lt;span class="s2"&gt;"Not/A)Brand"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"8"&lt;/span&gt;, &lt;span class="s2"&gt;"Chromium"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"126"&lt;/span&gt;, &lt;span class="s2"&gt;"Google Chrome"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"126"&lt;/span&gt;
  sec-ch-ua-mobile: ?0
  sec-ch-ua-platform: &lt;span class="s2"&gt;"macOS"&lt;/span&gt;
  Upgrade-Insecure-Requests: 1
  Accept: text/html,application/xhtml+xml,application/xml&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;q&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.9,image/avif,image/webp,image/apng,&lt;span class="k"&gt;*&lt;/span&gt;/&lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;q&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.8,application/signed-exchange&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;v&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;b3&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;q&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.7
  Sec-Fetch-Site: none
  Sec-Fetch-Mode: navigate
  Sec-Fetch-User: ?1
  Sec-Fetch-Dest: document
  Accept-Encoding: &lt;span class="nb"&gt;gzip&lt;/span&gt;, deflate, br, zstd
  Accept-Language: en-US,en&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;q&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.9,pt&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="nv"&gt;q&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.8


  Body:
  &amp;lt;empty&amp;gt;

  &lt;span class="nt"&gt;----------------------------------------&lt;/span&gt;
  Trace ID: 5525d312-5582-46ad-85d1-0fd3710f824e
  Response at: 2024-06-13T15:34:09.901304+00:00
  Took: 144 ms
  Status: 200

  Headers:
  Access-Control-Allow-Credentials: &lt;span class="nb"&gt;true
  &lt;/span&gt;Access-Control-Allow-Origin: &lt;span class="k"&gt;*&lt;/span&gt;
  Content-Length: 421
  Content-Type: application/json&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nv"&gt;encoding&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;utf-8
  Date: Thu, 13 Jun 2024 15:34:10 GMT


  Body:
  &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"slideshow"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
      &lt;span class="s2"&gt;"author"&lt;/span&gt;: &lt;span class="s2"&gt;"Yours Truly"&lt;/span&gt;,
      &lt;span class="s2"&gt;"date"&lt;/span&gt;: &lt;span class="s2"&gt;"date of publication"&lt;/span&gt;,
      &lt;span class="s2"&gt;"slides"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
        &lt;span class="o"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"title"&lt;/span&gt;: &lt;span class="s2"&gt;"Wake up to WonderWidgets!"&lt;/span&gt;,
          &lt;span class="s2"&gt;"type"&lt;/span&gt;: &lt;span class="s2"&gt;"all"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;,
        &lt;span class="o"&gt;{&lt;/span&gt;
          &lt;span class="s2"&gt;"items"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
            &lt;span class="s2"&gt;"Why &amp;lt;em&amp;gt;WonderWidgets&amp;lt;/em&amp;gt; are great"&lt;/span&gt;,
            &lt;span class="s2"&gt;"Who &amp;lt;em&amp;gt;buys&amp;lt;/em&amp;gt; WonderWidgets"&lt;/span&gt;
          &lt;span class="o"&gt;]&lt;/span&gt;,
          &lt;span class="s2"&gt;"title"&lt;/span&gt;: &lt;span class="s2"&gt;"Overview"&lt;/span&gt;,
          &lt;span class="s2"&gt;"type"&lt;/span&gt;: &lt;span class="s2"&gt;"all"&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
      &lt;span class="o"&gt;]&lt;/span&gt;,
      &lt;span class="s2"&gt;"title"&lt;/span&gt;: &lt;span class="s2"&gt;"Sample Slide Show"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
  &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Clean Logs Folder
&lt;/h3&gt;

&lt;p&gt;To manage disk space and keep your logs organized, you can clean the logs folder and check the size of the logs folder from kftray.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Open Main Menu:&lt;/strong&gt; Click the system tray icon to open the main window, then click the hamburger icon in the bottom-left corner. You should see a button  &lt;code&gt;Prune Logs (0.00 MB)&lt;/code&gt; that displays the size of the HTTP logs folder.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Prune Logs:&lt;/strong&gt; Click the &lt;code&gt;Prune Logs&lt;/code&gt; button to remove all the HTTP log files from the logs folder and reclaim disk space.&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%2Fkftray.app%2Fimg%2Fhttptraffic3.gif" 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%2Fkftray.app%2Fimg%2Fhttptraffic3.gif" alt="Prune Logs Folder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Use Cases
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Debugging CLI Tools
&lt;/h3&gt;

&lt;p&gt;When using CLI tools that abstract HTTP calls, such as LocalStack, it can be challenging to debug the underlying HTTP requests and responses. HTTP logging in KFtray can help you capture and analyze these interactions.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; If you're using a CLI tool like LocalStack to simulate AWS services locally, enable HTTP logging for the configurations that interact with LocalStack. The logs will capture all HTTP requests and responses made by the CLI tool, including trace IDs to link related requests and responses. This makes it easier to debug issues and understand the behavior of the CLI tool.&lt;/p&gt;

&lt;h3&gt;
  
  
  Save History of HTTP Requests and Don't Lose Made Requests
&lt;/h3&gt;

&lt;p&gt;By enabling HTTP logging, you can save a history of all HTTP requests and responses. This ensures that you don't lose any made requests, which is especially useful for debugging and auditing purposes.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; If you need to review past interactions or troubleshoot issues that occurred previously, the saved logs will provide a complete history of HTTP traffic, including trace IDs to link related requests and responses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Fixing Microservices Issues
&lt;/h3&gt;

&lt;p&gt;When developing a microservice architecture, use HTTP logging to view detailed request and response data. This helps identify issues in interactions between services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; If a service interaction fails intermittently, enable HTTP logging for the configurations involved. Use the logs to pinpoint the problem, such as incorrect request parameters or unexpected response formats. The trace IDs will help you link related requests and responses.&lt;/p&gt;

&lt;h3&gt;
  
  
  Security Audits
&lt;/h3&gt;

&lt;p&gt;Capture and review HTTP traffic logs to ensure no sensitive data is exposed in requests or responses. This is crucial for maintaining security compliance.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Enable HTTP logging for configurations handling sensitive data. Regularly review the logs to verify that no private information is being leaked. The trace IDs will help you track the flow of sensitive data through your system.&lt;/p&gt;

&lt;h3&gt;
  
  
  Solving Intermittent Problems
&lt;/h3&gt;

&lt;p&gt;Capture HTTP traffic during the occurrence of intermittent issues to find patterns or anomalies that may be causing the problems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; Users report sporadic issues with your web application. Enable HTTP logging for the related configurations and capture traffic during the problem periods. Analyze the logs to identify any patterns or anomalies. Use the trace IDs to correlate requests and responses during the issue periods.&lt;/p&gt;

&lt;h3&gt;
  
  
  Boosting Performance
&lt;/h3&gt;

&lt;p&gt;Monitor HTTP logs to identify slow endpoints and optimize the performance of your application.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example:&lt;/strong&gt; If certain endpoints are slow, enable HTTP logging for those configurations. Use the logs to identify the bottlenecks and optimize the endpoints for better performance. Trace IDs will help you follow the request-response cycle and pinpoint delays.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrap-Up
&lt;/h2&gt;

&lt;p&gt;The new logging of HTTP traffic in KFtray v0.11.7 takes the work out of debugging and simplifies it. Turn logging on for your configurations and you'll be fixing issues in minutes. Trace IDs enable easy request and response correlation even when handling multiple requests in parallel.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Star us on &lt;a href="https://github.com/hcavarsan/kftray" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt; ⭐&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Quick Demo
&lt;/h3&gt;

&lt;p&gt;This video demonstrates the complete flow of this new feature.&lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/Z1rCFu3VZAQ"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>development</category>
      <category>rust</category>
    </item>
    <item>
      <title>Kubectl Port-forward Flow Explained</title>
      <dc:creator>Henrique Cavarsan</dc:creator>
      <pubDate>Mon, 15 Apr 2024 15:08:27 +0000</pubDate>
      <link>https://dev.to/hcavarsan/k8s-debugging-handling-multiple-port-forwards-from-tray-4id8</link>
      <guid>https://dev.to/hcavarsan/k8s-debugging-handling-multiple-port-forwards-from-tray-4id8</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Recently, I joined a discussion about how the &lt;code&gt;kubectl port-forward&lt;/code&gt; command works, which caught my attention because I have an app that improves some aspects of the native &lt;code&gt;kubectl port-forward&lt;/code&gt;. I made a public Mermaid chart to show the complete process of executing this command. I included everything from the authentication phase to sending a request through localhost that goes to the target pod via SPDY.&lt;/p&gt;

&lt;p&gt;I noticed this topic often comes up on various social networks, so I decided to write this article to share the diagram and explain the steps involved. I had two main reasons for writing this article:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;To share this information with those who are interested, especially since the official documentation doesn't cover this process in one place, making it hard to quickly get a full picture.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;To have a reference for myself for future use, so I can look back at this article when needed :D&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The diagram might be updated after its release to add more details or correct any mistakes I might have made (it happens :D). Feel free to point out any errors or add information if you find something wrong ;)&lt;/p&gt;

&lt;p&gt;You can view and edit the full diagram here: &lt;a href="https://www.mermaidchart.com/app/projects/a4818a6d-bba3-4ab8-bd02-18b6bf99795f/diagrams/3e4987a0-69eb-4585-8ef4-dcf3474fe25a/version/v0.1/edit" rel="noopener noreferrer"&gt;Mermaid Link&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Sequence Diagram Explained
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbk3l8p3ovtz5l7nbgsbb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbk3l8p3ovtz5l7nbgsbb.png" alt="Complete Diagram" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Full &lt;a href="https://www.mermaidchart.com/raw/3e4987a0-69eb-4585-8ef4-dcf3474fe25a?theme=dark&amp;amp;version=v0.1&amp;amp;format=svg" rel="noopener noreferrer"&gt;Mermaid SVG Link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I will start by explaining each step in the diagram, grouped into 5 sections: Initialization, Authentication &amp;amp; Authorization, Information Retrieval for Pod, Port-forwarding Session Establishment, Configuring iptables for Port Forwarding and SPDY Session for Port Forwarding&lt;/p&gt;

&lt;h3&gt;
  
  
  Initialization
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe3wtnu2hzg5n60hahrbn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe3wtnu2hzg5n60hahrbn.png" alt="Initialization" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The user initiates the port-forwarding process by executing &lt;code&gt;kubectl port-forward -n &amp;lt;namespace&amp;gt; &amp;lt;pod-name&amp;gt; &amp;lt;local-port&amp;gt;:&amp;lt;pod-port&amp;gt;&lt;/code&gt; via the CLI (Command-Line Interface).&lt;/p&gt;

&lt;h3&gt;
  
  
  Authentication &amp;amp; Authorization
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9bd0q80err1q9q5u0gpf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9bd0q80err1q9q5u0gpf.png" alt="Authentication &amp;amp; Authorization" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Upon receiving the command, the CLI sends a request to the Kubernetes API server to authenticate the user's tokens and verify permissions. This involves an initial connection establishment with a Bearer Token. The API server then verifies the token's validity and checks if the user has authorization to access the specified pod.&lt;/p&gt;

&lt;h3&gt;
  
  
  Information Retrieval for Pod
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fibhrkvvnjo7oqwv1c0tv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fibhrkvvnjo7oqwv1c0tv.png" alt="Pod Details" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To proceed with port-forwarding, the CLI retrieves essential details about the target pod by sending a GET request to the Kubernetes API server. Once received,&lt;/p&gt;

&lt;h3&gt;
  
  
  Port-forwarding Session Establishment
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foc7kmm41pan7oe0e3gio.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foc7kmm41pan7oe0e3gio.png" alt="Session" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The CLI initiates the port-forwarding session by sending a POST request to the Kubernetes API server, requesting the establishment of a port-forwarding connection for the specified pod. Upon receiving the request, the API server switches protocols to Websocket/SPDY, establishing a persistent connection with multiplexing capabilities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Configuring iptables for Port Forwarding
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F70dtoe52cqey47dp4vwo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F70dtoe52cqey47dp4vwo.png" alt="iptables" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Kubernetes API server instructs the Kubelet to configure iptables for port-forwarding. The Kubelet sets up iptables rules to redirect traffic from the specified pod port to the designated external port (local port in kubectl)&lt;/p&gt;

&lt;h3&gt;
  
  
  SPDY Session for Port Forwarding
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm3k92a9wzewmw0iwpl06.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm3k92a9wzewmw0iwpl06.png" alt="SPDY" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With the port-forwarding session established, the user interacts with the pod's application by sending requests through the Websocket/SPDY stream. The CLI wraps the user's request in a Websocket/SPDY frame, forwarding it to the Kubernetes API server. The API server then forwards the request to the Kubelet, which transmits it to the pod's port. The pod processes the request internally and responds, initiating a response flow back to the user through the established Websocket/SPDY session.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Feel free to edit the Mermaid chart here:&lt;/strong&gt; Mermaid Live Editor&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This article explains the &lt;code&gt;kubectl port-forward&lt;/code&gt; command, detailing each step from starting up and logging in to transferring data. It covers authentication, authorization, and the SPDY connection to show how it works in Kubernetes.&lt;/p&gt;

&lt;p&gt;While this article is meant to inform and not to promote, I'd like to share a link to &lt;strong&gt;kftray&lt;/strong&gt;, a project I developed that adds new features and improvements to &lt;code&gt;kubectl port-forward&lt;/code&gt;. If you're interested, you can check out &lt;strong&gt;kftray&lt;/strong&gt; on GitHub here: &lt;a href="https://github.com/hcavarsan/kftray" rel="noopener noreferrer"&gt;kftray on GitHub&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>sre</category>
      <category>devops</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Kubernetes Debugging: Handling Multiple kubectl port-forward from Tray</title>
      <dc:creator>Henrique Cavarsan</dc:creator>
      <pubDate>Thu, 28 Mar 2024 01:49:15 +0000</pubDate>
      <link>https://dev.to/hcavarsan/kubernetes-debugging-handling-multiple-kubectl-port-forward-from-tray-50ad</link>
      <guid>https://dev.to/hcavarsan/kubernetes-debugging-handling-multiple-kubectl-port-forward-from-tray-50ad</guid>
      <description>&lt;p&gt;As a developer working with Kubernetes, I often find myself with multiple port-forward open sessions to debug pods across namespaces. Keeping track of all those terminals can get chaotic quickly. To help streamline my debugging workflow, I created an open-source tool called KFTray that centralizes all your port forwards in a system tray. In this post, I demonstrate how can save developer time by comparing workflows with and without it.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pain of Kubernetes Debugging with Kubectl Port Forward
&lt;/h2&gt;

&lt;p&gt;As an SRE, one of my primary responsibilities is debugging Kubernetes applications and infrastructure. The go-to tool for debugging pods in Kubernetes is kubectl port-forward. However, this utility has several limitations that often make the debugging process tedious and frustrating.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Lack of Auto-Reconnect for Unstable Connections&lt;/strong&gt;&lt;br&gt;
The kubectl port-forward command does not automatically reconnect if the connection is interrupted for any reason. This means if there is an issue with the network or Kubernetes API server, the port forward will stop working, and I have to manually restart it. For debugging unstable applications, this missing feature results in a poor experience and loss of productivity.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;No UDP Support&lt;/strong&gt;&lt;br&gt;
Kubectl port-forward only supports TCP and does not natively support UDP. Many applications rely on UDP, so without support for UDP forwarding, debugging them is very difficult. We often have to modify applications to use TCP instead of UDP just for debugging purposes, which is far from ideal.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Single Pod Forwarding Only&lt;/strong&gt;&lt;br&gt;
The kubectl port-forward command can only forward ports for a single pod at a time. When debugging complex, multi-pod applications, this means I frequently have to open multiple terminal tabs to port forward to each pod individually. This process is tedious, difficult to manage, and negatively impacts productivity during debugging sessions.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Difficulty Keeping Configurations in Sync&lt;/strong&gt;&lt;br&gt;
On our team, we have port forwarding configurations defined in a shared Git repository so we can standardize them across projects. However, with kubectl, the only way to use these shared configurations is to manually download them and run them locally. This makes it difficult to keep everyone's configurations in sync and up-to-date.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Introducing KFtray: A Developer Tool for Kubernetes
&lt;/h2&gt;

&lt;p&gt;As a developer working with Kubernetes, managing multiple port forwards for debugging applications can quickly become tedious and time-consuming. To simplify this process, I created KFtray, an open-source system tray application that provides a user-friendly interface for handling Kubernetes port forwarding.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simplified Port Forward Management&lt;/strong&gt;&lt;br&gt;
KFtray allows developers to easily start, stop, and manage multiple port forwarding configurations simultaneously through an intuitive interface. Users can save configurations locally or sync them with a GitHub repository for team collaboration. KFtray automatically restarts pods as needed to maintain service continuity in the event of pod failure, improving reliability.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Customized Configuration&lt;/strong&gt;&lt;br&gt;
Developers can customize KFtray to use a specified local IP address instead of the default localhost for port forwarding. They can also enable TCP/UDP proxy forwarding through Kubernetes for additional flexibility. KFtray uses each operating system's keyring to securely store confidential information like API keys.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Staying Up-to-Date with Git Synchronization&lt;/strong&gt;&lt;br&gt;
For teams collaborating on Kubernetes applications, keeping port forwarding configurations in sync can be challenging. KFtray addresses this through an optional Git synchronization feature. Developers can connect KFtray to a GitHub repository containing their port forwarding configurations. KFtray will then automatically pull the latest configurations from that repository on an adjustable polling schedule.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improved Productivity&lt;/strong&gt;&lt;br&gt;
By simplifying the management of Kubernetes port forwarding, KFtray aims to make developers more productive. No longer do they have to manually restart pods or switch between multiple terminal windows to handle port forwarding. KFtray provides a single interface to control all their port forwarding needs.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Keep your configurations updated with Github Sync&lt;/strong&gt;&lt;br&gt;
KFtray allows developers to easily store and manage port forward configurations from local files or GitHub repositories. This means users can save a configuration once and reload it whenever needed, reducing repetitive work. Developers can also share configurations with team members by committing them to a GitHub repo.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simultaneous Port Forwards&lt;/strong&gt;&lt;br&gt;
A key pain point KFtray solves is the ability to run multiple port forwards simultaneously. Without a tool like KFtray, developers have to manually run each port forward separately in their terminal. KFtray handles running all port forwards in the background, freeing up the developer’s terminal. This is especially useful when debugging microservice-based applications that have many component services.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Convenient System Tray&lt;/strong&gt;&lt;br&gt;
KFtray runs in the system tray, providing an easy way to manage all port forwards in one place. From the system tray menu, developers can start, stop, restart or remove port forwards. KFtray also displays the status of each port forward, indicating if it is running or stopped. This convenient UI enhances productivity by giving developers quick access to manage and monitor their port forwards.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  A Case Study: Debugging Microservices With and Without KFtray
&lt;/h2&gt;

&lt;p&gt;As a developer focused on building microservices, I found the debugging process to be tedious and time-consuming. Each microservice has its own deployment, necessitating a separate port forward for debugging. Without an efficient tool to manage multiple port forwards, significant time was lost setting up and keeping configurations up to date.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The Situation Before&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Prior to using KFtray, I had to manually run a &lt;code&gt;kubectl port-forward&lt;/code&gt; command for each microservice I wanted to debug. If a pod restarted, the port forward would need to be re-established, causing further delays. When code was updated, the port forward configurations had to be manually updated to match, requiring diligent version control. Overall, managing the debugging infrastructure for microservices was inefficient and distracting.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A New Approach&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;KFtray simplified the debugging workflow by allowing me to define port forward configurations for each microservice in a central repository. With a single click, KFtray establishes all required port forwards, freeing me to focus on debugging my code. KFtray automatically reconnects port forwards when pods restart, and stays up-to-date with configuration changes through Git version control.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;KFtray is available for macOS and Linux users via Homebrew, and directly from the GitHub releases page for other systems. Here's how you can get started:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For macOS and Linux:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;
brew tap hcavarsan/kftray

brew &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--HEAD&lt;/span&gt; kftray
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For other systems, visit the &lt;a href="https://github.com/hcavarsan/kftray/releases"&gt;GitHub releases page&lt;/a&gt; for downloadable binaries.&lt;/p&gt;

&lt;h2&gt;
  
  
  Configuring Your First Port Forward
&lt;/h2&gt;

&lt;p&gt;In a few simple steps, you can configure your first port forward:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Launch the application&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Open the configuration panel from the tray icon&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt; &lt;strong&gt;Add a new configuration:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*   Give it a unique alias and set if you want to set the alias as domain to your forward
*    Indicate if the configuration is for a port forward for a service (common use) or a proxy (port forward to an endpoint via a Kubernetes cluster).
*   Specify the Kubernetes context
*   Define the namespace housing your service
*   Enter the service name
*   Choose TCP or UDP
*   Set the local and remote port numbers
*   Configure a custom local IP address (optional)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Activate Your Configuration&lt;/strong&gt;: With your configuration saved, simply click on the switch button in the main menu to start the port forward in a single por forward or in Start All to start all configurations at the same time .&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Demonstration:&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/nqEhmcKeCc4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Export configurations to a JSON file
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt; Open the main menu in the footer&lt;/li&gt;
&lt;li&gt; Select the &lt;code&gt;Export Local File&lt;/code&gt; option&lt;/li&gt;
&lt;li&gt; Choose a file name and location to save the JSON file&lt;/li&gt;
&lt;li&gt; The JSON file will contain all your current configurations&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can then import this JSON file at any time to restore your configurations.&lt;/p&gt;

&lt;p&gt;Example Json configuration File:&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="p"&gt;[&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;span class="nl"&gt;"service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"argocd-server"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"argocd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"local_port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8888&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"remote_port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8080&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test-cluster"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"workload_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;"service"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"protocol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"remote_address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&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;"local_address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"127.0.0.1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"alias"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"argocd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"domain_enabled"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&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;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;h2&gt;
  
  
  Sharing the configurations through Git
&lt;/h2&gt;

&lt;p&gt;now, with the local json saved, you can share your configurations with your team members by committing the JSON file to a Github repository. This allows for easy collaboration and synchronization of KFtray configurations across your team.&lt;/p&gt;

&lt;p&gt;To import and sync your github configs in kftray:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Open the application's main menu&lt;/li&gt;
&lt;li&gt; Select the button with github icon in the footer menu&lt;/li&gt;
&lt;li&gt; Enter the URL of your Git repository and path containing the JSON file&lt;/li&gt;
&lt;li&gt; If your GitHub repository is private, you will need to enter the private token. Credentials are securely saved in the SO keyring (Keychain on macOS). Kftray does not store or save credentials in any local file; they are only stored in the local keyring.&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Select the polling time for when Kftray will synchronize configurations and retrieve them from GitHub.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;KFtray will now sync with the Git repository to automatically import any new configurations or changes committed to the JSON file.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This allows you to quickly deploy any port forward changes to all team members. And if someone on your team adds a new configuration, it will be automatically synced to everyone else's KFtray.&lt;/p&gt;

&lt;p&gt;Demonstration: &lt;br&gt;
&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/BAdL7IzaEh8?start=6"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;h2&gt;
  
  
  Share Your Thoughts: Help Us Enhance KFtray with Your Feedback!
&lt;/h2&gt;

&lt;p&gt;We hope our app makes your work easier. Any ideas for improvement? We’re all ears!&lt;/p&gt;

&lt;p&gt;Star us on &lt;a href="https://github.com/hcavarsan/kftray"&gt;Github&lt;/a&gt; ⭐ &lt;/p&gt;

&lt;p&gt;Kftray Website: &lt;a href="https://kftray.app"&gt;https://kftray.app&lt;/a&gt;&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>development</category>
      <category>devops</category>
      <category>sre</category>
    </item>
    <item>
      <title>🔥 Enhance Your Kubernetes Tools with KFtray 0.8.0's Latest Features</title>
      <dc:creator>Henrique Cavarsan</dc:creator>
      <pubDate>Mon, 04 Mar 2024 00:35:13 +0000</pubDate>
      <link>https://dev.to/hcavarsan/enhance-your-kubernetes-tools-with-kftray-800s-latest-features-2389</link>
      <guid>https://dev.to/hcavarsan/enhance-your-kubernetes-tools-with-kftray-800s-latest-features-2389</guid>
      <description>&lt;p&gt;Hey everyone!&lt;/p&gt;

&lt;p&gt;Kftray is a small, open-source app designed to simplify managing multiple kubectl port forwards, especially for local development. This app is a menu bar GUI and is built using the Tauri framework - Rust for the backend and TypeScript for the frontend and can be found more information at &lt;a href="https://kftray.app/" rel="noopener noreferrer"&gt;https://kftray.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Just a quick update: KFtray has just been upgraded to version 0.8.0 🚀. This release is packed with features that will refine your development workflow and enhance your productivity when working with Kubernetes and multiples &lt;code&gt;kubectl port forward&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4wqm6aqdvycp56j8wg7s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4wqm6aqdvycp56j8wg7s.png" alt="kftray" width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;⚡️ &lt;strong&gt;What's New in KFtray 8.0.0&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The team has been hard at work and we've rolled out some exciting updates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Git Time Polling Synchronization&lt;/strong&gt;: Your projects will remain up-to-date effortlessly! The new polling feature allows you to adjust how frequently KFtray checks your repositories for changes, ensuring your kftray environment aligns with the latest commits in the git.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Enhanced Git Synchronization Slider&lt;/strong&gt;: Fine-tune your Git sync frequency with the integration of a convenient slider. You're now in full control of the polling rate, perfect for conserving system resources or getting real-time updates depending on your needs.&lt;br&gt;
&lt;br&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Sync History Timestamps&lt;/strong&gt;: With our improved tooltips, you'll have a clear and precise log of your synchronization timeline. Monitor when the last sync took place and plan for the next one with ease.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Custom Local Address Configuration&lt;/strong&gt;: Say goodbye to the restrictions of &lt;code&gt;localhost&lt;/code&gt;. Customize your development environment by setting up a local IP address that fits your project structure or network configuration.&lt;/li&gt;
&lt;/ul&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Quick-access URL Icon&lt;/strong&gt;: Navigate to your forwarded local URL in an instant. Our new icon in KFtray provides immediate access to your application in your default browser with just a click.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;🚀 &lt;strong&gt;Ongoing Enhancements&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Rest assured, we're not stopping here. Our commitment to refining git-based state management is ongoing, and we can't wait to share more enhancements with you in the near future.&lt;/p&gt;

&lt;p&gt;🔍 &lt;strong&gt;Get Your Hands on the Latest Release&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Curious to see the updates in action? We invite you to check out the latest release at: &lt;a href="https://github.com/hcavarsan/kftray/releases/tag/v0.8.0" rel="noopener noreferrer"&gt;KFtray 0.8.0 Release&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We value your feedback and are excited to see how these new features help you in your Kubernetes development journey. Stay tuned for more updates, and happy coding!&lt;/p&gt;

&lt;p&gt;-&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>opensource</category>
      <category>development</category>
      <category>kubectl</category>
    </item>
    <item>
      <title>Managing multiple kubectl port-forward configurations and sharing them via Git 📦</title>
      <dc:creator>Henrique Cavarsan</dc:creator>
      <pubDate>Tue, 27 Feb 2024 22:21:55 +0000</pubDate>
      <link>https://dev.to/hcavarsan/managing-multiple-kubectl-port-forward-configurations-and-sharing-them-via-git-1k1</link>
      <guid>https://dev.to/hcavarsan/managing-multiple-kubectl-port-forward-configurations-and-sharing-them-via-git-1k1</guid>
      <description>&lt;p&gt;&lt;code&gt;kubectl port-forward&lt;/code&gt; is an invaluable tool for developers working with Kubernetes, allowing for the exposure of local services through a tunnel. However, as the number of services grows, this manual method can become cumbersome. Common issues like terminal lock-up, tunnels lost after pod termination, and lack of support for UDP services can occur.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Kftray
&lt;/h2&gt;

&lt;p&gt;To overcome these challenges, we created Kftray, a graphic interface application developed with Rust and TypeScript using the Tauri framework. Kftray offers a more efficient way to manage port-forward tunnels in a Kubernetes environment.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2p2itqppfxutb2wy1sw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2p2itqppfxutb2wy1sw.png" alt="Kftray Demo" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Key Features
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Configuration Management&lt;/strong&gt;: Easily add, start, and stop multiple port-forward configurations.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Autocomplete&lt;/strong&gt;: Reduces the need to remember complex commands thanks to an autocomplete feature.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6hqa1fa2l3m3honl0nc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ff6hqa1fa2l3m3honl0nc.png" alt="Add Configs" width="800" height="586"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Configuration Export&lt;/strong&gt;: Export your settings to a JSON file and keep a backup for quick restorations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Json Example:&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="p"&gt;[&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;span class="nl"&gt;"alias"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"consul-ui"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kind-7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"local_port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"consul"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"protocol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"remote_port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"consul-ui"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"workload_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;"service"&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"alias"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"redis-gcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kind-6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"local_port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;26379&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"protocol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"udp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"remote_address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"redis-prod.gcp.internal"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"remote_port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6379&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"workload_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;"proxy"&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;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;h3&gt;
  
  
  Solutions for Common Issues
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Terminals Don't Get Locked&lt;/strong&gt;: Kftray operates independently of kubectl and won't lock up terminals. An internal relay server allows UDP services to be port-forwarded over TCP.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pod Failure Resilience&lt;/strong&gt;: The application redirects traffic to new pods when the old ones fail, providing continuous connection.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Access to Non-Kubernetes Internal Services&lt;/strong&gt;: Kftray can direct TCP traffic even for internal services not hosted on the Kubernetes cluster.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Git Sync Plus
&lt;/h2&gt;

&lt;p&gt;The latest version of Kftray &lt;a href="https://github.com/hcavarsan/kftray/releases/tag/v0.7.0"&gt;v0.7.1&lt;/a&gt; introduces a new feature: synchronizing configurations with a GitHub repository. As soon as updates are made to the JSON configuration file, just one click is needed for Kftray to apply them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa5kujhxqh83jwg3vdima.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa5kujhxqh83jwg3vdima.gif" alt="Github Sync" width="512" height="465"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started with Kftray
&lt;/h2&gt;

&lt;p&gt;To try out Kftray, visit our GitHub repository and follow the instructions for downloading and installation: &lt;a href="https://github.com/hcavarsan/kftray"&gt;Github Kftray&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Contributions Are Welcome
&lt;/h2&gt;

&lt;p&gt;We invite the community to collaborate on the Kftray project. If you find bugs or have ideas for new features, feel free to contribute. Your participation is crucial for making Kftray even better! &lt;a href="https://github.com/hcavarsan/kftray"&gt;Github Kftray&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;we plan to release updates with new features like pooling for synchronization and the ability to add multiple configuration repositories. That's all for now! I hope you find Kftray helpful! 🚀🎉&lt;/p&gt;

&lt;p&gt;If you do, please consider giving us a star on GitHub at &lt;a href="https://github.com/hcavarsan/kftray"&gt;Kftray&lt;/a&gt;. It really helps us! 🌟&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>devtool</category>
      <category>development</category>
    </item>
    <item>
      <title>KFtray: Manage Multiple kubectl Port Forwards with Ease from Your Menu Bar 🚀</title>
      <dc:creator>Henrique Cavarsan</dc:creator>
      <pubDate>Fri, 16 Feb 2024 16:22:38 +0000</pubDate>
      <link>https://dev.to/hcavarsan/kftray-manage-multiple-kubectl-port-forwards-with-ease-from-your-menu-bar-1dok</link>
      <guid>https://dev.to/hcavarsan/kftray-manage-multiple-kubectl-port-forwards-with-ease-from-your-menu-bar-1dok</guid>
      <description>&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/_1wyhZM1nxE"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/hcavarsan/kftray" rel="noopener noreferrer"&gt;KFtray&lt;/a&gt;, the new open-source tool for Kubernetes users. It simplifies managing your kubectl port forwards from the menu bar. See why it could be useful for your toolkit:&lt;/p&gt;

&lt;h2&gt;
  
  
  Kubectl Pain Points 🚨
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/hcavarsan/kftray" rel="noopener noreferrer"&gt;KFtray&lt;/a&gt; was developed with a clear objective in mind: simplifying the complexities associated with managing multiple &lt;code&gt;kubectl&lt;/code&gt; port forwards, enhancing the stability of these connections, and filling in the capabilities that &lt;code&gt;kubectl&lt;/code&gt; lacks. The motivation for &lt;a href="https://github.com/hcavarsan/kftray" rel="noopener noreferrer"&gt;KFtray&lt;/a&gt; stemmed from several identified issues:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Excessive Terminal Windows&lt;/strong&gt;: Managing numerous &lt;code&gt;kubectl&lt;/code&gt; port forwards can lead to a cluttered and unmanageable desktop environment, making efficient work challenging.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Unreliable Connections&lt;/strong&gt;: The instability caused by pod failures can disrupt port forward connections, further complicated by the absence of UDP forwarding support in &lt;code&gt;kubectl&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why &lt;a href="https://github.com/hcavarsan/kftray" rel="noopener noreferrer"&gt;KFtray&lt;/a&gt;?  ✅
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/hcavarsan/kftray" rel="noopener noreferrer"&gt;KFtray&lt;/a&gt; aims to address these challenges by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simplifying the Workflow&lt;/strong&gt;: It eradicates the clutter of numerous terminal windows, paving the way for a cleaner and more manageable working environment.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ensuring Reliability&lt;/strong&gt;: the app is designed to automatically re-establish connections when disruptions occur, maintaining a stable workflow regardless of pod status.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Expanding Capabilities&lt;/strong&gt;: By incorporating UDP forwarding and proxy functionality, &lt;a href="https://github.com/hcavarsan/kftray" rel="noopener noreferrer"&gt;KFtray&lt;/a&gt; offers a more comprehensive set of tools than what &lt;code&gt;kubectl&lt;/code&gt; alone provides.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Through these measures, &lt;a href="https://github.com/hcavarsan/kftray" rel="noopener noreferrer"&gt;KFtray&lt;/a&gt; seeks to enhance productivity and streamline the management of Kubernetes resources, making it a valuable tool for developers and system administrators alike.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Features 🌟
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Reliable Port Forwarding&lt;/strong&gt;: Ensures your services stay connected, even if disruptions occur.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Batch Forwarding&lt;/strong&gt;: Initiate multiple port forwardings with a single action.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Bypass kubectl&lt;/strong&gt;: Direct interaction with Kubernetes API for a smoother experience.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;TCP &amp;amp; UDP Support&lt;/strong&gt;: Compatibility with both protocol types for versatile service connections.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Easy Installation 🛠️
&lt;/h3&gt;

&lt;p&gt;ou can directly download it from the GitHub releases page at &lt;a href="https://github.com/hcavarsan/kftray/releases" rel="noopener noreferrer"&gt;https://github.com/hcavarsan/kftray/releases&lt;/a&gt;. But, for macOS and Linux users, installation via Homebrew is an option, check more details in repository &lt;a href="https://github.com/hcavarsan/kftray?tab=readme-ov-file#kftray" rel="noopener noreferrer"&gt;README&lt;/a&gt; &lt;/p&gt;

&lt;h2&gt;
  
  
  Configurations Management🔧
&lt;/h2&gt;

&lt;p&gt;Kftray stores configurations in a SQLite file in the user's home folder for easy export, import, and sharing the exported JSON file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started with &lt;a href="https://github.com/hcavarsan/kftray" rel="noopener noreferrer"&gt;KFtray&lt;/a&gt; ✨
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/hcavarsan/kftray" rel="noopener noreferrer"&gt;KFtray&lt;/a&gt; offers simplicity for Kubernetes port forwarding tasks, presented in an easily accessible format. It's a practical tool for any Kubernetes user seeking a more manageable and effective port forwarding solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Share Your Thoughts: Help Us Enhance KFtray with Your Feedback! 🌟
&lt;/h2&gt;

&lt;p&gt;We hope our app makes your work easier and gets more folks into Kubernetes. Any ideas for improvement? We’re all ears!&lt;/p&gt;

&lt;p&gt;Star us on GitHub - ⭐ &lt;a href="https://github.com/hcavarsan/kftray" rel="noopener noreferrer"&gt;https://github.com/hcavarsan/kftray&lt;/a&gt;&lt;/p&gt;

</description>
      <category>opensource</category>
      <category>kubernetes</category>
      <category>devops</category>
      <category>cloud</category>
    </item>
    <item>
      <title>Kftray - kubernetes port forward no menu bar!</title>
      <dc:creator>Henrique Cavarsan</dc:creator>
      <pubDate>Fri, 16 Feb 2024 01:51:17 +0000</pubDate>
      <link>https://dev.to/hcavarsan/kftray-kubernetes-port-forward-no-menu-bar-3db9</link>
      <guid>https://dev.to/hcavarsan/kftray-kubernetes-port-forward-no-menu-bar-3db9</guid>
      <description>&lt;h2&gt;
  
  
  Introdução ao Kftray
&lt;/h2&gt;

&lt;p&gt;uma aplicação no menu bar desenvolvida com Rust e React usando o framework Tauri, o app tem um proposito simples: simplificar a forma como executamos e gerenciamos multiplos kubectl port-forward no dia a dia, e também o kftray adiciona novos recursos em comparação com o tradicional kubectl port-forward. (mais detalhes nos proximos topicos)&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsoq99qwzgrk4sc7wvpyf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsoq99qwzgrk4sc7wvpyf.gif" alt="gif demo" width="378" height="420"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  KFtray
&lt;/h2&gt;

&lt;p&gt;A principal missão do &lt;a href="https://github.com/hcavarsan/kftray"&gt;KFtray&lt;/a&gt; é simplificar o processo de gerenciamento de multipos kubectl port forward de clusters Kubernetes. Projetado com simplicidade e produtividade em mente, o app permite aos usuários iniciar e parar múltiplas configurações de redirecionamento de portas por meio de uma interface elegante e amigável. O app se destaca pela sua resiliência, operações com um clique e independência do kubectl, pois se conecta diretamente com a API do Kubernetes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mão na massa!
&lt;/h2&gt;

&lt;p&gt;Configurar o KFtray é muito simples:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Configurando configurações de port-forward:&lt;/strong&gt;
A UI intuitiva permite adicionar e gerenciar facilmente as configurações port forward com campos para workload (Proxy ou Serviço), alias único, contexto do Kubernetes, namespace, service, remote address (para Proxy), protocolo (TCP/UDP) e portas locais/remotas.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F219kcrvq32g6pyax9m1o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F219kcrvq32g6pyax9m1o.png" alt="create new configuration" width="524" height="565"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Ativando os port forwards:&lt;/strong&gt;
Você pode iniciar um unico port forward com um simples clique ou lançar multipos forwards simultaneamente, tornando muito fácil gerenciar configurações complexas.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzj58q4p2ny6nhb05it73.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzj58q4p2ny6nhb05it73.png" alt="multiple configurations" width="506" height="561"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; &lt;strong&gt;Gerenciando Configurações:&lt;/strong&gt;
O KFtray fornece opções para exportar/importar configurações como arquivos JSON, garantindo que você possa compartilhar ou fazer backup de suas configurações. Ele também salva as configurações de forma segura localmente em “$HOME/.kftray/configs.db”. Aqui está um exemplo do formato JSON esperado pelo KFtray:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&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;span class="nl"&gt;"alias"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"consul-ui"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kind-7"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"local_port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"consul"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"protocol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"tcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"remote_port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;8500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"consul-ui"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"workload_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;"service"&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;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"alias"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"redis-gcp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"context"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kind-6"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"local_port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;26379&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"namespace"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"default"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"protocol"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"udp"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"remote_address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"redis-prod.gcp.internal"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"remote_port"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;6379&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;  
    &lt;/span&gt;&lt;span class="nl"&gt;"workload_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;"proxy"&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;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;&lt;strong&gt;Conexão de Redirecionamento de Porta Resiliente:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Resilient Port Forwarding Connection:&lt;/strong&gt; O KFtray garante que seus serviços permaneçam acessíveis ao reconectar automaticamente a pods alternativos em execução, caso algum falhe..&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Vários port forwards com Um Clique:&lt;/strong&gt; Configure rapidamente múltiplas instâncias de port forward com um único clique &lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Independente do Kubectl:&lt;/strong&gt; A interface direta do KFtray com a API do Kubernetes elimina a dependência do kubectl, proporcionando uma experiência mais suave e atendendo àqueles que preferem interfaces gráficas ao invés da linha de comando.&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Suporte a Múltiplos Protocolos:&lt;/strong&gt;: Expandindo além do TCP, o suporte do KFtray a múltiplos protocolos, incluindo UDP, permite acesso a uma variedade de serviços, tanto internos quanto externos aos seus clusters Kubernetes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusão
&lt;/h2&gt;

&lt;p&gt;O KFtray visa melhorar a experiência de gerenciar multipos port forward de uma vez, oferecendo uma solução simples, eficiente e confiável. Seja para depuração de serviços ou acesso a recursos internos, o KFtray oferece a flexibilidade e confiabilidade necessárias em ambientes de desenvolvimento de ritmo acelerado.&lt;/p&gt;

&lt;p&gt;Se você achou o KFtray util, considere nos dar uma estrela no GitHub em &lt;a href="https://github.com/hcavarsan/kftray"&gt;https://github.com/hcavarsan/kftray&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Se você encontrar algum problema ou tiver dúvidas sobre o KFtray, crie uma issue em nosso repositório !&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>opensource</category>
      <category>cloud</category>
    </item>
  </channel>
</rss>
