Skip to content

Add kmeshctl dnsproxy command to start/stop DNS proxy at runtime#1582

Open
karankoder wants to merge 2 commits intokmesh-net:mainfrom
karankoder:enable-dns-proxy
Open

Add kmeshctl dnsproxy command to start/stop DNS proxy at runtime#1582
karankoder wants to merge 2 commits intokmesh-net:mainfrom
karankoder:enable-dns-proxy

Conversation

@karankoder
Copy link

@karankoder karankoder commented Feb 4, 2026

What type of PR is this?

/kind feature

Fixes #1574

What this PR does :

This PR adds the ability to dynamically enable and disable the DNS proxy via kmeshctl instead of relying on environment variables. This allows users to control the DNS proxy at any time during the operation of Kmesh.

New Commands:

  • kmeshctl dnsproxy enable [podNames...] - Enable DNS proxy for Kmesh
  • kmeshctl dnsproxy disable [podNames...] - Disable DNS proxy for Kmesh
  • kmeshctl dnsproxy status [podNames...] - Display current DNS proxy status

Example Usage:

# Enable DNS proxy for all kmesh daemons
kmeshctl dnsproxy enable

# Disable DNS proxy for a specific pod
kmeshctl dnsproxy disable kmesh-xxxx

# Check DNS proxy status
kmeshctl dnsproxy status

Signed-off-by: karankoder <mkaran4249@gmail.com>
Copilot AI review requested due to automatic review settings February 4, 2026 05:50
@kmesh-bot
Copy link
Collaborator

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign lizhencheng9527 for approval. For more information see the Kubernetes Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@gemini-code-assist
Copy link

Summary of Changes

Hello @karankoder, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the operational flexibility of Kmesh by introducing a new command-line interface, kmeshctl dnsproxy, for dynamic management of the DNS proxy. This change allows users to enable, disable, and query the status of the DNS proxy on Kmesh daemon pods without requiring service restarts, addressing a previous limitation where such changes were static and environment variable-driven. The implementation involves adding new CLI commands, an internal API endpoint within the Kmesh daemon, and corresponding logic to update BPF maps for DNS proxy functionality.

Highlights

  • New kmeshctl dnsproxy command: Introduces a new kmeshctl dnsproxy command with subcommands to enable, disable, and check the status of the DNS proxy dynamically at runtime.
  • Dynamic DNS Proxy Control: Enables dynamic control over the Kmesh DNS proxy, moving away from environment variable-based configuration that required restarts. This allows for real-time management of DNS proxy functionality.
  • API for DNS Proxy Management: Adds an internal HTTP API endpoint (/dnsproxy) to the Kmesh daemon, allowing kmeshctl to communicate and control the DNS proxy state (enable/disable/status) via HTTP requests and Kubernetes port-forwarding.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • ctl/common/common.go
    • Imported the new dnsproxy package.
    • Registered the dnsproxy command as a subcommand of the root kmeshctl command.
  • ctl/dnsproxy/dnsproxy.go
    • Added a new file to implement the kmeshctl dnsproxy command and its subcommands (enable, disable, status).
    • Includes logic to create Kubernetes clients and port-forwarders to communicate with Kmesh daemon pods.
    • Defines functions (SetDNSProxyForPods, SetDNSProxyPerKmeshDaemon, fetchDNSProxyStatus) to send HTTP POST/GET requests to Kmesh daemons for DNS proxy control and status retrieval.
  • docs/ctl/kmeshctl.md
    • Updated the 'SEE ALSO' section to include a link to the new kmeshctl dnsproxy documentation.
  • docs/ctl/kmeshctl_dnsproxy.md
    • Added new documentation for the kmeshctl dnsproxy command.
  • docs/ctl/kmeshctl_dnsproxy_disable.md
    • Added new documentation for the kmeshctl dnsproxy disable subcommand, including examples.
  • docs/ctl/kmeshctl_dnsproxy_enable.md
    • Added new documentation for the kmeshctl dnsproxy enable subcommand, including examples.
  • docs/ctl/kmeshctl_dnsproxy_status.md
    • Added new documentation for the kmeshctl dnsproxy status subcommand, including examples.
  • pkg/controller/workload/workload_controller.go
    • Imported the sync/atomic package.
    • Added an atomic.Bool field dnsProxyEnabled to the Controller struct to manage the DNS proxy state.
    • Initialized dnsProxyEnabled based on the EnableDNSProxy environment variable during controller creation.
    • Implemented SetDNSProxyEnabled and GetDNSProxyEnabled methods to allow dynamic control and retrieval of the DNS proxy state.
  • pkg/controller/workload/workload_processor.go
    • Added SetDNSProxyEnabled method to dynamically enable or disable the DNS proxy.
    • This method updates the BPF backend map by registering or deleting the Kmesh daemon's IP, effectively redirecting or stopping DNS requests.
  • pkg/status/status_server.go
    • Defined a new constant patternDNSProxy for the /dnsproxy HTTP endpoint.
    • Registered dnsProxyHandler to handle requests to the new /dnsproxy endpoint.
    • Implemented dnsProxyHandler to process HTTP GET requests (return status) and POST requests (enable/disable DNS proxy) by interacting with the WorkloadController.
