
You ran the flag to disable Traefik on K3s, installed ingress-nginx instead, and port 443 still won't respond. If that sounds familiar, Traefik isn't the culprit — it's another default component K3s quietly runs in the background.
1. You disabled Traefik, but ingress-nginx still can't grab port 443
You ran --disable=traefik, confirmed with kubectl get pods -n kube-system that the Traefik-related pods were gone, and then installed ingress-nginx as a LoadBalancer service. An external IP gets assigned, but requests to port 443 time out — or worse, land on the wrong pod entirely.
This isn't as rare as it sounds. According to the official K3s documentation, K3s automatically deploys two independent networking components at startup (K3s official docs: Networking Services). The first is Traefik (the Ingress Controller), which has been K3s's default Ingress Controller for years (Traefik Labs official blog: Easy Ingress Management on the Edge with K3s and Traefik). The second is ServiceLB (formerly known as Klipper LoadBalancer). Both NGINX and Traefik want ports 80/443, so if either one is still running, a conflict is guaranteed (k3s-io/k3s Issue #2403 documents a case where nginx stopped responding on port 80 for IPv4 right after installing k3s).
This kind of "invisible default dependency" is something every K3s cluster admin runs into sooner or later. In an environment where cluster configuration is actually visible, like Kubo, you'd catch this kind of oversight much earlier.

2. Traefik isn't the culprit. K3s was quietly running "ServiceLB" the whole time
What most engineers miss is that Traefik and ServiceLB are independent components managed by separate flags. --disable=traefik only stops Traefik. ServiceLB keeps running unless you disable it explicitly.
ServiceLB runs as a DaemonSet, placing pods prefixed with svclb- on nodes across the cluster, and assigns ports to LoadBalancer services using hostPort (K3s official docs: Networking Services). In other words, even after Traefik's LoadBalancer service disappears, ServiceLB keeps trying to assign ports to any other LoadBalancer service, including ingress-nginx, using the exact same mechanism. That's the direct cause of port 443 staying unreachable after disabling Traefik.
What ServiceLB actually does is explained by the K3s developers themselves in an official repository discussion. ServiceLB's job is simply to set up DNAT iptables rules on the node — the DaemonSet pods themselves don't handle traffic. Without ServiceLB, any type: LoadBalancer Service would stay pending forever; that's the entire reason it exists (k3s-io/k3s Discussion #9927: What does ServiceLB (Klipper LB) actually do?). Mechanically, it assigns one hostPort per service and forwards traffic to the cluster IP via iptables (k3s-io/klipper-lb).
As for why Traefik ships bundled with K3s in the first place, a K3s maintainer explains the reasoning directly in an official discussion: the design goal is to provide "a fully functional cluster out of the box, a step beyond vanilla Kubernetes," and disabling it via the --disable traefik flag is explicitly supported (k3s-io/k3s Discussion #6215: Consider dropping Traefik as a bundled component). In practice, though, there are reports of Traefik pods restarting even after --no-deploy traefik was specified (Issue #1160) — often traced back to directly editing /var/lib/rancher/k3s/server/manifests/traefik.yaml, which K3s's startup process simply regenerates on restart.

3. Confirm the "invisible roommate" with one diagnostic command
You can check whether ServiceLB is still running with a single command:
kubectl get pods -A | grep svclb
If any pod with the svclb- prefix shows up, ServiceLB is still active. As the official Kubernetes documentation explains, Ingress Controllers aren't built into Kubernetes core at all — every cluster is expected to run its own controller as a separate component (Kubernetes official docs: Ingress Controllers). K3s bundling Traefik by default is convenient, but it's also the root cause of the "install an alternative Ingress Controller and immediately hit a port conflict" problem — and simply stopping Traefik isn't always enough.
You also shouldn't edit manifests under /var/lib/rancher/k3s/server/manifests/ directly. K3s's startup process detects the diff and reverts it back to the original state. If you need to customize behavior, the correct approach is to place an additional HelmChartConfig resource in the same directory, as the official docs explain (K3s official docs: Networking Services).

This is exactly the kind of area where a visualized management console eliminates the need for CLI checks altogether. Kubo's Captain UI visualizes your cluster's Ingress/LoadBalancer configuration, reducing the risk of shipping to production without noticing a "default component that's still running."
4. The correct way to disable both, and what changes with MetalLB
If you want to disable both Traefik and ServiceLB on an existing cluster, follow these steps.
- On every server node, add the following to
/etc/rancher/k3s/config.yaml
disable:
- traefik
- servicelb
- Restart K3s with
sudo systemctl restart k3s - Re-run
kubectl get pods -A | grep svclband confirm there's no output
For a fresh install, just specify both flags at install time (oneuptime.com's MetalLB setup guide):
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="--disable servicelb --disable traefik" sh -
The same problem happens with MetalLB, too
ServiceLB doesn't just conflict with ingress-nginx — it conflicts with MetalLB as well. Both watch for LoadBalancer services and both try to assign external IPs, which leads to services getting stuck pending or receiving the wrong IP entirely — an "unpredictable behavior" pattern (k3s-io/k3s Issue #2323 describes a case where BGP routes kept flapping in MetalLB even after the user believed ServiceLB was disabled).
klipper-lb (ServiceLB) and MetalLB are built on fundamentally different design philosophies. ServiceLB is a lightweight mechanism that runs entirely on node-local iptables rules and never advertises IPs to the outside network. MetalLB, on the other hand, supports both L2 (ARP) and BGP modes and can genuinely advertise IPs to the external network, which is why it's the better fit for production bare-metal clusters (k3s-io/k3s Discussion #9927). If you're running MetalLB in production, disabling ServiceLB isn't optional — it's a prerequisite you can't skip.

With a managed K8s built on K3s like Kubo, AI-Driven Deployment detects this kind of Ingress/LoadBalancer configuration drift, which reduces the risk of a missed disable flag causing a production incident you never saw coming. If you need the same kind of configuration management on-premises, Kubo On-Premise offers a management console built on the same philosophy.
5. Summary
Disabling Traefik on K3s doesn't end with running --disable=traefik. K3s bundles two independent components by default — Traefik (Ingress) and ServiceLB (LoadBalancer, formerly Klipper) — and each one needs to be disabled with its own separate flag.
- Symptom: Traefik is disabled, but ingress-nginx still can't grab port 443
- Cause: ServiceLB keeps assigning hostPorts to other LoadBalancer services
- Diagnosis:
kubectl get pods -A | grep svclb - Fix: add
disable: [traefik, servicelb]to config.yaml and restart - Also applies to: MetalLB, where disabling ServiceLB is a prerequisite, not an option
Don't let "it's just the default" slide past you — knowing exactly which two networking components K3s bundles, and independently verifying both, should be the last checkpoint before anything goes to production. If you'd rather hand that visualization off entirely, get in touch with the Kubo team.