Skip to content

feat(cni-plugin): add iptables binary fallback logic#587

Merged
raykroeker merged 14 commits into
mainfrom
alex/detect-iptables
Jul 7, 2026
Merged

feat(cni-plugin): add iptables binary fallback logic#587
raykroeker merged 14 commits into
mainfrom
alex/detect-iptables

Conversation

@adleong

@adleong adleong commented Oct 23, 2025

Copy link
Copy Markdown
Member

The linkerd-cni plugin can be configured to use either iptables, iptables-legacy, or iptables-nft for a wide range of compatibility. However, when the configuration doesn't match the iptables executable on the host system, the linkerd-cni plugin will fail.

To make this more user friendly, we add a detection step which identifies which of the above executables are available on the system. If the configured executable is not available, we automatically fall back to one that is.

Additionally, cni plugin logs are only available through the kubelet, which can be difficult to access. To grant easier observability to the cni plugin, we additionally log to a file so that cni plugin logs are more easily accessible on the host node.

Sample log outputs:

time="2025-10-23T00:43:18Z" level=debug msg="iptables: using configured binaries" requestedBin=iptables-nft requestedSaveBin=iptables-nft-save
time="2025-10-23T00:45:39Z" level=warning msg="iptables: configured binaries not found; applying fallback to available binaries" fallbackBin=iptables fallbackSaveBin=iptables-save requestedBin=iptables-nft requestedSaveBin=iptables-nft-save

(tested by deleting iptables-nft off of the host node)

Signed-off-by: Alex Leong <alex@buoyant.io>
@adleong
adleong requested a review from a team as a code owner October 23, 2025 00:58
Signed-off-by: Alex Leong <alex@buoyant.io>
Signed-off-by: Alex Leong <alex@buoyant.io>
Signed-off-by: Alex Leong <alex@buoyant.io>
This reverts commit a85e19d.
Signed-off-by: Alex Leong <alex@buoyant.io>
@raykroeker

Copy link
Copy Markdown
Contributor

Printed error to stdout if the log directory cannot be created.
Added integration test for 'plain' ip tables mode.

@alpeb alpeb left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

According to the lumberjack docs:

Lumberjack assumes that only one process is writing to the output files. Using the same lumberjack configuration from multiple processes on the same machine will result in improper behavior.

The container runtime invokes the CNI plugin binary as a separate process every time a pod is created. My understanding is that the chain of plugins are called sequentially, but nothing forbids a plugin to be called concurrently, which can happen in large clusters with high pod churn, leading to corrupted logs or improper file rotation. For this reason I think we should instead explore an alternative solution.

Comment thread pkg/iptables/iptables.go

// resolveBinFallback ensures the configured BinPath and SaveBinPath exist on PATH; if not, it
// tries reasonable alternatives of the same family (ip6tables vs iptables).
func resolveBinFallback(fc *FirewallConfiguration, lookPath func(string) (string, error)) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

There's a getCommands function in cmd/root.go where the binaries to use is determined. I think that's a better place to place this logic, where we the ipv6 case is also considered without resorting to string comparison.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@alpeb My only concern with moving this to the cmd/ package is that it in effect limits the implementation to the proxy-init command only. If we leave it in iptables/ all calls to Configure|Cleanup will benefit from the resolution. Thoughts?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Yes you're right, I missed the initialization is a bit different for cni vs proxy-init. Should be good as-is then 👍

@raykroeker

Copy link
Copy Markdown
Contributor

According to the lumberjack docs:

Lumberjack assumes that only one process is writing to the output files. Using the same lumberjack configuration from multiple processes on the same machine will result in improper behavior.

The container runtime invokes the CNI plugin binary as a separate process every time a pod is created. My understanding is that the chain of plugins are called sequentially, but nothing forbids a plugin to be called concurrently, which can happen in large clusters with high pod churn, leading to corrupted logs or improper file rotation. For this reason I think we should instead explore an alternative solution.

The flags used when opening a file (w/in Lumberjack) confirm the documentation, there is no locking on the log file itself. I think removing file logging is the right answer for now. We can circle back to an alternative solution in the future.

@raykroeker
raykroeker merged commit 5cf5354 into main Jul 7, 2026
20 checks passed
@raykroeker
raykroeker deleted the alex/detect-iptables branch July 7, 2026 23:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants