mirror of
https://github.com/mulgadc/spinifex.git
synced 2026-10-20 03:11:46 +00:00
fix: tunnel apiserver controlplane egress through konnectivity (#991)
The EgressSelectorConfiguration written to every EKS control-plane VM defined only the `cluster` egress selection, which carries kubelet exec/logs/portforward. Admission webhooks and aggregated apiservers dial via the `controlplane` selection instead, and an undefined selection falls back to a direct dial. The control-plane VM sits alone in its own VPC with no route to the service CIDR, so every webhook call timed out after 10s and konnectivity never saw a single dial request for one. Define both selections on the konnectivity-server UDS so webhook traffic rides the agent-initiated reverse tunnel alongside kubelet traffic.
This commit is contained in:
@@ -87,9 +87,9 @@ const (
|
||||
k3sConfigPath = "/etc/rancher/k3s/config.yaml"
|
||||
|
||||
// k3sEgressSelectorConfigPath is the EgressSelectorConfiguration the apiserver
|
||||
// loads via --egress-selector-config-file. It points the `cluster` egress at the
|
||||
// konnectivity-server UDS, so apiserver→pod/kubelet traffic (exec/logs/webhooks)
|
||||
// rides the agent-initiated reverse tunnel instead of a direct (unroutable) IP.
|
||||
// loads via --egress-selector-config-file. It points the `controlplane` and
|
||||
// `cluster` egress at the konnectivity-server UDS, so apiserver→pod/kubelet
|
||||
// traffic rides the agent-initiated reverse tunnel, not a direct IP.
|
||||
k3sEgressSelectorConfigPath = "/etc/rancher/k3s/egress-selector-config.yaml"
|
||||
|
||||
// konnectivityUDSPath is the unix socket the konnectivity-server listens on for
|
||||
@@ -469,20 +469,28 @@ func k3sServerJoinURL(ip string) string {
|
||||
}
|
||||
|
||||
// egressSelectorConfigYAML renders the EgressSelectorConfiguration that wires the
|
||||
// apiserver `cluster` egress to the konnectivity-server UDS. v1beta1 is the schema
|
||||
// apiserver egress to the konnectivity-server UDS. v1beta1 is the schema
|
||||
// k3s/kube-apiserver accept for --egress-selector-config-file.
|
||||
func egressSelectorConfigYAML() string {
|
||||
return strings.Join([]string{
|
||||
lines := []string{
|
||||
"apiVersion: apiserver.k8s.io/v1beta1",
|
||||
"kind: EgressSelectorConfiguration",
|
||||
"egressSelections:",
|
||||
" - name: cluster",
|
||||
" connection:",
|
||||
" proxyProtocol: GRPC",
|
||||
" transport:",
|
||||
" uds:",
|
||||
" udsName: " + konnectivityUDSPath,
|
||||
}, "\n")
|
||||
}
|
||||
// controlplane carries admission-webhook and aggregated-apiserver dials;
|
||||
// cluster carries kubelet exec/logs/portforward. Both must ride the tunnel:
|
||||
// an undefined selection falls back to a direct, unroutable dial from the CP.
|
||||
for _, name := range []string{"controlplane", "cluster"} {
|
||||
lines = append(lines,
|
||||
" - name: "+name,
|
||||
" connection:",
|
||||
" proxyProtocol: GRPC",
|
||||
" transport:",
|
||||
" uds:",
|
||||
" udsName: "+konnectivityUDSPath,
|
||||
)
|
||||
}
|
||||
return strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
// dedupeNonEmpty returns the input with empty strings dropped and duplicates
|
||||
|
||||
@@ -440,6 +440,20 @@ func TestBuildK3sUserData_EgressSelectorDisabledWithKonnConfig(t *testing.T) {
|
||||
"the EgressSelectorConfiguration file routes the cluster egress to the konn socket")
|
||||
}
|
||||
|
||||
func TestEgressSelectorConfigYAML_TunnelsControlPlaneAndCluster(t *testing.T) {
|
||||
cfg := egressSelectorConfigYAML()
|
||||
|
||||
// Admission webhooks and aggregated apiservers dial via `controlplane`; only
|
||||
// kubelet exec/logs/portforward use `cluster`. Omitting controlplane leaves
|
||||
// webhook dials direct, which cannot route from the CP VPC to the service CIDR.
|
||||
assert.Contains(t, cfg, " - name: controlplane",
|
||||
"webhook dials use the controlplane egress and must ride the konnectivity tunnel")
|
||||
assert.Contains(t, cfg, " - name: cluster",
|
||||
"kubelet exec/logs dials use the cluster egress")
|
||||
assert.Equal(t, 2, strings.Count(cfg, "udsName: "+konnectivityUDSPath),
|
||||
"both egress selections must terminate on the konnectivity socket")
|
||||
}
|
||||
|
||||
func TestBuildK3sUserData_KonnectivityEnv(t *testing.T) {
|
||||
in := validK3sInput()
|
||||
in.PrivateEndpointIP = "10.32.100.4"
|
||||
|
||||
Reference in New Issue
Block a user