Activity
  • The pull request introduces new features and documentation. No specific review comments or activities were provided in the context.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.


A proxy, once static, now bends to command, With `kmeshctl`, its fate in your hand. Enable, disable, a swift, silent plea, For DNS traffic, now flowing free.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@karankoder
Copy link
Author

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a kmeshctl dnsproxy command to dynamically manage the DNS proxy, which is a valuable feature. The implementation is mostly sound, but there are a few significant issues that need to be addressed. The new CLI command code relies on os.Exit(1) for error handling, which should be replaced with proper error propagation. Additionally, there's a critical issue where the daemon could panic due to unsafe parsing of an environment variable. I've also noted an opportunity to reduce code duplication for better long-term maintainability. Addressing these points will improve the robustness and quality of the new functionality.

log.Infof("enabling DNS proxy, ip: %s", podIp)

bv := &bpf.BackendValue{}
nets.CopyIpByteFromSlice(&bv.Ip, netip.MustParseAddr(podIp).AsSlice())

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

netip.MustParseAddr will panic if the IP address string from the INSTANCE_IP environment variable is invalid. This can crash the entire kmesh-daemon. You should use netip.ParseAddr instead and handle the potential error gracefully.

Suggested change
nets.CopyIpByteFromSlice(&bv.Ip, netip.MustParseAddr(podIp).AsSlice())
addr, err := netip.ParseAddr(podIp)
if err != nil {
return fmt.Errorf("invalid INSTANCE_IP %q: %w", podIp, err)
}
nets.CopyIpByteFromSlice(&bv.Ip, addr.AsSlice())

Comment on lines 93 to 141
Run: func(cmd *cobra.Command, args []string) {
cli, err := utils.CreateKubeClient()
if err != nil {
log.Errorf("failed to create cli client: %v", err)
os.Exit(1)
}

// Determine which pods to query.
var podNames []string
if len(args) == 0 {
podList, err := cli.PodsForSelector(context.TODO(), utils.KmeshNamespace, utils.KmeshLabel)
if err != nil {
log.Errorf("failed to get kmesh podList: %v", err)
os.Exit(1)
}
for _, pod := range podList.Items {
podNames = append(podNames, pod.GetName())
}
} else {
podNames = args
}

// Prepare a slice of podStatuses.
type podStatus struct {
Pod string
Status string
}
statuses := make([]podStatus, 0, len(podNames))

// Collect the status for each pod.
for _, podName := range podNames {
status, err := fetchDNSProxyStatus(cli, podName)
if err != nil {
log.Errorf("failed to get DNS proxy status for pod %s: %v", podName, err)
continue
}
statuses = append(statuses, podStatus{Pod: podName, Status: status})
}

// Output the results in a table format.
var buf bytes.Buffer
tw := tabwriter.NewWriter(&buf, 0, 0, 2, ' ', 0)
fmt.Fprintln(tw, "POD\tDNS PROXY STATUS")
for _, s := range statuses {
fmt.Fprintf(tw, "%s\t%s\n", s.Pod, s.Status)
}
tw.Flush()
fmt.Print(buf.String())
},

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The Run function for this command calls os.Exit(1) upon failure. This is a problematic practice in CLI applications as it prevents proper error handling, testing, and reusability. It's recommended to use RunE which allows returning an error. Cobra will then handle printing the error and exiting with a non-zero status code. This principle should be applied to NewEnableCmd and NewDisableCmd as well, and helper functions like SetDNSProxyForPods should be refactored to return errors.

RunE: func(cmd *cobra.Command, args []string) error {
				cli, err := utils.CreateKubeClient()
				if err != nil {
					return fmt.Errorf("failed to create cli client: %v", err)
				}

				// Determine which pods to query.
				var podNames []string
				if len(args) == 0 {
					podList, err := cli.PodsForSelector(context.TODO(), utils.KmeshNamespace, utils.KmeshLabel)
					if err != nil {
						return fmt.Errorf("failed to get kmesh podList: %v", err)
					}
					for _, pod := range podList.Items {
						podNames = append(podNames, pod.GetName())
					}
				} else {
					podNames = args
				}

				// Prepare a slice of podStatuses.
				type podStatus struct {
					Pod    string
					Status string
				}
				statuses := make([]podStatus, 0, len(podNames))

				// Collect the status for each pod.
				for _, podName := range podNames {
					status, err := fetchDNSProxyStatus(cli, podName)
					if err != nil {
						log.Errorf("failed to get DNS proxy status for pod %s: %v", podName, err)
						continue
					}
					statuses = append(statuses, podStatus{Pod: podName, Status: status})
				}

				// Output the results in a table format.
				var buf bytes.Buffer
				tw := tabwriter.NewWriter(&buf, 0, 0, 2, ' ', 0)
				fmt.Fprintln(tw, "POD\tDNS PROXY STATUS")
				for _, s := range statuses {
					fmt.Fprintf(tw, "%s\t%s\n", s.Pod, s.Status)
				}
				tw.Flush()
				fmt.Print(buf.String())
				return nil
			},

Comment on lines 135 to 163
// SetDNSProxyEnabled dynamically enables or disables the DNS proxy.
// When enabled, registers the kmesh daemon IP in the BPF backend map.
// When disabled, removes the registration from the BPF map.
func (p *Processor) SetDNSProxyEnabled(enabled bool) error {
bk := &bpf.BackendKey{
BackendUid: 0,
}

if !enabled {
log.Info("disabling DNS proxy")
return p.bpf.BackendDelete(bk)
}

podIp := os.Getenv("INSTANCE_IP")
if podIp == "" {
return fmt.Errorf("ip of kmesh daemon is not set")
}

log.Infof("enabling DNS proxy, ip: %s", podIp)

bv := &bpf.BackendValue{}
nets.CopyIpByteFromSlice(&bv.Ip, netip.MustParseAddr(podIp).AsSlice())
if err := p.bpf.BackendUpdate(bk, bv); err != nil {
log.Errorf("failed to register kmesh daemon ip, err: %+v", err)
return err
}

return nil
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The function SetDNSProxyEnabled has almost the same implementation as PrepareDNSProxy. This code duplication can lead to maintenance issues where one function is updated but the other is forgotten. To improve maintainability, PrepareDNSProxy should be refactored to call SetDNSProxyEnabled.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds dynamic DNS proxy control to Kmesh via new kmeshctl dnsproxy commands, allowing users to enable, disable, and check the status of the DNS proxy at runtime instead of relying solely on environment variables at startup.

Changes:

  • Added SetDNSProxyEnabled and GetDNSProxyEnabled methods to the workload controller with atomic state management
  • Implemented HTTP handler (dnsProxyHandler) supporting GET (status) and POST (enable/disable) operations
  • Created new kmeshctl dnsproxy command with enable, disable, and status subcommands

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
pkg/controller/workload/workload_processor.go Added SetDNSProxyEnabled method to dynamically update BPF backend map for DNS proxy control
pkg/controller/workload/workload_controller.go Added atomic state tracking for DNS proxy status with getter/setter methods
pkg/status/status_server.go Added dnsProxyHandler to handle HTTP GET/POST requests for DNS proxy status and control
ctl/dnsproxy/dnsproxy.go Implemented CLI commands for DNS proxy management (enable, disable, status)
ctl/common/common.go Registered new dnsproxy command with root command
docs/ctl/kmeshctl_dnsproxy*.md Added documentation for new dnsproxy commands
docs/ctl/kmeshctl.md Updated main documentation to include dnsproxy command reference

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 138 to 163
func (p *Processor) SetDNSProxyEnabled(enabled bool) error {
bk := &bpf.BackendKey{
BackendUid: 0,
}

if !enabled {
log.Info("disabling DNS proxy")
return p.bpf.BackendDelete(bk)
}

podIp := os.Getenv("INSTANCE_IP")
if podIp == "" {
return fmt.Errorf("ip of kmesh daemon is not set")
}

log.Infof("enabling DNS proxy, ip: %s", podIp)

bv := &bpf.BackendValue{}
nets.CopyIpByteFromSlice(&bv.Ip, netip.MustParseAddr(podIp).AsSlice())
if err := p.bpf.BackendUpdate(bk, bv); err != nil {
log.Errorf("failed to register kmesh daemon ip, err: %+v", err)
return err
}

return nil
}
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function duplicates significant logic from PrepareDNSProxy (lines 108-133). Consider refactoring to extract the common logic for enabling DNS proxy (getting INSTANCE_IP, creating BackendValue, and calling BackendUpdate) into a shared helper function that both PrepareDNSProxy and SetDNSProxyEnabled can call. This would make the code more maintainable and reduce the risk of the two implementations diverging.

Copilot uses AI. Check for mistakes.
Comment on lines +72 to +73
// Initialize DNS proxy state based on the environment variable setting
c.dnsProxyEnabled.Store(EnableDNSProxy)
Copy link

Copilot AI Feb 4, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The dnsProxyEnabled atomic state is initialized based on the EnableDNSProxy environment variable before PrepareDNSProxy is called. If PrepareDNSProxy fails during Controller.Run, the dnsProxyEnabled state will incorrectly indicate that DNS proxy is enabled when it's actually not functional. Consider either: (1) initializing dnsProxyEnabled to false and only setting it to true after PrepareDNSProxy succeeds, or (2) updating dnsProxyEnabled based on the result of PrepareDNSProxy in the Run method.

Suggested change
// Initialize DNS proxy state based on the environment variable setting
c.dnsProxyEnabled.Store(EnableDNSProxy)
// Initialize DNS proxy state as disabled; it will be enabled only after
// DNS proxy preparation (e.g., PrepareDNSProxy) has successfully completed.
c.dnsProxyEnabled.Store(false)

Copilot uses AI. Check for mistakes.
Signed-off-by: karankoder <mkaran4249@gmail.com>
Copy link
Contributor

@LiZhenCheng9527 LiZhenCheng9527 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a flag in daemon/options/bpf.go to set the default value for enableDnsProxy

Short: "Manage DNS proxy for Kmesh",
}

dnsProxyCmd.AddCommand(NewEnableCmd())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you give more example about kmeshctl dnsproxy?

@LiZhenCheng9527
Copy link
Contributor

LiZhenCheng9527 commented Feb 5, 2026

You're doing exactly the same thing as #1581

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a startup parameter for the DNS proxy.

3 participants